Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
b8e5b36b
Commit
b8e5b36b
authored
May 24, 2017
by
peastman
Committed by
GitHub
May 24, 2017
Browse files
Merge pull request #1823 from swails/feature/flexibleConstraints
Flexible constraints
parents
10b1c7b2
3ebef4c6
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
22 deletions
+62
-22
wrappers/python/simtk/openmm/app/forcefield.py
wrappers/python/simtk/openmm/app/forcefield.py
+26
-17
wrappers/python/tests/TestForceField.py
wrappers/python/tests/TestForceField.py
+36
-5
No files found.
wrappers/python/simtk/openmm/app/forcefield.py
View file @
b8e5b36b
...
@@ -1035,6 +1035,8 @@ class ForceField(object):
...
@@ -1035,6 +1035,8 @@ class ForceField(object):
not terminated properly. This option can create ambiguities where multiple
not terminated properly. This option can create ambiguities where multiple
templates match the same residue. If that happens, use the residueTemplates
templates match the same residue. If that happens, use the residueTemplates
argument to specify which one to use.
argument to specify which one to use.
flexibleConstraints : boolean=False
If True, parameters for constrained degrees of freedom will be added to the System
args
args
Arbitrary additional keyword arguments may also be specified.
Arbitrary additional keyword arguments may also be specified.
This allows extra parameters to be specified that are specific to
This allows extra parameters to be specified that are specific to
...
@@ -1140,9 +1142,9 @@ class ForceField(object):
...
@@ -1140,9 +1142,9 @@ class ForceField(object):
if
not
unit
.
is_quantity
(
hydrogenMass
):
if
not
unit
.
is_quantity
(
hydrogenMass
):
hydrogenMass
*=
unit
.
dalton
hydrogenMass
*=
unit
.
dalton
for
atom1
,
atom2
in
topology
.
bonds
():
for
atom1
,
atom2
in
topology
.
bonds
():
if
atom1
.
element
==
elem
.
hydrogen
:
if
atom1
.
element
is
elem
.
hydrogen
:
(
atom1
,
atom2
)
=
(
atom2
,
atom1
)
(
atom1
,
atom2
)
=
(
atom2
,
atom1
)
if
atom2
.
element
==
elem
.
hydrogen
and
atom1
.
element
not
in
(
elem
.
hydrogen
,
None
):
if
atom2
.
element
is
elem
.
hydrogen
and
atom1
.
element
not
in
(
elem
.
hydrogen
,
None
):
transferMass
=
hydrogenMass
-
sys
.
getParticleMass
(
atom2
.
index
)
transferMass
=
hydrogenMass
-
sys
.
getParticleMass
(
atom2
.
index
)
sys
.
setParticleMass
(
atom2
.
index
,
hydrogenMass
)
sys
.
setParticleMass
(
atom2
.
index
,
hydrogenMass
)
sys
.
setParticleMass
(
atom1
.
index
,
sys
.
getParticleMass
(
atom1
.
index
)
-
transferMass
)
sys
.
setParticleMass
(
atom1
.
index
,
sys
.
getParticleMass
(
atom1
.
index
)
-
transferMass
)
...
@@ -1208,7 +1210,7 @@ class ForceField(object):
...
@@ -1208,7 +1210,7 @@ class ForceField(object):
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
]
bond
.
isConstrained
=
atom1
.
name
.
startswith
(
'H'
)
or
atom2
.
name
.
startswith
(
'H'
)
bond
.
isConstrained
=
atom1
.
element
is
elem
.
hydrogen
or
atom2
.
element
is
elem
.
hydrogen
if
rigidWater
:
if
rigidWater
:
for
bond
in
data
.
bonds
:
for
bond
in
data
.
bonds
:
atom1
=
data
.
atoms
[
bond
.
atom1
]
atom1
=
data
.
atoms
[
bond
.
atom1
]
...
@@ -1224,11 +1226,11 @@ class ForceField(object):
...
@@ -1224,11 +1226,11 @@ class ForceField(object):
atom2
=
data
.
atoms
[
angle
[
1
]]
atom2
=
data
.
atoms
[
angle
[
1
]]
atom3
=
data
.
atoms
[
angle
[
2
]]
atom3
=
data
.
atoms
[
angle
[
2
]]
numH
=
0
numH
=
0
if
atom1
.
name
.
startswith
(
'H'
)
:
if
atom1
.
element
is
elem
.
hydrogen
:
numH
+=
1
numH
+=
1
if
atom3
.
name
.
startswith
(
'H'
)
:
if
atom3
.
element
is
elem
.
hydrogen
:
numH
+=
1
numH
+=
1
data
.
isAngleConstrained
.
append
(
numH
==
2
or
(
numH
==
1
and
atom2
.
name
.
startswith
(
'O'
)
))
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
:
if
rigidWater
:
...
@@ -1897,7 +1899,10 @@ class HarmonicBondGenerator(object):
...
@@ -1897,7 +1899,10 @@ class HarmonicBondGenerator(object):
bond
.
length
=
self
.
length
[
i
]
bond
.
length
=
self
.
length
[
i
]
if
bond
.
isConstrained
:
if
bond
.
isConstrained
:
data
.
addConstraint
(
sys
,
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
])
data
.
addConstraint
(
sys
,
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
])
elif
self
.
k
[
i
]
!=
0
:
if
self
.
k
[
i
]
!=
0
:
# flexibleConstraints allows us to add parameters even if the DOF is
# constrained
if
not
bond
.
isConstrained
or
args
.
get
(
'flexibleConstraints'
,
False
):
force
.
addBond
(
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
],
self
.
k
[
i
])
force
.
addBond
(
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
],
self
.
k
[
i
])
break
break
...
@@ -1978,7 +1983,8 @@ class HarmonicAngleGenerator(object):
...
@@ -1978,7 +1983,8 @@ class HarmonicAngleGenerator(object):
if
l1
is
not
None
and
l2
is
not
None
:
if
l1
is
not
None
and
l2
is
not
None
:
length
=
sqrt
(
l1
*
l1
+
l2
*
l2
-
2
*
l1
*
l2
*
cos
(
self
.
angle
[
i
]))
length
=
sqrt
(
l1
*
l1
+
l2
*
l2
-
2
*
l1
*
l2
*
cos
(
self
.
angle
[
i
]))
data
.
addConstraint
(
sys
,
angle
[
0
],
angle
[
2
],
length
)
data
.
addConstraint
(
sys
,
angle
[
0
],
angle
[
2
],
length
)
elif
self
.
k
[
i
]
!=
0
:
if
self
.
k
[
i
]
!=
0
:
if
not
isConstrained
or
args
.
get
(
'flexibleConstraints'
,
False
):
force
.
addAngle
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
self
.
angle
[
i
],
self
.
k
[
i
])
force
.
addAngle
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
self
.
angle
[
i
],
self
.
k
[
i
])
break
break
...
@@ -3160,7 +3166,8 @@ class AmoebaBondGenerator(object):
...
@@ -3160,7 +3166,8 @@ class AmoebaBondGenerator(object):
bond
.
length
=
self
.
length
[
i
]
bond
.
length
=
self
.
length
[
i
]
if
bond
.
isConstrained
:
if
bond
.
isConstrained
:
data
.
addConstraint
(
sys
,
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
])
data
.
addConstraint
(
sys
,
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
])
elif
self
.
k
[
i
]
!=
0
:
if
self
.
k
[
i
]
!=
0
:
if
not
bond
.
isConstrained
or
args
.
get
(
'flexibleConstraints'
,
False
):
force
.
addBond
(
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
],
self
.
k
[
i
])
force
.
addBond
(
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
],
self
.
k
[
i
])
break
break
...
@@ -3288,6 +3295,8 @@ class AmoebaAngleGenerator(object):
...
@@ -3288,6 +3295,8 @@ class AmoebaAngleGenerator(object):
force
.
setAmoebaGlobalAnglePentic
(
self
.
pentic
)
force
.
setAmoebaGlobalAnglePentic
(
self
.
pentic
)
force
.
setAmoebaGlobalAngleSextic
(
self
.
sextic
)
force
.
setAmoebaGlobalAngleSextic
(
self
.
sextic
)
DEG_TO_RAD
=
math
.
pi
/
180
for
angleDict
in
angleList
:
for
angleDict
in
angleList
:
angle
=
angleDict
[
'angle'
]
angle
=
angleDict
[
'angle'
]
isConstrained
=
angleDict
[
'isConstrained'
]
isConstrained
=
angleDict
[
'isConstrained'
]
...
@@ -3302,8 +3311,8 @@ class AmoebaAngleGenerator(object):
...
@@ -3302,8 +3311,8 @@ class AmoebaAngleGenerator(object):
if
(
type1
in
types1
and
type2
in
types2
and
type3
in
types3
)
or
(
type1
in
types3
and
type2
in
types2
and
type3
in
types1
):
if
(
type1
in
types1
and
type2
in
types2
and
type3
in
types3
)
or
(
type1
in
types3
and
type2
in
types2
and
type3
in
types1
):
if
isConstrained
and
self
.
k
[
i
]
!=
0.0
:
if
isConstrained
and
self
.
k
[
i
]
!=
0.0
:
angleDict
[
'idealAngle'
]
=
self
.
angle
[
i
][
0
]
angleDict
[
'idealAngle'
]
=
self
.
angle
[
i
][
0
]
addAngleConstraint
(
angle
,
self
.
angle
[
i
][
0
]
*
math
.
pi
/
180.0
,
data
,
sys
)
addAngleConstraint
(
angle
,
self
.
angle
[
i
][
0
]
*
DEG_TO_RAD
,
data
,
sys
)
el
if
self
.
k
[
i
]
!=
0
:
if
self
.
k
[
i
]
!=
0
and
(
not
isConstrained
or
args
.
get
(
'flexibleConstraints'
,
False
))
:
lenAngle
=
len
(
self
.
angle
[
i
])
lenAngle
=
len
(
self
.
angle
[
i
])
if
(
lenAngle
>
1
):
if
(
lenAngle
>
1
):
# get k-index by counting number of non-angle hydrogens on the central atom
# get k-index by counting number of non-angle hydrogens on the central atom
...
@@ -3372,7 +3381,7 @@ class AmoebaAngleGenerator(object):
...
@@ -3372,7 +3381,7 @@ class AmoebaAngleGenerator(object):
angleDict
[
'idealAngle'
]
=
self
.
angle
[
i
][
0
]
angleDict
[
'idealAngle'
]
=
self
.
angle
[
i
][
0
]
if
(
isConstrained
and
self
.
k
[
i
]
!=
0.0
):
if
(
isConstrained
and
self
.
k
[
i
]
!=
0.0
):
addAngleConstraint
(
angle
,
self
.
angle
[
i
][
0
]
*
math
.
pi
/
180.0
,
data
,
sys
)
addAngleConstraint
(
angle
,
self
.
angle
[
i
][
0
]
*
math
.
pi
/
180.0
,
data
,
sys
)
else
:
if
self
.
k
[
i
]
!=
0.0
and
(
not
isConstrained
or
args
.
get
(
'flexibleConstraints'
,
False
))
:
force
.
addAngle
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
angle
[
3
],
self
.
angle
[
i
][
0
],
self
.
k
[
i
])
force
.
addAngle
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
angle
[
3
],
self
.
angle
[
i
][
0
],
self
.
k
[
i
])
break
break
...
@@ -5431,7 +5440,7 @@ class AmoebaUreyBradleyGenerator(object):
...
@@ -5431,7 +5440,7 @@ class AmoebaUreyBradleyGenerator(object):
force
=
existing
[
0
]
force
=
existing
[
0
]
for
(
angle
,
isConstrained
)
in
zip
(
data
.
angles
,
data
.
isAngleConstrained
):
for
(
angle
,
isConstrained
)
in
zip
(
data
.
angles
,
data
.
isAngleConstrained
):
if
(
isConstrained
):
if
(
isConstrained
and
not
args
.
get
(
'flexibleConstraints'
,
False
)
):
continue
continue
type1
=
data
.
atomType
[
data
.
atoms
[
angle
[
0
]]]
type1
=
data
.
atomType
[
data
.
atoms
[
angle
[
0
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
angle
[
1
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
angle
[
1
]]]
...
...
wrappers/python/tests/TestForceField.py
View file @
b8e5b36b
...
@@ -95,6 +95,37 @@ class TestForceField(unittest.TestCase):
...
@@ -95,6 +95,37 @@ class TestForceField(unittest.TestCase):
validateConstraints
(
self
,
topology
,
system
,
validateConstraints
(
self
,
topology
,
system
,
constraints_value
,
rigidWater_value
)
constraints_value
,
rigidWater_value
)
def
test_flexibleConstraints
(
self
):
""" Test the flexibleConstraints keyword """
topology
=
self
.
pdb1
.
topology
system1
=
self
.
forcefield1
.
createSystem
(
topology
,
constraints
=
HAngles
,
rigidWater
=
True
)
system2
=
self
.
forcefield1
.
createSystem
(
topology
,
constraints
=
HAngles
,
rigidWater
=
True
,
flexibleConstraints
=
True
)
system3
=
self
.
forcefield1
.
createSystem
(
topology
,
constraints
=
None
,
rigidWater
=
False
)
validateConstraints
(
self
,
topology
,
system1
,
HAngles
,
True
)
# validateConstraints fails for system2 since by definition atom pairs can be in both bond
# and constraint lists. So just check that the number of constraints is the same for both
# system1 and system2
self
.
assertEqual
(
system1
.
getNumConstraints
(),
system2
.
getNumConstraints
())
for
force
in
system1
.
getForces
():
if
isinstance
(
force
,
HarmonicBondForce
):
bf1
=
force
elif
isinstance
(
force
,
HarmonicAngleForce
):
af1
=
force
for
force
in
system2
.
getForces
():
if
isinstance
(
force
,
HarmonicBondForce
):
bf2
=
force
elif
isinstance
(
force
,
HarmonicAngleForce
):
af2
=
force
for
force
in
system3
.
getForces
():
if
isinstance
(
force
,
HarmonicAngleForce
):
af3
=
force
# Make sure we picked up extra bond terms with flexibleConstraints
self
.
assertGreater
(
bf2
.
getNumBonds
(),
bf1
.
getNumBonds
())
# Make sure flexibleConstraints yields just as many angles as no constraints
self
.
assertEqual
(
af2
.
getNumAngles
(),
af3
.
getNumAngles
())
def
test_ImplicitSolvent
(
self
):
def
test_ImplicitSolvent
(
self
):
"""Test the four types of implicit solvents using the implicitSolvent
"""Test the four types of implicit solvents using the implicitSolvent
parameter.
parameter.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment