Output files¶
This page lists what a run writes, file by file and column by column. The how-to is Output, restart and resume.
fm.Output¶
fm.Output(directory, trajectory_every=20, thermo_every=20, restart_every=10_000)
| Parameter | Values | Default | What it does |
|---|---|---|---|
directory |
path (str or os.PathLike) |
required | where the run writes; kept as given, as a string |
trajectory_every |
int ≥ 1 or None |
20 |
steps between trajectory frames; None writes no trajectory |
thermo_every |
int ≥ 1 | 20 |
steps between thermo rows; thermo rows are always written |
restart_every |
int ≥ 1 or None |
10000 |
steps between restart points; None writes no restart files on its own |
fm.md(output=...) takes a directory or an fm.Output. A directory gets
these default intervals. Without output, fm.md writes to
./<structure stem>.fastmace/, or ./fastmace-run/ for an in-memory
Atoms. fm.Simulation(output=None) writes nothing.
Intervals count the simulation's steps from 0, across run() calls and
resumes. A thermo row and, with trajectory_every, a frame are written at
step 0 when the run starts, then at every step that is a multiple of the
interval. A restart point is written at every multiple of restart_every.
The output directory¶
| File | Written by | Content |
|---|---|---|
thermo.<n>.csv |
every MD run | thermo rows, one chunk per file |
trajectory.<n>.traj |
every MD run | ASE trajectory frames, one chunk per file |
restart.npz |
restart points | the complete state at the last restart point |
simulation.json |
restart points | the inputs a resume needs |
metadata.json |
setup, each run(), restart points, stops |
plan, gate, report, counters, provenance |
.fastmace-handoff/ |
a plan that runs in a child process | the hand-off between parent and child; deleted on a clean close |
protocol.json |
protocol runs | stages, pieces, status |
relaxation.log, relaxed.extxyz |
protocol runs with [relax] |
the initial relaxation |
quench/, quench-NAME/ |
protocol runs with [quench], fastmace quench |
the quenched frames |
A new run refuses a directory that already holds output chunks
(FileExistsError): resume the run or use a new directory.
Chunks¶
The thermo table and the trajectory are written in chunks, n = 0, 1, ....
Every restart point closes the current pair of chunk files and opens the
next, so a chunk boundary lies exactly at each restart point. Each chunk is
complete on its own: every thermo chunk starts with the header, and a chunk
without rows or frames still has both files.
from fastmace.io.output import read_frames, read_thermo
header, rows = read_thermo("run/") # every chunk, in order; rows as strings
frames = read_frames("run/") # a list of ase.Atoms
ase.io.read("run/trajectory.0.traj", index=":") # one chunk
Thermo table¶
thermo.<n>.csv is a CSV file with a header line. Energies are per atom.
| Column | Unit | Content |
|---|---|---|
step |
the MD step | |
time_ps |
ps | step × timestep_fs / 1000 |
phase |
heating, cooling or hold (the schedule segment), or constant without a schedule |
|
target_K |
K | the thermostat target at this step; nan for NVE |
temperature_K |
K | the kinetic temperature, 2 E_kin / (f k_B) |
potential_eV_atom |
eV/atom | potential energy |
kinetic_eV_atom |
eV/atom | kinetic energy |
total_eV_atom |
eV/atom | potential plus kinetic |
volume_A3_atom |
ų/atom | NPT runs only: the cell volume |
pressure_GPa |
GPa | NPT runs only: the instantaneous pressure, kinetic part included |
mc_<move>_attempted, mc_<move>_accepted |
runs with MC only: cumulative counts per move type, as of the last MC block |
The degrees of freedom f are 3N − 3 for Langevin NVT with the centre of
mass fixed under the "mass_weighted" projection, 3(N − n_fixed) with
FixAtoms, and otherwise the integrator's count (3N for ASE's projection,
NPT and fixcm off). Simulation.degrees_of_freedom gives the value of a
run. A non-finite value stops the run before the row is written.
The NPT columns appear for every integrator with ensemble NPT:
LangevinBAOAB, MTK, and Berendsen with a pressure.
Trajectory frames¶
trajectory.<n>.traj is an ASE trajectory. Each frame holds the step's
cell, positions and momenta, and a single-point calculator with the energy
and forces; variable-cell runs add the stress (Voigt, eV/ų). After an MC
swap or transmutation, a frame carries the step's species and masses.
Durable writes¶
restart.npz, simulation.json and metadata.json are written durably and
atomically: a temporary file next to the target is written, flushed and
fsynced, renamed over the target, and then the directory is fsynced. A
crash leaves the old file or the new one, never a short one. The directory
fsync is skipped on Windows and on file systems that refuse it.
Thermo rows are flushed after each row; frames are on disk once written. At a restart point, the output queue is drained, the closing chunks and the directory are fsynced, and only then is the restart file written. So a restart never counts rows or frames that are not on disk. Rows and frames after the last restart point are flushed but not fsynced.
Output is asynchronous: a step's values are copied to the host behind the step and written while the next step runs. The files are the same as with synchronous writing.
restart.npz¶
One .npz file (plain arrays and JSON text, no pickles), format version 4.
The writer makes the same bytes from the same state.
| Entry | Content |
|---|---|
step, engine |
the step and the writing engine ("fastmace") |
positions, momenta, velocities, cell, forces, energy |
the state at the step |
masses, species, charges |
the current composition, after any MC change |
cell_state, stress, p_eps, force_eps |
variable-cell runs: the barostat state |
rng_state, noise, noise_next |
the random generator's state and the batch drawn ahead with its cursor |
integrator_keys |
the integrator scheme's own state (NHC, MTK, CSVR) |
physical |
total charge, spin, PBC, constraints, fixed atoms |
integrator |
class, configuration and thermostat target |
protocol |
the schedule and its position |
plan, plan_revision |
the plan record, with the edge bucket and neighbour capacity |
identity, identity_digest |
the force-field identity |
output_chunk, output_rows, output_frames |
the last closed chunk, and the rows and frames in chunks 0 to it |
mc |
the attached move set: moves, cycle position, counters, stream seeds, displacement step sizes |
fastmace_restart |
the format version |
Every restart write is a canonical point: the pipeline is quiesced and the neighbour lists are rebuilt first, so a resumed engine is in the state of the uninterrupted one. Restart writes happen only at committed steps, never inside an MC block.
restart.npz is written:
- every
restart_everysteps; - by
sim.save_restart(directory)(the file name must berestart.npz); - at the end of each piece of a protocol run;
- when an NPT run stops because the cell diverged.
A run that ends between restart points, for example fm.md with steps not
a multiple of restart_every, has no restart at its last step. Call
sim.save_restart(...) on RunResult.simulation if you need one.
simulation.json¶
Written next to every restart: what the restart format does not hold.
| Key | Content |
|---|---|
simulation_record_version |
2 |
model |
label, path, head, sha256, trust, charge, spin_multiplicity |
force_field |
precision, species, rewrites, and dispersion (the D3 record) when there is one |
integrator |
class and fields of the fm.integrators record |
workload |
the fm.Workload fields |
output |
the fm.Output fields; directory is "." when the restart lies in the output directory, so the directory can be moved |
seed |
the seed |
allow_naive_cueq |
as given |
planner_options |
mode, allow_reference, the fallback, gate, runner, engine, neighbour, adaptation and calibration records |
structure |
initial numbers, masses, pbc |
plan_revision |
the active plan revision |
restart_points |
[{step, output_chunk, output_rows, output_frames}] |
mc |
the MC record |
reference_volume_A3 |
NPT only: the starting volume of the cell-divergence check |
Resume¶
sim = fm.Simulation.resume("run/", allow_plan_change=False, check="skip")
sim.run() # the rest of the schedule, or sim.run(steps=...)
Simulation.resume(directory) needs restart.npz and simulation.json in
directory. It:
- loads the model again from
simulation.json's file, checked against its SHA-256; - compares the force-field identity with the restart's. A different
identity raises
RestartMismatch; a different MACE or FastMACE version alone warns, and is recorded as a new plan revision and in the report; - plans again. A plan different from the recorded one needs
allow_plan_change=True, and makes a new revision. A resume never calibrates; - builds the engine at the restart's positions, cell and composition, then loads the state, edge bucket and neighbour capacity;
- checks the output: every chunk up to
output_chunkmust be present with the recorded numbers of rows and frames, and every later chunk must be deletable. Otherwise it raisesRestartMismatchbefore it touches anything; - deletes the later chunks (rows and frames written after the restart
point) and continues with chunk
output_chunk + 1. Nothing is rewritten.
check is as in fm.Simulation. The command-line resume,
fastmace run --resume RUN_DIR, is for protocol runs only (below).
metadata.json¶
Schema fastmace.metadata/1, minor version 1. A JSON object with these
top-level keys, in this order. It holds no NaN, no infinity and no raw
random states (generator states appear as SHA-256 hashes).
| Key | Content |
|---|---|
schema, schema_minor |
"fastmace.metadata/1", 1; a record without schema_minor is minor 0 |
created_utc |
ISO time of the write |
code |
version, git_commit, git_dirty |
checkpoint |
path, sha256, head, licence, label, trust |
model |
the model block |
force_field_identity |
the force-field identity and its digest |
reference_record |
the reference record, with at least id |
plan |
the active plan: revision, tier, reason, step, description (str(plan)), description_full (plan.describe(full=True)), backend, conv_fusion, rewrites, engine, neighbours, polar, integrator, decisions (key, choice, reason, code, rule), requested, auto_options_off, superset, workload, software, allowances, fallbacks_tried, predicted_memory_bytes, runner ("in-process" or "subprocess"), calibration, adaptation |
plan_revisions |
every revision, oldest first, the active one last: revision, tier, step, reason, description, description_full, runner, fallback |
precision |
force, integration (always "float64"), tf32 (PyTorch's process-wide matmul TF32 flag when the record was written: torch.backends.cuda.matmul.allow_tf32, also set by torch.set_float32_matmul_precision), tf32_requested (the plan's PrecisionConfig.tf32), float64_energy |
runtime |
file_locks ("soft" or "kernel"), file_lock_source, file_lock_switch_late, cuda_driver_cache (see Environment and cache) |
software |
versions (Python and packages), kernels, patches, triton, oeq_extension (the OEq build variables for a hybrid plan, else null), treatments |
hardware |
gpu, driver, compute_capability; null off CUDA |
random |
seed, generators (SHA-256 of each generator state), cursors |
integrator |
the integrator parameters |
schedule |
the schedule and its position |
gate |
status, reason, selfchecks, device, reduced_cell, steps, and the rest of the gate record; status "skipped" without check="gate" |
counters |
recaptures, neighbour_lists ({name: {rebuilds, build_time_s, skin_A}}), overflows_redone, mc ({move: {attempted, impossible, accepted}}), tier_switches, segments (the runtime monitor's last 1,000 segments), fallbacks (mid-run fallbacks), engine (the engine's info()) |
restart_points |
[{step, output_chunk, output_rows, output_frames}] |
timing |
setup_s ({stage: seconds}), setup_total_s, status, steps, loop_s |
report |
the run report: text, speed, measured_window, speed_window, setup_s, setup_total_s, licence, gate_status, move_energy_status, mc_energy_precision, reasons, warnings, mc |
force_field |
the engine's force field record: backend, dtype, rewrites applied with their decisions and self-check errors, energy_treatment, strain_path, and d3 with D3 |
subprocess |
null in-process; for a plan in a child: python, reason, directory, children, calls, persistent, seconds, failed, last |
timing.status is running, paused (after a run() call; also after
fm.md returns), complete (after sim.close()), non-finite,
cell-diverged or fallback-failed. The fastmace.ase integrators add an
ase block.
RunResult¶
fm.md returns a frozen RunResult:
| Field | Type | Content |
|---|---|---|
summary |
str |
the one-screen run report |
plan |
Plan |
the plan the run used |
gate |
gate record | the gate status and results |
simulation |
fm.Simulation |
the simulation, with its output flushed; it can run on (run) or write a restart (save_restart) |
metadata |
dict |
metadata.json as written at the end of the run |
output |
str |
the output directory |
Protocol runs¶
fastmace run with [relax], [quench] or --steps writes, besides the
files above:
| File | Content |
|---|---|
protocol.json |
the protocol record (below) |
relaxation.log |
the initial relaxation's optimizer log |
relaxed.extxyz |
the relaxed starting structure |
quench/ |
the quench (below) |
protocol.json keys: protocol_record_version (1), source, structure,
repeat, atoms, timestep_fs, relax and relaxation (settings and
summary), quench and quench_result, mc, min_mc_temperature_K,
md_steps (the run's MD steps for a run without a schedule, so that
--resume continues to it; null with a schedule), dispersion, pieces (each first_step, last_step, wall_s,
counters), counters (the sums of neighbour_rebuilds, d3_builds,
d3_rebuilds, d3_build_s), and status:
status |
Meaning | --resume |
|---|---|---|
relax |
the relaxation is running | no |
md |
the MD is running or paused | continues |
quench |
the quench is running | continues |
complete |
done | reports it is complete |
relaxation not converged |
the relaxation stopped | no |
cell diverged |
an NPT piece stopped; stop holds the reason |
no |
Quench directory¶
quench/ (or quench-NAME/ from fastmace quench --into NAME):
| File | Content |
|---|---|
settings.json |
the resolved settings, written first; an interrupted quench continues only with them |
captured.traj |
the picked MD frames |
quenched.traj |
their minima |
quench.csv |
one row per frame, written after each frame |
quench.json |
settings and summary, written last; a quench with it is complete |
quench.csv columns: phase, bin, frame, step, time_ps,
target_K, md_temperature_K, md_potential_eV_atom,
singlepoint_eV_atom, quenched_eV_atom, converged, optimizer_steps,
seconds, fmax_eV_A, volume_A3_atom.
fastmace relax¶
fastmace relax writes three files, by default <stem>.relaxed.extxyz,
<stem>.relaxed.json and <stem>.relaxed.log (the --output name with
.json and .log).
.json key |
Content |
|---|---|
structure, repeat, atoms |
the input |
model, head, precision, output |
the model and the output file |
optimizer |
the optimizer that ran |
fixed_cell |
false with --cell-filter |
fmax_target_eV_A, max_steps |
the limits |
converged, steps, seconds |
the result |
initial_eV_atom, energy_eV_atom |
energy per atom before and after |
fmax_eV_A |
the largest force at the end |
energies_eV, fmax_history_eV_A, neighbour_rebuilds, recaptures |
gpu-* optimizers only |
cell_A, volume_A3, stress_GPa, scalar_pressure_GPa |
with --cell-filter only |
A relaxation Simulation in Python writes no output files and no restart.