Skip to content

Restart mechanism with a wall-time budget - #87

Open
cyfraysse wants to merge 9 commits into
TheDisorderedOrganization:mainfrom
cyfraysse:native-restart
Open

cyfraysse wants to merge 9 commits into
TheDisorderedOrganization:mainfrom
cyfraysse:native-restart

Conversation

@cyfraysse

@cyfraysse cyfraysse commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

When a simulation hits a wall-time budget (< CPU time), it stops cleanly, saves checkpoints, and can be resubmitted by a bash script to continue from these exact checkpoints.

Description :

1- Add a restart field in the params.toml (in seconds) that sets the wall-time budget. If the simulation has not finished by this time, run! returns :need_restart and Julia exits 1. Else Julia exits 0.

2- When starting, Julia checks if checkpoints exist. If yes then we are in a restart case (load checkpoints). Else, fresh start.

3- On restart positions are loaded from lastframe.fmt (fmt = xyz,exyz,lmp) and load_chains takes care that checkpoints are loaded in numeric order so chain N resumes into index N.

4- The restart time t is parsed depending on the checkpoints format and is used to set t_start on a restart so schedulers are conserved.

5- On restart ComputeRotation reloads R_ref, ɸ_acc and ɸ from lastphiframe.dat to keep the MSAD continuity.

6- StoreTrajectories and StorePhiTrajectories open files in append mode instead of write mode on a restart.

7- load_chains gets a fold keyword true by default and false if restart=true so positions are not folded back into the box on a restart. This way MSD is conserved through a restart.

8- After run! the chain's RNG state is serialised to chains/N/rng_state.jls. On restart it is deserialised back into simulation.algorithm[1].rngs[c]. Requires adding Serialization to Project.toml.

I join the results of a validation test: the blue curve is a simulation restarted every 10 minutes without saving RNG sequence, the orange curve is a single uninterrupted run and the green curve is a simulation restarted every 10 minutes and saving the RNG sequence.
Keeping the RNG sequence prevent bias introduced by restarting from the same seed at each checkpoints (blue curve large time divergence vs green curve statistically equivalent to the orange curve : zscore < 1). However, due to round approximation when saving a checkpoint we are still losing the bit for bit reproducibility.

restart_vs_norestart

cyfraysse added 7 commits July 6, 2026 17:12
read_header now returns the frame's timestep for every format (XYZ step:,
EXYZ Time=, LAMMPS ITEM: TIMESTEP), defaulting to 0 when the token is absent
(a plain input config is implicitly t=0). load_configuration surfaces it as
config_dict[:t]. Also fix EXYZ Properties parsing: greedy (.*) swallowed the
trailing 'Time=' token, so switch to (\S+).
StorePhiTrajectories opens its files in append mode when simulation.t_start > 0,
and no longer re-fires store_first on restart (which would duplicate the frame
at t_start), matching the convention used by Arianna's stores.
Route the TOML 'restart' key to run\!(; wall_time) (seconds budget; Inf = uncapped),
and detect t_start from the StoreLastFrames checkpoint: restart_format reads the
configured fmt, and t_start is read from chains/1/lastframe<ext>'s :t when it
exists. Detection is gated on a finite wall_time so non-chunked runs always start
fresh and ignore stale output.
init_path may now be a Vector of file paths, loaded in the given order (in
addition to a single file or a directory). This lets the caller control chain
order explicitly — needed on restart so chain c resumes into index c rather
than relying on walkdir's ordering.
On restart, build the per-chain lastframe list in numeric order
(sort(readdir(chains); by=Int)) and load it instead of config, so every chain
resumes from its own checkpoint. Also translate run\!'s status to a process exit
code (:need_restart -> 1) so a bash loop can resubmit.
Add read_phi_frame (+ read_block / row builders) to parse lastphiframe.dat, and
branch ComputeRotation.initialise on simulation.t_start > 0: reload R_ref, Φ_acc
and system.Φ per chain from chains/c/lastphiframe.dat instead of fresh-starting,
so the accumulated rotation is continuous across a restart. Also rename the
theta_T kwarg to θ_T (constructor + call site) consistently.

Verified end-to-end: a molecular job stopped at t=133 and resumed at t_start=133
with Φ continuous across the seam (mol 1 ‖Φ‖ 0.162 -> 0.165, not reset to 0).
@cyfraysse
cyfraysse requested a review from a team as a code owner September 22, 2026 10:58

@V-Francois V-Francois left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff!

The description mentions a lack of bit by bit reproducibility, but the rng states are written/read from json. I guess you added this after. Can you update the description and graphs to represent this?

Also, some tests fail.

Comment thread src/ParticlesMC.jl Outdated

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants