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
74912095
Unverified
Commit
74912095
authored
Nov 11, 2025
by
Peter Eastman
Committed by
GitHub
Nov 11, 2025
Browse files
Refactor reference PME (#5131)
parent
c24c619e
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
413 additions
and
766 deletions
+413
-766
platforms/cpu/src/CpuNonbondedForce.cpp
platforms/cpu/src/CpuNonbondedForce.cpp
+5
-9
platforms/reference/include/ReferenceConstantPotential.h
platforms/reference/include/ReferenceConstantPotential.h
+10
-10
platforms/reference/include/ReferencePME.h
platforms/reference/include/ReferencePME.h
+101
-85
platforms/reference/src/SimTKReference/ReferenceConstantPotential.cpp
...ference/src/SimTKReference/ReferenceConstantPotential.cpp
+21
-35
platforms/reference/src/SimTKReference/ReferenceLJCoulombIxn.cpp
...ms/reference/src/SimTKReference/ReferenceLJCoulombIxn.cpp
+4
-9
platforms/reference/src/SimTKReference/ReferencePME.cpp
platforms/reference/src/SimTKReference/ReferencePME.cpp
+261
-600
platforms/reference/tests/TestReferenceEwald.cpp
platforms/reference/tests/TestReferenceEwald.cpp
+7
-10
plugins/amoeba/platforms/reference/src/SimTKReference/AmoebaReferenceHippoNonbondedForce.cpp
...src/SimTKReference/AmoebaReferenceHippoNonbondedForce.cpp
+2
-4
plugins/cpupme/tests/TestCpuPme.cpp
plugins/cpupme/tests/TestCpuPme.cpp
+2
-4
No files found.
platforms/cpu/src/CpuNonbondedForce.cpp
View file @
74912095
...
...
@@ -255,28 +255,26 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
float
recipCoeff
=
(
float
)(
ONE_4PI_EPS0
*
4
*
PI_M
/
(
periodicBoxVectors
[
0
][
0
]
*
periodicBoxVectors
[
1
][
1
]
*
periodicBoxVectors
[
2
][
2
])
/
epsilon
);
if
(
pme
)
{
pme_t
pmedata
;
pme_init
(
&
pmedata
,
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
ReferencePME
pme
(
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
vector
<
double
>
charges
(
numberOfAtoms
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
charges
[
i
]
=
posq
[
4
*
i
+
3
];
double
recipEnergy
=
0.0
;
pme
_
exec
(
pmedata
,
atomCoordinates
,
forces
,
charges
,
periodicBoxVectors
,
&
recipEnergy
);
pme
.
exec
(
atomCoordinates
,
forces
,
charges
,
periodicBoxVectors
,
recipEnergy
);
if
(
totalEnergy
)
*
totalEnergy
+=
recipEnergy
;
pme_destroy
(
pmedata
);
if
(
ljpme
)
{
// Dispersion reciprocal space terms
pme_init
(
&
pmedata
,
alphaDispersionEwald
,
numberOfAtoms
,
dispersionMeshDim
,
5
,
1
);
ReferencePME
ljpme
(
alphaDispersionEwald
,
numberOfAtoms
,
dispersionMeshDim
,
5
,
1
);
std
::
vector
<
Vec3
>
dpmeforces
;
vector
<
Vec3
>
dpmeforces
;
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
){
charges
[
i
]
=
C6params
[
i
];
dpmeforces
.
push_back
(
Vec3
());
}
double
recipDispersionEnergy
=
0.0
;
pme
_
exec_dpme
(
pmedata
,
atomCoordinates
,
dpmeforces
,
charges
,
periodicBoxVectors
,
&
recipDispersionEnergy
);
lj
pme
.
exec_dpme
(
atomCoordinates
,
dpmeforces
,
charges
,
periodicBoxVectors
,
recipDispersionEnergy
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
){
forces
[
i
][
0
]
+=
dpmeforces
[
i
][
0
];
forces
[
i
][
1
]
+=
dpmeforces
[
i
][
1
];
...
...
@@ -284,8 +282,6 @@ void CpuNonbondedForce::calculateReciprocalIxn(int numberOfAtoms, float* posq, c
}
if
(
totalEnergy
)
*
totalEnergy
+=
recipDispersionEnergy
;
pme_destroy
(
pmedata
);
}
}
...
...
platforms/reference/include/ReferenceConstantPotential.h
View file @
74912095
...
...
@@ -90,14 +90,14 @@ public:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param conp constant potential derivative evaluation class
* @param pme
Data
reference PME solver
* @param pme
reference PME solver
*/
virtual
void
solve
(
int
numParticles
,
int
numElectrodeParticles
,
const
std
::
vector
<
Vec3
>&
posData
,
std
::
vector
<
double
>&
charges
,
const
std
::
vector
<
std
::
set
<
int
>>&
exclusions
,
const
std
::
vector
<
int
>&
sysToElec
,
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
ReferenceConstantPotential
&
conp
,
pme_t
pmeData
)
=
0
;
ReferenceConstantPotential
&
conp
,
ReferencePME
&
pme
)
=
0
;
};
/**
...
...
@@ -149,14 +149,14 @@ public:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param conp constant potential derivative evaluation class
* @param pme
Data
reference PME solver
* @param pme
reference PME solver
*/
void
solve
(
int
numParticles
,
int
numElectrodeParticles
,
const
std
::
vector
<
Vec3
>&
posData
,
std
::
vector
<
double
>&
charges
,
const
std
::
vector
<
std
::
set
<
int
>>&
exclusions
,
const
std
::
vector
<
int
>&
sysToElec
,
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
ReferenceConstantPotential
&
conp
,
pme_t
pmeData
);
ReferenceConstantPotential
&
conp
,
ReferencePME
&
pme
);
};
/**
...
...
@@ -208,14 +208,14 @@ public:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param conp constant potential derivative evaluation class
* @param pme
Data
reference PME solver
* @param pme
reference PME solver
*/
void
solve
(
int
numParticles
,
int
numElectrodeParticles
,
const
std
::
vector
<
Vec3
>&
posData
,
std
::
vector
<
double
>&
charges
,
const
std
::
vector
<
std
::
set
<
int
>>&
exclusions
,
const
std
::
vector
<
int
>&
sysToElec
,
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
ReferenceConstantPotential
&
conp
,
pme_t
pmeData
);
ReferenceConstantPotential
&
conp
,
ReferencePME
&
pme
);
};
/**
...
...
@@ -313,7 +313,7 @@ private:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param energy output system energy
* @param pme
Data
reference PME solver
* @param pme
reference PME solver
*/
void
getEnergyForces
(
int
numParticles
,
int
numElectrodeParticles
,
const
std
::
vector
<
Vec3
>&
posData
,
std
::
vector
<
Vec3
>&
forceData
,
...
...
@@ -321,7 +321,7 @@ private:
const
std
::
vector
<
std
::
set
<
int
>>&
exclusions
,
const
std
::
vector
<
int
>&
sysToElec
,
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
double
*
energy
,
pme_t
pmeData
);
double
*
energy
,
ReferencePME
&
pme
);
/**
* Computes energy derivatives with respect to charges.
*
...
...
@@ -334,14 +334,14 @@ private:
* @param elecToSys mapping from electrode particle indices to system particle indices
* @param electrodeParamArray electrode particle parameters
* @param chargeDerivatives output charge derivatives
* @param pme
Data
reference PME solver
* @param pme
reference PME solver
*/
void
getDerivatives
(
int
numParticles
,
int
numElectrodeParticles
,
const
std
::
vector
<
Vec3
>&
posData
,
std
::
vector
<
double
>&
charges
,
const
std
::
vector
<
std
::
set
<
int
>>&
exclusions
,
const
std
::
vector
<
int
>&
sysToElec
,
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
std
::
vector
<
double
>&
chargeDerivatives
,
pme_t
pmeData
);
std
::
vector
<
double
>&
chargeDerivatives
,
ReferencePME
&
pme
);
};
}
// namespace OpenMM
...
...
platforms/reference/include/ReferencePME.h
View file @
74912095
/*
* Reference implementation of PME reciprocal space interactions.
*
* Copyright (c) 2009
,
Erik Lindahl, Rossen Apostolov, Szilard Pall
* Copyright (c) 2009
-2025
Erik Lindahl, Rossen Apostolov, Szilard Pall
, Peter Eastman
* All rights reserved.
* Contact: lindahl@cbr.su.se Stockholm University, Sweden.
*
...
...
@@ -34,22 +34,19 @@
#include "openmm/Vec3.h"
#include "openmm/internal/windowsExport.h"
#include <array>
#include <complex>
#include <vector>
namespace
OpenMM
{
typedef
double
rvec
[
3
];
typedef
struct
pme
*
pme_t
;
/*
class
OPENMM_EXPORT
ReferencePME
{
public:
/*
* Initialize a PME calculation and set up data structures
*
* Arguments:
*
* ppme Pointer to an opaque pme_t object
* ewaldcoeff Coefficient derived from the beta factor to participate
* direct/reciprocal space. See gromacs code for documentation!
* We assume that you are using nm units...
...
...
@@ -58,77 +55,96 @@ pme_t;
* pme_order Interpolation order, almost always 4
* epsilon_r Dielectric coefficient, typically 1.0.
*/
int
OPENMM_EXPORT
pme_init
(
pme_t
*
ppme
,
double
ewaldcoeff
,
int
natoms
,
const
int
ngrid
[
3
],
int
pme_order
,
double
epsilon_r
);
ReferencePME
(
double
ewaldcoeff
,
int
natoms
,
const
int
ngrid
[
3
],
int
pme_order
,
double
epsilon_r
);
/*
/*
* Evaluate reciprocal space PME energy and forces.
*
* Args:
*
* pme Opaque pme_t object, must have been initialized with pme_init()
* atomCoordinates Pointer to coordinate data array (nm)
* forces Pointer to force data array (will be written as kJ/mol/nm)
* charges Array of charges (units of e)
* periodicBoxVectors Simulation cell dimensions (nm)
* energy Total energy (will be written in units of kJ/mol)
*/
int
OPENMM_EXPORT
pme_exec
(
pme_t
pme
,
const
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
const
std
::
vector
<
double
>&
charges
,
const
OpenMM
::
Vec3
periodicBoxVectors
[
3
],
double
*
energy
);
void
exec
(
const
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
const
std
::
vector
<
double
>&
charges
,
const
OpenMM
::
Vec3
periodicBoxVectors
[
3
],
double
&
energy
);
/*
/*
* Evaluate reciprocal space PME energy and charge derivatives.
*
* Args:
*
* pme Opaque pme_t object, must have been initialized with pme_init()
* atomCoordinates Pointer to coordinate data array (nm)
* chargeDerivatives Pointer to charge derivative data array (will be written as kJ/mol/e)
* chargeIndices Pointer to array of indices of particles to compute charge derivatives for
* charges Array of charges (units of e)
* periodicBoxVectors Simulation cell dimensions (nm)
*/
int
OPENMM_EXPORT
pme_exec_charge_derivatives
(
pme_t
pme
,
const
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
double
>&
chargeDerivatives
,
const
std
::
vector
<
int
>&
chargeIndices
,
const
std
::
vector
<
double
>&
charges
,
const
OpenMM
::
Vec3
periodicBoxVectors
[
3
]);
void
exec_charge_derivatives
(
const
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
double
>&
chargeDerivatives
,
const
std
::
vector
<
int
>&
chargeIndices
,
const
std
::
vector
<
double
>&
charges
,
const
OpenMM
::
Vec3
periodicBoxVectors
[
3
]);
/**
/**
* Evaluate reciprocal space PME dispersion energy and forces.
*
* Args:
*
* pme Opaque pme_t object, must have been initialized with pme_init()
* atomCoordinates Pointer to coordinate data array (nm)
* forces Pointer to force data array (will be written as kJ/mol/nm)
* c6s Array of c6 coefficients (units of sqrt(kJ/mol).nm^3 )
* periodicBoxVectors Simulation cell dimensions (nm)
* energy Total energy (will be written in units of kJ/mol)
*/
int
OPENMM_EXPORT
pme_exec_dpme
(
pme_t
pme
,
const
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
const
std
::
vector
<
double
>&
c6s
,
const
OpenMM
::
Vec3
periodicBoxVectors
[
3
],
double
*
energy
);
void
exec_dpme
(
const
std
::
vector
<
OpenMM
::
Vec3
>&
atomCoordinates
,
std
::
vector
<
OpenMM
::
Vec3
>&
forces
,
const
std
::
vector
<
double
>&
c6s
,
const
OpenMM
::
Vec3
periodicBoxVectors
[
3
],
double
&
energy
);
private:
void
calculate_bsplines_moduli
();
void
update_grid_index_and_fraction
(
const
std
::
vector
<
Vec3
>&
atomCoordinates
,
const
Vec3
recipBoxVectors
[
3
]);
void
update_bsplines
();
void
grid_spread_charge
(
const
std
::
vector
<
double
>&
charges
);
void
pme_reciprocal_convolution
(
const
Vec3
periodicBoxVectors
[
3
],
const
Vec3
recipBoxVectors
[
3
],
double
&
energy
);
void
dpme_reciprocal_convolution
(
const
Vec3
periodicBoxVectors
[
3
],
const
Vec3
recipBoxVectors
[
3
],
double
&
energy
);
void
grid_interpolate_force
(
const
Vec3
recipBoxVectors
[
3
],
const
std
::
vector
<
double
>&
charges
,
std
::
vector
<
Vec3
>&
forces
);
void
grid_interpolate_charge_derivatives
(
const
Vec3
recipBoxVectors
[
3
],
const
std
::
vector
<
double
>&
charges
,
std
::
vector
<
double
>&
chargeDerivatives
,
const
std
::
vector
<
int
>&
chargeIndices
);
int
natoms
;
double
ewaldcoeff
;
std
::
vector
<
std
::
complex
<
double
>
>
grid
;
/* Memory for the grid we spread charges on.
* Element (i,j,k) is accessed as:
* grid[i*ngrid[1]*ngrid[2] + j*ngrid[2] + k] */
int
ngrid
[
3
];
/* Total grid dimensions (all data is complex!) */
int
order
;
/* PME interpolation order. Almost always 4 */
/* Data for bspline interpolation, see the Essman PME paper */
std
::
vector
<
double
>
bsplines_moduli
[
3
];
/* 3 pointers, to x/y/z bspline moduli, each of length ngrid[x/y/z] */
std
::
vector
<
double
>
bsplines_theta
[
3
];
/* each of x/y/z has length order*natoms */
std
::
vector
<
double
>
bsplines_dtheta
[
3
];
/* each of x/y/z has length order*natoms */
std
::
vector
<
std
::
array
<
int
,
3
>
>
particleindex
;
/* Array of length natoms. Each element is
* three ints that specify the grid
* indices for that particular atom. Updated every step! */
std
::
vector
<
Vec3
>
particlefraction
;
/* Array of length natoms. Fractional offset in the grid for
* each atom in all three dimensions. */
/* Further explanation of index/fraction:
*
* Assume we have a cell of size 10*10*10nm, and a total grid dimension of 100*100*100 cells.
* In other words, each cell is 0.1*0.1*0.1 nm.
*
* If particle i has coordinates { 0.543 , 6.235 , -0.73 }, we will get:
*
* particleindex[i] = { 5 , 62 , 92 } (-0.73 + 10 = 9.27, we always apply PBC for grid calculations!)
* particlefraction[i] = { 0.43 , 0.35 , 0.7 } (this is the fraction of the cell length where the atom is)
*
* (The reason for precaculating / storing these is that it gets a bit more complex for triclinic cells :-)
*
* In the current code version we might assume that a particle is not more than a whole box length away from
* the central cell, i.e., in this case we would assume all coordinates fall in -10 nm < x,y,z < 20 nm.
*/
/* Release all memory in pme structure */
int
OPENMM_EXPORT
pme_destroy
(
pme_t
pme
);
double
epsilon_r
;
/* Dielectric coefficient to use, typically 1.0 */
};
}
// namespace OpenMM
...
...
platforms/reference/src/SimTKReference/ReferenceConstantPotential.cpp
View file @
74912095
...
...
@@ -29,7 +29,6 @@
#include "ReferenceConstantPotential.h"
#include "ReferenceForce.h"
#include "ReferencePME.h"
#include "SimTKOpenMMUtilities.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/MSVC_erfc.h"
...
...
@@ -97,22 +96,21 @@ void ReferenceConstantPotentialMatrixSolver::update(
std
::
vector
<
double
>
dUdQ0
(
numElectrodeParticles
);
std
::
vector
<
double
>
dUdQ
(
numElectrodeParticles
);
pme_t
pmeData
;
pme_init
(
&
pmeData
,
conp
.
ewaldAlpha
,
numParticles
,
conp
.
gridSize
,
5
,
1
);
ReferencePME
pme
(
conp
.
ewaldAlpha
,
numParticles
,
conp
.
gridSize
,
5
,
1
);
// Get derivatives when all electrode charges are zeroed.
std
::
vector
<
double
>
q
(
charges
);
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
q
[
elecToSys
[
ii
]]
=
0.0
;
}
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
q
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
dUdQ0
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
q
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
dUdQ0
,
pme
);
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
int
i
=
elecToSys
[
ii
];
// Get derivatives when one electrode charge is set.
q
[
i
]
=
1.0
;
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
q
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
dUdQ
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
q
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
dUdQ
,
pme
);
q
[
i
]
=
0.0
;
// Set matrix elements, subtracting zero charge derivatives so that the
...
...
@@ -123,8 +121,6 @@ void ReferenceConstantPotentialMatrixSolver::update(
A
[
ii
][
ii
]
=
dUdQ
[
ii
]
-
dUdQ0
[
ii
];
}
pme_destroy
(
pmeData
);
// Compute Cholesky decomposition representation of the inverse.
capacitance
=
JAMA
::
Cholesky
<
double
>
(
A
);
if
(
!
capacitance
.
is_spd
())
{
...
...
@@ -162,7 +158,7 @@ void ReferenceConstantPotentialMatrixSolver::solve(
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
ReferenceConstantPotential
&
conp
,
pme_t
pmeData
ReferencePME
&
pme
)
{
// Solves for charges using the matrix method.
...
...
@@ -171,7 +167,7 @@ void ReferenceConstantPotentialMatrixSolver::solve(
charges
[
elecToSys
[
ii
]]
=
0.0
;
}
std
::
vector
<
double
>
b
(
numElectrodeParticles
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
b
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
b
,
pme
);
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
b
[
ii
]
=
-
b
[
ii
];
}
...
...
@@ -236,14 +232,12 @@ void ReferenceConstantPotentialCGSolver::update(
// calculation. This will actually vary slightly with position but only due
// to finite accuracy of the PME splines, so it is fine to assume it will be
// constant for the preconditioner.
pme_t
pmeData
;
pme_init
(
&
pmeData
,
conp
.
ewaldAlpha
,
1
,
conp
.
gridSize
,
5
,
1
);
ReferencePME
pme
(
conp
.
ewaldAlpha
,
1
,
conp
.
gridSize
,
5
,
1
);
std
::
vector
<
Vec3
>
pmePosData
(
1
);
std
::
vector
<
double
>
pmeChargeDerivatives
(
1
);
std
::
vector
<
int
>
pmeElectrodeIndices
(
1
);
std
::
vector
<
double
>
pmeCharges
(
1
,
1.0
);
pme_exec_charge_derivatives
(
pmeData
,
pmePosData
,
pmeChargeDerivatives
,
pmeElectrodeIndices
,
pmeCharges
,
boxVectors
);
pme_destroy
(
pmeData
);
pme
.
exec_charge_derivatives
(
pmePosData
,
pmeChargeDerivatives
,
pmeElectrodeIndices
,
pmeCharges
,
boxVectors
);
// The diagonal has a contribution from reciprocal space, Ewald
// self-interaction, Ewald neutralizing plasma, Gaussian self-interaction,
...
...
@@ -274,7 +268,7 @@ void ReferenceConstantPotentialCGSolver::solve(
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
ReferenceConstantPotential
&
conp
,
pme_t
pmeData
ReferencePME
&
pme
)
{
// Solves for charges using the conjugate gradient method.
...
...
@@ -302,7 +296,7 @@ void ReferenceConstantPotentialCGSolver::solve(
}
// Evaluate the initial gradient Aq - b.
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
grad
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
grad
,
pme
);
// Project the initial gradient without preconditioning.
offset
=
0.0
;
...
...
@@ -332,7 +326,7 @@ void ReferenceConstantPotentialCGSolver::solve(
q
[
ii
]
=
charges
[
i
];
charges
[
i
]
=
0.0
;
}
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
grad0
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
grad0
,
pme
);
// Project the initial gradient with preconditioning.
if
(
precond
)
{
...
...
@@ -362,7 +356,7 @@ void ReferenceConstantPotentialCGSolver::solve(
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
charges
[
elecToSys
[
ii
]]
=
qStep
[
ii
];
}
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
gradStep
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
gradStep
,
pme
);
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
gradStep
[
ii
]
-=
grad0
[
ii
];
}
...
...
@@ -417,7 +411,7 @@ void ReferenceConstantPotentialCGSolver::solve(
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
charges
[
elecToSys
[
ii
]]
=
q
[
ii
];
}
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
grad
,
pme
Data
);
conp
.
getDerivatives
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
grad
,
pme
);
}
else
{
for
(
int
ii
=
0
;
ii
<
numElectrodeParticles
;
ii
++
)
{
...
...
@@ -542,13 +536,9 @@ void ReferenceConstantPotential::execute(
double
*
energy
,
ReferenceConstantPotentialSolver
*
solver
)
{
pme_t
pmeData
;
pme_init
(
&
pmeData
,
ewaldAlpha
,
numParticles
,
gridSize
,
5
,
1
);
solver
->
solve
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
*
this
,
pmeData
);
getEnergyForces
(
numParticles
,
numElectrodeParticles
,
posData
,
forceData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
energy
,
pmeData
);
pme_destroy
(
pmeData
);
ReferencePME
pme
(
ewaldAlpha
,
numParticles
,
gridSize
,
5
,
1
);
solver
->
solve
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
*
this
,
pme
);
getEnergyForces
(
numParticles
,
numElectrodeParticles
,
posData
,
forceData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
energy
,
pme
);
}
void
ReferenceConstantPotential
::
getCharges
(
...
...
@@ -562,12 +552,8 @@ void ReferenceConstantPotential::getCharges(
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
ReferenceConstantPotentialSolver
*
solver
)
{
pme_t
pmeData
;
pme_init
(
&
pmeData
,
ewaldAlpha
,
numParticles
,
gridSize
,
5
,
1
);
solver
->
solve
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
*
this
,
pmeData
);
pme_destroy
(
pmeData
);
ReferencePME
pme
(
ewaldAlpha
,
numParticles
,
gridSize
,
5
,
1
);
solver
->
solve
(
numParticles
,
numElectrodeParticles
,
posData
,
charges
,
exclusions
,
sysToElec
,
elecToSys
,
electrodeParamArray
,
*
this
,
pme
);
}
void
ReferenceConstantPotential
::
getEnergyForces
(
...
...
@@ -581,7 +567,7 @@ void ReferenceConstantPotential::getEnergyForces(
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
double
*
energy
,
pme_t
pmeData
ReferencePME
&
pme
)
{
const
double
SQRT_PI
=
sqrt
(
PI_M
);
const
double
TWO_OVER_SQRT_PI
=
2.0
/
SQRT_PI
;
...
...
@@ -671,7 +657,7 @@ void ReferenceConstantPotential::getEnergyForces(
// Reciprocal space.
double
pmeEnergy
=
0.0
;
pme
_
exec
(
pmeData
,
posData
,
forceData
,
charges
,
boxVectors
,
&
pmeEnergy
);
pme
.
exec
(
posData
,
forceData
,
charges
,
boxVectors
,
pmeEnergy
);
energyAccum
+=
pmeEnergy
;
// Ewald self-interaction and external field contributions (all particles).
...
...
@@ -710,7 +696,7 @@ void ReferenceConstantPotential::getDerivatives(
const
std
::
vector
<
int
>&
elecToSys
,
const
std
::
vector
<
std
::
array
<
double
,
3
>
>&
electrodeParamArray
,
std
::
vector
<
double
>&
chargeDerivatives
,
pme_t
pmeData
ReferencePME
&
pme
)
{
const
double
SQRT_PI
=
sqrt
(
PI_M
);
const
double
SELF_ALPHA_SCALE
=
2.0
*
ONE_4PI_EPS0
/
SQRT_PI
;
...
...
@@ -757,7 +743,7 @@ void ReferenceConstantPotential::getDerivatives(
}
// Reciprocal space.
pme
_
exec_charge_derivatives
(
pmeData
,
posData
,
chargeDerivatives
,
elecToSys
,
charges
,
boxVectors
);
pme
.
exec_charge_derivatives
(
posData
,
chargeDerivatives
,
elecToSys
,
charges
,
boxVectors
);
// Ewald neutralizing plasma precalculation.
double
qTotal
=
0.0
;
...
...
platforms/reference/src/SimTKReference/ReferenceLJCoulombIxn.cpp
View file @
74912095
...
...
@@ -243,33 +243,28 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<Vec3>& a
// PME
if
(
pme
&&
includeReciprocal
)
{
pme_t
pmedata
;
/* abstract handle for PME data */
pme_init
(
&
pmedata
,
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
ReferencePME
pme
(
alphaEwald
,
numberOfAtoms
,
meshDim
,
5
,
1
);
vector
<
double
>
charges
(
numberOfAtoms
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
charges
[
i
]
=
atomParameters
[
i
][
QIndex
];
pme
_
exec
(
pmedata
,
atomCoordinates
,
forces
,
charges
,
periodicBoxVectors
,
&
recipEnergy
);
pme
.
exec
(
atomCoordinates
,
forces
,
charges
,
periodicBoxVectors
,
recipEnergy
);
if
(
totalEnergy
)
*
totalEnergy
+=
recipEnergy
;
pme_destroy
(
pmedata
);
if
(
ljpme
)
{
// Dispersion reciprocal space terms
pme_init
(
&
pmedata
,
alphaDispersionEwald
,
numberOfAtoms
,
dispersionMeshDim
,
5
,
1
);
ReferencePME
ljpme
(
alphaDispersionEwald
,
numberOfAtoms
,
dispersionMeshDim
,
5
,
1
);
std
::
vector
<
Vec3
>
dpmeforces
(
numberOfAtoms
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
charges
[
i
]
=
8.0
*
pow
(
atomParameters
[
i
][
SigIndex
],
3.0
)
*
atomParameters
[
i
][
EpsIndex
];
pme
_
exec_dpme
(
pmedata
,
atomCoordinates
,
dpmeforces
,
charges
,
periodicBoxVectors
,
&
recipDispersionEnergy
);
lj
pme
.
exec_dpme
(
atomCoordinates
,
dpmeforces
,
charges
,
periodicBoxVectors
,
recipDispersionEnergy
);
for
(
int
i
=
0
;
i
<
numberOfAtoms
;
i
++
)
forces
[
i
]
+=
dpmeforces
[
i
];
if
(
totalEnergy
)
*
totalEnergy
+=
recipDispersionEnergy
;
pme_destroy
(
pmedata
);
}
}
// Ewald method
...
...
platforms/reference/src/SimTKReference/ReferencePME.cpp
View file @
74912095
This diff is collapsed.
Click to expand it.
platforms/reference/tests/TestReferenceEwald.cpp
View file @
74912095
...
...
@@ -59,14 +59,13 @@ void testReferencePmeDerivatives() {
double
ewaldAlpha
=
1.752
;
int
gridSize
[
3
]
=
{
54
,
49
,
43
};
pme_t
pme
;
pme_init
(
&
pme
,
ewaldAlpha
,
numParticles
,
gridSize
,
5
,
1
);
ReferencePME
pme
(
ewaldAlpha
,
numParticles
,
gridSize
,
5
,
1
);
double
dummyEnergy
=
0
;
vector
<
Vec3
>
dummyForces
(
numParticles
);
vector
<
Vec3
>
testForces
(
numParticles
);
pme
_
exec
(
pme
,
positions
,
testForces
,
charges
,
boxVectors
,
&
dummyEnergy
);
pme
.
exec
(
positions
,
testForces
,
charges
,
boxVectors
,
dummyEnergy
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
...
...
@@ -74,11 +73,11 @@ void testReferencePmeDerivatives() {
double
energyLess
=
0.0
;
positions
[
i
][
j
]
=
referencePosition
-
DELTA
;
pme
_
exec
(
pme
,
positions
,
dummyForces
,
charges
,
boxVectors
,
&
energyLess
);
pme
.
exec
(
positions
,
dummyForces
,
charges
,
boxVectors
,
energyLess
);
double
energyMore
=
0.0
;
positions
[
i
][
j
]
=
referencePosition
+
DELTA
;
pme
_
exec
(
pme
,
positions
,
dummyForces
,
charges
,
boxVectors
,
&
energyMore
);
pme
.
exec
(
positions
,
dummyForces
,
charges
,
boxVectors
,
energyMore
);
positions
[
i
][
j
]
=
referencePosition
;
...
...
@@ -87,25 +86,23 @@ void testReferencePmeDerivatives() {
}
vector
<
double
>
testDerivatives
(
numParticles
);
pme
_
exec_charge_derivatives
(
pme
,
positions
,
testDerivatives
,
indices
,
charges
,
boxVectors
);
pme
.
exec_charge_derivatives
(
positions
,
testDerivatives
,
indices
,
charges
,
boxVectors
);
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
double
referenceCharge
=
charges
[
i
];
double
energyLess
=
0.0
;
charges
[
i
]
=
referenceCharge
-
DELTA
;
pme
_
exec
(
pme
,
positions
,
dummyForces
,
charges
,
boxVectors
,
&
energyLess
);
pme
.
exec
(
positions
,
dummyForces
,
charges
,
boxVectors
,
energyLess
);
double
energyMore
=
0.0
;
charges
[
i
]
=
referenceCharge
+
DELTA
;
pme
_
exec
(
pme
,
positions
,
dummyForces
,
charges
,
boxVectors
,
&
energyMore
);
pme
.
exec
(
positions
,
dummyForces
,
charges
,
boxVectors
,
energyMore
);
charges
[
i
]
=
referenceCharge
;
ASSERT_EQUAL_TOL
((
energyMore
-
energyLess
)
/
(
2
*
DELTA
),
testDerivatives
[
i
],
EPSILON
);
}
pme_destroy
(
pme
);
}
void
runPlatformTests
()
{
...
...
plugins/amoeba/platforms/reference/src/SimTKReference/AmoebaReferenceHippoNonbondedForce.cpp
View file @
74912095
...
...
@@ -2873,8 +2873,7 @@ double AmoebaReferencePmeHippoNonbondedForce::calculateDispersionPairIxn(const M
}
double
AmoebaReferencePmeHippoNonbondedForce
::
computeReciprocalSpaceDispersionForceAndEnergy
(
const
vector
<
MultipoleParticleData
>&
particleData
,
vector
<
Vec3
>&
forces
)
const
{
pme_t
pmedata
;
pme_init
(
&
pmedata
,
_dalphaEwald
,
_numParticles
,
_dpmeGridDimensions
,
5
,
1
);
ReferencePME
pme
(
_dalphaEwald
,
_numParticles
,
_dpmeGridDimensions
,
5
,
1
);
vector
<
double
>
charges
(
_numParticles
);
vector
<
Vec3
>
dpmeforces
(
_numParticles
,
Vec3
()),
coords
;
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
{
...
...
@@ -2882,8 +2881,7 @@ double AmoebaReferencePmeHippoNonbondedForce::computeReciprocalSpaceDispersionFo
coords
.
push_back
(
particleData
[
i
].
position
);
}
double
recipDispersionEnergy
;
pme_exec_dpme
(
pmedata
,
coords
,
dpmeforces
,
charges
,
_periodicBoxVectors
,
&
recipDispersionEnergy
);
pme_destroy
(
pmedata
);
pme
.
exec_dpme
(
coords
,
dpmeforces
,
charges
,
_periodicBoxVectors
,
recipDispersionEnergy
);
for
(
int
i
=
0
;
i
<
_numParticles
;
i
++
)
forces
[
i
]
+=
dpmeforces
[
i
];
return
recipDispersionEnergy
;
...
...
plugins/cpupme/tests/TestCpuPme.cpp
View file @
74912095
...
...
@@ -650,12 +650,10 @@ void testPME(bool triclinic, bool nonNeutral) {
// Get charge derivatives from the reference PME implementation.
pme_t
referencePme
;
int
gridSize
[
3
]
=
{
gridx
,
gridy
,
gridz
};
pme_init
(
&
referencePme
,
alpha
,
numParticles
,
gridSize
,
5
,
1
);
ReferencePME
referencePme
(
alpha
,
numParticles
,
gridSize
,
5
,
1
);
vector
<
double
>
testDerivatives
(
numParticles
);
pme_exec_charge_derivatives
(
referencePme
,
positions
,
testDerivatives
,
testIndices
,
testCharges
,
boxVectors
);
pme_destroy
(
referencePme
);
referencePme
.
exec_charge_derivatives
(
positions
,
testDerivatives
,
testIndices
,
testCharges
,
boxVectors
);
// See if they match.
for
(
int
i
=
0
;
i
<
numParticles
;
i
++
)
{
...
...
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