Commit 3040bf9d authored by peastman's avatar peastman
Browse files

CPU implementation of parameter offsets for NonbondedForce

parent 1dd61bab
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#include "CpuPlatform.h" #include "CpuPlatform.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/System.h" #include "openmm/System.h"
#include <array>
#include <tuple>
namespace OpenMM { namespace OpenMM {
...@@ -267,17 +269,21 @@ public: ...@@ -267,17 +269,21 @@ public:
void getLJPMEParameters(double& alpha, int& nx, int& ny, int& nz) const; void getLJPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
private: private:
class PmeIO; class PmeIO;
void computeParameters(ContextImpl& context, bool offsetsOnly);
CpuPlatform::PlatformData& data; CpuPlatform::PlatformData& data;
int numParticles, num14, posqIndex; int numParticles, num14, posqIndex;
int **bonded14IndexArray; int **bonded14IndexArray;
double **bonded14ParamArray; double **bonded14ParamArray;
double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, ewaldDispersionAlpha, ewaldSelfEnergy, dispersionCoefficient; double nonbondedCutoff, switchingDistance, rfDielectric, ewaldAlpha, ewaldDispersionAlpha, ewaldSelfEnergy, dispersionCoefficient;
int kmax[3], gridSize[3], dispersionGridSize[3]; int kmax[3], gridSize[3], dispersionGridSize[3];
bool useSwitchingFunction, useOptimizedPme, hasInitializedPme, hasInitializedDispersionPme; bool useSwitchingFunction, useOptimizedPme, hasInitializedPme, hasInitializedDispersionPme, hasParticleOffsets, hasExceptionOffsets;
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
std::vector<std::pair<float, float> > particleParams; std::vector<std::pair<float, float> > particleParams;
std::vector<float> C6params; std::vector<float> C6params;
std::vector<float> charges; std::vector<float> charges;
std::vector<std::array<double, 3> > baseParticleParams, baseExceptionParams;
std::vector<std::vector<std::tuple<double, double, double, int> > > particleParamOffsets, exceptionParamOffsets;
std::vector<std::string> paramNames;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
CpuNonbondedForce* nonbonded; CpuNonbondedForce* nonbonded;
Kernel optimizedPme, optimizedDispersionPme; Kernel optimizedPme, optimizedDispersionPme;
......
...@@ -572,30 +572,58 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond ...@@ -572,30 +572,58 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
particleParams.resize(numParticles); particleParams.resize(numParticles);
charges.resize(numParticles); charges.resize(numParticles);
C6params.resize(numParticles); C6params.resize(numParticles);
double sumSquaredCharges = 0.0; baseParticleParams.resize(numParticles);
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i)
double charge, radius, depth; force.getParticleParameters(i, baseParticleParams[i][0], baseParticleParams[i][1], baseParticleParams[i][2]);
force.getParticleParameters(i, charge, radius, depth);
charges[i] = (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;
}
// Recorded exception parameters. // Record exception parameters.
baseExceptionParams.resize(num14);
for (int i = 0; i < num14; ++i) { for (int i = 0; i < num14; ++i) {
int particle1, particle2; int particle1, particle2;
double charge, radius, depth; force.getExceptionParameters(nb14s[i], particle1, particle2, baseExceptionParams[i][0], baseExceptionParams[i][1], baseExceptionParams[i][2]);
force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth);
bonded14IndexArray[i][0] = particle1; bonded14IndexArray[i][0] = particle1;
bonded14IndexArray[i][1] = particle2; bonded14IndexArray[i][1] = particle2;
bonded14ParamArray[i][0] = radius;
bonded14ParamArray[i][1] = 4.0*depth;
bonded14ParamArray[i][2] = charge;
} }
bondForce.initialize(system.getNumParticles(), num14, 2, bonded14IndexArray, data.threads); bondForce.initialize(system.getNumParticles(), num14, 2, bonded14IndexArray, data.threads);
// Record information about parameter offsets.
hasParticleOffsets = (force.getNumParticleParameterOffsets() > 0);
hasExceptionOffsets = (force.getNumExceptionParameterOffsets() > 0);
particleParamOffsets.resize(force.getNumParticles());
exceptionParamOffsets.resize(force.getNumExceptions());
for (int i = 0; i < force.getNumParticleParameterOffsets(); i++) {
string param;
int particle;
double charge, sigma, epsilon;
force.getParticleParameterOffset(i, param, particle, charge, sigma, epsilon);
auto paramPos = find(paramNames.begin(), paramNames.end(), param);
int paramIndex;
if (paramPos == paramNames.end()) {
paramIndex = paramNames.size();
paramNames.push_back(param);
}
else
paramIndex = paramPos-paramNames.begin();
particleParamOffsets[particle].push_back(make_tuple(charge, sigma, epsilon, paramIndex));
}
for (int i = 0; i < force.getNumExceptionParameterOffsets(); i++) {
string param;
int exception;
double charge, sigma, epsilon;
force.getExceptionParameterOffset(i, param, exception, charge, sigma, epsilon);
auto paramPos = find(paramNames.begin(), paramNames.end(), param);
int paramIndex;
if (paramPos == paramNames.end()) {
paramIndex = paramNames.size();
paramNames.push_back(param);
}
else
paramIndex = paramPos-paramNames.begin();
exceptionParamOffsets[exception].push_back(make_tuple(charge, sigma, epsilon, paramIndex));
}
// Record other parameters. // Record other parameters.
nonbondedMethod = CalcNonbondedForceKernel::NonbondedMethod(force.getNonbondedMethod()); nonbondedMethod = CalcNonbondedForceKernel::NonbondedMethod(force.getNonbondedMethod());
...@@ -625,18 +653,6 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond ...@@ -625,18 +653,6 @@ void CpuCalcNonbondedForceKernel::initialize(const System& system, const Nonbond
ewaldDispersionAlpha = alpha; ewaldDispersionAlpha = alpha;
useSwitchingFunction = false; useSwitchingFunction = false;
} }
if (nonbondedMethod == Ewald || nonbondedMethod == PME || nonbondedMethod == LJPME) {
ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI);
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(); rfDielectric = force.getReactionFieldDielectric();
if (force.getUseDispersionCorrection()) if (force.getUseDispersionCorrection())
dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(system, force); dispersionCoefficient = NonbondedForceImpl::calcDispersionCorrection(system, force);
...@@ -649,6 +665,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -649,6 +665,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
if (!hasInitializedPme) { if (!hasInitializedPme) {
hasInitializedPme = true; hasInitializedPme = true;
useOptimizedPme = false; useOptimizedPme = false;
computeParameters(context, false);
if (nonbondedMethod == PME) { if (nonbondedMethod == PME) {
// If available, use the optimized PME implementation. // If available, use the optimized PME implementation.
...@@ -675,6 +692,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo ...@@ -675,6 +692,7 @@ double CpuCalcNonbondedForceKernel::execute(ContextImpl& context, bool includeFo
} }
} }
} }
computeParameters(context, true);
copyChargesToPosq(context, charges, posqIndex); copyChargesToPosq(context, charges, posqIndex);
AlignedArray<float>& posq = data.posq; AlignedArray<float>& posq = data.posq;
vector<Vec3>& posData = extractPositions(context); vector<Vec3>& posData = extractPositions(context);
...@@ -743,28 +761,15 @@ void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context, ...@@ -743,28 +761,15 @@ void CpuCalcNonbondedForceKernel::copyParametersToContext(ContextImpl& context,
// Record the values. // Record the values.
posqIndex = data.requestPosqIndex(); posqIndex = data.requestPosqIndex();
double sumSquaredCharges = 0.0; for (int i = 0; i < numParticles; ++i)
for (int i = 0; i < numParticles; ++i) { force.getParticleParameters(i, baseParticleParams[i][0], baseParticleParams[i][1], baseParticleParams[i][2]);
double charge, radius, depth;
force.getParticleParameters(i, charge, radius, depth);
charges[i] = (float) charge;
particleParams[i] = make_pair((float) (0.5*radius), (float) (2.0*sqrt(depth)));
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; force.getExceptionParameters(nb14s[i], particle1, particle2, baseExceptionParams[i][0], baseExceptionParams[i][1], baseExceptionParams[i][2]);
force.getExceptionParameters(nb14s[i], particle1, particle2, charge, radius, depth);
bonded14IndexArray[i][0] = particle1; bonded14IndexArray[i][0] = particle1;
bonded14IndexArray[i][1] = particle2; bonded14IndexArray[i][1] = particle2;
bonded14ParamArray[i][0] = radius;
bonded14ParamArray[i][1] = 4.0*depth;
bonded14ParamArray[i][2] = charge;
} }
computeParameters(context, false);
// Recompute the coefficient for the dispersion correction. // Recompute the coefficient for the dispersion correction.
...@@ -799,6 +804,60 @@ void CpuCalcNonbondedForceKernel::getLJPMEParameters(double& alpha, int& nx, int ...@@ -799,6 +804,60 @@ void CpuCalcNonbondedForceKernel::getLJPMEParameters(double& alpha, int& nx, int
} }
} }
void CpuCalcNonbondedForceKernel::computeParameters(ContextImpl& context, bool offsetsOnly) {
vector<double> paramValues(paramNames.size());
for (int i = 0; i < paramNames.size(); i++)
paramValues[i] = context.getParameter(paramNames[i]);
// Compute particle parameters.
if (hasParticleOffsets || !offsetsOnly) {
double sumSquaredCharges = 0.0;
for (int i = 0; i < numParticles; i++) {
double charge = baseParticleParams[i][0];
double sigma = baseParticleParams[i][1];
double epsilon = baseParticleParams[i][2];
for (auto& offset : particleParamOffsets[i]) {
double value = paramValues[get<3>(offset)];
charge += value*get<0>(offset);
sigma += value*get<1>(offset);
epsilon += value*get<2>(offset);
}
charges[i] = (float) charge;
particleParams[i] = make_pair((float) (0.5*sigma), (float) (2.0*sqrt(epsilon)));
C6params[i] = 8.0*pow(particleParams[i].first, 3.0) * particleParams[i].second;
sumSquaredCharges += charge*charge;
}
if (nonbondedMethod == Ewald || nonbondedMethod == PME || nonbondedMethod == LJPME) {
ewaldSelfEnergy = -ONE_4PI_EPS0*ewaldAlpha*sumSquaredCharges/sqrt(M_PI);
if (nonbondedMethod == LJPME)
for (int atom = 0; atom < numParticles; atom++)
ewaldSelfEnergy += pow(ewaldDispersionAlpha, 6.0) * C6params[atom]*C6params[atom] / 12.0;
}
else
ewaldSelfEnergy = 0.0;
}
// Compute exception parameters.
if (hasExceptionOffsets || !offsetsOnly) {
for (int i = 0; i < num14; i++) {
double chargeProd = baseExceptionParams[i][0];
double sigma = baseExceptionParams[i][1];
double epsilon = baseExceptionParams[i][2];
for (auto& offset : exceptionParamOffsets[i]) {
double value = paramValues[get<3>(offset)];
chargeProd += value*get<0>(offset);
sigma += value*get<1>(offset);
epsilon += value*get<2>(offset);
}
bonded14ParamArray[i][0] = sigma;
bonded14ParamArray[i][1] = 4.0*epsilon;
bonded14ParamArray[i][2] = chargeProd;
}
}
}
CpuCalcCustomNonbondedForceKernel::CpuCalcCustomNonbondedForceKernel(string name, const Platform& platform, CpuPlatform::PlatformData& data) : CpuCalcCustomNonbondedForceKernel::CpuCalcCustomNonbondedForceKernel(string name, const Platform& platform, CpuPlatform::PlatformData& data) :
CalcCustomNonbondedForceKernel(name, platform), data(data), forceCopy(NULL), nonbonded(NULL) { CalcCustomNonbondedForceKernel(name, platform), data(data), forceCopy(NULL), nonbonded(NULL) {
} }
......
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