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
53f770f4
Commit
53f770f4
authored
Feb 21, 2017
by
peastman
Committed by
GitHub
Feb 21, 2017
Browse files
Merge pull request #1557 from andysim/dpme
Dispersion PME
parents
f36f36bf
c0850062
Changes
62
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
957 additions
and
198 deletions
+957
-198
docs-source/usersguide/application.rst
docs-source/usersguide/application.rst
+4
-3
docs-source/usersguide/references.bib
docs-source/usersguide/references.bib
+12
-0
docs-source/usersguide/theory.rst
docs-source/usersguide/theory.rst
+33
-1
olla/include/openmm/kernels.h
olla/include/openmm/kernels.h
+63
-2
openmmapi/include/openmm/NonbondedForce.h
openmmapi/include/openmm/NonbondedForce.h
+45
-6
openmmapi/include/openmm/internal/NonbondedForceImpl.h
openmmapi/include/openmm/internal/NonbondedForceImpl.h
+2
-1
openmmapi/src/NonbondedForce.cpp
openmmapi/src/NonbondedForce.cpp
+20
-1
openmmapi/src/NonbondedForceImpl.cpp
openmmapi/src/NonbondedForceImpl.cpp
+23
-11
platforms/cpu/include/CpuKernels.h
platforms/cpu/include/CpuKernels.h
+15
-5
platforms/cpu/include/CpuNonbondedForce.h
platforms/cpu/include/CpuNonbondedForce.h
+49
-14
platforms/cpu/include/CpuNonbondedForceVec4.h
platforms/cpu/include/CpuNonbondedForceVec4.h
+15
-1
platforms/cpu/include/CpuNonbondedForceVec8.h
platforms/cpu/include/CpuNonbondedForceVec8.h
+15
-0
platforms/cpu/src/CpuKernels.cpp
platforms/cpu/src/CpuKernels.cpp
+60
-9
platforms/cpu/src/CpuNonbondedForce.cpp
platforms/cpu/src/CpuNonbondedForce.cpp
+162
-50
platforms/cpu/src/CpuNonbondedForceVec4.cpp
platforms/cpu/src/CpuNonbondedForceVec4.cpp
+44
-5
platforms/cpu/src/CpuNonbondedForceVec8.cpp
platforms/cpu/src/CpuNonbondedForceVec8.cpp
+57
-3
platforms/cpu/tests/TestCpuDispersionPME.cpp
platforms/cpu/tests/TestCpuDispersionPME.cpp
+37
-0
platforms/cuda/include/CudaKernels.h
platforms/cuda/include/CudaKernels.h
+26
-4
platforms/cuda/include/CudaParallelKernels.h
platforms/cuda/include/CudaParallelKernels.h
+9
-0
platforms/cuda/src/CudaKernels.cpp
platforms/cuda/src/CudaKernels.cpp
+266
-82
No files found.
docs-source/usersguide/application.rst
View file @
53f770f4
...
...
@@ -916,8 +916,9 @@ Value Meaning
:
code
:`
NoCutoff
`
No
cutoff
is
applied
.
:
code
:`
CutoffNonPeriodic
`
The
reaction
field
method
is
used
to
eliminate
all
interactions
beyond
a
cutoff
distance
.
Not
valid
for
AMOEBA
.
:
code
:`
CutoffPeriodic
`
The
reaction
field
method
is
used
to
eliminate
all
interactions
beyond
a
cutoff
distance
.
Periodic
boundary
conditions
are
applied
,
so
each
atom
interacts
only
with
the
nearest
periodic
copy
of
every
other
atom
.
Not
valid
for
AMOEBA
.
:
code
:`
Ewald
`
Periodic
boundary
conditions
are
applied
.
Ewald
summation
is
used
to
compute
long
range
interactions
.
(
This
option
is
rarely
used
,
since
PME
is
much
faster
for
all
but
the
smallest
systems
.)
Not
valid
for
AMOEBA
.
:
code
:`
PME
`
Periodic
boundary
conditions
are
applied
.
The
Particle
Mesh
Ewald
method
is
used
to
compute
long
range
interactions
.
:
code
:`
Ewald
`
Periodic
boundary
conditions
are
applied
.
Ewald
summation
is
used
to
compute
long
range
Coulomb
interactions
.
(
This
option
is
rarely
used
,
since
PME
is
much
faster
for
all
but
the
smallest
systems
.)
Not
valid
for
AMOEBA
.
:
code
:`
PME
`
Periodic
boundary
conditions
are
applied
.
The
Particle
Mesh
Ewald
method
is
used
to
compute
long
range
Coulomb
interactions
.
:
code
:`
LJPME
`
Periodic
boundary
conditions
are
applied
.
The
Particle
Mesh
Ewald
method
is
used
to
compute
long
range
interactions
for
both
Coulomb
and
Lennard
-
Jones
.
=========================
===========================================================================================================================================================================================================================================
...
...
@@ -926,7 +927,7 @@ cutoff distance. Be sure to specify units, as shown in the examples above. For
example
,
:
code
:`
nonbondedCutoff
=
1.5
*
nanometers
`
or
:
code
:`
nonbondedCutoff
=
12
*
angstroms
`
are
legal
values
.
When
using
:
code
:`
Ewald
`
or
:
code
:`
PME
`\
,
you
can
optionally
specify
an
When
using
:
code
:`
Ewald
`
,
:
code
:`
PME
`,
or
:
code
:`
LJ
PME
`\
,
you
can
optionally
specify
an
error
tolerance
for
the
force
computation
.
For
example
:
::
...
...
docs-source/usersguide/references.bib
View file @
53f770f4
...
...
@@ -517,3 +517,15 @@
year = {2014},
type = {Journal Article}
}
@article
{
Wennberg2015
author
=
{Wennberg,
Christian
L.
and
Murtola,
Teemu
and
Páll,
Szilárd
and
Abraham,
Mark
J.
and
Hess,
Berk
and
Lindahl,
Erik
}
,
title = {Direct-Space Corrections Enable Fast and Accurate {Lorentz–Berthelot} Combination Rule {Lennard-Jones} Lattice Summation},
journal = {Journal of Chemical Theory and Computation},
volume = {11},
number = {12},
pages = {5737-5746},
year = {2015},
type = {Journal Article}
}
docs-source/usersguide/theory.rst
View file @
53f770f4
...
...
@@ -412,7 +412,7 @@ and the number of nodes in the mesh along each dimension as
.. math::
n_\mathit{mesh}=\frac{2\alpha d}{{3
d
}^{1/5}}
n_\mathit{mesh}=\frac{2\alpha d}{{3
\delta
}^{1/5}}
where *d* is the width of the periodic box along that dimension. Alternatively,
...
...
@@ -432,6 +432,38 @@ to numerical round-off error than Ewald summation. For Platforms that do
calculations in single precision, making :math:`\delta` too small (typically below about
5·10\ :sup:`-5`\ ) can actually cause the error to increase.
Lennard-Jones Interaction With Particle Mesh Ewald
==================================================
The PME algorithm can also be used for Lennard-Jones interactions. Usually this
is not necessary, since Lennard-Jones forces are short ranged, but there are
situations (such as membrane simulations) where neglecting interactions beyond
the cutoff can measurably affect results.
For computational efficiency, certain approximations are made\ :cite:`Wennberg2015`.
Interactions beyond the cutoff distance include only the attractive :math:`1/r^6`
term, not the repulsive :math:`1/r^{12}` term. Since the latter is much smaller
than the former at long distances, this usually has negligible effect. Also,
the interaction between particles farther apart than the cutoff distance is
computed using geometric combination rules:
.. math::
\sigma=\sqrt{\sigma_1 \sigma_2}
The effect of this approximation is also quite small, and it is still far more
accurate than ignoring the interactions altogether (which is what would happen
with PME).
The formula used to compute the number of nodes along each dimension of the mesh
is slightly different from the one used for Coulomb interactions:
.. math::
n_\mathit{mesh}=\frac{\alpha d}{{3\delta}^{1/5}}
As before, this is an empirical formula. It will usually produce an average
relative error in the forces less than or similar to :math:`\delta`\ , but that
is not guaranteed.
.. _gbsaobcforce:
GBSAOBCForce
...
...
olla/include/openmm/kernels.h
View file @
53f770f4
...
...
@@ -555,7 +555,8 @@ public:
CutoffNonPeriodic
=
1
,
CutoffPeriodic
=
2
,
Ewald
=
3
,
PME
=
4
PME
=
4
,
LJPME
=
5
};
static
std
::
string
Name
()
{
return
"CalcNonbondedForce"
;
...
...
@@ -589,13 +590,22 @@ public:
virtual
void
copyParametersToContext
(
ContextImpl
&
context
,
const
NonbondedForce
&
force
)
=
0
;
/**
* Get the parameters being used for PME.
*
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
virtual
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
=
0
;
/**
* Get the parameters being used for the dispersion terms in LJPME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
virtual
void
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
=
0
;
};
/**
...
...
@@ -1335,6 +1345,57 @@ public:
};
/**
* This kernel performs the dispersion reciprocal space calculation for LJPME. In most cases, this
* calculation is done directly by CalcNonbondedForceKernel so this kernel is unneeded.
* In some cases it may want to outsource the work to a different kernel. In particular,
* GPU based platforms sometimes use a CPU based implementation provided by a separate
* plugin.
*/
class
CalcDispersionPmeReciprocalForceKernel
:
public
KernelImpl
{
public:
class
IO
;
static
std
::
string
Name
()
{
return
"CalcDispersionPmeReciprocalForce"
;
}
CalcDispersionPmeReciprocalForceKernel
(
std
::
string
name
,
const
Platform
&
platform
)
:
KernelImpl
(
name
,
platform
)
{
}
/**
* Initialize the kernel.
*
* @param gridx the x size of the PME grid
* @param gridy the y size of the PME grid
* @param gridz the z size of the PME grid
* @param numParticles the number of particles in the system
* @param alpha the Ewald blending parameter
*/
virtual
void
initialize
(
int
gridx
,
int
gridy
,
int
gridz
,
int
numParticles
,
double
alpha
)
=
0
;
/**
* Begin computing the force and energy.
*
* @param io an object that coordinates data transfer
* @param periodicBoxVectors the vectors defining the periodic box (measured in nm)
* @param includeEnergy true if potential energy should be computed
*/
virtual
void
beginComputation
(
IO
&
io
,
const
Vec3
*
periodicBoxVectors
,
bool
includeEnergy
)
=
0
;
/**
* Finish computing the force and energy.
*
* @param io an object that coordinates data transfer
* @return the potential energy due to the PME reciprocal space interactions
*/
virtual
double
finishComputation
(
IO
&
io
)
=
0
;
/**
* Get the parameters being used for PME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
virtual
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
=
0
;
};
}
// namespace OpenMM
#endif
/*OPENMM_KERNELS_H_*/
openmmapi/include/openmm/NonbondedForce.h
View file @
53f770f4
...
...
@@ -101,15 +101,20 @@ public:
*/
CutoffPeriodic
=
2
,
/**
* Periodic boundary conditions are used, and Ewald summation is used to compute the interaction of each particle
* Periodic boundary conditions are used, and Ewald summation is used to compute the
Coulomb
interaction of each particle
* with all periodic copies of every other particle.
*/
Ewald
=
3
,
/**
* Periodic boundary conditions are used, and Particle-Mesh Ewald (PME) summation is used to compute the interaction of each particle
* Periodic boundary conditions are used, and Particle-Mesh Ewald (PME) summation is used to compute the
Coulomb
interaction of each particle
* with all periodic copies of every other particle.
*/
PME
=
4
PME
=
4
,
/**
* Periodic boundary conditions are used, and Particle-Mesh Ewald (PME) summation is used to compute the interaction of each particle
* with all periodic copies of every other particle for both Coulomb and Lennard-Jones. No switching is used for either interaction.
*/
LJPME
=
5
};
/**
* Create a NonbondedForce.
...
...
@@ -207,6 +212,16 @@ public:
* @param[out] nz the number of grid points along the Z axis
*/
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Get the parameters to use for dispersion term in LJ-PME calculations. If alpha is 0 (the default),
* these parameters are ignored and instead their values are chosen based on the Ewald error tolerance.
*
* @param[out] alpha the separation parameter
* @param[out] nx the number of dispersion grid points along the X axis
* @param[out] ny the number of dispersion grid points along the Y axis
* @param[out] nz the number of dispersion grid points along the Z axis
*/
void
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Set the parameters to use for PME calculations. If alpha is 0 (the default), these parameters are
* ignored and instead their values are chosen based on the Ewald error tolerance.
...
...
@@ -217,6 +232,16 @@ public:
* @param nz the number of grid points along the Z axis
*/
void
setPMEParameters
(
double
alpha
,
int
nx
,
int
ny
,
int
nz
);
/**
* Set the parameters to use for the dispersion term in LJPME calculations. If alpha is 0 (the default),
* these parameters are ignored and instead their values are chosen based on the Ewald error tolerance.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void
setLJPMEParameters
(
double
alpha
,
int
nx
,
int
ny
,
int
nz
);
/**
* Get the parameters being used for PME in a particular Context. Because some platforms have restrictions
* on the allowed grid sizes, the values that are actually used may be slightly different from those
...
...
@@ -230,6 +255,19 @@ public:
* @param[out] nz the number of grid points along the Z axis
*/
void
getPMEParametersInContext
(
const
Context
&
context
,
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Get the PME parameters being used for the dispersion term for LJPME in a particular Context. Because some
* platforms have restrictions on the allowed grid sizes, the values that are actually used may be slightly different
* from those specified with setPMEParameters(), or the standard values calculated based on the Ewald error tolerance.
* See the manual for details.
*
* @param context the Context for which to get the parameters
* @param[out] alpha the separation parameter
* @param[out] nx the number of grid points along the X axis
* @param[out] ny the number of grid points along the Y axis
* @param[out] nz the number of grid points along the Z axis
*/
void
getLJPMEParametersInContext
(
const
Context
&
context
,
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Add the nonbonded force parameters for a particle. This should be called once for each particle
* in the System. When it is called for the i'th time, it specifies the parameters for the i'th particle.
...
...
@@ -374,7 +412,8 @@ public:
bool
usesPeriodicBoundaryConditions
()
const
{
return
nonbondedMethod
==
NonbondedForce
::
CutoffPeriodic
||
nonbondedMethod
==
NonbondedForce
::
Ewald
||
nonbondedMethod
==
NonbondedForce
::
PME
;
nonbondedMethod
==
NonbondedForce
::
PME
||
nonbondedMethod
==
NonbondedForce
::
LJPME
;
}
protected:
ForceImpl
*
createImpl
()
const
;
...
...
@@ -382,9 +421,9 @@ private:
class
ParticleInfo
;
class
ExceptionInfo
;
NonbondedMethod
nonbondedMethod
;
double
cutoffDistance
,
switchingDistance
,
rfDielectric
,
ewaldErrorTol
,
alpha
;
double
cutoffDistance
,
switchingDistance
,
rfDielectric
,
ewaldErrorTol
,
alpha
,
dalpha
;
bool
useSwitchingFunction
,
useDispersionCorrection
;
int
recipForceGroup
,
nx
,
ny
,
nz
;
int
recipForceGroup
,
nx
,
ny
,
nz
,
dnx
,
dny
,
dnz
;
void
addExclusionsToSet
(
const
std
::
vector
<
std
::
set
<
int
>
>&
bonded12
,
std
::
set
<
int
>&
exclusions
,
int
baseParticle
,
int
fromParticle
,
int
currentLevel
)
const
;
std
::
vector
<
ParticleInfo
>
particles
;
std
::
vector
<
ExceptionInfo
>
exceptions
;
...
...
openmmapi/include/openmm/internal/NonbondedForceImpl.h
View file @
53f770f4
...
...
@@ -65,6 +65,7 @@ public:
std
::
vector
<
std
::
string
>
getKernelNames
();
void
updateParametersInContext
(
ContextImpl
&
context
);
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
void
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* This is a utility routine that calculates the values to use for alpha and kmax when using
* Ewald summation.
...
...
@@ -74,7 +75,7 @@ public:
* 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
);
static
void
calcPMEParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
xsize
,
int
&
ysize
,
int
&
zsize
,
bool
lj
);
/**
* Compute the coefficient which, when divided by the periodic box volume, gives the
* long range dispersion correction to the energy.
...
...
openmmapi/src/NonbondedForce.cpp
View file @
53f770f4
...
...
@@ -48,7 +48,8 @@ using std::stringstream;
using
std
::
vector
;
NonbondedForce
::
NonbondedForce
()
:
nonbondedMethod
(
NoCutoff
),
cutoffDistance
(
1.0
),
switchingDistance
(
-
1.0
),
rfDielectric
(
78.3
),
ewaldErrorTol
(
5e-4
),
alpha
(
0.0
),
useSwitchingFunction
(
false
),
useDispersionCorrection
(
true
),
recipForceGroup
(
-
1
),
nx
(
0
),
ny
(
0
),
nz
(
0
)
{
ewaldErrorTol
(
5e-4
),
alpha
(
0.0
),
dalpha
(
0.0
),
useSwitchingFunction
(
false
),
useDispersionCorrection
(
true
),
recipForceGroup
(
-
1
),
nx
(
0
),
ny
(
0
),
nz
(
0
),
dnx
(
0
),
dny
(
0
),
dnz
(
0
)
{
}
NonbondedForce
::
NonbondedMethod
NonbondedForce
::
getNonbondedMethod
()
const
{
...
...
@@ -106,6 +107,13 @@ void NonbondedForce::getPMEParameters(double& alpha, int& nx, int& ny, int& nz)
nz
=
this
->
nz
;
}
void
NonbondedForce
::
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
alpha
=
this
->
dalpha
;
nx
=
this
->
dnx
;
ny
=
this
->
dny
;
nz
=
this
->
dnz
;
}
void
NonbondedForce
::
setPMEParameters
(
double
alpha
,
int
nx
,
int
ny
,
int
nz
)
{
this
->
alpha
=
alpha
;
this
->
nx
=
nx
;
...
...
@@ -113,10 +121,21 @@ void NonbondedForce::setPMEParameters(double alpha, int nx, int ny, int nz) {
this
->
nz
=
nz
;
}
void
NonbondedForce
::
setLJPMEParameters
(
double
alpha
,
int
nx
,
int
ny
,
int
nz
)
{
this
->
dalpha
=
alpha
;
this
->
dnx
=
nx
;
this
->
dny
=
ny
;
this
->
dnz
=
nz
;
}
void
NonbondedForce
::
getPMEParametersInContext
(
const
Context
&
context
,
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
dynamic_cast
<
const
NonbondedForceImpl
&>
(
getImplInContext
(
context
)).
getPMEParameters
(
alpha
,
nx
,
ny
,
nz
);
}
void
NonbondedForce
::
getLJPMEParametersInContext
(
const
Context
&
context
,
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
dynamic_cast
<
const
NonbondedForceImpl
&>
(
getImplInContext
(
context
)).
getLJPMEParameters
(
alpha
,
nx
,
ny
,
nz
);
}
int
NonbondedForce
::
addParticle
(
double
charge
,
double
sigma
,
double
epsilon
)
{
particles
.
push_back
(
ParticleInfo
(
charge
,
sigma
,
epsilon
));
return
particles
.
size
()
-
1
;
...
...
openmmapi/src/NonbondedForceImpl.cpp
View file @
53f770f4
...
...
@@ -90,9 +90,7 @@ void NonbondedForceImpl::initialize(ContextImpl& context) {
exceptions
[
particle1
].
insert
(
particle2
);
exceptions
[
particle2
].
insert
(
particle1
);
}
if
(
owner
.
getNonbondedMethod
()
==
NonbondedForce
::
CutoffPeriodic
||
owner
.
getNonbondedMethod
()
==
NonbondedForce
::
Ewald
||
owner
.
getNonbondedMethod
()
==
NonbondedForce
::
PME
)
{
if
(
owner
.
getNonbondedMethod
()
!=
NonbondedForce
::
NoCutoff
&&
owner
.
getNonbondedMethod
()
!=
NonbondedForce
::
CutoffNonPeriodic
)
{
Vec3
boxVectors
[
3
];
system
.
getDefaultPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
double
cutoff
=
owner
.
getCutoffDistance
();
...
...
@@ -151,19 +149,29 @@ void NonbondedForceImpl::calcEwaldParameters(const System& system, const Nonbond
kmaxz
++
;
}
void
NonbondedForceImpl
::
calcPMEParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
xsize
,
int
&
ysize
,
int
&
zsize
)
{
force
.
getPMEParameters
(
alpha
,
xsize
,
ysize
,
zsize
);
void
NonbondedForceImpl
::
calcPMEParameters
(
const
System
&
system
,
const
NonbondedForce
&
force
,
double
&
alpha
,
int
&
xsize
,
int
&
ysize
,
int
&
zsize
,
bool
lj
)
{
if
(
lj
)
force
.
getLJPMEParameters
(
alpha
,
xsize
,
ysize
,
zsize
);
else
force
.
getPMEParameters
(
alpha
,
xsize
,
ysize
,
zsize
);
if
(
alpha
==
0.0
)
{
Vec3
boxVectors
[
3
];
system
.
getDefaultPeriodicBoxVectors
(
boxVectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
]);
double
tol
=
force
.
getEwaldErrorTolerance
();
alpha
=
(
1.0
/
force
.
getCutoffDistance
())
*
std
::
sqrt
(
-
log
(
2.0
*
tol
));
xsize
=
(
int
)
ceil
(
2
*
alpha
*
boxVectors
[
0
][
0
]
/
(
3
*
pow
(
tol
,
0.2
)));
ysize
=
(
int
)
ceil
(
2
*
alpha
*
boxVectors
[
1
][
1
]
/
(
3
*
pow
(
tol
,
0.2
)));
zsize
=
(
int
)
ceil
(
2
*
alpha
*
boxVectors
[
2
][
2
]
/
(
3
*
pow
(
tol
,
0.2
)));
xsize
=
max
(
xsize
,
5
);
ysize
=
max
(
ysize
,
5
);
zsize
=
max
(
zsize
,
5
);
if
(
lj
)
{
xsize
=
(
int
)
ceil
(
alpha
*
boxVectors
[
0
][
0
]
/
(
3
*
pow
(
tol
,
0.2
)));
ysize
=
(
int
)
ceil
(
alpha
*
boxVectors
[
1
][
1
]
/
(
3
*
pow
(
tol
,
0.2
)));
zsize
=
(
int
)
ceil
(
alpha
*
boxVectors
[
2
][
2
]
/
(
3
*
pow
(
tol
,
0.2
)));
}
else
{
xsize
=
(
int
)
ceil
(
2
*
alpha
*
boxVectors
[
0
][
0
]
/
(
3
*
pow
(
tol
,
0.2
)));
ysize
=
(
int
)
ceil
(
2
*
alpha
*
boxVectors
[
1
][
1
]
/
(
3
*
pow
(
tol
,
0.2
)));
zsize
=
(
int
)
ceil
(
2
*
alpha
*
boxVectors
[
2
][
2
]
/
(
3
*
pow
(
tol
,
0.2
)));
}
xsize
=
max
(
xsize
,
6
);
ysize
=
max
(
ysize
,
6
);
zsize
=
max
(
zsize
,
6
);
}
}
...
...
@@ -283,3 +291,7 @@ void NonbondedForceImpl::updateParametersInContext(ContextImpl& context) {
void
NonbondedForceImpl
::
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
kernel
.
getAs
<
CalcNonbondedForceKernel
>
().
getPMEParameters
(
alpha
,
nx
,
ny
,
nz
);
}
void
NonbondedForceImpl
::
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
kernel
.
getAs
<
CalcNonbondedForceKernel
>
().
getLJPMEParameters
(
alpha
,
nx
,
ny
,
nz
);
}
platforms/cpu/include/CpuKernels.h
View file @
53f770f4
...
...
@@ -249,27 +249,37 @@ public:
void
copyParametersToContext
(
ContextImpl
&
context
,
const
NonbondedForce
&
force
);
/**
* Get the parameters being used for PME.
*
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Get the parameters being used for the dispersion term in LJPME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
private:
class
PmeIO
;
CpuPlatform
::
PlatformData
&
data
;
int
numParticles
,
num14
;
int
**
bonded14IndexArray
;
double
**
bonded14ParamArray
;
double
nonbondedCutoff
,
switchingDistance
,
rfDielectric
,
ewaldAlpha
,
ewaldSelfEnergy
,
dispersionCoefficient
;
int
kmax
[
3
],
gridSize
[
3
];
bool
useSwitchingFunction
,
useOptimizedPme
,
hasInitializedPme
;
double
nonbondedCutoff
,
switchingDistance
,
rfDielectric
,
ewaldAlpha
,
ewaldDispersionAlpha
,
ewaldSelfEnergy
,
dispersionCoefficient
;
int
kmax
[
3
],
gridSize
[
3
]
,
dispersionGridSize
[
3
]
;
bool
useSwitchingFunction
,
useOptimizedPme
,
hasInitializedPme
,
hasInitializedDispersionPme
;
std
::
vector
<
std
::
set
<
int
>
>
exclusions
;
std
::
vector
<
std
::
pair
<
float
,
float
>
>
particleParams
;
std
::
vector
<
float
>
C6params
;
NonbondedMethod
nonbondedMethod
;
CpuNonbondedForce
*
nonbonded
;
Kernel
optimizedPme
;
Kernel
optimizedPme
,
optimizedDispersionPme
;
CpuBondForce
bondForce
;
};
...
...
platforms/cpu/include/CpuNonbondedForce.h
View file @
53f770f4
...
...
@@ -103,16 +103,27 @@ class CpuNonbondedForce {
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation.
@param alpha the Ewald separation parameter
@param gridSize the dimensions of the mesh
--------------------------------------------------------------------------------------- */
void
setUsePME
(
float
alpha
,
int
meshSize
[
3
]);
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation for dispersion.
@param alpha the Ewald separation parameter
@param gridSize the dimensions of the mesh
--------------------------------------------------------------------------------------- */
void
setUseLJPME
(
float
alpha
,
int
meshSize
[
3
]);
/**---------------------------------------------------------------------------------------
Calculate Ewald ixn
...
...
@@ -121,16 +132,17 @@ class CpuNonbondedForce {
@param posq atom coordinates and charges
@param atomCoordinates atom coordinates (in format needed by PME)
@param atomParameters atom parameters (sigma/2, 2*sqrt(epsilon))
@param C6Paramrs C6 parameters for multiplicative representation of dispersion
@param exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void
calculateReciprocalIxn
(
int
numberOfAtoms
,
float
*
posq
,
const
std
::
vector
<
RealVec
>&
atomCoordinates
,
const
std
::
vector
<
std
::
pair
<
float
,
float
>
>&
atomParameters
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusion
s
,
std
::
vector
<
RealVec
>&
forces
,
double
*
totalEnergy
)
const
;
const
std
::
vector
<
std
::
pair
<
float
,
float
>
>&
atomParameters
,
const
std
::
vector
<
float
>
&
C6param
s
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
std
::
vector
<
RealVec
>&
forces
,
double
*
totalEnergy
)
const
;
/**---------------------------------------------------------------------------------------
...
...
@@ -149,7 +161,7 @@ class CpuNonbondedForce {
--------------------------------------------------------------------------------------- */
void
calculateDirectIxn
(
int
numberOfAtoms
,
float
*
posq
,
const
std
::
vector
<
RealVec
>&
atomCoordinates
,
const
std
::
vector
<
std
::
pair
<
float
,
float
>
>&
atomParameters
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
std
::
vector
<
AlignedArray
<
float
>
>&
threadForce
,
double
*
totalEnergy
,
ThreadPool
&
threads
);
const
std
::
vector
<
float
>&
C6params
,
const
std
::
vector
<
std
::
set
<
int
>
>&
exclusions
,
std
::
vector
<
AlignedArray
<
float
>
>&
threadForce
,
double
*
totalEnergy
,
ThreadPool
&
threads
);
/**
* This routine contains the code executed by each thread.
...
...
@@ -162,28 +174,32 @@ protected:
bool
periodic
;
bool
triclinic
;
bool
ewald
;
bool
pme
;
bool
tableIsValid
;
bool
ljpme
,
pme
;
bool
tableIsValid
,
expTableIsValid
;
const
CpuNeighborList
*
neighborList
;
float
recipBoxSize
[
3
];
RealVec
periodicBoxVectors
[
3
];
AlignedArray
<
fvec4
>
periodicBoxVec4
;
float
cutoffDistance
,
switchingDistance
;
float
krf
,
crf
;
float
alphaEwald
;
float
alphaEwald
,
alphaDispersionEwald
;
int
numRx
,
numRy
,
numRz
;
int
meshDim
[
3
];
int
meshDim
[
3
]
,
dispersionMeshDim
[
3
]
;
std
::
vector
<
float
>
erfcTable
,
ewaldScaleTable
;
float
ewaldDX
,
ewaldDXInv
,
erfcDXInv
;
std
::
vector
<
float
>
exptermsTable
,
dExptermsTable
;
float
ewaldDX
,
ewaldDXInv
,
erfcDXInv
,
exptermsDX
,
exptermsDXInv
;
std
::
vector
<
double
>
threadEnergy
;
// The following variables are used to make information accessible to the individual threads.
int
numberOfAtoms
;
float
*
posq
;
RealVec
const
*
atomCoordinates
;
std
::
pair
<
float
,
float
>
const
*
atomParameters
;
std
::
pair
<
float
,
float
>
const
*
atomParameters
;
float
const
*
C6params
;
std
::
set
<
int
>
const
*
exclusions
;
std
::
vector
<
AlignedArray
<
float
>
>*
threadForce
;
bool
includeEnergy
;
float
inverseRcut6
;
float
inverseRcut6Expterm
;
void
*
atomicCounter
;
static
const
float
TWO_OVER_SQRT_PI
;
...
...
@@ -237,10 +253,29 @@ protected:
*/
void
tabulateEwaldScaleFactor
();
/**
* Create a lookup table for the scale factor used with dispersion PME.
*/
void
tabulateExpTerms
();
/**
* Compute a fast approximation to erfc(x).
*/
float
erfcApprox
(
float
x
);
/**
* Compute a fast approximation to (1.0 - EXP(-dar^2) * (1.0 + dar^2 + 0.5*dar^4))
* where dar = (dispersionAlpha * R)
* needed for LJPME energies.
*/
float
exptermsApprox
(
float
R
);
/**
* Compute a fast approximation to (1.0 - EXP(-dar^2) * (1.0 + dar^2 + 0.5*dar^4 + dar^6/6.0))
* where dar = (dispersionAlpha * R)
* needed for LJPME forces.
*/
float
dExptermsApprox
(
float
R
);
};
}
// namespace OpenMM
...
...
platforms/cpu/include/CpuNonbondedForceVec4.h
View file @
53f770f4
...
...
@@ -88,11 +88,25 @@ protected:
* Compute a fast approximation to erfc(x).
*/
fvec4
erfcApprox
(
const
fvec4
&
x
);
/**
* Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
*/
fvec4
ewaldScaleFunction
(
const
fvec4
&
x
);
/**
* Compute a fast approximation to (1.0 - EXP(-dar^2) * (1.0 + dar^2 + 0.5*dar^4))
* where dar = (dispersionAlpha * R)
* needed for LJPME energies.
*/
fvec4
exptermsApprox
(
const
fvec4
&
R
);
/**
* Compute a fast approximation to (1.0 - EXP(-dar^2) * (1.0 + dar^2 + 0.5*dar^4 + dar^6/6.0))
* where dar = (dispersionAlpha * R)
* needed for LJPME forces.
*/
fvec4
dExptermsApprox
(
const
fvec4
&
R
);
};
}
// namespace OpenMM
...
...
platforms/cpu/include/CpuNonbondedForceVec8.h
View file @
53f770f4
...
...
@@ -92,6 +92,21 @@ protected:
* Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
*/
fvec8
ewaldScaleFunction
(
const
fvec8
&
x
);
/**
* Compute a fast approximation to (1.0 - EXP(-dar^2) * (1.0 + dar^2 + 0.5*dar^4))
* where dar = (dispersionAlpha * R)
* needed for LJPME energies.
*/
fvec8
exptermsApprox
(
const
fvec8
&
R
);
/**
* Compute a fast approximation to (1.0 - EXP(-dar^2) * (1.0 + dar^2 + 0.5*dar^4 + dar^6/6.0))
* where dar = (dispersionAlpha * R)
* needed for LJPME forces.
*/
fvec8
dExptermsApprox
(
const
fvec8
&
R
);
};
}
// namespace OpenMM
...
...
platforms/cpu/src/CpuKernels.cpp
View file @
53f770f4
...
...
@@ -50,6 +50,7 @@
#include "lepton/CustomFunction.h"
#include "lepton/Operation.h"
#include "lepton/Parser.h"
#include <iostream>
#include "lepton/ParsedExpression.h"
using
namespace
OpenMM
;
...
...
@@ -508,7 +509,7 @@ CpuNonbondedForce* createCpuNonbondedForceVec4();
CpuNonbondedForce
*
createCpuNonbondedForceVec8
();
CpuCalcNonbondedForceKernel
::
CpuCalcNonbondedForceKernel
(
string
name
,
const
Platform
&
platform
,
CpuPlatform
::
PlatformData
&
data
)
:
CalcNonbondedForceKernel
(
name
,
platform
),
data
(
data
),
bonded14IndexArray
(
NULL
),
bonded14ParamArray
(
NULL
),
hasInitializedPme
(
false
),
nonbonded
(
NULL
)
{
data
(
data
),
bonded14IndexArray
(
NULL
),
bonded14ParamArray
(
NULL
),
hasInitializedPme
(
false
),
hasInitializedDispersionPme
(
false
),
nonbonded
(
NULL
)
{
if
(
isVec8Supported
())
nonbonded
=
createCpuNonbondedForceVec8
();
else
...
...
@@ -555,12 +556,14 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
for
(
int
i
=
0
;
i
<
num14
;
i
++
)
bonded14ParamArray
[
i
]
=
new
double
[
3
];
particleParams
.
resize
(
numParticles
);
C6params
.
resize
(
numParticles
);
double
sumSquaredCharges
=
0.0
;
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
double
charge
,
radius
,
depth
;
force
.
getParticleParameters
(
i
,
charge
,
radius
,
depth
);
data
.
posq
[
4
*
i
+
3
]
=
(
float
)
charge
;
particleParams
[
i
]
=
make_pair
((
float
)
(
0.5
*
radius
),
(
float
)
(
2.0
*
sqrt
(
depth
)));
C6params
[
i
]
=
8.0
*
pow
(
particleParams
[
i
].
first
,
3.0
)
*
particleParams
[
i
].
second
;
sumSquaredCharges
+=
charge
*
charge
;
}
...
...
@@ -596,19 +599,35 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
}
else
if
(
nonbondedMethod
==
PME
)
{
double
alpha
;
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
]);
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
]
,
false
);
ewaldAlpha
=
alpha
;
}
if
(
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
)
else
if
(
nonbondedMethod
==
LJPME
)
{
double
alpha
;
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
],
false
);
ewaldAlpha
=
(
RealOpenMM
)
alpha
;
NonbondedForceImpl
::
calcPMEParameters
(
system
,
force
,
alpha
,
dispersionGridSize
[
0
],
dispersionGridSize
[
1
],
dispersionGridSize
[
2
],
true
);
ewaldDispersionAlpha
=
(
RealOpenMM
)
alpha
;
useSwitchingFunction
=
false
;
}
if
(
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
||
nonbondedMethod
==
LJPME
)
{
ewaldSelfEnergy
=
-
ONE_4PI_EPS0
*
ewaldAlpha
*
sumSquaredCharges
/
sqrt
(
M_PI
);
else
if
(
nonbondedMethod
==
LJPME
){
for
(
int
atom
=
0
;
atom
<
numParticles
;
atom
++
)
{
// Dispersion self term
ewaldSelfEnergy
+=
pow
(
ewaldDispersionAlpha
,
6.0
)
*
C6params
[
atom
]
*
C6params
[
atom
]
/
12.0
;
}
}
}
else
{
ewaldSelfEnergy
=
0.0
;
}
rfDielectric
=
force
.
getReactionFieldDielectric
();
if
(
force
.
getUseDispersionCorrection
())
dispersionCoefficient
=
NonbondedForceImpl
::
calcDispersionCorrection
(
system
,
force
);
else
dispersionCoefficient
=
0.0
;
data
.
isPeriodic
=
(
nonbondedMethod
==
CutoffPeriodic
||
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
);
data
.
isPeriodic
=
(
nonbondedMethod
==
CutoffPeriodic
||
nonbondedMethod
==
Ewald
||
nonbondedMethod
==
PME
||
nonbondedMethod
==
LJPME
);
}
double
CpuCalcNonbondedForceKernel
::
execute
(
ContextImpl
&
context
,
bool
includeForces
,
bool
includeEnergy
,
bool
includeDirect
,
bool
includeReciprocal
)
{
...
...
@@ -626,6 +645,20 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
initialize
(
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
],
numParticles
,
ewaldAlpha
);
}
}
if
(
nonbondedMethod
==
LJPME
)
{
// If available, use the optimized PME implementation.
vector
<
string
>
kernelNames
;
kernelNames
.
push_back
(
"CalcPmeReciprocalForce"
);
useOptimizedPme
=
getPlatform
().
supportsKernels
(
kernelNames
);
if
(
useOptimizedPme
)
{
optimizedPme
=
getPlatform
().
createKernel
(
CalcPmeReciprocalForceKernel
::
Name
(),
context
);
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
initialize
(
gridSize
[
0
],
gridSize
[
1
],
gridSize
[
2
],
numParticles
,
ewaldAlpha
);
optimizedDispersionPme
=
getPlatform
().
createKernel
(
CalcDispersionPmeReciprocalForceKernel
::
Name
(),
context
);
optimizedDispersionPme
.
getAs
<
CalcDispersionPmeReciprocalForceKernel
>
().
initialize
(
dispersionGridSize
[
0
],
dispersionGridSize
[
1
],
dispersionGridSize
[
2
],
numParticles
,
ewaldDispersionAlpha
);
}
}
}
AlignedArray
<
float
>&
posq
=
data
.
posq
;
vector
<
RealVec
>&
posData
=
extractPositions
(
context
);
...
...
@@ -634,6 +667,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
double
energy
=
(
includeReciprocal
?
ewaldSelfEnergy
:
0.0
);
bool
ewald
=
(
nonbondedMethod
==
Ewald
);
bool
pme
=
(
nonbondedMethod
==
PME
);
bool
ljpme
=
(
nonbondedMethod
==
LJPME
);
if
(
nonbondedMethod
!=
NoCutoff
)
nonbonded
->
setUseCutoff
(
nonbondedCutoff
,
*
data
.
neighborList
,
rfDielectric
);
if
(
data
.
isPeriodic
)
{
...
...
@@ -649,9 +683,13 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
nonbonded
->
setUsePME
(
ewaldAlpha
,
gridSize
);
if
(
useSwitchingFunction
)
nonbonded
->
setUseSwitchingFunction
(
switchingDistance
);
if
(
ljpme
){
nonbonded
->
setUsePME
(
ewaldAlpha
,
gridSize
);
nonbonded
->
setUseLJPME
(
ewaldDispersionAlpha
,
dispersionGridSize
);
}
double
nonbondedEnergy
=
0
;
if
(
includeDirect
)
nonbonded
->
calculateDirectIxn
(
numParticles
,
&
posq
[
0
],
posData
,
particleParams
,
exclusions
,
data
.
threadForce
,
includeEnergy
?
&
nonbondedEnergy
:
NULL
,
data
.
threads
);
nonbonded
->
calculateDirectIxn
(
numParticles
,
&
posq
[
0
],
posData
,
particleParams
,
C6params
,
exclusions
,
data
.
threadForce
,
includeEnergy
?
&
nonbondedEnergy
:
NULL
,
data
.
threads
);
if
(
includeReciprocal
)
{
if
(
useOptimizedPme
)
{
PmeIO
io
(
&
posq
[
0
],
&
data
.
threadForce
[
0
][
0
],
numParticles
);
...
...
@@ -660,13 +698,13 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
nonbondedEnergy
+=
optimizedPme
.
getAs
<
CalcPmeReciprocalForceKernel
>
().
finishComputation
(
io
);
}
else
nonbonded
->
calculateReciprocalIxn
(
numParticles
,
&
posq
[
0
],
posData
,
particleParams
,
exclusions
,
forceData
,
includeEnergy
?
&
nonbondedEnergy
:
NULL
);
nonbonded
->
calculateReciprocalIxn
(
numParticles
,
&
posq
[
0
],
posData
,
particleParams
,
C6params
,
exclusions
,
forceData
,
includeEnergy
?
&
nonbondedEnergy
:
NULL
);
}
energy
+=
nonbondedEnergy
;
if
(
includeDirect
)
{
ReferenceLJCoulomb14
nonbonded14
;
bondForce
.
calculateForce
(
posData
,
bonded14ParamArray
,
forceData
,
includeEnergy
?
&
energy
:
NULL
,
nonbonded14
);
if
(
data
.
isPeriodic
)
if
(
data
.
isPeriodic
&&
nonbondedMethod
!=
LJPME
)
energy
+=
dispersionCoefficient
/
(
boxVectors
[
0
][
0
]
*
boxVectors
[
1
][
1
]
*
boxVectors
[
2
][
2
]);
}
return
energy
;
...
...
@@ -719,7 +757,7 @@ void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context,
}
void
CpuCalcNonbondedForceKernel
::
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
if
(
nonbondedMethod
!=
PME
)
if
(
nonbondedMethod
!=
PME
&&
nonbondedMethod
!=
LJPME
)
throw
OpenMMException
(
"getPMEParametersInContext: This Context is not using PME"
);
if
(
useOptimizedPme
)
optimizedPme
.
getAs
<
const
CalcPmeReciprocalForceKernel
>
().
getPMEParameters
(
alpha
,
nx
,
ny
,
nz
);
...
...
@@ -731,6 +769,19 @@ void CpuCalcNonbondedForceKernel::getPMEParameters(double& alpha, int& nx, int&
}
}
void
CpuCalcNonbondedForceKernel
::
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
{
if
(
nonbondedMethod
!=
LJPME
)
throw
OpenMMException
(
"getPMEParametersInContext: This Context is not using PME"
);
if
(
useOptimizedPme
)
optimizedDispersionPme
.
getAs
<
const
CalcPmeReciprocalForceKernel
>
().
getPMEParameters
(
alpha
,
nx
,
ny
,
nz
);
else
{
alpha
=
ewaldDispersionAlpha
;
nx
=
dispersionGridSize
[
0
];
ny
=
dispersionGridSize
[
1
];
nz
=
dispersionGridSize
[
2
];
}
}
CpuCalcCustomNonbondedForceKernel
::
CpuCalcCustomNonbondedForceKernel
(
string
name
,
const
Platform
&
platform
,
CpuPlatform
::
PlatformData
&
data
)
:
CalcCustomNonbondedForceKernel
(
name
,
platform
),
data
(
data
),
forceCopy
(
NULL
),
nonbonded
(
NULL
)
{
}
...
...
platforms/cpu/src/CpuNonbondedForce.cpp
View file @
53f770f4
...
...
@@ -30,6 +30,7 @@
#include "ReferencePME.h"
#include "openmm/internal/gmx_atomic.h"
#include <algorithm>
#include <iostream>
// In case we're using some primitive version of Visual Studio this will
// make sure that erf() and erfc() are defined.
...
...
@@ -47,7 +48,8 @@ const int CpuNonbondedForce::NUM_TABLE_POINTS = 2048;
--------------------------------------------------------------------------------------- */
CpuNonbondedForce
::
CpuNonbondedForce
()
:
cutoff
(
false
),
useSwitch
(
false
),
periodic
(
false
),
ewald
(
false
),
pme
(
false
),
tableIsValid
(
false
),
cutoffDistance
(
0.0
f
),
alphaEwald
(
0.0
f
)
{
CpuNonbondedForce
::
CpuNonbondedForce
()
:
cutoff
(
false
),
useSwitch
(
false
),
periodic
(
false
),
ewald
(
false
),
pme
(
false
),
ljpme
(
false
),
tableIsValid
(
false
),
expTableIsValid
(
false
),
cutoffDistance
(
0.0
f
),
alphaDispersionEwald
(
0.0
f
),
alphaEwald
(
0.0
f
)
{
}
CpuNonbondedForce
::~
CpuNonbondedForce
()
{
...
...
@@ -68,10 +70,21 @@ void CpuNonbondedForce::setUseCutoff(float distance, const CpuNeighborList& neig
tableIsValid
=
false
;
cutoff
=
true
;
cutoffDistance
=
distance
;
inverseRcut6
=
pow
(
cutoffDistance
,
-
6
);
neighborList
=
&
neighbors
;
krf
=
pow
(
cutoffDistance
,
-
3.0
f
)
*
(
solventDielectric
-
1.0
)
/
(
2.0
*
solventDielectric
+
1.0
);
crf
=
(
1.0
/
cutoffDistance
)
*
(
3.0
*
solventDielectric
)
/
(
2.0
*
solventDielectric
+
1.0
);
}
if
(
alphaDispersionEwald
!=
0.0
f
){
// We set this here, in case setUseCutoff is called after the dispersion alpha is set.
double
dalphaR
=
alphaDispersionEwald
*
cutoffDistance
;
double
dar2
=
dalphaR
*
dalphaR
;
double
dar4
=
dar2
*
dar2
;
double
dar6
=
dar4
*
dar2
;
double
expterm
=
EXP
(
-
dar2
);
inverseRcut6Expterm
=
inverseRcut6
*
(
1.0
-
expterm
*
(
1.0
+
dar2
+
0.5
*
dar4
));
}
}
/**---------------------------------------------------------------------------------------
...
...
@@ -86,7 +99,7 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
switchingDistance
=
distance
;
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use periodic boundary conditions. This requires that a cutoff has
also been set, and the smallest side of the periodic box is at least twice the cutoff
...
...
@@ -96,7 +109,7 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
--------------------------------------------------------------------------------------- */
void
CpuNonbondedForce
::
setPeriodic
(
RealVec
*
periodicBoxVectors
)
{
void
CpuNonbondedForce
::
setPeriodic
(
RealVec
*
periodicBoxVectors
)
{
assert
(
cutoff
);
assert
(
periodicBoxVectors
[
0
][
0
]
>=
2.0
*
cutoffDistance
);
...
...
@@ -114,11 +127,11 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
periodicBoxVec4
[
1
]
=
fvec4
(
periodicBoxVectors
[
1
][
0
],
periodicBoxVectors
[
1
][
1
],
periodicBoxVectors
[
1
][
2
],
0
);
periodicBoxVec4
[
2
]
=
fvec4
(
periodicBoxVectors
[
2
][
0
],
periodicBoxVectors
[
2
][
1
],
periodicBoxVectors
[
2
][
2
],
0
);
triclinic
=
(
periodicBoxVectors
[
0
][
1
]
!=
0.0
||
periodicBoxVectors
[
0
][
2
]
!=
0.0
||
periodicBoxVectors
[
1
][
0
]
!=
0.0
||
periodicBoxVectors
[
1
][
2
]
!=
0.0
||
periodicBoxVectors
[
2
][
0
]
!=
0.0
||
periodicBoxVectors
[
2
][
1
]
!=
0.0
);
}
periodicBoxVectors
[
1
][
0
]
!=
0.0
||
periodicBoxVectors
[
1
][
2
]
!=
0.0
||
periodicBoxVectors
[
2
][
0
]
!=
0.0
||
periodicBoxVectors
[
2
][
1
]
!=
0.0
);
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use Ewald summation.
...
...
@@ -129,18 +142,18 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
--------------------------------------------------------------------------------------- */
void
CpuNonbondedForce
::
setUseEwald
(
float
alpha
,
int
kmaxx
,
int
kmaxy
,
int
kmaxz
)
{
if
(
alpha
!=
alphaEwald
)
tableIsValid
=
false
;
alphaEwald
=
alpha
;
numRx
=
kmaxx
;
numRy
=
kmaxy
;
numRz
=
kmaxz
;
ewald
=
true
;
tabulateEwaldScaleFactor
();
}
void
CpuNonbondedForce
::
setUseEwald
(
float
alpha
,
int
kmaxx
,
int
kmaxy
,
int
kmaxz
)
{
if
(
alpha
!=
alphaEwald
)
tableIsValid
=
false
;
alphaEwald
=
alpha
;
numRx
=
kmaxx
;
numRy
=
kmaxy
;
numRz
=
kmaxz
;
ewald
=
true
;
tabulateEwaldScaleFactor
();
}
/**---------------------------------------------------------------------------------------
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation.
...
...
@@ -149,19 +162,49 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
--------------------------------------------------------------------------------------- */
void
CpuNonbondedForce
::
setUsePME
(
float
alpha
,
int
meshSize
[
3
])
{
if
(
alpha
!=
alphaEwald
)
tableIsValid
=
false
;
alphaEwald
=
alpha
;
meshDim
[
0
]
=
meshSize
[
0
];
meshDim
[
1
]
=
meshSize
[
1
];
meshDim
[
2
]
=
meshSize
[
2
];
pme
=
true
;
tabulateEwaldScaleFactor
();
}
void
CpuNonbondedForce
::
tabulateEwaldScaleFactor
()
{
void
CpuNonbondedForce
::
setUsePME
(
float
alpha
,
int
meshSize
[
3
])
{
if
(
alpha
!=
alphaEwald
)
tableIsValid
=
false
;
alphaEwald
=
alpha
;
meshDim
[
0
]
=
meshSize
[
0
];
meshDim
[
1
]
=
meshSize
[
1
];
meshDim
[
2
]
=
meshSize
[
2
];
pme
=
true
;
tabulateEwaldScaleFactor
();
}
/**---------------------------------------------------------------------------------------
Set the force to use Particle-Mesh Ewald (PME) summation for dispersion.
@param alpha the Ewald separation parameter
@param gridSize the dimensions of the mesh
--------------------------------------------------------------------------------------- */
void
CpuNonbondedForce
::
setUseLJPME
(
float
alpha
,
int
meshSize
[
3
])
{
if
(
alpha
!=
alphaDispersionEwald
)
expTableIsValid
=
false
;
alphaDispersionEwald
=
alpha
;
dispersionMeshDim
[
0
]
=
meshSize
[
0
];
dispersionMeshDim
[
1
]
=
meshSize
[
1
];
dispersionMeshDim
[
2
]
=
meshSize
[
2
];
ljpme
=
true
;
tabulateExpTerms
();
if
(
cutoffDistance
!=
0.0
f
){
// We set this here, in case setUseLJPME is called after the cutoff is set
double
dalphaR
=
alphaDispersionEwald
*
cutoffDistance
;
double
dar2
=
dalphaR
*
dalphaR
;
double
dar4
=
dar2
*
dar2
;
double
dar6
=
dar4
*
dar2
;
double
expterm
=
EXP
(
-
dar2
);
inverseRcut6Expterm
=
inverseRcut6
*
(
1.0
-
expterm
*
(
1.0
+
dar2
+
0.5
*
dar4
));
}
}
void
CpuNonbondedForce
::
tabulateEwaldScaleFactor
()
{
if
(
tableIsValid
)
return
;
tableIsValid
=
true
;
...
...
@@ -177,10 +220,30 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
ewaldScaleTable
[
i
]
=
erfcTable
[
i
]
+
TWO_OVER_SQRT_PI
*
alphaR
*
exp
(
-
alphaR
*
alphaR
);
}
}
void
CpuNonbondedForce
::
tabulateExpTerms
()
{
if
(
expTableIsValid
)
return
;
expTableIsValid
=
true
;
exptermsDX
=
cutoffDistance
/
NUM_TABLE_POINTS
;
exptermsDXInv
=
1.0
f
/
exptermsDX
;
exptermsTable
.
resize
(
NUM_TABLE_POINTS
+
4
);
dExptermsTable
.
resize
(
NUM_TABLE_POINTS
+
4
);
for
(
int
i
=
0
;
i
<
NUM_TABLE_POINTS
+
4
;
i
++
)
{
double
r
=
i
*
ewaldDX
;
double
dalphaR
=
alphaDispersionEwald
*
r
;
double
dar2
=
dalphaR
*
dalphaR
;
double
dar4
=
dar2
*
dar2
;
double
dar6
=
dar4
*
dar2
;
double
expterm
=
EXP
(
-
dar2
);
exptermsTable
[
i
]
=
(
1.0
-
expterm
*
(
1.0
+
dar2
+
0.5
*
dar4
));
dExptermsTable
[
i
]
=
(
1.0
-
expterm
*
(
1.0
+
dar2
+
0.5
*
dar4
+
dar6
/
6.0
));
}
}
void
CpuNonbondedForce
::
calculateReciprocalIxn
(
int
numberOfAtoms
,
float
*
posq
,
const
vector
<
RealVec
>&
atomCoordinates
,
const
vector
<
pair
<
float
,
float
>
>&
atomParameters
,
const
vector
<
set
<
int
>
>&
exclusions
,
vector
<
RealVec
>&
forces
,
double
*
totalEnergy
)
const
{
const
vector
<
pair
<
float
,
float
>
>&
atomParameters
,
const
vector
<
float
>
&
C6params
,
const
vector
<
set
<
int
>
>&
exclusions
,
vector
<
RealVec
>&
forces
,
double
*
totalEnergy
)
const
{
typedef
std
::
complex
<
float
>
d_complex
;
static
const
float
epsilon
=
1.0
;
...
...
@@ -201,6 +264,29 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
if
(
totalEnergy
)
*
totalEnergy
+=
recipEnergy
;
pme_destroy
(
pmedata
);
if
(
ljpme
)
{
// Dispersion reciprocal space terms
pme_init
(
&
pmedata
,
alphaDispersionEwald
,
numberOfAtoms
,
dispersionMeshDim
,
5
,
1
);
std
::
vector
<
RealVec
>
dpmeforces
;
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
){
charges
[
i
]
=
(
RealOpenMM
)
C6params
[
i
];
dpmeforces
.
push_back
(
RealVec
());
}
RealOpenMM
recipDispersionEnergy
=
0.0
;
pme_exec_dpme
(
pmedata
,
atomCoordinates
,
dpmeforces
,
charges
,
periodicBoxVectors
,
&
recipDispersionEnergy
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
){
forces
[
i
][
0
]
-=
2.0
*
dpmeforces
[
i
][
0
];
forces
[
i
][
1
]
-=
2.0
*
dpmeforces
[
i
][
1
];
forces
[
i
][
2
]
-=
2.0
*
dpmeforces
[
i
][
2
];
}
if
(
totalEnergy
)
*
totalEnergy
+=
recipDispersionEnergy
;
pme_destroy
(
pmedata
);
}
}
// Ewald method
...
...
@@ -214,7 +300,7 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
// setup K-vectors
#define EIR(x, y, z) eir[(x)*numberOfAtoms*3+(y)*3+z]
#define EIR(x, y, z) eir[(x)*numberOfAtoms*3+(y)*3+z]
vector
<
d_complex
>
eir
(
kmax
*
numberOfAtoms
*
3
);
vector
<
d_complex
>
tab_xy
(
numberOfAtoms
);
vector
<
d_complex
>
tab_qxyz
(
numberOfAtoms
);
...
...
@@ -222,15 +308,15 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
for
(
int
i
=
0
;
(
i
<
numberOfAtoms
);
i
++
)
{
float
*
pos
=
posq
+
4
*
i
;
for
(
int
m
=
0
;
(
m
<
3
);
m
++
)
EIR
(
0
,
i
,
m
)
=
d_complex
(
1
,
0
);
EIR
(
0
,
i
,
m
)
=
d_complex
(
1
,
0
);
for
(
int
m
=
0
;
(
m
<
3
);
m
++
)
EIR
(
1
,
i
,
m
)
=
d_complex
(
cos
(
pos
[
m
]
*
recipBoxSize
[
m
]),
sin
(
pos
[
m
]
*
recipBoxSize
[
m
]));
EIR
(
1
,
i
,
m
)
=
d_complex
(
cos
(
pos
[
m
]
*
recipBoxSize
[
m
]),
sin
(
pos
[
m
]
*
recipBoxSize
[
m
]));
for
(
int
j
=
2
;
(
j
<
kmax
);
j
++
)
for
(
int
m
=
0
;
(
m
<
3
);
m
++
)
EIR
(
j
,
i
,
m
)
=
EIR
(
j
-
1
,
i
,
m
)
*
EIR
(
1
,
i
,
m
);
for
(
int
m
=
0
;
(
m
<
3
);
m
++
)
EIR
(
j
,
i
,
m
)
=
EIR
(
j
-
1
,
i
,
m
)
*
EIR
(
1
,
i
,
m
);
}
// calculate reciprocal space energy and forces
...
...
@@ -244,11 +330,11 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
float
ky
=
ry
*
recipBoxSize
[
1
];
if
(
ry
>=
0
)
{
for
(
int
n
=
0
;
n
<
numberOfAtoms
;
n
++
)
tab_xy
[
n
]
=
EIR
(
rx
,
n
,
0
)
*
EIR
(
ry
,
n
,
1
);
tab_xy
[
n
]
=
EIR
(
rx
,
n
,
0
)
*
EIR
(
ry
,
n
,
1
);
}
else
{
for
(
int
n
=
0
;
n
<
numberOfAtoms
;
n
++
)
tab_xy
[
n
]
=
EIR
(
rx
,
n
,
0
)
*
conj
(
EIR
(
-
ry
,
n
,
1
));
tab_xy
[
n
]
=
EIR
(
rx
,
n
,
0
)
*
conj
(
EIR
(
-
ry
,
n
,
1
));
}
for
(
int
rz
=
lowrz
;
rz
<
numRz
;
rz
++
)
{
if
(
rz
>=
0
)
{
...
...
@@ -291,13 +377,14 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
void
CpuNonbondedForce
::
calculateDirectIxn
(
int
numberOfAtoms
,
float
*
posq
,
const
vector
<
RealVec
>&
atomCoordinates
,
const
vector
<
pair
<
float
,
float
>
>&
atomParameters
,
const
vector
<
set
<
int
>
>&
exclusions
,
vector
<
AlignedArray
<
float
>
>&
threadForce
,
double
*
totalEnergy
,
ThreadPool
&
threads
)
{
const
vector
<
float
>&
C6params
,
const
vector
<
set
<
int
>
>&
exclusions
,
vector
<
AlignedArray
<
float
>
>&
threadForce
,
double
*
totalEnergy
,
ThreadPool
&
threads
)
{
// Record the parameters for the threads.
this
->
numberOfAtoms
=
numberOfAtoms
;
this
->
posq
=
posq
;
this
->
atomCoordinates
=
&
atomCoordinates
[
0
];
this
->
atomParameters
=
&
atomParameters
[
0
];
this
->
C6params
=
&
C6params
[
0
];
this
->
exclusions
=
&
exclusions
[
0
];
this
->
threadForce
=
&
threadForce
;
includeEnergy
=
(
totalEnergy
!=
NULL
);
...
...
@@ -339,9 +426,8 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
float
*
forces
=
&
(
*
threadForce
)[
threadIndex
][
0
];
fvec4
boxSize
(
periodicBoxVectors
[
0
][
0
],
periodicBoxVectors
[
1
][
1
],
periodicBoxVectors
[
2
][
2
],
0
);
fvec4
invBoxSize
(
recipBoxSize
[
0
],
recipBoxSize
[
1
],
recipBoxSize
[
2
],
0
);
if
(
ewald
||
pme
)
{
if
(
ewald
||
pme
||
ljpme
)
{
// Compute the interactions from the neighbor list.
while
(
true
)
{
int
nextBlock
=
gmx_atomic_fetch_add
(
reinterpret_cast
<
gmx_atomic_t
*>
(
atomicCounter
),
1
);
if
(
nextBlock
>=
neighborList
->
getNumBlocks
())
...
...
@@ -359,7 +445,7 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
break
;
int
end
=
min
(
start
+
groupSize
,
numberOfAtoms
);
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
fvec4
posI
((
float
)
atomCoordinates
[
i
][
0
],
(
float
)
atomCoordinates
[
i
][
1
],
(
float
)
atomCoordinates
[
i
][
2
],
0.0
f
);
fvec4
posI
((
float
)
atomCoordinates
[
i
][
0
],
(
float
)
atomCoordinates
[
i
][
1
],
(
float
)
atomCoordinates
[
i
][
2
],
0.0
f
);
float
scaledChargeI
=
(
float
)
(
ONE_4PI_EPS0
*
posq
[
4
*
i
+
3
]);
for
(
set
<
int
>::
const_iterator
iter
=
exclusions
[
i
].
begin
();
iter
!=
exclusions
[
i
].
end
();
++
iter
)
{
if
(
*
iter
>
i
)
{
...
...
@@ -383,7 +469,18 @@ void CpuNonbondedForce::threadComputeDirect(ThreadPool& threads, int threadIndex
threadEnergy
[
threadIndex
]
-=
chargeProdOverR
*
erfAlphaR
;
}
else
if
(
includeEnergy
)
threadEnergy
[
threadIndex
]
-=
alphaEwald
*
TWO_OVER_SQRT_PI
*
scaledChargeI
*
posq
[
4
*
j
+
3
];
threadEnergy
[
threadIndex
]
-=
alphaEwald
*
TWO_OVER_SQRT_PI
*
scaledChargeI
*
posq
[
4
*
j
+
3
];
if
(
ljpme
)
{
float
C6ij
=
C6params
[
i
]
*
C6params
[
j
];
float
inverseR2
=
1.0
f
/
r2
;
float
emult
=
C6ij
*
inverseR2
*
inverseR2
*
inverseR2
*
exptermsApprox
(
r
);
if
(
includeEnergy
)
threadEnergy
[
threadIndex
]
+=
emult
;
float
dEdR
=
-
6.0
f
*
C6ij
*
inverseR2
*
inverseR2
*
inverseR2
*
inverseR2
*
dExptermsApprox
(
r
);
fvec4
result
=
deltaR
*
dEdR
;
(
fvec4
(
forces
+
4
*
i
)
-
result
).
store
(
forces
+
4
*
i
);
(
fvec4
(
forces
+
4
*
j
)
+
result
).
store
(
forces
+
4
*
j
);
}
}
}
}
...
...
@@ -433,7 +530,7 @@ void CpuNonbondedForce::calculateOneIxn(int ii, int jj, float* forces, double* t
}
float
sig
=
atomParameters
[
ii
].
first
+
atomParameters
[
jj
].
first
;
float
sig2
=
inverseR
*
sig
;
sig2
*=
sig2
;
sig2
*=
sig2
;
float
sig6
=
sig2
*
sig2
*
sig2
;
float
eps
=
atomParameters
[
ii
].
second
*
atomParameters
[
jj
].
second
;
...
...
@@ -465,7 +562,7 @@ void CpuNonbondedForce::calculateOneIxn(int ii, int jj, float* forces, double* t
fvec4
result
=
deltaR
*
dEdR
;
(
fvec4
(
forces
+
4
*
ii
)
+
result
).
store
(
forces
+
4
*
ii
);
(
fvec4
(
forces
+
4
*
jj
)
-
result
).
store
(
forces
+
4
*
jj
);
}
}
void
CpuNonbondedForce
::
getDeltaR
(
const
fvec4
&
posI
,
const
fvec4
&
posJ
,
fvec4
&
deltaR
,
float
&
r2
,
bool
periodic
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
const
{
deltaR
=
posJ
-
posI
;
...
...
@@ -491,3 +588,18 @@ float CpuNonbondedForce::erfcApprox(float x) {
return
coeff1
*
erfcTable
[
index
]
+
coeff2
*
erfcTable
[
index
+
1
];
}
float
CpuNonbondedForce
::
exptermsApprox
(
float
x
)
{
float
x1
=
x
*
exptermsDXInv
;
int
index
=
min
((
int
)
floor
(
x1
),
NUM_TABLE_POINTS
);
float
coeff2
=
x1
-
index
;
float
coeff1
=
1.0
f
-
coeff2
;
return
coeff1
*
exptermsTable
[
index
]
+
coeff2
*
exptermsTable
[
index
+
1
];
}
float
CpuNonbondedForce
::
dExptermsApprox
(
float
x
)
{
float
x1
=
x
*
exptermsDXInv
;
int
index
=
min
((
int
)
floor
(
x1
),
NUM_TABLE_POINTS
);
float
coeff2
=
x1
-
index
;
float
coeff1
=
1.0
f
-
coeff2
;
return
coeff1
*
dExptermsTable
[
index
]
+
coeff2
*
dExptermsTable
[
index
+
1
];
}
platforms/cpu/src/CpuNonbondedForceVec4.cpp
View file @
53f770f4
...
...
@@ -25,6 +25,7 @@
#include "SimTKOpenMMUtilities.h"
#include "CpuNonbondedForceVec4.h"
#include <algorithm>
#include <iostream>
using
namespace
std
;
using
namespace
OpenMM
;
...
...
@@ -213,7 +214,6 @@ void CpuNonbondedForceVec4::calculateBlockIxnImpl(int blockIndex, float* forces,
void
CpuNonbondedForceVec4
::
calculateBlockEwaldIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Determine whether we need to apply periodic boundary conditions.
PeriodicType
periodicType
;
fvec4
blockCenter
;
if
(
!
periodic
)
{
...
...
@@ -263,7 +263,6 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxn(int blockIndex, float* forces
template
<
int
PERIODIC_TYPE
>
void
CpuNonbondedForceVec4
::
calculateBlockEwaldIxnImpl
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
,
const
fvec4
&
blockCenter
)
{
// Load the positions and parameters of the atoms in the block.
const
int
*
blockAtom
=
&
neighborList
->
getSortedAtoms
()[
4
*
blockIndex
];
fvec4
blockAtomPosq
[
4
];
fvec4
blockAtomForceX
(
0.0
f
),
blockAtomForceY
(
0.0
f
),
blockAtomForceZ
(
0.0
f
);
...
...
@@ -278,9 +277,10 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
fvec4
blockAtomCharge
=
fvec4
(
ONE_4PI_EPS0
)
*
fvec4
(
blockAtomPosq
[
0
][
3
],
blockAtomPosq
[
1
][
3
],
blockAtomPosq
[
2
][
3
],
blockAtomPosq
[
3
][
3
]);
fvec4
blockAtomSigma
(
atomParameters
[
blockAtom
[
0
]].
first
,
atomParameters
[
blockAtom
[
1
]].
first
,
atomParameters
[
blockAtom
[
2
]].
first
,
atomParameters
[
blockAtom
[
3
]].
first
);
fvec4
blockAtomEpsilon
(
atomParameters
[
blockAtom
[
0
]].
second
,
atomParameters
[
blockAtom
[
1
]].
second
,
atomParameters
[
blockAtom
[
2
]].
second
,
atomParameters
[
blockAtom
[
3
]].
second
);
fvec4
C6s
(
C6params
[
blockAtom
[
0
]],
C6params
[
blockAtom
[
1
]],
C6params
[
blockAtom
[
2
]],
C6params
[
blockAtom
[
3
]]);
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
// Loop over neighbors for this block.
const
vector
<
int
>&
neighbors
=
neighborList
->
getBlockNeighbors
(
blockIndex
);
...
...
@@ -318,7 +318,8 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
fvec4
sig2
=
inverseR
*
sig
;
sig2
*=
sig2
;
fvec4
sig6
=
sig2
*
sig2
*
sig2
;
fvec4
epsSig6
=
blockAtomEpsilon
*
atomEpsilon
*
sig6
;
fvec4
eps
=
blockAtomEpsilon
*
atomEpsilon
;
fvec4
epsSig6
=
eps
*
sig6
;
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
if
(
useSwitch
)
{
...
...
@@ -328,6 +329,17 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
dEdR
=
switchValue
*
dEdR
-
energy
*
switchDeriv
*
r
;
energy
*=
switchValue
;
}
if
(
ljpme
)
{
fvec4
C6ij
=
C6s
*
C6params
[
atom
];
fvec4
inverseR2
=
inverseR
*
inverseR
;
fvec4
mysig2
=
sig
*
sig
;
fvec4
mysig6
=
mysig2
*
mysig2
*
mysig2
;
fvec4
emult
=
C6ij
*
inverseR2
*
inverseR2
*
inverseR2
*
exptermsApprox
(
r
);
fvec4
potentialShift
=
eps
*
(
1.0
f
-
mysig6
*
inverseRcut6
)
*
mysig6
*
inverseRcut6
-
C6ij
*
inverseRcut6Expterm
;
dEdR
+=
6.0
f
*
C6ij
*
inverseR2
*
inverseR2
*
inverseR2
*
dExptermsApprox
(
r
);
energy
+=
emult
+
potentialShift
;
}
}
else
{
energy
=
0.0
f
;
...
...
@@ -362,7 +374,7 @@ void CpuNonbondedForceVec4::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
}
// Record the forces on the block atoms.
fvec4
f
[
4
]
=
{
blockAtomForceX
,
blockAtomForceY
,
blockAtomForceZ
,
0.0
f
};
transpose
(
f
[
0
],
f
[
1
],
f
[
2
],
f
[
3
]);
for
(
int
j
=
0
;
j
<
4
;
j
++
)
...
...
@@ -420,3 +432,30 @@ fvec4 CpuNonbondedForceVec4::ewaldScaleFunction(const fvec4& x) {
transpose
(
t1
,
t2
,
t3
,
t4
);
return
coeff1
*
t1
+
coeff2
*
t2
;
}
fvec4
CpuNonbondedForceVec4
::
exptermsApprox
(
const
fvec4
&
r
)
{
fvec4
r1
=
r
*
exptermsDXInv
;
ivec4
index
=
min
(
floor
(
r1
),
NUM_TABLE_POINTS
);
fvec4
coeff2
=
r1
-
index
;
fvec4
coeff1
=
1.0
f
-
coeff2
;
fvec4
t1
(
&
exptermsTable
[
index
[
0
]]);
fvec4
t2
(
&
exptermsTable
[
index
[
1
]]);
fvec4
t3
(
&
exptermsTable
[
index
[
2
]]);
fvec4
t4
(
&
exptermsTable
[
index
[
3
]]);
transpose
(
t1
,
t2
,
t3
,
t4
);
return
coeff1
*
t1
+
coeff2
*
t2
;
}
fvec4
CpuNonbondedForceVec4
::
dExptermsApprox
(
const
fvec4
&
r
)
{
fvec4
r1
=
r
*
exptermsDXInv
;
ivec4
index
=
min
(
floor
(
r1
),
NUM_TABLE_POINTS
);
fvec4
coeff2
=
r1
-
index
;
fvec4
coeff1
=
1.0
f
-
coeff2
;
fvec4
t1
(
&
dExptermsTable
[
index
[
0
]]);
fvec4
t2
(
&
dExptermsTable
[
index
[
1
]]);
fvec4
t3
(
&
dExptermsTable
[
index
[
2
]]);
fvec4
t4
(
&
dExptermsTable
[
index
[
3
]]);
transpose
(
t1
,
t2
,
t3
,
t4
);
return
coeff1
*
t1
+
coeff2
*
t2
;
}
platforms/cpu/src/CpuNonbondedForceVec8.cpp
View file @
53f770f4
...
...
@@ -27,6 +27,7 @@
#include "openmm/OpenMMException.h"
#include "openmm/internal/hardware.h"
#include <algorithm>
#include <iostream>
using
namespace
std
;
using
namespace
OpenMM
;
...
...
@@ -80,8 +81,7 @@ CpuNonbondedForceVec8::CpuNonbondedForceVec8() {
enum
PeriodicType
{
NoPeriodic
,
PeriodicPerAtom
,
PeriodicPerInteraction
,
PeriodicTriclinic
};
void
CpuNonbondedForceVec8
::
calculateBlockIxn
(
int
blockIndex
,
float
*
forces
,
double
*
totalEnergy
,
const
fvec4
&
boxSize
,
const
fvec4
&
invBoxSize
)
{
// Determine whether we need to apply periodic boundary conditions.
// Determine whether we need to apply periodic boundary conditions.
PeriodicType
periodicType
;
fvec4
blockCenter
;
if
(
!
periodic
)
{
...
...
@@ -308,6 +308,7 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
blockAtomCharge
*=
ONE_4PI_EPS0
;
fvec8
blockAtomSigma
(
atomParameters
[
blockAtom
[
0
]].
first
,
atomParameters
[
blockAtom
[
1
]].
first
,
atomParameters
[
blockAtom
[
2
]].
first
,
atomParameters
[
blockAtom
[
3
]].
first
,
atomParameters
[
blockAtom
[
4
]].
first
,
atomParameters
[
blockAtom
[
5
]].
first
,
atomParameters
[
blockAtom
[
6
]].
first
,
atomParameters
[
blockAtom
[
7
]].
first
);
fvec8
blockAtomEpsilon
(
atomParameters
[
blockAtom
[
0
]].
second
,
atomParameters
[
blockAtom
[
1
]].
second
,
atomParameters
[
blockAtom
[
2
]].
second
,
atomParameters
[
blockAtom
[
3
]].
second
,
atomParameters
[
blockAtom
[
4
]].
second
,
atomParameters
[
blockAtom
[
5
]].
second
,
atomParameters
[
blockAtom
[
6
]].
second
,
atomParameters
[
blockAtom
[
7
]].
second
);
fvec8
C6s
(
C6params
[
blockAtom
[
0
]],
C6params
[
blockAtom
[
1
]],
C6params
[
blockAtom
[
2
]],
C6params
[
blockAtom
[
3
]],
C6params
[
blockAtom
[
4
]],
C6params
[
blockAtom
[
5
]],
C6params
[
blockAtom
[
6
]],
C6params
[
blockAtom
[
7
]]);
const
bool
needPeriodic
=
(
PERIODIC_TYPE
==
PeriodicPerInteraction
||
PERIODIC_TYPE
==
PeriodicTriclinic
);
const
float
invSwitchingInterval
=
1
/
(
cutoffDistance
-
switchingDistance
);
...
...
@@ -348,7 +349,8 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
fvec8
sig2
=
inverseR
*
sig
;
sig2
*=
sig2
;
fvec8
sig6
=
sig2
*
sig2
*
sig2
;
fvec8
epsSig6
=
blockAtomEpsilon
*
atomEpsilon
*
sig6
;
fvec8
eps
=
blockAtomEpsilon
*
atomEpsilon
;
fvec8
epsSig6
=
eps
*
sig6
;
dEdR
=
epsSig6
*
(
12.0
f
*
sig6
-
6.0
f
);
energy
=
epsSig6
*
(
sig6
-
1.0
f
);
if
(
useSwitch
)
{
...
...
@@ -358,6 +360,17 @@ void CpuNonbondedForceVec8::calculateBlockEwaldIxnImpl(int blockIndex, float* fo
dEdR
=
switchValue
*
dEdR
-
energy
*
switchDeriv
*
r
;
energy
*=
switchValue
;
}
if
(
ljpme
)
{
fvec8
C6ij
=
C6s
*
C6params
[
atom
];
fvec8
inverseR2
=
inverseR
*
inverseR
;
fvec8
mysig2
=
sig
*
sig
;
fvec8
mysig6
=
mysig2
*
mysig2
*
mysig2
;
fvec8
emult
=
C6ij
*
inverseR2
*
inverseR2
*
inverseR2
*
exptermsApprox
(
r
);
fvec8
potentialShift
=
eps
*
(
1.0
f
-
mysig6
*
inverseRcut6
)
*
mysig6
*
inverseRcut6
-
C6ij
*
inverseRcut6Expterm
;
dEdR
+=
6.0
f
*
C6ij
*
inverseR2
*
inverseR2
*
inverseR2
*
dExptermsApprox
(
r
);
energy
+=
emult
+
potentialShift
;
}
}
else
{
energy
=
0.0
f
;
...
...
@@ -464,4 +477,45 @@ fvec8 CpuNonbondedForceVec8::ewaldScaleFunction(const fvec8& x) {
transpose
(
t1
,
t2
,
t3
,
t4
,
t5
,
t6
,
t7
,
t8
,
s1
,
s2
,
s3
,
s4
);
return
coeff1
*
s1
+
coeff2
*
s2
;
}
fvec8
CpuNonbondedForceVec8
::
exptermsApprox
(
const
fvec8
&
r
)
{
fvec8
r1
=
r
*
exptermsDXInv
;
ivec8
index
=
min
(
floor
(
r1
),
NUM_TABLE_POINTS
);
fvec8
coeff2
=
r1
-
index
;
fvec8
coeff1
=
1.0
f
-
coeff2
;
ivec4
indexLower
=
index
.
lowerVec
();
ivec4
indexUpper
=
index
.
upperVec
();
fvec4
t1
(
&
exptermsTable
[
indexLower
[
0
]]);
fvec4
t2
(
&
exptermsTable
[
indexLower
[
1
]]);
fvec4
t3
(
&
exptermsTable
[
indexLower
[
2
]]);
fvec4
t4
(
&
exptermsTable
[
indexLower
[
3
]]);
fvec4
t5
(
&
exptermsTable
[
indexUpper
[
0
]]);
fvec4
t6
(
&
exptermsTable
[
indexUpper
[
1
]]);
fvec4
t7
(
&
exptermsTable
[
indexUpper
[
2
]]);
fvec4
t8
(
&
exptermsTable
[
indexUpper
[
3
]]);
fvec8
s1
,
s2
,
s3
,
s4
;
transpose
(
t1
,
t2
,
t3
,
t4
,
t5
,
t6
,
t7
,
t8
,
s1
,
s2
,
s3
,
s4
);
return
coeff1
*
s1
+
coeff2
*
s2
;
}
fvec8
CpuNonbondedForceVec8
::
dExptermsApprox
(
const
fvec8
&
r
)
{
fvec8
r1
=
r
*
exptermsDXInv
;
ivec8
index
=
min
(
floor
(
r1
),
NUM_TABLE_POINTS
);
fvec8
coeff2
=
r1
-
index
;
fvec8
coeff1
=
1.0
f
-
coeff2
;
ivec4
indexLower
=
index
.
lowerVec
();
ivec4
indexUpper
=
index
.
upperVec
();
fvec4
t1
(
&
dExptermsTable
[
indexLower
[
0
]]);
fvec4
t2
(
&
dExptermsTable
[
indexLower
[
1
]]);
fvec4
t3
(
&
dExptermsTable
[
indexLower
[
2
]]);
fvec4
t4
(
&
dExptermsTable
[
indexLower
[
3
]]);
fvec4
t5
(
&
dExptermsTable
[
indexUpper
[
0
]]);
fvec4
t6
(
&
dExptermsTable
[
indexUpper
[
1
]]);
fvec4
t7
(
&
dExptermsTable
[
indexUpper
[
2
]]);
fvec4
t8
(
&
dExptermsTable
[
indexUpper
[
3
]]);
fvec8
s1
,
s2
,
s3
,
s4
;
transpose
(
t1
,
t2
,
t3
,
t4
,
t5
,
t6
,
t7
,
t8
,
s1
,
s2
,
s3
,
s4
);
return
coeff1
*
s1
+
coeff2
*
s2
;
}
#endif
platforms/cpu/tests/TestCpuDispersionPME.cpp
0 → 100644
View file @
53f770f4
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2017 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "CpuTests.h"
#include "TestDispersionPME.h"
void
runPlatformTests
()
{
}
platforms/cuda/include/CudaKernels.h
View file @
53f770f4
...
...
@@ -614,7 +614,8 @@ class CudaCalcNonbondedForceKernel : public CalcNonbondedForceKernel {
public:
CudaCalcNonbondedForceKernel
(
std
::
string
name
,
const
Platform
&
platform
,
CudaContext
&
cu
,
const
System
&
system
)
:
CalcNonbondedForceKernel
(
name
,
platform
),
cu
(
cu
),
hasInitializedFFT
(
false
),
sigmaEpsilon
(
NULL
),
exceptionParams
(
NULL
),
cosSinSums
(
NULL
),
directPmeGrid
(
NULL
),
reciprocalPmeGrid
(
NULL
),
pmeBsplineModuliX
(
NULL
),
pmeBsplineModuliY
(
NULL
),
pmeBsplineModuliZ
(
NULL
),
pmeAtomRange
(
NULL
),
pmeAtomGridIndex
(
NULL
),
pmeEnergyBuffer
(
NULL
),
sort
(
NULL
),
fft
(
NULL
),
pmeio
(
NULL
)
{
pmeBsplineModuliX
(
NULL
),
pmeBsplineModuliY
(
NULL
),
pmeBsplineModuliZ
(
NULL
),
pmeDispersionBsplineModuliX
(
NULL
),
pmeDispersionBsplineModuliY
(
NULL
),
pmeDispersionBsplineModuliZ
(
NULL
),
pmeAtomRange
(
NULL
),
pmeAtomGridIndex
(
NULL
),
pmeEnergyBuffer
(
NULL
),
sort
(
NULL
),
dispersionFft
(
NULL
),
fft
(
NULL
),
pmeio
(
NULL
)
{
}
~
CudaCalcNonbondedForceKernel
();
/**
...
...
@@ -651,6 +652,15 @@ public:
* @param nz the number of grid points along the Z axis
*/
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Get the dispersion parameters being used for the dispersion term in LJPME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
private:
class
SortTrait
:
public
CudaSort
::
SortTrait
{
int
getDataSize
()
const
{
return
8
;}
...
...
@@ -679,6 +689,9 @@ private:
CudaArray
*
pmeBsplineModuliX
;
CudaArray
*
pmeBsplineModuliY
;
CudaArray
*
pmeBsplineModuliZ
;
CudaArray
*
pmeDispersionBsplineModuliX
;
CudaArray
*
pmeDispersionBsplineModuliY
;
CudaArray
*
pmeDispersionBsplineModuliZ
;
CudaArray
*
pmeAtomRange
;
CudaArray
*
pmeAtomGridIndex
;
CudaArray
*
pmeEnergyBuffer
;
...
...
@@ -690,20 +703,29 @@ private:
CudaFFT3D
*
fft
;
cufftHandle
fftForward
;
cufftHandle
fftBackward
;
CudaFFT3D
*
dispersionFft
;
cufftHandle
dispersionFftForward
;
cufftHandle
dispersionFftBackward
;
CUfunction
ewaldSumsKernel
;
CUfunction
ewaldForcesKernel
;
CUfunction
pmeGridIndexKernel
;
CUfunction
pmeDispersionGridIndexKernel
;
CUfunction
pmeSpreadChargeKernel
;
CUfunction
pmeDispersionSpreadChargeKernel
;
CUfunction
pmeFinishSpreadChargeKernel
;
CUfunction
pmeDispersionFinishSpreadChargeKernel
;
CUfunction
pmeEvalEnergyKernel
;
CUfunction
pmeEvalDispersionEnergyKernel
;
CUfunction
pmeConvolutionKernel
;
CUfunction
pmeDispersionConvolutionKernel
;
CUfunction
pmeInterpolateForceKernel
;
std
::
map
<
std
::
string
,
std
::
string
>
pmeDefi
ne
s
;
CUfunction
pmeInterpolateDispersionForceKer
ne
l
;
std
::
vector
<
std
::
pair
<
int
,
int
>
>
exceptionAtoms
;
double
ewaldSelfEnergy
,
dispersionCoefficient
,
alpha
;
double
ewaldSelfEnergy
,
dispersionCoefficient
,
alpha
,
dispersionAlpha
;
int
interpolateForceThreads
;
int
gridSizeX
,
gridSizeY
,
gridSizeZ
;
bool
hasCoulomb
,
hasLJ
,
usePmeStream
,
useCudaFFT
;
int
dispersionGridSizeX
,
dispersionGridSizeY
,
dispersionGridSizeZ
;
bool
hasCoulomb
,
hasLJ
,
usePmeStream
,
useCudaFFT
,
doLJPME
;
NonbondedMethod
nonbondedMethod
;
static
const
int
PmeOrder
=
5
;
};
...
...
platforms/cuda/include/CudaParallelKernels.h
View file @
53f770f4
...
...
@@ -439,6 +439,15 @@ public:
* @param nz the number of grid points along the Z axis
*/
void
getPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
/**
* Get the dispersion parameters being used for the dispersion term in LJPME.
*
* @param alpha the separation parameter
* @param nx the number of grid points along the X axis
* @param ny the number of grid points along the Y axis
* @param nz the number of grid points along the Z axis
*/
void
getLJPMEParameters
(
double
&
alpha
,
int
&
nx
,
int
&
ny
,
int
&
nz
)
const
;
private:
class
Task
;
CudaPlatform
::
PlatformData
&
data
;
...
...
platforms/cuda/src/CudaKernels.cpp
View file @
53f770f4
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
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