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
cceb3171
Commit
cceb3171
authored
Sep 18, 2015
by
peastman
Browse files
Reference implementation of periodicdistance() function for CustomExternalForce
parent
992487c6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
108 additions
and
1 deletion
+108
-1
openmmapi/include/openmm/CustomExternalForce.h
openmmapi/include/openmm/CustomExternalForce.h
+8
-0
platforms/reference/include/ReferenceKernels.h
platforms/reference/include/ReferenceKernels.h
+13
-0
platforms/reference/src/ReferenceKernels.cpp
platforms/reference/src/ReferenceKernels.cpp
+45
-1
platforms/reference/tests/TestReferenceCustomExternalForce.cpp
...orms/reference/tests/TestReferenceCustomExternalForce.cpp
+42
-0
No files found.
openmmapi/include/openmm/CustomExternalForce.h
View file @
cceb3171
...
...
@@ -67,6 +67,14 @@ namespace OpenMM {
* force->addPerParticleParameter("z0");
* </pre></tt>
*
* Special care is needed in systems that use periodic boundary conditions. In that case, each particle really represents
* an infinite set of particles repeating through space. The variables x, y, and z contain the coordinates of one of those
* periodic copies, but there is no guarantee about which. It might even change from one time step to the next. You can handle
* this situation by using the function periodicdistance(x1, y1, z1, x2, y2, z2), which returns the minimum distance between
* periodic copies of the points (x1, y1, z1) and (x2, y2, z2). For example, the force given above would be rewritten as
*
* <tt>CustomExternalForce* force = new CustomExternalForce("k*periodicdistance(x, y, z, x0, y0, z0)^2");</tt>
*
* Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following
* functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions
* are defined in radians, and log is the natural logarithm. step(x) = 0 if x is less than 0, 1 otherwise. delta(x) = 1 if x is 0, 0 otherwise.
...
...
platforms/reference/include/ReferenceKernels.h
View file @
cceb3171
...
...
@@ -37,6 +37,7 @@
#include "SimTKOpenMMRealType.h"
#include "ReferenceNeighborList.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CustomFunction.h"
#include "lepton/ExpressionProgram.h"
namespace
OpenMM
{
...
...
@@ -795,11 +796,23 @@ public:
*/
void
copyParametersToContext
(
ContextImpl
&
context
,
const
CustomExternalForce
&
force
);
private:
class
PeriodicDistanceFunction
;
int
numParticles
;
std
::
vector
<
int
>
particles
;
RealOpenMM
**
particleParamArray
;
Lepton
::
CompiledExpression
energyExpression
,
forceExpressionX
,
forceExpressionY
,
forceExpressionZ
;
std
::
vector
<
std
::
string
>
parameterNames
,
globalParameterNames
;
RealVec
*
boxVectors
;
};
class
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
:
public
Lepton
::
CustomFunction
{
public:
RealVec
**
boxVectorHandle
;
PeriodicDistanceFunction
(
RealVec
**
boxVectorHandle
);
int
getNumArguments
()
const
;
double
evaluate
(
const
double
*
arguments
)
const
;
double
evaluateDerivative
(
const
double
*
arguments
,
const
int
*
derivOrder
)
const
;
Lepton
::
CustomFunction
*
clone
()
const
;
};
/**
...
...
platforms/reference/src/ReferenceKernels.cpp
View file @
cceb3171
...
...
@@ -1402,6 +1402,46 @@ 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
(
argIndex
<
3
)
return
delta
[
argIndex
]
/
r
;
return
-
delta
[
argIndex
-
3
]
/
r
;
}
Lepton
::
CustomFunction
*
ReferenceCalcCustomExternalForceKernel
::
PeriodicDistanceFunction
::
clone
()
const
{
return
new
PeriodicDistanceFunction
(
boxVectorHandle
);
}
ReferenceCalcCustomExternalForceKernel
::~
ReferenceCalcCustomExternalForceKernel
()
{
disposeRealArray
(
particleParamArray
,
numParticles
);
}
...
...
@@ -1423,7 +1463,10 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
// 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
();
forceExpressionX
=
expression
.
differentiate
(
"x"
).
createCompiledExpression
();
forceExpressionY
=
expression
.
differentiate
(
"y"
).
createCompiledExpression
();
...
...
@@ -1437,6 +1480,7 @@ void ReferenceCalcCustomExternalForceKernel::initialize(const System& system, co
double
ReferenceCalcCustomExternalForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
)
{
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
vector
<
RealVec
>&
forceData
=
extractForces
(
context
);
boxVectors
=
extractBoxVectors
(
context
);
RealOpenMM
energy
=
0
;
map
<
string
,
double
>
globalParameters
;
for
(
int
i
=
0
;
i
<
(
int
)
globalParameterNames
.
size
();
i
++
)
...
...
platforms/reference/tests/TestReferenceCustomExternalForce.cpp
View file @
cceb3171
...
...
@@ -101,9 +101,51 @@ void testForce() {
}
}
void
testPeriodic
()
{
Vec3
vx
(
5
,
0
,
0
);
Vec3
vy
(
0
,
6
,
0
);
Vec3
vz
(
1
,
2
,
7
);
double
x0
=
51
,
y0
=
-
17
,
z0
=
11.2
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
vx
,
vy
,
vz
);
system
.
addParticle
(
1.0
);
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"periodicdistance(x, y, z, x0, y0, z0)^2"
);
force
->
addPerParticleParameter
(
"x0"
);
force
->
addPerParticleParameter
(
"y0"
);
force
->
addPerParticleParameter
(
"z0"
);
vector
<
double
>
params
(
3
);
params
[
0
]
=
x0
;
params
[
1
]
=
y0
;
params
[
2
]
=
z0
;
force
->
addParticle
(
0
,
params
);
system
.
addForce
(
force
);
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
vector
<
Vec3
>
positions
(
1
);
positions
[
0
]
=
Vec3
(
0
,
2
,
0
);
context
.
setPositions
(
positions
);
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
State
state
=
context
.
getState
(
State
::
Positions
|
State
::
Forces
|
State
::
Energy
);
// Apply periodic boundary conditions to the difference between the two positions.
Vec3
delta
=
Vec3
(
x0
,
y0
,
z0
)
-
state
.
getPositions
()[
0
];
delta
-=
vz
*
floor
(
delta
[
2
]
/
vz
[
2
]
+
0.5
);
delta
-=
vy
*
floor
(
delta
[
1
]
/
vy
[
1
]
+
0.5
);
delta
-=
vx
*
floor
(
delta
[
0
]
/
vx
[
0
]
+
0.5
);
// Verify that the force and energy are correct.
ASSERT_EQUAL_VEC
(
delta
*
2
,
state
.
getForces
()[
0
],
1e-6
);
ASSERT_EQUAL_TOL
(
delta
.
dot
(
delta
),
state
.
getPotentialEnergy
(),
1e-6
);
integrator
.
step
(
1
);
}
}
int
main
()
{
try
{
testForce
();
testPeriodic
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
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