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
a11a0a56
Commit
a11a0a56
authored
Aug 13, 2013
by
peastman
Browse files
Implemented long range correction for interaction groups
parent
b2af59a8
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
236 additions
and
30 deletions
+236
-30
openmmapi/src/CustomNonbondedForceImpl.cpp
openmmapi/src/CustomNonbondedForceImpl.cpp
+61
-30
platforms/cuda/tests/TestCudaCustomNonbondedForce.cpp
platforms/cuda/tests/TestCudaCustomNonbondedForce.cpp
+58
-0
platforms/opencl/tests/TestOpenCLCustomNonbondedForce.cpp
platforms/opencl/tests/TestOpenCLCustomNonbondedForce.cpp
+58
-0
platforms/reference/tests/TestReferenceCustomNonbondedForce.cpp
...rms/reference/tests/TestReferenceCustomNonbondedForce.cpp
+59
-0
No files found.
openmmapi/src/CustomNonbondedForceImpl.cpp
View file @
a11a0a56
...
@@ -42,14 +42,10 @@
...
@@ -42,14 +42,10 @@
#include "lepton/Parser.h"
#include "lepton/Parser.h"
#include <cmath>
#include <cmath>
#include <sstream>
#include <sstream>
#include <utility>
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
std
::
map
;
using
namespace
std
;
using
std
::
pair
;
using
std
::
vector
;
using
std
::
set
;
using
std
::
string
;
using
std
::
stringstream
;
CustomNonbondedForceImpl
::
CustomNonbondedForceImpl
(
const
CustomNonbondedForce
&
owner
)
:
owner
(
owner
)
{
CustomNonbondedForceImpl
::
CustomNonbondedForceImpl
(
const
CustomNonbondedForce
&
owner
)
:
owner
(
owner
)
{
}
}
...
@@ -176,20 +172,6 @@ double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedFo
...
@@ -176,20 +172,6 @@ double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedFo
if
(
force
.
getNonbondedMethod
()
==
CustomNonbondedForce
::
NoCutoff
||
force
.
getNonbondedMethod
()
==
CustomNonbondedForce
::
CutoffNonPeriodic
)
if
(
force
.
getNonbondedMethod
()
==
CustomNonbondedForce
::
NoCutoff
||
force
.
getNonbondedMethod
()
==
CustomNonbondedForce
::
CutoffNonPeriodic
)
return
0.0
;
return
0.0
;
// Identify all particle classes (defined by parameters), and count the number of
// particles in each class.
map
<
vector
<
double
>
,
int
>
classCounts
;
for
(
int
i
=
0
;
i
<
force
.
getNumParticles
();
i
++
)
{
vector
<
double
>
parameters
;
force
.
getParticleParameters
(
i
,
parameters
);
map
<
vector
<
double
>
,
int
>::
iterator
entry
=
classCounts
.
find
(
parameters
);
if
(
entry
==
classCounts
.
end
())
classCounts
[
parameters
]
=
1
;
else
entry
->
second
++
;
}
// Parse the energy expression.
// Parse the energy expression.
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
map
<
string
,
Lepton
::
CustomFunction
*>
functions
;
...
@@ -201,20 +183,69 @@ double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedFo
...
@@ -201,20 +183,69 @@ double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedFo
functions
[
name
]
=
new
TabulatedFunction
(
min
,
max
,
values
);
functions
[
name
]
=
new
TabulatedFunction
(
min
,
max
,
values
);
}
}
Lepton
::
ExpressionProgram
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
).
optimize
().
createProgram
();
Lepton
::
ExpressionProgram
expression
=
Lepton
::
Parser
::
parse
(
force
.
getEnergyFunction
(),
functions
).
optimize
().
createProgram
();
// Identify all particle classes (defined by parameters), and record the class of each particle.
int
numParticles
=
force
.
getNumParticles
();
vector
<
vector
<
double
>
>
classes
;
map
<
vector
<
double
>
,
int
>
classIndex
;
vector
<
int
>
atomClass
(
numParticles
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
vector
<
double
>
parameters
;
force
.
getParticleParameters
(
i
,
parameters
);
if
(
classIndex
.
find
(
parameters
)
==
classIndex
.
end
())
{
classIndex
[
parameters
]
=
classes
.
size
();
classes
.
push_back
(
parameters
);
}
atomClass
[
i
]
=
classIndex
[
parameters
];
}
int
numClasses
=
classes
.
size
();
// Count the total number of particle pairs for each pair of classes.
map
<
pair
<
int
,
int
>
,
int
>
interactionCount
;
if
(
force
.
getNumInteractionGroups
()
==
0
)
{
// Count the particles of each class.
vector
<
int
>
classCounts
(
numClasses
,
0
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
classCounts
[
atomClass
[
i
]]
++
;
for
(
int
i
=
0
;
i
<
numClasses
;
i
++
)
{
interactionCount
[
make_pair
(
i
,
i
)]
=
(
classCounts
[
i
]
*
(
classCounts
[
i
]
+
1
))
/
2
;
for
(
int
j
=
i
+
1
;
j
<
numClasses
;
j
++
)
interactionCount
[
make_pair
(
i
,
j
)]
=
classCounts
[
i
]
*
classCounts
[
j
];
}
}
else
{
// Initialize the counts to 0.
for
(
int
i
=
0
;
i
<
numClasses
;
i
++
)
{
for
(
int
j
=
i
;
j
<
numClasses
;
j
++
)
interactionCount
[
make_pair
(
i
,
j
)]
=
0
;
}
// Loop over interaction groups and count the interactions in each one.
for
(
int
group
=
0
;
group
<
force
.
getNumInteractionGroups
();
group
++
)
{
set
<
int
>
set1
,
set2
;
force
.
getInteractionGroupParameters
(
group
,
set1
,
set2
);
for
(
set
<
int
>::
const_iterator
a1
=
set1
.
begin
();
a1
!=
set1
.
end
();
++
a1
)
for
(
set
<
int
>::
const_iterator
a2
=
set2
.
begin
();
a2
!=
set2
.
end
();
++
a2
)
{
if
(
*
a1
>=
*
a2
&&
set1
.
find
(
*
a2
)
!=
set1
.
end
()
&&
set2
.
find
(
*
a1
)
!=
set2
.
end
())
continue
;
int
class1
=
atomClass
[
*
a1
];
int
class2
=
atomClass
[
*
a2
];
interactionCount
[
make_pair
(
min
(
class1
,
class2
),
max
(
class1
,
class2
))]
++
;
}
}
}
// Loop over all pairs of classes to compute the coefficient.
// Loop over all pairs of classes to compute the coefficient.
double
sum
=
0
;
double
sum
=
0
;
for
(
map
<
vector
<
double
>
,
int
>::
const_iterator
entry
=
classCounts
.
begin
();
entry
!=
classCounts
.
end
();
++
entry
)
{
for
(
int
i
=
0
;
i
<
numClasses
;
i
++
)
int
count
=
(
entry
->
second
*
(
entry
->
second
+
1
))
/
2
;
for
(
int
j
=
i
;
j
<
numClasses
;
j
++
)
sum
+=
count
*
integrateInteraction
(
expression
,
entry
->
first
,
entry
->
first
,
force
,
context
);
sum
+=
interactionCount
[
make_pair
(
i
,
j
)]
*
integrateInteraction
(
expression
,
classes
[
i
],
classes
[
j
],
force
,
context
);
}
for
(
map
<
vector
<
double
>
,
int
>::
const_iterator
class1
=
classCounts
.
begin
();
class1
!=
classCounts
.
end
();
++
class1
)
for
(
map
<
vector
<
double
>
,
int
>::
const_iterator
class2
=
classCounts
.
begin
();
class2
!=
class1
;
++
class2
)
{
int
count
=
class1
->
second
*
class2
->
second
;
sum
+=
count
*
integrateInteraction
(
expression
,
class1
->
first
,
class2
->
first
,
force
,
context
);
}
int
numParticles
=
force
.
getNumParticles
();
int
numInteractions
=
(
numParticles
*
(
numParticles
+
1
))
/
2
;
int
numInteractions
=
(
numParticles
*
(
numParticles
+
1
))
/
2
;
sum
/=
numInteractions
;
sum
/=
numInteractions
;
return
2
*
M_PI
*
numParticles
*
numParticles
*
sum
;
return
2
*
M_PI
*
numParticles
*
numParticles
*
sum
;
...
...
platforms/cuda/tests/TestCudaCustomNonbondedForce.cpp
View file @
a11a0a56
...
@@ -654,6 +654,63 @@ void testLargeInteractionGroup() {
...
@@ -654,6 +654,63 @@ void testLargeInteractionGroup() {
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state3
.
getForces
()[
i
],
1e-4
);
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state3
.
getForces
()[
i
],
1e-4
);
}
}
void
testInteractionGroupLongRangeCorrection
()
{
const
int
numParticles
=
10
;
const
double
boxSize
=
10.0
;
const
double
cutoff
=
0.5
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
CustomNonbondedForce
*
nonbonded
=
new
CustomNonbondedForce
(
"c1*c2*r^-4"
);
nonbonded
->
addPerParticleParameter
(
"c"
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
double
>
params
(
1
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
params
[
0
]
=
(
i
%
2
==
0
?
1.1
:
2.0
);
nonbonded
->
addParticle
(
params
);
positions
[
i
]
=
Vec3
(
0.5
*
i
,
0
,
0
);
}
nonbonded
->
setNonbondedMethod
(
CustomNonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
// Setup nonbonded groups. They involve 1 interaction of type AA,
// 2 of type BB, and 5 of type AB.
set
<
int
>
set1
,
set2
,
set3
,
set4
,
set5
;
set1
.
insert
(
0
);
set1
.
insert
(
1
);
set1
.
insert
(
2
);
nonbonded
->
addInteractionGroup
(
set1
,
set1
);
set2
.
insert
(
3
);
set3
.
insert
(
4
);
set3
.
insert
(
6
);
set3
.
insert
(
8
);
nonbonded
->
addInteractionGroup
(
set2
,
set3
);
set4
.
insert
(
5
);
set5
.
insert
(
7
);
set5
.
insert
(
9
);
nonbonded
->
addInteractionGroup
(
set4
,
set5
);
// Compute energy with and without the correction.
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
double
energy1
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
nonbonded
->
setUseLongRangeCorrection
(
true
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
double
energy2
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
// Check the result.
double
sum
=
(
1.1
*
1.1
+
2
*
2.0
*
2.0
+
5
*
1.1
*
2.0
)
*
2.0
;
int
numPairs
=
(
numParticles
*
(
numParticles
+
1
))
/
2
;
double
expected
=
2
*
M_PI
*
numParticles
*
numParticles
*
sum
/
(
numPairs
*
boxSize
*
boxSize
*
boxSize
);
ASSERT_EQUAL_TOL
(
expected
,
energy2
-
energy1
,
1e-4
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
try
{
if
(
argc
>
1
)
if
(
argc
>
1
)
...
@@ -671,6 +728,7 @@ int main(int argc, char* argv[]) {
...
@@ -671,6 +728,7 @@ int main(int argc, char* argv[]) {
testLongRangeCorrection
();
testLongRangeCorrection
();
testInteractionGroups
();
testInteractionGroups
();
testLargeInteractionGroup
();
testLargeInteractionGroup
();
testInteractionGroupLongRangeCorrection
();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
platforms/opencl/tests/TestOpenCLCustomNonbondedForce.cpp
View file @
a11a0a56
...
@@ -654,6 +654,63 @@ void testLargeInteractionGroup() {
...
@@ -654,6 +654,63 @@ void testLargeInteractionGroup() {
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state3
.
getForces
()[
i
],
1e-4
);
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state3
.
getForces
()[
i
],
1e-4
);
}
}
void
testInteractionGroupLongRangeCorrection
()
{
const
int
numParticles
=
10
;
const
double
boxSize
=
10.0
;
const
double
cutoff
=
0.5
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
CustomNonbondedForce
*
nonbonded
=
new
CustomNonbondedForce
(
"c1*c2*r^-4"
);
nonbonded
->
addPerParticleParameter
(
"c"
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
double
>
params
(
1
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
params
[
0
]
=
(
i
%
2
==
0
?
1.1
:
2.0
);
nonbonded
->
addParticle
(
params
);
positions
[
i
]
=
Vec3
(
0.5
*
i
,
0
,
0
);
}
nonbonded
->
setNonbondedMethod
(
CustomNonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
// Setup nonbonded groups. They involve 1 interaction of type AA,
// 2 of type BB, and 5 of type AB.
set
<
int
>
set1
,
set2
,
set3
,
set4
,
set5
;
set1
.
insert
(
0
);
set1
.
insert
(
1
);
set1
.
insert
(
2
);
nonbonded
->
addInteractionGroup
(
set1
,
set1
);
set2
.
insert
(
3
);
set3
.
insert
(
4
);
set3
.
insert
(
6
);
set3
.
insert
(
8
);
nonbonded
->
addInteractionGroup
(
set2
,
set3
);
set4
.
insert
(
5
);
set5
.
insert
(
7
);
set5
.
insert
(
9
);
nonbonded
->
addInteractionGroup
(
set4
,
set5
);
// Compute energy with and without the correction.
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
double
energy1
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
nonbonded
->
setUseLongRangeCorrection
(
true
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
double
energy2
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
// Check the result.
double
sum
=
(
1.1
*
1.1
+
2
*
2.0
*
2.0
+
5
*
1.1
*
2.0
)
*
2.0
;
int
numPairs
=
(
numParticles
*
(
numParticles
+
1
))
/
2
;
double
expected
=
2
*
M_PI
*
numParticles
*
numParticles
*
sum
/
(
numPairs
*
boxSize
*
boxSize
*
boxSize
);
ASSERT_EQUAL_TOL
(
expected
,
energy2
-
energy1
,
1e-4
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
try
{
try
{
if
(
argc
>
1
)
if
(
argc
>
1
)
...
@@ -671,6 +728,7 @@ int main(int argc, char* argv[]) {
...
@@ -671,6 +728,7 @@ int main(int argc, char* argv[]) {
testLongRangeCorrection
();
testLongRangeCorrection
();
testInteractionGroups
();
testInteractionGroups
();
testLargeInteractionGroup
();
testLargeInteractionGroup
();
testInteractionGroupLongRangeCorrection
();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
platforms/reference/tests/TestReferenceCustomNonbondedForce.cpp
View file @
a11a0a56
...
@@ -589,6 +589,64 @@ void testLargeInteractionGroup() {
...
@@ -589,6 +589,64 @@ void testLargeInteractionGroup() {
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state3
.
getForces
()[
i
],
1e-4
);
ASSERT_EQUAL_VEC
(
state1
.
getForces
()[
i
],
state3
.
getForces
()[
i
],
1e-4
);
}
}
void
testInteractionGroupLongRangeCorrection
()
{
const
int
numParticles
=
10
;
const
double
boxSize
=
10.0
;
const
double
cutoff
=
0.5
;
ReferencePlatform
platform
;
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
boxSize
,
0
,
0
),
Vec3
(
0
,
boxSize
,
0
),
Vec3
(
0
,
0
,
boxSize
));
CustomNonbondedForce
*
nonbonded
=
new
CustomNonbondedForce
(
"c1*c2*r^-4"
);
nonbonded
->
addPerParticleParameter
(
"c"
);
vector
<
Vec3
>
positions
(
numParticles
);
vector
<
double
>
params
(
1
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
params
[
0
]
=
(
i
%
2
==
0
?
1.1
:
2.0
);
nonbonded
->
addParticle
(
params
);
positions
[
i
]
=
Vec3
(
0.5
*
i
,
0
,
0
);
}
nonbonded
->
setNonbondedMethod
(
CustomNonbondedForce
::
CutoffPeriodic
);
nonbonded
->
setCutoffDistance
(
cutoff
);
system
.
addForce
(
nonbonded
);
// Setup nonbonded groups. They involve 1 interaction of type AA,
// 2 of type BB, and 5 of type AB.
set
<
int
>
set1
,
set2
,
set3
,
set4
,
set5
;
set1
.
insert
(
0
);
set1
.
insert
(
1
);
set1
.
insert
(
2
);
nonbonded
->
addInteractionGroup
(
set1
,
set1
);
set2
.
insert
(
3
);
set3
.
insert
(
4
);
set3
.
insert
(
6
);
set3
.
insert
(
8
);
nonbonded
->
addInteractionGroup
(
set2
,
set3
);
set4
.
insert
(
5
);
set5
.
insert
(
7
);
set5
.
insert
(
9
);
nonbonded
->
addInteractionGroup
(
set4
,
set5
);
// Compute energy with and without the correction.
VerletIntegrator
integrator
(
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
double
energy1
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
nonbonded
->
setUseLongRangeCorrection
(
true
);
context
.
reinitialize
();
context
.
setPositions
(
positions
);
double
energy2
=
context
.
getState
(
State
::
Energy
).
getPotentialEnergy
();
// Check the result.
double
sum
=
(
1.1
*
1.1
+
2
*
2.0
*
2.0
+
5
*
1.1
*
2.0
)
*
2.0
;
int
numPairs
=
(
numParticles
*
(
numParticles
+
1
))
/
2
;
double
expected
=
2
*
M_PI
*
numParticles
*
numParticles
*
sum
/
(
numPairs
*
boxSize
*
boxSize
*
boxSize
);
ASSERT_EQUAL_TOL
(
expected
,
energy2
-
energy1
,
1e-4
);
}
int
main
()
{
int
main
()
{
try
{
try
{
testSimpleExpression
();
testSimpleExpression
();
...
@@ -602,6 +660,7 @@ int main() {
...
@@ -602,6 +660,7 @@ int main() {
testLongRangeCorrection
();
testLongRangeCorrection
();
testInteractionGroups
();
testInteractionGroups
();
testLargeInteractionGroup
();
testLargeInteractionGroup
();
testInteractionGroupLongRangeCorrection
();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
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