Skip to content

Fix qtb#253

Merged
srmnitc merged 6 commits into
mainfrom
fix_qtb
May 22, 2026
Merged

Fix qtb#253
srmnitc merged 6 commits into
mainfrom
fix_qtb

Conversation

@srmnitc

@srmnitc srmnitc commented May 20, 2026

Copy link
Copy Markdown
Member

No description provided.

srmnitc and others added 6 commits May 19, 2026 08:28
Add equilibration_control=qtb option that routes all thermostat call
sites in the solid free-energy path through LAMMPS fix qtb (paired
with fix nph for NPT and fix nve for NVT).

- input.py: QuantumThermalBath model (damping, f_max, N_f, seed)
- phase.py: fix_qtb/unfix_qtb helpers; qtb branches in zero-pressure
  and finite-pressure equilibration, (un)constrained pressure
  convergence, and __init__ damping wiring
- solid.py: qtb branches in spring-constant convergence and the
  Einstein-crystal TI switching block (Langevin -> qtb)
- liquid.py / alchemy.py: refuse QTB at run_integration with a clear
  NotImplementedError. Liquid Uhlenbeck-Ford reference is intrinsically
  classical so pairing with QTB sampling would be inconsistent.
- phase.py: refuse QTB at reversible_scaling / temperature_scaling
  (LAMMPS fix qtb does not support ramped temperature).

Layer 1 is plumbing only; the Einstein-crystal reference free energy
remains the classical formula. Layer 2 will add the quantum harmonic
reference required for self-consistent QTB free energies.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add quantum=True branch to get_einstein_crystal_fe that returns the
quantum harmonic-oscillator free energy:
    F_e/N = sum_i (1/2) hbar omega_i + k_B T ln(1 - exp(-hbar omega_i/k_BT))
with omega_i = sqrt(k_i/m_i). Wired in solid.thermodynamic_integration
to activate automatically when equilibration_control == "qtb".

This is the reference required for self-consistent free energies under
QTB sampling: the QTB injects quantum-statistical fluctuations into
classical MD, so the reference free energy at lambda=0 must be the
quantum (not classical) harmonic oscillator. Pairing classical
sampling with the quantum reference, or QTB sampling with the
classical reference, gives an inconsistent thermodynamic path that
breaks down below the Debye temperature.

The CM correction is retained in its classical form: it is a
phase-space integration correction whose leading form is unchanged
by QTB sampling.

Verified analytically: F_qm - F_cl -> 0 above ~3 Theta_D, and
F_qm(T=0) = 1.5 hbar omega per atom = ZPE.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spell out the reason mode=ts cannot use QTB sampling in the
NotImplementedError message: the Frenkel-Smit reversible-scaling
identity relies on classical Boltzmann factorisation
exp(-beta * lambda * U) = exp(-(lambda*beta) * U). Under QTB, the
sampled distribution is quantum-statistical and does not factorise
that way: when potential is scaled by lambda, mode frequencies become
omega * sqrt(lambda), so the QTB spectrum theta(omega, T_start) does
not match the target system's theta(omega*sqrt(lambda), T_start/lambda)
spectrum. The classical scaling trick therefore breaks down.

This documents why QTB+ts is *methodologically* refused, not just an
implementation gap. mode=fe at discrete T remains the supported path
for QTB free energies.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous integration overloaded equilibration_control, a field whose
documented role is "thermostat for the initial equilibration cycle
only", to also drive QTB sampling throughout the workflow and to select
the quantum Einstein reference. That's semantic creep that bites future
readers. Replace with a proper mode-level surface.

User-facing:
- mode: fe-qtb is the new way to ask for QTB sampling + quantum reference
- equilibration_control reverts to its original narrow meaning
  (nose-hoover or berendsen for the equilibration thermostat only)
- mode=fe-qtb with reference_phase=liquid raises ValidationError at
  input-parsing time (UF reference is intrinsically classical)

Internal:
- Calculation gains a private _qtb: bool flag, set by the model
  validator when mode == "fe-qtb"; mode is then normalised to "fe" so
  Phase-class dispatch is unchanged.
- All call sites in phase.py / solid.py that previously checked
  equilibration_control == "qtb" now check self.calc._qtb. The
  if/elif/else chains in phase.py are reordered so _qtb takes
  precedence over equilibration_control, with a warning if the user
  set equilibration_control=berendsen alongside mode=fe-qtb.
- NotImplementedError guards in phase.reversible_scaling /
  phase.temperature_scaling / liquid.run_integration /
  alchemy.run_integration are removed. They were defensive in nature
  but the new mode dispatch makes them unreachable: mode=fe-qtb only
  enters solid Frenkel-Ladd; nothing else can flip _qtb on.

Smoke-tested at 300 K Cu FCC: classical F = -3.5628, QTB F = -3.5611
(dF = +1.7 meV), matching the previous laptop benchmark within
stochastic noise. Quantum harmonic Einstein reference is selected
automatically, confirmed in the log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Issue #247 review pass — code already implemented and verified, but
docs and tests were out of date.

Docs:
- inputfile.md: add mode: fe-qtb to the mode field description with
  reference-phase restriction note, add a quantum_thermal_bath block
  with thermostat_damping/barostat_damping/f_max/n_f/seed entries,
  add cross-reference from equilibration_control noting it is
  ignored when mode: fe-qtb is set. Add quantum_thermal_bath to the
  page-level navigation grid.
- gettingstarted.md: add PKG_QTB=ON to the list of optional LAMMPS
  cmake flags with a one-liner explaining when it is needed.

Code:
- input.py: update QuantumThermalBath docstring to point at the
  mode: fe-qtb surface instead of the obsolete
  equilibration_control: qtb surface, and note the NPH/NVE pairing.

Tests:
- tests/test_qtb_input.py: 4 schema-level tests verifying that
  mode: fe-qtb sets the internal _qtb flag and normalises mode to
  'fe' for downstream dispatch; that mode: fe leaves _qtb=False;
  that user-set quantum_thermal_bath parameters round-trip through
  the schema; and that mode: fe-qtb with reference_phase: liquid is
  rejected at input-parsing time (Uhlenbeck-Ford liquid reference
  is classical).

Issue #247 sub-tasks addressed:
  1. Implement Dammak's QTB in MD phase                 → done
  2. NVE / NPH ensemble support                          → done (fix nve / fix nph paired with fix qtb in phase.py fix_qtb)
  3. Configure via input.yaml, not init_commands         → done (mode: fe-qtb + quantum_thermal_bath: block)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@srmnitc srmnitc merged commit 5369ff9 into main May 22, 2026
4 checks passed
@srmnitc srmnitc deleted the fix_qtb branch May 22, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant