Skip to content

Dcc - #285

Merged
srmnitc merged 15 commits into
mainfrom
dcc
Oct 6, 2026
Merged

Dcc#285
srmnitc merged 15 commits into
mainfrom
dcc

Conversation

@srmnitc

@srmnitc srmnitc commented Oct 6, 2026

Copy link
Copy Markdown
Member

No description provided.

…weeps

The scaled system at (T0, lambda) samples the real system at (T0/lambda, P)
only if the barostat imposes P_RS = lambda*P (de Koning, Antonelli, Yip,
J. Chem. Phys. 115, 11025 (2001), Eq. 11), and integrate_rs assumes that
when it integrates U + P V at constant P.  Both sweeps computed pf = lf*pi
and logged the ramp, but the fix that stayed active through the sweep was
created with a constant target pi, so the sweep sampled the real system at
P/lambda and the middle equilibration of the backward sweep sat at the
wrong scaled pressure.

fix npt can only ramp its target linearly over one run, so the constant
pressure equilibration fix is now replaced right before each sweep by one
ramping pi -> pf (forward) and pf -> pi (backward), with the COM-corrected
temperature rebound to the new fix; the middle equilibration holds pf.

Exactly a no-op at pressure 0, which is where the golden streams are
recorded; they only gain the unfix/fix/fix_modify triple.  Cross-check with
a direct fe at the sweep endpoint (Cu01, 500 atoms, 2500/5000 steps): at
50 kbar 400 -> 700 K both old and new agree with fe within 0.5 meV/atom;
at 300 kbar 400 -> 1000 K the old sweep ends at a real pressure of 750 kbar
and is off by 30 meV/atom, the new one agrees within 0.3 meV/atom.
…kward

temperature_scaling and scan_temperature_range ramp the real temperature
with the thermostat; lambda = T0/T is only the recorded label.  Both
nevertheless ramped the barostat to (T0/Tf)*P, the scaled-pressure end
point that belongs to the lambda-scaled Hamiltonian of reversible_scaling,
and so sampled the wrong isobar at finite pressure (a no-op at 0 bar).
The real pressure is now held throughout.

Since "switch to stepped ts" (b286426) the tscale backward sweep was also
created with temp T0 T0 instead of Tf T0, i.e. it quenched to T0 at the
start of the sweep instead of mirroring the forward ramp, corrupting the
backward integral at any pressure.  Restored to Tf -> T0.
The golden streams are recorded at pressure 0, where the scaled and the
real pressure coincide, so they cannot tell a ramped from a constant
barostat.  Record the same driver methods at 50 kbar and assert the
targets directly: the ts sweeps ramp P <-> (T0/Tf)*P and the backward
middle equilibration sits at (T0/Tf)*P; tscale and the pre-scan hold the
real pressure and tscale ramps Tf -> T0 on the way back.
…ies on

DCCI_PLAN.md lays out the dynamic Clausius-Clapeyron mode: two cells
driven in lockstep at a fixed kinetic temperature, the scaled pressure
P_RS ramped linearly by a single fix npt and lambda integrated per block
from the block averages of U and V (de Koning, Antonelli, Yip 2001).

The three LAMMPS behaviours that design leans on are pinned as -m lammps
tests: a ramped fix npt keeps following the global sweep when the sweep is
chopped into 'run n start 0 stop N' segments (a control without start/stop
restarts the ramp at every boundary), hybrid/scaled re-reads a redefined
scale variable immediately, and fix ave/time 1 n n writes exactly one row
per block across restarts.
mode: dcci takes the known coexistence point as temperature and
pressure[0], the pressure to integrate to as pressure[1], and a dcci:
block (n_block_steps, integrator, stop_at_target_pressure, n_check_blocks,
hysteresis_tolerance).  The temperature must be explicit: the mendeleev
melting-point guess is not a coexistence point of the potential.  Swaps
and NVT are rejected, reference_phase is forced to solid since the mode
always builds one solid and one liquid cell.

queuekernel dispatches to calphy.dcci.DynamicCCI (the coordinator, whose
sweep follows in the next parts), the preflight requires hybrid/scaled for
the mode, reset_timestep joins the runner vocabulary for the sweep clock,
and dcci-* folders are ignored.
DynamicCCI builds a Solid and a Liquid sub-calculation from the parent
input (its phase, the starting pressure, the melt/freeze checks switched
on as melting_temperature does; enable_phase_detection is factored out of
MeltingTemp for that), equilibrates both with run_averaging at (T0,
P_start), and then drives them in lockstep: one lambda-scaled session per
cell, a single fix npt ramping the scaled pressure P_start -> P_stop over
the sweep, 'run n start 0 stop N' blocks, and after every block lambda is
corrected from the block averages of U = pe/lambda and V of the two cells
through d lambda / d P_RS = -(v_s - v_l)/(u_s - u_l); within a block lambda
is ramped along the last measured slope so the Hamiltonian stays
continuous.  T = T0/lambda and P = P_RS/lambda are written per block to
dcci.forward_<i>.dat together with the real-space slope dH/(T dV), and the
sweep stops once the real pressure reaches P_stop.

Checked against a fake runner with constant du, dv (the analytic line is
reproduced, the command stream matches the design) and on Cu01: 500 atoms,
6 blocks of 500 steps from 1340 K at 0 bar reach 1580 K at 59 kbar in ten
seconds, with dP/dT of 236-257 bar/K, i.e. the known ~40 K/GPa melting
slope of copper.
After each forward sweep the cells are driven back: the sessions restart
from the forward end configurations at the lambda reached, equilibrate
there, and the scaled pressure is ramped back to P_start over the same
number of blocks.  integrate_dcci puts the forward line on the real
pressure grid (starting point included), interpolates the backward one
onto it and writes coexistence_line.dat with the mean of both directions;
the error is half the local hysteresis combined with the standard error
over n_iterations, as integrate_rs does.  The round-trip miss of the
starting temperature is reported as the hysteresis and flagged against
dcci.hysteresis_tolerance.  report.yaml and metadata.yaml are written at
the top level; postprocessing gains read_coexistence_line and
plot_coexistence_line.

Fake-runner cycle with constant du, dv closes exactly; synthetic sweeps
check the error combination; the -m lammps slow end-to-end test runs Cu
out to 50 kbar and back (500 atoms, 6 blocks of 500 steps, ~20 s) and
closes within 2 K.
Input-file docs for mode dcci and its block, the output files of a dcci-*
folder, the LAMMPS package table, and example 13: the melting line of Cu
(Mishin Cu01, 500-atom cells) from a melting_temperature point at 0 bar
out to 5, 10 and 158 GPa with 53, 155 and 29 blocks.  The three lines
agree with each other to about 10 K, close their round trips to between
0.01 and 2.4 K, track the published Simon fits for this potential within a
few percent up to 160 GPa, and match direct fe crossings of both phases at
5 and 10 GPa to 2 K once the 13 K offset of the starting melting_temperature
value (1340 K against 1353 K from direct fe) is taken into account: the
accuracy of the line is the accuracy of its starting point.  The notebook
is executed; the raw result folders follow the repository convention and
are not committed.  The plan records the validation and two findings from
it: hysteresis does not measure discretisation error, and the
ExecutableRunner fails a segment whose LAMMPS log ends cleanly when mpirun
returns nonzero under heavy concurrency.
…lls)

The cells exchange information only at block boundaries, through the
driver, so between exchanges they are independent.  With parallel_cells
(off by default) the per-block sequence of each cell -- lambda ramp, run,
sync -- and the equilibration, the phase checks and the session teardown
run in two threads, each cell's LAMMPS with queue.cores/2, so the total
allocation is unchanged and the sweep wall time halves.  With a single
core the cells fall back to running one after the other, with a warning.
Velocity seeds are drawn in the main thread so the random stream is used
from one place only.

Fake-runner test: the concurrent run reproduces the sequential line exactly
and the cells carry half the cores; the LAMMPS end-to-end test runs in
both modes.
# Conflicts:
#	.bumpversion.cfg
#	CITATION.cff
#	calphy/__init__.py
#	calphy/input.py
#	calphy/phase.py
#	pyproject.toml
#	tests/golden/ts_backward_solid.txt
#	tests/golden/ts_forward_solid.txt
#	tests/golden/ts_mc_swaps.txt
#	tests/golden/ts_uniform_temperature.txt
#	tests/test_sweep_barostat_targets.py
The three Cu01 runs (default, high and converged settings) from 1340 K
at 0 bar: input_file.yaml, forward/backward sweeps, coexistence_line.dat
and report.yaml. Force-added past the dcci-* and *.dat ignore rules so
the notebook runs without repeating the simulations.
The runs used the linear schedule, the only one left since 2.2.1, so
the key carries no information and stops the files from loading.
@srmnitc
srmnitc merged commit c07ac2a into main Oct 6, 2026
6 checks passed
@srmnitc
srmnitc deleted the dcc branch October 6, 2026 10:34
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