From 041bdf3dd26f45d53d55ceb3dab7b7556f0d45c2 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Wed, 28 Jan 2026 13:41:04 +0000 Subject: [PATCH 1/6] Log restarts when running replica exchange. --- src/somd2/runner/_repex.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/somd2/runner/_repex.py b/src/somd2/runner/_repex.py index e6bd4f5..98ef0dc 100644 --- a/src/somd2/runner/_repex.py +++ b/src/somd2/runner/_repex.py @@ -721,11 +721,17 @@ def __init__(self, system, config): output_directory=self._config.output_directory, ) else: + _logger.debug("Restarting from file") + # Check to see if the simulation is already complete. time = self._system[0].time() if time > self._config.runtime - self._config.timestep: - _logger.success(f"Simulation already complete. Exiting.") + _logger.success("Simulation already complete. Exiting.") _sys.exit(0) + else: + _logger.info( + f"Restarting at time {time}, time remaining = {self._config.runtime - time}" + ) try: with open(self._repex_state, "rb") as f: From de0949823eb7a353c76d4b62f484748f55f364b2 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Wed, 28 Jan 2026 13:41:53 +0000 Subject: [PATCH 2/6] Fix variable name. --- src/somd2/runner/_repex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/somd2/runner/_repex.py b/src/somd2/runner/_repex.py index 98ef0dc..e4d84d2 100644 --- a/src/somd2/runner/_repex.py +++ b/src/somd2/runner/_repex.py @@ -1041,7 +1041,7 @@ def run(self): repeat(num_blocks + int(rem > 0)), repeat(i == cycles - 1), ): - if not result: + if error: _logger.error( f"Checkpoint failed for {_lam_sym} = " f"{self._lambda_values[index]:.5f}: {error}" From d2b36a048d5e94f2d1790da388070a2eaa0338a2 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Wed, 28 Jan 2026 13:42:23 +0000 Subject: [PATCH 3/6] Delete trajectory frames before streaming to file. --- src/somd2/runner/_base.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/somd2/runner/_base.py b/src/somd2/runner/_base.py index 9e0eaf7..c401fc9 100644 --- a/src/somd2/runner/_base.py +++ b/src/somd2/runner/_base.py @@ -1762,6 +1762,9 @@ def _checkpoint( ) system.set_property("lambda", lam) + # Delete all frames from the system. + system.delete_all_frames() + # Stream the final system to file. _sr.stream.save(system, self._filenames[index]["checkpoint"]) @@ -1796,6 +1799,9 @@ def _checkpoint( ) system.set_property("lambda", lam) + # Delete all frames from the system. + system.delete_all_frames() + # Stream the checkpoint to file. _sr.stream.save(system, self._filenames[index]["checkpoint"]) From d9efdaebeb7e441998f8d1b2b8a24e3c49580a23 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Wed, 28 Jan 2026 13:46:06 +0000 Subject: [PATCH 4/6] Delete existing trajectory frames prior to simulation. --- src/somd2/runner/_repex.py | 3 +++ src/somd2/runner/_runner.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/somd2/runner/_repex.py b/src/somd2/runner/_repex.py index e4d84d2..ecd7907 100644 --- a/src/somd2/runner/_repex.py +++ b/src/somd2/runner/_repex.py @@ -247,6 +247,9 @@ def _create_dynamics( else: mols = system + # Delete an existing trajectory frames. + mols.delete_all_frames() + # Overload the device and lambda value. dynamics_kwargs["device"] = device dynamics_kwargs["lambda_value"] = lam diff --git a/src/somd2/runner/_runner.py b/src/somd2/runner/_runner.py index b763225..89b3f75 100644 --- a/src/somd2/runner/_runner.py +++ b/src/somd2/runner/_runner.py @@ -292,6 +292,9 @@ def run_window(self, index): else: system = self._system.clone() + # Delete an existing trajectory frames. + system.delete_all_frames() + # GPU platform. if self._is_gpu: # Get a GPU from the pool. From 9bda42219feb32ce571adbaa43712de0a273f242 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Wed, 28 Jan 2026 14:10:09 +0000 Subject: [PATCH 5/6] Only modify checkpoint frequency in local scope. --- src/somd2/runner/_repex.py | 16 ++++++++-------- src/somd2/runner/_runner.py | 15 +++++++++------ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/somd2/runner/_repex.py b/src/somd2/runner/_repex.py index ecd7907..34303f1 100644 --- a/src/somd2/runner/_repex.py +++ b/src/somd2/runner/_repex.py @@ -836,28 +836,28 @@ def run(self): else: cycles = int(ceil(cycles)) - if self._config.checkpoint_frequency.value() > 0.0: + # Store the current checkpoint frequency. + checkpoint_frequency = self._config.checkpoint_frequency + + if checkpoint_frequency.value() > 0.0: # Calculate the number of blocks and the remainder time. - frac = (self._config.runtime / self._config.checkpoint_frequency).value() + frac = (self._config.runtime / checkpoint_frequency).value() # Handle the case where the runtime is less than the checkpoint frequency. if frac < 1.0: frac = 1.0 - self._config.checkpoint_frequency = str(self._config.runtime) + checkpoint_frequency = self._config.runtime num_blocks = int(frac) rem = round(frac - num_blocks, 12) # Work out the number of repex cycles per block. - frac = ( - self._config.checkpoint_frequency.value() - / self._config.energy_frequency.value() - ) + frac = (checkpoint_frequency / self._config.energy_frequency).value() # Handle the case where the checkpoint frequency is less than the energy frequency. if frac < 1.0: frac = 1.0 - self._config.checkpoint_frequency = str(self._config.energy_frequency) + checkpoint_frequency = self._config.energy_frequency # Store the number of repex cycles per block. cycles_per_checkpoint = int(frac) diff --git a/src/somd2/runner/_runner.py b/src/somd2/runner/_runner.py index 89b3f75..8b56e97 100644 --- a/src/somd2/runner/_runner.py +++ b/src/somd2/runner/_runner.py @@ -647,22 +647,25 @@ def generate_lam_vals(lambda_base, increment=0.001): else: num_energy_neighbours = None + # Store the current checkpoint frequency. + checkpoint_frequency = self._config.checkpoint_frequency + # Store the checkpoint time in nanoseconds. - checkpoint_interval = self._config.checkpoint_frequency.to("ns") + checkpoint_interval = checkpoint_frequency.to("ns") # Store the start time. start = _timer() # Run the simulation, checkpointing in blocks. - if self._config.checkpoint_frequency.value() > 0.0: + if checkpoint_frequency.value() > 0.0: # Calculate the number of blocks and the remainder time. - frac = (time / self._config.checkpoint_frequency).value() + frac = (time / checkpoint_frequency).value() # Handle the case where the runtime is less than the checkpoint frequency. if frac < 1.0: frac = 1.0 - self._config.checkpoint_frequency = f"{time} ps" + checkpoint_frequency = _sr.u(f"{time} ps") num_blocks = int(frac) rem = round(frac - num_blocks, 12) @@ -687,7 +690,7 @@ def generate_lam_vals(lambda_base, increment=0.001): next_frame = self._config.frame_frequency # Loop until we reach the runtime. - while runtime <= self._config.checkpoint_frequency: + while runtime <= checkpoint_frequency: # Run the dynamics in blocks of the GCMC frequency. dynamics.run( self._config.gcmc_frequency, @@ -728,7 +731,7 @@ def generate_lam_vals(lambda_base, increment=0.001): else: dynamics.run( - self._config.checkpoint_frequency, + checkpoint_frequency, energy_frequency=self._config.energy_frequency, frame_frequency=self._config.frame_frequency, lambda_windows=lambda_array, From 66354b8a0b89cd1725b1e4fc85dbec8c1b1e3d65 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Wed, 28 Jan 2026 14:17:15 +0000 Subject: [PATCH 6/6] Update checkpoint interval if frequency is adjusted. --- src/somd2/runner/_runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/somd2/runner/_runner.py b/src/somd2/runner/_runner.py index 8b56e97..12a637c 100644 --- a/src/somd2/runner/_runner.py +++ b/src/somd2/runner/_runner.py @@ -666,6 +666,7 @@ def generate_lam_vals(lambda_base, increment=0.001): if frac < 1.0: frac = 1.0 checkpoint_frequency = _sr.u(f"{time} ps") + checkpoint_interval = checkpoint_frequency.to("ns") num_blocks = int(frac) rem = round(frac - num_blocks, 12)