Resuming long synthesis runs¶
A production continuous synthesis run synthesizes a full
protein one residue at a time, each as three MD sub-stages, at production step counts
(~10⁵–10⁶ steps/stage). A full chain is therefore hours to days of wall time — longer
than a typical scheduler slot, and exposed to node failures and pre-emption. CSP runs
are resumable: re-invoking topo-csp on an interrupted output directory continues from
the last completed residue instead of restarting from L0.
This page covers operating a long run: how resume works, the on-disk artifacts, the config knob, and an HPC requeue pattern. For the physics and the full option reference see Synthesis in coarse-grained ribosome model and Synthesis control options.
Note
Resume works for both synthesis runners: topo-csp (explicit ribosome, three
sub-stages per residue) and topo-cylinder (analytic tunnel, one MD segment per residue).
The resume knob, progress.log, and the up-front cost report are identical; the only
differences are internal — the cylinder’s dwell_times.dat carries one step count per
residue (no #PTC header, since its tunnel geometry is cheap and deterministic) and its
per-residue finals live in a flat L_<L>/traj_final.pdb layout. Everything below applies
to both; examples use topo-csp unless noted.
TL;DR¶
# csp.ini — resume is on by default (nothing to add)
resume = auto # auto (default) | yes | no — continue an interrupted synthesis
restart = no # no (default) | yes — continue the ejection MD from its checkpoint
topo-csp -f csp.ini # launch; interrupted at any point...
topo-csp -f csp.ini # ...re-run the SAME command -> continues where it left off
topo-csp -f csp.ini --fresh # ignore any prior run and start over
A launched run prints its exact total planned MD-step count before the first MD step, so you can size a scheduler wall-clock request:
[schedule] 306 residues, 51,272,940 planned MD steps (~769.1 ns simulated at dt=0.015 ps; ...)
How it works¶
The insight is that almost nothing crosses a residue boundary. Reading the driver
loop for L in range(L0, L_max+1), only two pieces of state carry from one residue to the
next, and both are already on disk:
State |
Recovery on resume |
|---|---|
the previous residue’s final coordinates (the seed for residue |
reloaded from |
the per-residue kinetic schedule |
re-read from the persisted schedule (no RNG redraw) |
Everything else the loop consumes (ribosome load, anchors, native contacts + STRIDE, the codon kinetic lists) is cheap and recomputed from the config at startup. The one expensive-but-deterministic quantity — the optimized PTC restraint geometry — is persisted at first launch and re-read on resume (see below), never re-solved.
So there is no heavyweight simulation checkpoint. The resume unit is the residue, and all resume needs to record is how far the run got.
The two on-disk artifacts¶
At the output root, alongside the per-residue L_<L>/ directories:
dwell_times.dat — the immutable plan
: The full per-residue 3-stage schedule, drawn once from the seeded generator before
the main loop, plus a machine-readable #PTC header carrying the restraint geometry
(the A-/P-site target points and the tunnel-wall plane) at full float precision. On
resume this file is re-read, never rewritten — the schedule is not redrawn and the
PTC geometry is not re-solved, so both are pinned identical to the residues already on
disk. It is written once and is the source of truth the loop reads back.
progress.log — the mutable status
: A human-readable, append-only record of how far the run got:
# csp progress log -- schema 1
L_001 RUNNING
L_001 DONE
...
L_041 DONE
L_042 RUNNING <- crash here: L_042 is the partial unit dropped on resume
A residue is marked RUNNING when it starts and DONE only after all three stages
finish. The DONE line is the commit point: a short append is effectively atomic on
POSIX, so every crash is recoverable — die before DONE and that unit is RUNNING
(dropped and redone); die after DONE and resume picks up at the next residue. The
post-synthesis ejection phase appears as its own unit.
On resume, the driver takes the last status per unit, drops the (at most one) RUNNING
unit and its directory, reloads the last DONE residue’s final structure as the seed,
and continues from max(DONE) + 1. Redone work is bounded to a single residue (≤ 3
stages) — negligible against a run measured in hours to days.
Tip
Both files are plain text — cat progress.log to see exactly how far a run got, or
tail -f it to watch a live run advance.
The resume knob¶
Set it in csp.ini, or override on the CLI.
Value |
Behavior |
|---|---|
|
Resume iff a |
|
Require a resumable run — error if no |
|
Always start fresh (the pre-resume behavior). |
topo-csp -f csp.ini --no-resume # or --fresh; forces resume = no for this invocation
Because auto is the default, re-running the same command on an existing output
directory now resumes rather than silently overwriting it — the intended behavior for a
requeued job.
What resume guarantees (and what it does not)¶
Guaranteed — the kinetic schedule is identical to an uninterrupted run. The schedule
is materialized once and re-read, so dwell_times.dat is byte-identical across the
interruption, and the resumed conformation continues from the last completed residue’s
final structure (0.001 nm PDB precision, far below the model’s thermal noise).
Not guaranteed — bit-reproducible MD micro-trajectories. The per-stage dynamics are stochastic and not bit-reproducible across a process boundary: the Langevin thermostat and velocity initialization draw from OpenMM’s own unseeded platform RNG (and stage 1 re-seeds + re-minimizes every residue regardless). The intended and achievable guarantee is the schedule + conformational continuity, not a bit-exact trajectory.
Two consequences worth knowing:
No config fingerprint. Because the schedule is loaded, not redrawn, a changed
random_seedor retuned kinetic knob on resume cannot corrupt the tail — the RNG is never consulted again. (A genuinely different force config on resume is a self-inflicted footgun the tool does not police; keep the config stable across a requeue.)Extending the synthesis is a fresh run. The schedule is fixed at first launch to cover exactly
L0..L_max. Resuming with a largerL_maxis rejected with an actionable error (persisted schedule covers L=1..10 but this run asks for L=1..20 … Extending a run is a fresh run) — it would need draws past the materialized schedule. Decide the final length before launching. (Extending the post-synthesis ejection free run is the opposite — a supported, cheap restart; see Resume vs. restart.)
Warning
Presence guard. progress.log records intent; the disk records reality. Before
resuming, CSP verifies that every length L0..last_done still has its
traj_final.pdb on disk. If one is missing (a directory deleted, or lost to a scratch
purge), the resume aborts naming the offending length rather than silently
continuing from the last DONE and leaving a permanent hole in the assembled trajectory.
Re-run fresh, or restore the missing length.
Note
Concurrent invocations. Two topo-csp processes on the same outdir would race
progress.log; don’t do that. Resume assumes one writer at a time.
Resume vs. restart¶
Two different mechanisms continue a stopped run, at two different levels — and they are easy to confuse because the ejection-extend workflow uses both. Resume (everything above) is the driver-level machinery that picks a multi-residue synthesis back up. Restart is the OpenMM-checkpoint machinery that continues a single MD run step-for-step.
Resume ( |
Restart ( |
|
|---|---|---|
Level |
CSP driver ( |
OpenMM engine ( |
Unit |
one residue (or a whole post-synthesis phase) |
MD steps |
State carried |
positions ( |
positions + velocities + step count ( |
In-flight work |
the interrupted unit is dropped and redone fresh |
the run continues exactly, velocity-continuous |
Trigger |
re-run the command on an existing |
set |
Default |
|
|
Used for |
surviving a crash/pre-emption of the hours-to-days synthesis |
extending the ejection free run so the chain finishes leaving the ribosome |
When to use which:
Resume — you don’t really choose it: leave
resume = auto, and re-running a requeued or interrupted job continues the synthesis. It is residue-granular and reseeds each stage fromtraj_final.pdb, so it needs no OpenMM checkpoint.Restart — reach for it when the finished chain has not fully left the ribosome by the end of the ejection phase. It is opt-in: set
restart = yes(defaultno), raiseejection_steps, and re-run on the existingoutdir(resume = auto). The ejection phase then reloads itsejection/traj.chk(positions + velocities + step count) and appends only the additional steps to reach the new cumulativeejection_steps— a true continuation of the same free-diffusion trajectory, not a fresh, re-thermalized run. If the checkpoint has already reachedejection_steps, the phase prints “already met” and steps nothing. With the defaultrestart = no, a completed ejection is instead skipped on resume (like thestallphase) — raisingejection_stepsdoes not re-run or extend it; userestart = yes(orresume = noto redo the whole synthesis). Inspectejection/traj_final.pdbyourself and top it up until the chain is clear; the nascent-only final is then a ready ribosome-free input for a post-translationtopo-mdrun. See Synthesis in coarse-grained ribosome model.
Why only the ejection phase carries a checkpoint: each elongation stage is a short segment
reseeded from the previous traj_final.pdb, so a per-stage .chk would be dead weight. The
ejection free run is the one phase you may want to continue step-for-step — to add diffusion
time without a velocity discontinuity — so it, and only it, writes traj.chk.
Note
The checkpoint-continue applies to the extend workflow (restart = yes), where the prior
ejection reached DONE. A crash in the middle of an ejection run leaves it RUNNING, so
resume’s drop-the-in-flight-unit rule removes the ejection/ directory (checkpoint included)
and re-ejects fresh — consistent with the residue-granular policy. So: with restart = yes,
ejection/traj.chk extends a completed ejection; it does not rescue a half-finished
one. With the default restart = no, a completed ejection is skipped on resume (like
stall); only a fresh run or a never-completed ejection runs.
Worked example¶
A fast, self-contained demonstration (small step clamp, CPU) — synthesize L = 1..20,
interrupt after residue 10, and resume to completion:
# 1. Launch (L_max = 20). Kill it (Ctrl-C / scheduler pre-emption) after ~residue 10.
topo-csp -f csp.ini
# progress.log now ends: L_010 DONE / L_011 RUNNING (residue 11 was in flight)
# 2. Re-run the SAME command — resume is automatic.
topo-csp -f csp.ini
The resume run opens by reporting where it picks up:
[resume] 10 length(s) complete on disk; dropped in-flight ['L_011']; continuing from L=11.
[schedule] 20 residues, 1,189 planned MD steps (~0.0 ns simulated at dt=0.015 ps; ...)
L= 11 GGU dwell 0.02757 s steps 20/ 20/ 20
...
L= 20 CUG dwell 0.05463 s steps 20/ 20/ 20
Done. Synthesized 1 -> 20.
The partial L_011/ directory is dropped and cleanly rebuilt from its persisted schedule
row, dwell_times.dat is unchanged (re-read, not rewritten), and the run reaches L_max.
HPC requeue pattern¶
Because a re-run resumes automatically, a self-requeuing SLURM job survives wall-clock
limits with no bookkeeping — the same topo-csp line runs each slot and advances the run:
#!/bin/bash
#SBATCH --job-name=csp_synth
#SBATCH --time=48:00:00
#SBATCH --signal=B:USR1@120 # warn the script 120 s before the wall-clock kill
#SBATCH --gres=gpu:1
# Re-queue this same script if we hit the time limit, then continue running.
trap 'scontrol requeue "$SLURM_JOB_ID"' USR1
# resume = auto (default): first slot starts fresh, every requeue continues.
topo-csp -f csp.ini &
wait
Each slot: the schedule + PTC geometry are read back from dwell_times.dat, the last
completed residue’s final is reloaded, and synthesis continues. Point outdir at
persistent (not node-local) storage so the partial output survives between slots.
See also¶
Visualizing the synthesis process — once the run finishes, stitch the segments into a movie (cylinder tunnel or CG ribosome; interactive or headless).
Synthesis in coarse-grained ribosome model — the CSP runner, physics, and full output layout.
Synthesis control options — the canonical per-key
csp.inireference (incl.resume).topo.csp.resume— the module implementing the schedule/progress persistence and the resume actions.