The planner¶
Every Simulation (and so every fm.md, fastmace md and fastmace.ase
run) starts with a plan. The planner reads the model, the structure, the
integrator, the workload, the installed software and the GPU, and decides:
- the tier: the CUDA-graph engine (fastest), the compiled tier without graphs, the eager hybrid, or the reference path;
- the backend: the cuEquivariance/OpenEquivariance hybrid, or plain cuEquivariance;
- the precision of the force evaluation (float32 by default; integration is always float64);
- which rewrites are on, and the reason for each one that is off;
- the neighbour-list skin and buffer sizes.
Rules are general: there are no per-GPU or per-crystal tuning tables. Every rewrite is exact to rounding and is checked against the original MACE module when it is applied.
Read the plan¶
model = fm.load("mh1", head="matpes_r2scan")
sim = fm.Simulation(atoms, model, integrator=..., seed=1)
print(sim.plan) # str(plan): about 30 lines, by section
print(sim.plan.describe(full=True)) # every decision with its rule and reason
str(plan) gives a short overview: the tier, backend and precision, the
hard rules that decided them, the rewrites that are on and the ones that are
off with a short reason. describe(full=True) lists every decision. The
same text is in the run report and in metadata.json.
plan.decision(key) returns (item, choice, reason) for one decision, and
plan.overrides() lists the options you set explicitly.
Influence the plan¶
- Workload:
fm.Workload(max_temperature_K=..., species_changes=..., mc_moves=..., host_callbacks_every=...)tells the planner what the run will do.fm.mdinfers it from its arguments. A schedule abovemax_temperature_Kis refused. For runs with MC moves or species changes the skin and buffer headroom are sized from it; plain MD keeps the 0.3 Å skin. - Mode:
Simulation(mode=...)asks for a tier;Nonelets the planner choose. - Rewrites and precision live on the force field:
fm.ForceField(model, atoms, precision="float32", rewrites="auto"). - An option the planner cannot honour raises
PlanRefusedwith every reason, before the first step. Nothing is substituted silently.
The gate¶
check="gate" evaluates the planned engine on your structure (and rattled
copies) against a float64 reference before the first step. If it fails, the
fallback searches for the closest plan that passes, turning off rewrites one
by one, and records what it did. The gate is opt-in; the default is
check="skip". The record is sim.gate.
Runtime adaptation¶
During a run the planner watches re-captures and buffer overflows. Past a
budget it may switch tier at a committed step, or fall back after a capture
error, and the report's runtime line records it. A resume rebuilds the
recorded revision exactly.
When the run did not get the graph engine¶
The report says why and what would change it: a structure that is not 3D
periodic, a missing OpenEquivariance (fastmace doctor names the piece), a
model outside the rewrite registry, padded edges that are not exactly zero,
a failed self-check, or a fallback after a failed gate.
The full rule list is on Planner, gate and fallback. The planner design note in the repository explains the design.
See also: Planner, gate and fallback, Engine and neighbour list, Rewrites and precision.