Execution Model#

BATTER’s orchestration layer is composed of three lightweight building blocks: pipelines, runtime artifact stores, and system descriptors. Understanding how they interact helps when customising workflows or writing new handlers.

Pipelines#

batter.pipeline.pipeline.Pipeline stores an acyclic list of Step objects plus useful introspection helpers:

  • Pipeline.describe() returns a serialisable summary with step names, dependencies, and payload types.

  • Pipeline.adjacency() exposes the DAG in adjacency-list form, which is handy when rendering graphs or verifying dependency structure in tests.

  • Pipeline.dependencies() lets you query the prerequisites for any step, mirroring the Step.requires metadata.

Because Step instances are immutable dataclasses, call Step.replace() to clone a step with a modified payload.

Runtime Artifacts#

batter.runtime.portable.ArtifactStore manages portable outputs (restarts, analysis tables, etc.) and keeps a manifest in JSON form for reproducibility. Use ArtifactStore.list_artifacts() to inspect what has been stored, filter by name prefix (for example prefix="fe/"), or limit results to files versus directories. The manifest is shared across rebased views so you can relocate a run’s artifacts to another filesystem while preserving metadata.

System Descriptors#

batter.systems.core.SimSystem encapsulates the layout of a simulation on disk. The helper methods introduced here simplify everyday tasks:

  • SimSystem.path() joins root with arbitrary path fragments, reducing boilerplate when locating artifacts.

  • SimSystem.with_meta() merges updates into the attached SystemMeta object, keeping provenance and ligand-specific metadata in sync without mutating the original descriptor.

When building or transforming systems, prefer SimSystem.with_artifacts() for structural changes (new topology/coordinate paths) and SimSystem.with_meta() for contextual tweaks (ligand IDs, run labels, etc.).

Phase ordering and sentinels#

Orchestration follows a fixed phase order: system_prep → param_ligands → prepare_equil → equil → equil_analysis → prepare_fe → fe → analysis. MD-only runs stop after equilibration analysis. Handlers drop FINISHED/FAILED sentinels in window/component folders; the job manager (local or SLURM) checks these to decide whether to continue, retry, or mark ligands as failed. RunConfig.run.on_failure controls behaviour: prune skips remaining phases for failed ligands, retry clears FAILED once and reruns, and raise aborts the whole run. Interrupted runs can resume because submit helpers and run-local*.bash honor the sentinels and the total_steps markers in mdin templates; each invocation runs a single segment and updates rolling restarts. For a manual reset before rerunning, use run.clean_failures or batter run --clean-failures to remove FAILED sentinels, job_attempt.txt retry counters, and progress caches.