"vscode:/vscode.git/clone" did not exist on "7ee7de16288c27cdfae0415b2a59db047a48ea55"
Commit 57d85036 authored by peastman's avatar peastman
Browse files

Improved behavior of rigidWater option

parent 2fed304b
...@@ -2983,7 +2983,7 @@ ...@@ -2983,7 +2983,7 @@
<ExternalBond from="14" /> <ExternalBond from="14" />
<ExternalBond from="0" /> <ExternalBond from="0" />
</Residue> </Residue>
<Residue name="HOH"> <Residue name="HOH" rigidWater="false">
<Atom name="H1" type="403" /> <Atom name="H1" type="403" />
<Atom name="H2" type="403" /> <Atom name="H2" type="403" />
<Atom name="O" type="402" /> <Atom name="O" type="402" />
......
...@@ -1756,7 +1756,7 @@ ...@@ -1756,7 +1756,7 @@
<ExternalBond from="14" /> <ExternalBond from="14" />
<ExternalBond from="0" /> <ExternalBond from="0" />
</Residue> </Residue>
<Residue name="HOH"> <Residue name="HOH" rigidWater="false">
<Atom name="H1" type="248" /> <Atom name="H1" type="248" />
<Atom name="H2" type="248" /> <Atom name="H2" type="248" />
<Atom name="O" type="247" /> <Atom name="O" type="247" />
......
...@@ -264,6 +264,8 @@ class ForceField(object): ...@@ -264,6 +264,8 @@ class ForceField(object):
template = ForceField._TemplateData(resName) template = ForceField._TemplateData(resName)
if 'override' in residue.attrib: if 'override' in residue.attrib:
template.overrideLevel = int(residue.attrib['override']) template.overrideLevel = int(residue.attrib['override'])
if 'rigidWater' in residue.attrib:
template.rigidWater = (residue.attrib['rigidWater'].lower() == 'true')
atomIndices = template.atomIndices atomIndices = template.atomIndices
for ia, atom in enumerate(residue.findall('Atom')): for ia, atom in enumerate(residue.findall('Atom')):
params = {} params = {}
...@@ -594,6 +596,7 @@ class ForceField(object): ...@@ -594,6 +596,7 @@ class ForceField(object):
self.bonds = [] self.bonds = []
self.externalBonds = [] self.externalBonds = []
self.overrideLevel = 0 self.overrideLevel = 0
self.rigidWater = True
def getAtomIndexByName(self, atom_name): def getAtomIndexByName(self, atom_name):
"""Look up an atom index by atom name, providing a helpful error message if not found.""" """Look up an atom index by atom name, providing a helpful error message if not found."""
...@@ -1051,7 +1054,7 @@ class ForceField(object): ...@@ -1051,7 +1054,7 @@ class ForceField(object):
return [templates, unique_unmatched_residues] return [templates, unique_unmatched_residues]
def createSystem(self, topology, nonbondedMethod=NoCutoff, nonbondedCutoff=1.0*unit.nanometer, def createSystem(self, topology, nonbondedMethod=NoCutoff, nonbondedCutoff=1.0*unit.nanometer,
constraints=None, rigidWater=True, removeCMMotion=True, hydrogenMass=None, residueTemplates=dict(), constraints=None, rigidWater=None, removeCMMotion=True, hydrogenMass=None, residueTemplates=dict(),
ignoreExternalBonds=False, switchDistance=None, flexibleConstraints=False, **args): ignoreExternalBonds=False, switchDistance=None, flexibleConstraints=False, **args):
"""Construct an OpenMM System representing a Topology with this force field. """Construct an OpenMM System representing a Topology with this force field.
...@@ -1067,9 +1070,10 @@ class ForceField(object): ...@@ -1067,9 +1070,10 @@ class ForceField(object):
constraints : object=None constraints : object=None
Specifies which bonds and angles should be implemented with constraints. Specifies which bonds and angles should be implemented with constraints.
Allowed values are None, HBonds, AllBonds, or HAngles. Allowed values are None, HBonds, AllBonds, or HAngles.
rigidWater : boolean=True rigidWater : boolean=None
If true, water molecules will be fully rigid regardless of the value If true, water molecules will be fully rigid regardless of the value
passed for the constraints argument passed for the constraints argument. If None (the default), it uses the
default behavior for this force field's water model.
removeCMMotion : boolean=True removeCMMotion : boolean=True
If true, a CMMotionRemover will be added to the System If true, a CMMotionRemover will be added to the System
hydrogenMass : mass=None hydrogenMass : mass=None
...@@ -1109,6 +1113,7 @@ class ForceField(object): ...@@ -1109,6 +1113,7 @@ class ForceField(object):
data.atoms = list(topology.atoms()) data.atoms = list(topology.atoms())
for atom in data.atoms: for atom in data.atoms:
data.excludeAtomWith.append([]) data.excludeAtomWith.append([])
rigidResidue = [False]*topology.getNumResidues()
# Make a list of all bonds # Make a list of all bonds
...@@ -1146,6 +1151,13 @@ class ForceField(object): ...@@ -1146,6 +1151,13 @@ class ForceField(object):
unmatchedResidues.append(res) unmatchedResidues.append(res)
else: else:
data.recordMatchedAtomParameters(res, template, matches) data.recordMatchedAtomParameters(res, template, matches)
if res.name == 'HOH':
# Determine whether this should be a rigid water.
if rigidWater is None and template is not None:
rigidResidue[res.index] = template.rigidWater
elif rigidWater:
rigidResidue[res.index] = True
# Try to apply patches to find matches for any unmatched residues. # Try to apply patches to find matches for any unmatched residues.
...@@ -1269,12 +1281,11 @@ class ForceField(object): ...@@ -1269,12 +1281,11 @@ class ForceField(object):
atom1 = data.atoms[bond.atom1] atom1 = data.atoms[bond.atom1]
atom2 = data.atoms[bond.atom2] atom2 = data.atoms[bond.atom2]
bond.isConstrained = atom1.element is elem.hydrogen or atom2.element is elem.hydrogen bond.isConstrained = atom1.element is elem.hydrogen or atom2.element is elem.hydrogen
if rigidWater: for bond in data.bonds:
for bond in data.bonds: atom1 = data.atoms[bond.atom1]
atom1 = data.atoms[bond.atom1] atom2 = data.atoms[bond.atom2]
atom2 = data.atoms[bond.atom2] if rigidResidue[atom1.residue.index] and rigidResidue[atom2.residue.index]:
if atom1.residue.name == 'HOH' and atom2.residue.name == 'HOH': bond.isConstrained = True
bond.isConstrained = True
# Identify angles that should be implemented with constraints # Identify angles that should be implemented with constraints
...@@ -1291,14 +1302,13 @@ class ForceField(object): ...@@ -1291,14 +1302,13 @@ class ForceField(object):
data.isAngleConstrained.append(numH == 2 or (numH == 1 and atom2.element is elem.oxygen)) data.isAngleConstrained.append(numH == 2 or (numH == 1 and atom2.element is elem.oxygen))
else: else:
data.isAngleConstrained = len(data.angles)*[False] data.isAngleConstrained = len(data.angles)*[False]
if rigidWater: for i in range(len(data.angles)):
for i in range(len(data.angles)): angle = data.angles[i]
angle = data.angles[i] atom1 = data.atoms[angle[0]]
atom1 = data.atoms[angle[0]] atom2 = data.atoms[angle[1]]
atom2 = data.atoms[angle[1]] atom3 = data.atoms[angle[2]]
atom3 = data.atoms[angle[2]] if rigidResidue[atom1.residue.index] and rigidResidue[atom2.residue.index] and rigidResidue[atom3.residue.index]:
if atom1.residue.name == 'HOH' and atom2.residue.name == 'HOH' and atom3.residue.name == 'HOH': data.isAngleConstrained[i] = True
data.isAngleConstrained[i] = True
# Add virtual sites # Add virtual sites
......
...@@ -165,12 +165,12 @@ class TestForceField(unittest.TestCase): ...@@ -165,12 +165,12 @@ class TestForceField(unittest.TestCase):
topology = self.pdb1.topology topology = self.pdb1.topology
for constraints_value in [None, HBonds, AllBonds, HAngles]: for constraints_value in [None, HBonds, AllBonds, HAngles]:
for rigidWater_value in [True, False]: for rigidWater_value in [True, False, None]:
system = self.forcefield1.createSystem(topology, system = self.forcefield1.createSystem(topology,
constraints=constraints_value, constraints=constraints_value,
rigidWater=rigidWater_value) rigidWater=rigidWater_value)
validateConstraints(self, topology, system, validateConstraints(self, topology, system,
constraints_value, rigidWater_value) constraints_value, rigidWater_value != False)
def test_flexibleConstraints(self): def test_flexibleConstraints(self):
""" Test the flexibleConstraints keyword """ """ Test the flexibleConstraints keyword """
...@@ -1061,6 +1061,15 @@ class AmoebaTestForceField(unittest.TestCase): ...@@ -1061,6 +1061,15 @@ class AmoebaTestForceField(unittest.TestCase):
self.assertAlmostEqual(constraints[(0,1)], hoDist) self.assertAlmostEqual(constraints[(0,1)], hoDist)
self.assertAlmostEqual(constraints[(0,2)], hoDist) self.assertAlmostEqual(constraints[(0,2)], hoDist)
self.assertAlmostEqual(constraints[(1,2)], hohDist) self.assertAlmostEqual(constraints[(1,2)], hohDist)
# Check that all values of rigidWater are interpreted correctly.
numWaters = 215
self.assertEqual(3*numWaters, system.getNumConstraints())
system = self.forcefield1.createSystem(self.pdb1.topology, rigidWater=False)
self.assertEqual(0, system.getNumConstraints())
system = self.forcefield1.createSystem(self.pdb1.topology, rigidWater=None)
self.assertEqual(0, system.getNumConstraints())
def test_Forces(self): def test_Forces(self):
"""Compute forces and compare them to ones generated with a previous version of OpenMM to ensure they haven't changed.""" """Compute forces and compare them to ones generated with a previous version of OpenMM to ensure they haven't changed."""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment