Moves
A move in mcpy proposes a new atomic configuration. The ensemble then evaluates the corresponding acceptance rule – Metropolis for number-conserving moves, de-Broglie for insertions and deletions – and either commits the new configuration or rolls back.
Every move exposes do_trial_move(atoms), which proposes a trial structure and, for number-changing moves, signals the change via delta_particles. A run typically mixes several move types using a MoveSelector.
MoveSelector
MoveSelector samples moves from a weighted list.
One ensemble step runs n_moves trial moves, and each trial draws its own move.
By default n_moves is round(sum(weights)) (at least 1), so the weights [1, 1] give two
trials per step.
Pass n_moves to set the count directly.
The selector tracks acceptance statistics on two levels:
per-interval counters – reset after each log write; reported in outfile as the recent acceptance ratio of each move,
cumulative counters – never reset; reported in the final summary at the end of the run.
Trial moves that cannot be proposed (for example, a deletion when no atom of the requested species lies inside the cell) are tracked separately and excluded from the acceptance-ratio denominator, so the reported ratios reflect viable attempts only.
from mcpy.moves import MoveSelector, InsertionMove, DeletionMove
selector = MoveSelector(
probabilities=[1, 1],
move_list=[
InsertionMove(cell, ["O"], seed=1),
DeletionMove(cell, ["O"], seed=2),
],
)
Weights need not sum to one – they are interpreted as relative frequencies.
The acceptance rule assumes that a species is inserted and deleted with equal probability per
trial in the same cell.
GrandCanonicalEnsemble checks this when you create it.
For each species and cell, it adds up the insertion weights and the deletion weights (a move
with several species splits its weight equally between them).
If the two sums differ, it raises ValueError, because the difference shifts
\(\mu\) by \(kT \ln(p_{\mathrm{ins}}/p_{\mathrm{del}})\).
Give the insertion move and the deletion move of a species the same weight, the same species
list and the same cell object.
Built-in moves
The following move classes are available from mcpy.moves.
The displacement, shake, permutation and MD moves act on atoms anywhere in the box. They can carry an exchanged atom out of the region of the insertion and deletion moves, or into it. GrandCanonicalEnsemble rejects such trials for a SphericalCell, a DomeCell and the top of a CustomCell (see Cells).
InsertionMove
Attempts to insert an atom of one of the selected species at a random point drawn from the
attached cell. Sets delta_particles = +1 on a successful proposal. Optional max_atoms
skips the trial (no mutation, no energy evaluation) when the structure already contains at
least that many free atoms of the selected species.
Free atoms are the atoms outside molecules (molecule_id < 0), in the whole system, so the
substrate counts too.
Optional min_insert is a seed clearance for relaxed trials (ADR 0004).
Use it only with a relaxing calculator: with single-point energies it shifts \(\mu\) by
\(kT \ln(V_{\mathrm{free}}/V_{\mathrm{seed}})\), and the ensemble warns.
DeletionMove
Attempts to delete a randomly chosen atom of one of the selected species lying inside the
attached cell. Sets delta_particles = -1 on a successful proposal; returns falsy when no
candidate atom exists or when optional min_atoms would be violated, which the
MoveSelector records as a failure rather than as a rejection.
min_atoms counts free atoms (molecule_id < 0) of the species in the whole system,
like max_atoms.
Atoms held by FixAtoms are never deleted, because no insertion can put them back.
DisplacementMove
Displaces one randomly selected atom by a random vector with magnitude up to max_displacement. Particle count is preserved (delta_particles = 0).
The optional n_steps parameter (default 1) bundles n_steps distinct atom
displacements into a single trial – the energy is evaluated once, after all displacements,
and the whole compound perturbation is accepted or rejected together. This is the building
block of basin-hopping with displacement moves: a one-atom step usually relaxes back into the
same basin, so a meaningful escape requires several atoms to move at once.
If n_steps is larger than the number of movable atoms, the move displaces all movable atoms.
PermutationMove
Swaps the species labels of two atoms drawn from different species groups. Useful for sampling compositional ordering (homotop space) in multi-component systems at fixed stoichiometry.
The optional n_swaps parameter (default 1) applies n_swaps independent pair swaps
in a single trial – one energy evaluation, one accept/reject. For basin-hopping on alloy
ordering, a single swap is typically too gentle (relaxation returns to a near-identical
basin); a perturbation of order \(\sim 1\text{--}5\%\) of the atom count per trial is a
sensible default. In a replica-exchange run, scaling n_swaps with replica temperature –
small n_swaps for cold refiners, large n_swaps for hot explorers – keeps acceptance
ratios balanced across the ladder.
ShakeMove
Displaces all atoms by independent random vectors bounded by r_max. Useful as a global
perturbation, typically combined with a local relaxation in the calculator wrapper.
Atoms held by FixAtoms do not move.
Without FixAtoms, the move removes the mass-weighted mean displacement, so a free particle
does not drift through the box.
BrownianMove
Runs a short Velocity-Verlet trajectory at a target temperature as the trial move. Useful as a relaxation-like perturbation that explores the local basin more thoroughly than a single random displacement.
AlchemiBrownianMove
Runs a short Langevin MD trajectory on the GPU as the trial move, reusing the model of an
Alchemi calculator, so no second model is loaded. The MD needs forces: pass an
AlchemiFCalculator, or an AlchemiCalculator built with energy_only=False
(an AlchemiCalculator that loads its own model is energy-only by default).
Both MD moves take a debug option, trajectory_file.
When you set it, the move appends every MD step of every call to that file as an extended-XYZ frame.
The move writes the frames before the acceptance test, so the file also contains the rejected runs.
Each frame holds the positions, the velocities (as momenta) and the forces.
The info line holds md_run (the call count of the move), md_step, time_fs,
T_target_K, the instantaneous T_K, and epot, ekin and etot in eV.
Use it on short runs only, because it writes one frame per MD step.
Without FixAtoms, both MD moves remove the center-of-mass motion.
BrownianMove zeros the net momentum of the initial velocities, and AlchemiBrownianMove
zeros the center-of-mass velocity after every Langevin step.
Otherwise each accepted move would shift the whole particle a little, and the shifts would add
up to a random walk.
With FixAtoms, the fixed atoms hold the system in place, and the COM motion is kept.
If every atom is fixed, the move is a failed proposal.
Warning
BrownianMove and AlchemiBrownianMove do not satisfy exact detailed balance. The acceptance uses the potential energy only. It has no kinetic-energy term, and an MD or Langevin trajectory is not a symmetric proposal. Use these moves for basin-hopping-style exploration with a relaxing calculator. Do not use them with an energy-only calculator when you need equilibrium averages.
Molecular moves
Three moves exchange and move whole rigid molecules. They identify a molecule by the
per-atom molecule_id array and take the ASE template and the species name used as the
key in mu. Simulating molecular adsorbates explains the bookkeeping and the chemical
potential.
MoleculeInsertionMove
Inserts the template at a random center of mass drawn from the cell’s free volume, with a
uniform random orientation. Optional max_molecules caps the population.
MoleculeDeletionMove
Deletes one whole molecule, drawn uniformly among those whose center of mass lies in the
cell’s exchangeable region. Optional min_molecules keeps a floor.
MoleculeDisplacementMove
Translates one molecule by up to max_displacement and rotates it about its center of
mass, rigidly. Optional max_angle caps the rotation for strongly anchored adsorbates.
A move that would carry the center of mass out of the cell counts as a rejection.
The test uses cell.is_point_inside, so for a CustomCell the top is a hard wall.