The project's README from github.com/kpleo/pyraimd. As one markdown file: README.md.
Python wrapped Ab initio Molecular Dynamics — a name drawn from the PYR-AIMD letters.
Pyramid brings first-principles engines, machine-learned interatomic potentials (MLIPs), solvers and molecular dynamics into one extensible Python framework. Reference calculations supply energies and forces; fast potentials propagate atomic motion; the framework coordinates when to evaluate, check and update them.
Its energetic force-error method connects force accuracy to the motion of the atoms. A local directional response predicts how force errors grow away from a reference configuration. Signed residual work measures their energetic effect along the trajectory. Together, these quantities guide reference calculations and provide a physical account of the forces used during a run.
Python 3.12 or later. The core install needs only NumPy and ASE — no torch, no PySCF, no external programs. From a checkout:
pip install . # user install
pip install -e '.[dev]' # development: adds pytest and ruff
Or install the 0.7.5 wheel into a clean virtual environment. The wheel and source distribution are attached to the corresponding GitHub Release; the examples and example plugins below come from that tag's source tree:
python -m venv ~/.venvs/pyramid && . ~/.venvs/pyramid/bin/activate
pip install pyraimd2-0.7.5-py3-none-any.whl
A first run with the built-in harmonic model — the analytic demo needs no backend installation and finishes in seconds. Validation has three separate layers, and the CLI keeps them explicit:
pyramid validate run.toml — is the configuration well-formed? This
never touches the machine's programs or packages.pyramid validate run.toml --check-environment — are the local
runtime prerequisites present (executables, optional packages, local
model files)? Read-only and zero-computation: it starts no backend,
runs no command, loads no weights, downloads nothing. A
blocked/unverified answer explains what it could and
could not confirm.pyramid validate run.toml --probe-backends — explicitly evaluate the
structure once per backend (the only layer that computes).pyramid init --template harmonic --output my_run
pyramid validate my_run/run.toml
pyramid validate my_run/run.toml --check-environment # harmonic: ready
pyramid run my_run/run.toml
pyramid inspect my_run/runs/harmonic-demo
pyramid resume my_run/runs/harmonic-demo --steps 5
pyramid export my_run/runs/harmonic-demo --force-source driving
All three validation scopes also accept --json, which writes one
machine-readable report object to stdout (handy for submission scripts:
a blocked environment is distinguishable from an invalid configuration
by exit status and by readiness).
Optional backends install separately and are only imported when selected:
pip install '.[pyscf]' # molecular reference engine
pip install '.[mace]' # MACE surrogate potentials
all installs both; builders adds optional structure-building tools. Quantum
ESPRESSO additionally needs a pw.x executable and pseudopotentials installed
outside Python.
The Python import is pyraimd2; the CLI is pyramid (alias pyraimd2).
pyramid --version and pyramid --help work offline and download nothing.
examples/harmonic_adaptive/ is a complete, offline adaptive NVE run: builtin
analytic reference and surrogate models drive a toy H2O molecule. It exercises
anchoring, surrogate acceptance, independent checks, checkpoints, stop and
resume — no external programs, no model downloads, finishes in seconds:
cd examples/harmonic_adaptive
pyramid validate run.toml
pyramid run run.toml
pyramid inspect runs/harmonic-demo
pyramid resume runs/harmonic-demo --steps 10
pyramid export runs/harmonic-demo --force-source reference --output reference.extxyz
pyramid init --template harmonic --output my_run writes the same pair of
files as a starting point for your own configuration. The template's policy and
verification numbers are demonstration values, not accuracy recommendations for
any material. The full field reference is in
docs/configuration.md.
examples/periodic_lj/ runs a 32-atom fcc Lennard-Jones cell through the three
stages with only NumPy + ASE plus the example plugin. The NVT stage is adaptive
(fixed model) and the NVE stage continues with the NVT boundary's complete
momenta — never rethermalized:
pip install . # the core package
pip install examples/backends/pyraimd2_lj # the example backend plugin
cd examples/periodic_lj
python run_recipe.py --output results/lj-recipe # relax + NVT + NVE
python run_recipe.py --output results/lj-recipe # continue/resume, idempotent
pyramid inspect results/lj-recipe/nvt
pyramid export results/lj-recipe/nve --force-source driving
For guarded online model updates under NVT (Python interface),
examples/guarded_nvt.py runs offline on analytic potentials, with stop and
new-process resume.
examples/qe_mace_skeleton/ shows the configuration shape for a real-material
adaptive run: pw.x as the reference engine and a MACE foundation model as the
surrogate over a small periodic silicon cell. It is a skeleton, not a verified
materials recipe. For complete structure generators and task configurations,
see the bulk Si and
Al(111) slab examples. They include
input requirements, short NVE runs, resume and export commands.
Before pyramid run works you need, on that machine:
pw.x on PATH (or reference.pw_cmd) and the pseudopotential files the
configuration names;pip install '.[mace]' and a MACE model (a local file, or a foundation-model
name that MACE itself downloads on first use).Without them, pyramid validate run.toml still parses the configuration and
reports configuration problems — and
pyramid validate run.toml --check-environment is the layer that reports the
local prerequisites themselves before any run is committed (a missing pw.x, a missing
optional package, a not-yet-downloaded foundation-model name, or a
launcher command such as srun -n 4 pw.x whose solver layer cannot be
confirmed statically are reported as blocked or unverified, with the
remedy spelled out). With them,
pyramid validate run.toml --probe-backends evaluates the structure once with
each backend before committing to a run.
Ctrl-C during pyramid run stops at the next complete-step boundary and
writes a checkpoint; nothing is half-written.pyramid resume RUN_DIR --steps N always adds N steps to wherever the run
actually is, and prints the current and target step numbers first. Settings
come from the run's resolved_config.json — same physics, model chain and
check stream. This works for adaptive runs and for plain
reference/surrogate-only runs.pyramid resume RUN_DIR --steps N --force-unlock reclaims it (only when no
live writer exists).file_parameters) can be
relocated — moved together with those files and resumed at the new
location, with the files re-verified byte-for-byte first: from Python
via resume_workflow(..., resource_paths=...), or from the CLI via
pyramid resume RUN_DIR --steps N --resource 'BACKEND.ROLE=PATH'
(repeatable; a relative PATH resolves against the caller's working
directory). The offline walkthrough
examples/file_model_relocation/ shows
the full loop in two processes.[scratch] root = "...", retention = "..."
section (or QeConfig(scratch_root=..., retention=...)). Every adapted
attempt runs in its exclusive tmp/<run-uuid>/<backend-role>/<request>/ <attempt>/ directory; with retention = "results" the verified result
is archived out of scratch and the attempt's subtree is reclaimed
immediately, with pyramid scratch inspect --root PATH and
pyramid scratch clean --root PATH [--dry-run] to view and safely retry.
A complete fake-QE walkthrough — install, configure the root, run a
standalone label, read the archived result, inspect and clean — is in
examples/standalone_qe_label/ (its
demo_fake.sh verifies the program flow only; it produces no real DFT
label). Older processes never switch code mid-run, and existing runs
are never migrated or cleaned retroactively: enable the root for new
tasks. The verified cross-version scope today is the plain-NVT toy
checkpoint resume under identical dependencies.fork that inherits
the physical state and model chain under a new check stream.Plain serial reference MD runs can opt into the persistent density chain
([density] persist = true): every successful evaluation publishes one
immutable, content-verified generation under restart/density/ in the run
directory. To see why each generation is kept — without changing
anything — run:
pyramid density inspect RUN_DIR
The JSON answer lists every generation with its decision
(keep / reclaim_candidate / hold / reclaimed), the concrete
reasons (latest pointer, retained checkpoints, committed boundary,
in-flight inputs, unconsumed producer seeds, tombstones), any blocked
references, and the space report per class. reclaim_candidate there
is a preview, not a deletion authorization, and the report claims no
bound on the run's whole-disk usage. The command is strictly read-only
and applies to the plain serial reference-MD workflow shape.
Two routes, both without modifying the core package:
Python API — the generic adapters wrap separately configured ASE calculator instances:
from pyraimd2.engines import AseEngine
from pyraimd2.surrogate import AseSurrogate
engine = AseEngine(reference_calculator, force_consistent=True)
surrogate = AseSurrogate(potential_calculator)
Plugin package — register factories under the pyraimd2.backends
entry-point group and the backend name becomes usable from TOML
configurations. examples/backends/pyraimd2_harmonic/ is a minimal,
installable example (two analytic backends, ~one file of code).
pyramid backends lists everything the registry can see.
Capability declarations (energy kind, force consistency, stress, uncertainty) are checked when a backend is created — before any expensive calculation. See docs/architecture.md for the protocols.
Engine/Surrogate protocols, capabilities and identity fingerprints.engines,
surrogate, runtime, workflows and backends modules.pyraimd2.energetics is a pure numerical layer (directional response,
forecasts, signed work, independent checks) usable outside MD.pyraimd2.loop.online (GuardedUpdater, UpdatePolicy) is the guarded
candidate → validate → publish/rollback protocol for stateful model updates;
pyraimd2.runtime provides the event log, checkpoints and the immutable
model registry a new updater must plug into to be resumable.fixcm=False) with FixAtoms: plain
reference/surrogate modes, and adaptive MD in both ensembles — with a
fixed base model via TOML/CLI, or with guarded online updates through
the Python GuardedUpdater interface (EnergeticRunner(on_label=...);
re-anchoring supported, each segment recorded independently). Online
updates are not expressible in configuration files: no TOML key installs
an update callback. Variable-cell dynamics and other constraint types
are unsupported. The default force budget measures the free coordinates
(active_dofs_max_atom); all_atoms_max_atom is an explicit
alternative. Checkpoints retain two generations.[policy.calibration_pacing] is
enabled, adaptive runs defer the probe investment of recalibrations
that keep failing to produce an accept: those steps drive
reference-direct, the wait retries on a bounded backoff, and every
decision is recorded and resumable. This reduces repeated ineffective
calibration effort inside the existing accuracy-management protocol —
it does not relax the gate, the budgets or the independent checks, and
it gives no new error guarantee. Scope: fixed base model, fixed cell,
the default single-direction NVE/NVT paths; not composable with online
updates or explicit direction callbacks. Try it:
examples/calibration_pacing (analytic, core-only).relax → NVT → NVE chains run through
run_serial_recipe with per-stage run identities and deduped
stop/continue (examples/periodic_lj offline; examples/si_bulk_qe_mace
for QE + MACE). Stage handoff carries the authoritative completed state:
positions, cell/PBC, masses, FixAtoms, initial charges/magmoms, and
complete momenta — initialized once at the first MD stage, preserved
afterwards, never rethermalized.examples/guarded_nvt.py) demonstrates guarded online updates on a toy
model; MACE is used as a fixed model in the examples (its online
fine-tuning interface is not an accepted feature of this release).free_energy reference can be paired with a MACE energy
surrogate when both declare force-energy consistency and conservative
forces. Cross-kind combinations with an undeclared requirement are
rejected; unknown is never evidence of consistency. Reference identity
includes smearing type/width, XC and pseudopotential content.pyramid inspect
to count anchors, probes, checks, retries and cache hits; a surrogate
acceptance rate is not a reference-calculation saving.on_label callback can use new labels to
adapt the potential. A model change or a detected violation requires a fresh
anchor and response before accepting further fast forces.Directional probes supply an empirical forecast. Independent accepted-force checks provide a separate statistical assessment of violations under their sampling protocol. The method guide explains these quantities, their units and the conditions for interpreting them.
examples/ — the demos above, plus direct Python-API scripts:
energetic_loop.py runs offline on analytic backends, guarded_nvt.py
demonstrates guarded online updates under NVT (fresh run, stop, resume),
and periodic_lj/run_recipe.py drives the serial relax → NVT → NVE
recipe; the others need the optional extras they name.src/pyraimd2/ — framework implementation; tests/ — numerical, interface
and integration checks.Run the offline core suite (NumPy + ASE only, no optional backends needed):
pytest tests/unit tests/test_smoke.py -q
Backend integration tests marked slow require the corresponding optional
software and model files; they are deselected by default and never count as
passing when their dependency is missing. Configure production executables,
model locations and compute resources in your own run setup.
If you use Pyramid in your research, please cite the underlying method paper:
Pyramid is released under the MIT License.