Skip to content

Commit ef4ad73

Browse files
committed
Handle HMR detection for waters and non-waters.
1 parent b0ae4fa commit ef4ad73

File tree

1 file changed

+49
-21
lines changed

1 file changed

+49
-21
lines changed

src/somd2/runner/_base.py

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -258,40 +258,54 @@ def __init__(self, system, config):
258258
self._rest2_scale_factors = scale_factors
259259
else:
260260
if len(self._config.rest2_scale) != len(self._lambda_values):
261-
raise ValueError(
262-
f"Length of 'rest2_scale' must match the number of {_lam_sym} values."
263-
)
261+
msg = f"Length of 'rest2_scale' must match the number of {_lam_sym} values."
262+
_logger.error(msg)
263+
raise ValueError(msg)
264264
if self._lambda_energy != self._lambda_values:
265-
raise ValueError(
266-
"'rest2_scale' can only be used when 'lambda_energy' matches 'lambda_values'."
265+
msg = (
266+
"REST2 scaling can currently only be used when "
267+
"'lambda_energy' matches 'lambda_values'."
267268
)
269+
_logger.error(msg)
270+
raise ValueError(msg)
268271
# Make sure the end states are close to 1.0.
269272
if not isclose(
270273
self._config.rest2_scale[0], 1.0, abs_tol=1e-4
271274
) or not isclose(self._config.rest2_scale[-1], 1.0, abs_tol=1e-4):
272-
raise ValueError(
273-
f"'rest2_scale' must be 1.0 at {_lam_sym}=0 and {_lam_sym}=1."
274-
)
275+
msg = f"'rest2_scale' must be 1.0 at {_lam_sym}=0 and {_lam_sym}=1."
276+
_logger.error(msg)
277+
raise ValueError(msg)
275278
self._rest2_scale_factors = self._config.rest2_scale
276279

277280
# Apply hydrogen mass repartitioning.
278281
if self._config.hmr:
279282
# Work out the current hydrogen mass factor.
280-
h_mass_factor, has_hydrogen = self._get_h_mass_factor(self._system)
283+
factor_non_water, factor_water = self._get_h_mass_factor(self._system)
284+
285+
# We don't support repartiioning water molecules, so check those first.
286+
if factor_water is not None:
287+
if not isclose(factor_water, 1.0, abs_tol=1e-4):
288+
msg = (
289+
"Water molecules have already been repartitioned with "
290+
f"a factor of {factor_water:.3f}. We only support "
291+
"repartitioning of non-water molecules."
292+
)
293+
_logger.error(msg)
294+
raise ValueError(msg)
281295

282296
# HMR has already been applied.
283-
if has_hydrogen:
284-
if not isclose(h_mass_factor, 1.0, abs_tol=1e-4):
297+
if factor_non_water is not None:
298+
if not isclose(factor_non_water, 1.0, abs_tol=1e-4):
285299
_logger.info(
286-
f"Detected existing hydrogen mass repartioning factor of {h_mass_factor:.3f}."
300+
f"Detected existing hydrogen mass repartioning factor of {factor_non_water:.3f}."
287301
)
288302

289303
if not isclose(
290-
h_mass_factor, self._config.h_mass_factor, abs_tol=1e-4
304+
factor_non_water, self._config.h_mass_factor, abs_tol=1e-4
291305
):
292-
new_factor = self._config.h_mass_factor / h_mass_factor
306+
new_factor = self._config.h_mass_factor / factor_non_water
293307
_logger.warning(
294-
f"Existing hydrogen mass repartitioning factor of {h_mass_factor:.3f} "
308+
f"Existing hydrogen mass repartitioning factor of {factor_non_water:.3f} "
295309
f"does not match the requested value of {self._config.h_mass_factor:.3f}. "
296310
f"Applying new factor of {new_factor:.3f}."
297311
)
@@ -1001,22 +1015,36 @@ def _get_h_mass_factor(system):
10011015
10021016
system : :class: `System <sire.system.System>`
10031017
The system of interest.
1018+
1019+
Returns
1020+
1021+
h_mass_non_water : float
1022+
The mass of the first non-water hydrogen.
1023+
1024+
h_mass_water : float
1025+
The mass of the first water hydrogen.
10041026
"""
10051027

10061028
from sire.mol import Element
10071029

10081030
# Store the expected hydrogen mass.
10091031
expected_h_mass = Element("H").mass().value()
10101032

1011-
# Get the mass of the first hydrogen atom.
1033+
# Get the mass of the first non-water hydrogen.
1034+
try:
1035+
h_mass = system["not water"].molecules()["element H"][0].mass()
1036+
h_mass_non_water = round(h_mass.value() / expected_h_mass, 3)
1037+
except:
1038+
h_mass_non_water = None
1039+
1040+
# Get the mass of the first water hydrogen.
10121041
try:
1013-
h_mass = system["element H"][0].mass()
1042+
h_mass = system["water"].molecules()["element H"][0].mass()
1043+
h_mass_water = round(h_mass.value() / expected_h_mass, 3)
10141044
except:
1015-
return expected_h_mass, False
1045+
h_mass_water = None
10161046

1017-
# Work out the current hydrogen mass factor. We round to 3dp due to
1018-
# the precision of atomic masses loaded from text files.
1019-
return round(h_mass.value() / expected_h_mass, 3), True
1047+
return h_mass_non_water, h_mass_water
10201048

10211049
@staticmethod
10221050
def _repartition_h_mass(system, factor=1.0):

0 commit comments

Comments
 (0)