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
b5eda392
"...serialization/tests/TestSerializeAmoebaPiTorsionForce.cpp" did not exist on "18c9a78a8a9950be32af8021986d619afab3e017"
Commit
b5eda392
authored
Oct 23, 2009
by
Peter Eastman
Browse files
Implemented new method for selecting Ewald and PME parameters
parent
7e9cf94b
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
199 additions
and
52 deletions
+199
-52
openmmapi/include/openmm/internal/NonbondedForceImpl.h
openmmapi/include/openmm/internal/NonbondedForceImpl.h
+15
-0
openmmapi/src/NonbondedForceImpl.cpp
openmmapi/src/NonbondedForceImpl.cpp
+58
-4
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+7
-18
platforms/cuda/tests/TestCudaEwald.cpp
platforms/cuda/tests/TestCudaEwald.cpp
+54
-4
platforms/reference/src/ReferenceKernels.cpp
platforms/reference/src/ReferenceKernels.cpp
+10
-23
platforms/reference/tests/TestReferenceEwald.cpp
platforms/reference/tests/TestReferenceEwald.cpp
+55
-3
No files found.
openmmapi/include/openmm/internal/NonbondedForceImpl.h
View file @
b5eda392
...
...
@@ -41,6 +41,8 @@
namespace
OpenMM
{
class
System
;
/**
* This is the internal implementation of NonbondedForce.
*/
...
...
@@ -62,7 +64,20 @@ public:
return
std
::
map
<
std
::
string
,
double
>
();
// This force field doesn't define any parameters.
}
std
::
vector
<
std
::
string
>
getKernelNames
();
/**
* This is a utility routine that calculates the values to use for alpha and kmax when using
* Ewald summation.
*/
static
void
calcEwaldParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
kmaxx
,
int
&
kmaxy
,
int
&
kmaxz
);
/**
* This is a utility routine that calculates the values to use for alpha and grid size when using
* Particle Mesh Ewald.
*/
static
void
calcPMEParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
xsize
,
int
&
ysize
,
int
&
zsize
);
private:
class
ErrorFunction
;
class
EwaldErrorFunction
;
static
double
findZero
(
const
ErrorFunction
&
f
,
int
initialGuess
);
NonbondedForce
&
owner
;
Kernel
kernel
;
};
...
...
openmmapi/src/NonbondedForceImpl.cpp
View file @
b5eda392
...
...
@@ -33,13 +33,11 @@
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "openmm/kernels.h"
#include <cmath>
#include <sstream>
using
namespace
OpenMM
;
using
std
::
pair
;
using
std
::
vector
;
using
std
::
set
;
using
std
::
stringstream
;
using
namespace
std
;
NonbondedForceImpl
::
NonbondedForceImpl
(
NonbondedForce
&
owner
)
:
owner
(
owner
)
{
}
...
...
@@ -99,3 +97,59 @@ std::vector<std::string> NonbondedForceImpl::getKernelNames() {
names
.
push_back
(
CalcNonbondedForceKernel
::
Name
());
return
names
;
}
class
NonbondedForceImpl
::
ErrorFunction
{
public:
virtual
double
getValue
(
int
arg
)
const
=
0
;
};
class
NonbondedForceImpl
::
EwaldErrorFunction
:
public
ErrorFunction
{
public:
EwaldErrorFunction
(
double
width
,
double
alpha
,
double
target
)
:
width
(
width
),
alpha
(
alpha
),
target
(
target
)
{
}
double
getValue
(
int
arg
)
const
{
double
temp
=
arg
*
M_PI
/
(
width
*
alpha
);
return
target
-
0.05
*
sqrt
(
width
*
alpha
)
*
arg
*
exp
(
-
temp
*
temp
);
}
private:
double
width
,
alpha
,
target
;
};
void
NonbondedForceImpl
::
calcEwaldParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
kmaxx
,
int
&
kmaxy
,
int
&
kmaxz
)
{
Vec3
boxVectors
[
3
];
system
.
getPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
double
tol
=
force
.
getEwaldErrorTolerance
();
alpha
=
(
1.0
/
force
.
getCutoffDistance
())
*
std
::
sqrt
(
-
log
(
0.5
*
tol
));
kmaxx
=
findZero
(
EwaldErrorFunction
(
boxVectors
[
0
][
0
],
alpha
,
tol
),
10
);
kmaxy
=
findZero
(
EwaldErrorFunction
(
boxVectors
[
1
][
1
],
alpha
,
tol
),
10
);
kmaxz
=
findZero
(
EwaldErrorFunction
(
boxVectors
[
2
][
2
],
alpha
,
tol
),
10
);
if
(
kmaxx
%
2
==
0
)
kmaxx
++
;
if
(
kmaxy
%
2
==
0
)
kmaxy
++
;
if
(
kmaxz
%
2
==
0
)
kmaxz
++
;
}
void
NonbondedForceImpl
::
calcPMEParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
xsize
,
int
&
ysize
,
int
&
zsize
)
{
Vec3
boxVectors
[
3
];
system
.
getPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
double
tol
=
force
.
getEwaldErrorTolerance
();
alpha
=
(
1.0
/
force
.
getCutoffDistance
())
*
std
::
sqrt
(
-
log
(
2.0
*
tol
));
xsize
=
(
int
)
ceil
(
alpha
*
boxVectors
[
0
][
0
]
/
pow
(
0.5
*
tol
,
0.2
));
ysize
=
(
int
)
ceil
(
alpha
*
boxVectors
[
1
][
1
]
/
pow
(
0.5
*
tol
,
0.2
));
zsize
=
(
int
)
ceil
(
alpha
*
boxVectors
[
2
][
2
]
/
pow
(
0.5
*
tol
,
0.2
));
}
double
NonbondedForceImpl
::
findZero
(
const
NonbondedForceImpl
::
ErrorFunction
&
f
,
int
initialGuess
)
{
int
arg
=
initialGuess
;
double
value
=
f
.
getValue
(
arg
);
if
(
value
>
0.0
)
{
while
(
value
>
0.0
&&
arg
>
0
)
value
=
f
.
getValue
(
--
arg
);
return
arg
+
1
;
}
while
(
value
<
0.0
)
value
=
f
.
getValue
(
++
arg
);
return
arg
;
}
platforms/cuda/src/CudaKernels.cpp
View file @
b5eda392
...
...
@@ -28,6 +28,7 @@
#include "openmm/LangevinIntegrator.h"
#include "openmm/Context.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "kernels/gputypes.h"
#include "kernels/cudaKernels.h"
#include <cmath>
...
...
@@ -343,29 +344,17 @@ void CudaCalcNonbondedForceKernel::initialize(const System& system, const Nonbon
method
=
PERIODIC
;
}
if
(
force
.
getNonbondedMethod
()
==
NonbondedForce
::
Ewald
||
force
.
getNonbondedMethod
()
==
NonbondedForce
::
PME
)
{
double
ewaldErrorTol
=
force
.
getEwaldErrorTolerance
();
double
alpha
=
(
1.0
/
force
.
getCutoffDistance
())
*
std
::
sqrt
(
-
std
::
log
(
ewaldErrorTol
));
double
mx
=
boxVectors
[
0
][
0
]
/
force
.
getCutoffDistance
();
double
my
=
boxVectors
[
1
][
1
]
/
force
.
getCutoffDistance
();
double
mz
=
boxVectors
[
2
][
2
]
/
force
.
getCutoffDistance
();
double
pi
=
3.1415926535897932385
;
int
kmaxx
=
(
int
)
std
::
ceil
(
-
(
mx
/
pi
)
*
std
::
log
(
ewaldErrorTol
));
int
kmaxy
=
(
int
)
std
::
ceil
(
-
(
my
/
pi
)
*
std
::
log
(
ewaldErrorTol
));
int
kmaxz
=
(
int
)
std
::
ceil
(
-
(
mz
/
pi
)
*
std
::
log
(
ewaldErrorTol
));
if
(
force
.
getNonbondedMethod
()
==
NonbondedForce
::
Ewald
)
{
if
(
kmaxx
%
2
==
0
)
kmaxx
++
;
if
(
kmaxy
%
2
==
0
)
kmaxy
++
;
if
(
kmaxz
%
2
==
0
)
kmaxz
++
;
double
alpha
;
int
kmaxx
,
kmaxy
,
kmaxz
;
NonbondedForceImpl
::
calcEwaldParameters
(
system
,
force
,
alpha
,
kmaxx
,
kmaxy
,
kmaxz
);
gpuSetEwaldParameters
(
gpu
,
(
float
)
alpha
,
kmaxx
,
kmaxy
,
kmaxz
);
method
=
EWALD
;
}
else
{
int
gridSizeX
=
-
0.5
*
kmaxx
*
std
::
log
(
ewaldErrorTol
)
;
int
gridSize
Y
=
-
0.5
*
kmaxy
*
std
::
log
(
ewaldErrorTol
)
;
int
gridSizeZ
=
-
0.5
*
kmaxz
*
std
::
log
(
ewaldErrorTol
);
double
alpha
;
int
gridSize
X
,
gridSizeY
,
gridSizeZ
;
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
gridSizeX
,
gridSizeY
,
gridSizeZ
);
gpuSetPMEParameters
(
gpu
,
(
float
)
alpha
,
gridSizeX
,
gridSizeY
,
gridSizeZ
);
method
=
PARTICLE_MESH_EWALD
;
}
...
...
platforms/cuda/tests/TestCudaEwald.cpp
View file @
b5eda392
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors.
*
* Portions copyright (c) 2008
-2009
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -119,7 +119,7 @@ void testEwaldPME() {
Context
cudaContext2
(
system
,
integrator
,
cuda
);
cudaContext2
.
setPositions
(
positions
);
tol
=
1e-
4
;
tol
=
1e-
3
;
State
cudaState2
=
cudaContext2
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
cudaState2
.
getPotentialEnergy
()
-
cudaState
.
getPotentialEnergy
())
/
delta
,
tol
)
...
...
@@ -157,10 +157,9 @@ void testEwaldPME() {
Context
cudaContext3
(
system
,
integrator
,
cuda
);
cudaContext3
.
setPositions
(
positions
);
tol
=
1e-
4
;
tol
=
1e-
3
;
State
cudaState3
=
cudaContext3
.
getState
(
State
::
Energy
);
ASSERT_EQUAL_TOL
(
norm
,
(
cudaState3
.
getPotentialEnergy
()
-
cudaState
.
getPotentialEnergy
())
/
delta
,
tol
)
}
void
testEwald2Ions
()
{
...
...
@@ -191,11 +190,62 @@ void testEwald2Ions() {
ASSERT_EQUAL_TOL
(
-
217.276
,
state
.
getPotentialEnergy
(),
0.01
/*10*TOL*/
);
}
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
// Create a cloud of random point charges.
const
int
numParticles
=
51
;
const
double
boxWidth
=
5.0
;
System
system
;
system
.
setPeriodicBoxVectors
(
Vec3
(
boxWidth
,
0
,
0
),
Vec3
(
0
,
boxWidth
,
0
),
Vec3
(
0
,
0
,
boxWidth
));
NonbondedForce
*
force
=
new
NonbondedForce
();
system
.
addForce
(
force
);
vector
<
Vec3
>
positions
(
numParticles
);
init_gen_rand
(
0
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
force
->
addParticle
(
-
1.0
+
i
*
2.0
/
(
numParticles
-
1
),
1.0
,
0.0
);
positions
[
i
]
=
Vec3
(
boxWidth
*
genrand_real2
(),
boxWidth
*
genrand_real2
(),
boxWidth
*
genrand_real2
());
}
force
->
setNonbondedMethod
(
method
);
CudaPlatform
platform
;
VerletIntegrator
integrator
(
0.01
);
// For various values of the cutoff and error tolerance, see if the actual error is reasonable.
for
(
double
cutoff
=
1.0
;
cutoff
<
boxWidth
/
2
;
cutoff
+=
0.2
)
{
force
->
setCutoffDistance
(
cutoff
);
vector
<
Vec3
>
refForces
;
double
norm
=
0.0
;
for
(
double
tol
=
5e-5
;
tol
<
1e-3
;
tol
*=
2.0
)
{
force
->
setEwaldErrorTolerance
(
tol
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
);
if
(
refForces
.
size
()
==
0
)
{
refForces
=
state
.
getForces
();
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
norm
+=
refForces
[
i
].
dot
(
refForces
[
i
]);
norm
=
sqrt
(
norm
);
}
else
{
double
diff
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
Vec3
delta
=
refForces
[
i
]
-
state
.
getForces
()[
i
];
diff
+=
delta
.
dot
(
delta
);
}
diff
=
sqrt
(
diff
)
/
norm
;
ASSERT
(
diff
<
5
*
tol
);
}
}
}
}
int
main
()
{
try
{
testEwaldPME
();
// testEwald2Ions();
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
PME
);
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
platforms/reference/src/ReferenceKernels.cpp
View file @
b5eda392
...
...
@@ -50,6 +50,7 @@
#include "openmm/CMMotionRemover.h"
#include "openmm/System.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/NonbondedForceImpl.h"
#include "openmm/Integrator.h"
#include "SimTKUtilities/SimTKOpenMMUtilities.h"
#include "lepton/CustomFunction.h"
...
...
@@ -470,29 +471,15 @@ void ReferenceCalcNonbondedForceKernel::initialize(const System& system, const N
neighborList
=
NULL
;
else
neighborList
=
new
NeighborList
();
if
(
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
)
{
RealOpenMM
ewaldErrorTol
=
(
RealOpenMM
)
force
.
getEwaldErrorTolerance
();
ewaldAlpha
=
(
RealOpenMM
)
(
std
::
sqrt
(
-
std
::
log
(
ewaldErrorTol
))
/
nonbondedCutoff
);
RealOpenMM
mx
=
periodicBoxSize
[
0
]
/
nonbondedCutoff
;
RealOpenMM
my
=
periodicBoxSize
[
1
]
/
nonbondedCutoff
;
RealOpenMM
mz
=
periodicBoxSize
[
2
]
/
nonbondedCutoff
;
RealOpenMM
pi
=
(
RealOpenMM
)
3.1415926535897932385
;
kmax
[
0
]
=
(
int
)
std
::
ceil
(
-
(
mx
/
pi
)
*
std
::
log
(
ewaldErrorTol
));
kmax
[
1
]
=
(
int
)
std
::
ceil
(
-
(
my
/
pi
)
*
std
::
log
(
ewaldErrorTol
));
kmax
[
2
]
=
(
int
)
std
::
ceil
(
-
(
mz
/
pi
)
*
std
::
log
(
ewaldErrorTol
));
if
(
nonbondedMethod
==
Ewald
)
{
if
(
kmax
[
0
]
%
2
==
0
)
kmax
[
0
]
++
;
if
(
kmax
[
1
]
%
2
==
0
)
kmax
[
1
]
++
;
if
(
kmax
[
2
]
%
2
==
0
)
kmax
[
2
]
++
;
}
else
{
gridSize
[
0
]
=
-
0.5
*
kmax
[
0
]
*
std
::
log
(
ewaldErrorTol
);
gridSize
[
1
]
=
-
0.5
*
kmax
[
1
]
*
std
::
log
(
ewaldErrorTol
);
gridSize
[
2
]
=
-
0.5
*
kmax
[
2
]
*
std
::
log
(
ewaldErrorTol
);
double
alpha
;
NonbondedForceImpl
::
calcEwaldParameters
(
system
,
force
,
alpha
,
kmax
[
0
],
kmax
[
1
],
kmax
[
2
]);
ewaldAlpha
=
alpha
;
}
else
if
(
nonbondedMethod
==
PME
)
{
double
alpha
;
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
]);
ewaldAlpha
=
alpha
;
}
rfDielectric
=
(
RealOpenMM
)
force
.
getReactionFieldDielectric
();
}
...
...
platforms/reference/tests/TestReferenceEwald.cpp
View file @
b5eda392
...
...
@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors.
*
* Portions copyright (c) 2008
-2009
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
...
...
@@ -40,6 +40,7 @@
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h"
#include "openmm/HarmonicBondForce.h"
#include <iostream>
#include <vector>
...
...
@@ -138,7 +139,7 @@ void testEwaldPME() {
// (1) CHECK EXACT VALUE OF EWALD ENERGY (Against Gromacs output)
tol
=
1e-
5
;
tol
=
1e-
4
;
ASSERT_EQUAL_TOL
(
-
3.82047e+05
,
state1
.
getPotentialEnergy
(),
tol
);
// (2) CHECK WHETHER THE EWALD FORCES ARE THE SAME AS THE GROMACS OUTPUT
...
...
@@ -303,6 +304,55 @@ void testWaterSystem() {
}
void
testErrorTolerance
(
NonbondedForce
::
NonbondedMethod
method
)
{
// Create a cloud of random point charges.
const
int
numParticles
=
51
;
const
double
boxWidth
=
5.0
;
System
system
;
system
.
setPeriodicBoxVectors
(
Vec3
(
boxWidth
,
0
,
0
),
Vec3
(
0
,
boxWidth
,
0
),
Vec3
(
0
,
0
,
boxWidth
));
NonbondedForce
*
force
=
new
NonbondedForce
();
system
.
addForce
(
force
);
vector
<
Vec3
>
positions
(
numParticles
);
init_gen_rand
(
0
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
system
.
addParticle
(
1.0
);
force
->
addParticle
(
-
1.0
+
i
*
2.0
/
(
numParticles
-
1
),
1.0
,
0.0
);
positions
[
i
]
=
Vec3
(
boxWidth
*
genrand_real2
(),
boxWidth
*
genrand_real2
(),
boxWidth
*
genrand_real2
());
}
force
->
setNonbondedMethod
(
method
);
ReferencePlatform
platform
;
VerletIntegrator
integrator
(
0.01
);
// For various values of the cutoff and error tolerance, see if the actual error is reasonable.
for
(
double
cutoff
=
1.0
;
cutoff
<
boxWidth
/
2
;
cutoff
+=
0.2
)
{
force
->
setCutoffDistance
(
cutoff
);
vector
<
Vec3
>
refForces
;
double
norm
=
0.0
;
for
(
double
tol
=
5e-5
;
tol
<
1e-3
;
tol
*=
2.0
)
{
force
->
setEwaldErrorTolerance
(
tol
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
State
state
=
context
.
getState
(
State
::
Forces
);
if
(
refForces
.
size
()
==
0
)
{
refForces
=
state
.
getForces
();
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
norm
+=
refForces
[
i
].
dot
(
refForces
[
i
]);
norm
=
sqrt
(
norm
);
}
else
{
double
diff
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
Vec3
delta
=
refForces
[
i
]
-
state
.
getForces
()[
i
];
diff
+=
delta
.
dot
(
delta
);
}
diff
=
sqrt
(
diff
)
/
norm
;
ASSERT
(
diff
<
5
*
tol
);
}
}
}
}
int
main
()
{
try
{
...
...
@@ -310,6 +360,8 @@ int main() {
testEwaldPME
();
// testEwald2Ions();
// testWaterSystem();
testErrorTolerance
(
NonbondedForce
::
Ewald
);
testErrorTolerance
(
NonbondedForce
::
PME
);
}
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