Skip to content

Commit c5ad571

Browse files
authored
Merge pull request #85 from OpenBioSim/fix_84
Fix issue #84
2 parents 5b36617 + 41625d8 commit c5ad571

2 files changed

Lines changed: 57 additions & 23 deletions

File tree

src/somd2/runner/_base.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,13 @@ def __init__(self, system, config):
581581

582582
# Make sure the selection is valid.
583583
if self._config.gcmc_selection is not None:
584+
if isinstance(self._system, list):
585+
mols = self._system[0]
586+
else:
587+
mols = self._system
584588
try:
585589
atoms = _sr.mol.selection_to_atoms(
586-
self._system, self._config.gcmc_selection
590+
mols, self._config.gcmc_selection
587591
)
588592
except:
589593
msg = "Invalid 'gcmc_selection' value."
@@ -700,6 +704,7 @@ def __init__(self, system, config):
700704
"shift_delta": str(self._config.shift_delta),
701705
"swap_end_states": self._config.swap_end_states,
702706
"tolerance": self._config.gcmc_tolerance,
707+
"restart": self._is_restart,
703708
"overwrite": self._config.overwrite,
704709
"no_logger": True,
705710
}
@@ -1127,8 +1132,14 @@ def _check_restart(self):
11271132
_logger.error(msg)
11281133
raise ValueError(msg)
11291134
else:
1135+
if self._config.gcmc:
1136+
num_gcmc_waters = self._config.gcmc_num_waters
1137+
else:
1138+
num_gcmc_waters = 0
11301139
# Check the system is the same as the reference system.
1131-
are_same, reason = self._systems_are_same(self._system, system)
1140+
are_same, reason = self._systems_are_same(
1141+
self._system, system, num_gcmc_waters=num_gcmc_waters
1142+
)
11321143
if not are_same:
11331144
raise ValueError(
11341145
f"Checkpoint file does not match system for the following reason: {reason}."
@@ -1169,12 +1180,14 @@ def _check_restart(self):
11691180
self._restart_ghost_waters = []
11701181
# List to store the current positions.
11711182
self._restart_positions = []
1172-
_logger.info("Removing existing ghost waters from GCMC checkpoint systems")
1183+
_logger.info(
1184+
"Determining existing ghost waters from GCMC checkpoint systems"
1185+
)
11731186
for i, system in enumerate(systems):
11741187
# Store the positions of all atoms.
11751188
self._restart_positions.append(_sr.io.get_coords_array(system))
11761189
if system is not None:
1177-
# Remove the ghost waters from the system.
1190+
# Find and log the current ghost waters.
11781191
try:
11791192
# Get the water molecule indices.
11801193
waters = system.molecules().find(system["water"].molecules())
@@ -1189,14 +1202,16 @@ def _check_restart(self):
11891202
idxs.append(waters.index(index))
11901203
self._restart_ghost_waters.append(idxs)
11911204

1192-
for mol in system["property is_ghost_water"].molecules():
1193-
_logger.debug(
1194-
f"Removing ghost water molecule {mol.number()} for {_lam_sym}={self._lambda_values[i]:.5f}"
1195-
)
1196-
system.remove(mol)
11971205
except:
11981206
pass
11991207

1208+
# Remove the additional GCMC waters from the end of the system.
1209+
for mol in system.molecules()[-self._config.gcmc_num_waters :]:
1210+
_logger.debug(
1211+
f"Removing GCMC water molecule {mol.number()} for {_lam_sym}={self._lambda_values[i]:.5f}"
1212+
)
1213+
system.remove(mol)
1214+
12001215
return True, systems
12011216

12021217
@staticmethod
@@ -1259,6 +1274,9 @@ def _compare_configs(config1, config2):
12591274

12601275
if (v1 == None and v2 == False) or (v2 == None and v1 == False):
12611276
continue
1277+
# The GCMC frequency will be automaticall set if None.
1278+
elif key == "gcmc_frequency" and v1 is None:
1279+
continue
12621280
elif v1 != v2:
12631281
raise ValueError(
12641282
f"{key} has changed since the last run. This is not "
@@ -1313,7 +1331,7 @@ def get_last_config(output_directory):
13131331
self._compare_configs(self._last_config, config)
13141332

13151333
@staticmethod
1316-
def _systems_are_same(system0, system1):
1334+
def _systems_are_same(system0, system1, num_gcmc_waters=0):
13171335
"""
13181336
Check for equivalence between a pair of sire systems.
13191337
@@ -1326,6 +1344,9 @@ def _systems_are_same(system0, system1):
13261344
system1: sire.system.System
13271345
The second system to be compared.
13281346
1347+
num_gcmc_waters: int
1348+
The number of GCMC ghost waters to ignore in the comparison.
1349+
13291350
Returns
13301351
-------
13311352
@@ -1337,18 +1358,25 @@ def _systems_are_same(system0, system1):
13371358
if not isinstance(system1, _System):
13381359
raise TypeError("'system1' must be of type 'sire.system.System'")
13391360

1361+
try:
1362+
num_point = system0["water"].molecules()[0].num_atoms()
1363+
except:
1364+
num_point = 0
1365+
13401366
# Check for matching number of molecules.
1341-
if not len(system0.molecules()) == len(system1.molecules()):
1367+
if not len(system0.molecules()) == len(system1.molecules()) - num_gcmc_waters:
13421368
reason = "number of molecules do not match"
13431369
return False, reason
13441370

13451371
# Check for matching number of residues.
1346-
if not len(system0.residues()) == len(system1.residues()):
1372+
if not len(system0.residues()) == len(system1.residues()) - num_gcmc_waters:
13471373
reason = "number of residues do not match"
13481374
return False, reason
13491375

13501376
# Check for matching number of atoms.
1351-
if not len(system0.atoms()) == len(system1.atoms()):
1377+
if not len(system0.atoms()) == len(system1.atoms()) - (
1378+
num_gcmc_waters * num_point
1379+
):
13521380
reason = "number of atoms do not match"
13531381
return False, reason
13541382

src/somd2/runner/_runner.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -938,16 +938,22 @@ def generate_lam_vals(lambda_base, increment=0.001):
938938
# Calculate the speed in nanoseconds per day.
939939
speed = time.to("ns") / days
940940

941-
# Checkpoint.
942-
self._checkpoint(
943-
system,
944-
index,
945-
0,
946-
speed,
947-
is_final_block=True,
948-
lambda_energy=lambda_energy,
949-
lambda_grad=lambda_grad,
950-
)
941+
# Acquire the file lock to ensure that the checkpoint files are
942+
# in a consistent state if read by another process.
943+
with lock.acquire(timeout=self._config.timeout.to("seconds")):
944+
# Backup any existing checkpoint files.
945+
self._backup_checkpoint(index)
946+
947+
# Write the checkpoint files.
948+
self._checkpoint(
949+
system,
950+
index,
951+
0,
952+
speed,
953+
lambda_energy=lambda_energy,
954+
lambda_grad=lambda_grad,
955+
is_final_block=True,
956+
)
951957

952958
_logger.success(
953959
f"{_lam_sym} = {lambda_value:.5f} complete, speed = {speed:.2f} ns day-1"

0 commit comments

Comments
 (0)