Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration Reference

A simulation is specified by a TOML config file. The config pins every parameter that affects the trajectory; everything else (positions, velocities, box) lives in the init file. Run a config with:

heddlemd run path/to/argon.in.toml

This chapter is the user-facing rendering of the field reference. The canonical, exhaustive schema lives at rqm/io/config-schema.md in the repository — consult it for the deserialiser/validator error catalogue and any field this chapter elides.

Config filename convention

The config-file path passed to heddlemd run must end in .in.toml. The loader rejects any other name (InvalidConfigFilename) before it opens the file. The convention has two purposes:

  • An ls of a simulation directory groups inputs (*.in.*) and outputs (*.out.*) into two visible blocks, so it is obvious which files were generated and can safely be deleted before a re-run.
  • The loader derives every default output path from the <root> of the config filename without an extra config field: strip the .toml extension, then strip one trailing .in. The result is the config’s root.

Examples:

Config filename<root>Default output paths (per phase <phase>)
argon.in.tomlargonargon.out.<phase>.{xyz,log,timings}
spc.in.tomlspcspc.out.<phase>.{xyz,log,timings}
run-01.in.tomlrun-01run-01.out.<phase>.{xyz,log,timings}
foo.in.in.tomlfoo.infoo.in.out.<phase>.{xyz,log,timings}

The suffix match is case-sensitive on the whole .in.toml string. argon.IN.toml is rejected. Filenames whose <root> derivation would yield the empty string (e.g. .in.toml) are likewise rejected.

The init-file path, the topology-file path, and any explicit output.*_path field are not subject to the convention — they are arbitrary user-supplied paths.

Units

The top-level units field selects the unit system used by the config file, the referenced init (.in.xyz) file, and every output file the run produces. Two values are accepted:

  • units = "si" — the default (equivalent to omitting the field). SI throughout:

    QuantitySI unit
    lengthmetres
    masskilograms
    timeseconds
    energyjoules
    chargecoulombs
    temperaturekelvin
    pressurepascals
  • units = "atomic" — Hartree atomic units (length in Bohr radii, mass in electron masses, time in atomic time units, energy in Hartrees, temperature as k_B · T in Hartrees, and so on).

The comparison is case-sensitive; any other value is rejected (UnknownUnits). The engine stores and computes in atomic units internally regardless — the loader converts every unit-bearing value at the I/O boundary, and threads the chosen system back through to every output writer so your view stays consistent end to end. All field descriptions below name their SI form for clarity; in atomic mode you write (and read) the corresponding atomic-unit quantity instead. No unit suffixes are supported in either mode.

Path resolution

All file paths in the config (init, topology, phase.<name>.output.*) are interpreted relative to the directory containing the config file, not the current working directory. Absolute paths are honored as-is. After resolution, every supplied path must be pairwise distinct.

Phases

A simulation is composed of one or more phases. Phases come in two kinds:

  • MD phases declared as [[phase]] array elements. Each MD phase carries its own n_steps, dt, and slot blocks ([phase.integrator], optional [phase.thermostat], optional [phase.barostat], optional [phase.output]).
  • Minimization phases declared as [[minimization]] array elements. Each minimization phase carries an algorithm selector (steepest-descent in v1), algorithm parameters, convergence criteria, and an optional [minimization.output] block.

Particle state (positions, velocities, box) carries from one phase into the next regardless of phase kind; per-phase slot state resets at every boundary. Velocities and the simulation box are unchanged by a minimization phase — only positions move.

The two arrays may be freely interleaved: phases execute in source-document order across [[phase]] and [[minimization]] combined. Typical pattern is one minimization phase followed by one or more MD phases:

[[minimization]]
name = "min"

[minimization.algorithm]
kind = "steepest-descent"

[[phase]]
name = "equil"
n_steps = 5000
dt = 1.0e-15
...

[[phase]]
name = "prod"
n_steps = 10000
dt = 1.0e-15
...

Each phase produces its own output files derived from <root> (the config file stem with one trailing .in stripped) and the phase’s name:

  • MD phases write <root>.out.<phase>.xyz, <root>.out.<phase>.log, <root>.out.<phase>.timings.
  • Minimization phases write <root>.out.<phase>.minlog and <root>.out.<phase>.timings (always), plus <root>.out.<phase>.xyz when trajectory_every > 0.

Per-phase paths can be overridden via the phase’s output block ([phase.output] for MD, [minimization.output] for minimization).

Phases must have distinct names across the union of both arrays. Stochastic MD slots of the same kind across phases (e.g. two CSVR thermostats) must use distinct seeds.

Worked example

