diff --git a/CHANGELOG.md b/CHANGELOG.md index 648817d..cbb8405 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,9 +19,11 @@ Changelog * Skip minimisation on restart [#191](https://github.com/OpenBioSim/somd2/pull/191). * Pre-equilibrate the water with GCMC moves before minimising in the regular `Runner`, making it consistent with the `RepexRunner`, which already did so to stop the geometry relaxing into a dry pocket [#191](https://github.com/OpenBioSim/somd2/pull/191). * Add a `precision` option for GPU platforms, defaulting to `mixed` [#191](https://github.com/OpenBioSim/somd2/pull/191). -* Add support for generating Morse restraints for ring-breaking perturbations. -* Remove the unused `kappa` lever equations from the ring-breaking/making lambda schedules. -* Account for off-site charges (virtual sites) when computing the charge difference between the end states. They are held as a molecule property rather than on the atoms, so a charge-preserving perturbation could appear to change charge and be given spurious alchemical ions. +* Add support for generating Morse restraints for ring-breaking perturbations [#194](https://github.com/OpenBioSim/somd2/pull/194). +* Remove the unused `kappa` lever equations from the ring-breaking/making lambda schedules [#195](https://github.com/OpenBioSim/somd2/pull/195). +* Accept stream file paths for the `restraints` and `lambda_schedule` configuration options, so they can be set from the command line [#198](https://github.com/OpenBioSim/somd2/pull/198). +* Account for off-site charges (virtual sites) when computing the charge difference between the end states. They are held as a molecule property rather than on the atoms, so a charge-preserving perturbation could appear to change charge and be given spurious alchemical ions [#200](https://github.com/OpenBioSim/somd2/pull/200). +* Handle `num_lambda=1`, which previously raised a `ZeroDivisionError` when generating the lambda values. The `RepexRunner` now rejects a single lambda window, since there is nothing to exchange with and the regular `Runner` is faster [#203](https://github.com/OpenBioSim/somd2/pull/203). [2026.1.0](https://github.com/openbiosim/somd2/compare/2025.1.0...2026.1.0) - Jun 2026 -------------------------------------------------------------------------------------- diff --git a/src/somd2/runner/_base.py b/src/somd2/runner/_base.py index 809e189..1d28609 100644 --- a/src/somd2/runner/_base.py +++ b/src/somd2/runner/_base.py @@ -466,6 +466,8 @@ def __init__(self, system, config): # Set the lambda values. if self._config.lambda_values: self._lambda_values = self._config.lambda_values + elif self._config.num_lambda == 1: + self._lambda_values = [0.0] else: self._lambda_values = [ round(i / (self._config.num_lambda - 1), 5) diff --git a/src/somd2/runner/_repex.py b/src/somd2/runner/_repex.py index fe6c4a6..f6aa553 100644 --- a/src/somd2/runner/_repex.py +++ b/src/somd2/runner/_repex.py @@ -1233,6 +1233,16 @@ def __init__(self, system, config): # fewer slots than replicas, each slot is re-used to propagate several # replicas per cycle, changing its lambda value as it goes. self._num_replicas = len(self._lambda_values) + + # There is nothing to exchange with a single replica. + if self._num_replicas < 2: + msg = ( + "Replica exchange requires at least two " + f"{_lam_sym} values. Please use the Runner class instead." + ) + _logger.error(msg) + raise ValueError(msg) + self._set_num_slots() # Auto-generate a Boresch restraint for ABFE runs with no user-supplied @@ -3068,7 +3078,7 @@ def _save_transition_matrix(self): swaps[i_state, j_state] + swaps[j_state, i_state] ) / denom else: - t[i_state, i_state] = 1.0 + t_ij[i_state, i_state] = 1.0 # Backup the existing transition matrix, if it exists. if self._repex_matrix.exists():