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
18295108
Commit
18295108
authored
Sep 05, 2017
by
peastman
Browse files
Merge changes from main branch
parents
e6101f68
8d7234e5
Changes
154
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
991 additions
and
238 deletions
+991
-238
serialization/src/CustomIntegratorProxy.cpp
serialization/src/CustomIntegratorProxy.cpp
+15
-6
serialization/src/SerializationProxyRegistration.cpp
serialization/src/SerializationProxyRegistration.cpp
+3
-0
serialization/src/SystemProxy.cpp
serialization/src/SystemProxy.cpp
+31
-13
serialization/tests/TestSerializeCustomCVForce.cpp
serialization/tests/TestSerializeCustomCVForce.cpp
+114
-0
serialization/tests/TestSerializeIntegrator.cpp
serialization/tests/TestSerializeIntegrator.cpp
+17
-0
serialization/tests/TestSerializeSystem.cpp
serialization/tests/TestSerializeSystem.cpp
+20
-2
tests/TestCustomCVForce.h
tests/TestCustomCVForce.h
+242
-0
tests/TestCustomGBForce.h
tests/TestCustomGBForce.h
+1
-0
tests/TestCustomHbondForce.h
tests/TestCustomHbondForce.h
+28
-0
tests/TestCustomIntegrator.h
tests/TestCustomIntegrator.h
+128
-1
tests/TestVirtualSites.h
tests/TestVirtualSites.h
+45
-22
wrappers/generateWrappers.py
wrappers/generateWrappers.py
+10
-4
wrappers/python/simtk/openmm/app/amberprmtopfile.py
wrappers/python/simtk/openmm/app/amberprmtopfile.py
+7
-2
wrappers/python/simtk/openmm/app/charmmpsffile.py
wrappers/python/simtk/openmm/app/charmmpsffile.py
+31
-21
wrappers/python/simtk/openmm/app/dcdreporter.py
wrappers/python/simtk/openmm/app/dcdreporter.py
+1
-1
wrappers/python/simtk/openmm/app/forcefield.py
wrappers/python/simtk/openmm/app/forcefield.py
+209
-136
wrappers/python/simtk/openmm/app/gromacsgrofile.py
wrappers/python/simtk/openmm/app/gromacsgrofile.py
+8
-5
wrappers/python/simtk/openmm/app/gromacstopfile.py
wrappers/python/simtk/openmm/app/gromacstopfile.py
+64
-15
wrappers/python/simtk/openmm/app/internal/amber_file_parser.py
...ers/python/simtk/openmm/app/internal/amber_file_parser.py
+14
-9
wrappers/python/simtk/openmm/app/pdbfile.py
wrappers/python/simtk/openmm/app/pdbfile.py
+3
-1
No files found.
serialization/src/CustomIntegratorProxy.cpp
View file @
18295108
...
...
@@ -40,22 +40,22 @@ CustomIntegratorProxy::CustomIntegratorProxy() : SerializationProxy("CustomInteg
}
void
CustomIntegratorProxy
::
serialize
(
const
void
*
object
,
SerializationNode
&
node
)
const
{
node
.
setIntProperty
(
"version"
,
1
);
node
.
setIntProperty
(
"version"
,
2
);
const
CustomIntegrator
&
integrator
=
*
reinterpret_cast
<
const
CustomIntegrator
*>
(
object
);
SerializationNode
&
globalVariablesNode
=
node
.
createChildNode
(
"GlobalVariables"
);
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
{
for
(
int
i
=
0
;
i
<
integrator
.
getNumGlobalVariables
();
i
++
)
{
globalVariablesNode
.
setDoubleProperty
(
integrator
.
getGlobalVariableName
(
i
),
integrator
.
getGlobalVariable
(
i
));
}
SerializationNode
&
perDofVariablesNode
=
node
.
createChildNode
(
"PerDofVariables"
);
for
(
int
i
=
0
;
i
<
integrator
.
getNumPerDofVariables
();
i
++
)
{
for
(
int
i
=
0
;
i
<
integrator
.
getNumPerDofVariables
();
i
++
)
{
SerializationNode
&
perDofValuesNode
=
perDofVariablesNode
.
createChildNode
(
integrator
.
getPerDofVariableName
(
i
));
vector
<
Vec3
>
perDofValues
;
integrator
.
getPerDofVariable
(
i
,
perDofValues
);
for
(
int
j
=
0
;
j
<
perDofValues
.
size
();
j
++
)
{
for
(
int
j
=
0
;
j
<
perDofValues
.
size
();
j
++
)
{
perDofValuesNode
.
createChildNode
(
"Value"
).
setDoubleProperty
(
"x"
,
perDofValues
[
j
][
0
]).
setDoubleProperty
(
"y"
,
perDofValues
[
j
][
1
]).
setDoubleProperty
(
"z"
,
perDofValues
[
j
][
2
]);
}
}
SerializationNode
&
computationsNode
=
node
.
createChildNode
(
"Computations"
);
for
(
int
i
=
0
;
i
<
integrator
.
getNumComputations
();
i
++
)
{
for
(
int
i
=
0
;
i
<
integrator
.
getNumComputations
();
i
++
)
{
CustomIntegrator
::
ComputationType
computationType
;
string
computationVariable
;
string
computationExpression
;
...
...
@@ -63,6 +63,9 @@ void CustomIntegratorProxy::serialize(const void* object, SerializationNode& nod
computationsNode
.
createChildNode
(
"Computation"
).
setIntProperty
(
"computationType"
,
static_cast
<
int
>
(
computationType
))
.
setStringProperty
(
"computationVariable"
,
computationVariable
).
setStringProperty
(
"computationExpression"
,
computationExpression
);
}
SerializationNode
&
functions
=
node
.
createChildNode
(
"Functions"
);
for
(
int
i
=
0
;
i
<
integrator
.
getNumTabulatedFunctions
();
i
++
)
functions
.
createChildNode
(
"Function"
,
&
integrator
.
getTabulatedFunction
(
i
)).
setStringProperty
(
"name"
,
integrator
.
getTabulatedFunctionName
(
i
));
node
.
setStringProperty
(
"kineticEnergyExpression"
,
integrator
.
getKineticEnergyExpression
());
node
.
setIntProperty
(
"randomSeed"
,
integrator
.
getRandomNumberSeed
());
node
.
setDoubleProperty
(
"stepSize"
,
integrator
.
getStepSize
());
...
...
@@ -70,7 +73,8 @@ void CustomIntegratorProxy::serialize(const void* object, SerializationNode& nod
}
void
*
CustomIntegratorProxy
::
deserialize
(
const
SerializationNode
&
node
)
const
{
if
(
node
.
getIntProperty
(
"version"
)
!=
1
)
int
version
=
node
.
getIntProperty
(
"version"
);
if
(
version
<
1
||
version
>
2
)
throw
OpenMMException
(
"Unsupported version number"
);
CustomIntegrator
*
integrator
=
new
CustomIntegrator
(
node
.
getDoubleProperty
(
"stepSize"
));
const
SerializationNode
&
globalVariablesNode
=
node
.
getChildNode
(
"GlobalVariables"
);
...
...
@@ -112,6 +116,11 @@ void* CustomIntegratorProxy::deserialize(const SerializationNode& node) const {
throw
(
OpenMMException
(
"Custom Integrator Deserialization: Unknown computation type"
));
}
}
if
(
version
>
1
)
{
const
SerializationNode
&
functions
=
node
.
getChildNode
(
"Functions"
);
for
(
auto
&
function
:
functions
.
getChildren
())
integrator
->
addTabulatedFunction
(
function
.
getStringProperty
(
"name"
),
function
.
decodeObject
<
TabulatedFunction
>
());
}
integrator
->
setKineticEnergyExpression
(
node
.
getStringProperty
(
"kineticEnergyExpression"
));
integrator
->
setRandomNumberSeed
(
node
.
getIntProperty
(
"randomSeed"
));
integrator
->
setConstraintTolerance
(
node
.
getDoubleProperty
(
"constraintTolerance"
));
...
...
serialization/src/SerializationProxyRegistration.cpp
View file @
18295108
...
...
@@ -38,6 +38,7 @@
#include "openmm/CustomBondForce.h"
#include "openmm/CustomCentroidBondForce.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/CustomCVForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomGBForce.h"
#include "openmm/CustomHbondForce.h"
...
...
@@ -72,6 +73,7 @@
#include "openmm/serialization/CustomBondForceProxy.h"
#include "openmm/serialization/CustomCentroidBondForceProxy.h"
#include "openmm/serialization/CustomCompoundBondForceProxy.h"
#include "openmm/serialization/CustomCVForceProxy.h"
#include "openmm/serialization/CustomExternalForceProxy.h"
#include "openmm/serialization/CustomGBForceProxy.h"
#include "openmm/serialization/CustomHbondForceProxy.h"
...
...
@@ -124,6 +126,7 @@ extern "C" void registerSerializationProxies() {
SerializationProxy
::
registerProxy
(
typeid
(
CustomBondForce
),
new
CustomBondForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
CustomCentroidBondForce
),
new
CustomCentroidBondForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
CustomCompoundBondForce
),
new
CustomCompoundBondForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
CustomCVForce
),
new
CustomCVForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
CustomExternalForce
),
new
CustomExternalForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
CustomGBForce
),
new
CustomGBForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
CustomHbondForce
),
new
CustomHbondForceProxy
());
...
...
serialization/src/SystemProxy.cpp
View file @
18295108
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-201
5
Stanford University and the Authors. *
* Portions copyright (c) 2010-201
7
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -71,15 +71,23 @@ void SystemProxy::serialize(const void* object, SerializationNode& node) const {
}
else
if
(
typeid
(
system
.
getVirtualSite
(
i
))
==
typeid
(
LocalCoordinatesSite
))
{
const
LocalCoordinatesSite
&
site
=
dynamic_cast
<
const
LocalCoordinatesSite
&>
(
system
.
getVirtualSite
(
i
));
Vec3
wo
=
site
.
getOriginWeights
();
Vec3
wx
=
site
.
getXWeights
();
Vec3
wy
=
site
.
getYWeights
();
int
numParticles
=
site
.
getNumParticles
();
vector
<
double
>
wo
,
wx
,
wy
;
site
.
getOriginWeights
(
wo
);
site
.
getXWeights
(
wx
);
site
.
getYWeights
(
wy
);
Vec3
p
=
site
.
getLocalPosition
();
particle
.
createChildNode
(
"LocalCoordinatesSite"
).
setIntProperty
(
"p1"
,
site
.
getParticle
(
0
)).
setIntProperty
(
"p2"
,
site
.
getParticle
(
1
)).
setIntProperty
(
"p3"
,
site
.
getParticle
(
2
)).
setDoubleProperty
(
"wo1"
,
wo
[
0
]).
setDoubleProperty
(
"wo2"
,
wo
[
1
]).
setDoubleProperty
(
"wo3"
,
wo
[
2
]).
setDoubleProperty
(
"wx1"
,
wx
[
0
]).
setDoubleProperty
(
"wx2"
,
wx
[
1
]).
setDoubleProperty
(
"wx3"
,
wx
[
2
]).
setDoubleProperty
(
"wy1"
,
wy
[
0
]).
setDoubleProperty
(
"wy2"
,
wy
[
1
]).
setDoubleProperty
(
"wy3"
,
wy
[
2
]).
setDoubleProperty
(
"pos1"
,
p
[
0
]).
setDoubleProperty
(
"pos2"
,
p
[
1
]).
setDoubleProperty
(
"pos3"
,
p
[
2
]);
SerializationNode
&
siteNode
=
particle
.
createChildNode
(
"LocalCoordinatesSite"
);
siteNode
.
setDoubleProperty
(
"pos1"
,
p
[
0
]).
setDoubleProperty
(
"pos2"
,
p
[
1
]).
setDoubleProperty
(
"pos3"
,
p
[
2
]);
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
{
stringstream
ss
;
ss
<<
(
j
+
1
);
string
index
=
ss
.
str
();
siteNode
.
setIntProperty
(
"p"
+
index
,
site
.
getParticle
(
j
));
siteNode
.
setDoubleProperty
(
"wo"
+
index
,
wo
[
j
]);
siteNode
.
setDoubleProperty
(
"wx"
+
index
,
wx
[
j
]);
siteNode
.
setDoubleProperty
(
"wy"
+
index
,
wy
[
j
]);
}
}
}
}
...
...
@@ -120,11 +128,21 @@ void* SystemProxy::deserialize(const SerializationNode& node) const {
else
if
(
vsite
.
getName
()
==
"OutOfPlaneSite"
)
system
->
setVirtualSite
(
i
,
new
OutOfPlaneSite
(
vsite
.
getIntProperty
(
"p1"
),
vsite
.
getIntProperty
(
"p2"
),
vsite
.
getIntProperty
(
"p3"
),
vsite
.
getDoubleProperty
(
"w12"
),
vsite
.
getDoubleProperty
(
"w13"
),
vsite
.
getDoubleProperty
(
"wc"
)));
else
if
(
vsite
.
getName
()
==
"LocalCoordinatesSite"
)
{
Vec3
wo
(
vsite
.
getDoubleProperty
(
"wo1"
),
vsite
.
getDoubleProperty
(
"wo2"
),
vsite
.
getDoubleProperty
(
"wo3"
));
Vec3
wx
(
vsite
.
getDoubleProperty
(
"wx1"
),
vsite
.
getDoubleProperty
(
"wx2"
),
vsite
.
getDoubleProperty
(
"wx3"
));
Vec3
wy
(
vsite
.
getDoubleProperty
(
"wy1"
),
vsite
.
getDoubleProperty
(
"wy2"
),
vsite
.
getDoubleProperty
(
"wy3"
));
vector
<
int
>
particles
;
vector
<
double
>
wo
,
wx
,
wy
;
for
(
int
j
=
0
;
;
j
++
)
{
stringstream
ss
;
ss
<<
(
j
+
1
);
string
index
=
ss
.
str
();
if
(
!
vsite
.
hasProperty
(
"p"
+
index
))
break
;
particles
.
push_back
(
vsite
.
getIntProperty
(
"p"
+
index
));
wo
.
push_back
(
vsite
.
getDoubleProperty
(
"wo"
+
index
));
wx
.
push_back
(
vsite
.
getDoubleProperty
(
"wx"
+
index
));
wy
.
push_back
(
vsite
.
getDoubleProperty
(
"wy"
+
index
));
}
Vec3
p
(
vsite
.
getDoubleProperty
(
"pos1"
),
vsite
.
getDoubleProperty
(
"pos2"
),
vsite
.
getDoubleProperty
(
"pos3"
));
system
->
setVirtualSite
(
i
,
new
LocalCoordinatesSite
(
vsite
.
getIntProperty
(
"p1"
),
vsite
.
getIntProperty
(
"p2"
),
vsite
.
getIntProperty
(
"p3"
)
,
wo
,
wx
,
wy
,
p
));
system
->
setVirtualSite
(
i
,
new
LocalCoordinatesSite
(
particles
,
wo
,
wx
,
wy
,
p
));
}
}
}
...
...
serialization/tests/TestSerializeCustomCVForce.cpp
0 → 100644
View file @
18295108
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-2017 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/CustomCVForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/serialization/XmlSerializer.h"
#include <iostream>
#include <sstream>
using
namespace
OpenMM
;
using
namespace
std
;
void
testSerialization
()
{
// Create a Force.
CustomCVForce
force
(
"2*v1+v2"
);
force
.
setForceGroup
(
3
);
force
.
addGlobalParameter
(
"x"
,
1.3
);
force
.
addGlobalParameter
(
"y"
,
2.221
);
force
.
addEnergyParameterDerivative
(
"y"
);
HarmonicBondForce
*
v1
=
new
HarmonicBondForce
();
v1
->
addBond
(
2
,
3
,
5.2
,
1.1
);
force
.
addCollectiveVariable
(
"v1"
,
v1
);
HarmonicAngleForce
*
v2
=
new
HarmonicAngleForce
();
v2
->
addAngle
(
3
,
11
,
15
,
0.4
,
0.2
);
force
.
addCollectiveVariable
(
"v2"
,
v2
);
vector
<
double
>
values
(
10
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
values
[
i
]
=
sin
((
double
)
i
);
force
.
addTabulatedFunction
(
"f"
,
new
Continuous1DFunction
(
values
,
0.5
,
1.5
));
// Serialize and then deserialize it.
stringstream
buffer
;
XmlSerializer
::
serialize
<
CustomCVForce
>
(
&
force
,
"Force"
,
buffer
);
CustomCVForce
*
copy
=
XmlSerializer
::
deserialize
<
CustomCVForce
>
(
buffer
);
// Compare the two forces to see if they are identical.
CustomCVForce
&
force2
=
*
copy
;
ASSERT_EQUAL
(
force
.
getForceGroup
(),
force2
.
getForceGroup
());
ASSERT_EQUAL
(
force
.
getEnergyFunction
(),
force2
.
getEnergyFunction
());
ASSERT_EQUAL
(
force
.
getNumGlobalParameters
(),
force2
.
getNumGlobalParameters
());
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
{
ASSERT_EQUAL
(
force
.
getGlobalParameterName
(
i
),
force2
.
getGlobalParameterName
(
i
));
ASSERT_EQUAL
(
force
.
getGlobalParameterDefaultValue
(
i
),
force2
.
getGlobalParameterDefaultValue
(
i
));
}
ASSERT_EQUAL
(
force
.
getNumEnergyParameterDerivatives
(),
force2
.
getNumEnergyParameterDerivatives
());
for
(
int
i
=
0
;
i
<
force
.
getNumEnergyParameterDerivatives
();
i
++
)
ASSERT_EQUAL
(
force
.
getEnergyParameterDerivativeName
(
i
),
force2
.
getEnergyParameterDerivativeName
(
i
));
ASSERT_EQUAL
(
force
.
getNumCollectiveVariables
(),
force2
.
getNumCollectiveVariables
());
for
(
int
i
=
0
;
i
<
force
.
getNumCollectiveVariables
();
i
++
)
{
ASSERT_EQUAL
(
force
.
getCollectiveVariableName
(
i
),
force2
.
getCollectiveVariableName
(
i
));
stringstream
buffer1
,
buffer2
;
XmlSerializer
::
serialize
<
Force
>
(
&
force
.
getCollectiveVariable
(
i
),
"Force"
,
buffer1
);
XmlSerializer
::
serialize
<
Force
>
(
&
force2
.
getCollectiveVariable
(
i
),
"Force"
,
buffer2
);
ASSERT_EQUAL
(
buffer1
.
str
(),
buffer2
.
str
());
}
ASSERT_EQUAL
(
force
.
getNumTabulatedFunctions
(),
force2
.
getNumTabulatedFunctions
());
for
(
int
i
=
0
;
i
<
force
.
getNumTabulatedFunctions
();
i
++
)
{
double
min1
,
min2
,
max1
,
max2
;
vector
<
double
>
val1
,
val2
;
dynamic_cast
<
Continuous1DFunction
&>
(
force
.
getTabulatedFunction
(
i
)).
getFunctionParameters
(
val1
,
min1
,
max1
);
dynamic_cast
<
Continuous1DFunction
&>
(
force2
.
getTabulatedFunction
(
i
)).
getFunctionParameters
(
val2
,
min2
,
max2
);
ASSERT_EQUAL
(
force
.
getTabulatedFunctionName
(
i
),
force2
.
getTabulatedFunctionName
(
i
));
ASSERT_EQUAL
(
min1
,
min2
);
ASSERT_EQUAL
(
max1
,
max2
);
ASSERT_EQUAL
(
val1
.
size
(),
val2
.
size
());
for
(
int
j
=
0
;
j
<
(
int
)
val1
.
size
();
j
++
)
ASSERT_EQUAL
(
val1
[
j
],
val2
[
j
]);
}
}
int
main
()
{
try
{
testSerialization
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
serialization/tests/TestSerializeIntegrator.cpp
View file @
18295108
...
...
@@ -156,6 +156,10 @@ void testSerializeCustomIntegrator() {
intg
->
addComputeSum
(
"summand2"
,
"v*v+f*f"
);
intg
->
setConstraintTolerance
(
1e-5
);
intg
->
setKineticEnergyExpression
(
"m*v1*v1/2; v1=v+0.5*dt*f/m"
);
vector
<
double
>
values
(
10
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
values
[
i
]
=
sin
((
double
)
i
);
intg
->
addTabulatedFunction
(
"f"
,
new
Continuous1DFunction
(
values
,
0.5
,
1.5
));
stringstream
ss
;
XmlSerializer
::
serialize
<
Integrator
>
(
intg
,
"CustomIntegrator"
,
ss
);
CustomIntegrator
*
intg2
=
dynamic_cast
<
CustomIntegrator
*>
(
XmlSerializer
::
deserialize
<
Integrator
>
(
ss
));
...
...
@@ -190,6 +194,19 @@ void testSerializeCustomIntegrator() {
ASSERT_EQUAL
(
intg
->
getRandomNumberSeed
(),
intg2
->
getRandomNumberSeed
());
ASSERT_EQUAL
(
intg
->
getStepSize
(),
intg2
->
getStepSize
());
ASSERT_EQUAL
(
intg
->
getConstraintTolerance
(),
intg2
->
getConstraintTolerance
());
ASSERT_EQUAL
(
intg
->
getNumTabulatedFunctions
(),
intg2
->
getNumTabulatedFunctions
());
for
(
int
i
=
0
;
i
<
intg
->
getNumTabulatedFunctions
();
i
++
)
{
double
min1
,
min2
,
max1
,
max2
;
vector
<
double
>
val1
,
val2
;
dynamic_cast
<
Continuous1DFunction
&>
(
intg
->
getTabulatedFunction
(
i
)).
getFunctionParameters
(
val1
,
min1
,
max1
);
dynamic_cast
<
Continuous1DFunction
&>
(
intg2
->
getTabulatedFunction
(
i
)).
getFunctionParameters
(
val2
,
min2
,
max2
);
ASSERT_EQUAL
(
intg
->
getTabulatedFunctionName
(
i
),
intg2
->
getTabulatedFunctionName
(
i
));
ASSERT_EQUAL
(
min1
,
min2
);
ASSERT_EQUAL
(
max1
,
max2
);
ASSERT_EQUAL
(
val1
.
size
(),
val2
.
size
());
for
(
int
j
=
0
;
j
<
(
int
)
val1
.
size
();
j
++
)
ASSERT_EQUAL
(
val1
[
j
],
val2
[
j
]);
}
delete
intg
;
delete
intg2
;
}
...
...
serialization/tests/TestSerializeSystem.cpp
View file @
18295108
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors.
*
* Portions copyright (c) 2010
-2017
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -82,6 +82,23 @@ void compareSystems(System& system, System& system2) {
ASSERT_EQUAL
(
0.1
,
site7
.
getWeight12
());
ASSERT_EQUAL
(
0.2
,
site7
.
getWeight13
());
ASSERT_EQUAL
(
0.5
,
site7
.
getWeightCross
());
const
LocalCoordinatesSite
&
site8
=
dynamic_cast
<
const
LocalCoordinatesSite
&>
(
system2
.
getVirtualSite
(
8
));
ASSERT_EQUAL
(
4
,
site8
.
getNumParticles
());
ASSERT_EQUAL
(
4
,
site8
.
getParticle
(
0
));
ASSERT_EQUAL
(
3
,
site8
.
getParticle
(
1
));
ASSERT_EQUAL
(
2
,
site8
.
getParticle
(
2
));
ASSERT_EQUAL
(
1
,
site8
.
getParticle
(
3
));
ASSERT_EQUAL
(
Vec3
(
-
0.5
,
1.0
,
1.5
),
site8
.
getLocalPosition
());
vector
<
double
>
wo
,
wx
,
wy
;
site8
.
getOriginWeights
(
wo
);
site8
.
getXWeights
(
wx
);
site8
.
getYWeights
(
wy
);
vector
<
double
>
woExpected
=
{
0.1
,
0.2
,
0.3
,
0.4
};
vector
<
double
>
wxExpected
=
{
-
1.0
,
0.4
,
0.4
,
0.2
};
vector
<
double
>
wyExpected
=
{
0.3
,
0.7
,
0.0
,
-
1.0
};
ASSERT_EQUAL_CONTAINERS
(
woExpected
,
wo
);
ASSERT_EQUAL_CONTAINERS
(
wxExpected
,
wx
);
ASSERT_EQUAL_CONTAINERS
(
wyExpected
,
wy
);
ASSERT_EQUAL
(
system
.
getNumForces
(),
system2
.
getNumForces
());
for
(
int
i
=
0
;
i
<
system
.
getNumForces
();
i
++
)
ASSERT
(
typeid
(
system
.
getForce
(
i
))
==
typeid
(
system2
.
getForce
(
i
)))
...
...
@@ -93,7 +110,7 @@ void testSerialization() {
System
system
;
for
(
int
i
=
0
;
i
<
5
;
i
++
)
system
.
addParticle
(
0.1
*
i
+
1
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
for
(
int
i
=
0
;
i
<
5
;
i
++
)
system
.
addParticle
(
0.0
);
system
.
addConstraint
(
0
,
1
,
3.0
);
system
.
addConstraint
(
1
,
2
,
2.5
);
...
...
@@ -102,6 +119,7 @@ void testSerialization() {
system
.
setVirtualSite
(
5
,
new
TwoParticleAverageSite
(
0
,
1
,
0.3
,
0.7
));
system
.
setVirtualSite
(
6
,
new
ThreeParticleAverageSite
(
2
,
4
,
3
,
0.5
,
0.2
,
0.3
));
system
.
setVirtualSite
(
7
,
new
OutOfPlaneSite
(
0
,
3
,
1
,
0.1
,
0.2
,
0.5
));
system
.
setVirtualSite
(
8
,
new
LocalCoordinatesSite
({
4
,
3
,
2
,
1
},
{
0.1
,
0.2
,
0.3
,
0.4
},
{
-
1.0
,
0.4
,
0.4
,
0.2
},
{
0.3
,
0.7
,
0.0
,
-
1.0
},
Vec3
(
-
0.5
,
1.0
,
1.5
)));
system
.
addForce
(
new
HarmonicBondForce
());
// Serialize and then deserialize it, then make sure the systems are identical.
...
...
tests/TestCustomCVForce.h
0 → 100644
View file @
18295108
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2017 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#ifdef WIN32
#define _USE_MATH_DEFINES // Needed to get M_PI
#endif
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "openmm/CustomBondForce.h"
#include "openmm/CustomCVForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomNonbondedForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
void
testCVs
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
// Create a CustomCVForce with two collective variables.
CustomCVForce
*
cv
=
new
CustomCVForce
(
"v1+3*v2"
);
system
.
addForce
(
cv
);
CustomBondForce
*
v1
=
new
CustomBondForce
(
"2*r"
);
v1
->
addBond
(
0
,
1
);
cv
->
addCollectiveVariable
(
"v1"
,
v1
);
CustomBondForce
*
v2
=
new
CustomBondForce
(
"r"
);
v2
->
addBond
(
0
,
2
);
cv
->
addCollectiveVariable
(
"v2"
,
v2
);
ASSERT
(
!
cv
->
usesPeriodicBoundaryConditions
());
// Create a context for evaluating it.
VerletIntegrator
integrator
(
1.0
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
3
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1.5
,
0
,
0
);
positions
[
2
]
=
Vec3
(
0
,
0
,
2.5
);
context
.
setPositions
(
positions
);
// Verify the values of the collective variables.
vector
<
double
>
values
;
cv
->
getCollectiveVariableValues
(
context
,
values
);
ASSERT_EQUAL_TOL
(
2
*
1.5
,
values
[
0
],
1e-6
);
ASSERT_EQUAL_TOL
(
2.5
,
values
[
1
],
1e-6
);
// Verify the energy and forces.
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
);
ASSERT_EQUAL_TOL
(
2
*
1.5
+
3
*
2.5
,
state
.
getPotentialEnergy
(),
1e-6
);
ASSERT_EQUAL_VEC
(
Vec3
(
2.0
,
0.0
,
3.0
),
state
.
getForces
()[
0
],
1e-6
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
2.0
,
0.0
,
0.0
),
state
.
getForces
()[
1
],
1e-6
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.0
,
0.0
,
-
3.0
),
state
.
getForces
()[
2
],
1e-6
);
}
void
testEnergyParameterDerivatives
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
// Create a CustomCVForce with one collective variable and two global parameters.
// The CV in turn depends on a global parameter.
CustomCVForce
*
cv
=
new
CustomCVForce
(
"v1*g1+g2"
);
system
.
addForce
(
cv
);
CustomBondForce
*
v1
=
new
CustomBondForce
(
"r*g3"
);
v1
->
addGlobalParameter
(
"g3"
,
2.0
);
v1
->
addEnergyParameterDerivative
(
"g3"
);
v1
->
addBond
(
0
,
1
);
cv
->
addCollectiveVariable
(
"v1"
,
v1
);
cv
->
addGlobalParameter
(
"g1"
,
1.5
);
cv
->
addGlobalParameter
(
"g2"
,
-
1.0
);
cv
->
addEnergyParameterDerivative
(
"g2"
);
cv
->
addEnergyParameterDerivative
(
"g1"
);
// Create a context for evaluating it.
VerletIntegrator
integrator
(
1.0
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
2.0
,
0
,
0
);
context
.
setPositions
(
positions
);
// Verify the energy and parameter derivatives.
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
ParameterDerivatives
);
ASSERT_EQUAL_TOL
(
4.0
*
1.5
-
1.0
,
state
.
getPotentialEnergy
(),
1e-6
);
map
<
string
,
double
>
derivs
=
state
.
getEnergyParameterDerivatives
();
ASSERT_EQUAL_TOL
(
4.0
,
derivs
[
"g1"
],
1e-6
);
ASSERT_EQUAL_TOL
(
1.0
,
derivs
[
"g2"
],
1e-6
);
ASSERT_EQUAL_TOL
(
2.0
*
1.5
,
derivs
[
"g3"
],
1e-6
);
}
void
testTabulatedFunction
()
{
const
int
xsize
=
10
;
const
int
ysize
=
11
;
const
double
xmin
=
0.4
;
const
double
xmax
=
1.1
;
const
double
ymin
=
0.0
;
const
double
ymax
=
0.95
;
System
system
;
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomCVForce
*
cv
=
new
CustomCVForce
(
"fn(x,y)+1"
);
CustomExternalForce
*
v1
=
new
CustomExternalForce
(
"x"
);
v1
->
addParticle
(
0
);
cv
->
addCollectiveVariable
(
"x"
,
v1
);
CustomExternalForce
*
v2
=
new
CustomExternalForce
(
"y"
);
v2
->
addParticle
(
0
);
cv
->
addCollectiveVariable
(
"y"
,
v2
);
vector
<
double
>
table
(
xsize
*
ysize
);
for
(
int
i
=
0
;
i
<
xsize
;
i
++
)
{
for
(
int
j
=
0
;
j
<
ysize
;
j
++
)
{
double
x
=
xmin
+
i
*
(
xmax
-
xmin
)
/
xsize
;
double
y
=
ymin
+
j
*
(
ymax
-
ymin
)
/
ysize
;
table
[
i
+
xsize
*
j
]
=
sin
(
0.25
*
x
)
*
cos
(
0.33
*
y
);
}
}
cv
->
addTabulatedFunction
(
"fn"
,
new
Continuous2DFunction
(
xsize
,
ysize
,
table
,
xmin
,
xmax
,
ymin
,
ymax
));
system
.
addForce
(
cv
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
);
for
(
double
x
=
xmin
-
0.15
;
x
<
xmax
+
0.2
;
x
+=
0.1
)
{
for
(
double
y
=
ymin
-
0.15
;
y
<
ymax
+
0.2
;
y
+=
0.1
)
{
positions
[
0
]
=
Vec3
(
x
,
y
,
1.5
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
double
energy
=
1
;
Vec3
force
(
0
,
0
,
0
);
if
(
x
>=
xmin
&&
x
<=
xmax
&&
y
>=
ymin
&&
y
<=
ymax
)
{
energy
=
sin
(
0.25
*
x
)
*
cos
(
0.33
*
y
)
+
1
;
force
[
0
]
=
-
0.25
*
cos
(
0.25
*
x
)
*
cos
(
0.33
*
y
);
force
[
1
]
=
0.3
*
sin
(
0.25
*
x
)
*
sin
(
0.33
*
y
);
}
ASSERT_EQUAL_VEC
(
force
,
forces
[
0
],
0.1
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.05
);
}
}
}
void
testReordering
()
{
// Create a larger system with a nonbonded force, since that will trigger atom
// reordering on the GPU.
const
int
numParticles
=
100
;
System
system
;
CustomCVForce
*
cv
=
new
CustomCVForce
(
"2*v2"
);
CustomNonbondedForce
*
v1
=
new
CustomNonbondedForce
(
"r"
);
v1
->
addPerParticleParameter
(
"a"
);
CustomBondForce
*
v2
=
new
CustomBondForce
(
"r+1"
);
v2
->
addBond
(
5
,
10
);
cv
->
addCollectiveVariable
(
"v1"
,
v1
);
cv
->
addCollectiveVariable
(
"v2"
,
v2
);
cv
->
setForceGroup
(
2
);
system
.
addForce
(
cv
);
CustomNonbondedForce
*
nb
=
new
CustomNonbondedForce
(
"r^2"
);
nb
->
addPerParticleParameter
(
"a"
);
system
.
addForce
(
nb
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
;
vector
<
double
>
params
(
1
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
params
[
0
]
=
i
%
2
;
v1
->
addParticle
(
params
);
params
[
0
]
=
(
i
<
numParticles
/
2
?
2.0
:
3.0
);
nb
->
addParticle
(
params
);
positions
.
push_back
(
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
))
*
10
);
}
// Make sure it works correctly.
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Energy
|
State
::
Forces
,
false
,
1
<<
2
);
Vec3
delta
=
positions
[
5
]
-
positions
[
10
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
ASSERT_EQUAL_TOL
(
2
*
(
r
+
1
),
state
.
getPotentialEnergy
(),
1e-5
);
ASSERT_EQUAL_VEC
(
-
delta
*
2
/
r
,
state
.
getForces
()[
5
],
1e-5
);
ASSERT_EQUAL_VEC
(
delta
*
2
/
r
,
state
.
getForces
()[
10
],
1e-5
);
}
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
initializeTests
(
argc
,
argv
);
testCVs
();
testEnergyParameterDerivatives
();
testTabulatedFunction
();
testReordering
();
runPlatformTests
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
tests/TestCustomGBForce.h
View file @
18295108
...
...
@@ -118,6 +118,7 @@ void testOBC(GBSAOBCForce::NonbondedMethod obcMethod, CustomGBForce::NonbondedMe
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
custom
->
addExclusion
(
2
*
i
,
2
*
i
+
1
);
positions
[
2
*
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
positions
[
2
*
i
+
1
]
=
Vec3
(
positions
[
2
*
i
][
0
]
+
1.0
,
positions
[
2
*
i
][
1
],
positions
[
2
*
i
][
2
]);
velocities
[
2
*
i
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
...
...
tests/TestCustomHbondForce.h
View file @
18295108
...
...
@@ -244,6 +244,33 @@ void testIllegalVariable() {
ASSERT
(
threwException
);
}
void
testParameters
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomHbondForce
*
custom
=
new
CustomHbondForce
(
"(2*d+a)*distance(d1,a1)"
);
custom
->
addPerDonorParameter
(
"d"
);
custom
->
addPerAcceptorParameter
(
"a"
);
custom
->
addDonor
(
1
,
0
,
-
1
,
vector
<
double
>
({
1.5
}));
custom
->
addDonor
(
2
,
0
,
-
1
,
vector
<
double
>
({
1.8
}));
custom
->
addAcceptor
(
0
,
1
,
-
1
,
vector
<
double
>
({
2.1
}));
system
.
addForce
(
custom
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
3
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
2
,
0
);
positions
[
2
]
=
Vec3
(
2
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
((
2
*
1.8
+
2.1
),
(
2
*
1.5
+
2.1
),
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
(
2
*
1.5
+
2.1
),
0
),
forces
[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
(
2
*
1.8
+
2.1
),
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_TOL
(
2
*
(
2
*
1.8
+
2.1
)
+
2
*
(
2
*
1.5
+
2.1
),
state
.
getPotentialEnergy
(),
TOL
);
}
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
@@ -254,6 +281,7 @@ int main(int argc, char* argv[]) {
testCutoff
();
testCustomFunctions
();
testIllegalVariable
();
testParameters
();
runPlatformTests
();
}
catch
(
const
exception
&
e
)
{
...
...
tests/TestCustomIntegrator.h
View file @
18295108
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-201
6
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
7
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -37,8 +37,10 @@
#include "openmm/AndersenThermostat.h"
#include "openmm/CustomAngleForce.h"
#include "openmm/CustomBondForce.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/CustomIntegrator.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/MonteCarloBarostat.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "SimTKOpenMMRealType.h"
...
...
@@ -895,6 +897,128 @@ void testChangeDT() {
}
}
/**
* Test an integrator that uses a tabulated function.
*/
void
testTabulatedFunction
()
{
System
system
;
system
.
addParticle
(
1.0
);
CustomIntegrator
integrator
(
1.0
);
integrator
.
addGlobalVariable
(
"global"
,
1.5
);
integrator
.
addPerDofVariable
(
"dof"
,
0.0
);
integrator
.
addComputeGlobal
(
"global"
,
"fn(global)"
);
integrator
.
addComputePerDof
(
"dof"
,
"fn(x)"
);
vector
<
double
>
table
;
table
.
push_back
(
10.0
);
table
.
push_back
(
20.0
);
integrator
.
addTabulatedFunction
(
"fn"
,
new
Continuous1DFunction
(
table
,
1.0
,
2.0
));
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
);
positions
[
0
]
=
Vec3
(
1.2
,
1.3
,
1.4
);
context
.
setPositions
(
positions
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
15.0
,
integrator
.
getGlobalVariable
(
0
),
1e-5
);
vector
<
Vec3
>
values
;
integrator
.
getPerDofVariable
(
0
,
values
);
ASSERT_EQUAL_VEC
(
Vec3
(
12.0
,
13.0
,
14.0
),
values
[
0
],
1e-5
);
}
/**
* Test an integrator that alternates repeatedly between force groups.
*/
void
testAlternatingGroups
()
{
System
system
;
system
.
addParticle
(
1.0
);
CustomExternalForce
*
force1
=
new
CustomExternalForce
(
"-0.5*x"
);
force1
->
addParticle
(
0
);
system
.
addForce
(
force1
);
CustomExternalForce
*
force2
=
new
CustomExternalForce
(
"-0.8*y"
);
force2
->
addParticle
(
0
);
force2
->
setForceGroup
(
1
);
system
.
addForce
(
force2
);
CustomIntegrator
integrator
(
0.5
);
integrator
.
addGlobalVariable
(
"savede1"
,
0.0
);
integrator
.
addGlobalVariable
(
"savede2"
,
0.0
);
integrator
.
addGlobalVariable
(
"savede3"
,
0.0
);
integrator
.
addGlobalVariable
(
"savede4"
,
0.0
);
integrator
.
addPerDofVariable
(
"savedf1"
,
0.0
);
integrator
.
addPerDofVariable
(
"savedf2"
,
0.0
);
integrator
.
addPerDofVariable
(
"savedf3"
,
0.0
);
integrator
.
addPerDofVariable
(
"savedf4"
,
0.0
);
integrator
.
addComputeGlobal
(
"savede1"
,
"energy0"
);
integrator
.
addComputeGlobal
(
"savede2"
,
"energy1"
);
integrator
.
addComputePerDof
(
"savedf1"
,
"f0"
);
integrator
.
addComputePerDof
(
"savedf2"
,
"f1"
);
integrator
.
addComputeGlobal
(
"savede3"
,
"energy0"
);
integrator
.
addComputeGlobal
(
"savede4"
,
"energy1"
);
integrator
.
addComputePerDof
(
"savedf3"
,
"f0"
);
integrator
.
addComputePerDof
(
"savedf4"
,
"f1"
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
);
positions
[
0
]
=
Vec3
(
1
,
2
,
3
);
context
.
setPositions
(
positions
);
integrator
.
step
(
1
);
vector
<
Vec3
>
f
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
ASSERT_EQUAL_TOL
(
-
0.5
*
1
,
integrator
.
getGlobalVariable
(
2
*
i
),
1e-5
);
ASSERT_EQUAL_TOL
(
-
0.8
*
2
,
integrator
.
getGlobalVariable
(
2
*
i
+
1
),
1e-5
);
integrator
.
getPerDofVariable
(
2
*
i
,
f
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.5
,
0
,
0
),
f
[
0
],
1e-5
);
integrator
.
getPerDofVariable
(
2
*
i
+
1
,
f
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0.8
,
0
),
f
[
0
],
1e-5
);
}
}
/**
* Test that the forces are recomputed when updateContextState() modifies positions.
*/
void
testUpdateContextState
()
{
const
int
numParticles
=
100
;
const
double
boxSize
=
5.0
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
CustomIntegrator
integrator
(
0.003
);
integrator
.
addPerDofVariable
(
"force1"
,
0.0
);
integrator
.
addPerDofVariable
(
"force2"
,
0.0
);
integrator
.
addComputePerDof
(
"force1"
,
"f"
);
integrator
.
addUpdateContextState
();
integrator
.
addComputePerDof
(
"force2"
,
"f"
);
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
2.0
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
nonbonded
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
nonbonded
);
system
.
addForce
(
new
MonteCarloBarostat
(
1.0
,
300.0
,
1
));
Context
context
(
system
,
integrator
,
platform
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
positions
[
i
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
))
*
boxSize
;
context
.
setPositions
(
positions
);
// Make sure the forces change when the barostat accepts a step, and don't change
// otherwise.
for
(
int
i
=
0
;
i
<
50
;
i
++
)
{
State
state1
=
context
.
getState
(
0
);
integrator
.
step
(
1
);
State
state2
=
context
.
getState
(
0
);
bool
changed
=
(
state1
.
getPeriodicBoxVolume
()
!=
state2
.
getPeriodicBoxVolume
());
vector
<
Vec3
>
f1
,
f2
;
integrator
.
getPerDofVariable
(
0
,
f1
);
integrator
.
getPerDofVariable
(
1
,
f2
);
bool
different
=
false
;
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
if
(
f1
[
j
]
!=
f2
[
j
])
different
=
true
;
ASSERT_EQUAL
(
changed
,
different
);
}
}
void
runPlatformTests
();
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
@@ -917,6 +1041,9 @@ int main(int argc, char* argv[]) {
testChangingGlobal
();
testEnergyParameterDerivatives
();
testChangeDT
();
testTabulatedFunction
();
testAlternatingGroups
();
testUpdateContextState
();
runPlatformTests
();
}
catch
(
const
exception
&
e
)
{
...
...
tests/TestVirtualSites.h
View file @
18295108
...
...
@@ -206,30 +206,51 @@ void testOutOfPlane() {
}
}
Vec3
computeWeightedPosition
(
const
vector
<
Vec3
>&
positions
,
const
vector
<
double
>&
weights
)
{
Vec3
sum
;
for
(
int
i
=
0
;
i
<
weights
.
size
();
i
++
)
sum
+=
positions
[
i
]
*
weights
[
i
];
return
sum
;
}
/**
* Test a LocalCoordinatesSite virtual site.
*/
void
testLocalCoordinates
()
{
const
Vec3
originWeights
(
0.2
,
0.3
,
0.5
);
const
Vec3
xWeights
(
-
1.0
,
0.5
,
0.5
);
const
Vec3
yWeights
(
0.0
,
-
1.0
,
1.0
);
void
testLocalCoordinates
(
int
numSiteParticles
)
{
vector
<
int
>
particles
;
vector
<
double
>
originWeights
,
xWeights
,
yWeights
;
if
(
numSiteParticles
==
2
)
{
particles
=
{
0
,
1
};
originWeights
=
{
0.4
,
0.6
};
xWeights
=
{
-
1.0
,
1.0
};
yWeights
=
{
1.0
,
-
1.0
};
}
else
if
(
numSiteParticles
==
3
)
{
particles
=
{
0
,
1
,
2
};
originWeights
=
{
0.2
,
0.3
,
0.5
};
xWeights
=
{
-
1.0
,
0.5
,
0.5
};
yWeights
=
{
0.0
,
-
1.0
,
1.0
};
}
else
if
(
numSiteParticles
==
4
)
{
particles
=
{
0
,
1
,
2
,
3
};
originWeights
=
{
0.2
,
0.3
,
0.1
,
0.4
};
xWeights
=
{
-
1.0
,
0.3
,
0.3
,
0.4
};
yWeights
=
{
0.5
,
0.5
,
-
0.5
,
-
0.5
};
}
const
Vec3
localPosition
(
0.4
,
0.3
,
0.2
);
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
for
(
int
i
=
0
;
i
<
numSiteParticles
;
i
++
)
system
.
addParticle
(
1.0
);
system
.
addParticle
(
0.0
);
system
.
setVirtualSite
(
3
,
new
LocalCoordinatesSite
(
0
,
1
,
2
,
originWeights
,
xWeights
,
yWeights
,
localPosition
));
system
.
setVirtualSite
(
numSiteParticles
,
new
LocalCoordinatesSite
(
particles
,
originWeights
,
xWeights
,
yWeights
,
localPosition
));
CustomExternalForce
*
forceField
=
new
CustomExternalForce
(
"2*x^2+3*y^2+4*z^2"
);
system
.
addForce
(
forceField
);
vector
<
double
>
params
;
forceField
->
addParticle
(
0
,
params
);
forceField
->
addParticle
(
1
,
params
);
forceField
->
addParticle
(
2
,
params
);
forceField
->
addParticle
(
3
,
params
);
for
(
int
i
=
0
;
i
<
numSiteParticles
+
1
;
i
++
)
forceField
->
addParticle
(
0
,
params
);
LangevinIntegrator
integrator
(
300.0
,
0.1
,
0.002
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
4
),
positions2
(
4
),
positions3
(
4
);
vector
<
Vec3
>
positions
(
numSiteParticles
+
1
),
positions2
(
numSiteParticles
+
1
),
positions3
(
numSiteParticles
+
1
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
...
...
@@ -237,12 +258,12 @@ void testLocalCoordinates() {
Vec3
xdir
,
ydir
,
zdir
;
do
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
for
(
int
j
=
0
;
j
<
numSiteParticles
;
j
++
)
positions
[
j
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
xdir
=
positions
[
0
]
*
xWeights
[
0
]
+
positions
[
1
]
*
xWeights
[
1
]
+
positions
[
2
]
*
xWeights
[
2
]
;
ydir
=
positions
[
0
]
*
yWeights
[
0
]
+
positions
[
1
]
*
yWeights
[
1
]
+
positions
[
2
]
*
yWeights
[
2
]
;
xdir
=
computeWeightedPosition
(
positions
,
xWeights
)
;
ydir
=
computeWeightedPosition
(
positions
,
yWeights
);
;
zdir
=
xdir
.
cross
(
ydir
);
if
(
sqrt
(
xdir
.
dot
(
xdir
))
>
0.1
&&
sqrt
(
ydir
.
dot
(
ydir
))
>
0.1
&&
sqrt
(
zdir
.
dot
(
zdir
))
>
0.1
)
if
(
sqrt
(
xdir
.
dot
(
xdir
))
>
0.1
&&
(
numSiteParticles
==
2
||
(
sqrt
(
ydir
.
dot
(
ydir
))
>
0.1
&&
sqrt
(
zdir
.
dot
(
zdir
))
>
0.1
)
))
break
;
// These positions give a reasonable coordinate system.
}
while
(
true
);
context
.
setPositions
(
positions
);
...
...
@@ -252,23 +273,23 @@ void testLocalCoordinates() {
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Forces
);
const
vector
<
Vec3
>&
pos
=
state
.
getPositions
();
Vec3
origin
=
pos
[
0
]
*
originWeights
[
0
]
+
pos
[
1
]
*
originWeights
[
1
]
+
pos
[
2
]
*
originWeights
[
2
]
;
Vec3
origin
=
computeWeightedPosition
(
pos
,
originWeights
);
;
xdir
/=
sqrt
(
xdir
.
dot
(
xdir
));
zdir
/=
sqrt
(
zdir
.
dot
(
zdir
));
ydir
=
zdir
.
cross
(
xdir
);
ASSERT_EQUAL_VEC
(
origin
+
xdir
*
localPosition
[
0
]
+
ydir
*
localPosition
[
1
]
+
zdir
*
localPosition
[
2
],
pos
[
3
],
1e-5
);
ASSERT_EQUAL_VEC
(
origin
+
xdir
*
localPosition
[
0
]
+
ydir
*
localPosition
[
1
]
+
zdir
*
localPosition
[
2
],
pos
[
numSiteParticles
],
1e-5
);
// Take a small step in the direction of the energy gradient and see whether the potential energy changes by the expected amount.
double
norm
=
0.0
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
for
(
int
i
=
0
;
i
<
numSiteParticles
;
++
i
)
{
Vec3
f
=
state
.
getForces
()[
i
];
norm
+=
f
[
0
]
*
f
[
0
]
+
f
[
1
]
*
f
[
1
]
+
f
[
2
]
*
f
[
2
];
}
norm
=
std
::
sqrt
(
norm
);
const
double
delta
=
1e-2
;
double
step
=
0.5
*
delta
/
norm
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
for
(
int
i
=
0
;
i
<
numSiteParticles
;
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
state
.
getForces
()[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
...
...
@@ -469,7 +490,9 @@ int main(int argc, char* argv[]) {
testTwoParticleAverage
();
testThreeParticleAverage
();
testOutOfPlane
();
testLocalCoordinates
();
testLocalCoordinates
(
2
);
testLocalCoordinates
(
3
);
testLocalCoordinates
(
4
);
testConservationLaws
();
testOverlappingSites
();
runPlatformTests
();
...
...
wrappers/generateWrappers.py
View file @
18295108
...
...
@@ -68,7 +68,15 @@ class WrapperGenerator:
def
__init__
(
self
,
inputDirname
,
output
):
self
.
skipClasses
=
[
'OpenMM::Vec3'
,
'OpenMM::XmlSerializer'
,
'OpenMM::Kernel'
,
'OpenMM::KernelImpl'
,
'OpenMM::KernelFactory'
,
'OpenMM::ContextImpl'
,
'OpenMM::SerializationNode'
,
'OpenMM::SerializationProxy'
]
self
.
skipMethods
=
[
'OpenMM::Context::getState'
,
'OpenMM::Platform::loadPluginsFromDirectory'
,
'OpenMM::Platform::getPluginLoadFailures'
,
'OpenMM::Context::createCheckpoint'
,
'OpenMM::Context::loadCheckpoint'
,
'OpenMM::Context::getMolecules'
]
self
.
skipMethods
=
[
'State OpenMM::Context::getState'
,
'void OpenMM::Context::createCheckpoint'
,
'void OpenMM::Context::loadCheckpoint'
,
'const std::vector<std::vector<int> >& OpenMM::Context::getMolecules'
,
'static std::vector<std::string> OpenMM::Platform::getPluginLoadFailures'
,
'static std::vector<std::string> OpenMM::Platform::loadPluginsFromDirectory'
,
'Vec3 OpenMM::LocalCoordinatesSite::getOriginWeights'
,
'Vec3 OpenMM::LocalCoordinatesSite::getXWeights'
,
'Vec3 OpenMM::LocalCoordinatesSite::getYWeights'
]
self
.
hideClasses
=
[
'Kernel'
,
'KernelImpl'
,
'KernelFactory'
,
'ContextImpl'
,
'SerializationNode'
,
'SerializationProxy'
]
self
.
nodeByID
=
{}
...
...
@@ -119,9 +127,7 @@ class WrapperGenerator:
for
section
in
findNodes
(
classNode
,
"sectiondef"
,
kind
=
"public-static-func"
)
+
findNodes
(
classNode
,
"sectiondef"
,
kind
=
"public-func"
):
for
memberNode
in
findNodes
(
section
,
"memberdef"
,
kind
=
"function"
,
prot
=
"public"
):
methodDefinition
=
getText
(
"definition"
,
memberNode
)
shortMethodDefinition
=
stripOpenMMPrefix
(
methodDefinition
)
methodName
=
shortMethodDefinition
.
split
()[
-
1
]
if
className
+
'::'
+
methodName
in
self
.
skipMethods
:
if
methodDefinition
in
self
.
skipMethods
:
continue
methodList
.
append
(
memberNode
)
return
methodList
...
...
wrappers/python/simtk/openmm/app/amberprmtopfile.py
View file @
18295108
...
...
@@ -161,7 +161,7 @@ class AmberPrmtopFile(object):
implicitSolventKappa
=
None
,
temperature
=
298.15
*
u
.
kelvin
,
soluteDielectric
=
1.0
,
solventDielectric
=
78.5
,
removeCMMotion
=
True
,
hydrogenMass
=
None
,
ewaldErrorTolerance
=
0.0005
,
switchDistance
=
0.0
*
u
.
nanometer
):
switchDistance
=
0.0
*
u
.
nanometer
,
gbsaModel
=
'ACE'
):
"""Construct an OpenMM System representing the topology described by this
prmtop file.
...
...
@@ -208,6 +208,11 @@ class AmberPrmtopFile(object):
turned on for Lennard-Jones interactions. If the switchDistance is 0
or evaluates to boolean False, no switching function will be used.
Values greater than nonbondedCutoff or less than 0 raise ValueError
gbsaModel : str='ACE'
The SA model used to model the nonpolar solvation component of GB
implicit solvent models. If GB is active, this must be 'ACE' or None
(the latter indicates no SA model will be used). Other values will
result in a ValueError
Returns
-------
...
...
@@ -273,7 +278,7 @@ class AmberPrmtopFile(object):
nonbondedCutoff
=
nonbondedCutoff
,
nonbondedMethod
=
methodMap
[
nonbondedMethod
],
flexibleConstraints
=
False
,
gbmodel
=
implicitString
,
soluteDielectric
=
soluteDielectric
,
solventDielectric
=
solventDielectric
,
implicitSolventKappa
=
implicitSolventKappa
,
rigidWater
=
rigidWater
,
elements
=
self
.
elements
)
rigidWater
=
rigidWater
,
elements
=
self
.
elements
,
gbsaModel
=
gbsaModel
)
if
hydrogenMass
is
not
None
:
for
atom1
,
atom2
in
self
.
topology
.
bonds
():
...
...
wrappers/python/simtk/openmm/app/charmmpsffile.py
View file @
18295108
...
...
@@ -117,22 +117,23 @@ class CharmmPsfFile(object):
This structure has numerous attributes that are lists of the elements of
this structure, including atoms, bonds, torsions, etc. The attributes are
- residue_list
- atom_list
- bond_list
- angle_list
- dihedral_list
- dihedral_parameter_list
- improper_list
- cmap_list
- donor_list # hbonds donors?
- acceptor_list # hbond acceptors?
- group_list # list of nonbonded interaction groups
- residue_list
- atom_list
- bond_list
- angle_list
- dihedral_list
- dihedral_parameter_list
- improper_list
- cmap_list
- donor_list # hbonds donors?
- acceptor_list # hbond acceptors?
- group_list # list of nonbonded interaction groups
Additional attribute is available if a CharmmParameterSet is loaded into
this structure.
- urey_bradley_list
- urey_bradley_list
The lengths of each of these lists gives the pointers (e.g., natom, nres,
etc.)
...
...
@@ -678,7 +679,8 @@ class CharmmPsfFile(object):
hydrogenMass
=
None
,
ewaldErrorTolerance
=
0.0005
,
flexibleConstraints
=
True
,
verbose
=
False
):
verbose
=
False
,
gbsaModel
=
None
):
"""Construct an OpenMM System representing the topology described by the
prmtop file. You MUST have loaded a parameter set into this PSF before
calling createSystem. If not, AttributeError will be raised. ValueError
...
...
@@ -712,7 +714,7 @@ class CharmmPsfFile(object):
solvent.
implicitSolventSaltConc : float=0.0*u.moles/u.liter
Salt concentration for GB simulations. Converted to Debye length
`kappa
'
`
`kappa
``
temperature : float=298.15*u.kelvin
Temperature used in the salt concentration-to-kappa conversion for
GB salt concentration term
...
...
@@ -733,10 +735,16 @@ class CharmmPsfFile(object):
Are our constraints flexible or not?
verbose : bool=False
Optionally prints out a running progress report
gbsaModel : str=None
Can be ACE (to use the ACE solvation model) or None. Other values
raise a ValueError
"""
# Load the parameter set
self
.
loadParameters
(
params
.
condense
())
hasbox
=
self
.
topology
.
getUnitCellDimensions
()
is
not
None
# Check GB input parameters
if
implicitSolvent
is
not
None
and
gbsaModel
not
in
(
'ACE'
,
None
):
raise
ValueError
(
'gbsaModel must be ACE or None'
)
# Set the cutoff distance in nanometers
cutoff
=
None
if
nonbondedMethod
is
not
ff
.
NoCutoff
:
...
...
@@ -906,8 +914,10 @@ class CharmmPsfFile(object):
if
verbose
:
print
(
'Adding impropers...'
)
# Ick. OpenMM does not have an improper torsion class. Need to
# construct one from CustomTorsionForce
force
=
mm
.
CustomTorsionForce
(
'k*(theta-theta0)^2'
)
# construct one from CustomTorsionForce that respects toroidal boundaries
energy_function
=
'k*min(dtheta, 2*pi-dtheta)^2; dtheta = abs(theta-theta0);'
energy_function
+=
'pi = %f;'
%
pi
force
=
mm
.
CustomTorsionForce
(
energy_function
)
force
.
addPerTorsionParameter
(
'k'
)
force
.
addPerTorsionParameter
(
'theta0'
)
force
.
setForceGroup
(
self
.
IMPROPER_FORCE_GROUP
)
...
...
@@ -1189,19 +1199,19 @@ class CharmmPsfFile(object):
implicitSolventKappa
=
implicitSolventKappa
.
value_in_unit
(
(
1.0
/
u
.
nanometer
).
unit
)
if
implicitSolvent
is
HCT
:
gb
=
GBSAHCTForce
(
solventDielectric
,
soluteDielectric
,
None
,
gb
=
GBSAHCTForce
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
kappa
=
implicitSolventKappa
)
elif
implicitSolvent
is
OBC1
:
gb
=
GBSAOBC1Force
(
solventDielectric
,
soluteDielectric
,
None
,
gb
=
GBSAOBC1Force
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
kappa
=
implicitSolventKappa
)
elif
implicitSolvent
is
OBC2
:
gb
=
GBSAOBC2Force
(
solventDielectric
,
soluteDielectric
,
None
,
gb
=
GBSAOBC2Force
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
kappa
=
implicitSolventKappa
)
elif
implicitSolvent
is
GBn
:
gb
=
GBSAGBnForce
(
solventDielectric
,
soluteDielectric
,
None
,
gb
=
GBSAGBnForce
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
kappa
=
implicitSolventKappa
)
elif
implicitSolvent
is
GBn2
:
gb
=
GBSAGBn2Force
(
solventDielectric
,
soluteDielectric
,
None
,
gb
=
GBSAGBn2Force
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
kappa
=
implicitSolventKappa
)
gb_parms
=
gb
.
getStandardParameters
(
self
.
topology
)
for
atom
,
gb_parm
in
zip
(
self
.
atom_list
,
gb_parms
):
...
...
wrappers/python/simtk/openmm/app/dcdreporter.py
View file @
18295108
...
...
@@ -57,7 +57,7 @@ class DCDReporter(object):
self
.
_reportInterval
=
reportInterval
self
.
_append
=
append
if
append
:
mode
=
'
a
+b'
mode
=
'
r
+b'
else
:
mode
=
'wb'
self
.
_out
=
open
(
file
,
mode
)
...
...
wrappers/python/simtk/openmm/app/forcefield.py
View file @
18295108
...
...
@@ -47,6 +47,16 @@ from . import element as elem
from
simtk.openmm.app
import
Topology
from
simtk.openmm.app.internal.singleton
import
Singleton
# Directories from which to load built in force fields.
_dataDirectories
=
[
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'data'
)]
try
:
from
pkg_resources
import
iter_entry_points
for
entry
in
iter_entry_points
(
group
=
'openmm.forcefielddir'
):
_dataDirectories
.
append
(
entry
.
load
()())
except
:
pass
# pkg_resources is not installed
def
_convertParameterToNumber
(
param
):
if
unit
.
is_quantity
(
param
):
if
param
.
unit
.
is_compatible
(
unit
.
bar
):
...
...
@@ -186,11 +196,16 @@ class ForceField(object):
trees
=
[]
for
file
in
files
:
tree
=
None
try
:
# this handles either filenames or open file-like objects
tree
=
etree
.
parse
(
file
)
except
IOError
:
tree
=
etree
.
parse
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'data'
,
file
))
for
dataDir
in
_dataDirectories
:
f
=
os
.
path
.
join
(
dataDir
,
file
)
if
os
.
path
.
isfile
(
f
):
tree
=
etree
.
parse
(
f
)
break
except
Exception
as
e
:
# Fail with an error message about which file could not be read.
# TODO: Also handle case where fallback to 'data' directory encounters problems,
...
...
@@ -202,9 +217,24 @@ class ForceField(object):
filename
=
str
(
file
)
msg
+=
"ForceField.loadFile() encountered an error reading file '%s'
\n
"
%
filename
raise
Exception
(
msg
)
if
tree
is
None
:
raise
ValueError
(
'Could not locate file "%s"'
%
file
)
trees
.
append
(
tree
)
# Process includes.
for
parentFile
,
tree
in
zip
(
files
,
trees
):
if
isinstance
(
parentFile
,
str
):
parentDir
=
os
.
path
.
dirname
(
parentFile
)
else
:
parentDir
=
''
for
include
in
tree
.
getroot
().
findall
(
'Include'
):
includeFile
=
include
.
attrib
[
'file'
]
joined
=
os
.
path
.
join
(
parentDir
,
includeFile
)
if
os
.
path
.
isfile
(
joined
):
includeFile
=
joined
self
.
loadFile
(
includeFile
)
# Load the atom types.
...
...
@@ -415,17 +445,19 @@ class ForceField(object):
generator : function
A function that will be called when a residue is encountered that does not match an existing forcefield template.
When a residue without a template is encountered, the `generator` function is called with:
When a residue without a template is encountered, the
`
`generator`
`
function is called with:
::
success = generator(forcefield, residue)
```
where `forcefield` is the calling `ForceField` object and `residue` is a simtk.openmm.app.topology.Residue object.
where ``forcefield`` is the calling ``ForceField`` object and ``residue`` is a simtk.openmm.app.topology.Residue object.
``generator`` must conform to the following API:
`generator` must conform to the following API:
::
Parameters
generator API
Parameters
----------
forcefield : simtk.openmm.app.ForceField
The ForceField object to which residue templates and/or parameters are to be added.
...
...
@@ -508,6 +540,7 @@ class ForceField(object):
def
__init__
(
self
):
self
.
atomType
=
{}
self
.
atomParameters
=
{}
self
.
atomTemplateIndexes
=
{}
self
.
atoms
=
[]
self
.
excludeAtomWith
=
[]
self
.
virtualSites
=
{}
...
...
@@ -535,6 +568,7 @@ class ForceField(object):
for
atom
,
match
in
zip
(
residue
.
atoms
(),
matches
):
self
.
atomType
[
atom
]
=
template
.
atoms
[
match
].
type
self
.
atomParameters
[
atom
]
=
template
.
atoms
[
match
].
parameters
self
.
atomTemplateIndexes
[
atom
]
=
match
for
site
in
template
.
virtualSites
:
if
match
==
site
.
index
:
self
.
virtualSites
[
atom
]
=
(
site
,
[
matchAtoms
[
i
].
index
for
i
in
site
.
atoms
],
matchAtoms
[
site
.
excludeWith
].
index
)
...
...
@@ -615,10 +649,15 @@ class ForceField(object):
numAtoms
=
3
self
.
weights
=
[
float
(
attrib
[
'weight12'
]),
float
(
attrib
[
'weight13'
]),
float
(
attrib
[
'weightCross'
])]
elif
self
.
type
==
'localCoords'
:
numAtoms
=
3
self
.
originWeights
=
[
float
(
attrib
[
'wo1'
]),
float
(
attrib
[
'wo2'
]),
float
(
attrib
[
'wo3'
])]
self
.
xWeights
=
[
float
(
attrib
[
'wx1'
]),
float
(
attrib
[
'wx2'
]),
float
(
attrib
[
'wx3'
])]
self
.
yWeights
=
[
float
(
attrib
[
'wy1'
]),
float
(
attrib
[
'wy2'
]),
float
(
attrib
[
'wy3'
])]
numAtoms
=
0
self
.
originWeights
=
[]
self
.
xWeights
=
[]
self
.
yWeights
=
[]
while
(
'wo%d'
%
(
numAtoms
+
1
))
in
attrib
:
numAtoms
+=
1
self
.
originWeights
.
append
(
float
(
attrib
[
'wo%d'
%
numAtoms
]))
self
.
xWeights
.
append
(
float
(
attrib
[
'wx%d'
%
numAtoms
]))
self
.
yWeights
.
append
(
float
(
attrib
[
'wy%d'
%
numAtoms
]))
self
.
localPos
=
[
float
(
attrib
[
'p1'
]),
float
(
attrib
[
'p2'
]),
float
(
attrib
[
'p3'
])]
else
:
raise
ValueError
(
'Unknown virtual site type: %s'
%
self
.
type
)
...
...
@@ -1003,6 +1042,8 @@ class ForceField(object):
not terminated properly. This option can create ambiguities where multiple
templates match the same residue. If that happens, use the residueTemplates
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
Arbitrary additional keyword arguments may also be specified.
This allows extra parameters to be specified that are specific to
...
...
@@ -1108,9 +1149,9 @@ class ForceField(object):
if
not
unit
.
is_quantity
(
hydrogenMass
):
hydrogenMass
*=
unit
.
dalton
for
atom1
,
atom2
in
topology
.
bonds
():
if
atom1
.
element
==
elem
.
hydrogen
:
if
atom1
.
element
is
elem
.
hydrogen
:
(
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
)
sys
.
setParticleMass
(
atom2
.
index
,
hydrogenMass
)
sys
.
setParticleMass
(
atom1
.
index
,
sys
.
getParticleMass
(
atom1
.
index
)
-
transferMass
)
...
...
@@ -1176,7 +1217,7 @@ class ForceField(object):
for
bond
in
data
.
bonds
:
atom1
=
data
.
atoms
[
bond
.
atom1
]
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
:
for
bond
in
data
.
bonds
:
atom1
=
data
.
atoms
[
bond
.
atom1
]
...
...
@@ -1192,11 +1233,11 @@ class ForceField(object):
atom2
=
data
.
atoms
[
angle
[
1
]]
atom3
=
data
.
atoms
[
angle
[
2
]]
numH
=
0
if
atom1
.
name
.
startswith
(
'H'
)
:
if
atom1
.
element
is
elem
.
hydrogen
:
numH
+=
1
if
atom3
.
name
.
startswith
(
'H'
)
:
if
atom3
.
element
is
elem
.
hydrogen
:
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
:
data
.
isAngleConstrained
=
len
(
data
.
angles
)
*
[
False
]
if
rigidWater
:
...
...
@@ -1221,11 +1262,7 @@ class ForceField(object):
elif
site
.
type
==
'outOfPlane'
:
sys
.
setVirtualSite
(
index
,
mm
.
OutOfPlaneSite
(
atoms
[
0
],
atoms
[
1
],
atoms
[
2
],
site
.
weights
[
0
],
site
.
weights
[
1
],
site
.
weights
[
2
]))
elif
site
.
type
==
'localCoords'
:
sys
.
setVirtualSite
(
index
,
mm
.
LocalCoordinatesSite
(
atoms
[
0
],
atoms
[
1
],
atoms
[
2
],
mm
.
Vec3
(
site
.
originWeights
[
0
],
site
.
originWeights
[
1
],
site
.
originWeights
[
2
]),
mm
.
Vec3
(
site
.
xWeights
[
0
],
site
.
xWeights
[
1
],
site
.
xWeights
[
2
]),
mm
.
Vec3
(
site
.
yWeights
[
0
],
site
.
yWeights
[
1
],
site
.
yWeights
[
2
]),
mm
.
Vec3
(
site
.
localPos
[
0
],
site
.
localPos
[
1
],
site
.
localPos
[
2
])))
sys
.
setVirtualSite
(
index
,
mm
.
LocalCoordinatesSite
(
atoms
,
site
.
originWeights
,
site
.
xWeights
,
site
.
yWeights
,
site
.
localPos
))
# Add forces to the System
...
...
@@ -1704,6 +1741,108 @@ def _createResidueTemplate(residue):
template
.
addExternalBondByName
(
atom2
.
name
)
return
template
def
_matchImproper
(
data
,
torsion
,
generator
):
type1
=
data
.
atomType
[
data
.
atoms
[
torsion
[
0
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
torsion
[
1
]]]
type3
=
data
.
atomType
[
data
.
atoms
[
torsion
[
2
]]]
type4
=
data
.
atomType
[
data
.
atoms
[
torsion
[
3
]]]
wildcard
=
generator
.
ff
.
_atomClasses
[
''
]
match
=
None
for
tordef
in
generator
.
improper
:
types1
=
tordef
.
types1
types2
=
tordef
.
types2
types3
=
tordef
.
types3
types4
=
tordef
.
types4
hasWildcard
=
(
wildcard
in
(
types1
,
types2
,
types3
,
types4
))
if
match
is
not
None
and
hasWildcard
:
# Prefer specific definitions over ones with wildcards
continue
if
type1
in
types1
:
for
(
t2
,
t3
,
t4
)
in
itertools
.
permutations
(((
type2
,
1
),
(
type3
,
2
),
(
type4
,
3
))):
if
t2
[
0
]
in
types2
and
t3
[
0
]
in
types3
and
t4
[
0
]
in
types4
:
if
tordef
.
ordering
==
'default'
:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1
=
torsion
[
t2
[
1
]]
a2
=
torsion
[
t3
[
1
]]
e1
=
data
.
atoms
[
a1
].
element
e2
=
data
.
atoms
[
a2
].
element
if
e1
==
e2
and
a1
>
a2
:
(
a1
,
a2
)
=
(
a2
,
a1
)
elif
e1
!=
elem
.
carbon
and
(
e2
==
elem
.
carbon
or
e1
.
mass
<
e2
.
mass
):
(
a1
,
a2
)
=
(
a2
,
a1
)
match
=
(
a1
,
a2
,
torsion
[
0
],
torsion
[
t4
[
1
]],
tordef
)
break
elif
tordef
.
ordering
==
'charmm'
:
if
hasWildcard
:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1
=
torsion
[
t2
[
1
]]
a2
=
torsion
[
t3
[
1
]]
e1
=
data
.
atoms
[
a1
].
element
e2
=
data
.
atoms
[
a2
].
element
if
e1
==
e2
and
a1
>
a2
:
(
a1
,
a2
)
=
(
a2
,
a1
)
elif
e1
!=
elem
.
carbon
and
(
e2
==
elem
.
carbon
or
e1
.
mass
<
e2
.
mass
):
(
a1
,
a2
)
=
(
a2
,
a1
)
match
=
(
a1
,
a2
,
torsion
[
0
],
torsion
[
t4
[
1
]],
tordef
)
else
:
# There are no wildcards, so the order is unambiguous.
match
=
(
torsion
[
0
],
torsion
[
t2
[
1
]],
torsion
[
t3
[
1
]],
torsion
[
t4
[
1
]],
tordef
)
break
elif
tordef
.
ordering
==
'amber'
:
# topology atom indexes
a2
=
torsion
[
t2
[
1
]]
a3
=
torsion
[
t3
[
1
]]
a4
=
torsion
[
t4
[
1
]]
# residue indexes
r2
=
data
.
atoms
[
a2
].
residue
.
index
r3
=
data
.
atoms
[
a3
].
residue
.
index
r4
=
data
.
atoms
[
a4
].
residue
.
index
# template atom indexes
ta2
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a2
]]
ta3
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a3
]]
ta4
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a4
]]
# elements
e2
=
data
.
atoms
[
a2
].
element
e3
=
data
.
atoms
[
a3
].
element
e4
=
data
.
atoms
[
a4
].
element
if
not
hasWildcard
:
if
t2
[
0
]
==
t4
[
0
]
and
(
r2
>
r4
or
(
r2
==
r4
and
ta2
>
ta4
)):
(
a2
,
a4
)
=
(
a4
,
a2
)
r2
=
data
.
atoms
[
a2
].
residue
.
index
r4
=
data
.
atoms
[
a4
].
residue
.
index
ta2
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a2
]]
ta4
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a4
]]
if
t3
[
0
]
==
t4
[
0
]
and
(
r3
>
r4
or
(
r3
==
r4
and
ta3
>
ta4
)):
(
a3
,
a4
)
=
(
a4
,
a3
)
r3
=
data
.
atoms
[
a3
].
residue
.
index
r4
=
data
.
atoms
[
a4
].
residue
.
index
ta3
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a3
]]
ta4
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a4
]]
if
t2
[
0
]
==
t3
[
0
]
and
(
r2
>
r3
or
(
r2
==
r3
and
ta2
>
ta3
)):
(
a2
,
a3
)
=
(
a3
,
a2
)
else
:
if
e2
==
e4
and
(
r2
>
r4
or
(
r2
==
r4
and
ta2
>
ta4
)):
(
a2
,
a4
)
=
(
a4
,
a2
)
r2
=
data
.
atoms
[
a2
].
residue
.
index
r4
=
data
.
atoms
[
a4
].
residue
.
index
ta2
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a2
]]
ta4
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a4
]]
if
e3
==
e4
and
(
r3
>
r4
or
(
r3
==
r4
and
ta3
>
ta4
)):
(
a3
,
a4
)
=
(
a4
,
a3
)
r3
=
data
.
atoms
[
a3
].
residue
.
index
r4
=
data
.
atoms
[
a4
].
residue
.
index
ta3
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a3
]]
ta4
=
data
.
atomTemplateIndexes
[
data
.
atoms
[
a4
]]
if
r2
>
r3
or
(
r2
==
r3
and
ta2
>
ta3
):
(
a2
,
a3
)
=
(
a3
,
a2
)
match
=
(
a2
,
a3
,
torsion
[
0
],
a4
,
tordef
)
break
return
match
# The following classes are generators that know how to create Force subclasses and add them to a System that is being
# created. Each generator class must define two methods: 1) a static method that takes an etree Element and a ForceField,
# and returns the corresponding generator object; 2) a createForce() method that constructs the Force object and adds it
...
...
@@ -1763,8 +1902,11 @@ class HarmonicBondGenerator(object):
bond
.
length
=
self
.
length
[
i
]
if
bond
.
isConstrained
:
data
.
addConstraint
(
sys
,
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
])
elif
self
.
k
[
i
]
!=
0
:
force
.
addBond
(
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
],
self
.
k
[
i
])
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
])
break
parsers
[
"HarmonicBondForce"
]
=
HarmonicBondGenerator
.
parseElement
...
...
@@ -1844,8 +1986,9 @@ class HarmonicAngleGenerator(object):
if
l1
is
not
None
and
l2
is
not
None
:
length
=
sqrt
(
l1
*
l1
+
l2
*
l2
-
2
*
l1
*
l2
*
cos
(
self
.
angle
[
i
]))
data
.
addConstraint
(
sys
,
angle
[
0
],
angle
[
2
],
length
)
elif
self
.
k
[
i
]
!=
0
:
force
.
addAngle
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
self
.
angle
[
i
],
self
.
k
[
i
])
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
])
break
parsers
[
"HarmonicAngleForce"
]
=
HarmonicAngleGenerator
.
parseElement
...
...
@@ -1863,6 +2006,7 @@ class PeriodicTorsion(object):
self
.
periodicity
=
[]
self
.
phase
=
[]
self
.
k
=
[]
self
.
ordering
=
'default'
## @private
class
PeriodicTorsionGenerator
(
object
):
...
...
@@ -1878,9 +2022,13 @@ class PeriodicTorsionGenerator(object):
if
torsion
is
not
None
:
self
.
proper
.
append
(
torsion
)
def
registerImproperTorsion
(
self
,
parameters
):
def
registerImproperTorsion
(
self
,
parameters
,
ordering
=
'default'
):
torsion
=
self
.
ff
.
_parseTorsion
(
parameters
)
if
torsion
is
not
None
:
if
ordering
in
[
'default'
,
'charmm'
,
'amber'
]:
torsion
.
ordering
=
ordering
else
:
raise
ValueError
(
'Illegal ordering type %s for improper torsion %s'
%
(
ordering
,
torsion
))
self
.
improper
.
append
(
torsion
)
@
staticmethod
...
...
@@ -1894,7 +2042,10 @@ class PeriodicTorsionGenerator(object):
for
torsion
in
element
.
findall
(
'Proper'
):
generator
.
registerProperTorsion
(
torsion
.
attrib
)
for
torsion
in
element
.
findall
(
'Improper'
):
generator
.
registerImproperTorsion
(
torsion
.
attrib
)
if
'ordering'
in
element
.
attrib
:
generator
.
registerImproperTorsion
(
torsion
.
attrib
,
element
.
attrib
[
'ordering'
])
else
:
generator
.
registerImproperTorsion
(
torsion
.
attrib
)
def
createForce
(
self
,
sys
,
data
,
nonbondedMethod
,
nonbondedCutoff
,
args
):
existing
=
[
sys
.
getForce
(
i
)
for
i
in
range
(
sys
.
getNumForces
())]
...
...
@@ -1927,36 +2078,7 @@ class PeriodicTorsionGenerator(object):
if
match
.
k
[
i
]
!=
0
:
force
.
addTorsion
(
torsion
[
0
],
torsion
[
1
],
torsion
[
2
],
torsion
[
3
],
match
.
periodicity
[
i
],
match
.
phase
[
i
],
match
.
k
[
i
])
for
torsion
in
data
.
impropers
:
type1
=
data
.
atomType
[
data
.
atoms
[
torsion
[
0
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
torsion
[
1
]]]
type3
=
data
.
atomType
[
data
.
atoms
[
torsion
[
2
]]]
type4
=
data
.
atomType
[
data
.
atoms
[
torsion
[
3
]]]
match
=
None
for
tordef
in
self
.
improper
:
types1
=
tordef
.
types1
types2
=
tordef
.
types2
types3
=
tordef
.
types3
types4
=
tordef
.
types4
hasWildcard
=
(
wildcard
in
(
types1
,
types2
,
types3
,
types4
))
if
match
is
not
None
and
hasWildcard
:
# Prefer specific definitions over ones with wildcards
continue
if
type1
in
types1
:
for
(
t2
,
t3
,
t4
)
in
itertools
.
permutations
(((
type2
,
1
),
(
type3
,
2
),
(
type4
,
3
))):
if
t2
[
0
]
in
types2
and
t3
[
0
]
in
types3
and
t4
[
0
]
in
types4
:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1
=
torsion
[
t2
[
1
]]
a2
=
torsion
[
t3
[
1
]]
e1
=
data
.
atoms
[
a1
].
element
e2
=
data
.
atoms
[
a2
].
element
if
e1
==
e2
and
a1
>
a2
:
(
a1
,
a2
)
=
(
a2
,
a1
)
elif
e1
!=
elem
.
carbon
and
(
e2
==
elem
.
carbon
or
e1
.
mass
<
e2
.
mass
):
(
a1
,
a2
)
=
(
a2
,
a1
)
match
=
(
a1
,
a2
,
torsion
[
0
],
torsion
[
t4
[
1
]],
tordef
)
break
match
=
_matchImproper
(
data
,
torsion
,
self
)
if
match
is
not
None
:
(
a1
,
a2
,
a3
,
a4
,
tordef
)
=
match
for
i
in
range
(
len
(
tordef
.
phase
)):
...
...
@@ -1970,12 +2092,16 @@ parsers["PeriodicTorsionForce"] = PeriodicTorsionGenerator.parseElement
class
RBTorsion
(
object
):
"""An RBTorsion records the information for a Ryckaert-Bellemans torsion definition."""
def
__init__
(
self
,
types
,
c
):
def
__init__
(
self
,
types
,
c
,
ordering
=
'charmm'
):
self
.
types1
=
types
[
0
]
self
.
types2
=
types
[
1
]
self
.
types3
=
types
[
2
]
self
.
types4
=
types
[
3
]
self
.
c
=
c
if
ordering
in
[
'default'
,
'charmm'
,
'amber'
]:
self
.
ordering
=
ordering
else
:
raise
ValueError
(
'Illegal ordering type %s for RBTorsion (%s,%s,%s,%s)'
%
(
ordering
,
types
[
0
],
types
[
1
],
types
[
2
],
types
[
3
]))
## @private
class
RBTorsionGenerator
(
object
):
...
...
@@ -2001,7 +2127,10 @@ class RBTorsionGenerator(object):
for
torsion
in
element
.
findall
(
'Improper'
):
types
=
ff
.
_findAtomTypes
(
torsion
.
attrib
,
4
)
if
None
not
in
types
:
generator
.
improper
.
append
(
RBTorsion
(
types
,
[
float
(
torsion
.
attrib
[
'c'
+
str
(
i
)])
for
i
in
range
(
6
)]))
if
'ordering'
in
element
.
attrib
:
generator
.
improper
.
append
(
RBTorsion
(
types
,
[
float
(
torsion
.
attrib
[
'c'
+
str
(
i
)])
for
i
in
range
(
6
)],
element
.
attrib
[
'ordering'
]))
else
:
generator
.
improper
.
append
(
RBTorsion
(
types
,
[
float
(
torsion
.
attrib
[
'c'
+
str
(
i
)])
for
i
in
range
(
6
)]))
def
createForce
(
self
,
sys
,
data
,
nonbondedMethod
,
nonbondedCutoff
,
args
):
existing
=
[
sys
.
getForce
(
i
)
for
i
in
range
(
sys
.
getNumForces
())]
...
...
@@ -2032,40 +2161,7 @@ class RBTorsionGenerator(object):
if
match
is
not
None
:
force
.
addTorsion
(
torsion
[
0
],
torsion
[
1
],
torsion
[
2
],
torsion
[
3
],
match
.
c
[
0
],
match
.
c
[
1
],
match
.
c
[
2
],
match
.
c
[
3
],
match
.
c
[
4
],
match
.
c
[
5
])
for
torsion
in
data
.
impropers
:
type1
=
data
.
atomType
[
data
.
atoms
[
torsion
[
0
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
torsion
[
1
]]]
type3
=
data
.
atomType
[
data
.
atoms
[
torsion
[
2
]]]
type4
=
data
.
atomType
[
data
.
atoms
[
torsion
[
3
]]]
match
=
None
for
tordef
in
self
.
improper
:
types1
=
tordef
.
types1
types2
=
tordef
.
types2
types3
=
tordef
.
types3
types4
=
tordef
.
types4
hasWildcard
=
(
wildcard
in
(
types1
,
types2
,
types3
,
types4
))
if
match
is
not
None
and
hasWildcard
:
# Prefer specific definitions over ones with wildcards
continue
if
type1
in
types1
:
for
(
t2
,
t3
,
t4
)
in
itertools
.
permutations
(((
type2
,
1
),
(
type3
,
2
),
(
type4
,
3
))):
if
t2
[
0
]
in
types2
and
t3
[
0
]
in
types3
and
t4
[
0
]
in
types4
:
if
hasWildcard
:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1
=
torsion
[
t2
[
1
]]
a2
=
torsion
[
t3
[
1
]]
e1
=
data
.
atoms
[
a1
].
element
e2
=
data
.
atoms
[
a2
].
element
if
e1
==
e2
and
a1
>
a2
:
(
a1
,
a2
)
=
(
a2
,
a1
)
elif
e1
!=
elem
.
carbon
and
(
e2
==
elem
.
carbon
or
e1
.
mass
<
e2
.
mass
):
(
a1
,
a2
)
=
(
a2
,
a1
)
match
=
(
a1
,
a2
,
torsion
[
0
],
torsion
[
t4
[
1
]],
tordef
)
else
:
# There are no wildcards, so the order is unambiguous.
match
=
(
torsion
[
0
],
torsion
[
t2
[
1
]],
torsion
[
t3
[
1
]],
torsion
[
t4
[
1
]],
tordef
)
break
match
=
_matchImproper
(
data
,
torsion
,
self
)
if
match
is
not
None
:
(
a1
,
a2
,
a3
,
a4
,
tordef
)
=
match
force
.
addTorsion
(
a1
,
a2
,
a3
,
a4
,
tordef
.
c
[
0
],
tordef
.
c
[
1
],
tordef
.
c
[
2
],
tordef
.
c
[
3
],
tordef
.
c
[
4
],
tordef
.
c
[
5
])
...
...
@@ -2526,12 +2622,16 @@ parsers["CustomAngleForce"] = CustomAngleGenerator.parseElement
class
CustomTorsion
(
object
):
"""A CustomTorsion records the information for a custom torsion definition."""
def
__init__
(
self
,
types
,
paramValues
):
def
__init__
(
self
,
types
,
paramValues
,
ordering
=
'charmm'
):
self
.
types1
=
types
[
0
]
self
.
types2
=
types
[
1
]
self
.
types3
=
types
[
2
]
self
.
types4
=
types
[
3
]
self
.
paramValues
=
paramValues
if
ordering
in
[
'default'
,
'charmm'
,
'amber'
]:
self
.
ordering
=
ordering
else
:
raise
ValueError
(
'Illegal ordering type %s for CustomTorsion (%s,%s,%s,%s)'
%
(
ordering
,
types
[
0
],
types
[
1
],
types
[
2
],
types
[
3
]))
## @private
class
CustomTorsionGenerator
(
object
):
...
...
@@ -2560,7 +2660,10 @@ class CustomTorsionGenerator(object):
for
torsion
in
element
.
findall
(
'Improper'
):
types
=
ff
.
_findAtomTypes
(
torsion
.
attrib
,
4
)
if
None
not
in
types
:
generator
.
improper
.
append
(
CustomTorsion
(
types
,
[
float
(
torsion
.
attrib
[
param
])
for
param
in
generator
.
perTorsionParams
]))
if
'ordering'
in
element
.
attrib
:
generator
.
improper
.
append
(
CustomTorsion
(
types
,
[
float
(
torsion
.
attrib
[
param
])
for
param
in
generator
.
perTorsionParams
],
element
.
attrib
[
'ordering'
]))
else
:
generator
.
improper
.
append
(
CustomTorsion
(
types
,
[
float
(
torsion
.
attrib
[
param
])
for
param
in
generator
.
perTorsionParams
]))
def
createForce
(
self
,
sys
,
data
,
nonbondedMethod
,
nonbondedCutoff
,
args
):
force
=
mm
.
CustomTorsionForce
(
self
.
energy
)
...
...
@@ -2590,40 +2693,7 @@ class CustomTorsionGenerator(object):
if
match
is
not
None
:
force
.
addTorsion
(
torsion
[
0
],
torsion
[
1
],
torsion
[
2
],
torsion
[
3
],
match
.
paramValues
)
for
torsion
in
data
.
impropers
:
type1
=
data
.
atomType
[
data
.
atoms
[
torsion
[
0
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
torsion
[
1
]]]
type3
=
data
.
atomType
[
data
.
atoms
[
torsion
[
2
]]]
type4
=
data
.
atomType
[
data
.
atoms
[
torsion
[
3
]]]
match
=
None
for
tordef
in
self
.
improper
:
types1
=
tordef
.
types1
types2
=
tordef
.
types2
types3
=
tordef
.
types3
types4
=
tordef
.
types4
hasWildcard
=
(
wildcard
in
(
types1
,
types2
,
types3
,
types4
))
if
match
is
not
None
and
hasWildcard
:
# Prefer specific definitions over ones with wildcards
continue
if
type1
in
types1
:
for
(
t2
,
t3
,
t4
)
in
itertools
.
permutations
(((
type2
,
1
),
(
type3
,
2
),
(
type4
,
3
))):
if
t2
[
0
]
in
types2
and
t3
[
0
]
in
types3
and
t4
[
0
]
in
types4
:
if
hasWildcard
:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1
=
torsion
[
t2
[
1
]]
a2
=
torsion
[
t3
[
1
]]
e1
=
data
.
atoms
[
a1
].
element
e2
=
data
.
atoms
[
a2
].
element
if
e1
==
e2
and
a1
>
a2
:
(
a1
,
a2
)
=
(
a2
,
a1
)
elif
e1
!=
elem
.
carbon
and
(
e2
==
elem
.
carbon
or
e1
.
mass
<
e2
.
mass
):
(
a1
,
a2
)
=
(
a2
,
a1
)
match
=
(
a1
,
a2
,
torsion
[
0
],
torsion
[
t4
[
1
]],
tordef
)
else
:
# There are no wildcards, so the order is unambiguous.
match
=
(
torsion
[
0
],
torsion
[
t2
[
1
]],
torsion
[
t3
[
1
]],
torsion
[
t4
[
1
]],
tordef
)
break
match
=
_matchImproper
(
data
,
torsion
,
self
)
if
match
is
not
None
:
(
a1
,
a2
,
a3
,
a4
,
tordef
)
=
match
force
.
addTorsion
(
a1
,
a2
,
a3
,
a4
,
tordef
.
paramValues
)
...
...
@@ -3099,8 +3169,9 @@ class AmoebaBondGenerator(object):
bond
.
length
=
self
.
length
[
i
]
if
bond
.
isConstrained
:
data
.
addConstraint
(
sys
,
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
])
elif
self
.
k
[
i
]
!=
0
:
force
.
addBond
(
bond
.
atom1
,
bond
.
atom2
,
self
.
length
[
i
],
self
.
k
[
i
])
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
])
break
parsers
[
"AmoebaBondForce"
]
=
AmoebaBondGenerator
.
parseElement
...
...
@@ -3227,6 +3298,8 @@ class AmoebaAngleGenerator(object):
force
.
setAmoebaGlobalAnglePentic
(
self
.
pentic
)
force
.
setAmoebaGlobalAngleSextic
(
self
.
sextic
)
DEG_TO_RAD
=
math
.
pi
/
180
for
angleDict
in
angleList
:
angle
=
angleDict
[
'angle'
]
isConstrained
=
angleDict
[
'isConstrained'
]
...
...
@@ -3241,8 +3314,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
isConstrained
and
self
.
k
[
i
]
!=
0.0
:
angleDict
[
'idealAngle'
]
=
self
.
angle
[
i
][
0
]
addAngleConstraint
(
angle
,
self
.
angle
[
i
][
0
]
*
math
.
pi
/
180.0
,
data
,
sys
)
el
if
self
.
k
[
i
]
!=
0
:
addAngleConstraint
(
angle
,
self
.
angle
[
i
][
0
]
*
DEG_TO_RAD
,
data
,
sys
)
if
self
.
k
[
i
]
!=
0
and
(
not
isConstrained
or
args
.
get
(
'flexibleConstraints'
,
False
))
:
lenAngle
=
len
(
self
.
angle
[
i
])
if
(
lenAngle
>
1
):
# get k-index by counting number of non-angle hydrogens on the central atom
...
...
@@ -3311,7 +3384,7 @@ class AmoebaAngleGenerator(object):
angleDict
[
'idealAngle'
]
=
self
.
angle
[
i
][
0
]
if
(
isConstrained
and
self
.
k
[
i
]
!=
0.0
):
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
])
break
...
...
@@ -3963,7 +4036,7 @@ class AmoebaTorsionTorsionGenerator(object):
# raise error if atoms E or F not found
if
(
atomE
==
-
1
or
atomF
==
-
1
):
outputString
=
"getChiralAtomIndex: error getting bonded partners of atomC=%s %d %s"
%
(
atomC
.
name
,
atomC
.
resi
u
de
.
index
,
atomC
.
resi
u
de
.
name
,)
outputString
=
"getChiralAtomIndex: error getting bonded partners of atomC=%s %d %s"
%
(
atomC
.
name
,
atomC
.
resid
u
e
.
index
,
atomC
.
resid
u
e
.
name
,)
raise
ValueError
(
outputString
)
# check for different type/mass between atoms E & F
...
...
@@ -5370,7 +5443,7 @@ class AmoebaUreyBradleyGenerator(object):
force
=
existing
[
0
]
for
(
angle
,
isConstrained
)
in
zip
(
data
.
angles
,
data
.
isAngleConstrained
):
if
(
isConstrained
):
if
(
isConstrained
and
not
args
.
get
(
'flexibleConstraints'
,
False
)
):
continue
type1
=
data
.
atomType
[
data
.
atoms
[
angle
[
0
]]]
type2
=
data
.
atomType
[
data
.
atoms
[
angle
[
1
]]]
...
...
wrappers/python/simtk/openmm/app/gromacsgrofile.py
View file @
18295108
...
...
@@ -69,11 +69,14 @@ def _is_gro_coord(line):
@param[in] line The line to be tested
"""
sline
=
line
.
split
()
if
len
(
sline
)
==
6
or
len
(
sline
)
==
9
:
return
all
([
_isint
(
sline
[
2
]),
_isfloat
(
sline
[
3
]),
_isfloat
(
sline
[
4
]),
_isfloat
(
sline
[
5
])])
elif
len
(
sline
)
==
5
or
len
(
sline
)
==
8
:
return
all
([
_isint
(
line
[
15
:
20
]),
_isfloat
(
sline
[
2
]),
_isfloat
(
sline
[
3
]),
_isfloat
(
sline
[
4
])])
# data lines are fixed field
fields
=
[]
fields
.
append
(
line
[
16
:
20
].
strip
())
# atom number
fields
.
append
(
line
[
21
:
28
].
strip
())
# x coord
fields
.
append
(
line
[
29
:
36
].
strip
())
# y coord
fields
.
append
(
line
[
37
:
44
].
strip
())
# z coord
if
(
all
([
f
!=
''
for
f
in
fields
])):
# check for empty fields
return
all
([
_isint
(
fields
[
0
]),
_isfloat
(
fields
[
1
]),
_isfloat
(
fields
[
2
]),
_isfloat
(
fields
[
3
])])
else
:
return
0
...
...
wrappers/python/simtk/openmm/app/gromacstopfile.py
View file @
18295108
...
...
@@ -258,11 +258,16 @@ class GromacsTopFile(object):
def
_processDefaults
(
self
,
line
):
"""Process the [ defaults ] line."""
fields
=
line
.
split
()
if
len
(
fields
)
<
4
:
raise
ValueError
(
'Too few fields in [ defaults ] line: '
+
line
)
if
len
(
fields
)
<
5
:
# fudgeLJ and fudgeQQ not specified, assumed 1.0 by default
if
len
(
fields
)
==
3
:
fields
.
append
(
1.0
)
fields
.
append
(
1.0
)
else
:
raise
ValueError
(
'Too few fields in [ defaults ] line: '
+
line
)
if
fields
[
0
]
!=
'1'
:
raise
ValueError
(
'Unsupported nonbonded type: '
+
fields
[
0
])
if
fields
[
1
]
!
=
'2'
:
if
not
(
fields
[
1
]
=
=
'2'
or
fields
[
1
]
==
'1'
)
:
raise
ValueError
(
'Unsupported combination rule: '
+
fields
[
1
])
if
fields
[
2
].
lower
()
==
'no'
:
self
.
_genpairs
=
False
...
...
@@ -570,7 +575,7 @@ class GromacsTopFile(object):
The solvent dielectric constant to use in the implicit solvent
model.
ewaldErrorTolerance : float=0.0005
The error tolerance to use if nonbondedMethod is Ewald, PME
,
or LJPME.
The error tolerance to use if nonbondedMethod is Ewald, PME or LJPME.
removeCMMotion : boolean=True
If true, a CMMotionRemover will be added to the System
hydrogenMass : mass=None
...
...
@@ -593,6 +598,11 @@ class GromacsTopFile(object):
raise
ValueError
(
'Illegal nonbonded method for a non-periodic system'
)
nb
=
mm
.
NonbondedForce
()
sys
.
addForce
(
nb
)
if
self
.
_defaults
[
1
]
==
'1'
:
lj
=
mm
.
CustomNonbondedForce
(
'sqrt(A1*A2)/r^12-sqrt(C1*C2)/r^6'
)
lj
.
addPerParticleParameter
(
'C'
)
lj
.
addPerParticleParameter
(
'A'
)
sys
.
addForce
(
lj
)
if
implicitSolvent
is
OBC2
:
gb
=
mm
.
GBSAOBCForce
()
gb
.
setSoluteDielectric
(
soluteDielectric
)
...
...
@@ -610,8 +620,10 @@ class GromacsTopFile(object):
mapIndices
=
{}
bondIndices
=
[]
topologyAtoms
=
list
(
self
.
topology
.
atoms
())
exceptions
=
[]
exclusions
=
[]
pairs
=
[]
fudgeQQ
=
float
(
self
.
_defaults
[
4
])
fudgeLJ
=
float
(
self
.
_defaults
[
3
])
# Build a lookup table to let us process dihedrals more quickly.
...
...
@@ -748,7 +760,7 @@ class GromacsTopFile(object):
dihedralType
=
fields
[
4
]
reversedTypes
=
types
[::
-
1
]
+
(
dihedralType
,)
types
=
types
+
(
dihedralType
,)
if
(
dihedralType
in
(
'1'
,
'2'
,
'4'
,
'9'
)
and
len
(
fields
)
>
7
)
or
(
dihedralType
==
'3'
and
len
(
fields
)
>
10
):
if
(
dihedralType
in
(
'1'
,
'4'
,
'9'
)
and
len
(
fields
)
>
7
)
or
(
dihedralType
==
'3'
and
len
(
fields
)
>
10
)
or
(
dihedralType
==
'2'
and
len
(
fields
)
>
6
)
:
paramsList
=
[
fields
]
else
:
# Look for a matching dihedral type.
...
...
@@ -776,13 +788,16 @@ class GromacsTopFile(object):
elif
dihedralType
==
'2'
:
# Harmonic torsion
k
=
float
(
params
[
6
])
phi0
=
float
(
params
[
5
])
if
k
!=
0
:
if
harmonicTorsion
is
None
:
harmonicTorsion
=
mm
.
CustomTorsionForce
(
'0.5*k*(theta-theta0)^2
'
)
harmonicTorsion
=
mm
.
CustomTorsionForce
(
'0.5*k*(theta
p
-theta0)^2
; thetap = step(-(theta-theta0+pi))*2*pi+theta+step(theta-theta0-pi)*(-2*pi); pi = %.15g'
%
math
.
pi
)
harmonicTorsion
.
addPerTorsionParameter
(
'theta0'
)
harmonicTorsion
.
addPerTorsionParameter
(
'k'
)
sys
.
addForce
(
harmonicTorsion
)
harmonicTorsion
.
addTorsion
(
baseAtomIndex
+
atoms
[
0
],
baseAtomIndex
+
atoms
[
1
],
baseAtomIndex
+
atoms
[
2
],
baseAtomIndex
+
atoms
[
3
],
(
float
(
params
[
5
])
*
degToRad
,
k
))
# map phi0 into correct space
phi0
=
phi0
-
360
if
phi0
>
180
else
phi0
harmonicTorsion
.
addTorsion
(
baseAtomIndex
+
atoms
[
0
],
baseAtomIndex
+
atoms
[
1
],
baseAtomIndex
+
atoms
[
2
],
baseAtomIndex
+
atoms
[
3
],
(
phi0
*
degToRad
,
k
))
else
:
# RB Torsion
c
=
[
float
(
x
)
for
x
in
params
[
5
:
11
]]
...
...
@@ -825,11 +840,18 @@ class GromacsTopFile(object):
for
fields
in
moleculeType
.
atoms
:
params
=
self
.
_atomTypes
[
fields
[
1
]]
if
len
(
fields
)
>
6
:
q
=
float
(
fields
[
6
])
else
:
q
=
float
(
params
[
4
])
nb
.
addParticle
(
q
,
float
(
params
[
6
]),
float
(
params
[
7
]))
if
self
.
_defaults
[
1
]
==
'1'
:
nb
.
addParticle
(
q
,
1.0
,
0.0
)
lj
.
addParticle
([
float
(
params
[
6
]),
float
(
params
[
7
])])
elif
self
.
_defaults
[
1
]
==
'2'
:
nb
.
addParticle
(
q
,
float
(
params
[
6
]),
float
(
params
[
7
]))
if
implicitSolvent
is
OBC2
:
if
fields
[
1
]
not
in
self
.
_implicitTypes
:
raise
ValueError
(
'No implicit solvent parameters specified for atom type: '
+
fields
[
1
])
...
...
@@ -857,19 +879,37 @@ class GromacsTopFile(object):
continue
# We'll use the automatically generated parameters
atom1params
=
nb
.
getParticleParameters
(
baseAtomIndex
+
atoms
[
0
])
atom2params
=
nb
.
getParticleParameters
(
baseAtomIndex
+
atoms
[
1
])
exception
s
.
append
((
baseAtomIndex
+
atoms
[
0
],
baseAtomIndex
+
atoms
[
1
],
atom1params
[
0
]
*
atom2params
[
0
]
*
fudgeQQ
,
params
[
0
],
params
[
1
]))
pair
s
.
append
((
baseAtomIndex
+
atoms
[
0
],
baseAtomIndex
+
atoms
[
1
],
atom1params
[
0
]
*
atom2params
[
0
]
*
fudgeQQ
,
params
[
0
],
params
[
1
]))
for
fields
in
moleculeType
.
exclusions
:
atoms
=
[
int
(
x
)
-
1
for
x
in
fields
]
for
atom
in
atoms
[
1
:]:
if
atom
>
atoms
[
0
]:
exc
ept
ions
.
append
((
baseAtomIndex
+
atoms
[
0
],
baseAtomIndex
+
atom
,
0
,
0
,
0
))
exc
lus
ions
.
append
((
baseAtomIndex
+
atoms
[
0
],
baseAtomIndex
+
atom
))
# Create nonbonded exceptions.
nb
.
createExceptionsFromBonds
(
bondIndices
,
fudgeQQ
,
float
(
self
.
_defaults
[
3
]))
for
exception
in
exceptions
:
nb
.
addException
(
exception
[
0
],
exception
[
1
],
exception
[
2
],
float
(
exception
[
3
]),
float
(
exception
[
4
]),
True
)
nb
.
createExceptionsFromBonds
(
bondIndices
,
fudgeQQ
,
fudgeLJ
)
for
exclusion
in
exclusions
:
nb
.
addException
(
exclusion
[
0
],
exclusion
[
1
],
0.0
,
1.0
,
0.0
,
True
)
if
self
.
_defaults
[
1
]
==
'1'
:
# We're using a CustomNonbondedForce for LJ interactions, so also create a CustomBondForce
# to handle the exceptions.
pair_bond
=
mm
.
CustomBondForce
(
'138.935456*q/r-C/r^6+A/r^12'
)
pair_bond
.
addPerBondParameter
(
'q'
)
pair_bond
.
addPerBondParameter
(
'C'
)
pair_bond
.
addPerBondParameter
(
'A'
)
sys
.
addForce
(
pair_bond
)
lj
.
createExclusionsFromBonds
(
bondIndices
,
3
)
for
pair
in
pairs
:
nb
.
addException
(
pair
[
0
],
pair
[
1
],
pair
[
2
],
1.0
,
0.0
,
True
)
pair_bond
.
addBond
(
pair
[
0
],
pair
[
1
],
[
pair
[
2
],
float
(
pair
[
3
]),
float
(
pair
[
4
])])
for
exclusion
in
exclusions
:
lj
.
addExclusion
(
exclusion
[
0
],
exclusion
[
1
])
elif
self
.
_defaults
[
1
]
==
'2'
:
for
pair
in
pairs
:
nb
.
addException
(
pair
[
0
],
pair
[
1
],
pair
[
2
],
float
(
pair
[
3
]),
float
(
pair
[
4
]),
True
)
# Finish configuring the NonbondedForce.
...
...
@@ -882,6 +922,15 @@ class GromacsTopFile(object):
nb
.
setNonbondedMethod
(
methodMap
[
nonbondedMethod
])
nb
.
setCutoffDistance
(
nonbondedCutoff
)
nb
.
setEwaldErrorTolerance
(
ewaldErrorTolerance
)
if
self
.
_defaults
[
1
]
==
'1'
:
methodMap
=
{
ff
.
NoCutoff
:
mm
.
CustomNonbondedForce
.
NoCutoff
,
ff
.
CutoffNonPeriodic
:
mm
.
CustomNonbondedForce
.
CutoffNonPeriodic
,
ff
.
CutoffPeriodic
:
mm
.
CustomNonbondedForce
.
CutoffPeriodic
,
ff
.
Ewald
:
mm
.
CustomNonbondedForce
.
CutoffPeriodic
,
ff
.
PME
:
mm
.
CustomNonbondedForce
.
CutoffPeriodic
,
ff
.
LJPME
:
mm
.
CustomNonbondedForce
.
CutoffPeriodic
}
lj
.
setNonbondedMethod
(
methodMap
[
nonbondedMethod
])
lj
.
setCutoffDistance
(
nonbondedCutoff
)
# Adjust masses.
...
...
wrappers/python/simtk/openmm/app/internal/amber_file_parser.py
View file @
18295108
...
...
@@ -525,7 +525,7 @@ class PrmtopLoader(object):
iScnb
=
float
(
self
.
_raw_data
[
"SCNB_SCALE_FACTOR"
][
iidx
])
except
KeyError
:
iScnb
=
2.0
returnList
.
append
((
iAtom
,
lAtom
,
chargeProd
,
rMin
,
epsilon
,
iScee
,
iScnb
))
return
returnList
...
...
@@ -579,7 +579,8 @@ def readAmberSystem(topology, prmtop_filename=None, prmtop_loader=None, shake=No
soluteDielectric
=
1.0
,
solventDielectric
=
78.5
,
implicitSolventKappa
=
0.0
*
(
1
/
units
.
nanometer
),
nonbondedCutoff
=
None
,
nonbondedMethod
=
'NoCutoff'
,
scee
=
None
,
scnb
=
None
,
mm
=
None
,
verbose
=
False
,
EwaldErrorTolerance
=
None
,
flexibleConstraints
=
True
,
rigidWater
=
True
,
elements
=
None
):
EwaldErrorTolerance
=
None
,
flexibleConstraints
=
True
,
rigidWater
=
True
,
elements
=
None
,
gbsaModel
=
'ACE'
):
"""
Create an OpenMM System from an Amber prmtop file.
...
...
@@ -603,6 +604,7 @@ def readAmberSystem(topology, prmtop_filename=None, prmtop_loader=None, shake=No
verbose (boolean) - if True, print out information on progress (default: False)
flexibleConstraints (boolean) - if True, flexible bonds will be added in addition ot constrained bonds
rigidWater (boolean=True) If true, water molecules will be fully rigid regardless of the value passed for the shake argument
gbsaModel (str='ACE') The string representing the SA model to use for GB calculations. Must be 'ACE' or None
NOTES
...
...
@@ -648,6 +650,9 @@ def readAmberSystem(topology, prmtop_filename=None, prmtop_loader=None, shake=No
warnings
.
warn
(
"1-4 scaling parameters in topology file are being ignored. "
"This is not recommended unless you know what you are doing."
)
if
gbmodel
is
not
None
and
gbsaModel
not
in
(
'ACE'
,
None
):
raise
ValueError
(
'gbsaModel must be ACE or None'
)
has_1264
=
'LENNARD_JONES_CCOEF'
in
prmtop
.
_raw_data
.
keys
()
if
has_1264
:
parm_ccoef
=
[
float
(
x
)
for
x
in
prmtop
.
_raw_data
[
'LENNARD_JONES_CCOEF'
]]
...
...
@@ -974,20 +979,20 @@ def readAmberSystem(topology, prmtop_filename=None, prmtop_loader=None, shake=No
if
units
.
is_quantity
(
cutoff
):
cutoff
=
cutoff
.
value_in_unit
(
units
.
nanometers
)
if
gbmodel
==
'HCT'
:
gb
=
customgb
.
GBSAHCTForce
(
solventDielectric
,
soluteDielectric
,
'ACE'
,
cutoff
,
implicitSolventKappa
)
gb
=
customgb
.
GBSAHCTForce
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
implicitSolventKappa
)
elif
gbmodel
==
'OBC1'
:
gb
=
customgb
.
GBSAOBC1Force
(
solventDielectric
,
soluteDielectric
,
'ACE'
,
cutoff
,
implicitSolventKappa
)
gb
=
customgb
.
GBSAOBC1Force
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
implicitSolventKappa
)
elif
gbmodel
==
'OBC2'
:
if
implicitSolventKappa
>
0
:
gb
=
customgb
.
GBSAOBC2Force
(
solventDielectric
,
soluteDielectric
,
'ACE'
,
cutoff
,
implicitSolventKappa
)
gb
=
customgb
.
GBSAOBC2Force
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
implicitSolventKappa
)
else
:
gb
=
mm
.
GBSAOBCForce
()
gb
.
setSoluteDielectric
(
soluteDielectric
)
gb
.
setSolventDielectric
(
solventDielectric
)
elif
gbmodel
==
'GBn'
:
gb
=
customgb
.
GBSAGBnForce
(
solventDielectric
,
soluteDielectric
,
'ACE'
,
cutoff
,
implicitSolventKappa
)
gb
=
customgb
.
GBSAGBnForce
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
implicitSolventKappa
)
elif
gbmodel
==
'GBn2'
:
gb
=
customgb
.
GBSAGBn2Force
(
solventDielectric
,
soluteDielectric
,
'ACE'
,
cutoff
,
implicitSolventKappa
)
gb
=
customgb
.
GBSAGBn2Force
(
solventDielectric
,
soluteDielectric
,
gbsaModel
,
cutoff
,
implicitSolventKappa
)
else
:
raise
ValueError
(
"Illegal value specified for implicit solvent model"
)
if
isinstance
(
gb
,
mm
.
GBSAOBCForce
):
...
...
@@ -1121,7 +1126,7 @@ class AmberAsciiRestart(object):
self
.
natom
=
int
(
words
[
0
])
except
(
IndexError
,
ValueError
):
raise
TypeError
(
'Unrecognized file type [%s]'
%
self
.
filename
)
if
len
(
words
)
>=
2
:
self
.
time
=
float
(
words
[
1
])
*
units
.
picoseconds
...
...
@@ -1290,7 +1295,7 @@ class AmberNetcdfRestart(object):
from
scipy.io.netcdf
import
NetCDFFile
except
ImportError
:
raise
ImportError
(
'scipy is necessary to parse NetCDF restarts'
)
self
.
filename
=
filename
self
.
velocities
=
self
.
boxVectors
=
self
.
time
=
None
...
...
wrappers/python/simtk/openmm/app/pdbfile.py
View file @
18295108
...
...
@@ -123,6 +123,8 @@ class PDBFile(object):
# Try to guess the element.
upper
=
atomName
.
upper
()
while
len
(
upper
)
>
1
and
upper
[
0
].
isdigit
():
upper
=
upper
[
1
:]
if
upper
.
startswith
(
'CL'
):
element
=
elem
.
chlorine
elif
upper
.
startswith
(
'NA'
):
...
...
@@ -141,7 +143,7 @@ class PDBFile(object):
element
=
elem
.
calcium
else
:
try
:
element
=
elem
.
get_by_symbol
(
atomName
[
0
])
element
=
elem
.
get_by_symbol
(
upper
[
0
])
except
KeyError
:
pass
newAtom
=
top
.
addAtom
(
atomName
,
element
,
r
,
str
(
atom
.
serial_number
))
...
...
Prev
1
…
3
4
5
6
7
8
Next
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