A complete single-phase config for 10,000 argon atoms in NVE:

Saved as argon.in.toml:

schema_version = 1
init = "argon.in.xyz"

[simulation]
seed = 1
temperature = 100.0 # K

[[phase]]
name = "run"
n_steps = 100
dt = 1.0e-15        # 1 fs

[phase.integrator]
kind = "velocity-verlet"
lossless = false

[phase.output]
trajectory_every = 10
include_velocities = true
log_every = 5

[[particle_types]]
name = "Ar"
mass = 6.6335e-26   # kg

[[pair_interactions]]
between = ["Ar", "Ar"]
potential = "lennard-jones"
sigma = 3.40e-10    # m
epsilon = 1.65e-21  # J  (~120 K · k_B)
cutoff = 8.5e-10    # m  (2.5σ)

This is the bundled examples/lj-10000-argon/argon.in.toml file. The Configuration sections below walk through every field.

A multi-phase NPT example (equilibration then production) is shown in the bundled examples/spc-water-8192/water.in.toml.

Configuration sections

Top level

FieldTypeRequiredDefaultNotes
schema_versionu64yesmust be 1
unitsstringno"si""si" or "atomic"; see Units
initstringyespath to the init file
topologystringnononepath to a .topology file (bonded forces, exclusions, constraints)

When topology is omitted no bonded forces are evaluated and the LJ and SPME real-space kernels see no exclusion list.

[simulation]

FieldTypeRequiredDefaultNotes
seedu64yesRNG seed for Maxwell-Boltzmann velocity generation. Required even when the init file supplies velocities.
temperaturef64yesInitial-velocity temperature in K. Finite, >= 0. Used only when the init file omits velocities. The thermostat’s bath temperature is a separate field.
fast_mathboolnotrueBuild every JIT-compiled kernel with nvcc’s --use_fast_math. ~13% faster pair force; still bit-reproducible run-to-run on a fixed GPU (a true run follows a different f32 trajectory than a false run, but each is independently reproducible). Set false for precise-IEEE kernels.
graph_batch_sizeu32no5Number of step replays between displacement checks / output-cadence re-evaluations when a phase runs under CUDA-graph mode. Must be >= 1.
cuda_graphs_disableboolnofalseWhen true, every MD phase runs the per-step launch loop with full per-kernel timings — a diagnostic escape hatch from CUDA-graph batching.

Per-step settings (timestep, step count, integrator/thermostat/barostat composition, output cadences) live in the [[phase]] array, not here.

[[phase]]

At least one [[phase]] array element is required. Each phase carries:

FieldTypeRequiredDefaultNotes
namestringyesIdentifier used in output filenames and error messages. Must be unique across phases and use only ASCII letters, digits, -, or _.
n_stepsu64yesNumber of integration steps in this phase. 0 is permitted (the runner writes the initial state and moves on).
dtf64yesIntegration timestep in seconds. Finite, strictly positive.

A phase is then specified by its [phase.integrator] (required), [phase.thermostat] (optional), [phase.barostat] (optional), and [phase.output] (optional) sub-tables. The schema of each of those slot blocks is described in the sections that follow.

[phase.integrator]

A required kind field selects the integrator; all other fields are kind-specific. Configs that pair an integrator that owns its own thermostat (langevin-baoab, mtk-npt) with a [phase.thermostat] section are rejected at load time.

kind = "velocity-verlet"

Symplectic NVE time-stepping. Compose with [phase.thermostat] for NVT.

FieldTypeRequiredDefaultNotes
losslessboolnofalseWhen true, runs the compensated-summation variant that enables bit-exact time reversal. See Reproducibility. Incompatible with topology-file [constraints].

kind = "langevin-baoab"

Stochastic NVT via the BAOAB splitting (Leimkuhler–Matthews). Owns its own thermostat; incompatible with [phase.thermostat].

FieldTypeRequiredNotes
frictionf64yesDamping γ in s⁻¹. Strictly positive.
temperaturef64yesBath temperature in K. Independent of simulation.temperature.
seedu64yesRNG seed for the OU noise. Independent of simulation.seed.

kind = "mtk-npt"

Deterministic extended-system NPT (Martyna-Tobias-Klein, isotropic). Owns both its thermostat and its barostat; incompatible with both [phase.thermostat] and [phase.barostat].

FieldTypeRequiredDefaultNotes
temperaturef64yesBath temperature in K.
pressuref64yesTarget pressure in Pa. Any sign.
tau_tf64yesThermostat coupling time (s).
tau_pf64yesBarostat coupling time (s).
chain_lengthu32no3Length of both particle and cell thermostat chains.
yoshida_orderu32no3Suzuki-Yoshida sub-steps; one of 1, 3, 5, 7.
n_respu32no1Chain RESP sub-cycle count.

[phase.thermostat] (optional)

Omit for NVE composition with the integrator. A required kind field selects the thermostat; per-kind fields are listed below. Configs that combine [phase.thermostat] with an integrator that owns its own thermostat are rejected.

kind = "nose-hoover-chain"

Deterministic NVT. Adds nhc_conserved to the log.

FieldTypeRequiredDefaultNotes
temperaturef64yesBath temperature in K.
tauf64yesCoupling time (s). 50–100 fs typical for water.
chain_lengthu32no3M = 1 reduces to vanilla Nosé-Hoover.
yoshida_orderu32no3One of 1, 3, 5, 7.
n_respu32no1Chain RESP sub-cycle count.

kind = "csvr"

Stochastic canonical sampling velocity rescaling (Bussi-Donadio-Parrinello).

FieldTypeRequiredNotes
temperaturef64yesBath temperature in K.
tauf64yesCoupling time (s). Larger τ → closer to NVE.
seedu64yesRNG seed. Independent of other slots.

kind = "andersen"

Per-particle stochastic Maxwell-Boltzmann resampling.

FieldTypeRequiredNotes
temperaturef64yesBath temperature in K.
collision_ratef64yesν in s⁻¹. >= 0; 0 degenerates to NVE.
seedu64yesRNG seed.

kind = "berendsen"

Deterministic weak-coupling thermostat. Equilibration only — does not sample the canonical ensemble.

FieldTypeRequiredNotes
temperaturef64yesBath temperature in K.
tauf64yesCoupling time (s).

[phase.barostat] (optional)

Omit for constant-volume composition. A required kind selects the barostat. Configs that combine [phase.barostat] with an integrator that owns its own barostat (currently mtk-npt) are rejected.

kind = "berendsen"

Deterministic isotropic weak-coupling barostat. Equilibration only.

FieldTypeRequiredNotes
pressuref64yesTarget pressure (Pa). Any sign.
tauf64yesCoupling time (s). Should be longer than the thermostat’s τ.
compressibilityf64yesIsothermal compressibility β (1/Pa).

kind = "c-rescale"

Stochastic isotropic cell-rescaling barostat (Bernetti-Bussi). Samples the canonical NPT distribution exactly.

FieldTypeRequiredNotes
pressuref64yesTarget pressure (Pa).
temperaturef64yesUsed in the noise term. Keep consistent with the thermostat for canonical sampling.
tauf64yesCoupling time (s).
compressibilityf64yesIsothermal compressibility (1/Pa).
seedu64yesRNG seed.

[[minimization]]

A minimization phase advances positions along the negative gradient of the potential energy. Each entry carries:

FieldTypeRequiredDefaultNotes
namestringyesIdentifier used in output filenames. Same character set and uniqueness rules as [[phase]]’s name (the uniqueness check spans both arrays).

A minimization entry has a required [minimization.algorithm] block and an optional [minimization.output] block. Unlike MD phases, minimization rejects n_steps, dt, [minimization.integrator], [minimization.thermostat], and [minimization.barostat] — those concepts do not apply.

[minimization.algorithm]

A required kind field selects the algorithm; all other fields are optional with documented defaults.

kind = "steepest-descent"

Adaptive-step steepest descent. Each iteration proposes a trial position x_trial = x + step · F / F_max, where F_max = max_i ||F_i||; if the trial energy is lower, the step is accepted and step is multiplied by step_increase (capped at max_step); otherwise positions are restored and step is multiplied by step_decrease.

FieldTypeRequiredDefaultNotes
initial_stepf64no1.0e-12Initial scalar step in m. Finite, strictly positive.
max_stepf64no1.0e-10Upper bound on step in m. Must be >= initial_step.
step_increasef64no1.2Multiplier applied to step on accept. Must be >= 1.0.
step_decreasef64no0.2Multiplier applied to step on reject. Must be in (0.0, 1.0).
force_tolerancef64no1.0e-10Convergence threshold on F_max in N. 0.0 disables this criterion.
energy_tolerancef64no1.0e-7Relative convergence threshold on `
max_iterationsu64no1000Iteration cap. Reaching it without satisfying any physical criterion is a hard error and exits with code 2.

The phase terminates with success when either F_max <= force_tolerance or the energy-tolerance criterion fires on an accepted iteration.

[minimization.output] (optional; all fields have defaults)

FieldTypeDefaultNotes
minlog_pathstring<root>.out.<phase>.minlogPath to the per-iteration CSV.
minlog_everyu641Iterations between .minlog rows. 0 disables the file. The final convergence iteration is always logged.
trajectory_pathstring<root>.out.<phase>.xyzPath to the optional .xyz trajectory.
trajectory_everyu640Iterations between trajectory frames. 0 (the default) disables intermediate frames; only the step-0 and convergence frames are written when this is > 0.
include_imagesbooltrueInclude image:I:3 columns in trajectory frames.
timings_pathstring<root>.out.<phase>.timingsPath to the per-stage performance summary. Always written.

Velocities never appear in minimization trajectory frames; setting include_velocities under [minimization.output] is rejected as an unknown field. See Output Files for the .minlog format.

[[particle_types]] (array, ≥ 1 entry)

One entry per species. Names must be unique.

FieldTypeRequiredDefaultNotes
namestringyesIdentifier referenced from the init file and from pair_interactions.between. Case-sensitive. Non-empty.
massf64yesParticle mass in kg. Finite, strictly positive.
chargef64no0.0Per-particle charge in C. Any sign. Consumed by the SPME slot.

[[pair_interactions]] (array)

One entry per unordered pair of declared types. For N types you must supply exactly N · (N + 1) / 2 entries (including same-type self-pairs). ["A", "B"] and ["B", "A"] refer to the same pair.

Common fields:

FieldTypeRequiredDefaultNotes
between[string; 2]yesUnordered pair of type names.
potentialstringyesCurrently only "lennard-jones".
cutofff64yesCutoff distance in m.
r_switchf64no0.9 · cutoffInner radius of the switching function applied over [r_switch, cutoff] (continuous in value and first derivative, so there is no force discontinuity at the cutoff). r_switch = cutoff selects the hard-cutoff degenerate case.

Fields for potential = "lennard-jones":

FieldTypeRequiredNotes
sigmaf64yesLJ zero-crossing distance (m).
epsilonf64yesLJ well depth (J).

[spme] (optional)

Activates smooth particle-mesh Ewald — the engine’s electrostatics model. Per-particle charges come from [[particle_types]].charge. Requires the cell-list neighbor mode ([spme] combined with mode = "all-pairs" is rejected).

The top-level [coulomb] truncated-Coulomb table used by earlier versions of the config has been retired. A config that declares [coulomb] is rejected at load time (CoulombRetired); use [spme] for electrostatics.

FieldTypeRequiredDefaultNotes
alphaf64yesEwald splitting parameter (1/m).
r_cut_realf64yesReal-space cutoff (m).
grid[u32; 3]yesFFT grid [n_a, n_b, n_c]. Each n_d >= 2 · spline_order.
spline_orderu32no4One of 4, 5, 6, 7, 8.

[[bond_types]], [[angle_types]], [[dihedral_types]], [[constraint_types]]

These four optional arrays declare parameter sets referenced by name from the optional .topology file’s [bonds], [angles], [dihedrals], and [constraints] sections respectively. Each is empty by default; declared-but-unused entries are permitted. Every entry has a name (unique within its array) and — for the force potentials — a potential selector; constraint types use a kind selector instead.

[[bond_types]]

Two-atom bonded potentials. A system may freely mix bond potentials; each bond is routed to the matching slot by its type.

potential = "harmonic"U = ½ k (r − r₀)² (harmonic stiff spring):

FieldTypeRequiredNotes
kf64yesForce constant in J/m² (in the ½ k (r−r₀)² convention). Strictly positive.
r0f64yesEquilibrium distance in m. Strictly positive.

potential = "morse"U = D_e (1 − e^{−a(r−r_e)})²:

FieldTypeRequiredNotes
def64yesWell depth in J. Strictly positive.
af64yesWidth parameter in 1/m. Strictly positive.
ref64yesEquilibrium distance in m. Strictly positive.

[[angle_types]]

Three-atom angle potentials. potential = "harmonic" is the only supported value — U = ½ k_θ (θ − θ₀)²:

FieldTypeRequiredNotes
k_thetaf64yesForce constant in J/rad². Strictly positive.
theta_0f64yesEquilibrium angle in radians, in [0, π].

[[dihedral_types]]

Four-atom torsion potentials. potential = "periodic" is the only supported value — U = k_φ · (1 + cos(n·φ − φ₀)). A multi-term torsion on one (i, j, k, l) quadruple is expressed by declaring one dihedral type per Fourier term and naming each from its own [dihedrals] row on the same quadruple.

FieldTypeRequiredDefaultNotes
k_phif64yesForce constant in J. Finite (may be zero or negative).
nu32yesMultiplicity, integer in [1, 6].
phi_0f64yesPhase offset in radians, in [−2π, 2π].
scale_lj_14f64no0.5LJ scale for the implicit 1-4 exclusion this torsion introduces. In [0, 1].
scale_coul_14f64no0.8333 (1/1.2)Coulomb scale for that same 1-4 exclusion. In [0, 1].

[[constraint_types]]

Rigid-constraint groups. Each entry’s kind selects the algorithm that processes any group declared with that type in the topology’s [constraints] section. The presence of any constraint group is incompatible with the Langevin BAOAB, MTK NPT, and lossless velocity-Verlet integrators (see Validation).

kind = "settle" — analytic three-atom rigid water (fast path). A [constraints] row for this type lists three atoms in canonical order: oxygen, then the two hydrogens.

FieldTypeRequiredNotes
d_OHf64yesOxygen–hydrogen bond length in m. Strictly positive.
d_HHf64yesHydrogen–hydrogen distance in m. Strictly positive and < 2 · d_OH.

kind = "shake" — general iterative SHAKE/RATTLE for arbitrary rigid clusters. A [constraints] row lists this type’s atoms global atom indices.

FieldTypeRequiredNotes
atomsu32yesAtoms per group. 1 ≤ atoms ≤ 8.
constraintslist of { i, j, d }yesOne entry per pair-distance constraint; 1–12 entries. i, j are local indices in 0..atoms (i ≠ j, each unordered pair unique); d is the target distance in m (strictly positive).

The exhaustive validator error catalogue for all four arrays lives in rqm/io/config-schema.md, with the physics in the matching pages under rqm/forces/ and rqm/integration/.

[neighbor_list] (optional)

Selects the algorithm short-range pair-force slots use to enumerate non-bonded pairs. Defaults to the cell-list pipeline.

FieldTypeRequiredDefaultNotes
modestringno"cell-list""cell-list" or "all-pairs".
r_skinf64no0.3 · cutoffCell-list only. Skin distance in m.

There is no max_neighbors field: the packed-neighbour pair-force architecture sizes its buffers to the actual interaction count plus a growth margin, so supplying max_neighbors is a load-time error. For mode = "all-pairs", r_skin is likewise rejected as an unknown field, and combining all-pairs with [spme] is rejected. The simulation box’s minimum perpendicular width must satisfy >= 3 · (cutoff_max + r_skin); the runner validates this once the box is known.

[phase.output] (optional; all fields have defaults)

FieldTypeDefaultNotes
trajectory_pathstring<root>.out.<phase>.xyzPath to the trajectory file. Relative to the config’s directory.
trajectory_everyu64100Steps between frames. 0 disables trajectory output.
include_velocitiesbooltrueInclude velo:R:3 columns.
include_imagesbooltrueInclude image:I:3 columns.
log_pathstring<root>.out.<phase>.logPath to the CSV log.
log_everyu64100Steps between log rows. 0 disables the log.
timings_pathstring<root>.out.<phase>.timingsPath to the per-stage performance summary. Always written; there is no timings_every.

<root> is the config root derived from the filename per the Config filename convention, and <phase> is the phase’s name. See Output Files for the full format spec.

Validation

The loader rejects configs that:

  • live at a path whose final filename component does not end in .in.toml, or whose <root> derivation is empty (InvalidConfigFilename; see the Config filename convention);
  • carry an unrecognised top-level or section field;
  • choose an unknown kind for the integrator, thermostat, barostat, or any constraint type;
  • omit a required field, or supply a non-finite or out-of-domain value (negative dt, empty type name, r_switch > cutoff, etc.);
  • declare a [[pair_interactions]] entry referencing an undeclared type, omit a required pair, or duplicate a pair;
  • resolve two supplied file paths to the same location;
  • declare the retired [coulomb] table (CoulombRetired), or combine mode = "all-pairs" with [spme];
  • combine [phase.thermostat]/[phase.barostat] with an integrator that owns its own;
  • declare zero phases (the union of [[phase]] and [[minimization]] must be non-empty), duplicate a phase name across either array, or share a seed between two stochastic slots of the same kind across phases;
  • choose an unknown minimization kind, or supply out-of-domain values for the SD parameters (e.g. step_decrease >= 1.0, max_step < initial_step, max_iterations = 0);
  • pair the constraint framework with an integrator that does not support constraints (Langevin BAOAB, MTK NPT, and lossless velocity-Verlet currently do not).

Errors are reported on stderr as error: <message> and exit with code 1 (no integration steps run). The runner only proceeds when the config validates cleanly.