Moves¶
Monte Carlo moves are defined in the propagate section of the YAML input file.
Propagate settings¶
| Key | Required | Default | Description |
|---|---|---|---|
repeat |
no | 1 | Number of propagate cycles (outer loop) |
collections |
no | [] |
Ordered list of move collections (see below) |
seed |
no | Hardware |
RNG seed: Hardware (random) or !Fixed N |
criterion |
no | MetropolisHastings |
Acceptance criterion (Metropolis or Minimize) |
Each propagate cycle executes every collection in order; after all collections have run, one cycle is complete and the step counter advances.
Collections¶
A collection groups moves together and controls how they are selected. Two types are available:
!Stochastic— each repeat draws one move at random, with probability proportional toweight. This is the normal Monte Carlo sampling mode.!Deterministic— each repeat executes all moves in order. Useful for e.g. hybrid MC/MD schemes. Theweightfield is unused here but still required by the move schema.
| Key | Required | Default | Description |
|---|---|---|---|
repeat |
no | 1 | How many times the collection runs per propagate cycle |
moves |
no | [] |
List of moves |
Common move options¶
Every move accepts at least:
| Key | Description |
|---|---|
weight |
Selection weight (only meaningful inside !Stochastic collections) |
repeat |
How many trial moves to attempt each time the move is selected (default 1) |
max_displacement |
Maximum translational displacement (Å), for translational moves (alias dp) |
max_angle |
Maximum rotational angle (radians), for rotational moves (alias dprot) |
The two repeat levels nest: the collection's repeat controls how often
moves are drawn, and the move's repeat controls how many trials are
performed per draw. For example, a stochastic collection with repeat: 100
containing a move with repeat: 5 will attempt that move up to 500 times
per propagate cycle (depending on how often it is drawn).
Example¶
propagate:
seed: Hardware
criterion: Metropolis
repeat: 1000
collections:
- !Stochastic
repeat: 10
moves:
- !TranslateMolecule { molecule: Water, max_displacement: 0.5, weight: 1.0 }
- !RotateMolecule { molecule: Water, max_angle: 0.3, weight: 1.0 }
- !VolumeMove { volume_displacement: 0.04, weight: 0.5 }
- !Deterministic
repeat: 1
moves:
- !TranslateAtom { molecule: Water, atom: O, max_displacement: 0.1, weight: 1.0 }
Translate Molecule¶
Picks a random molecule of the given type and translates it by a random displacement vector
with magnitude uniformly sampled in \([-\Delta r, +\Delta r]\), set by max_displacement.
- !TranslateMolecule { molecule: Water, max_displacement: 0.5, weight: 1.0 }
- !TranslateMolecule { molecule: Protein, max_displacement: 0.2, weight: 2.0, repeat: 3, directions: xy }
| Key | Required | Default | Description |
|---|---|---|---|
molecule |
yes | Name of the molecule type (not allowed for atomic molecules) |
|
max_displacement |
yes | Maximum displacement (Å); alias dp |
|
weight |
yes | Selection weight | |
repeat |
no | 1 | Repetitions per selection |
directions |
no | xyz |
Active directions (x, y, z, xy, xz, yz, xyz) |
Translate Atom¶
Picks a random atom and translates it by a random displacement.
If molecule is specified, the atom is chosen from that molecule type only.
If atom is specified, only atoms of that type are selected.
- !TranslateAtom { max_displacement: 0.1, weight: 1.0 }
- !TranslateAtom { molecule: Water, atom: O, max_displacement: 0.2, weight: 1.0, repeat: 5 }
| Key | Required | Default | Description |
|---|---|---|---|
max_displacement |
yes | Maximum displacement (Å); alias dp |
|
weight |
yes | Selection weight | |
molecule |
no | Restrict to this molecule type | |
atom |
no | Restrict to this atom type | |
repeat |
no | 1 | Repetitions per selection |
preferential |
no | Preferential sampling settings (see below) |
Preferential Sampling¶
In a dilute solution, most trial moves displace bulk particles far from the solute, where little of interest happens. Preferential sampling picks the particles near the solute more often and corrects the acceptance so that the equilibrium distribution is unchanged (Owicki & Scheraga, 1977; Allen & Tildesley, 2017, §9.3.1). Only the rate of convergence improves; the sampled ensemble does not.
Candidate atom \(j\) sits a distance \(r_j\) from the bounding sphere of the nearest matching reference group and carries the unnormalized weight
where offset keeps the weight finite at contact. Atom \(i\) is then selected with probability
The sum runs over every atom the move may pick, across all matching groups, so a particle beside the solute competes against the whole bulk.
Selecting atoms unevenly makes a move and its reverse unequally likely to be proposed, so the acceptance criterion carries the ratio of the two selection probabilities of the moved atom,
An atom that moves away from the solute was easy to select and would be hard to select back, so such moves are accepted less often; moves toward the solute are accepted more often. Dropping this correction would drain the very region the method exists to sample.
The reference groups may move as freely as any others, and need no correction of their own:
- !Stochastic
moves:
- !TranslateMolecule { molecule: Protein, max_displacement: 0.5 }
- !RotateMolecule { molecule: Protein, max_angle: 0.5 }
- !TranslateAtom
molecule: Na
max_displacement: 0.5
repeat: 100
preferential:
reference: "molecule Protein"
exponent: 2
offset: 1.0
Multiple reference groups can be selected; the distance is always to the nearest one:
preferential:
reference: "molecule Protein1 or molecule Protein2"
The reference field uses the selection language,
e.g. "molecule Protein", "protein", or boolean combinations.
The bias acts among the candidates, so there must be more than one: if molecule and atom
together match a single atom, \(W(r_i) = 1\) throughout and the selection reduces to the uniform
one. Choose the mobile species so that the candidates span the solvent — an atomic species such
as Na, or a single atom kind shared by many solvent molecules.
The move may not displace its own reference, and is refused if it would. Moving a reference atom
would shift the sphere the distances are measured from, changing every candidate's weight at once,
which the acceptance correction above does not account for. Restrict the move with molecule or
atom so that its candidates and the reference are distinct — an unrestricted !TranslateAtom
selects from every molecule in the system, the reference included.
| Key | Required | Default | Description |
|---|---|---|---|
reference |
yes | Selection expression for reference group(s); must not match atoms the move displaces | |
exponent |
no | 2 | Exponent \(\nu\) in the weight function; must be positive |
offset |
no | 1.0 | Offset (Angstrom) to avoid singularity at \(r = 0\); must be positive |
file |
no | Path to write selection-distance histogram (.dat/.csv) |
Rotate Molecule¶
Picks a random molecule of the given type and rotates it around a random axis
by an angle uniformly sampled in \([-\theta_\text{max}, +\theta_\text{max}]\), set by max_angle.
Atomic molecules have no orientation to sample and are rejected.
- !RotateMolecule { molecule: Protein, max_angle: 0.3, weight: 1.0 }
| Key | Required | Default | Description |
|---|---|---|---|
molecule |
yes | Name of the molecule type | |
max_angle |
yes | Maximum angular displacement, in \((0, \pi]\) radians; alias dprot |
|
weight |
yes | Selection weight | |
repeat |
no | 1 | Repetitions per selection |
Pivot Move¶
Picks a random atom as pivot in a polymer chain, randomly selects a bonded direction, and rotates the connected sub-tree around the pivot position. Uses the bond graph from the molecule topology, so it works for arbitrary topologies (linear, branched, star, dendrimer). The sub-tree is unwrapped along its bonds before rotation, so chains reaching further than half the box length turn correctly.
See Madras & Sokal, J. Stat. Phys. 50, 109–186 (1988).
- !PivotMove { molecule: Polymer, max_angle: 1.5, weight: 1.0 }
| Key | Required | Default | Description |
|---|---|---|---|
molecule |
yes | Name of the molecule type | |
max_angle |
yes | Maximum angular displacement, in \((0, \pi]\) radians; alias dprot |
|
weight |
yes | Selection weight | |
repeat |
no | 1 | Repetitions per selection |
The molecule must be bonded and free to change shape; declaring it rigid or frozen, or giving it no bonds, is an input error. Partially active molecules, as encountered under grand-canonical or speciation moves, are skipped.
Crankshaft Move¶
Picks a random bond axis in the molecule and rotates the smaller sub-tree
around it by an angle uniformly sampled in \([-\theta_\text{max}, +\theta_\text{max}]\), set by max_angle.
When proper dihedrals are defined, only their middle bonds are used as axes;
otherwise all bonds serve as candidate axes (e.g. FASTA chains with only
harmonic bonds). Terminal bonds are excluded, as no torsion is defined about them.
Because rotation is constrained to a single bond axis (1-DOF), crankshaft
preserves bond lengths and bond angles by construction. This makes it
complementary to PivotMove, which applies a full 3D rotation
(3-DOF) and can change bond angles at the pivot. For models without angle
potentials, PivotMove alone is typically sufficient.
- !CrankshaftMove { molecule: Peptide, max_angle: 0.5, weight: 1.0 }
| Key | Required | Default | Description |
|---|---|---|---|
molecule |
yes | Name of the molecule type | |
max_angle |
yes | Maximum angular displacement, in \((0, \pi]\) radians; alias dprot |
|
weight |
yes | Selection weight | |
repeat |
no | 1 | Repetitions per selection |
The restrictions listed for PivotMove apply here too.
Cluster Move¶
Picks a random seed molecule, grows a cluster of nearby molecules of the same type, and translates and rotates the whole cluster as one rigid body. In strongly associating systems — for example proteins with short-ranged attractions at high concentration — single-molecule moves leave a molecule trapped by its neighbours, so aggregates diffuse only slowly and structural observables such as \(S(q)\) converge poorly. Moving whole clusters restores that diffusion.
Two molecules join the same cluster when their separation is below threshold. The separation is
measured between mass centers (use_com: true, the default) or between the closest pair of beads
(use_com: false); the latter makes the threshold a surface separation that transfers across
molecule sizes. Membership is transitive: the cluster grows outward from the seed until no further
molecule lies within the threshold.
Detailed balance is preserved by rejecting any move after which the cluster membership would change, and by drawing the translation and rotation from symmetric distributions, so the move samples the correct Boltzmann distribution. The cluster grows in unwrapped coordinates, so a cluster that spans the periodic boundary still rotates correctly.
See Dress & Krauth, J. Phys. A 28, L597 (1995) and Whitelam & Geissler, J. Chem. Phys. 127, 154101 (2007).
- !ClusterMove { molecule: Protein, max_displacement: 10.0, max_angle: 0.5, threshold: 35.0 }
| Key | Required | Default | Description |
|---|---|---|---|
molecule |
yes | Name of the molecule type | |
max_displacement |
yes | Maximum translational displacement (Å); alias dp |
|
max_angle |
yes | Maximum angular displacement (radians); alias dprot |
|
threshold |
yes | Clustering distance (Å); mass-center or bead separation | |
use_com |
no | true |
Cluster on mass-center (true) or closest-bead (false) distance |
weight |
no | 1 | Selection weight in a !Stochastic collection |
repeat |
no | 1 | Repetitions per selection |
Output reports the mean cluster size \(\langle N\rangle\) with its standard error, the fraction of
trials rejected to preserve membership (bias_rejection_rate), and the root-mean-square
translational and rotational displacements. For an ideal gas, \(\langle N\rangle = 1 + (N/V)\,\tfrac{4}{3}\pi R_c^3\)
with threshold \(R_c\), a useful check that the clustering is unbiased.
Volume Move (NPT)¶
Proposes isotropic or anisotropic volume changes for sampling the NPT ensemble. The volume is sampled logarithmically:
where \(\xi\) is a uniform random number in \([0, 1)\) and \(\Delta \ln V\) is the width of the
displacement in \(\ln V\), set by volume_displacement. Being a displacement of the logarithm,
it is dimensionless: it scales the volume by a factor, not by an absolute amount.
No move-level bias is applied; the acceptance is handled by standard Metropolis
sampling together with the isobaric energy term
which contributes \(PV - (N+1) k_BT \ln V\).
Example¶
system:
energy:
pressure: !atm 1.0
propagate:
collections:
- !Stochastic
moves:
- !TranslateMolecule { molecule: Water, max_displacement: 0.5, weight: 1.0 }
- !VolumeMove { volume_displacement: 0.04, weight: 0.5 }
Options¶
| Key | Required | Default | Description |
|---|---|---|---|
volume_displacement |
yes | Width \(\Delta \ln V\) of the displacement in \(\ln V\); dimensionless (alias dV) |
|
weight |
yes | Selection weight | |
method |
no | Isotropic |
Scaling policy (see table below) |
repeat |
no | 1 | Repetitions per selection |
Scaling policies¶
| Policy | Description |
|---|---|
Isotropic |
Equal scaling in all directions (default) |
ScaleZ |
Scale along the z-axis only |
ScaleXY |
Scale the xy-plane only |
IsochoricZ |
Scale z and xy at constant total volume |
Speciation Move (Reaction Ensemble)¶
Performs molecular insertion/deletion and atom-type swaps according to chemical reactions in the grand canonical or semi-grand canonical ensemble. The acceptance criterion follows Smith & Triska, J. Chem. Phys. 100, 3019 (1994).
Each step randomly picks a reaction and direction (forward or backward), then proposes the corresponding operations:
- Molecular insertion: activates an empty group at a random position in the cell.
- Molecular deletion: deactivates a randomly chosen active group.
- Molecular swap: replaces a molecule of one type with another of equal atom count, preserving spatial orientation via gyration tensor alignment.
- Atom swap: changes the type of a random atom (for reactions like \(A \rightleftharpoons B\)).
Reactions are written using the syntax described in Chemical Reactions.
The equilibrium constant \(K\) is related to the excess chemical potential,
and the system must pre-allocate inactive molecule slots using active < N
in the blocks section.
Molecular insertion and deletion¶
\(K\) is dimensionless, referred to a standard state of 1 M. Concentrations therefore enter the acceptance relative to the standard-state number density
so it is \(c_0 V\), not \(V\), that pairs with \(K\).
For a reaction that creates or destroys molecules (e.g. \(\emptyset \rightleftharpoons M\) with equilibrium constant \(K\)), the acceptance follows:
where \(N\) is the number of molecules before the move and \(V\) is the cell volume. At equilibrium for an ideal gas (\(\Delta U = 0\)) this yields
To place on average ten molecules in a \(10 \times 10 \times 10\) Å cell, set \(K = 10 / (c_0 V) = 16.6054\).
For a general reaction \(\sum_i \nu_i A_i = 0\) involving multiple species, the combinatorial bias generalises to
with the sign matching the direction of the stoichiometric change (doi:10/fqcpg3).
Reservoir molecules participate as molecular
reaction species and do not need a ~ prefix.
The factor \(c_0 V\) is replaced by unity for reservoir species,
since they exist outside the simulation cell.
Atom-type swaps¶
For reactions that swap atom types within a molecule (e.g. \(A \rightleftharpoons B\) with equilibrium constant \(K\)), the acceptance is:
where \(N_\text{from}\) and \(N_\text{to}\) are the counts of the source and target atom types before the swap, summed over all molecules of the relevant type. This \(N_\text{from}/(N_\text{to}+1)\) factor ensures detailed balance and yields a binomial equilibrium distribution with \(\langle N_B \rangle / \langle N_A \rangle = K\), consistent with Faunus and ESPResSo.
Molecular swaps¶
When a reaction has exactly one molecular reactant and one molecular product (each with multiplicity one) of the same atom count (e.g. \(A \rightleftharpoons B + \text{implicit}\)), the move is automatically detected as a molecular swap. A full group of the source type is deactivated and an empty group of the target type is activated with positions transferred via gyration tensor principal-axis alignment.
A species appearing with a coefficient greater than one (e.g. \(2A \rightleftharpoons B\))
is not a swap: it is handled as insertion/deletion of the individual molecules,
conserving charge across the whole reaction. Charge-conserving exchanges such as
\(2\,\mathrm{Na}^+ \rightleftharpoons \mathrm{Ca}^{2+}\) work with either one group per
ion or pooled atomic: true ions.
A one-to-one reaction between two species is always read as a molecular swap, so both
species must be non-atomic: every member of an atomic: true kind shares a single
group, which cannot move between full and empty on its own.
The acceptance is:
where \(N_\text{from}\) and \(N_\text{to}\) are the counts of source and target
molecule groups before the move.
No volume factor appears because the total molecule count is conserved.
\(\Delta U\) excludes intramolecular energy (bonded and nonbonded self-interactions)
since these are absorbed into the equilibrium constant \(K\).
The total energy still counts it, so if the two states differ in intramolecular energy —
say their sites carry different charges — the incremental and the recomputed energy
disagree and the run reports an energy drift. Exclude every intramolecular pair of the
swapped molecules to remove the term from both sides; faunus warns at startup when a swap
between molecules of differing atom types leaves such pairs unexcluded.
Each species must have pre-allocated groups (active < N) to serve as a pool;
if the pool is exhausted, the move is silently rejected.
Phosphate titration example¶
Four charge states of orthophosphate with three \(pK_a\) values and implicit protons:
atoms:
- {name: P, mass: 31.0, sigma: 3.0}
- {name: O, mass: 16.0, sigma: 2.8}
- {name: H+, mass: 1.0, activity: 6.31e-8} # pH 7.2
molecules:
- name: H₃PO₄
atoms: [P, O, O, O, O]
- name: H₂PO₄⁻
atoms: [P, O, O, O, O]
- name: HPO₄²⁻
atoms: [P, O, O, O, O]
- name: PO₄³⁻
atoms: [P, O, O, O, O]
system:
blocks:
- {molecule: H₃PO₄, N: 20, active: 0, insert: !RandomAtomPos {}}
- {molecule: H₂PO₄⁻, N: 20, active: 20, insert: !RandomAtomPos {}}
- {molecule: HPO₄²⁻, N: 20, active: 0, insert: !RandomAtomPos {}}
- {molecule: PO₄³⁻, N: 20, active: 0, insert: !RandomAtomPos {}}
propagate:
collections:
- !Deterministic
moves:
- !SpeciationMove
reactions:
- ["H₃PO₄ = H₂PO₄⁻ + ~H+", !pK 2.15]
- ["H₂PO₄⁻ = HPO₄²⁻ + ~H+", !pK 7.20]
- ["HPO₄²⁻ = PO₄³⁻ + ~H+", !pK 12.35]
At \(pH = pK_{a2} = 7.20\), the effective equilibrium constant for the second reaction is unity, giving equal populations of H₂PO₄⁻ and HPO₄²⁻.
Grand-canonical salt example¶
Insertion and deletion of a neutral ion pair from a salt reservoir at fixed activity.
For single-atom species, atomic: true pools all instances into one group, reducing
overhead from \(N\) groups to one.
atoms:
- {name: Na, mass: 22.99, charge: 1.0, sigma: 3.3, epsilon: 0.01}
- {name: Cl, mass: 35.45, charge: -1.0, sigma: 4.4, epsilon: 0.01}
molecules:
- name: cation
atoms: [Na]
atomic: true
activity: 0.05 # molar
- name: anion
atoms: [Cl]
atomic: true
activity: 0.05
system:
cell: !Cuboid [40.0, 40.0, 40.0]
medium:
permittivity: !Water
temperature: 298.15
energy:
nonbonded:
default:
- !Coulomb {cutoff: 20.0}
- !WeeksChandlerAndersen {mixing: LB}
blocks:
- {molecule: cation, N: 120, active: 30, insert: !RandomAtomPos {}}
- {molecule: anion, N: 120, active: 30, insert: !RandomAtomPos {}}
propagate:
repeat: 10000
collections:
- !Stochastic
moves:
- !TranslateAtom {atom: Na, molecule: cation, max_displacement: 5.0}
- !TranslateAtom {atom: Cl, molecule: anion, max_displacement: 5.0}
- !Deterministic
moves:
- !SpeciationMove
repeat: 5
reactions:
# Both activities fold into K_eff; see Activity folding below.
- ["= cation + anion", !dG 0.0]
The ion densities settle above the 0.05 M reservoir activity — about 0.061 M here. The activity, not the concentration, is what the reservoir fixes; ion–ion attraction makes the electrostatic excess chemical potential negative, so the mean activity coefficient \(\gamma_\pm \approx 0.82 < 1\) and \(c = a / \gamma_\pm > a\).
Options¶
| Key | Required | Default | Description |
|---|---|---|---|
reactions |
yes | List of reactions (see below) | |
weight |
no | 1 | Selection weight |
repeat |
no | 1 | Repetitions per selection |
temperature |
no | Deprecated and ignored; see below |
The system temperature (system.medium.temperature) sets the thermal energy \(RT\) used
throughout. The temperature key is a leftover that duplicated it, and a value
disagreeing with the system temperature is an error — remove the key.
Each reaction is a two-element tuple [reaction_string, equilibrium_constant]:
- Reaction string: e.g.
"= NaCl"or"⚛A = ⚛B" - Equilibrium constant:
!K <value>,!lnK <value>,!pK <value>(\(K = 10^{-\text{pK}}\)), or!dG <kJ/mol>(\(K = e^{-\Delta G / RT}\), with \(R\) the molar gas constant, matching the kJ/mol energy unit)
An equilibrium constant that overflows to infinity — from a large !lnK, or from a
!dG mistakenly given in J/mol — is rejected at startup rather than accepting every
trial.
Activity folding¶
The user-specified \(K\) (or \(10^{-\text{pK}}\)) is combined with species activities to form an effective equilibrium constant used in acceptance:
where:
- Implicit species (
~H+): \(a_i\) is theactivityfield on the matching atom type, or, if no atom type carries that name, on the matching molecule type — so an implicit molecular reservoir such as~H2Ois legal. Consumed reactants increase \(K_\text{eff}\); produced products decrease it. - Molecular species involved in insertion/deletion (
Na+,Cl-): \(z_i = a_i c_0\) converts the molaractivityon the molecule type to a number density. The sign is reversed relative to implicit species because the acceptance criterion already includes the combinatorial factor \((c_0 V)^{\Delta\nu} \cdot \prod [N!/(N+\nu)!]\), which uses \(N/(c_0 V)\); the fugacity correction turns this into \(N/(c_0 V a)\). - Molecular swap participants are excluded from fugacity folding since no volume factor enters the acceptance (total molecule count is conserved).
For example, with ["= Na+ + Cl-", !K 1.0] and molecular activities
of 0.030 M on both ions, the bare \(K=1\) is modified by the two product
fugacities: \(\ln K_\text{eff} = 0 + \ln z_\text{Na} + \ln z_\text{Cl}\).
Notes¶
- Molecule blocks must have
active < Nto provide empty slots for insertion and swap targets. - A titratable atom type may occur in several molecule types; all of them titrate, and \(N_\text{from}\) and \(N_\text{to}\) are counted over the whole population. If some molecule type lists both protonation states, only those types titrate — which keeps a species that merely reuses the same atom type (say a monatomic salt ion) out of the reaction.
- Molecular swaps are auto-detected when a reaction has one molecular reactant and one molecular
product with equal atom counts. Pool exhaustion silently rejects the move — increase
Nif needed. - Inserted molecules arrive with their reference geometry at a random position and orientation.
- The move targets the entire system, so energy is recomputed globally on each trial.
The following are rejected at startup rather than sampled as a different reaction:
- an atom or molecule name that matches no type;
- unbalanced atom stoichiometry, e.g.
"⚛A + ⚛A = ⚛B"; - an equilibrium constant that is not positive and finite;
- a reaction naming a molecule for which no
blocks:entry allocates groups; - a one-to-one reaction between
atomic: truespecies.
Gibbs Ensemble¶
The Gibbs ensemble method
(Panagiotopoulos, Mol. Phys. 61, 813 (1987))
simulates two coupled simulation boxes to study phase coexistence without
an explicit interface.
When propagate.gibbs is present, faunus clones the system into two boxes
and alternates between:
- Intra-box MC — each box runs
intra_stepspropagation cycles in parallel (using thecollectionsdefined above). - Inter-box moves — volume exchange and particle transfer between the two boxes.
The total number of Gibbs sweeps is repeat / intra_steps.
Molecule blocks must pre-allocate inactive slots for transfer using active < N
in the blocks section, e.g. { molecule: LJ, N: 600, active: 300 }.
Configuration¶
propagate:
repeat: 5000
collections:
- !Stochastic
moves:
- !TranslateMolecule { molecule: LJ, max_displacement: 0.3, repeat: 100 }
gibbs:
intra_steps: 1
moves:
- !GibbsVolumeExchange { volume_displacement: 0.3 }
- !GibbsParticleTransfer { molecule: LJ }
| Key | Required | Default | Description |
|---|---|---|---|
intra_steps |
yes | Intra-box propagation cycles between inter-box moves | |
moves |
yes | List of inter-box moves |
Gibbs Volume Exchange¶
Exchanges volume between two boxes while conserving total volume \(V_1 + V_2\). Both boxes are isotropically rescaled and all particle positions scale with the box. \(N\) counts independently translatable mass centers: one per molecular group, one per active atom in atomic groups.
Logarithmic (default) — displaces in \(\ln(V_1/V_2)\) space (Frenkel & Smit, Sec. 8.3.2):
The \((N{+}1)\) factor comes from the Jacobian of the \(\ln V\) transformation.
Linear (opt-in) — direct \(\delta V\) transfer (Allen & Tildesley, Eq. 9.75):
- !GibbsVolumeExchange { volume_displacement: 10 } # default: Logarithmic
- !GibbsVolumeExchange { volume_displacement: 10, method: Linear } # opt-in linear
| Key | Required | Default | Description |
|---|---|---|---|
volume_displacement |
yes | Displacement width; its meaning follows method (see below). Alias dV |
|
method |
no | Logarithmic |
Displacement method: Logarithmic or Linear |
The two methods give volume_displacement different meanings and different units:
Logarithmic— the width of a displacement in \(\ln(V_1/V_2)\), so it is dimensionless and scales the two volumes by a factor while conserving \(V_1 + V_2\).Linear— the width of a direct volume transfer \(\delta V\), in ų.
Gibbs Particle Transfer¶
Transfers a molecule from one box to the other. A random direction is chosen (box 0 → 1 or box 1 → 0). Both molecular and atomic molecule kinds are supported: for molecular groups, a full group is deactivated/activated; for atomic groups, a single atom is removed/inserted via the speciation expand/shrink mechanism. If no suitable slot exists in either box, the move is rejected.
Acceptance follows Panagiotopoulos Eq. 8:
where \(N\) counts are measured before the move.
- !GibbsParticleTransfer { molecule: LJ }
| Key | Required | Description |
|---|---|---|
molecule |
yes | Name of the molecule type to transfer |
Langevin Dynamics¶
Rigid-body Langevin dynamics using the BAOAB splitting scheme, accelerated via
CubeCL (wgpu, CUDA, or CPU backends).
Molecules are treated as rigid bodies with translational and rotational degrees of freedom,
integrated with per-body friction and stochastic forces at the target temperature.
Requires the gpu cargo feature (cargo run --features gpu).
Langevin dynamics is placed as a collection entry alongside Monte Carlo moves, enabling hybrid MC/LD schemes where MC sweeps alternate with LD blocks within each propagation cycle. On each MC→LD transition, atom positions, centers of mass, and rigid-body orientations are uploaded to the compute device; after the LD block, updated positions and orientations are downloaded back.
Pair interactions are evaluated on-device using cubic spline interpolation of the
tabulated pair potentials (see energy.spline in Energy).
A cell list reduces pairwise force evaluation from \(O(n^2)\) to \(O(n \cdot k)\)
where \(k\) is the number of atoms in neighboring cells.
The cell list is built on the CPU from periodically downloaded positions
and uploaded as a CSR structure; the rebuild interval is configurable.
Intramolecular bonded forces (harmonic bonds, harmonic angles, and periodic/harmonic
dihedrals) are also computed on-device when present in the topology.
Theory¶
The Langevin equation couples Newtonian dynamics to a heat bath through friction and stochastic forces:
where \(m\) is the particle mass, \(\gamma\) the friction coefficient (1/ps), \(\mathbf{F}\) the conservative force, and \(\mathbf{\xi}(t)\) is Gaussian white noise with \(\langle \xi_i(t)\,\xi_j(t') \rangle = \delta_{ij}\,\delta(t - t')\). The friction and noise terms satisfy the fluctuation–dissipation theorem, ensuring that the system samples the canonical (NVT) ensemble at temperature \(T\).
BAOAB integrator¶
Time integration uses the BAOAB splitting (Leimkuhler & Matthews, Appl. Math. Res. Express 2013, 34–56), which splits each timestep \(\Delta t\) into five sub-steps:
| Step | Operation |
|---|---|
| B | Half-kick: \(\mathbf{v} \leftarrow \mathbf{v} + \frac{\Delta t}{2m}\,\mathbf{F}\) |
| A | Half-drift: \(\mathbf{r} \leftarrow \mathbf{r} + \frac{\Delta t}{2}\,\mathbf{v}\) |
| O | Ornstein–Uhlenbeck: \(\mathbf{v} \leftarrow e^{-\gamma \Delta t}\,\mathbf{v} + \sqrt{\frac{k_BT}{m}(1 - e^{-2\gamma \Delta t})}\;\mathbf{R}\) |
| A | Half-drift: \(\mathbf{r} \leftarrow \mathbf{r} + \frac{\Delta t}{2}\,\mathbf{v}\) |
| B | Half-kick: \(\mathbf{v} \leftarrow \mathbf{v} + \frac{\Delta t}{2m}\,\mathbf{F}\) |
Here \(\mathbf{R}\) is a vector of independent standard normal variates. Placing the stochastic step (O) at the center gives superior configurational sampling accuracy compared to other splittings, with the configurational distribution correct to \(\mathcal{O}(\Delta t^2)\).
Rigid-body rotational dynamics¶
Each molecule is represented by its center-of-mass position and a unit quaternion \(\mathbf{q}\) encoding orientation. Atom positions are reconstructed as
where \(\mathbf{r}_i^{\,\text{ref}}\) are time-independent reference coordinates in the body frame. Rotational equations of motion follow the same BAOAB pattern, with the body-frame angular velocity \(\mathbf{\omega}\) and diagonal inertia tensor \(\mathbf{I} = \operatorname{diag}(I_{xx}, I_{yy}, I_{zz})\) replacing \(\mathbf{v}\) and \(m\). The O step applies the Ornstein–Uhlenbeck thermostat independently to each angular velocity component:
The A drift steps update the quaternion by composing an incremental rotation:
Torques are computed from the forces on each atom in the body frame: \(\mathbf{\tau} = \sum_i \mathbf{r}_i^{\,\text{ref}} \times \mathbf{f}_i^{\,\text{body}}\).
Example¶
propagate:
seed: Hardware
criterion: Metropolis
repeat: 500
collections:
- !Stochastic
repeat: 20
moves:
- !TranslateMolecule { molecule: Water, max_displacement: 0.5, repeat: 1 }
- !RotateMolecule { molecule: Water, max_angle: 0.3, repeat: 1 }
- !LangevinDynamics
timestep: 0.1
friction: 5.0
steps: 20
temperature: 298.15
Options¶
| Key | Required | Default | Description |
|---|---|---|---|
timestep |
yes | Integration timestep (ps) | |
friction |
yes | Friction coefficient (1/ps) | |
steps |
yes | Number of LD steps per block | |
temperature |
yes | Target temperature (K) | |
cell_list_rebuild |
no | 20 | Cell list rebuild interval (steps; 0 = only at start) |
Output¶
After simulation, the YAML output reports measured temperatures from the equipartition theorem:
- !LangevinDynamics
timestep: 0.1
friction: 5.0
steps: 20
temperature: 298.15
measured_temperature:
translational: {mean: 298.3, error: 1.2}
rotational: {mean: 297.8, error: 2.1}
Notes¶
- Molecules must have
degrees_of_freedom: Rigidandhas_com: truein the topology. - The simulation cell must be bounded (cuboid).
- Velocities are initialized from the Maxwell–Boltzmann distribution on the first call and persist on the compute device across subsequent LD blocks.
- MC rotation moves (
!RotateMolecule) automatically track rigid-body orientation, which is transferred to the device at each LD block start. - Energy splines must be configured (
energy.spline) to provide on-device pair potentials.