Commit e22b8f53 authored by peastman's avatar peastman
Browse files

PME works correctly in CPU platform

parent 6b10b909
...@@ -44,7 +44,7 @@ namespace OpenMM { ...@@ -44,7 +44,7 @@ namespace OpenMM {
*/ */
class CpuCalcNonbondedForceKernel : public CalcNonbondedForceKernel { class CpuCalcNonbondedForceKernel : public CalcNonbondedForceKernel {
public: public:
CpuCalcNonbondedForceKernel(std::string name, const Platform& platform) : CalcNonbondedForceKernel(name, platform) { CpuCalcNonbondedForceKernel(std::string name, const Platform& platform) : CalcNonbondedForceKernel(name, platform), bonded14IndexArray(NULL), bonded14ParamArray(NULL) {
} }
~CpuCalcNonbondedForceKernel(); ~CpuCalcNonbondedForceKernel();
/** /**
...@@ -75,12 +75,12 @@ public: ...@@ -75,12 +75,12 @@ public:
private: private:
int numParticles, num14; int numParticles, num14;
int **bonded14IndexArray; int **bonded14IndexArray;
float **particleParamArray;
double **bonded14ParamArray; double **bonded14ParamArray;
double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, dispersionCoefficient; double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, ewaldSelfEnergy, dispersionCoefficient;
int kmax[3], gridSize[3]; int kmax[3], gridSize[3];
bool useSwitchingFunction; bool useSwitchingFunction;
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
std::vector<std::pair<float, float> > particleParams;
std::vector<float> posq; std::vector<float> posq;
std::vector<float> forces; std::vector<float> forces;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
......
...@@ -49,30 +49,7 @@ class CpuNonbondedForce { ...@@ -49,30 +49,7 @@ class CpuNonbondedForce {
int numRx, numRy, numRz; int numRx, numRy, numRz;
int meshDim[3]; int meshDim[3];
__m128 boxSize, invBoxSize, half; __m128 boxSize, invBoxSize, half;
static float TWO_OVER_SQRT_PI;
// parameter indices
static const int SigIndex = 0;
static const int EpsIndex = 1;
static const int QIndex = 2;
/**---------------------------------------------------------------------------------------
Calculate LJ Coulomb pair ixn between two atoms
@param atom1 the index of the first atom
@param atom2 the index of the second atom
@param atomCoordinates atom coordinates
@param atomParameters atom parameters (charges, c6, c12, ...) atomParameters[atomIndex][paramterIndex]
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void calculateOneIxn( int atom1, int atom2, float* atomCoordinates,
float** atomParameters, float* forces,
double* totalEnergy ) const;
public: public:
...@@ -150,54 +127,86 @@ class CpuNonbondedForce { ...@@ -150,54 +127,86 @@ class CpuNonbondedForce {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void setUsePME(float alpha, int meshSize[3]); void setUsePME(float alpha, int meshSize[3]);
/**---------------------------------------------------------------------------------------
Calculate Ewald ixn
@param numberOfAtoms number of atoms
@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 exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom
@param fixedParameters non atom parameters (not currently used)
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void calculateReciprocalIxn(int numberOfAtoms, float* posq, std::vector<OpenMM::RealVec>& atomCoordinates,
const std::vector<std::pair<float, float> >& atomParameters, const std::vector<std::set<int> >& exclusions,
float* fixedParameters, std::vector<OpenMM::RealVec>& forces, float* totalEnergy) const;
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Calculate LJ Coulomb pair ixn Calculate LJ Coulomb pair ixn
@param numberOfAtoms number of atoms @param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates @param posq atom coordinates and charges
@param atomParameters atom parameters (charges, c6, c12, ...) atomParameters[atomIndex][paramterIndex] @param atomParameters atom parameters (sigma/2, 2*sqrt(epsilon))
@param exclusions atom exclusion indices @param exclusions atom exclusion indices
exclusions[atomIndex] contains the list of exclusions for that atom exclusions[atomIndex] contains the list of exclusions for that atom
@param fixedParameters non atom parameters (not currently used) @param fixedParameters non atom parameters (not currently used)
@param forces force array (forces added) @param forces force array (forces added)
@param totalEnergy total energy @param totalEnergy total energy
@param includeDirect true if direct space interactions should be included
@param includeReciprocal true if reciprocal space interactions should be included
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void calculatePairIxn(int numberOfAtoms, float* atomCoordinates, void calculateDirectIxn(int numberOfAtoms, float* posq,
float** atomParameters, std::vector<std::set<int> >& exclusions, const std::vector<std::pair<float, float> >& atomParameters, const std::vector<std::set<int> >& exclusions,
float* fixedParameters, float* forces, float* fixedParameters, float* forces, float* totalEnergy) const;
float* totalEnergy, bool includeDirect, bool includeReciprocal) const;
private: private:
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Calculate Ewald ixn Calculate LJ Coulomb pair ixn between two atoms
@param numberOfAtoms number of atoms @param atom1 the index of the first atom
@param atomCoordinates atom coordinates @param atom2 the index of the second atom
@param atomParameters atom parameters (charges, c6, c12, ...) atomParameters[atomIndex][paramterIndex] @param posq atom coordinates and charges
@param exclusions atom exclusion indices @param atomParameters atom parameters (sigma/2, 2*sqrt(epsilon))
exclusions[atomIndex] contains the list of exclusions for that atom
@param fixedParameters non atom parameters (not currently used)
@param forces force array (forces added) @param forces force array (forces added)
@param totalEnergy total energy @param totalEnergy total energy
@param includeDirect true if direct space interactions should be included
@param includeReciprocal true if reciprocal space interactions should be included
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void calculateEwaldIxn(int numberOfAtoms, float* atomCoordinates, void calculateOneIxn( int atom1, int atom2, float* posq,
float** atomParameters, std::vector<std::set<int> >& exclusions, const std::vector<std::pair<float, float> >& atomParameters, float* forces,
float* fixedParameters, float* forces, double* totalEnergy ) const;
float* totalEnergy, bool includeDirect, bool includeReciprocal) const;
/**---------------------------------------------------------------------------------------
Calculate LJ Coulomb pair ixn between two atoms
@param atom1 the index of the first atom
@param atom2 the index of the second atom
@param posq atom coordinates and charges
@param atomParameters atom parameters (sigma/2, 2*sqrt(epsilon))
@param forces force array (forces added)
@param totalEnergy total energy
--------------------------------------------------------------------------------------- */
void calculateOneEwaldIxn( int atom1, int atom2, float* posq,
const std::vector<std::pair<float, float> >& atomParameters, float* forces,
double* totalEnergy ) const;
void getDeltaR(const __m128& posI, const __m128& posJ, __m128& deltaR, float& r2, bool periodic) const; void getDeltaR(const __m128& posI, const __m128& posJ, __m128& deltaR, float& r2, bool periodic) const;
static float erfcApprox(float x);
}; };
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
......
...@@ -63,9 +63,14 @@ static RealVec& extractBoxSize(ContextImpl& context) { ...@@ -63,9 +63,14 @@ static RealVec& extractBoxSize(ContextImpl& context) {
} }
CpuCalcNonbondedForceKernel::~CpuCalcNonbondedForceKernel() { CpuCalcNonbondedForceKernel::~CpuCalcNonbondedForceKernel() {
delete bonded14IndexArray; // Do this properly if (bonded14ParamArray != NULL) {
delete bonded14ParamArray; // Do this properly for (int i = 0; i < num14; i++) {
delete particleParamArray; // Do this properly delete[] bonded14IndexArray[i];
delete[] bonded14ParamArray[i];
}
delete bonded14IndexArray;
delete bonded14ParamArray;
}
} }
void CpuCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force) { void CpuCalcNonbondedForceKernel::initialize(const System& system, const NonbondedForce& force) {
...@@ -96,16 +101,14 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond ...@@ -96,16 +101,14 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
bonded14ParamArray = new double*[num14]; bonded14ParamArray = new double*[num14];
for (int i = 0; i < num14; i++) for (int i = 0; i < num14; i++)
bonded14ParamArray[i] = new double[3]; bonded14ParamArray[i] = new double[3];
particleParamArray = new float*[numParticles]; particleParams.resize(numParticles);
for (int i = 0; i < numParticles; i++) double sumSquaredCharges = 0.0;
particleParamArray[i] = new float[3];
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
double charge, radius, depth; double charge, radius, depth;
force.getParticleParameters(i, charge, radius, depth); force.getParticleParameters(i, charge, radius, depth);
posq[4*i+3] = (float) charge; posq[4*i+3] = (float) charge;
particleParamArray[i][0] = (float) (0.5*radius); particleParams[i] = make_pair((float) (0.5*radius), (float) (2.0*sqrt(depth)));
particleParamArray[i][1] = (float) (2.0*sqrt(depth)); sumSquaredCharges += charge*charge;
particleParamArray[i][2] = (float) (charge);
} }
for (int i = 0; i < num14; ++i) { for (int i = 0; i < num14; ++i) {
int particle1, particle2; int particle1, particle2;
...@@ -135,6 +138,10 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond ...@@ -135,6 +138,10 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
NonbondedForceImpl::calcPMEParameters(system, force, alpha, gridSize[0], gridSize[1], gridSize[2]); NonbondedForceImpl::calcPMEParameters(system, force, alpha, gridSize[0], gridSize[1], gridSize[2]);
ewaldAlpha = alpha; ewaldAlpha = alpha;
} }
if (nonbondedMethod == Ewald || nonbondedMethod == PME)
ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI);
else
ewaldSelfEnergy = 0.0;
rfDielectric = force.getReactionFieldDielectric(); rfDielectric = force.getReactionFieldDielectric();
if (force.getUseDispersionCorrection()) if (force.getUseDispersionCorrection())
dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(system, force); dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(system, force);
...@@ -147,7 +154,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -147,7 +154,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
vector<RealVec>& forceData = extractForces(context); vector<RealVec>& forceData = extractForces(context);
RealVec boxSize = extractBoxSize(context); RealVec boxSize = extractBoxSize(context);
float floatBoxSize[3] = {(float) boxSize[0], (float) boxSize[1], (float) boxSize[2]}; float floatBoxSize[3] = {(float) boxSize[0], (float) boxSize[1], (float) boxSize[2]};
double energy = 0; double energy = ewaldSelfEnergy;
CpuNonbondedForce clj; CpuNonbondedForce clj;
bool periodic = (nonbondedMethod == CutoffPeriodic); bool periodic = (nonbondedMethod == CutoffPeriodic);
bool ewald = (nonbondedMethod == Ewald); bool ewald = (nonbondedMethod == Ewald);
...@@ -186,9 +193,12 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -186,9 +193,12 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
clj.setUsePME(ewaldAlpha, gridSize); clj.setUsePME(ewaldAlpha, gridSize);
if (useSwitchingFunction) if (useSwitchingFunction)
clj.setUseSwitchingFunction(switchingDistance); clj.setUseSwitchingFunction(switchingDistance);
float directEnergy = 0; float nonbondedEnergy = 0;
clj.calculatePairIxn(numParticles, &posq[0], particleParamArray, exclusions, 0, &forces[0], includeEnergy ? &directEnergy : NULL, includeDirect, includeReciprocal); if (includeDirect)
energy += directEnergy; clj.calculateDirectIxn(numParticles, &posq[0], particleParams, exclusions, 0, &forces[0], includeEnergy ? &nonbondedEnergy : NULL);
if (includeReciprocal)
clj.calculateReciprocalIxn(numParticles, &posq[0], posData, particleParams, exclusions, 0, forceData, includeEnergy ? &nonbondedEnergy : NULL);
energy += nonbondedEnergy;
for (int i = 0; i < numParticles; i++) { for (int i = 0; i < numParticles; i++) {
forceData[i][0] += forces[4*i]; forceData[i][0] += forces[4*i];
forceData[i][1] += forces[4*i+1]; forceData[i][1] += forces[4*i+1];
...@@ -220,13 +230,18 @@ void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, ...@@ -220,13 +230,18 @@ void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context,
// Record the values. // Record the values.
double sumSquaredCharges = 0.0;
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
double charge, radius, depth; double charge, radius, depth;
force.getParticleParameters(i, charge, radius, depth); force.getParticleParameters(i, charge, radius, depth);
particleParamArray[i][0] = (float) (0.5*radius); posq[4*i+3] = (float) charge;
particleParamArray[i][1] = (float) (2.0*sqrt(depth)); particleParams[i] = make_pair((float) (0.5*radius), (float) (2.0*sqrt(depth)));
particleParamArray[i][2] = (float) (charge); sumSquaredCharges += charge*charge;
} }
if (nonbondedMethod == Ewald || nonbondedMethod == PME)
ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI);
else
ewaldSelfEnergy = 0.0;
for (int i = 0; i < num14; ++i) { for (int i = 0; i < num14; ++i) {
int particle1, particle2; int particle1, particle2;
double charge, radius, depth; double charge, radius, depth;
......
This diff is collapsed.
...@@ -54,11 +54,11 @@ pme_t; ...@@ -54,11 +54,11 @@ pme_t;
*/ */
int int
pme_init(pme_t * ppme, pme_init(pme_t * ppme,
RealOpenMM ewaldcoeff, RealOpenMM ewaldcoeff,
int natoms, int natoms,
const int ngrid[3], const int ngrid[3],
int pme_order, int pme_order,
RealOpenMM epsilon_r); RealOpenMM epsilon_r);
/* /*
* Evaluate reciprocal space PME energy and forces. * Evaluate reciprocal space PME energy and forces.
...@@ -75,9 +75,9 @@ pme_init(pme_t * ppme, ...@@ -75,9 +75,9 @@ pme_init(pme_t * ppme,
*/ */
int int
pme_exec(pme_t pme, pme_exec(pme_t pme,
std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& atomCoordinates,
std::vector<OpenMM::RealVec>& forces, std::vector<OpenMM::RealVec>& forces,
RealOpenMM ** atomParameters, std::vector<RealOpenMM>& charges,
const RealOpenMM periodicBoxSize[3], const RealOpenMM periodicBoxSize[3],
RealOpenMM * energy, RealOpenMM * energy,
RealOpenMM pme_virial[3][3]); RealOpenMM pme_virial[3][3]);
......
...@@ -233,7 +233,10 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec> ...@@ -233,7 +233,10 @@ void ReferenceLJCoulombIxn::calculateEwaldIxn(int numberOfAtoms, vector<RealVec>
pme_init(&pmedata,alphaEwald,numberOfAtoms,meshDim,5,1); pme_init(&pmedata,alphaEwald,numberOfAtoms,meshDim,5,1);
pme_exec(pmedata,atomCoordinates,forces,atomParameters,periodicBoxSize,&recipEnergy,virial); vector<RealOpenMM> charges(numberOfAtoms);
for (int i = 0; i < numberOfAtoms; i++)
charges[i] = atomParameters[i][QIndex];
pme_exec(pmedata,atomCoordinates,forces,charges,periodicBoxSize,&recipEnergy,virial);
if( totalEnergy ) if( totalEnergy )
*totalEnergy += recipEnergy; *totalEnergy += recipEnergy;
......
...@@ -317,10 +317,8 @@ pme_update_bsplines(pme_t pme) ...@@ -317,10 +317,8 @@ pme_update_bsplines(pme_t pme)
static void static void
pme_grid_spread_charge(pme_t pme, pme_grid_spread_charge(pme_t pme, vector<RealOpenMM>& charges)
RealOpenMM ** atomParameters)
{ {
static const int QIndex = 2; // atom charges are stored in atomParameters[atomID][2]
int order; int order;
int i; int i;
int ix,iy,iz; int ix,iy,iz;
...@@ -342,7 +340,7 @@ pme_grid_spread_charge(pme_t pme, ...@@ -342,7 +340,7 @@ pme_grid_spread_charge(pme_t pme,
for(i=0;i<pme->natoms;i++) for(i=0;i<pme->natoms;i++)
{ {
q = atomParameters[i][QIndex]; q = charges[i];
/* Grid index for the actual atom position */ /* Grid index for the actual atom position */
x0index = pme->particleindex[i][0]; x0index = pme->particleindex[i][0];
...@@ -523,10 +521,9 @@ pme_reciprocal_convolution(pme_t pme, ...@@ -523,10 +521,9 @@ pme_reciprocal_convolution(pme_t pme,
static void static void
pme_grid_interpolate_force(pme_t pme, pme_grid_interpolate_force(pme_t pme,
const RealOpenMM periodicBoxSize[3], const RealOpenMM periodicBoxSize[3],
RealOpenMM ** atomParameters, vector<RealOpenMM>& charges,
vector<RealVec>& forces) vector<RealVec>& forces)
{ {
static const int QIndex = 2; // atom charges are stored in atomParameters[atomID][2]
int i; int i;
int ix,iy,iz; int ix,iy,iz;
int x0index,y0index,z0index; int x0index,y0index,z0index;
...@@ -558,7 +555,7 @@ pme_grid_interpolate_force(pme_t pme, ...@@ -558,7 +555,7 @@ pme_grid_interpolate_force(pme_t pme,
{ {
fx = fy = fz = 0; fx = fy = fz = 0;
q = atomParameters[i][QIndex]; q = charges[i];
/* Grid index for the actual atom position */ /* Grid index for the actual atom position */
x0index = pme->particleindex[i][0]; x0index = pme->particleindex[i][0];
...@@ -671,7 +668,7 @@ pme_init(pme_t * ppme, ...@@ -671,7 +668,7 @@ pme_init(pme_t * ppme,
int pme_exec(pme_t pme, int pme_exec(pme_t pme,
vector<RealVec>& atomCoordinates, vector<RealVec>& atomCoordinates,
vector<RealVec>& forces, vector<RealVec>& forces,
RealOpenMM ** atomParameters, vector<RealOpenMM>& charges,
const RealOpenMM periodicBoxSize[3], const RealOpenMM periodicBoxSize[3],
RealOpenMM * energy, RealOpenMM * energy,
RealOpenMM pme_virial[3][3]) RealOpenMM pme_virial[3][3])
...@@ -692,7 +689,7 @@ int pme_exec(pme_t pme, ...@@ -692,7 +689,7 @@ int pme_exec(pme_t pme,
pme_update_bsplines(pme); pme_update_bsplines(pme);
/* Spread the charges on grid (using newly calculated bsplines in the pme structure) */ /* Spread the charges on grid (using newly calculated bsplines in the pme structure) */
pme_grid_spread_charge(pme,atomParameters); pme_grid_spread_charge(pme, charges);
/* do 3d-fft */ /* do 3d-fft */
fftpack_exec_3d(pme->fftplan,FFTPACK_FORWARD,pme->grid,pme->grid); fftpack_exec_3d(pme->fftplan,FFTPACK_FORWARD,pme->grid,pme->grid);
...@@ -704,7 +701,7 @@ int pme_exec(pme_t pme, ...@@ -704,7 +701,7 @@ int pme_exec(pme_t pme,
fftpack_exec_3d(pme->fftplan,FFTPACK_BACKWARD,pme->grid,pme->grid); fftpack_exec_3d(pme->fftplan,FFTPACK_BACKWARD,pme->grid,pme->grid);
/* Get the particle forces from the grid and bsplines in the pme structure */ /* Get the particle forces from the grid and bsplines in the pme structure */
pme_grid_interpolate_force(pme,periodicBoxSize,atomParameters,forces); pme_grid_interpolate_force(pme,periodicBoxSize,charges,forces);
return 0; return 0;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment