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
fd473eea
Commit
fd473eea
authored
Oct 29, 2015
by
Peter Eastman
Browse files
Merge branch 'master' into nucleic
parents
0a751b5b
6a985cfd
Changes
279
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
616 additions
and
3231 deletions
+616
-3231
platforms/reference/src/ReferenceKernels.cpp
platforms/reference/src/ReferenceKernels.cpp
+206
-4
platforms/reference/src/ReferencePlatform.cpp
platforms/reference/src/ReferencePlatform.cpp
+1
-0
platforms/reference/src/SimTKReference/ReferenceConstraints.cpp
...rms/reference/src/SimTKReference/ReferenceConstraints.cpp
+26
-26
platforms/reference/src/SimTKReference/ReferenceCustomCentroidBondIxn.cpp
...nce/src/SimTKReference/ReferenceCustomCentroidBondIxn.cpp
+232
-0
platforms/reference/src/SimTKReference/ReferenceStochasticDynamics.cpp
...erence/src/SimTKReference/ReferenceStochasticDynamics.cpp
+13
-9
platforms/reference/tests/CMakeLists.txt
platforms/reference/tests/CMakeLists.txt
+1
-1
platforms/reference/tests/ReferenceTests.h
platforms/reference/tests/ReferenceTests.h
+40
-0
platforms/reference/tests/TestReferenceAndersenThermostat.cpp
...forms/reference/tests/TestReferenceAndersenThermostat.cpp
+4
-186
platforms/reference/tests/TestReferenceBrownianIntegrator.cpp
...forms/reference/tests/TestReferenceBrownianIntegrator.cpp
+4
-237
platforms/reference/tests/TestReferenceCMAPTorsionForce.cpp
platforms/reference/tests/TestReferenceCMAPTorsionForce.cpp
+4
-148
platforms/reference/tests/TestReferenceCMMotionRemover.cpp
platforms/reference/tests/TestReferenceCMMotionRemover.cpp
+4
-85
platforms/reference/tests/TestReferenceCheckpoints.cpp
platforms/reference/tests/TestReferenceCheckpoints.cpp
+17
-108
platforms/reference/tests/TestReferenceCustomAngleForce.cpp
platforms/reference/tests/TestReferenceCustomAngleForce.cpp
+4
-117
platforms/reference/tests/TestReferenceCustomBondForce.cpp
platforms/reference/tests/TestReferenceCustomBondForce.cpp
+4
-85
platforms/reference/tests/TestReferenceCustomCentroidBondForce.cpp
.../reference/tests/TestReferenceCustomCentroidBondForce.cpp
+36
-0
platforms/reference/tests/TestReferenceCustomCompoundBondForce.cpp
.../reference/tests/TestReferenceCustomCompoundBondForce.cpp
+4
-302
platforms/reference/tests/TestReferenceCustomExternalForce.cpp
...orms/reference/tests/TestReferenceCustomExternalForce.cpp
+4
-84
platforms/reference/tests/TestReferenceCustomGBForce.cpp
platforms/reference/tests/TestReferenceCustomGBForce.cpp
+4
-879
platforms/reference/tests/TestReferenceCustomHbondForce.cpp
platforms/reference/tests/TestReferenceCustomHbondForce.cpp
+4
-217
platforms/reference/tests/TestReferenceCustomIntegrator.cpp
platforms/reference/tests/TestReferenceCustomIntegrator.cpp
+4
-743
No files found.
Too many changes to show.
To preserve performance only
279 of 279+
files are displayed.
Plain diff
Email patch
platforms/reference/src/ReferenceKernels.cpp
View file @
fd473eea
...
@@ -41,6 +41,7 @@
...
@@ -41,6 +41,7 @@
#include "ReferenceConstraints.h"
#include "ReferenceConstraints.h"
#include "ReferenceCustomAngleIxn.h"
#include "ReferenceCustomAngleIxn.h"
#include "ReferenceCustomBondIxn.h"
#include "ReferenceCustomBondIxn.h"
#include "ReferenceCustomCentroidBondIxn.h"
#include "ReferenceCustomCompoundBondIxn.h"
#include "ReferenceCustomCompoundBondIxn.h"
#include "ReferenceCustomDynamics.h"
#include "ReferenceCustomDynamics.h"
#include "ReferenceCustomExternalIxn.h"
#include "ReferenceCustomExternalIxn.h"
...
@@ -66,6 +67,7 @@
...
@@ -66,6 +67,7 @@
#include "openmm/System.h"
#include "openmm/System.h"
#include "openmm/internal/AndersenThermostatImpl.h"
#include "openmm/internal/AndersenThermostatImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomCentroidBondForceImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
...
@@ -75,6 +77,7 @@
...
@@ -75,6 +77,7 @@
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
#include "SimTKOpenMMUtilities.h"
#include "SimTKOpenMMUtilities.h"
#include "lepton/CustomFunction.h"
#include "lepton/CustomFunction.h"
#include "lepton/Operation.h"
#include "lepton/Parser.h"
#include "lepton/Parser.h"
#include "lepton/ParsedExpression.h"
#include "lepton/ParsedExpression.h"
#include <cmath>
#include <cmath>
...
@@ -144,6 +147,17 @@ static ReferenceConstraints& extractConstraints(ContextImpl& context) {
...
@@ -144,6 +147,17 @@ static ReferenceConstraints& extractConstraints(ContextImpl& context) {
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
return
*
(
ReferenceConstraints
*
)
data
->
constraints
;
}
}
/**
* Make sure an expression doesn't use any undefined variables.
*/
static
void
validateVariables
(
const
Lepton
::
ExpressionTreeNode
&
node
,
const
set
<
string
>&
variables
)
{
const
Lepton
::
Operation
&
op
=
node
.
getOperation
();
if
(
op
.
getId
()
==
Lepton
::
Operation
::
VARIABLE
&&
variables
.
find
(
op
.
getName
())
==
variables
.
end
())
throw
OpenMMException
(
"Unknown variable in expression: "
+
op
.
getName
());
for
(
int
i
=
0
;
i
<
(
int
)
node
.
getChildren
().
size
();
i
++
)
validateVariables
(
node
.
getChildren
()[
i
],
variables
);
}
/**
/**
* Compute the kinetic energy of the system, possibly shifting the velocities in time to account
* Compute the kinetic energy of the system, possibly shifting the velocities in time to account
* for a leapfrog integrator.
* for a leapfrog integrator.
...
@@ -420,6 +434,11 @@ void ReferenceCalcCustomBondForceKernel::initialize(const System& system, const
...
@@ -420,6 +434,11 @@ void ReferenceCalcCustomBondForceKernel::initialize(const System& system, const
parameterNames
.
push_back
(
force
.
getPerBondParameterName
(
i
));
parameterNames
.
push_back
(
force
.
getPerBondParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
set
<
string
>
variables
;
variables
.
insert
(
"r"
);
variables
.
insert
(
parameterNames
.
begin
(),
parameterNames
.
end
());
variables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
validateVariables
(
expression
.
getRootNode
(),
variables
);
}
}
double
ReferenceCalcCustomBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
ReferenceCalcCustomBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
...
@@ -534,6 +553,11 @@ void ReferenceCalcCustomAngleForceKernel::initialize(const System& system, const
...
@@ -534,6 +553,11 @@ void ReferenceCalcCustomAngleForceKernel::initialize(const System& system, const
parameterNames
.
push_back
(
force
.
getPerAngleParameterName
(
i
));
parameterNames
.
push_back
(
force
.
getPerAngleParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
set
<
string
>
variables
;
variables
.
insert
(
"theta"
);
variables
.
insert
(
parameterNames
.
begin
(),
parameterNames
.
end
());
variables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
validateVariables
(
expression
.
getRootNode
(),
variables
);
}
}
double
ReferenceCalcCustomAngleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
ReferenceCalcCustomAngleForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
...
@@ -778,6 +802,11 @@ void ReferenceCalcCustomTorsionForceKernel::initialize(const System& system, con
...
@@ -778,6 +802,11 @@ void ReferenceCalcCustomTorsionForceKernel::initialize(const System& system, con
parameterNames
.
push_back
(
force
.
getPerTorsionParameterName
(
i
));
parameterNames
.
push_back
(
force
.
getPerTorsionParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
set
<
string
>
variables
;
variables
.
insert
(
"theta"
);
variables
.
insert
(
parameterNames
.
begin
(),
parameterNames
.
end
());
variables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
validateVariables
(
expression
.
getRootNode
(),
variables
);
}
}
double
ReferenceCalcCustomTorsionForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
ReferenceCalcCustomTorsionForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
...
@@ -967,6 +996,15 @@ void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& con
...
@@ -967,6 +996,15 @@ void ReferenceCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& con
dispersionCoefficient
=
NonbondedForceImpl
::
calcDispersionCorrection
(
context
.
getSystem
(),
force
);
dispersionCoefficient
=
NonbondedForceImpl
::
calcDispersionCorrection
(
context
.
getSystem
(),
force
);
}
}
void
ReferenceCalcNonbondedForceKernel
::
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
if
(
nonbondedMethod
!=
PME
)
throw
OpenMMException
(
"getPMEParametersInContext: This Context is not using PME"
);
alpha
=
ewaldAlpha
;
nx
=
gridSize
[
0
];
ny
=
gridSize
[
1
];
nz
=
gridSize
[
2
];
}
ReferenceCalcCustomNonbondedForceKernel
::~
ReferenceCalcCustomNonbondedForceKernel
()
{
ReferenceCalcCustomNonbondedForceKernel
::~
ReferenceCalcCustomNonbondedForceKernel
()
{
disposeRealArray
(
particleParamArray
,
numParticles
);
disposeRealArray
(
particleParamArray
,
numParticles
);
if
(
neighborList
!=
NULL
)
if
(
neighborList
!=
NULL
)
...
@@ -1027,6 +1065,14 @@ void ReferenceCalcCustomNonbondedForceKernel::initialize(const System& system, c
...
@@ -1027,6 +1065,14 @@ void ReferenceCalcCustomNonbondedForceKernel::initialize(const System& system, c
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParamValues
[
force
.
getGlobalParameterName
(
i
)]
=
force
.
getGlobalParameterDefaultValue
(
i
);
globalParamValues
[
force
.
getGlobalParameterName
(
i
)]
=
force
.
getGlobalParameterDefaultValue
(
i
);
}
}
set
<
string
>
variables
;
variables
.
insert
(
"r"
);
for
(
int
i
=
0
;
i
<
numParameters
;
i
++
)
{
variables
.
insert
(
parameterNames
[
i
]
+
"1"
);
variables
.
insert
(
parameterNames
[
i
]
+
"2"
);
}
variables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
validateVariables
(
expression
.
getRootNode
(),
variables
);
// Delete the custom functions.
// Delete the custom functions.
...
@@ -1303,6 +1349,18 @@ void ReferenceCalcCustomGBForceKernel::initialize(const System& system, const Cu
...
@@ -1303,6 +1349,18 @@ void ReferenceCalcCustomGBForceKernel::initialize(const System& system, const Cu
valueDerivExpressions
.
resize
(
force
.
getNumComputedValues
());
valueDerivExpressions
.
resize
(
force
.
getNumComputedValues
());
valueGradientExpressions
.
resize
(
force
.
getNumComputedValues
());
valueGradientExpressions
.
resize
(
force
.
getNumComputedValues
());
set
<
string
>
particleVariables
,
pairVariables
;
pairVariables
.
insert
(
"r"
);
particleVariables
.
insert
(
"x"
);
particleVariables
.
insert
(
"y"
);
particleVariables
.
insert
(
"z"
);
for
(
int
i
=
0
;
i
<
numPerParticleParameters
;
i
++
)
{
particleVariables
.
insert
(
particleParameterNames
[
i
]);
pairVariables
.
insert
(
particleParameterNames
[
i
]
+
"1"
);
pairVariables
.
insert
(
particleParameterNames
[
i
]
+
"2"
);
}
particleVariables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
pairVariables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
for
(
int
i
=
0
;
i
<
force
.
getNumComputedValues
();
i
++
)
{
string
name
,
expression
;
string
name
,
expression
;
CustomGBForce
::
ComputationType
type
;
CustomGBForce
::
ComputationType
type
;
...
@@ -1311,15 +1369,21 @@ void ReferenceCalcCustomGBForceKernel::initialize(const System& system, const Cu
...
@@ -1311,15 +1369,21 @@ void ReferenceCalcCustomGBForceKernel::initialize(const System& system, const Cu
valueExpressions
.
push_back
(
ex
.
createProgram
());
valueExpressions
.
push_back
(
ex
.
createProgram
());
valueTypes
.
push_back
(
type
);
valueTypes
.
push_back
(
type
);
valueNames
.
push_back
(
name
);
valueNames
.
push_back
(
name
);
if
(
i
==
0
)
if
(
i
==
0
)
{
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"r"
).
optimize
().
createProgram
());
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"r"
).
optimize
().
createProgram
());
validateVariables
(
ex
.
getRootNode
(),
pairVariables
);
}
else
{
else
{
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
optimize
().
createProgram
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
optimize
().
createProgram
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
optimize
().
createProgram
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
optimize
().
createProgram
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
optimize
().
createProgram
());
valueGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
optimize
().
createProgram
());
for
(
int
j
=
0
;
j
<
i
;
j
++
)
for
(
int
j
=
0
;
j
<
i
;
j
++
)
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]).
optimize
().
createProgram
());
valueDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]).
optimize
().
createProgram
());
validateVariables
(
ex
.
getRootNode
(),
particleVariables
);
}
}
particleVariables
.
insert
(
name
);
pairVariables
.
insert
(
name
+
"1"
);
pairVariables
.
insert
(
name
+
"2"
);
}
}
// Parse the expressions for energy terms.
// Parse the expressions for energy terms.
...
@@ -1341,10 +1405,12 @@ void ReferenceCalcCustomGBForceKernel::initialize(const System& system, const Cu
...
@@ -1341,10 +1405,12 @@ void ReferenceCalcCustomGBForceKernel::initialize(const System& system, const Cu
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
optimize
().
createProgram
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"x"
).
optimize
().
createProgram
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
optimize
().
createProgram
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"y"
).
optimize
().
createProgram
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
optimize
().
createProgram
());
energyGradientExpressions
[
i
].
push_back
(
ex
.
differentiate
(
"z"
).
optimize
().
createProgram
());
validateVariables
(
ex
.
getRootNode
(),
particleVariables
);
}
}
else
{
else
{
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"1"
).
optimize
().
createProgram
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"1"
).
optimize
().
createProgram
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"2"
).
optimize
().
createProgram
());
energyDerivExpressions
[
i
].
push_back
(
ex
.
differentiate
(
valueNames
[
j
]
+
"2"
).
optimize
().
createProgram
());
validateVariables
(
ex
.
getRootNode
(),
pairVariables
);
}
}
}
}
}
}
...
@@ -1391,6 +1457,48 @@ void ReferenceCalcCustomGBForceKernel::copyParametersToContext(ContextImpl& cont
...
@@ -1391,6 +1457,48 @@ void ReferenceCalcCustomGBForceKernel::copyParametersToContext(ContextImpl& cont
}
}
}
}
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
::
PeriodicDistanceFunction
(
RealVec
**
boxVectorHandle
)
:
boxVectorHandle
(
boxVectorHandle
)
{
}
int
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
::
getNumArguments
()
const
{
return
6
;
}
double
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
::
evaluate
(
const
double
*
arguments
)
const
{
RealVec
*
boxVectors
=
*
boxVectorHandle
;
RealVec
delta
=
RealVec
(
arguments
[
0
],
arguments
[
1
],
arguments
[
2
])
-
RealVec
(
arguments
[
3
],
arguments
[
4
],
arguments
[
5
]);
delta
-=
boxVectors
[
2
]
*
floor
(
delta
[
2
]
/
boxVectors
[
2
][
2
]
+
0.5
);
delta
-=
boxVectors
[
1
]
*
floor
(
delta
[
1
]
/
boxVectors
[
1
][
1
]
+
0.5
);
delta
-=
boxVectors
[
0
]
*
floor
(
delta
[
0
]
/
boxVectors
[
0
][
0
]
+
0.5
);
return
sqrt
(
delta
.
dot
(
delta
));
}
double
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
::
evaluateDerivative
(
const
double
*
arguments
,
const
int
*
derivOrder
)
const
{
int
argIndex
=
-
1
;
for
(
int
i
=
0
;
i
<
6
;
i
++
)
{
if
(
derivOrder
[
i
]
>
0
)
{
if
(
derivOrder
[
i
]
>
1
||
argIndex
!=
-
1
)
throw
OpenMMException
(
"Unsupported derivative of periodicdistance"
);
// Should be impossible for this to happen.
argIndex
=
i
;
}
}
RealVec
*
boxVectors
=
*
boxVectorHandle
;
RealVec
delta
=
RealVec
(
arguments
[
0
],
arguments
[
1
],
arguments
[
2
])
-
RealVec
(
arguments
[
3
],
arguments
[
4
],
arguments
[
5
]);
delta
-=
boxVectors
[
2
]
*
floor
(
delta
[
2
]
/
boxVectors
[
2
][
2
]
+
0.5
);
delta
-=
boxVectors
[
1
]
*
floor
(
delta
[
1
]
/
boxVectors
[
1
][
1
]
+
0.5
);
delta
-=
boxVectors
[
0
]
*
floor
(
delta
[
0
]
/
boxVectors
[
0
][
0
]
+
0.5
);
double
r
=
sqrt
(
delta
.
dot
(
delta
));
if
(
r
==
0
)
return
0.0
;
if
(
argIndex
<
3
)
return
delta
[
argIndex
]
/
r
;
return
-
delta
[
argIndex
-
3
]
/
r
;
}
Lepton
::
CustomFunction
*
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
::
clone
()
const
{
return
new
PeriodicDistanceFunction
(
boxVectorHandle
);
}
ReferenceCalcCustomExternalForceKernel
::~
ReferenceCalcCustomExternalForceKernel
()
{
ReferenceCalcCustomExternalForceKernel
::~
ReferenceCalcCustomExternalForceKernel
()
{
disposeRealArray
(
particleParamArray
,
numParticles
);
disposeRealArray
(
particleParamArray
,
numParticles
);
}
}
...
@@ -1412,7 +1520,10 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
...
@@ -1412,7 +1520,10 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
// Parse the expression used to calculate the force.
// Parse the expression used to calculate the force.
Lepton
::
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
()).
optimize
();
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
PeriodicDistanceFunction
periodicDistance
(
&
boxVectors
);
functions
[
"periodicdistance"
]
=
&
periodicDistance
;
Lepton
::
ParsedExpression
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
).
optimize
();
energyExpression
=
expression
.
createCompiledExpression
();
energyExpression
=
expression
.
createCompiledExpression
();
forceExpressionX
=
expression
.
differentiate
(
"x"
).
createCompiledExpression
();
forceExpressionX
=
expression
.
differentiate
(
"x"
).
createCompiledExpression
();
forceExpressionY
=
expression
.
differentiate
(
"y"
).
createCompiledExpression
();
forceExpressionY
=
expression
.
differentiate
(
"y"
).
createCompiledExpression
();
...
@@ -1421,11 +1532,19 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
...
@@ -1421,11 +1532,19 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
parameterNames
.
push_back
(
force
.
getPerParticleParameterName
(
i
));
parameterNames
.
push_back
(
force
.
getPerParticleParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
set
<
string
>
variables
;
variables
.
insert
(
"x"
);
variables
.
insert
(
"y"
);
variables
.
insert
(
"z"
);
variables
.
insert
(
parameterNames
.
begin
(),
parameterNames
.
end
());
variables
.
insert
(
globalParameterNames
.
begin
(),
globalParameterNames
.
end
());
validateVariables
(
expression
.
getRootNode
(),
variables
);
}
}
double
ReferenceCalcCustomExternalForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
double
ReferenceCalcCustomExternalForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
boxVectors
=
extractBoxVectors
(
context
);
RealOpenMM
energy
=
0
;
RealOpenMM
energy
=
0
;
map
<
string
,
double
>
globalParameters
;
map
<
string
,
double
>
globalParameters
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
...
@@ -1582,6 +1701,90 @@ void ReferenceCalcCustomHbondForceKernel::copyParametersToContext(ContextImpl& c
...
@@ -1582,6 +1701,90 @@ void ReferenceCalcCustomHbondForceKernel::copyParametersToContext(ContextImpl& c
}
}
}
}
ReferenceCalcCustomCentroidBondForceKernel
::~
ReferenceCalcCustomCentroidBondForceKernel
()
{
disposeRealArray
(
bondParamArray
,
numBonds
);
if
(
ixn
!=
NULL
)
delete
ixn
;
}
void
ReferenceCalcCustomCentroidBondForceKernel
::
initialize
(
const
System
&
system
,
const
CustomCentroidBondForce
&
force
)
{
// Build the arrays.
int
numGroups
=
force
.
getNumGroups
();
vector
<
vector
<
int
>
>
groupAtoms
(
numGroups
);
vector
<
double
>
ignored
;
for
(
int
i
=
0
;
i
<
numGroups
;
i
++
)
force
.
getGroupParameters
(
i
,
groupAtoms
[
i
],
ignored
);
vector
<
vector
<
double
>
>
normalizedWeights
;
CustomCentroidBondForceImpl
::
computeNormalizedWeights
(
force
,
system
,
normalizedWeights
);
numBonds
=
force
.
getNumBonds
();
vector
<
vector
<
int
>
>
bondGroups
(
numBonds
);
int
numBondParameters
=
force
.
getNumPerBondParameters
();
bondParamArray
=
allocateRealArray
(
numBonds
,
numBondParameters
);
for
(
int
i
=
0
;
i
<
numBonds
;
++
i
)
{
vector
<
double
>
parameters
;
force
.
getBondParameters
(
i
,
bondGroups
[
i
],
parameters
);
for
(
int
j
=
0
;
j
<
numBondParameters
;
j
++
)
bondParamArray
[
i
][
j
]
=
static_cast
<
RealOpenMM
>
(
parameters
[
j
]);
}
// Create custom functions for the tabulated functions.
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
for
(
int
i
=
0
;
i
<
force
.
getNumFunctions
();
i
++
)
functions
[
force
.
getTabulatedFunctionName
(
i
)]
=
createReferenceTabulatedFunction
(
force
.
getTabulatedFunction
(
i
));
// Parse the expression and create the object used to calculate the interaction.
map
<
string
,
vector
<
int
>
>
distances
;
map
<
string
,
vector
<
int
>
>
angles
;
map
<
string
,
vector
<
int
>
>
dihedrals
;
Lepton
::
ParsedExpression
energyExpression
=
CustomCentroidBondForceImpl
::
prepareExpression
(
force
,
functions
,
distances
,
angles
,
dihedrals
);
vector
<
string
>
bondParameterNames
;
for
(
int
i
=
0
;
i
<
numBondParameters
;
i
++
)
bondParameterNames
.
push_back
(
force
.
getPerBondParameterName
(
i
));
for
(
int
i
=
0
;
i
<
force
.
getNumGlobalParameters
();
i
++
)
globalParameterNames
.
push_back
(
force
.
getGlobalParameterName
(
i
));
ixn
=
new
ReferenceCustomCentroidBondIxn
(
force
.
getNumGroupsPerBond
(),
groupAtoms
,
normalizedWeights
,
bondGroups
,
energyExpression
,
bondParameterNames
,
distances
,
angles
,
dihedrals
);
// Delete the custom functions.
for
(
map
<
string
,
Lepton
::
CustomFunction
*>::
iterator
iter
=
functions
.
begin
();
iter
!=
functions
.
end
();
iter
++
)
delete
iter
->
second
;
}
double
ReferenceCalcCustomCentroidBondForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
RealOpenMM
energy
=
0
;
map
<
string
,
double
>
globalParameters
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
globalParameters
[
globalParameterNames
[
i
]]
=
context
.
getParameter
(
globalParameterNames
[
i
]);
ixn
->
calculatePairIxn
(
posData
,
bondParamArray
,
globalParameters
,
forceData
,
includeEnergy
?
&
energy
:
NULL
);
return
energy
;
}
void
ReferenceCalcCustomCentroidBondForceKernel
::
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomCentroidBondForce
&
force
)
{
if
(
numBonds
!=
force
.
getNumBonds
())
throw
OpenMMException
(
"updateParametersInContext: The number of bonds has changed"
);
// Record the values.
int
numParameters
=
force
.
getNumPerBondParameters
();
const
vector
<
vector
<
int
>
>&
bondGroups
=
ixn
->
getBondGroups
();
vector
<
int
>
groups
;
vector
<
double
>
params
;
for
(
int
i
=
0
;
i
<
numBonds
;
++
i
)
{
force
.
getBondParameters
(
i
,
groups
,
params
);
for
(
int
j
=
0
;
j
<
groups
.
size
();
j
++
)
if
(
groups
[
j
]
!=
bondGroups
[
i
][
j
])
throw
OpenMMException
(
"updateParametersInContext: The set of groups in a bond has changed"
);
for
(
int
j
=
0
;
j
<
numParameters
;
j
++
)
bondParamArray
[
i
][
j
]
=
(
RealOpenMM
)
params
[
j
];
}
}
ReferenceCalcCustomCompoundBondForceKernel
::~
ReferenceCalcCustomCompoundBondForceKernel
()
{
ReferenceCalcCustomCompoundBondForceKernel
::~
ReferenceCalcCustomCompoundBondForceKernel
()
{
disposeRealArray
(
bondParamArray
,
numBonds
);
disposeRealArray
(
bondParamArray
,
numBonds
);
if
(
ixn
!=
NULL
)
if
(
ixn
!=
NULL
)
...
@@ -1593,7 +1796,6 @@ void ReferenceCalcCustomCompoundBondForceKernel::initialize(const System& system
...
@@ -1593,7 +1796,6 @@ void ReferenceCalcCustomCompoundBondForceKernel::initialize(const System& system
// Build the arrays.
// Build the arrays.
numBonds
=
force
.
getNumBonds
();
numBonds
=
force
.
getNumBonds
();
numParticles
=
system
.
getNumParticles
();
vector
<
vector
<
int
>
>
bondParticles
(
numBonds
);
vector
<
vector
<
int
>
>
bondParticles
(
numBonds
);
int
numBondParameters
=
force
.
getNumPerBondParameters
();
int
numBondParameters
=
force
.
getNumPerBondParameters
();
bondParamArray
=
allocateRealArray
(
numBonds
,
numBondParameters
);
bondParamArray
=
allocateRealArray
(
numBonds
,
numBondParameters
);
...
@@ -1652,7 +1854,7 @@ void ReferenceCalcCustomCompoundBondForceKernel::copyParametersToContext(Context
...
@@ -1652,7 +1854,7 @@ void ReferenceCalcCustomCompoundBondForceKernel::copyParametersToContext(Context
vector
<
double
>
params
;
vector
<
double
>
params
;
for
(
int
i
=
0
;
i
<
numBonds
;
++
i
)
{
for
(
int
i
=
0
;
i
<
numBonds
;
++
i
)
{
force
.
getBondParameters
(
i
,
particles
,
params
);
force
.
getBondParameters
(
i
,
particles
,
params
);
for
(
int
j
=
0
;
j
<
numP
articles
;
j
++
)
for
(
int
j
=
0
;
j
<
p
articles
.
size
()
;
j
++
)
if
(
particles
[
j
]
!=
bondAtoms
[
i
][
j
])
if
(
particles
[
j
]
!=
bondAtoms
[
i
][
j
])
throw
OpenMMException
(
"updateParametersInContext: The set of particles in a bond has changed"
);
throw
OpenMMException
(
"updateParametersInContext: The set of particles in a bond has changed"
);
for
(
int
j
=
0
;
j
<
numParameters
;
j
++
)
for
(
int
j
=
0
;
j
<
numParameters
;
j
++
)
...
...
platforms/reference/src/ReferencePlatform.cpp
View file @
fd473eea
...
@@ -62,6 +62,7 @@ ReferencePlatform::ReferencePlatform() {
...
@@ -62,6 +62,7 @@ ReferencePlatform::ReferencePlatform() {
registerKernelFactory
(
CalcCustomGBForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomGBForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomExternalForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomExternalForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomHbondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomHbondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCentroidBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomCompoundBondForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
CalcCustomManyParticleForceKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
registerKernelFactory
(
IntegrateVerletStepKernel
::
Name
(),
factory
);
...
...
platforms/reference/src/SimTKReference/ReferenceConstraints.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2013 Stanford University and the Authors.
*
* Portions copyright (c) 2013
-2015
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -98,14 +98,13 @@ ReferenceConstraints::ReferenceConstraints(const System& system) : ccma(NULL), s
...
@@ -98,14 +98,13 @@ ReferenceConstraints::ReferenceConstraints(const System& system) : ccma(NULL), s
// Record the SETTLE clusters.
// Record the SETTLE clusters.
vector
<
bool
>
isSettleAtom
(
numParticles
,
false
);
vector
<
bool
>
isSettleAtom
(
numParticles
,
false
);
int
numSETTLE
=
settleClusters
.
size
();
if
(
settleClusters
.
size
()
>
0
)
{
if
(
numSETTLE
>
0
)
{
vector
<
int
>
atom1
;
vector
<
int
>
atom1
(
numSETTLE
);
vector
<
int
>
atom2
;
vector
<
int
>
atom2
(
numSETTLE
);
vector
<
int
>
atom3
;
vector
<
int
>
atom3
(
numSETTLE
);
vector
<
RealOpenMM
>
distance1
;
vector
<
RealOpenMM
>
distance1
(
numSETTLE
);
vector
<
RealOpenMM
>
distance2
;
vector
<
RealOpenMM
>
distance2
(
numSETTLE
);
for
(
int
i
=
0
;
i
<
settleClusters
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
numSETTLE
;
i
++
)
{
int
p1
=
settleClusters
[
i
];
int
p1
=
settleClusters
[
i
];
int
p2
=
settleConstraints
[
p1
].
begin
()
->
first
;
int
p2
=
settleConstraints
[
p1
].
begin
()
->
first
;
int
p3
=
(
++
settleConstraints
[
p1
].
begin
())
->
first
;
int
p3
=
(
++
settleConstraints
[
p1
].
begin
())
->
first
;
...
@@ -114,35 +113,36 @@ ReferenceConstraints::ReferenceConstraints(const System& system) : ccma(NULL), s
...
@@ -114,35 +113,36 @@ ReferenceConstraints::ReferenceConstraints(const System& system) : ccma(NULL), s
float
dist23
=
settleConstraints
[
p2
].
find
(
p3
)
->
second
;
float
dist23
=
settleConstraints
[
p2
].
find
(
p3
)
->
second
;
if
(
dist12
==
dist13
)
{
if
(
dist12
==
dist13
)
{
// p1 is the central atom
// p1 is the central atom
atom1
[
i
]
=
p1
;
atom1
.
push_back
(
p1
)
;
atom2
[
i
]
=
p2
;
atom2
.
push_back
(
p2
)
;
atom3
[
i
]
=
p3
;
atom3
.
push_back
(
p3
)
;
distance1
[
i
]
=
dist12
;
distance1
.
push_back
(
dist12
)
;
distance2
[
i
]
=
dist23
;
distance2
.
push_back
(
dist23
)
;
}
}
else
if
(
dist12
==
dist23
)
{
else
if
(
dist12
==
dist23
)
{
// p2 is the central atom
// p2 is the central atom
atom1
[
i
]
=
p2
;
atom1
.
push_back
(
p2
)
;
atom2
[
i
]
=
p1
;
atom2
.
push_back
(
p1
)
;
atom3
[
i
]
=
p3
;
atom3
.
push_back
(
p3
)
;
distance1
[
i
]
=
dist12
;
distance1
.
push_back
(
dist12
)
;
distance2
[
i
]
=
dist13
;
distance2
.
push_back
(
dist13
)
;
}
}
else
if
(
dist13
==
dist23
)
{
else
if
(
dist13
==
dist23
)
{
// p3 is the central atom
// p3 is the central atom
atom1
[
i
]
=
p3
;
atom1
.
push_back
(
p3
)
;
atom2
[
i
]
=
p1
;
atom2
.
push_back
(
p1
)
;
atom3
[
i
]
=
p2
;
atom3
.
push_back
(
p2
)
;
distance1
[
i
]
=
dist13
;
distance1
.
push_back
(
dist13
)
;
distance2
[
i
]
=
dist12
;
distance2
.
push_back
(
dist12
)
;
}
}
else
else
throw
OpenMMException
(
"Two of the three distances constrained with SETTLE must be the same."
);
continue
;
// We can't handle this with SETTLE
isSettleAtom
[
p1
]
=
true
;
isSettleAtom
[
p1
]
=
true
;
isSettleAtom
[
p2
]
=
true
;
isSettleAtom
[
p2
]
=
true
;
isSettleAtom
[
p3
]
=
true
;
isSettleAtom
[
p3
]
=
true
;
}
}
settle
=
new
ReferenceSETTLEAlgorithm
(
atom1
,
atom2
,
atom3
,
distance1
,
distance2
,
masses
);
if
(
atom1
.
size
()
>
0
)
settle
=
new
ReferenceSETTLEAlgorithm
(
atom1
,
atom2
,
atom3
,
distance1
,
distance2
,
masses
);
}
}
// All other constraints are handled with CCMA.
// All other constraints are handled with CCMA.
...
...
platforms/reference/src/SimTKReference/ReferenceCustomCentroidBondIxn.cpp
0 → 100644
View file @
fd473eea
/* Portions copyright (c) 2009-2015 Stanford University and Simbios.
* Contributors: Peter Eastman
*
* 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 <string.h>
#include <sstream>
#include <utility>
#include "SimTKOpenMMUtilities.h"
#include "ReferenceForce.h"
#include "ReferenceCustomCentroidBondIxn.h"
using
std
::
map
;
using
std
::
pair
;
using
std
::
string
;
using
std
::
stringstream
;
using
std
::
vector
;
using
namespace
OpenMM
;
ReferenceCustomCentroidBondIxn
::
ReferenceCustomCentroidBondIxn
(
int
numGroupsPerBond
,
const
vector
<
vector
<
int
>
>&
groupAtoms
,
const
vector
<
vector
<
double
>
>&
normalizedWeights
,
const
vector
<
vector
<
int
>
>&
bondGroups
,
const
Lepton
::
ParsedExpression
&
energyExpression
,
const
vector
<
string
>&
bondParameterNames
,
const
map
<
string
,
vector
<
int
>
>&
distances
,
const
map
<
string
,
vector
<
int
>
>&
angles
,
const
map
<
string
,
vector
<
int
>
>&
dihedrals
)
:
groupAtoms
(
groupAtoms
),
normalizedWeights
(
normalizedWeights
),
bondGroups
(
bondGroups
),
energyExpression
(
energyExpression
.
createProgram
()),
bondParamNames
(
bondParameterNames
)
{
for
(
int
i
=
0
;
i
<
numGroupsPerBond
;
i
++
)
{
stringstream
xname
,
yname
,
zname
;
xname
<<
'x'
<<
(
i
+
1
);
yname
<<
'y'
<<
(
i
+
1
);
zname
<<
'z'
<<
(
i
+
1
);
positionTerms
.
push_back
(
ReferenceCustomCentroidBondIxn
::
PositionTermInfo
(
xname
.
str
(),
i
,
0
,
energyExpression
.
differentiate
(
xname
.
str
()).
optimize
().
createProgram
()));
positionTerms
.
push_back
(
ReferenceCustomCentroidBondIxn
::
PositionTermInfo
(
yname
.
str
(),
i
,
1
,
energyExpression
.
differentiate
(
yname
.
str
()).
optimize
().
createProgram
()));
positionTerms
.
push_back
(
ReferenceCustomCentroidBondIxn
::
PositionTermInfo
(
zname
.
str
(),
i
,
2
,
energyExpression
.
differentiate
(
zname
.
str
()).
optimize
().
createProgram
()));
}
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
distances
.
begin
();
iter
!=
distances
.
end
();
++
iter
)
distanceTerms
.
push_back
(
ReferenceCustomCentroidBondIxn
::
DistanceTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpression
.
differentiate
(
iter
->
first
).
optimize
().
createProgram
()));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
angles
.
begin
();
iter
!=
angles
.
end
();
++
iter
)
angleTerms
.
push_back
(
ReferenceCustomCentroidBondIxn
::
AngleTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpression
.
differentiate
(
iter
->
first
).
optimize
().
createProgram
()));
for
(
map
<
string
,
vector
<
int
>
>::
const_iterator
iter
=
dihedrals
.
begin
();
iter
!=
dihedrals
.
end
();
++
iter
)
dihedralTerms
.
push_back
(
ReferenceCustomCentroidBondIxn
::
DihedralTermInfo
(
iter
->
first
,
iter
->
second
,
energyExpression
.
differentiate
(
iter
->
first
).
optimize
().
createProgram
()));
}
ReferenceCustomCentroidBondIxn
::~
ReferenceCustomCentroidBondIxn
()
{
}
void
ReferenceCustomCentroidBondIxn
::
calculatePairIxn
(
vector
<
RealVec
>&
atomCoordinates
,
RealOpenMM
**
bondParameters
,
const
map
<
string
,
double
>&
globalParameters
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
// First compute the center of each group.
int
numGroups
=
groupAtoms
.
size
();
vector
<
RealVec
>
groupCenters
(
numGroups
);
for
(
int
group
=
0
;
group
<
numGroups
;
group
++
)
{
for
(
int
i
=
0
;
i
<
groupAtoms
[
group
].
size
();
i
++
)
groupCenters
[
group
]
+=
atomCoordinates
[
groupAtoms
[
group
][
i
]]
*
normalizedWeights
[
group
][
i
];
}
// Compute the forces on groups.
map
<
string
,
double
>
variables
=
globalParameters
;
vector
<
RealVec
>
groupForces
(
numGroups
);
int
numBonds
=
bondGroups
.
size
();
for
(
int
bond
=
0
;
bond
<
numBonds
;
bond
++
)
{
for
(
int
j
=
0
;
j
<
(
int
)
bondParamNames
.
size
();
j
++
)
variables
[
bondParamNames
[
j
]]
=
bondParameters
[
bond
][
j
];
calculateOneIxn
(
bond
,
groupCenters
,
variables
,
groupForces
,
totalEnergy
);
}
// Apply the forces to the individual atoms.
for
(
int
group
=
0
;
group
<
numGroups
;
group
++
)
{
for
(
int
i
=
0
;
i
<
groupAtoms
[
group
].
size
();
i
++
)
forces
[
groupAtoms
[
group
][
i
]]
+=
groupForces
[
group
]
*
normalizedWeights
[
group
][
i
];
}
}
void
ReferenceCustomCentroidBondIxn
::
calculateOneIxn
(
int
bond
,
vector
<
RealVec
>&
groupCenters
,
map
<
string
,
double
>&
variables
,
vector
<
RealVec
>&
forces
,
RealOpenMM
*
totalEnergy
)
const
{
// ---------------------------------------------------------------------------------------
static
const
std
::
string
methodName
=
"
\n
ReferenceCustomCentroidBondIxn::calculateOneIxn"
;
// ---------------------------------------------------------------------------------------
// Compute all of the variables the energy can depend on.
const
vector
<
int
>&
groups
=
bondGroups
[
bond
];
for
(
int
i
=
0
;
i
<
(
int
)
positionTerms
.
size
();
i
++
)
{
const
PositionTermInfo
&
term
=
positionTerms
[
i
];
variables
[
term
.
name
]
=
groupCenters
[
groups
[
term
.
group
]][
term
.
component
];
}
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
computeDelta
(
groups
[
term
.
g1
],
groups
[
term
.
g2
],
term
.
delta
,
groupCenters
);
variables
[
term
.
name
]
=
term
.
delta
[
ReferenceForce
::
RIndex
];
}
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
computeDelta
(
groups
[
term
.
g1
],
groups
[
term
.
g2
],
term
.
delta1
,
groupCenters
);
computeDelta
(
groups
[
term
.
g3
],
groups
[
term
.
g2
],
term
.
delta2
,
groupCenters
);
variables
[
term
.
name
]
=
computeAngle
(
term
.
delta1
,
term
.
delta2
);
}
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
computeDelta
(
groups
[
term
.
g2
],
groups
[
term
.
g1
],
term
.
delta1
,
groupCenters
);
computeDelta
(
groups
[
term
.
g2
],
groups
[
term
.
g3
],
term
.
delta2
,
groupCenters
);
computeDelta
(
groups
[
term
.
g4
],
groups
[
term
.
g3
],
term
.
delta3
,
groupCenters
);
RealOpenMM
dotDihedral
,
signOfDihedral
;
RealOpenMM
*
crossProduct
[]
=
{
term
.
cross1
,
term
.
cross2
};
variables
[
term
.
name
]
=
getDihedralAngleBetweenThreeVectors
(
term
.
delta1
,
term
.
delta2
,
term
.
delta3
,
crossProduct
,
&
dotDihedral
,
term
.
delta1
,
&
signOfDihedral
,
1
);
}
// Apply forces based on individual particle coordinates.
for
(
int
i
=
0
;
i
<
(
int
)
positionTerms
.
size
();
i
++
)
{
const
PositionTermInfo
&
term
=
positionTerms
[
i
];
forces
[
groups
[
term
.
group
]][
term
.
component
]
-=
term
.
forceExpression
.
evaluate
(
variables
);
}
// Apply forces based on distances.
for
(
int
i
=
0
;
i
<
(
int
)
distanceTerms
.
size
();
i
++
)
{
const
DistanceTermInfo
&
term
=
distanceTerms
[
i
];
RealOpenMM
dEdR
=
(
RealOpenMM
)
(
term
.
forceExpression
.
evaluate
(
variables
)
/
(
term
.
delta
[
ReferenceForce
::
RIndex
]));
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
RealOpenMM
force
=
-
dEdR
*
term
.
delta
[
i
];
forces
[
groups
[
term
.
g1
]][
i
]
-=
force
;
forces
[
groups
[
term
.
g2
]][
i
]
+=
force
;
}
}
// Apply forces based on angles.
for
(
int
i
=
0
;
i
<
(
int
)
angleTerms
.
size
();
i
++
)
{
const
AngleTermInfo
&
term
=
angleTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
(
variables
);
RealOpenMM
thetaCross
[
ReferenceForce
::
LastDeltaRIndex
];
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta1
,
term
.
delta2
,
thetaCross
);
RealOpenMM
lengthThetaCross
=
SQRT
(
DOT3
(
thetaCross
,
thetaCross
));
if
(
lengthThetaCross
<
1.0e-06
)
lengthThetaCross
=
(
RealOpenMM
)
1.0e-06
;
RealOpenMM
termA
=
dEdTheta
/
(
term
.
delta1
[
ReferenceForce
::
R2Index
]
*
lengthThetaCross
);
RealOpenMM
termC
=
-
dEdTheta
/
(
term
.
delta2
[
ReferenceForce
::
R2Index
]
*
lengthThetaCross
);
RealOpenMM
deltaCrossP
[
3
][
3
];
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta1
,
thetaCross
,
deltaCrossP
[
0
]);
SimTKOpenMMUtilities
::
crossProductVector3
(
term
.
delta2
,
thetaCross
,
deltaCrossP
[
2
]);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
deltaCrossP
[
0
][
i
]
*=
termA
;
deltaCrossP
[
2
][
i
]
*=
termC
;
deltaCrossP
[
1
][
i
]
=
-
(
deltaCrossP
[
0
][
i
]
+
deltaCrossP
[
2
][
i
]);
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
groups
[
term
.
g1
]][
i
]
+=
deltaCrossP
[
0
][
i
];
forces
[
groups
[
term
.
g2
]][
i
]
+=
deltaCrossP
[
1
][
i
];
forces
[
groups
[
term
.
g3
]][
i
]
+=
deltaCrossP
[
2
][
i
];
}
}
// Apply forces based on dihedrals.
for
(
int
i
=
0
;
i
<
(
int
)
dihedralTerms
.
size
();
i
++
)
{
const
DihedralTermInfo
&
term
=
dihedralTerms
[
i
];
RealOpenMM
dEdTheta
=
(
RealOpenMM
)
term
.
forceExpression
.
evaluate
(
variables
);
RealOpenMM
internalF
[
4
][
3
];
RealOpenMM
forceFactors
[
4
];
RealOpenMM
normCross1
=
DOT3
(
term
.
cross1
,
term
.
cross1
);
RealOpenMM
normBC
=
term
.
delta2
[
ReferenceForce
::
RIndex
];
forceFactors
[
0
]
=
(
-
dEdTheta
*
normBC
)
/
normCross1
;
RealOpenMM
normCross2
=
DOT3
(
term
.
cross2
,
term
.
cross2
);
forceFactors
[
3
]
=
(
dEdTheta
*
normBC
)
/
normCross2
;
forceFactors
[
1
]
=
DOT3
(
term
.
delta1
,
term
.
delta2
);
forceFactors
[
1
]
/=
term
.
delta2
[
ReferenceForce
::
R2Index
];
forceFactors
[
2
]
=
DOT3
(
term
.
delta3
,
term
.
delta2
);
forceFactors
[
2
]
/=
term
.
delta2
[
ReferenceForce
::
R2Index
];
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
internalF
[
0
][
i
]
=
forceFactors
[
0
]
*
term
.
cross1
[
i
];
internalF
[
3
][
i
]
=
forceFactors
[
3
]
*
term
.
cross2
[
i
];
RealOpenMM
s
=
forceFactors
[
1
]
*
internalF
[
0
][
i
]
-
forceFactors
[
2
]
*
internalF
[
3
][
i
];
internalF
[
1
][
i
]
=
internalF
[
0
][
i
]
-
s
;
internalF
[
2
][
i
]
=
internalF
[
3
][
i
]
+
s
;
}
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
forces
[
groups
[
term
.
g1
]][
i
]
+=
internalF
[
0
][
i
];
forces
[
groups
[
term
.
g2
]][
i
]
-=
internalF
[
1
][
i
];
forces
[
groups
[
term
.
g3
]][
i
]
-=
internalF
[
2
][
i
];
forces
[
groups
[
term
.
g4
]][
i
]
+=
internalF
[
3
][
i
];
}
}
// Add the energy
if
(
totalEnergy
)
*
totalEnergy
+=
(
RealOpenMM
)
energyExpression
.
evaluate
(
variables
);
}
void
ReferenceCustomCentroidBondIxn
::
computeDelta
(
int
group1
,
int
group2
,
RealOpenMM
*
delta
,
vector
<
RealVec
>&
groupCenters
)
const
{
ReferenceForce
::
getDeltaR
(
groupCenters
[
group1
],
groupCenters
[
group2
],
delta
);
}
RealOpenMM
ReferenceCustomCentroidBondIxn
::
computeAngle
(
RealOpenMM
*
vec1
,
RealOpenMM
*
vec2
)
{
RealOpenMM
dot
=
DOT3
(
vec1
,
vec2
);
RealOpenMM
cosine
=
dot
/
SQRT
((
vec1
[
ReferenceForce
::
R2Index
]
*
vec2
[
ReferenceForce
::
R2Index
]));
RealOpenMM
angle
;
if
(
cosine
>=
1
)
angle
=
0
;
else
if
(
cosine
<=
-
1
)
angle
=
PI_M
;
else
angle
=
ACOS
(
cosine
);
return
angle
;
}
platforms/reference/src/SimTKReference/ReferenceStochasticDynamics.cpp
View file @
fd473eea
...
@@ -163,11 +163,21 @@ void ReferenceStochasticDynamics::updatePart2(int numberOfAtoms, vector<RealVec>
...
@@ -163,11 +163,21 @@ void ReferenceStochasticDynamics::updatePart2(int numberOfAtoms, vector<RealVec>
for
(
int
ii
=
0
;
ii
<
numberOfAtoms
;
ii
++
)
{
for
(
int
ii
=
0
;
ii
<
numberOfAtoms
;
ii
++
)
{
if
(
inverseMasses
[
ii
]
!=
0.0
)
if
(
inverseMasses
[
ii
]
!=
0.0
)
for
(
int
jj
=
0
;
jj
<
3
;
jj
++
)
xPrime
[
ii
]
=
atomCoordinates
[
ii
]
+
velocities
[
ii
]
*
getDeltaT
();
xPrime
[
ii
][
jj
]
=
atomCoordinates
[
ii
][
jj
]
+
getDeltaT
()
*
velocities
[
ii
][
jj
];
}
}
}
}
void
ReferenceStochasticDynamics
::
updatePart3
(
int
numberOfAtoms
,
vector
<
RealVec
>&
atomCoordinates
,
vector
<
RealVec
>&
velocities
,
vector
<
RealOpenMM
>&
inverseMasses
,
vector
<
RealVec
>&
xPrime
)
{
RealOpenMM
invStepSize
=
1.0
/
getDeltaT
();
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
++
i
)
if
(
inverseMasses
[
i
]
!=
0
)
{
velocities
[
i
]
=
(
xPrime
[
i
]
-
atomCoordinates
[
i
])
*
invStepSize
;
atomCoordinates
[
i
]
=
xPrime
[
i
];
}
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Update -- driver routine for performing stochastic dynamics update of coordinates
Update -- driver routine for performing stochastic dynamics update of coordinates
...
@@ -221,13 +231,7 @@ void ReferenceStochasticDynamics::update(const OpenMM::System& system, vector<Re
...
@@ -221,13 +231,7 @@ void ReferenceStochasticDynamics::update(const OpenMM::System& system, vector<Re
// copy xPrime -> atomCoordinates
// copy xPrime -> atomCoordinates
RealOpenMM
invStepSize
=
1.0
/
getDeltaT
();
updatePart3
(
numberOfAtoms
,
atomCoordinates
,
velocities
,
inverseMasses
,
xPrime
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
++
i
)
if
(
masses
[
i
]
!=
zero
)
for
(
int
j
=
0
;
j
<
3
;
++
j
)
{
velocities
[
i
][
j
]
=
invStepSize
*
(
xPrime
[
i
][
j
]
-
atomCoordinates
[
i
][
j
]);
atomCoordinates
[
i
][
j
]
=
xPrime
[
i
][
j
];
}
ReferenceVirtualSites
::
computePositions
(
system
,
atomCoordinates
);
ReferenceVirtualSites
::
computePositions
(
system
,
atomCoordinates
);
incrementTimeStep
();
incrementTimeStep
();
...
...
platforms/reference/tests/CMakeLists.txt
View file @
fd473eea
...
@@ -15,7 +15,7 @@ FOREACH(TEST_PROG ${TEST_PROGS})
...
@@ -15,7 +15,7 @@ FOREACH(TEST_PROG ${TEST_PROGS})
ELSE
(
OPENMM_BUILD_SHARED_LIB
)
ELSE
(
OPENMM_BUILD_SHARED_LIB
)
TARGET_LINK_LIBRARIES
(
${
TEST_ROOT
}
${
STATIC_TARGET
}
)
TARGET_LINK_LIBRARIES
(
${
TEST_ROOT
}
${
STATIC_TARGET
}
)
ENDIF
(
OPENMM_BUILD_SHARED_LIB
)
ENDIF
(
OPENMM_BUILD_SHARED_LIB
)
SET_TARGET_PROPERTIES
(
${
TEST_ROOT
}
PROPERTIES LINK_FLAGS
"
${
EXTRA_
COMPILE
_FLAGS
}
"
COMPILE_FLAGS
"
${
EXTRA_COMPILE_FLAGS
}
"
)
SET_TARGET_PROPERTIES
(
${
TEST_ROOT
}
PROPERTIES LINK_FLAGS
"
${
EXTRA_
LINK
_FLAGS
}
"
COMPILE_FLAGS
"
${
EXTRA_COMPILE_FLAGS
}
"
)
ADD_TEST
(
${
TEST_ROOT
}
${
EXECUTABLE_OUTPUT_PATH
}
/
${
TEST_ROOT
}
)
ADD_TEST
(
${
TEST_ROOT
}
${
EXECUTABLE_OUTPUT_PATH
}
/
${
TEST_ROOT
}
)
ENDFOREACH
(
TEST_PROG
${
TEST_PROGS
}
)
ENDFOREACH
(
TEST_PROG
${
TEST_PROGS
}
)
...
...
platforms/reference/tests/ReferenceTests.h
0 → 100644
View file @
fd473eea
/* -------------------------------------------------------------------------- *
* 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) 2015 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 "ReferencePlatform.h"
OpenMM
::
ReferencePlatform
platform
;
void
initializeTests
(
int
argc
,
char
*
argv
[])
{
}
platforms/reference/tests/TestReferenceAndersenThermostat.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08-2009
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,190 +29,8 @@
...
@@ -29,190 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of AndersenThermostat.
#include "TestAndersenThermostat.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/AndersenThermostat.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
void
testTemperature
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
const
double
collisionFreq
=
10.0
;
const
int
numSteps
=
5000
;
System
system
;
VerletIntegrator
integrator
(
0.003
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
forceField
);
AndersenThermostat
*
thermostat
=
new
AndersenThermostat
(
temp
,
collisionFreq
);
system
.
addForce
(
thermostat
);
ASSERT
(
!
thermostat
->
usesPeriodicBoundaryConditions
());
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
positions
[
i
]
=
Vec3
((
i
%
2
==
0
?
2
:
-
2
),
(
i
%
4
<
2
?
2
:
-
2
),
(
i
<
4
?
2
:
-
2
));
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
temp
);
// Let it equilibrate.
integrator
.
step
(
10000
);
// Now run it for a while and see if the temperature is correct.
double
ke
=
0.0
;
for
(
int
i
=
0
;
i
<
numSteps
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Energy
);
ke
+=
state
.
getKineticEnergy
();
integrator
.
step
(
10
);
}
ke
/=
numSteps
;
double
expected
=
0.5
*
numParticles
*
3
*
BOLTZ
*
temp
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
ke
,
0.1
);
}
void
testConstraints
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
const
double
collisionFreq
=
10.0
;
const
int
numSteps
=
15000
;
System
system
;
VerletIntegrator
integrator
(
0.004
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
forceField
);
system
.
addConstraint
(
0
,
1
,
1
);
system
.
addConstraint
(
1
,
2
,
1
);
system
.
addConstraint
(
2
,
3
,
1
);
system
.
addConstraint
(
3
,
0
,
1
);
system
.
addConstraint
(
4
,
5
,
1
);
system
.
addConstraint
(
5
,
6
,
1
);
system
.
addConstraint
(
6
,
7
,
1
);
system
.
addConstraint
(
7
,
4
,
1
);
AndersenThermostat
*
thermostat
=
new
AndersenThermostat
(
temp
,
collisionFreq
);
system
.
addForce
(
thermostat
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
positions
[
2
]
=
Vec3
(
1
,
1
,
0
);
positions
[
3
]
=
Vec3
(
0
,
1
,
0
);
positions
[
4
]
=
Vec3
(
1
,
0
,
1
);
positions
[
5
]
=
Vec3
(
1
,
1
,
1
);
positions
[
6
]
=
Vec3
(
0
,
1
,
1
);
positions
[
7
]
=
Vec3
(
0
,
0
,
1
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
temp
);
// Let it equilibrate.
integrator
.
step
(
5000
);
// Now run it for a while and see if the temperature is correct.
double
ke
=
0.0
;
for
(
int
i
=
0
;
i
<
numSteps
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Energy
);
ke
+=
state
.
getKineticEnergy
();
integrator
.
step
(
1
);
}
ke
/=
numSteps
;
double
expected
=
0.5
*
(
numParticles
*
3
-
system
.
getNumConstraints
())
*
BOLTZ
*
temp
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
ke
,
0.1
);
}
void
testRandomSeed
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
const
double
collisionFreq
=
10.0
;
System
system
;
VerletIntegrator
integrator
(
0.01
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
forceField
);
AndersenThermostat
*
thermostat
=
new
AndersenThermostat
(
temp
,
collisionFreq
);
system
.
addForce
(
thermostat
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
((
i
%
2
==
0
?
2
:
-
2
),
(
i
%
4
<
2
?
2
:
-
2
),
(
i
<
4
?
2
:
-
2
));
velocities
[
i
]
=
Vec3
(
0
,
0
,
0
);
}
// Try twice with the same random seed.
thermostat
->
setRandomNumberSeed
(
5
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state1
=
context
.
getState
(
State
::
Positions
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state2
=
context
.
getState
(
State
::
Positions
);
// Try twice with a different random seed.
thermostat
->
setRandomNumberSeed
(
10
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state3
=
context
.
getState
(
State
::
Positions
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state4
=
context
.
getState
(
State
::
Positions
);
// Compare the results.
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
ASSERT
(
state1
.
getPositions
()[
i
][
j
]
==
state2
.
getPositions
()[
i
][
j
]);
ASSERT
(
state3
.
getPositions
()[
i
][
j
]
==
state4
.
getPositions
()[
i
][
j
]);
ASSERT
(
state1
.
getPositions
()[
i
][
j
]
!=
state3
.
getPositions
()[
i
][
j
]);
}
}
}
int
main
()
{
try
{
testTemperature
();
testConstraints
();
testRandomSeed
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
}
platforms/reference/tests/TestReferenceBrownianIntegrator.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,241 +29,8 @@
...
@@ -29,241 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of BrownianIntegrator.
#include "TestBrownianIntegrator.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/BrownianIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testSingleBond
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
double
dt
=
0.01
;
BrownianIntegrator
integrator
(
0
,
0.1
,
dt
);
HarmonicBondForce
*
forceField
=
new
HarmonicBondForce
();
forceField
->
addBond
(
0
,
1
,
1.5
,
1
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
// This is simply an overdamped harmonic oscillator, so compare it to the analytical solution.
double
rate
=
2
*
1.0
/
(
0.1
*
2.0
);
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
);
double
time
=
state
.
getTime
();
double
expectedDist
=
1.5
+
0.5
*
std
::
exp
(
-
rate
*
time
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
*
expectedDist
,
0
,
0
),
state
.
getPositions
()[
0
],
0.02
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.5
*
expectedDist
,
0
,
0
),
state
.
getPositions
()[
1
],
0.02
);
if
(
i
>
0
)
{
double
expectedSpeed
=
-
0.5
*
rate
*
std
::
exp
(
-
rate
*
(
time
-
0.5
*
dt
));
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
*
expectedSpeed
,
0
,
0
),
state
.
getVelocities
()[
0
],
0.11
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.5
*
expectedSpeed
,
0
,
0
),
state
.
getVelocities
()[
1
],
0.11
);
}
integrator
.
step
(
1
);
}
}
void
testTemperature
()
{
const
int
numParticles
=
8
;
const
int
numBonds
=
numParticles
-
1
;
const
double
temp
=
10.0
;
System
system
;
BrownianIntegrator
integrator
(
temp
,
2.0
,
0.01
);
HarmonicBondForce
*
forceField
=
new
HarmonicBondForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
}
for
(
int
i
=
0
;
i
<
numBonds
;
++
i
)
forceField
->
addBond
(
i
,
i
+
1
,
1.0
,
5.0
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
positions
[
i
]
=
Vec3
(
i
,
0
,
0
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
10000
);
// Now run it for a while and see if the temperature is correct.
double
pe
=
0.0
;
const
int
steps
=
50000
;
for
(
int
i
=
0
;
i
<
steps
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Energy
);
pe
+=
state
.
getPotentialEnergy
();
integrator
.
step
(
1
);
}
pe
/=
steps
;
double
expected
=
0.5
*
numBonds
*
BOLTZ
*
temp
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
pe
,
0.1
*
expected
);
}
void
testConstraints
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
System
system
;
BrownianIntegrator
integrator
(
temp
,
2.0
,
0.001
);
integrator
.
setConstraintTolerance
(
1e-5
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
10.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
0.2
:
-
0.2
),
0.5
,
5.0
);
}
for
(
int
i
=
0
;
i
<
numParticles
-
1
;
++
i
)
system
.
addConstraint
(
i
,
i
+
1
,
1.0
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
(
i
/
2
,
(
i
+
1
)
/
2
,
0
);
velocities
[
i
]
=
Vec3
(
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
);
}
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
// Simulate it and see whether the constraints remain satisfied.
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Positions
);
for
(
int
j
=
0
;
j
<
numParticles
-
1
;
++
j
)
{
Vec3
p1
=
state
.
getPositions
()[
j
];
Vec3
p2
=
state
.
getPositions
()[
j
+
1
];
double
dist
=
std
::
sqrt
((
p1
[
0
]
-
p2
[
0
])
*
(
p1
[
0
]
-
p2
[
0
])
+
(
p1
[
1
]
-
p2
[
1
])
*
(
p1
[
1
]
-
p2
[
1
])
+
(
p1
[
2
]
-
p2
[
2
])
*
(
p1
[
2
]
-
p2
[
2
]));
ASSERT_EQUAL_TOL
(
1.0
,
dist
,
2e-5
);
}
integrator
.
step
(
1
);
}
}
void
testConstrainedMasslessParticles
()
{
System
system
;
system
.
addParticle
(
0.0
);
system
.
addParticle
(
1.0
);
system
.
addConstraint
(
0
,
1
,
1.5
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
BrownianIntegrator
integrator
(
300.0
,
2.0
,
0.01
);
bool
failed
=
false
;
try
{
// This should throw an exception.
Context
context
(
system
,
integrator
,
platform
);
}
catch
(
exception
&
ex
)
{
failed
=
true
;
}
ASSERT
(
failed
);
// Now make both particles massless, which should work.
system
.
setParticleMass
(
1
,
0.0
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
300.0
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
ASSERT_EQUAL
(
0.0
,
state
.
getVelocities
()[
0
][
0
]);
}
void
testRandomSeed
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
const
double
collisionFreq
=
10.0
;
System
system
;
BrownianIntegrator
integrator
(
temp
,
2.0
,
0.001
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
forceField
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
((
i
%
2
==
0
?
2
:
-
2
),
(
i
%
4
<
2
?
2
:
-
2
),
(
i
<
4
?
2
:
-
2
));
velocities
[
i
]
=
Vec3
(
0
,
0
,
0
);
}
// Try twice with the same random seed.
integrator
.
setRandomNumberSeed
(
5
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state1
=
context
.
getState
(
State
::
Positions
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state2
=
context
.
getState
(
State
::
Positions
);
// Try twice with a different random seed.
integrator
.
setRandomNumberSeed
(
10
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state3
=
context
.
getState
(
State
::
Positions
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
integrator
.
step
(
10
);
State
state4
=
context
.
getState
(
State
::
Positions
);
// Compare the results.
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
ASSERT
(
state1
.
getPositions
()[
i
][
j
]
==
state2
.
getPositions
()[
i
][
j
]);
ASSERT
(
state3
.
getPositions
()[
i
][
j
]
==
state4
.
getPositions
()[
i
][
j
]);
ASSERT
(
state1
.
getPositions
()[
i
][
j
]
!=
state3
.
getPositions
()[
i
][
j
]);
}
}
}
int
main
()
{
try
{
testSingleBond
();
testTemperature
();
testConstraints
();
testConstrainedMasslessParticles
();
testRandomSeed
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
}
platforms/reference/tests/TestReferenceCMAPTorsionForce.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c)
2010-
2015 Stanford University and the Authors. *
* Portions copyright (c) 2015 Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,152 +29,8 @@
...
@@ -29,152 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of CMAPTorsionForce.
#include "TestCMAPTorsionForce.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/CMAPTorsionForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testCMAPTorsions
()
{
const
int
mapSize
=
36
;
// Create two systems: one with a pair of periodic torsions, and one with a CMAP torsion
// that approximates the same force.
System
system1
;
for
(
int
i
=
0
;
i
<
5
;
i
++
)
system1
.
addParticle
(
1.0
);
PeriodicTorsionForce
*
periodic
=
new
PeriodicTorsionForce
();
periodic
->
addTorsion
(
0
,
1
,
2
,
3
,
2
,
M_PI
/
4
,
1.5
);
periodic
->
addTorsion
(
1
,
2
,
3
,
4
,
3
,
M_PI
/
3
,
2.0
);
system1
.
addForce
(
periodic
);
ASSERT
(
!
periodic
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
system1
.
usesPeriodicBoundaryConditions
());
System
system2
;
for
(
int
i
=
0
;
i
<
5
;
i
++
)
system2
.
addParticle
(
1.0
);
CMAPTorsionForce
*
cmap
=
new
CMAPTorsionForce
();
vector
<
double
>
mapEnergy
(
mapSize
*
mapSize
);
for
(
int
i
=
0
;
i
<
mapSize
;
i
++
)
{
double
angle1
=
i
*
2
*
M_PI
/
mapSize
;
double
energy1
=
1.5
*
(
1
+
cos
(
2
*
angle1
-
M_PI
/
4
));
for
(
int
j
=
0
;
j
<
mapSize
;
j
++
)
{
double
angle2
=
j
*
2
*
M_PI
/
mapSize
;
double
energy2
=
2.0
*
(
1
+
cos
(
3
*
angle2
-
M_PI
/
3
));
mapEnergy
[
i
+
j
*
mapSize
]
=
energy1
+
energy2
;
}
}
cmap
->
addMap
(
mapSize
,
mapEnergy
);
cmap
->
addTorsion
(
0
,
0
,
1
,
2
,
3
,
1
,
2
,
3
,
4
);
system2
.
addForce
(
cmap
);
ASSERT
(
!
cmap
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
system2
.
usesPeriodicBoundaryConditions
());
// Set the atoms in various positions, and verify that both systems give equal forces and energy.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
(
5
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
system1
,
integrator1
,
platform
);
Context
c2
(
system2
,
integrator2
,
platform
);
for
(
int
i
=
0
;
i
<
50
;
i
++
)
{
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c2
.
setPositions
(
positions
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
for
(
int
i
=
0
;
i
<
system1
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s1
.
getForces
()[
i
],
s2
.
getForces
()[
i
],
0.05
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
s2
.
getPotentialEnergy
(),
1e-3
);
}
}
void
testChangingParameters
()
{
// Create a system with two maps and one torsion.
const
int
mapSize
=
8
;
System
system
;
for
(
int
i
=
0
;
i
<
5
;
i
++
)
system
.
addParticle
(
1.0
);
CMAPTorsionForce
*
cmap
=
new
CMAPTorsionForce
();
vector
<
double
>
mapEnergy1
(
mapSize
*
mapSize
);
vector
<
double
>
mapEnergy2
(
mapSize
*
mapSize
);
for
(
int
i
=
0
;
i
<
mapSize
;
i
++
)
{
double
angle1
=
i
*
2
*
M_PI
/
mapSize
;
double
energy1
=
cos
(
angle1
);
for
(
int
j
=
0
;
j
<
mapSize
;
j
++
)
{
double
angle2
=
j
*
2
*
M_PI
/
mapSize
;
double
energy2
=
10
*
sin
(
angle2
);
mapEnergy1
[
i
+
j
*
mapSize
]
=
energy1
+
energy2
;
mapEnergy2
[
i
+
j
*
mapSize
]
=
energy1
-
energy2
;
}
}
cmap
->
addMap
(
mapSize
,
mapEnergy1
);
cmap
->
addMap
(
mapSize
,
mapEnergy2
);
cmap
->
addTorsion
(
0
,
0
,
1
,
2
,
3
,
1
,
2
,
3
,
4
);
system
.
addForce
(
cmap
);
// Set particle positions so angle1=0 and angle2=PI/4.
vector
<
Vec3
>
positions
(
5
);
positions
[
0
]
=
Vec3
(
0
,
0
,
1
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
positions
[
3
]
=
Vec3
(
1
,
0
,
1
);
positions
[
4
]
=
Vec3
(
0.5
,
-
0.5
,
1
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Check that the energy is correct.
double
energy
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
1
+
10
*
sin
(
M_PI
/
4
),
energy
,
1e-5
);
// Modify the parameters.
cmap
->
setTorsionParameters
(
0
,
1
,
0
,
1
,
2
,
3
,
1
,
2
,
3
,
4
);
for
(
int
i
=
0
;
i
<
mapSize
*
mapSize
;
i
++
)
mapEnergy2
[
i
]
*=
2.0
;
cmap
->
setMapParameters
(
1
,
mapSize
,
mapEnergy2
);
cmap
->
updateParametersInContext
(
context
);
// See if the results are correct.
energy
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
2
-
20
*
sin
(
M_PI
/
4
),
energy
,
1e-5
);
}
}
int
main
()
{
try
{
testCMAPTorsions
();
testChangingParameters
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCMMotionRemover.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,89 +29,8 @@
...
@@ -29,89 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of AndersenThermostat.
#include "TestCMMotionRemover.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/CMMotionRemover.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
Vec3
calcCM
(
const
vector
<
Vec3
>&
values
,
System
&
system
)
{
Vec3
cm
;
for
(
int
j
=
0
;
j
<
system
.
getNumParticles
();
++
j
)
{
cm
[
0
]
+=
values
[
j
][
0
]
*
system
.
getParticleMass
(
j
);
cm
[
1
]
+=
values
[
j
][
1
]
*
system
.
getParticleMass
(
j
);
cm
[
2
]
+=
values
[
j
][
2
]
*
system
.
getParticleMass
(
j
);
}
return
cm
;
}
void
testMotionRemoval
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
const
double
collisionFreq
=
10.0
;
System
system
;
VerletIntegrator
integrator
(
0.01
);
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
bonds
->
addBond
(
2
,
3
,
2.0
,
0.5
);
system
.
addForce
(
bonds
);
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
i
+
1
);
nonbonded
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
nonbonded
);
CMMotionRemover
*
remover
=
new
CMMotionRemover
();
system
.
addForce
(
remover
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
((
i
%
2
==
0
?
2
:
-
2
),
(
i
%
4
<
2
?
2
:
-
2
),
(
i
<
4
?
2
:
-
2
));
velocities
[
i
]
=
Vec3
(
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
);
}
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
// Now run it for a while and see if the center of mass remains fixed.
Vec3
cmPos
=
calcCM
(
context
.
getState
(
State
::
Positions
).
getPositions
(),
system
);
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
);
Vec3
pos
=
calcCM
(
state
.
getPositions
(),
system
);
ASSERT_EQUAL_VEC
(
cmPos
,
pos
,
1e-2
);
Vec3
vel
=
calcCM
(
state
.
getVelocities
(),
system
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
vel
,
1e-2
);
}
}
int
main
()
{
try
{
testMotionRemoval
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
}
platforms/reference/tests/TestReferenceCheckpoints.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2012-201
3
Stanford University and the Authors. *
* Portions copyright (c) 2012-201
5
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,49 +29,12 @@
...
@@ -29,49 +29,12 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests creating and loading checkpoints with the reference platform.
#include "TestCheckpoints.h"
*/
#include "ReferencePlatform.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/AndersenThermostat.h"
#include "openmm/Context.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <sstream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
compareStates
(
State
&
s1
,
State
&
s2
)
{
ASSERT_EQUAL_TOL
(
s1
.
getTime
(),
s2
.
getTime
(),
TOL
);
int
numParticles
=
s1
.
getPositions
().
size
();
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
s1
.
getPositions
()[
i
],
s2
.
getPositions
()[
i
],
TOL
);
ASSERT_EQUAL_VEC
(
s1
.
getVelocities
()[
i
],
s2
.
getVelocities
()[
i
],
TOL
);
Vec3
a1
,
b1
,
c1
,
a2
,
b2
,
c2
;
s1
.
getPeriodicBoxVectors
(
a1
,
b1
,
c1
);
s2
.
getPeriodicBoxVectors
(
a2
,
b2
,
c2
);
ASSERT_EQUAL_VEC
(
a1
,
a2
,
TOL
);
ASSERT_EQUAL_VEC
(
b1
,
b2
,
TOL
);
ASSERT_EQUAL_VEC
(
c1
,
c2
,
TOL
);
for
(
map
<
string
,
double
>::
const_iterator
iter
=
s1
.
getParameters
().
begin
();
iter
!=
s1
.
getParameters
().
end
();
++
iter
)
ASSERT_EQUAL
(
iter
->
second
,
(
*
s2
.
getParameters
().
find
(
iter
->
first
)).
second
);
}
}
void
testCheckpoint
()
{
void
testCheckpoint
()
{
const
int
numParticles
=
10
;
const
int
numParticles
=
10
0
;
const
double
boxSize
=
3
.0
;
const
double
boxSize
=
5
.0
;
const
double
temperature
=
200.0
;
const
double
temperature
=
200.0
;
System
system
;
System
system
;
system
.
addForce
(
new
AndersenThermostat
(
0.0
,
100.0
));
system
.
addForce
(
new
AndersenThermostat
(
0.0
,
100.0
));
...
@@ -84,7 +47,16 @@ void testCheckpoint() {
...
@@ -84,7 +47,16 @@ void testCheckpoint() {
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
i
%
2
==
0
?
0.1
:
-
0.1
,
0.2
,
0.1
);
nonbonded
->
addParticle
(
i
%
2
==
0
?
0.1
:
-
0.1
,
0.2
,
0.1
);
positions
[
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
bool
clash
;
do
{
clash
=
false
;
positions
[
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
for
(
int
j
=
0
;
j
<
i
;
j
++
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
if
(
sqrt
(
delta
.
dot
(
delta
))
<
0.1
)
clash
=
true
;
}
}
while
(
clash
);
}
}
VerletIntegrator
integrator
(
0.001
);
VerletIntegrator
integrator
(
0.001
);
Context
context
(
system
,
integrator
,
platform
);
Context
context
(
system
,
integrator
,
platform
);
...
@@ -122,69 +94,6 @@ void testCheckpoint() {
...
@@ -122,69 +94,6 @@ void testCheckpoint() {
compareStates
(
s2
,
s4
);
compareStates
(
s2
,
s4
);
}
}
void
testSetState
()
{
void
runPlatformTests
()
{
const
int
numParticles
=
10
;
testCheckpoint
();
const
double
boxSize
=
3.0
;
const
double
temperature
=
200.0
;
System
system
;
system
.
addForce
(
new
AndersenThermostat
(
0.0
,
100.0
));
NonbondedForce
*
nonbonded
=
new
NonbondedForce
();
system
.
addForce
(
nonbonded
);
nonbonded
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
nonbonded
->
addParticle
(
i
%
2
==
0
?
0.1
:
-
0.1
,
0.2
,
0.1
);
positions
[
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
}
VerletIntegrator
integrator
(
0.001
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
context
.
setParameter
(
AndersenThermostat
::
Temperature
(),
temperature
);
// Run for a little while.
integrator
.
step
(
100
);
// Record the current state.
State
s1
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
|
State
::
Parameters
);
// Continue the simulation for a few more steps and record a partial state.
integrator
.
step
(
10
);
State
s2
=
context
.
getState
(
State
::
Positions
);
// Restore the original state and see if everything gets restored correctly.
context
.
setPeriodicBoxVectors
(
Vec3
(
2
*
boxSize
,
0
,
0
),
Vec3
(
0
,
2
*
boxSize
,
0
),
Vec3
(
0
,
0
,
2
*
boxSize
));
context
.
setParameter
(
AndersenThermostat
::
Temperature
(),
temperature
+
10
);
context
.
setState
(
s1
);
State
s3
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
|
State
::
Parameters
);
compareStates
(
s1
,
s3
);
// Set the partial state and see if the correct things were set.
context
.
setState
(
s2
);
State
s4
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
|
State
::
Parameters
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
s2
.
getPositions
()[
i
],
s4
.
getPositions
()[
i
],
TOL
);
ASSERT_EQUAL_VEC
(
s1
.
getVelocities
()[
i
],
s4
.
getVelocities
()[
i
],
TOL
);
}
}
int
main
()
{
try
{
testCheckpoint
();
testSetState
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
}
platforms/reference/tests/TestReferenceCustomAngleForce.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08-2010
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,122 +29,9 @@
...
@@ -29,122 +29,9 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
* This tests the reference implementation of CustomAngleForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "ReferenceTests.h"
#include "openmm/Context.h"
#include "TestCustomAngleForce.h"
#include "ReferencePlatform.h"
#include "openmm/CustomAngleForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
void
runPlatformTests
()
{
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testAngles
()
{
// Create a system using a CustomAngleForce.
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomAngleForce
*
custom
=
new
CustomAngleForce
(
"scale*k*(theta-theta0)^2"
);
custom
->
addPerAngleParameter
(
"theta0"
);
custom
->
addPerAngleParameter
(
"k"
);
custom
->
addGlobalParameter
(
"scale"
,
0.5
);
vector
<
double
>
parameters
(
2
);
parameters
[
0
]
=
1.5
;
parameters
[
1
]
=
0.8
;
custom
->
addAngle
(
0
,
1
,
2
,
parameters
);
parameters
[
0
]
=
2.0
;
parameters
[
1
]
=
0.5
;
custom
->
addAngle
(
1
,
2
,
3
,
parameters
);
customSystem
.
addForce
(
custom
);
ASSERT
(
!
custom
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
customSystem
.
usesPeriodicBoundaryConditions
());
// Create an identical system using a HarmonicAngleForce.
System
harmonicSystem
;
harmonicSystem
.
addParticle
(
1.0
);
harmonicSystem
.
addParticle
(
1.0
);
harmonicSystem
.
addParticle
(
1.0
);
harmonicSystem
.
addParticle
(
1.0
);
HarmonicAngleForce
*
harmonic
=
new
HarmonicAngleForce
();
harmonic
->
addAngle
(
0
,
1
,
2
,
1.5
,
0.8
);
harmonic
->
addAngle
(
1
,
2
,
3
,
2.0
,
0.5
);
harmonicSystem
.
addForce
(
harmonic
);
// Set the atoms in various positions, and verify that both systems give identical forces and energy.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
(
4
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
customSystem
,
integrator1
,
platform
);
Context
c2
(
harmonicSystem
,
integrator2
,
platform
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c2
.
setPositions
(
positions
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
s1
.
getForces
();
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s1
.
getForces
()[
i
],
s2
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
s2
.
getPotentialEnergy
(),
TOL
);
}
// Try changing the angle parameters and make sure it's still correct.
parameters
[
0
]
=
1.6
;
parameters
[
1
]
=
0.9
;
custom
->
setAngleParameters
(
0
,
0
,
1
,
2
,
parameters
);
parameters
[
0
]
=
2.1
;
parameters
[
1
]
=
0.6
;
custom
->
setAngleParameters
(
1
,
1
,
2
,
3
,
parameters
);
custom
->
updateParametersInContext
(
c1
);
harmonic
->
setAngleParameters
(
0
,
0
,
1
,
2
,
1.6
,
0.9
);
harmonic
->
setAngleParameters
(
1
,
1
,
2
,
3
,
2.1
,
0.6
);
harmonic
->
updateParametersInContext
(
c2
);
{
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c2
.
setPositions
(
positions
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
s1
.
getForces
();
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s1
.
getForces
()[
i
],
s2
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
s2
.
getPotentialEnergy
(),
TOL
);
}
}
int
main
()
{
try
{
testAngles
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
}
platforms/reference/tests/TestReferenceCustomBondForce.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08-2009
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,90 +29,9 @@
...
@@ -29,90 +29,9 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
* This tests the reference implementation of CustomBondForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "ReferenceTests.h"
#include "openmm/Context.h"
#include "TestCustomBondForce.h"
#include "ReferencePlatform.h"
#include "openmm/CustomBondForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
void
runPlatformTests
()
{
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testBonds
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomBondForce
*
forceField
=
new
CustomBondForce
(
"scale*k*(r-r0)^2"
);
forceField
->
addPerBondParameter
(
"r0"
);
forceField
->
addPerBondParameter
(
"k"
);
forceField
->
addGlobalParameter
(
"scale"
,
0.5
);
vector
<
double
>
parameters
(
2
);
parameters
[
0
]
=
1.5
;
parameters
[
1
]
=
0.8
;
forceField
->
addBond
(
0
,
1
,
parameters
);
parameters
[
0
]
=
1.2
;
parameters
[
1
]
=
0.7
;
forceField
->
addBond
(
1
,
2
,
parameters
);
system
.
addForce
(
forceField
);
ASSERT
(
!
forceField
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
system
.
usesPeriodicBoundaryConditions
());
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
3
);
positions
[
0
]
=
Vec3
(
0
,
2
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
positions
[
2
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
{
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
0.8
*
0.5
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.7
*
0.2
,
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
forces
[
0
][
0
]
-
forces
[
2
][
0
],
-
forces
[
0
][
1
]
-
forces
[
2
][
1
],
-
forces
[
0
][
2
]
-
forces
[
2
][
2
]),
forces
[
1
],
TOL
);
ASSERT_EQUAL_TOL
(
0.5
*
0.8
*
0.5
*
0.5
+
0.5
*
0.7
*
0.2
*
0.2
,
state
.
getPotentialEnergy
(),
TOL
);
}
// Try changing the bond parameters and make sure it's still correct.
parameters
[
0
]
=
1.6
;
parameters
[
1
]
=
0.9
;
forceField
->
setBondParameters
(
0
,
0
,
1
,
parameters
);
parameters
[
0
]
=
1.3
;
parameters
[
1
]
=
0.8
;
forceField
->
setBondParameters
(
1
,
1
,
2
,
parameters
);
forceField
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
{
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
0.9
*
0.4
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.8
*
0.3
,
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
forces
[
0
][
0
]
-
forces
[
2
][
0
],
-
forces
[
0
][
1
]
-
forces
[
2
][
1
],
-
forces
[
0
][
2
]
-
forces
[
2
][
2
]),
forces
[
1
],
TOL
);
ASSERT_EQUAL_TOL
(
0.5
*
0.9
*
0.4
*
0.4
+
0.5
*
0.8
*
0.3
*
0.3
,
state
.
getPotentialEnergy
(),
TOL
);
}
}
}
int
main
()
{
try
{
testBonds
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCustomCentroidBondForce.cpp
0 → 100644
View file @
fd473eea
/* -------------------------------------------------------------------------- *
* 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) 2015 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 "ReferenceTests.h"
#include "TestCustomCentroidBondForce.h"
void
runPlatformTests
()
{
}
platforms/reference/tests/TestReferenceCustomCompoundBondForce.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c)
2012-
2015 Stanford University and the Authors. *
* Portions copyright (c) 2015 Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,306 +29,8 @@
...
@@ -29,306 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of CustomCompoundBondForce.
#include "TestCustomCompoundBondForce.h"
*/
#ifdef WIN32
void
runPlatformTests
()
{
#define _USE_MATH_DEFINES // Needed to get M_PI
#endif
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/CustomCompoundBondForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testBond
()
{
// Create a system using a CustomCompoundBondForce.
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomCompoundBondForce
*
custom
=
new
CustomCompoundBondForce
(
4
,
"0.5*kb*((distance(p1,p2)-b0)^2+(distance(p2,p3)-b0)^2)+0.5*ka*(angle(p2,p3,p4)-a0)^2+kt*(1+cos(dihedral(p1,p2,p3,p4)-t0))"
);
custom
->
addPerBondParameter
(
"kb"
);
custom
->
addPerBondParameter
(
"ka"
);
custom
->
addPerBondParameter
(
"kt"
);
custom
->
addPerBondParameter
(
"b0"
);
custom
->
addPerBondParameter
(
"a0"
);
custom
->
addPerBondParameter
(
"t0"
);
vector
<
int
>
particles
(
4
);
particles
[
0
]
=
0
;
particles
[
1
]
=
1
;
particles
[
2
]
=
3
;
particles
[
3
]
=
2
;
vector
<
double
>
parameters
(
6
);
parameters
[
0
]
=
1.5
;
parameters
[
1
]
=
0.8
;
parameters
[
2
]
=
0.6
;
parameters
[
3
]
=
1.1
;
parameters
[
4
]
=
2.9
;
parameters
[
5
]
=
1.3
;
custom
->
addBond
(
particles
,
parameters
);
customSystem
.
addForce
(
custom
);
ASSERT
(
!
custom
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
customSystem
.
usesPeriodicBoundaryConditions
());
// Create an identical system using standard forces.
System
standardSystem
;
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
bonds
->
addBond
(
0
,
1
,
1.1
,
1.5
);
bonds
->
addBond
(
1
,
3
,
1.1
,
1.5
);
standardSystem
.
addForce
(
bonds
);
HarmonicAngleForce
*
angles
=
new
HarmonicAngleForce
();
angles
->
addAngle
(
1
,
3
,
2
,
2.9
,
0.8
);
standardSystem
.
addForce
(
angles
);
PeriodicTorsionForce
*
torsions
=
new
PeriodicTorsionForce
();
torsions
->
addTorsion
(
0
,
1
,
3
,
2
,
1
,
1.3
,
0.6
);
standardSystem
.
addForce
(
torsions
);
// Set the atoms in various positions, and verify that both systems give identical forces and energy.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
customSystem
,
integrator1
,
platform
);
Context
c2
(
standardSystem
,
integrator2
,
platform
);
vector
<
Vec3
>
positions
(
4
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
),
5.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c2
.
setPositions
(
positions
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s1
.
getForces
()[
i
],
s2
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
s2
.
getPotentialEnergy
(),
TOL
);
}
// Try changing the bond parameters and make sure it's still correct.
parameters
[
0
]
=
1.6
;
parameters
[
3
]
=
1.3
;
custom
->
setBondParameters
(
0
,
particles
,
parameters
);
custom
->
updateParametersInContext
(
c1
);
bonds
->
setBondParameters
(
0
,
0
,
1
,
1.3
,
1.6
);
bonds
->
setBondParameters
(
1
,
1
,
3
,
1.3
,
1.6
);
bonds
->
updateParametersInContext
(
c2
);
{
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
s1
.
getForces
();
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s1
.
getForces
()[
i
],
s2
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
s2
.
getPotentialEnergy
(),
TOL
);
}
}
void
testPositionDependence
()
{
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomCompoundBondForce
*
custom
=
new
CustomCompoundBondForce
(
2
,
"scale1*distance(p1,p2)+scale2*x1+2*y2"
);
custom
->
addGlobalParameter
(
"scale1"
,
0.3
);
custom
->
addGlobalParameter
(
"scale2"
,
0.2
);
vector
<
int
>
particles
(
2
);
particles
[
0
]
=
1
;
particles
[
1
]
=
0
;
vector
<
double
>
parameters
;
custom
->
addBond
(
particles
,
parameters
);
customSystem
.
addForce
(
custom
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
1.5
,
1
,
0
);
positions
[
1
]
=
Vec3
(
0.5
,
1
,
0
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
customSystem
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.3
*
1.0
+
0.2
*
0.5
+
2
*
1
,
state
.
getPotentialEnergy
(),
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.3
,
-
2
,
0
),
state
.
getForces
()[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.3
-
0.2
,
0
,
0
),
state
.
getForces
()[
1
],
1e-5
);
}
}
void
testContinuous2DFunction
()
{
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.9
;
System
system
;
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomCompoundBondForce
*
forceField
=
new
CustomCompoundBondForce
(
1
,
"fn(x1,y1)+1"
);
vector
<
int
>
particles
(
1
,
0
);
forceField
->
addBond
(
particles
,
vector
<
double
>
());
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
);
}
}
forceField
->
addTabulatedFunction
(
"fn"
,
new
Continuous2DFunction
(
xsize
,
ysize
,
table
,
xmin
,
xmax
,
ymin
,
ymax
));
system
.
addForce
(
forceField
);
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
testContinuous3DFunction
()
{
const
int
xsize
=
10
;
const
int
ysize
=
11
;
const
int
zsize
=
12
;
const
double
xmin
=
0.4
;
const
double
xmax
=
1.1
;
const
double
ymin
=
0.0
;
const
double
ymax
=
0.9
;
const
double
zmin
=
0.2
;
const
double
zmax
=
1.3
;
System
system
;
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomCompoundBondForce
*
forceField
=
new
CustomCompoundBondForce
(
1
,
"fn(x1,y1,z1)+1"
);
vector
<
int
>
particles
(
1
,
0
);
forceField
->
addBond
(
particles
,
vector
<
double
>
());
vector
<
double
>
table
(
xsize
*
ysize
*
zsize
);
for
(
int
i
=
0
;
i
<
xsize
;
i
++
)
{
for
(
int
j
=
0
;
j
<
ysize
;
j
++
)
{
for
(
int
k
=
0
;
k
<
zsize
;
k
++
)
{
double
x
=
xmin
+
i
*
(
xmax
-
xmin
)
/
xsize
;
double
y
=
ymin
+
j
*
(
ymax
-
ymin
)
/
ysize
;
double
z
=
zmin
+
k
*
(
zmax
-
zmin
)
/
zsize
;
table
[
i
+
xsize
*
j
+
xsize
*
ysize
*
k
]
=
sin
(
0.25
*
x
)
*
cos
(
0.33
*
y
)
*
(
1
+
z
);
}
}
}
forceField
->
addTabulatedFunction
(
"fn"
,
new
Continuous3DFunction
(
xsize
,
ysize
,
zsize
,
table
,
xmin
,
xmax
,
ymin
,
ymax
,
zmin
,
zmax
));
system
.
addForce
(
forceField
);
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
)
{
for
(
double
z
=
zmin
-
0.15
;
z
<
zmax
+
0.2
;
z
+=
0.1
)
{
positions
[
0
]
=
Vec3
(
x
,
y
,
z
);
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
&&
z
>=
zmin
&&
z
<=
zmax
)
{
energy
=
sin
(
0.25
*
x
)
*
cos
(
0.33
*
y
)
*
(
1.0
+
z
)
+
1
;
force
[
0
]
=
-
0.25
*
cos
(
0.25
*
x
)
*
cos
(
0.33
*
y
)
*
(
1.0
+
z
);
force
[
1
]
=
0.3
*
sin
(
0.25
*
x
)
*
sin
(
0.33
*
y
)
*
(
1.0
+
z
);
force
[
2
]
=
-
sin
(
0.25
*
x
)
*
cos
(
0.33
*
y
);
}
ASSERT_EQUAL_VEC
(
force
,
forces
[
0
],
0.1
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.05
);
}
}
}
}
void
testMultipleBonds
()
{
// Two compound bonds using Urey-Bradley example from API doc
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomCompoundBondForce
*
custom
=
new
CustomCompoundBondForce
(
3
,
"0.5*(kangle*(angle(p1,p2,p3)-theta0)^2+kbond*(distance(p1,p3)-r0)^2)"
);
custom
->
addPerBondParameter
(
"kangle"
);
custom
->
addPerBondParameter
(
"kbond"
);
custom
->
addPerBondParameter
(
"theta0"
);
custom
->
addPerBondParameter
(
"r0"
);
vector
<
double
>
parameters
(
4
);
parameters
[
0
]
=
1.0
;
parameters
[
1
]
=
1.0
;
parameters
[
2
]
=
2
*
M_PI
/
3
;
parameters
[
3
]
=
sqrt
(
3.0
)
/
2
;
vector
<
int
>
particles0
(
3
);
particles0
[
0
]
=
0
;
particles0
[
1
]
=
1
;
particles0
[
2
]
=
2
;
vector
<
int
>
particles1
(
3
);
particles1
[
0
]
=
1
;
particles1
[
1
]
=
2
;
particles1
[
2
]
=
3
;
custom
->
addBond
(
particles0
,
parameters
);
custom
->
addBond
(
particles1
,
parameters
);
customSystem
.
addForce
(
custom
);
vector
<
Vec3
>
positions
(
4
);
positions
[
0
]
=
Vec3
(
0
,
0.5
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
0
);
positions
[
2
]
=
Vec3
(
0.5
,
0
,
0
);
positions
[
3
]
=
Vec3
(
0.6
,
0
,
0.4
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
customSystem
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
0.199
,
state
.
getPotentialEnergy
(),
1e-3
);
vector
<
Vec3
>
forces
(
state
.
getForces
());
ASSERT_EQUAL_VEC
(
Vec3
(
-
1.160
,
0.112
,
0.0
),
forces
[
0
],
1e-3
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.927
,
1.047
,
-
0.638
),
forces
[
1
],
1e-3
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.543
,
-
1.160
,
0.721
),
forces
[
2
],
1e-3
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.776
,
0.0
,
-
0.084
),
forces
[
3
],
1e-3
);
}
int
main
()
{
try
{
testBond
();
testPositionDependence
();
testContinuous2DFunction
();
testContinuous3DFunction
();
testMultipleBonds
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCustomExternalForce.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08-2009
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,88 +29,8 @@
...
@@ -29,88 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of CustomExternalForce.
#include "TestCustomExternalForce.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testForce
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomExternalForce
*
forceField
=
new
CustomExternalForce
(
"scale*(x+yscale*(y-y0)^2)"
);
forceField
->
addPerParticleParameter
(
"y0"
);
forceField
->
addPerParticleParameter
(
"yscale"
);
forceField
->
addGlobalParameter
(
"scale"
,
0.5
);
vector
<
double
>
parameters
(
2
);
parameters
[
0
]
=
0.5
;
parameters
[
1
]
=
2.0
;
forceField
->
addParticle
(
0
,
parameters
);
parameters
[
0
]
=
1.5
;
parameters
[
1
]
=
3.0
;
forceField
->
addParticle
(
2
,
parameters
);
system
.
addForce
(
forceField
);
ASSERT
(
!
forceField
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
system
.
usesPeriodicBoundaryConditions
());
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
3
);
positions
[
0
]
=
Vec3
(
0
,
2
,
0
);
positions
[
1
]
=
Vec3
(
0
,
0
,
1
);
positions
[
2
]
=
Vec3
(
1
,
0
,
1
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
{
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
,
-
0.5
*
2.0
*
2.0
*
1.5
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
forces
[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
,
0.5
*
3.0
*
2.0
*
1.5
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_TOL
(
0.5
*
(
1.0
+
2.0
*
1.5
*
1.5
+
3.0
*
1.5
*
1.5
),
state
.
getPotentialEnergy
(),
TOL
);
}
// Try changing the parameters and make sure it's still correct.
parameters
[
0
]
=
1.4
;
parameters
[
1
]
=
3.5
;
forceField
->
setParticleParameters
(
1
,
2
,
parameters
);
forceField
->
updateParametersInContext
(
context
);
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
{
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
,
-
0.5
*
2.0
*
2.0
*
1.5
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
forces
[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
,
0.5
*
3.5
*
2.0
*
1.4
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_TOL
(
0.5
*
(
1.0
+
2.0
*
1.5
*
1.5
+
3.5
*
1.4
*
1.4
),
state
.
getPotentialEnergy
(),
TOL
);
}
}
}
int
main
()
{
try
{
testForce
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCustomGBForce.cpp
View file @
fd473eea
/* -------------------------------------------------------------------------- *
/* -------------------------------------------------------------------------- *
* OpenMM *
* OpenMM *
* -------------------------------------------------------------------------- *
* -------------------------------------------------------------------------- *
...
@@ -7,7 +6,7 @@
...
@@ -7,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08-2013
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -30,882 +29,8 @@
...
@@ -30,882 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests all the different force terms in the reference implementation of CustomGBForce.
#include "TestCustomGBForce.h"
*/
#include "openmm/internal/AssertionUtilities.h"
#include "sfmt/SFMT.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/CustomGBForce.h"
#include "openmm/GBSAOBCForce.h"
#include "openmm/GBVIForce.h"
#include "openmm/OpenMMException.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include <iostream>
#include <vector>
#include <algorithm>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testOBC
(
GBSAOBCForce
::
NonbondedMethod
obcMethod
,
CustomGBForce
::
NonbondedMethod
customMethod
)
{
const
int
numMolecules
=
70
;
const
int
numParticles
=
numMolecules
*
2
;
const
double
boxSize
=
10.0
;
const
double
cutoff
=
2.0
;
// Create two systems: one with a GBSAOBCForce, and one using a CustomGBForce to implement the same interaction.
System
standardSystem
;
System
customSystem
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
standardSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
}
standardSystem
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
customSystem
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
GBSAOBCForce
*
obc
=
new
GBSAOBCForce
();
CustomGBForce
*
custom
=
new
CustomGBForce
();
obc
->
setCutoffDistance
(
cutoff
);
custom
->
setCutoffDistance
(
cutoff
);
custom
->
addPerParticleParameter
(
"q"
);
custom
->
addPerParticleParameter
(
"radius"
);
custom
->
addPerParticleParameter
(
"scale"
);
custom
->
addGlobalParameter
(
"solventDielectric"
,
obc
->
getSolventDielectric
());
custom
->
addGlobalParameter
(
"soluteDielectric"
,
obc
->
getSoluteDielectric
());
custom
->
addComputedValue
(
"I"
,
"step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(1/U^2-1/L^2)*(r-sr2*sr2/r)+0.5*log(L/U)/r+C);"
"U=r+sr2;"
"C=2*(1/or1-1/L)*step(sr2-r-or1);"
"L=max(or1, D);"
"D=abs(r-sr2);"
"sr2 = scale2*or2;"
"or1 = radius1-0.009; or2 = radius2-0.009"
,
CustomGBForce
::
ParticlePairNoExclusions
);
custom
->
addComputedValue
(
"B"
,
"1/(1/or-tanh(1*psi-0.8*psi^2+4.85*psi^3)/radius);"
"psi=I*or; or=radius-0.009"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"28.3919551*(radius+0.14)^2*(radius/B)^6-0.5*138.935485*(1/soluteDielectric-1/solventDielectric)*q^2/B"
,
CustomGBForce
::
SingleParticle
);
string
invCutoffString
=
""
;
if
(
obcMethod
!=
GBSAOBCForce
::
NoCutoff
)
{
stringstream
s
;
s
<<
(
1.0
/
cutoff
);
invCutoffString
=
s
.
str
();
}
custom
->
addEnergyTerm
(
"138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2*("
+
invCutoffString
+
"-1/f);"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))"
,
CustomGBForce
::
ParticlePairNoExclusions
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
double
>
params
(
3
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
if
(
i
<
numMolecules
/
2
)
{
obc
->
addParticle
(
1.0
,
0.2
,
0.5
);
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.5
;
custom
->
addParticle
(
params
);
obc
->
addParticle
(
-
1.0
,
0.1
,
0.5
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
else
{
obc
->
addParticle
(
1.0
,
0.2
,
0.8
);
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.8
;
custom
->
addParticle
(
params
);
obc
->
addParticle
(
-
1.0
,
0.1
,
0.8
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
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
));
velocities
[
2
*
i
+
1
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
}
obc
->
setNonbondedMethod
(
obcMethod
);
custom
->
setNonbondedMethod
(
customMethod
);
standardSystem
.
addForce
(
obc
);
customSystem
.
addForce
(
custom
);
if
(
customMethod
==
CustomGBForce
::
CutoffPeriodic
)
{
ASSERT
(
custom
->
usesPeriodicBoundaryConditions
());
ASSERT
(
obc
->
usesPeriodicBoundaryConditions
());
ASSERT
(
standardSystem
.
usesPeriodicBoundaryConditions
());
ASSERT
(
customSystem
.
usesPeriodicBoundaryConditions
());
}
else
{
ASSERT
(
!
custom
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
obc
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
standardSystem
.
usesPeriodicBoundaryConditions
());
ASSERT
(
!
customSystem
.
usesPeriodicBoundaryConditions
());
}
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
context1
(
standardSystem
,
integrator1
,
platform
);
context1
.
setPositions
(
positions
);
context1
.
setVelocities
(
velocities
);
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
Context
context2
(
customSystem
,
integrator2
,
platform
);
context2
.
setPositions
(
positions
);
context2
.
setVelocities
(
velocities
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-4
);
}
// Try changing the particle parameters and make sure it's still correct.
for
(
int
i
=
0
;
i
<
numMolecules
/
2
;
i
++
)
{
obc
->
setParticleParameters
(
2
*
i
,
1.1
,
0.3
,
0.6
);
params
[
0
]
=
1.1
;
params
[
1
]
=
0.3
;
params
[
2
]
=
0.6
;
custom
->
setParticleParameters
(
2
*
i
,
params
);
obc
->
setParticleParameters
(
2
*
i
+
1
,
-
1.1
,
0.2
,
0.4
);
params
[
0
]
=
-
1.1
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.4
;
custom
->
setParticleParameters
(
2
*
i
+
1
,
params
);
}
obc
->
updateParametersInContext
(
context1
);
custom
->
updateParametersInContext
(
context2
);
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-4
);
}
}
void
testMembrane
()
{
const
int
numMolecules
=
70
;
const
int
numParticles
=
numMolecules
*
2
;
const
double
boxSize
=
10.0
;
// Create a system with an implicit membrane.
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
}
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
CustomGBForce
*
custom
=
new
CustomGBForce
();
custom
->
setCutoffDistance
(
2.0
);
custom
->
addPerParticleParameter
(
"q"
);
custom
->
addPerParticleParameter
(
"radius"
);
custom
->
addPerParticleParameter
(
"scale"
);
custom
->
addGlobalParameter
(
"thickness"
,
3
);
custom
->
addGlobalParameter
(
"solventDielectric"
,
78.3
);
custom
->
addGlobalParameter
(
"soluteDielectric"
,
1
);
custom
->
addComputedValue
(
"Imol"
,
"step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(1/U^2-1/L^2)*(r-sr2*sr2/r)+0.5*log(L/U)/r+C);"
"U=r+sr2;"
"C=2*(1/or1-1/L)*step(sr2-r-or1);"
"L=max(or1, D);"
"D=abs(r-sr2);"
"sr2 = scale2*or2;"
"or1 = radius1-0.009; or2 = radius2-0.009"
,
CustomGBForce
::
ParticlePairNoExclusions
);
custom
->
addComputedValue
(
"Imem"
,
"(1/radius+2*log(2)/thickness)/(1+exp(7.2*(abs(z)+radius-0.5*thickness)))"
,
CustomGBForce
::
SingleParticle
);
custom
->
addComputedValue
(
"B"
,
"1/(1/or-tanh(1*psi-0.8*psi^2+4.85*psi^3)/radius);"
"psi=max(Imol,Imem)*or; or=radius-0.009"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"28.3919551*(radius+0.14)^2*(radius/B)^6-0.5*138.935456*(1/soluteDielectric-1/solventDielectric)*q^2/B"
,
CustomGBForce
::
SingleParticle
);
custom
->
addEnergyTerm
(
"-138.935456*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))"
,
CustomGBForce
::
ParticlePairNoExclusions
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
double
>
params
(
3
);
for
(
int
i
=
0
;
i
<
numMolecules
;
i
++
)
{
if
(
i
<
numMolecules
/
2
)
{
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.5
;
custom
->
addParticle
(
params
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
else
{
params
[
0
]
=
1.0
;
params
[
1
]
=
0.2
;
params
[
2
]
=
0.8
;
custom
->
addParticle
(
params
);
params
[
0
]
=
-
1.0
;
params
[
1
]
=
0.1
;
custom
->
addParticle
(
params
);
}
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
));
velocities
[
2
*
i
+
1
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
}
system
.
addForce
(
custom
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
// 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
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-2
;
double
step
=
0.5
*
stepSize
/
norm
;
vector
<
Vec3
>
positions2
(
numParticles
),
positions3
(
numParticles
);
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
stepSize
,
1e-3
);
}
void
testTabulatedFunction
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"0"
,
CustomGBForce
::
ParticlePair
);
force
->
addEnergyTerm
(
"fn(r)+1"
,
CustomGBForce
::
ParticlePair
);
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
vector
<
double
>
table
;
for
(
int
i
=
0
;
i
<
21
;
i
++
)
table
.
push_back
(
std
::
sin
(
0.25
*
i
));
force
->
addTabulatedFunction
(
"fn"
,
new
Continuous1DFunction
(
table
,
1.0
,
6.0
));
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
for
(
int
i
=
1
;
i
<
30
;
i
++
)
{
double
x
=
(
7.0
/
30.0
)
*
i
;
positions
[
1
]
=
Vec3
(
x
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
double
force
=
(
x
<
1.0
||
x
>
6.0
?
0.0
:
-
std
::
cos
(
x
-
1.0
));
double
energy
=
(
x
<
1.0
||
x
>
6.0
?
0.0
:
std
::
sin
(
x
-
1.0
))
+
1.0
;
ASSERT_EQUAL_VEC
(
Vec3
(
-
force
,
0
,
0
),
forces
[
0
],
0.1
);
ASSERT_EQUAL_VEC
(
Vec3
(
force
,
0
,
0
),
forces
[
1
],
0.1
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.02
);
}
}
void
testMultipleChainRules
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"2*r"
,
CustomGBForce
::
ParticlePair
);
force
->
addComputedValue
(
"b"
,
"a+1"
,
CustomGBForce
::
SingleParticle
);
force
->
addComputedValue
(
"c"
,
"2*b+a"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"0.1*a+1*b+10*c"
,
CustomGBForce
::
SingleParticle
);
// 0.1*(2*r) + 2*r+1 + 10*(3*a+2) = 0.2*r + 2*r+1 + 40*r+20+20*r = 62.2*r+21
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
for
(
int
i
=
1
;
i
<
5
;
i
++
)
{
positions
[
1
]
=
Vec3
(
i
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
ASSERT_EQUAL_VEC
(
Vec3
(
124.4
,
0
,
0
),
forces
[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
124.4
,
0
,
0
),
forces
[
1
],
1e-4
);
ASSERT_EQUAL_TOL
(
2
*
(
62.2
*
i
+
21
),
state
.
getPotentialEnergy
(),
0.02
);
}
}
void
testPositionDependence
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"r"
,
CustomGBForce
::
ParticlePair
);
force
->
addComputedValue
(
"b"
,
"a+x*y"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"b*z"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"b1+b2"
,
CustomGBForce
::
ParticlePair
);
// = 2*r+x1*y1+x2*y2
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
vector
<
Vec3
>
forces
(
2
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
positions
[
0
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
positions
[
1
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
Vec3
delta
=
positions
[
0
]
-
positions
[
1
];
double
r
=
sqrt
(
delta
.
dot
(
delta
));
double
energy
=
2
*
r
+
positions
[
0
][
0
]
*
positions
[
0
][
1
]
+
positions
[
1
][
0
]
*
positions
[
1
][
1
];
for
(
int
j
=
0
;
j
<
2
;
j
++
)
energy
+=
positions
[
j
][
2
]
*
(
r
+
positions
[
j
][
0
]
*
positions
[
j
][
1
]);
Vec3
force1
(
-
(
1
+
positions
[
0
][
2
])
*
delta
[
0
]
/
r
-
(
1
+
positions
[
0
][
2
])
*
positions
[
0
][
1
]
-
(
1
+
positions
[
1
][
2
])
*
delta
[
0
]
/
r
,
-
(
1
+
positions
[
0
][
2
])
*
delta
[
1
]
/
r
-
(
1
+
positions
[
0
][
2
])
*
positions
[
0
][
0
]
-
(
1
+
positions
[
1
][
2
])
*
delta
[
1
]
/
r
,
-
(
1
+
positions
[
0
][
2
])
*
delta
[
2
]
/
r
-
(
r
+
positions
[
0
][
0
]
*
positions
[
0
][
1
])
-
(
1
+
positions
[
1
][
2
])
*
delta
[
2
]
/
r
);
Vec3
force2
((
1
+
positions
[
0
][
2
])
*
delta
[
0
]
/
r
+
(
1
+
positions
[
1
][
2
])
*
delta
[
0
]
/
r
-
(
1
+
positions
[
1
][
2
])
*
positions
[
1
][
1
],
(
1
+
positions
[
0
][
2
])
*
delta
[
1
]
/
r
+
(
1
+
positions
[
1
][
2
])
*
delta
[
1
]
/
r
-
(
1
+
positions
[
1
][
2
])
*
positions
[
1
][
0
],
(
1
+
positions
[
0
][
2
])
*
delta
[
2
]
/
r
+
(
1
+
positions
[
1
][
2
])
*
delta
[
2
]
/
r
-
(
r
+
positions
[
1
][
0
]
*
positions
[
1
][
1
]));
ASSERT_EQUAL_VEC
(
force1
,
forces
[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
force2
,
forces
[
1
],
1e-4
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
0.02
);
// 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
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-3
;
double
step
=
0.5
*
stepSize
/
norm
;
vector
<
Vec3
>
positions2
(
2
),
positions3
(
2
);
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions2
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
positions3
[
i
]
=
Vec3
(
p
[
0
]
+
f
[
0
]
*
step
,
p
[
1
]
+
f
[
1
]
*
step
,
p
[
2
]
+
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions2
);
State
state2
=
context
.
getState
(
State
::
Energy
);
context
.
setPositions
(
positions3
);
State
state3
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state3
.
getPotentialEnergy
())
/
stepSize
,
1e-3
);
}
}
void
testExclusions
()
{
for
(
int
i
=
3
;
i
<
4
;
i
++
)
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomGBForce
*
force
=
new
CustomGBForce
();
force
->
addComputedValue
(
"a"
,
"r"
,
i
<
2
?
CustomGBForce
::
ParticlePair
:
CustomGBForce
::
ParticlePairNoExclusions
);
force
->
addEnergyTerm
(
"a"
,
CustomGBForce
::
SingleParticle
);
force
->
addEnergyTerm
(
"(1+a1+a2)*r"
,
i
%
2
==
0
?
CustomGBForce
::
ParticlePair
:
CustomGBForce
::
ParticlePairNoExclusions
);
force
->
addParticle
(
vector
<
double
>
());
force
->
addParticle
(
vector
<
double
>
());
force
->
addExclusion
(
0
,
1
);
system
.
addForce
(
force
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
);
const
vector
<
Vec3
>&
forces
=
state
.
getForces
();
double
f
,
energy
;
switch
(
i
)
{
case
0
:
// e = 0
f
=
0
;
energy
=
0
;
break
;
case
1
:
// e = r
f
=
1
;
energy
=
1
;
break
;
case
2
:
// e = 2r
f
=
2
;
energy
=
2
;
break
;
case
3
:
// e = 3r + 2r^2
f
=
7
;
energy
=
5
;
break
;
default:
ASSERT
(
false
);
}
ASSERT_EQUAL_VEC
(
Vec3
(
f
,
0
,
0
),
forces
[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
f
,
0
,
0
),
forces
[
1
],
1e-4
);
ASSERT_EQUAL_TOL
(
energy
,
state
.
getPotentialEnergy
(),
1e-4
);
// 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
<
(
int
)
forces
.
size
();
++
i
)
norm
+=
forces
[
i
].
dot
(
forces
[
i
]);
norm
=
std
::
sqrt
(
norm
);
const
double
stepSize
=
1e-3
;
double
step
=
stepSize
/
norm
;
for
(
int
i
=
0
;
i
<
(
int
)
positions
.
size
();
++
i
)
{
Vec3
p
=
positions
[
i
];
Vec3
f
=
forces
[
i
];
positions
[
i
]
=
Vec3
(
p
[
0
]
-
f
[
0
]
*
step
,
p
[
1
]
-
f
[
1
]
*
step
,
p
[
2
]
-
f
[
2
]
*
step
);
}
context
.
setPositions
(
positions
);
State
state2
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
state2
.
getPotentialEnergy
()
-
state
.
getPotentialEnergy
())
/
stepSize
,
1e-3
*
abs
(
state
.
getPotentialEnergy
()));
}
}
// create custom GB/VI force
static
CustomGBForce
*
createCustomGBVI
(
double
solventDielectric
,
double
soluteDielectric
)
{
CustomGBForce
*
customGbviForce
=
new
CustomGBForce
();
customGbviForce
->
setCutoffDistance
(
2.0
);
customGbviForce
->
addPerParticleParameter
(
"q"
);
customGbviForce
->
addPerParticleParameter
(
"radius"
);
customGbviForce
->
addPerParticleParameter
(
"scaleFactor"
);
// derived in GBVIForce implmentation, but parameter here
customGbviForce
->
addPerParticleParameter
(
"gamma"
);
customGbviForce
->
addGlobalParameter
(
"solventDielectric"
,
solventDielectric
);
customGbviForce
->
addGlobalParameter
(
"soluteDielectric"
,
soluteDielectric
);
customGbviForce
->
addComputedValue
(
"V"
,
" uL - lL + factor3/(radius1*radius1*radius1);"
"uL = 1.5*x2uI*(0.25*rI-0.33333*xuI+0.125*(r2-S2)*rI*x2uI);"
"lL = 1.5*x2lI*(0.25*rI-0.33333*xlI+0.125*(r2-S2)*rI*x2lI);"
"x2lI = 1.0/(xl*xl);"
"xlI = 1.0/(xl);"
"xuI = 1.0/(xu);"
"x2uI = 1.0/(xu*xu);"
"xu = (r+scaleFactor2);"
"rI = 1.0/(r);"
"r2 = (r*r);"
"xl = factor1*lMax + factor2*xuu + factor3*(r-scaleFactor2);"
"xuu = (r+scaleFactor2);"
"S2 = (scaleFactor2*scaleFactor2);"
"factor1 = step(r-absRadiusScaleDiff);"
"absRadiusScaleDiff = abs(radiusScaleDiff);"
"radiusScaleDiff = (radius1-scaleFactor2);"
"factor2 = step(radius1-scaleFactor2-r);"
"factor3 = step(scaleFactor2-radius1-r);"
"lMax = max(radius1,r-scaleFactor2);"
,
CustomGBForce
::
ParticlePairNoExclusions
);
customGbviForce
->
addComputedValue
(
"B"
,
"(1.0/(radius*radius*radius)-V)^(-0.33333333)"
,
CustomGBForce
::
SingleParticle
);
// nonpolar term + polar self energy
customGbviForce
->
addEnergyTerm
(
"(-138.935485*0.5*((1.0/soluteDielectric)-(1.0/solventDielectric))*q^2/B)-((1.0/soluteDielectric)-(1.0/solventDielectric))*((gamma*(radius/B)^3))"
,
CustomGBForce
::
SingleParticle
);
// polar pair energy
customGbviForce
->
addEnergyTerm
(
"-138.935485*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
"f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))"
,
CustomGBForce
::
ParticlePairNoExclusions
);
return
customGbviForce
;
}
// ethance GB/VI test case
static
void
buildEthane
(
GBVIForce
*
gbviForce
,
std
::
vector
<
Vec3
>&
positions
)
{
const
int
numParticles
=
8
;
double
C_HBondDistance
=
0.1097
;
double
C_CBondDistance
=
0.1504
;
double
C_radius
,
C_gamma
,
C_charge
,
H_radius
,
H_gamma
,
H_charge
;
int
AM1_BCC
=
1
;
H_charge
=
-
0.053
;
C_charge
=
-
3.0
*
H_charge
;
if
(
AM1_BCC
)
{
C_radius
=
0.180
;
C_gamma
=
-
0.2863
;
H_radius
=
0.125
;
H_gamma
=
0.2437
;
}
else
{
C_radius
=
0.215
;
C_gamma
=
-
1.1087
;
H_radius
=
0.150
;
H_gamma
=
0.1237
;
}
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
gbviForce
->
addParticle
(
H_charge
,
H_radius
,
H_gamma
);
}
gbviForce
->
setParticleParameters
(
1
,
C_charge
,
C_radius
,
C_gamma
);
gbviForce
->
setParticleParameters
(
4
,
C_charge
,
C_radius
,
C_gamma
);
gbviForce
->
addBond
(
0
,
1
,
C_HBondDistance
);
gbviForce
->
addBond
(
2
,
1
,
C_HBondDistance
);
gbviForce
->
addBond
(
3
,
1
,
C_HBondDistance
);
gbviForce
->
addBond
(
1
,
4
,
C_CBondDistance
);
gbviForce
->
addBond
(
5
,
4
,
C_HBondDistance
);
gbviForce
->
addBond
(
6
,
4
,
C_HBondDistance
);
gbviForce
->
addBond
(
7
,
4
,
C_HBondDistance
);
std
::
vector
<
pair
<
int
,
int
>
>
bondExceptions
;
std
::
vector
<
double
>
bondDistances
;
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
0
,
1
));
bondDistances
.
push_back
(
C_HBondDistance
);
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
2
,
1
));
bondDistances
.
push_back
(
C_HBondDistance
);
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
3
,
1
));
bondDistances
.
push_back
(
C_HBondDistance
);
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
1
,
4
));
bondDistances
.
push_back
(
C_CBondDistance
);
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
5
,
4
));
bondDistances
.
push_back
(
C_HBondDistance
);
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
6
,
4
));
bondDistances
.
push_back
(
C_HBondDistance
);
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
7
,
4
));
bondDistances
.
push_back
(
C_HBondDistance
);
positions
.
resize
(
numParticles
);
positions
[
0
]
=
Vec3
(
0.5480
,
1.7661
,
0.0000
);
positions
[
1
]
=
Vec3
(
0.7286
,
0.8978
,
0.6468
);
positions
[
2
]
=
Vec3
(
0.4974
,
0.0000
,
0.0588
);
positions
[
3
]
=
Vec3
(
0.0000
,
0.9459
,
1.4666
);
positions
[
4
]
=
Vec3
(
2.1421
,
0.8746
,
1.1615
);
positions
[
5
]
=
Vec3
(
2.3239
,
0.0050
,
1.8065
);
positions
[
6
]
=
Vec3
(
2.8705
,
0.8295
,
0.3416
);
positions
[
7
]
=
Vec3
(
2.3722
,
1.7711
,
1.7518
);
}
// dimer GB/VI test case
static
void
buildDimer
(
GBVIForce
*
gbviForce
,
std
::
vector
<
Vec3
>&
positions
)
{
const
int
numParticles
=
2
;
double
C_HBondDistance
=
0.1097
;
double
C_CBondDistance
=
0.1504
;
double
C_radius
,
C_gamma
,
C_charge
,
H_radius
,
H_gamma
,
H_charge
;
int
AM1_BCC
=
1
;
H_charge
=
-
0.053
;
C_charge
=
-
3.0
*
H_charge
;
H_charge
=
0.0
;
C_charge
=
0.0
;
if
(
AM1_BCC
)
{
C_radius
=
0.180
;
C_gamma
=
-
0.2863
;
H_radius
=
0.125
;
H_gamma
=
0.2437
;
}
else
{
C_radius
=
0.215
;
C_gamma
=
-
1.1087
;
H_radius
=
0.150
;
H_gamma
=
0.1237
;
}
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
gbviForce
->
addParticle
(
H_charge
,
H_radius
,
H_gamma
);
}
gbviForce
->
setParticleParameters
(
1
,
C_charge
,
C_radius
,
C_gamma
);
gbviForce
->
addBond
(
0
,
1
,
C_HBondDistance
);
std
::
vector
<
pair
<
int
,
int
>
>
bondExceptions
;
std
::
vector
<
double
>
bondDistances
;
bondExceptions
.
push_back
(
pair
<
int
,
int
>
(
0
,
1
));
bondDistances
.
push_back
(
C_HBondDistance
);
positions
.
resize
(
numParticles
);
positions
[
0
]
=
Vec3
(
0.0
,
0.0
,
0.0
);
positions
[
1
]
=
Vec3
(
0.15
,
0.0
,
0.0
);
}
// monomer GB/VI test case
static
void
buildMonomer
(
GBVIForce
*
gbviForce
,
std
::
vector
<
Vec3
>&
positions
)
{
const
int
numParticles
=
1
;
double
H_radius
,
H_gamma
,
H_charge
;
H_charge
=
1.0
;
H_radius
=
0.125
;
H_gamma
=
0.2437
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
gbviForce
->
addParticle
(
H_charge
,
H_radius
,
H_gamma
);
}
positions
.
resize
(
numParticles
);
positions
[
0
]
=
Vec3
(
0.0
,
0.0
,
0.0
);
}
// taken from gbviForceImpl class
// computes the scaled radii based on covalent info and atomic radii
static
void
findScaledRadii
(
GBVIForce
&
gbviForce
,
std
::
vector
<
double
>
&
scaledRadii
)
{
int
numberOfParticles
=
gbviForce
.
getNumParticles
();
int
numberOfBonds
=
gbviForce
.
getNumBonds
();
// load 1-2 atom pairs along w/ bond distance using HarmonicBondForce & constraints
// numberOfBonds < 1, indicating they were not set by the user
std
::
vector
<
std
::
vector
<
int
>
>
bondIndices
;
bondIndices
.
resize
(
numberOfBonds
);
std
::
vector
<
double
>
bondLengths
;
bondLengths
.
resize
(
numberOfBonds
);
scaledRadii
.
resize
(
numberOfParticles
);
for
(
int
i
=
0
;
i
<
numberOfParticles
;
i
++
)
{
double
charge
,
radius
,
gamma
;
gbviForce
.
getParticleParameters
(
i
,
charge
,
radius
,
gamma
);
scaledRadii
[
i
]
=
radius
;
}
for
(
int
i
=
0
;
i
<
numberOfBonds
;
i
++
)
{
int
particle1
,
particle2
;
double
bondLength
;
gbviForce
.
getBondParameters
(
i
,
particle1
,
particle2
,
bondLength
);
if
(
particle1
<
0
||
particle1
>=
gbviForce
.
getNumParticles
())
{
std
::
stringstream
msg
;
msg
<<
"GBVISoftcoreForce: Illegal particle index: "
;
msg
<<
particle1
;
throw
OpenMMException
(
msg
.
str
());
}
if
(
particle2
<
0
||
particle2
>=
gbviForce
.
getNumParticles
())
{
std
::
stringstream
msg
;
msg
<<
"GBVISoftcoreForce: Illegal particle index: "
;
msg
<<
particle2
;
throw
OpenMMException
(
msg
.
str
());
}
if
(
bondLength
<
0
)
{
std
::
stringstream
msg
;
msg
<<
"GBVISoftcoreForce: negative bondlength: "
;
msg
<<
bondLength
;
throw
OpenMMException
(
msg
.
str
());
}
bondIndices
[
i
].
push_back
(
particle1
);
bondIndices
[
i
].
push_back
(
particle2
);
bondLengths
[
i
]
=
bondLength
;
}
// load 1-2 indicies for each atom
std
::
vector
<
std
::
vector
<
int
>
>
bonded12
(
numberOfParticles
);
for
(
int
i
=
0
;
i
<
(
int
)
bondIndices
.
size
();
++
i
)
{
void
runPlatformTests
()
{
bonded12
[
bondIndices
[
i
][
0
]].
push_back
(
i
);
bonded12
[
bondIndices
[
i
][
1
]].
push_back
(
i
);
}
int
errors
=
0
;
// compute scaled radii (Eq. 5 of Labute paper [JCC 29 p. 1693-1698 2008])
for
(
int
j
=
0
;
j
<
(
int
)
bonded12
.
size
();
++
j
)
{
double
charge
;
double
gamma
;
double
radiusJ
;
double
scaledRadiusJ
;
gbviForce
.
getParticleParameters
(
j
,
charge
,
radiusJ
,
gamma
);
if
(
bonded12
[
j
].
size
()
==
0
)
{
scaledRadiusJ
=
radiusJ
;
// errors++;
}
else
{
double
rJ2
=
radiusJ
*
radiusJ
;
// loop over bonded neighbors of atom j, applying Eq. 5 in Labute
scaledRadiusJ
=
0.0
;
for
(
int
i
=
0
;
i
<
(
int
)
bonded12
[
j
].
size
();
++
i
)
{
int
index
=
bonded12
[
j
][
i
];
int
bondedAtomIndex
=
(
j
==
bondIndices
[
index
][
0
])
?
bondIndices
[
index
][
1
]
:
bondIndices
[
index
][
0
];
double
radiusI
;
gbviForce
.
getParticleParameters
(
bondedAtomIndex
,
charge
,
radiusI
,
gamma
);
double
rI2
=
radiusI
*
radiusI
;
double
a_ij
=
(
radiusI
-
bondLengths
[
index
]);
a_ij
*=
a_ij
;
a_ij
=
(
rJ2
-
a_ij
)
/
(
2.0
*
bondLengths
[
index
]);
double
a_ji
=
radiusJ
-
bondLengths
[
index
];
a_ji
*=
a_ji
;
a_ji
=
(
rI2
-
a_ji
)
/
(
2.0
*
bondLengths
[
index
]);
scaledRadiusJ
+=
a_ij
*
a_ij
*
(
3.0
*
radiusI
-
a_ij
)
+
a_ji
*
a_ji
*
(
3.0
*
radiusJ
-
a_ji
);
}
scaledRadiusJ
=
(
radiusJ
*
radiusJ
*
radiusJ
)
-
0.125
*
scaledRadiusJ
;
if
(
scaledRadiusJ
>
0.0
)
{
scaledRadiusJ
=
0.95
*
pow
(
scaledRadiusJ
,
(
1.0
/
3.0
));
}
else
{
scaledRadiusJ
=
0.0
;
}
}
scaledRadii
[
j
]
=
scaledRadiusJ
;
}
// abort if errors
if
(
errors
)
{
throw
OpenMMException
(
"GBVIForceImpl::findScaledRadii errors -- aborting"
);
}
}
}
// load parameters from gbviForce to customGbviForce
// findScaledRadii() is called to calculate the scaled radii (S)
// S is derived quantity in GBVIForce, not a parameter is the case here
static
void
loadGbviParameters
(
GBVIForce
*
gbviForce
,
CustomGBForce
*
customGbviForce
)
{
int
numParticles
=
gbviForce
->
getNumParticles
();
// charge, radius, scale factor, gamma
vector
<
double
>
params
(
4
);
std
::
vector
<
double
>
scaledRadii
;
findScaledRadii
(
*
gbviForce
,
scaledRadii
);
for
(
int
ii
=
0
;
ii
<
numParticles
;
ii
++
)
{
double
charge
,
radius
,
gamma
;
gbviForce
->
getParticleParameters
(
ii
,
charge
,
radius
,
gamma
);
params
[
0
]
=
charge
;
params
[
1
]
=
radius
;
params
[
2
]
=
scaledRadii
[
ii
];
params
[
3
]
=
gamma
;
customGbviForce
->
addParticle
(
params
);
}
}
void
testGBVI
(
GBVIForce
::
NonbondedMethod
gbviMethod
,
CustomGBForce
::
NonbondedMethod
customGbviMethod
,
std
::
string
molecule
)
{
const
int
numMolecules
=
1
;
const
double
boxSize
=
10.0
;
GBVIForce
*
gbvi
=
new
GBVIForce
();
std
::
vector
<
Vec3
>
positions
;
// select molecule
if
(
molecule
==
"Monomer"
)
{
buildMonomer
(
gbvi
,
positions
);
}
else
if
(
molecule
==
"Dimer"
)
{
buildDimer
(
gbvi
,
positions
);
}
else
{
buildEthane
(
gbvi
,
positions
);
}
int
numParticles
=
gbvi
->
getNumParticles
();
System
standardSystem
;
System
customGbviSystem
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
standardSystem
.
addParticle
(
1.0
);
customGbviSystem
.
addParticle
(
1.0
);
}
standardSystem
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
customGbviSystem
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0.0
,
0.0
),
Vec3
(
0.0
,
boxSize
,
0.0
),
Vec3
(
0.0
,
0.0
,
boxSize
));
gbvi
->
setCutoffDistance
(
2.0
);
// create customGbviForce GBVI force
CustomGBForce
*
customGbviForce
=
createCustomGBVI
(
gbvi
->
getSolventDielectric
(),
gbvi
->
getSoluteDielectric
());
customGbviForce
->
setCutoffDistance
(
2.0
);
// load parameters from gbvi to customGbviForce
loadGbviParameters
(
gbvi
,
customGbviForce
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
velocities
(
numParticles
);
for
(
int
ii
=
0
;
ii
<
numParticles
;
ii
++
)
{
velocities
[
ii
]
=
Vec3
(
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
),
genrand_real2
(
sfmt
));
}
gbvi
->
setNonbondedMethod
(
gbviMethod
);
customGbviForce
->
setNonbondedMethod
(
customGbviMethod
);
standardSystem
.
addForce
(
gbvi
);
customGbviSystem
.
addForce
(
customGbviForce
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
context1
(
standardSystem
,
integrator1
,
platform
);
context1
.
setPositions
(
positions
);
context1
.
setVelocities
(
velocities
);
State
state1
=
context1
.
getState
(
State
::
Forces
|
State
::
Energy
);
Context
context2
(
customGbviSystem
,
integrator2
,
platform
);
context2
.
setPositions
(
positions
);
context2
.
setVelocities
(
velocities
);
State
state2
=
context2
.
getState
(
State
::
Forces
|
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state1
.
getPotentialEnergy
(),
state2
.
getPotentialEnergy
(),
1e-4
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state2
.
getForces
()[
i
],
1e-4
);
}
}
int
main
()
{
try
{
testOBC
(
GBSAOBCForce
::
NoCutoff
,
CustomGBForce
::
NoCutoff
);
testOBC
(
GBSAOBCForce
::
CutoffNonPeriodic
,
CustomGBForce
::
CutoffNonPeriodic
);
testOBC
(
GBSAOBCForce
::
CutoffPeriodic
,
CustomGBForce
::
CutoffPeriodic
);
testMembrane
();
testTabulatedFunction
();
testMultipleChainRules
();
testPositionDependence
();
testExclusions
();
// GBVI tests
testGBVI
(
GBVIForce
::
NoCutoff
,
CustomGBForce
::
NoCutoff
,
"Monomer"
);
testGBVI
(
GBVIForce
::
NoCutoff
,
CustomGBForce
::
NoCutoff
,
"Dimer"
);
testGBVI
(
GBVIForce
::
NoCutoff
,
CustomGBForce
::
NoCutoff
,
"Ethane"
);
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCustomHbondForce.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 20
08-2012
Stanford University and the Authors. *
* Portions copyright (c) 20
15
Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,221 +29,8 @@
...
@@ -29,221 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of CustomHbondForce.
#include "TestCustomHbondForce.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/CustomHbondForce.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
void
testHbond
()
{
// Create a system using a CustomHbondForce.
System
customSystem
;
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
customSystem
.
addParticle
(
1.0
);
CustomHbondForce
*
custom
=
new
CustomHbondForce
(
"0.5*kr*(distance(d1,a1)-r0)^2 + 0.5*ktheta*(angle(a1,d1,d2)-theta0)^2 + 0.5*kpsi*(angle(d1,a1,a2)-psi0)^2 + kchi*(1+cos(n*dihedral(a3,a2,a1,d1)-chi0))"
);
custom
->
addPerDonorParameter
(
"r0"
);
custom
->
addPerDonorParameter
(
"theta0"
);
custom
->
addPerDonorParameter
(
"psi0"
);
custom
->
addPerAcceptorParameter
(
"chi0"
);
custom
->
addPerAcceptorParameter
(
"n"
);
custom
->
addGlobalParameter
(
"kr"
,
0.4
);
custom
->
addGlobalParameter
(
"ktheta"
,
0.5
);
custom
->
addGlobalParameter
(
"kpsi"
,
0.6
);
custom
->
addGlobalParameter
(
"kchi"
,
0.7
);
vector
<
double
>
parameters
(
3
);
parameters
[
0
]
=
1.5
;
parameters
[
1
]
=
1.7
;
parameters
[
2
]
=
1.9
;
custom
->
addDonor
(
1
,
0
,
-
1
,
parameters
);
parameters
.
resize
(
2
);
parameters
[
0
]
=
2.1
;
parameters
[
1
]
=
2
;
custom
->
addAcceptor
(
2
,
3
,
4
,
parameters
);
custom
->
setCutoffDistance
(
10.0
);
customSystem
.
addForce
(
custom
);
ASSERT
(
!
custom
->
usesPeriodicBoundaryConditions
());
ASSERT
(
!
customSystem
.
usesPeriodicBoundaryConditions
());
// Create an identical system using HarmonicBondForce, HarmonicAngleForce, and PeriodicTorsionForce.
System
standardSystem
;
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
standardSystem
.
addParticle
(
1.0
);
HarmonicBondForce
*
bond
=
new
HarmonicBondForce
();
bond
->
addBond
(
1
,
2
,
1.5
,
0.4
);
standardSystem
.
addForce
(
bond
);
HarmonicAngleForce
*
angle
=
new
HarmonicAngleForce
();
angle
->
addAngle
(
0
,
1
,
2
,
1.7
,
0.5
);
angle
->
addAngle
(
1
,
2
,
3
,
1.9
,
0.6
);
standardSystem
.
addForce
(
angle
);
PeriodicTorsionForce
*
torsion
=
new
PeriodicTorsionForce
();
torsion
->
addTorsion
(
1
,
2
,
3
,
4
,
2
,
2.1
,
0.7
);
standardSystem
.
addForce
(
torsion
);
// Set the atoms in various positions, and verify that both systems give identical forces and energy.
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
vector
<
Vec3
>
positions
(
5
);
VerletIntegrator
integrator1
(
0.01
);
VerletIntegrator
integrator2
(
0.01
);
Context
c1
(
customSystem
,
integrator1
,
platform
);
Context
c2
(
standardSystem
,
integrator2
,
platform
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
(
int
)
positions
.
size
();
j
++
)
positions
[
j
]
=
Vec3
(
2.0
*
genrand_real2
(
sfmt
),
2.0
*
genrand_real2
(
sfmt
),
2.0
*
genrand_real2
(
sfmt
));
c1
.
setPositions
(
positions
);
c2
.
setPositions
(
positions
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s2
.
getForces
()[
i
],
s1
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s2
.
getPotentialEnergy
(),
s1
.
getPotentialEnergy
(),
TOL
);
}
// Try changing the parameters and make sure it's still correct.
parameters
.
resize
(
3
);
parameters
[
0
]
=
1.4
;
parameters
[
1
]
=
1.7
;
parameters
[
2
]
=
1.9
;
custom
->
setDonorParameters
(
0
,
1
,
0
,
-
1
,
parameters
);
parameters
.
resize
(
2
);
parameters
[
0
]
=
2.2
;
parameters
[
1
]
=
2
;
custom
->
setAcceptorParameters
(
0
,
2
,
3
,
4
,
parameters
);
bond
->
setBondParameters
(
0
,
1
,
2
,
1.4
,
0.4
);
torsion
->
setTorsionParameters
(
0
,
1
,
2
,
3
,
4
,
2
,
2.2
,
0.7
);
custom
->
updateParametersInContext
(
c1
);
bond
->
updateParametersInContext
(
c2
);
torsion
->
updateParametersInContext
(
c2
);
State
s1
=
c1
.
getState
(
State
::
Forces
|
State
::
Energy
);
State
s2
=
c2
.
getState
(
State
::
Forces
|
State
::
Energy
);
for
(
int
i
=
0
;
i
<
customSystem
.
getNumParticles
();
i
++
)
ASSERT_EQUAL_VEC
(
s2
.
getForces
()[
i
],
s1
.
getForces
()[
i
],
TOL
);
ASSERT_EQUAL_TOL
(
s2
.
getPotentialEnergy
(),
s1
.
getPotentialEnergy
(),
TOL
);
}
}
void
testExclusions
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomHbondForce
*
custom
=
new
CustomHbondForce
(
"(distance(d1,a1)-1)^2"
);
custom
->
addDonor
(
0
,
1
,
-
1
,
vector
<
double
>
());
custom
->
addDonor
(
1
,
0
,
-
1
,
vector
<
double
>
());
custom
->
addAcceptor
(
2
,
0
,
-
1
,
vector
<
double
>
());
custom
->
addExclusion
(
1
,
0
);
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
,
0
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
forces
[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
2
,
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_TOL
(
1.0
,
state
.
getPotentialEnergy
(),
TOL
);
}
void
testCutoff
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomHbondForce
*
custom
=
new
CustomHbondForce
(
"(distance(d1,a1)-1)^2"
);
custom
->
addDonor
(
0
,
1
,
-
1
,
vector
<
double
>
());
custom
->
addDonor
(
1
,
0
,
-
1
,
vector
<
double
>
());
custom
->
addAcceptor
(
2
,
0
,
-
1
,
vector
<
double
>
());
custom
->
setNonbondedMethod
(
CustomHbondForce
::
CutoffNonPeriodic
);
custom
->
setCutoffDistance
(
2.5
);
system
.
addForce
(
custom
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
3
);
positions
[
0
]
=
Vec3
(
0
,
0
,
0
);
positions
[
1
]
=
Vec3
(
0
,
3
,
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
,
0
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
0
,
0
),
forces
[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
2
,
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_TOL
(
1.0
,
state
.
getPotentialEnergy
(),
TOL
);
}
void
testCustomFunctions
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
VerletIntegrator
integrator
(
0.01
);
CustomHbondForce
*
custom
=
new
CustomHbondForce
(
"foo(distance(d1,a1))"
);
custom
->
addDonor
(
1
,
0
,
-
1
,
vector
<
double
>
());
custom
->
addDonor
(
2
,
0
,
-
1
,
vector
<
double
>
());
custom
->
addAcceptor
(
0
,
1
,
-
1
,
vector
<
double
>
());
vector
<
double
>
function
(
2
);
function
[
0
]
=
0
;
function
[
1
]
=
1
;
custom
->
addTabulatedFunction
(
"foo"
,
new
Continuous1DFunction
(
function
,
0
,
10
));
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
(
0.1
,
0.1
,
0
),
forces
[
0
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
0
,
-
0.1
,
0
),
forces
[
1
],
TOL
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.1
,
0
,
0
),
forces
[
2
],
TOL
);
ASSERT_EQUAL_TOL
(
0.1
*
2
+
0.1
*
2
,
state
.
getPotentialEnergy
(),
TOL
);
}
int
main
()
{
try
{
testHbond
();
testExclusions
();
testCutoff
();
testCustomFunctions
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
platforms/reference/tests/TestReferenceCustomIntegrator.cpp
View file @
fd473eea
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c)
2008-
2015 Stanford University and the Authors. *
* Portions copyright (c) 2015 Stanford University and the Authors.
*
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -29,747 +29,8 @@
...
@@ -29,747 +29,8 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
/**
#include "ReferenceTests.h"
* This tests the reference implementation of CustomIntegrator.
#include "TestCustomIntegrator.h"
*/
#include "openmm/internal/AssertionUtilities.h"
void
runPlatformTests
()
{
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "openmm/AndersenThermostat.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/System.h"
#include "openmm/CustomIntegrator.h"
#include "SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using
namespace
OpenMM
;
using
namespace
std
;
ReferencePlatform
platform
;
const
double
TOL
=
1e-5
;
/**
* Test a simple leapfrog integrator on a single bond.
*/
void
testSingleBond
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
const
double
dt
=
0.01
;
CustomIntegrator
integrator
(
dt
);
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
setKineticEnergyExpression
(
"m*v1*v1/2; v1=v+0.5*dt*f/m"
);
HarmonicBondForce
*
forceField
=
new
HarmonicBondForce
();
forceField
->
addBond
(
0
,
1
,
1.5
,
1
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
vector
<
Vec3
>
velocities
(
2
);
velocities
[
0
]
=
Vec3
(
-
0.5
*
dt
*
0.5
*
0.5
,
0
,
0
);
velocities
[
1
]
=
Vec3
(
0.5
*
dt
*
0.5
*
0.5
,
0
,
0
);
context
.
setVelocities
(
velocities
);
// This is simply a harmonic oscillator, so compare it to the analytical solution.
const
double
freq
=
1.0
;;
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
|
State
::
Energy
);
double
time
=
state
.
getTime
();
double
expectedDist
=
1.5
+
0.5
*
std
::
cos
(
freq
*
time
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
*
expectedDist
,
0
,
0
),
state
.
getPositions
()[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.5
*
expectedDist
,
0
,
0
),
state
.
getPositions
()[
1
],
1e-4
);
double
expectedSpeed
=
-
0.5
*
freq
*
std
::
sin
(
freq
*
(
time
-
dt
/
2
));
ASSERT_EQUAL_VEC
(
Vec3
(
-
0.5
*
expectedSpeed
,
0
,
0
),
state
.
getVelocities
()[
0
],
1e-4
);
ASSERT_EQUAL_VEC
(
Vec3
(
0.5
*
expectedSpeed
,
0
,
0
),
state
.
getVelocities
()[
1
],
1e-4
);
double
energy
=
state
.
getKineticEnergy
()
+
state
.
getPotentialEnergy
();
ASSERT_EQUAL_TOL
(
0.5
*
0.5
*
0.5
,
energy
,
1e-4
);
integrator
.
step
(
1
);
}
}
/**
* Test an integrator that enforces constraints.
*/
void
testConstraints
()
{
const
int
numParticles
=
8
;
const
double
temp
=
500.0
;
System
system
;
CustomIntegrator
integrator
(
0.002
);
integrator
.
addPerDofVariable
(
"oldx"
,
0
);
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"oldx"
,
"x"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
addConstrainPositions
();
integrator
.
addComputePerDof
(
"v"
,
"(x-oldx)/dt"
);
integrator
.
setConstraintTolerance
(
1e-5
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
i
%
2
==
0
?
5.0
:
10.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
0.2
:
-
0.2
),
0.5
,
5.0
);
}
for
(
int
i
=
0
;
i
<
numParticles
-
1
;
++
i
)
system
.
addConstraint
(
i
,
i
+
1
,
1.0
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
(
i
/
2
,
(
i
+
1
)
/
2
,
0
);
velocities
[
i
]
=
Vec3
(
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
);
}
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
// Simulate it and see whether the constraints remain satisfied.
double
initialEnergy
=
0.0
;
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Energy
);
for
(
int
j
=
0
;
j
<
system
.
getNumConstraints
();
++
j
)
{
int
particle1
,
particle2
;
double
distance
;
system
.
getConstraintParameters
(
j
,
particle1
,
particle2
,
distance
);
Vec3
p1
=
state
.
getPositions
()[
particle1
];
Vec3
p2
=
state
.
getPositions
()[
particle2
];
double
dist
=
std
::
sqrt
((
p1
[
0
]
-
p2
[
0
])
*
(
p1
[
0
]
-
p2
[
0
])
+
(
p1
[
1
]
-
p2
[
1
])
*
(
p1
[
1
]
-
p2
[
1
])
+
(
p1
[
2
]
-
p2
[
2
])
*
(
p1
[
2
]
-
p2
[
2
]));
ASSERT_EQUAL_TOL
(
distance
,
dist
,
2e-5
);
}
double
energy
=
state
.
getKineticEnergy
()
+
state
.
getPotentialEnergy
();
if
(
i
==
1
)
initialEnergy
=
energy
;
else
if
(
i
>
1
)
ASSERT_EQUAL_TOL
(
initialEnergy
,
energy
,
0.01
);
integrator
.
step
(
1
);
}
}
/**
* Test an integrator that applies constraints directly to velocities.
*/
void
testVelocityConstraints
()
{
const
int
numParticles
=
10
;
System
system
;
CustomIntegrator
integrator
(
0.002
);
integrator
.
addPerDofVariable
(
"x1"
,
0
);
integrator
.
addComputePerDof
(
"v"
,
"v+0.5*dt*f/m"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
addComputePerDof
(
"x1"
,
"x"
);
integrator
.
addConstrainPositions
();
integrator
.
addComputePerDof
(
"v"
,
"v+0.5*dt*f/m+(x-x1)/dt"
);
integrator
.
addConstrainVelocities
();
integrator
.
setConstraintTolerance
(
1e-5
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
i
%
2
==
0
?
5.0
:
10.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
0.2
:
-
0.2
),
0.5
,
5.0
);
}
// Constrain the first three particles with SHAKE.
system
.
addConstraint
(
0
,
1
,
1.0
);
system
.
addConstraint
(
1
,
2
,
1.0
);
// Constrain the next three with SETTLE.
system
.
addConstraint
(
3
,
4
,
1.0
);
system
.
addConstraint
(
5
,
4
,
1.0
);
system
.
addConstraint
(
3
,
5
,
sqrt
(
2.0
));
// Constraint the rest with CCMA.
for
(
int
i
=
6
;
i
<
numParticles
-
1
;
++
i
)
system
.
addConstraint
(
i
,
i
+
1
,
1.0
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
(
i
/
2
,
(
i
+
1
)
/
2
,
0
);
velocities
[
i
]
=
Vec3
(
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
);
}
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
// Simulate it and see whether the constraints remain satisfied.
double
initialEnergy
=
0.0
;
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
integrator
.
step
(
2
);
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Velocities
|
State
::
Energy
);
for
(
int
j
=
0
;
j
<
system
.
getNumConstraints
();
++
j
)
{
int
particle1
,
particle2
;
double
distance
;
system
.
getConstraintParameters
(
j
,
particle1
,
particle2
,
distance
);
Vec3
p1
=
state
.
getPositions
()[
particle1
];
Vec3
p2
=
state
.
getPositions
()[
particle2
];
double
dist
=
std
::
sqrt
((
p1
[
0
]
-
p2
[
0
])
*
(
p1
[
0
]
-
p2
[
0
])
+
(
p1
[
1
]
-
p2
[
1
])
*
(
p1
[
1
]
-
p2
[
1
])
+
(
p1
[
2
]
-
p2
[
2
])
*
(
p1
[
2
]
-
p2
[
2
]));
ASSERT_EQUAL_TOL
(
distance
,
dist
,
2e-5
);
if
(
i
>
0
)
{
Vec3
v1
=
state
.
getVelocities
()[
particle1
];
Vec3
v2
=
state
.
getVelocities
()[
particle2
];
double
vel
=
(
v1
-
v2
).
dot
(
p1
-
p2
);
ASSERT_EQUAL_TOL
(
0.0
,
vel
,
2e-5
);
}
}
double
energy
=
state
.
getKineticEnergy
()
+
state
.
getPotentialEnergy
();
if
(
i
==
0
)
initialEnergy
=
energy
;
else
if
(
i
>
0
)
ASSERT_EQUAL_TOL
(
initialEnergy
,
energy
,
0.01
);
}
}
void
testConstrainedMasslessParticles
()
{
System
system
;
system
.
addParticle
(
0.0
);
system
.
addParticle
(
1.0
);
system
.
addConstraint
(
0
,
1
,
1.5
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
CustomIntegrator
integrator
(
0.002
);
integrator
.
addPerDofVariable
(
"oldx"
,
0
);
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"oldx"
,
"x"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
addConstrainPositions
();
integrator
.
addComputePerDof
(
"v"
,
"(x-oldx)/dt"
);
bool
failed
=
false
;
try
{
// This should throw an exception.
Context
context
(
system
,
integrator
,
platform
);
}
catch
(
exception
&
ex
)
{
failed
=
true
;
}
ASSERT
(
failed
);
// Now make both particles massless, which should work.
system
.
setParticleMass
(
1
,
0.0
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
300.0
);
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Velocities
|
State
::
Positions
);
ASSERT_EQUAL
(
0.0
,
state
.
getVelocities
()[
0
][
0
]);
}
/**
* Test an integrator with an AndersenThermostat to see if updateContextState()
* is being handled correctly.
*/
void
testWithThermostat
()
{
const
int
numParticles
=
8
;
const
double
temp
=
100.0
;
const
double
collisionFreq
=
10.0
;
const
int
numSteps
=
5000
;
System
system
;
CustomIntegrator
integrator
(
0.003
);
integrator
.
addUpdateContextState
();
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
NonbondedForce
*
forceField
=
new
NonbondedForce
();
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
2.0
);
forceField
->
addParticle
((
i
%
2
==
0
?
1.0
:
-
1.0
),
1.0
,
5.0
);
}
system
.
addForce
(
forceField
);
AndersenThermostat
*
thermostat
=
new
AndersenThermostat
(
temp
,
collisionFreq
);
system
.
addForce
(
thermostat
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
positions
[
i
]
=
Vec3
((
i
%
2
==
0
?
2
:
-
2
),
(
i
%
4
<
2
?
2
:
-
2
),
(
i
<
4
?
2
:
-
2
));
context
.
setPositions
(
positions
);
context
.
setVelocitiesToTemperature
(
temp
);
// Let it equilibrate.
integrator
.
step
(
10000
);
// Now run it for a while and see if the temperature is correct.
double
ke
=
0.0
;
for
(
int
i
=
0
;
i
<
numSteps
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Energy
);
ke
+=
state
.
getKineticEnergy
();
integrator
.
step
(
10
);
}
ke
/=
numSteps
;
double
expected
=
0.5
*
numParticles
*
3
*
BOLTZ
*
temp
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
ke
,
0.1
);
}
/**
* Test a Monte Carlo integrator that uses global variables and depends on energy.
*/
void
testMonteCarlo
()
{
System
system
;
system
.
addParticle
(
1.0
);
system
.
addParticle
(
1.0
);
CustomIntegrator
integrator
(
0.1
);
const
double
kT
=
BOLTZ
*
300.0
;
integrator
.
addGlobalVariable
(
"kT"
,
kT
);
integrator
.
addGlobalVariable
(
"oldE"
,
0
);
integrator
.
addGlobalVariable
(
"accept"
,
0
);
integrator
.
addPerDofVariable
(
"oldx"
,
0
);
integrator
.
addComputeGlobal
(
"oldE"
,
"energy"
);
integrator
.
addComputePerDof
(
"oldx"
,
"x"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*gaussian"
);
integrator
.
addComputeGlobal
(
"accept"
,
"step(exp((oldE-energy)/kT)-uniform)"
);
integrator
.
addComputePerDof
(
"x"
,
"select(accept, x, oldx)"
);
HarmonicBondForce
*
forceField
=
new
HarmonicBondForce
();
forceField
->
addBond
(
0
,
1
,
2.0
,
10.0
);
system
.
addForce
(
forceField
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
// Compute the histogram of distances and see if it satisfies a Boltzmann distribution.
const
int
numBins
=
100
;
const
double
maxDist
=
4.0
;
const
int
numIterations
=
5000
;
vector
<
int
>
counts
(
numBins
,
0
);
for
(
int
i
=
0
;
i
<
numIterations
;
++
i
)
{
integrator
.
step
(
10
);
State
state
=
context
.
getState
(
State
::
Positions
);
Vec3
delta
=
state
.
getPositions
()[
0
]
-
state
.
getPositions
()[
1
];
double
dist
=
sqrt
(
delta
.
dot
(
delta
));
if
(
dist
<
maxDist
)
counts
[(
int
)
(
numBins
*
dist
/
maxDist
)]
++
;
}
vector
<
double
>
expected
(
numBins
,
0
);
double
sum
=
0
;
for
(
int
i
=
0
;
i
<
numBins
;
i
++
)
{
double
dist
=
(
i
+
0.5
)
*
maxDist
/
numBins
;
expected
[
i
]
=
dist
*
dist
*
exp
(
-
5.0
*
(
dist
-
2
)
*
(
dist
-
2
)
/
kT
);
sum
+=
expected
[
i
];
}
for
(
int
i
=
0
;
i
<
numBins
;
i
++
)
ASSERT_USUALLY_EQUAL_TOL
((
double
)
counts
[
i
]
/
numIterations
,
expected
[
i
]
/
sum
,
0.01
);
}
/**
* Test the ComputeSum operation.
*/
void
testSum
()
{
const
int
numParticles
=
200
;
const
double
boxSize
=
10
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
NonbondedForce
*
nb
=
new
NonbondedForce
();
system
.
addForce
(
nb
);
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
i
%
10
==
0
?
0.0
:
1.5
);
nb
->
addParticle
(
i
%
2
==
0
?
0.1
:
-
0.1
,
0.1
,
1
);
bool
close
=
true
;
while
(
close
)
{
positions
[
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
close
=
false
;
for
(
int
j
=
0
;
j
<
i
;
++
j
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
if
(
delta
.
dot
(
delta
)
<
1
)
close
=
true
;
}
}
}
CustomIntegrator
integrator
(
0.005
);
integrator
.
addGlobalVariable
(
"ke"
,
0
);
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
addComputeSum
(
"ke"
,
"m*v*v/2"
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// See if the sum is being computed correctly.
for
(
int
i
=
0
;
i
<
100
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
state
.
getKineticEnergy
(),
integrator
.
getGlobalVariable
(
0
),
1e-5
);
integrator
.
step
(
1
);
}
}
/**
* Test an integrator that both uses and modifies a context parameter.
*/
void
testParameter
()
{
System
system
;
system
.
addParticle
(
1.0
);
AndersenThermostat
*
thermostat
=
new
AndersenThermostat
(
0.1
,
0.1
);
system
.
addForce
(
thermostat
);
CustomIntegrator
integrator
(
0.1
);
integrator
.
addGlobalVariable
(
"temp"
,
0
);
integrator
.
addComputeGlobal
(
"temp"
,
"AndersenTemperature"
);
integrator
.
addComputeGlobal
(
"AndersenTemperature"
,
"temp*2"
);
Context
context
(
system
,
integrator
,
platform
);
// See if the parameter is being used correctly.
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
context
.
getParameter
(
"AndersenTemperature"
),
0.1
*
(
1
<<
(
i
+
1
)),
1e-10
);
}
}
/**
* Test random number distributions.
*/
void
testRandomDistributions
()
{
const
int
numParticles
=
100
;
const
int
numBins
=
20
;
const
int
numSteps
=
100
;
System
system
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
system
.
addParticle
(
1.0
);
CustomIntegrator
integrator
(
0.1
);
integrator
.
addPerDofVariable
(
"a"
,
0
);
integrator
.
addPerDofVariable
(
"b"
,
0
);
integrator
.
addComputePerDof
(
"a"
,
"uniform"
);
integrator
.
addComputePerDof
(
"b"
,
"gaussian"
);
Context
context
(
system
,
integrator
,
platform
);
// See if the random numbers are distributed correctly.
vector
<
int
>
bins
(
numBins
);
double
mean
=
0.0
;
double
var
=
0.0
;
double
skew
=
0.0
;
double
kurtosis
=
0.0
;
vector
<
Vec3
>
values
;
for
(
int
i
=
0
;
i
<
numSteps
;
i
++
)
{
integrator
.
step
(
1
);
integrator
.
getPerDofVariable
(
0
,
values
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
double
v
=
values
[
i
][
j
];
ASSERT
(
v
>=
0
&&
v
<
1
);
bins
[(
int
)
(
v
*
numBins
)]
++
;
}
integrator
.
getPerDofVariable
(
1
,
values
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
double
v
=
values
[
i
][
j
];
mean
+=
v
;
var
+=
v
*
v
;
skew
+=
v
*
v
*
v
;
kurtosis
+=
v
*
v
*
v
*
v
;
}
}
// Check the distribution of uniform randoms.
int
numValues
=
numParticles
*
numSteps
*
3
;
double
expected
=
numValues
/
(
double
)
numBins
;
double
tol
=
4
*
sqrt
(
expected
);
for
(
int
i
=
0
;
i
<
numBins
;
i
++
)
ASSERT
(
bins
[
i
]
>=
expected
-
tol
&&
bins
[
i
]
<=
expected
+
tol
);
// Check the distribution of gaussian randoms.
mean
/=
numValues
;
var
/=
numValues
;
skew
/=
numValues
;
kurtosis
/=
numValues
;
double
c2
=
var
-
mean
*
mean
;
double
c3
=
skew
-
3
*
var
*
mean
+
2
*
mean
*
mean
*
mean
;
double
c4
=
kurtosis
-
4
*
skew
*
mean
-
3
*
var
*
var
+
12
*
var
*
mean
*
mean
-
6
*
mean
*
mean
*
mean
*
mean
;
ASSERT_EQUAL_TOL
(
0.0
,
mean
,
3.0
/
sqrt
((
double
)
numValues
));
ASSERT_EQUAL_TOL
(
1.0
,
c2
,
3.0
/
pow
(
numValues
,
1.0
/
3.0
));
ASSERT_EQUAL_TOL
(
0.0
,
c3
,
3.0
/
pow
(
numValues
,
1.0
/
4.0
));
ASSERT_EQUAL_TOL
(
0.0
,
c4
,
3.0
/
pow
(
numValues
,
1.0
/
4.0
));
}
/**
* Test getting and setting per-DOF variables.
*/
void
testPerDofVariables
()
{
const
int
numParticles
=
200
;
const
double
boxSize
=
10
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
NonbondedForce
*
nb
=
new
NonbondedForce
();
system
.
addForce
(
nb
);
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffNonPeriodic
);
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.5
);
nb
->
addParticle
(
i
%
2
==
0
?
1
:
-
1
,
0.1
,
1
);
bool
close
=
true
;
while
(
close
)
{
positions
[
i
]
=
Vec3
(
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
),
boxSize
*
genrand_real2
(
sfmt
));
close
=
false
;
for
(
int
j
=
0
;
j
<
i
;
++
j
)
{
Vec3
delta
=
positions
[
i
]
-
positions
[
j
];
if
(
delta
.
dot
(
delta
)
<
0.1
)
close
=
true
;
}
}
}
CustomIntegrator
integrator
(
0.01
);
integrator
.
addPerDofVariable
(
"temp"
,
0
);
integrator
.
addPerDofVariable
(
"pos"
,
0
);
integrator
.
addComputePerDof
(
"v"
,
"v+dt*f/m"
);
integrator
.
addComputePerDof
(
"x"
,
"x+dt*v"
);
integrator
.
addComputePerDof
(
"pos"
,
"x"
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
vector
<
Vec3
>
initialValues
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
initialValues
[
i
]
=
Vec3
(
i
+
0.1
,
i
+
0.2
,
i
+
0.3
);
integrator
.
setPerDofVariable
(
0
,
initialValues
);
// Run a simulation, then query per-DOF values and see if they are correct.
vector
<
Vec3
>
values
;
for
(
int
i
=
0
;
i
<
100
;
++
i
)
{
integrator
.
step
(
1
);
State
state
=
context
.
getState
(
State
::
Positions
);
integrator
.
getPerDofVariable
(
0
,
values
);
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
ASSERT_EQUAL_VEC
(
initialValues
[
j
],
values
[
j
],
1e-5
);
integrator
.
getPerDofVariable
(
1
,
values
);
for
(
int
j
=
0
;
j
<
numParticles
;
j
++
)
ASSERT_EQUAL_VEC
(
state
.
getPositions
()[
j
],
values
[
j
],
1e-5
);
}
}
/**
* Test evaluating force groups separately.
*/
void
testForceGroups
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
CustomIntegrator
integrator
(
0.01
);
integrator
.
addPerDofVariable
(
"outf"
,
0
);
integrator
.
addPerDofVariable
(
"outf1"
,
0
);
integrator
.
addPerDofVariable
(
"outf2"
,
0
);
integrator
.
addGlobalVariable
(
"oute"
,
0
);
integrator
.
addGlobalVariable
(
"oute1"
,
0
);
integrator
.
addGlobalVariable
(
"oute2"
,
0
);
integrator
.
addComputePerDof
(
"outf"
,
"f"
);
integrator
.
addComputePerDof
(
"outf1"
,
"f1"
);
integrator
.
addComputePerDof
(
"outf2"
,
"f2"
);
integrator
.
addComputeGlobal
(
"oute"
,
"energy"
);
integrator
.
addComputeGlobal
(
"oute1"
,
"energy1"
);
integrator
.
addComputeGlobal
(
"oute2"
,
"energy2"
);
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
bonds
->
addBond
(
0
,
1
,
1.5
,
1.1
);
bonds
->
setForceGroup
(
1
);
system
.
addForce
(
bonds
);
NonbondedForce
*
nb
=
new
NonbondedForce
();
nb
->
addParticle
(
0.2
,
1
,
0
);
nb
->
addParticle
(
0.2
,
1
,
0
);
nb
->
setForceGroup
(
2
);
system
.
addForce
(
nb
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
2
);
positions
[
0
]
=
Vec3
(
-
1
,
0
,
0
);
positions
[
1
]
=
Vec3
(
1
,
0
,
0
);
context
.
setPositions
(
positions
);
// See if the various forces are computed correctly.
integrator
.
step
(
1
);
vector
<
Vec3
>
f
,
f1
,
f2
;
double
e1
=
0.5
*
1.1
*
0.5
*
0.5
;
double
e2
=
138.935456
*
0.2
*
0.2
/
2.0
;
integrator
.
getPerDofVariable
(
0
,
f
);
integrator
.
getPerDofVariable
(
1
,
f1
);
integrator
.
getPerDofVariable
(
2
,
f2
);
ASSERT_EQUAL_VEC
(
Vec3
(
1.1
*
0.5
,
0
,
0
),
f1
[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
1.1
*
0.5
,
0
,
0
),
f1
[
1
],
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
-
138.935456
*
0.2
*
0.2
/
4.0
,
0
,
0
),
f2
[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
Vec3
(
138.935456
*
0.2
*
0.2
/
4.0
,
0
,
0
),
f2
[
1
],
1e-5
);
ASSERT_EQUAL_VEC
(
f1
[
0
]
+
f2
[
0
],
f
[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
f1
[
1
]
+
f2
[
1
],
f
[
1
],
1e-5
);
ASSERT_EQUAL_TOL
(
e1
,
integrator
.
getGlobalVariable
(
1
),
1e-5
);
ASSERT_EQUAL_TOL
(
e2
,
integrator
.
getGlobalVariable
(
2
),
1e-5
);
ASSERT_EQUAL_TOL
(
e1
+
e2
,
integrator
.
getGlobalVariable
(
0
),
1e-5
);
// Make sure they also match the values returned by the Context.
State
s
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
,
false
);
State
s1
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
,
false
,
2
);
State
s2
=
context
.
getState
(
State
::
Forces
|
State
::
Energy
,
false
,
4
);
vector
<
Vec3
>
c
,
c1
,
c2
;
c
=
context
.
getState
(
State
::
Forces
,
false
).
getForces
();
c1
=
context
.
getState
(
State
::
Forces
,
false
,
2
).
getForces
();
c2
=
context
.
getState
(
State
::
Forces
,
false
,
4
).
getForces
();
ASSERT_EQUAL_VEC
(
f
[
0
],
c
[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
f
[
1
],
c
[
1
],
1e-5
);
ASSERT_EQUAL_VEC
(
f1
[
0
],
c1
[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
f1
[
1
],
c1
[
1
],
1e-5
);
ASSERT_EQUAL_VEC
(
f2
[
0
],
c2
[
0
],
1e-5
);
ASSERT_EQUAL_VEC
(
f2
[
1
],
c2
[
1
],
1e-5
);
ASSERT_EQUAL_TOL
(
s
.
getPotentialEnergy
(),
integrator
.
getGlobalVariable
(
0
),
1e-5
);
ASSERT_EQUAL_TOL
(
s1
.
getPotentialEnergy
(),
integrator
.
getGlobalVariable
(
1
),
1e-5
);
ASSERT_EQUAL_TOL
(
s2
.
getPotentialEnergy
(),
integrator
.
getGlobalVariable
(
2
),
1e-5
);
}
/**
* Test a multiple time step r-RESPA integrator.
*/
void
testRespa
()
{
const
int
numParticles
=
8
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
4
,
0
,
0
),
Vec3
(
0
,
4
,
0
),
Vec3
(
0
,
0
,
4
));
CustomIntegrator
integrator
(
0.002
);
integrator
.
addComputePerDof
(
"v"
,
"v+0.5*dt*f1/m"
);
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
integrator
.
addComputePerDof
(
"v"
,
"v+0.5*(dt/2)*f0/m"
);
integrator
.
addComputePerDof
(
"x"
,
"x+(dt/2)*v"
);
integrator
.
addComputePerDof
(
"v"
,
"v+0.5*(dt/2)*f0/m"
);
}
integrator
.
addComputePerDof
(
"v"
,
"v+0.5*dt*f1/m"
);
HarmonicBondForce
*
bonds
=
new
HarmonicBondForce
();
for
(
int
i
=
0
;
i
<
numParticles
-
2
;
i
++
)
bonds
->
addBond
(
i
,
i
+
1
,
1.0
,
0.5
);
system
.
addForce
(
bonds
);
NonbondedForce
*
nb
=
new
NonbondedForce
();
nb
->
setCutoffDistance
(
2.0
);
nb
->
setNonbondedMethod
(
NonbondedForce
::
Ewald
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
i
%
2
==
0
?
5.0
:
10.0
);
nb
->
addParticle
((
i
%
2
==
0
?
0.2
:
-
0.2
),
0.5
,
5.0
);
}
nb
->
setForceGroup
(
1
);
nb
->
setReciprocalSpaceForceGroup
(
0
);
system
.
addForce
(
nb
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
Vec3
>
velocities
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
positions
[
i
]
=
Vec3
(
i
/
2
,
(
i
+
1
)
/
2
,
0
);
velocities
[
i
]
=
Vec3
(
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
,
genrand_real2
(
sfmt
)
-
0.5
);
}
context
.
setPositions
(
positions
);
context
.
setVelocities
(
velocities
);
// Simulate it and monitor energy conservations.
double
initialEnergy
=
0.0
;
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
{
State
state
=
context
.
getState
(
State
::
Energy
);
double
energy
=
state
.
getKineticEnergy
()
+
state
.
getPotentialEnergy
();
if
(
i
==
1
)
initialEnergy
=
energy
;
else
if
(
i
>
1
)
ASSERT_EQUAL_TOL
(
initialEnergy
,
energy
,
0.05
);
integrator
.
step
(
2
);
}
}
void
testIfBlock
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
const
double
dt
=
0.01
;
CustomIntegrator
integrator
(
dt
);
integrator
.
addGlobalVariable
(
"a"
,
0
);
integrator
.
addGlobalVariable
(
"b"
,
0
);
integrator
.
addComputeGlobal
(
"b"
,
"1"
);
integrator
.
beginIfBlock
(
"a < 3.5"
);
integrator
.
addComputeGlobal
(
"b"
,
"a+1"
);
integrator
.
endBlock
();
Context
context
(
system
,
integrator
,
platform
);
// Set "a" to 1.7 and verify that "b" gets set to a+1.
integrator
.
setGlobalVariable
(
0
,
1.7
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
2.7
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
// Now set it to a value that should cause the block to be skipped.
integrator
.
setGlobalVariable
(
0
,
4.1
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
1.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
}
void
testWhileBlock
()
{
System
system
;
system
.
addParticle
(
2.0
);
system
.
addParticle
(
2.0
);
const
double
dt
=
0.01
;
CustomIntegrator
integrator
(
dt
);
integrator
.
addGlobalVariable
(
"a"
,
0
);
integrator
.
addGlobalVariable
(
"b"
,
0
);
integrator
.
addComputeGlobal
(
"b"
,
"1"
);
integrator
.
beginWhileBlock
(
"b <= a"
);
integrator
.
addComputeGlobal
(
"b"
,
"b+1"
);
integrator
.
endBlock
();
Context
context
(
system
,
integrator
,
platform
);
// Try a case where the loop should be skipped.
integrator
.
setGlobalVariable
(
0
,
-
3.3
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
1.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
// In this case it should be executed exactly once.
integrator
.
setGlobalVariable
(
0
,
1.2
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
2.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
// In this case, it should be executed several times.
integrator
.
setGlobalVariable
(
0
,
5.3
);
integrator
.
step
(
1
);
ASSERT_EQUAL_TOL
(
6.0
,
integrator
.
getGlobalVariable
(
1
),
1e-6
);
}
int
main
()
{
try
{
testSingleBond
();
testConstraints
();
testVelocityConstraints
();
testConstrainedMasslessParticles
();
testWithThermostat
();
testMonteCarlo
();
testSum
();
testParameter
();
testRandomDistributions
();
testPerDofVariables
();
testForceGroups
();
testRespa
();
testIfBlock
();
testWhileBlock
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
}
Prev
1
…
8
9
10
11
12
13
14
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