"platforms/cpu/vscode:/vscode.git/clone" did not exist on "7dc2ff9eb4cee8cfdd9fb7af9dd3c0a8a405c391"
Unverified Commit 779400a1 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Optimized computing long range correction for CustomNonbondedForce (#3236)

parent b7ee3022
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. * * Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "ForceImpl.h" #include "ForceImpl.h"
#include "openmm/CustomNonbondedForce.h" #include "openmm/CustomNonbondedForce.h"
#include "openmm/Kernel.h" #include "openmm/Kernel.h"
#include "openmm/internal/ThreadPool.h"
#include "lepton/CompiledExpression.h" #include "lepton/CompiledExpression.h"
#include <utility> #include <utility>
#include <map> #include <map>
...@@ -48,6 +49,7 @@ namespace OpenMM { ...@@ -48,6 +49,7 @@ namespace OpenMM {
class OPENMM_EXPORT CustomNonbondedForceImpl : public ForceImpl { class OPENMM_EXPORT CustomNonbondedForceImpl : public ForceImpl {
public: public:
class LongRangeCorrectionData;
CustomNonbondedForceImpl(const CustomNonbondedForce& owner); CustomNonbondedForceImpl(const CustomNonbondedForce& owner);
~CustomNonbondedForceImpl(); ~CustomNonbondedForceImpl();
void initialize(ContextImpl& context); void initialize(ContextImpl& context);
...@@ -61,12 +63,19 @@ public: ...@@ -61,12 +63,19 @@ public:
std::map<std::string, double> getDefaultParameters(); std::map<std::string, double> getDefaultParameters();
std::vector<std::string> getKernelNames(); std::vector<std::string> getKernelNames();
void updateParametersInContext(ContextImpl& context); void updateParametersInContext(ContextImpl& context);
/**
* Prepare for computing the long range correction. This function pre-computes anything
* that depends only on the Force (such as particle parameters) but not on information in
* the Context (such as global parameters). This allows the coefficient to be updated
* more quickly when global parameters change.
*/
static LongRangeCorrectionData prepareLongRangeCorrection(const CustomNonbondedForce& force);
/** /**
* Compute the coefficient which, when divided by the periodic box volume, gives the * Compute the coefficient which, when divided by the periodic box volume, gives the
* long range correction to the energy. If the Force computes parameter derivatives, * long range correction to the energy. If the Force computes parameter derivatives,
* also compute the corresponding derivatives of the correction. * also compute the corresponding derivatives of the correction.
*/ */
static void calcLongRangeCorrection(const CustomNonbondedForce& force, const Context& context, double& coefficient, std::vector<double>& derivatives); static void calcLongRangeCorrection(const CustomNonbondedForce& force, LongRangeCorrectionData& data, const Context& context, double& coefficient, std::vector<double>& derivatives, ThreadPool& threads);
private: private:
static double integrateInteraction(Lepton::CompiledExpression& expression, const std::vector<double>& params1, const std::vector<double>& params2, static double integrateInteraction(Lepton::CompiledExpression& expression, const std::vector<double>& params1, const std::vector<double>& params2,
const CustomNonbondedForce& force, const Context& context, const std::vector<std::string>& paramNames); const CustomNonbondedForce& force, const Context& context, const std::vector<std::string>& paramNames);
...@@ -74,6 +83,16 @@ private: ...@@ -74,6 +83,16 @@ private:
Kernel kernel; Kernel kernel;
}; };
class CustomNonbondedForceImpl::LongRangeCorrectionData {
public:
CustomNonbondedForce::NonbondedMethod method;
std::vector<std::vector<double> > classes;
std::vector<std::string> paramNames;
std::map<std::pair<int, int>, long long int> interactionCount;
Lepton::CompiledExpression energyExpression;
std::vector<Lepton::CompiledExpression> derivExpressions;
};
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_CUSTOMNONBONDEDFORCEIMPL_H_*/ #endif /*OPENMM_CUSTOMNONBONDEDFORCEIMPL_H_*/
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. * * Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "ReferenceTabulatedFunction.h" #include "ReferenceTabulatedFunction.h"
#include "lepton/ParsedExpression.h" #include "lepton/ParsedExpression.h"
#include "lepton/Parser.h" #include "lepton/Parser.h"
#include <atomic>
#include <cmath> #include <cmath>
#include <sstream> #include <sstream>
#include <utility> #include <utility>
...@@ -158,16 +159,15 @@ void CustomNonbondedForceImpl::updateParametersInContext(ContextImpl& context) { ...@@ -158,16 +159,15 @@ void CustomNonbondedForceImpl::updateParametersInContext(ContextImpl& context) {
context.systemChanged(); context.systemChanged();
} }
void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForce& force, const Context& context, double& coefficient, vector<double>& derivatives) { CustomNonbondedForceImpl::LongRangeCorrectionData CustomNonbondedForceImpl::prepareLongRangeCorrection(const CustomNonbondedForce& force) {
if (force.getNonbondedMethod() == CustomNonbondedForce::NoCutoff || force.getNonbondedMethod() == CustomNonbondedForce::CutoffNonPeriodic) { LongRangeCorrectionData data;
coefficient = 0.0; data.method = force.getNonbondedMethod();
return; if (data.method == CustomNonbondedForce::NoCutoff || data.method == CustomNonbondedForce::CutoffNonPeriodic)
} return data;
// Identify all particle classes (defined by parameters), and record the class of each particle. // Identify all particle classes (defined by parameters), and record the class of each particle.
int numParticles = force.getNumParticles(); int numParticles = force.getNumParticles();
vector<vector<double> > classes;
map<vector<double>, int> classIndex; map<vector<double>, int> classIndex;
vector<int> atomClass(numParticles); vector<int> atomClass(numParticles);
vector<double> parameters; vector<double> parameters;
...@@ -175,18 +175,17 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc ...@@ -175,18 +175,17 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc
force.getParticleParameters(i, parameters); force.getParticleParameters(i, parameters);
map<vector<double>, int>::iterator entry = classIndex.find(parameters); map<vector<double>, int>::iterator entry = classIndex.find(parameters);
if (entry == classIndex.end()) { if (entry == classIndex.end()) {
classIndex[parameters] = classes.size(); classIndex[parameters] = data.classes.size();
atomClass[i] = classes.size(); atomClass[i] = data.classes.size();
classes.push_back(parameters); data.classes.push_back(parameters);
} }
else else
atomClass[i] = entry->second; atomClass[i] = entry->second;
} }
int numClasses = classes.size(); int numClasses = data.classes.size();
// Count the total number of particle pairs for each pair of classes. // Count the total number of particle pairs for each pair of classes.
map<pair<int, int>, long long int> interactionCount;
if (force.getNumInteractionGroups() == 0) { if (force.getNumInteractionGroups() == 0) {
// Count the particles of each class. // Count the particles of each class.
...@@ -194,9 +193,9 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc ...@@ -194,9 +193,9 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc
for (int i = 0; i < numParticles; i++) for (int i = 0; i < numParticles; i++)
classCounts[atomClass[i]]++; classCounts[atomClass[i]]++;
for (int i = 0; i < numClasses; i++) { for (int i = 0; i < numClasses; i++) {
interactionCount[make_pair(i, i)] = (classCounts[i]*(classCounts[i]+1))/2; data.interactionCount[make_pair(i, i)] = (classCounts[i]*(classCounts[i]+1))/2;
for (int j = i+1; j < numClasses; j++) for (int j = i+1; j < numClasses; j++)
interactionCount[make_pair(i, j)] = classCounts[i]*classCounts[j]; data.interactionCount[make_pair(i, j)] = classCounts[i]*classCounts[j];
} }
} }
else { else {
...@@ -204,7 +203,7 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc ...@@ -204,7 +203,7 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc
for (int i = 0; i < numClasses; i++) { for (int i = 0; i < numClasses; i++) {
for (int j = i; j < numClasses; j++) for (int j = i; j < numClasses; j++)
interactionCount[make_pair(i, j)] = 0; data.interactionCount[make_pair(i, j)] = 0;
} }
// Loop over interaction groups and count the interactions in each one. // Loop over interaction groups and count the interactions in each one.
...@@ -218,44 +217,80 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc ...@@ -218,44 +217,80 @@ void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForc
continue; continue;
int class1 = atomClass[*a1]; int class1 = atomClass[*a1];
int class2 = atomClass[*a2]; int class2 = atomClass[*a2];
interactionCount[make_pair(min(class1, class2), max(class1, class2))]++; data.interactionCount[make_pair(min(class1, class2), max(class1, class2))]++;
} }
} }
} }
// Compute the coefficient. // Prepare for evaluating the expressions.
map<string, Lepton::CustomFunction*> functions; map<string, Lepton::CustomFunction*> functions;
for (int i = 0; i < force.getNumFunctions(); i++) for (int i = 0; i < force.getNumFunctions(); i++)
functions[force.getTabulatedFunctionName(i)] = createReferenceTabulatedFunction(force.getTabulatedFunction(i)); functions[force.getTabulatedFunctionName(i)] = createReferenceTabulatedFunction(force.getTabulatedFunction(i));
double nPart = (double) numParticles; data.energyExpression = Lepton::Parser::parse(force.getEnergyFunction(), functions).createCompiledExpression();
double numInteractions = (nPart*(nPart+1))/2; for (int k = 0; k < force.getNumEnergyParameterDerivatives(); k++)
Lepton::CompiledExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).createCompiledExpression(); data.derivExpressions.push_back(Lepton::Parser::parse(force.getEnergyFunction(), functions).differentiate(force.getEnergyParameterDerivativeName(k)).createCompiledExpression());
vector<string> paramNames;
for (int i = 0; i < force.getNumPerParticleParameters(); i++) { for (int i = 0; i < force.getNumPerParticleParameters(); i++) {
stringstream name1, name2; stringstream name1, name2;
name1 << force.getPerParticleParameterName(i) << 1; name1 << force.getPerParticleParameterName(i) << 1;
name2 << force.getPerParticleParameterName(i) << 2; name2 << force.getPerParticleParameterName(i) << 2;
paramNames.push_back(name1.str()); data.paramNames.push_back(name1.str());
paramNames.push_back(name2.str()); data.paramNames.push_back(name2.str());
} }
double sum = 0; return data;
for (int i = 0; i < numClasses; i++) }
void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForce& force, LongRangeCorrectionData& data, const Context& context, double& coefficient, vector<double>& derivatives, ThreadPool& threads) {
if (data.method == CustomNonbondedForce::NoCutoff || data.method == CustomNonbondedForce::CutoffNonPeriodic) {
coefficient = 0.0;
return;
}
// Compute the coefficient. Use multiple threads to compute the integrals in parallel.
int numClasses = data.classes.size();
double nPart = (double) context.getSystem().getNumParticles();
double numInteractions = (nPart*(nPart+1))/2;
vector<double> threadSum(threads.getNumThreads(), 0.0);
atomic<int> atomicCounter(0);
threads.execute([&] (ThreadPool& threads, int threadIndex) {
Lepton::CompiledExpression expression = data.energyExpression;
while (true) {
int i = atomicCounter++;
if (i >= numClasses)
break;
for (int j = i; j < numClasses; j++) for (int j = i; j < numClasses; j++)
sum += interactionCount[make_pair(i, j)]*integrateInteraction(expression, classes[i], classes[j], force, context, paramNames); threadSum[threadIndex] += data.interactionCount.at(make_pair(i, j))*integrateInteraction(expression, data.classes[i], data.classes[j], force, context, data.paramNames);
}
});
threads.waitForThreads();
double sum = 0;
for (int i = 0; i < threadSum.size(); i++)
sum += threadSum[i];
sum /= numInteractions; sum /= numInteractions;
coefficient = 2*M_PI*nPart*nPart*sum; coefficient = 2*M_PI*nPart*nPart*sum;
// Now do the same for parameter derivatives. // Now do the same for parameter derivatives.
int numDerivs = force.getNumEnergyParameterDerivatives(); int numDerivs = data.derivExpressions.size();
derivatives.resize(numDerivs); derivatives.resize(numDerivs);
for (int k = 0; k < numDerivs; k++) { for (int k = 0; k < numDerivs; k++) {
expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).differentiate(force.getEnergyParameterDerivativeName(k)).createCompiledExpression(); atomicCounter = 0;
sum = 0; threads.execute([&] (ThreadPool& threads, int threadIndex) {
for (int i = 0; i < numClasses; i++) threadSum[threadIndex] = 0;
Lepton::CompiledExpression expression = data.derivExpressions[k];
while (true) {
int i = atomicCounter++;
if (i >= numClasses)
break;
for (int j = i; j < numClasses; j++) for (int j = i; j < numClasses; j++)
sum += interactionCount[make_pair(i, j)]*integrateInteraction(expression, classes[i], classes[j], force, context, paramNames); threadSum[threadIndex] += data.interactionCount.at(make_pair(i, j))*integrateInteraction(expression, data.classes[i], data.classes[j], force, context, data.paramNames);
}
});
threads.waitForThreads();
sum = 0;
for (int i = 0; i < threadSum.size(); i++)
sum += threadSum[i];
sum /= numInteractions; sum /= numInteractions;
derivatives[k] = 2*M_PI*nPart*nPart*sum; derivatives[k] = 2*M_PI*nPart*nPart*sum;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2020 Stanford University and the Authors. * * Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/internal/CompiledExpressionSet.h" #include "openmm/internal/CompiledExpressionSet.h"
#include "openmm/internal/CustomIntegratorUtilities.h" #include "openmm/internal/CustomIntegratorUtilities.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "lepton/CompiledExpression.h" #include "lepton/CompiledExpression.h"
#include "lepton/ExpressionProgram.h" #include "lepton/ExpressionProgram.h"
...@@ -616,6 +617,8 @@ public: ...@@ -616,6 +617,8 @@ public:
void copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force); void copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force);
private: private:
class ForceInfo; class ForceInfo;
class LongRangePostComputation;
class LongRangeTask;
void initInteractionGroups(const CustomNonbondedForce& force, const std::string& interactionSource, const std::vector<std::string>& tableTypes); void initInteractionGroups(const CustomNonbondedForce& force, const std::string& interactionSource, const std::vector<std::string>& tableTypes);
ComputeContext& cc; ComputeContext& cc;
ForceInfo* info; ForceInfo* info;
...@@ -631,6 +634,7 @@ private: ...@@ -631,6 +634,7 @@ private:
bool hasInitializedLongRangeCorrection, hasInitializedKernel, hasParamDerivs, useNeighborList; bool hasInitializedLongRangeCorrection, hasInitializedKernel, hasParamDerivs, useNeighborList;
int numGroupThreadBlocks; int numGroupThreadBlocks;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
CustomNonbondedForceImpl::LongRangeCorrectionData longRangeCorrectionData;
const System& system; const System& system;
}; };
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include "openmm/internal/CustomCompoundBondForceImpl.h" #include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h" #include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomManyParticleForceImpl.h" #include "openmm/internal/CustomManyParticleForceImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "CommonKernelSources.h" #include "CommonKernelSources.h"
#include "lepton/CustomFunction.h" #include "lepton/CustomFunction.h"
#include "lepton/ExpressionTreeNode.h" #include "lepton/ExpressionTreeNode.h"
...@@ -1771,6 +1770,47 @@ private: ...@@ -1771,6 +1770,47 @@ private:
vector<set<int> > groupsForParticle; vector<set<int> > groupsForParticle;
}; };
class CommonCalcCustomNonbondedForceKernel::LongRangePostComputation : public ComputeContext::ForcePostComputation {
public:
LongRangePostComputation(ComputeContext& cc, double& longRangeCoefficient, vector<double>& longRangeCoefficientDerivs, CustomNonbondedForce* force) :
cc(cc), longRangeCoefficient(longRangeCoefficient), longRangeCoefficientDerivs(longRangeCoefficientDerivs), force(force) {
}
double computeForceAndEnergy(bool includeForces, bool includeEnergy, int groups) {
cc.getWorkThread().flush();
Vec3 a, b, c;
cc.getPeriodicBoxVectors(a, b, c);
double volume = a[0]*b[1]*c[2];
map<string, double>& derivs = cc.getEnergyParamDerivWorkspace();
for (int i = 0; i < longRangeCoefficientDerivs.size(); i++)
derivs[force->getEnergyParameterDerivativeName(i)] += longRangeCoefficientDerivs[i]/volume;
return longRangeCoefficient/volume;
}
private:
ComputeContext& cc;
double& longRangeCoefficient;
vector<double>& longRangeCoefficientDerivs;
CustomNonbondedForce* force;
};
class CommonCalcCustomNonbondedForceKernel::LongRangeTask : public ComputeContext::WorkTask {
public:
LongRangeTask(ComputeContext& cc, Context& context, CustomNonbondedForceImpl::LongRangeCorrectionData& data,
double& longRangeCoefficient, vector<double>& longRangeCoefficientDerivs, CustomNonbondedForce* force) :
cc(cc), context(context), data(data), longRangeCoefficient(longRangeCoefficient),
longRangeCoefficientDerivs(longRangeCoefficientDerivs), force(force) {
}
void execute() {
CustomNonbondedForceImpl::calcLongRangeCorrection(*force, data, context, longRangeCoefficient, longRangeCoefficientDerivs, cc.getThreadPool());
}
private:
ComputeContext& cc;
Context& context;
CustomNonbondedForceImpl::LongRangeCorrectionData& data;
double& longRangeCoefficient;
vector<double>& longRangeCoefficientDerivs;
CustomNonbondedForce* force;
};
CommonCalcCustomNonbondedForceKernel::~CommonCalcCustomNonbondedForceKernel() { CommonCalcCustomNonbondedForceKernel::~CommonCalcCustomNonbondedForceKernel() {
cc.setAsCurrent(); cc.setAsCurrent();
if (params != NULL) if (params != NULL)
...@@ -1912,6 +1952,8 @@ void CommonCalcCustomNonbondedForceKernel::initialize(const System& system, cons ...@@ -1912,6 +1952,8 @@ void CommonCalcCustomNonbondedForceKernel::initialize(const System& system, cons
if (force.getNonbondedMethod() == CustomNonbondedForce::CutoffPeriodic && force.getUseLongRangeCorrection() && cc.getContextIndex() == 0) { if (force.getNonbondedMethod() == CustomNonbondedForce::CutoffPeriodic && force.getUseLongRangeCorrection() && cc.getContextIndex() == 0) {
forceCopy = new CustomNonbondedForce(force); forceCopy = new CustomNonbondedForce(force);
longRangeCorrectionData = CustomNonbondedForceImpl::prepareLongRangeCorrection(force);
cc.addPostComputation(new LongRangePostComputation(cc, longRangeCoefficient, longRangeCoefficientDerivs, forceCopy));
hasInitializedLongRangeCorrection = false; hasInitializedLongRangeCorrection = false;
} }
else { else {
...@@ -2199,6 +2241,7 @@ double CommonCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool ...@@ -2199,6 +2241,7 @@ double CommonCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool
// When using a neighbor list, run the whole calculation on a single device. // When using a neighbor list, run the whole calculation on a single device.
return 0.0; return 0.0;
} }
bool recomputeLongRangeCorrection = !hasInitializedLongRangeCorrection;
if (globals.isInitialized()) { if (globals.isInitialized()) {
bool changed = false; bool changed = false;
for (int i = 0; i < (int) globalParamNames.size(); i++) { for (int i = 0; i < (int) globalParamNames.size(); i++) {
...@@ -2209,14 +2252,12 @@ double CommonCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool ...@@ -2209,14 +2252,12 @@ double CommonCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool
} }
if (changed) { if (changed) {
globals.upload(globalParamValues); globals.upload(globalParamValues);
if (forceCopy != NULL) { if (forceCopy != NULL)
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); recomputeLongRangeCorrection = true;
hasInitializedLongRangeCorrection = true;
}
} }
} }
if (!hasInitializedLongRangeCorrection) { if (recomputeLongRangeCorrection) {
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); cc.getWorkThread().addTask(new LongRangeTask(cc, context.getOwner(), longRangeCorrectionData, longRangeCoefficient, longRangeCoefficientDerivs, forceCopy));
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
if (interactionGroupData.isInitialized()) { if (interactionGroupData.isInitialized()) {
...@@ -2264,13 +2305,7 @@ double CommonCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool ...@@ -2264,13 +2305,7 @@ double CommonCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool
setPeriodicBoxArgs(cc, interactionGroupKernel, 6); setPeriodicBoxArgs(cc, interactionGroupKernel, 6);
interactionGroupKernel->execute(numGroupThreadBlocks*forceThreadBlockSize, forceThreadBlockSize); interactionGroupKernel->execute(numGroupThreadBlocks*forceThreadBlockSize, forceThreadBlockSize);
} }
Vec3 a, b, c; return 0;
cc.getPeriodicBoxVectors(a, b, c);
double volume = a[0]*b[1]*c[2];
map<string, double>& derivs = cc.getEnergyParamDerivWorkspace();
for (int i = 0; i < longRangeCoefficientDerivs.size(); i++)
derivs[forceCopy->getEnergyParameterDerivativeName(i)] += longRangeCoefficientDerivs[i]/volume;
return longRangeCoefficient/volume;
} }
void CommonCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force) { void CommonCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& context, const CustomNonbondedForce& force) {
...@@ -2296,8 +2331,9 @@ void CommonCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& ...@@ -2296,8 +2331,9 @@ void CommonCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl&
// If necessary, recompute the long range correction. // If necessary, recompute the long range correction.
if (forceCopy != NULL) { if (forceCopy != NULL) {
CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); longRangeCorrectionData = CustomNonbondedForceImpl::prepareLongRangeCorrection(force);
hasInitializedLongRangeCorrection = true; CustomNonbondedForceImpl::calcLongRangeCorrection(force, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, cc.getThreadPool());
hasInitializedLongRangeCorrection = false;
*forceCopy = force; *forceCopy = force;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2020 Stanford University and the Authors. * * Portions copyright (c) 2013-2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "CpuPlatform.h" #include "CpuPlatform.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/System.h" #include "openmm/System.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include <array> #include <array>
#include <tuple> #include <tuple>
...@@ -326,6 +327,7 @@ private: ...@@ -326,6 +327,7 @@ private:
double nonbondedCutoff, switchingDistance, periodicBoxSize[3], longRangeCoefficient; double nonbondedCutoff, switchingDistance, periodicBoxSize[3], longRangeCoefficient;
bool useSwitchingFunction, hasInitializedLongRangeCorrection; bool useSwitchingFunction, hasInitializedLongRangeCorrection;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
CustomNonbondedForceImpl::LongRangeCorrectionData longRangeCorrectionData;
std::map<std::string, double> globalParamValues; std::map<std::string, double> globalParamValues;
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
std::vector<std::string> parameterNames, globalParameterNames, energyParamDerivNames; std::vector<std::string> parameterNames, globalParameterNames, energyParamDerivNames;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2020 Stanford University and the Authors. * * Portions copyright (c) 2013-2021 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "openmm/Vec3.h" #include "openmm/Vec3.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h" #include "openmm/internal/NonbondedForceImpl.h"
#include "openmm/internal/vectorize.h" #include "openmm/internal/vectorize.h"
#include "lepton/CompiledExpression.h" #include "lepton/CompiledExpression.h"
...@@ -975,10 +974,13 @@ double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool inc ...@@ -975,10 +974,13 @@ double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool inc
// Add in the long range correction. // Add in the long range correction.
if (!hasInitializedLongRangeCorrection || (globalParamsChanged && forceCopy != NULL)) { if (!hasInitializedLongRangeCorrection) {
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); longRangeCorrectionData = CustomNonbondedForceImpl::prepareLongRangeCorrection(*forceCopy);
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, data.threads);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
else if (globalParamsChanged && forceCopy != NULL)
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, data.threads);
double volume = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]; double volume = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2];
energy += longRangeCoefficient/volume; energy += longRangeCoefficient/volume;
for (int i = 0; i < longRangeCoefficientDerivs.size(); i++) for (int i = 0; i < longRangeCoefficientDerivs.size(); i++)
...@@ -1004,7 +1006,8 @@ void CpuCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& con ...@@ -1004,7 +1006,8 @@ void CpuCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& con
// If necessary, recompute the long range correction. // If necessary, recompute the long range correction.
if (forceCopy != NULL) { if (forceCopy != NULL) {
CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); longRangeCorrectionData = CustomNonbondedForceImpl::prepareLongRangeCorrection(force);
CustomNonbondedForceImpl::calcLongRangeCorrection(force, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, data.threads);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
*forceCopy = force; *forceCopy = force;
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "ReferencePlatform.h" #include "ReferencePlatform.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "SimTKOpenMMRealType.h" #include "SimTKOpenMMRealType.h"
#include "ReferenceNeighborList.h" #include "ReferenceNeighborList.h"
#include "lepton/CompiledExpression.h" #include "lepton/CompiledExpression.h"
...@@ -686,6 +687,7 @@ private: ...@@ -686,6 +687,7 @@ private:
double nonbondedCutoff, switchingDistance, periodicBoxSize[3], longRangeCoefficient; double nonbondedCutoff, switchingDistance, periodicBoxSize[3], longRangeCoefficient;
bool useSwitchingFunction, hasInitializedLongRangeCorrection; bool useSwitchingFunction, hasInitializedLongRangeCorrection;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
CustomNonbondedForceImpl::LongRangeCorrectionData longRangeCorrectionData;
std::map<std::string, double> globalParamValues; std::map<std::string, double> globalParamValues;
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
Lepton::CompiledExpression energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
......
...@@ -76,7 +76,6 @@ ...@@ -76,7 +76,6 @@
#include "openmm/internal/CustomCentroidBondForceImpl.h" #include "openmm/internal/CustomCentroidBondForceImpl.h"
#include "openmm/internal/CustomCompoundBondForceImpl.h" #include "openmm/internal/CustomCompoundBondForceImpl.h"
#include "openmm/internal/CustomHbondForceImpl.h" #include "openmm/internal/CustomHbondForceImpl.h"
#include "openmm/internal/CustomNonbondedForceImpl.h"
#include "openmm/internal/CMAPTorsionForceImpl.h" #include "openmm/internal/CMAPTorsionForceImpl.h"
#include "openmm/internal/NonbondedForceImpl.h" #include "openmm/internal/NonbondedForceImpl.h"
#include "openmm/Integrator.h" #include "openmm/Integrator.h"
...@@ -1260,10 +1259,16 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo ...@@ -1260,10 +1259,16 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo
// Add in the long range correction. // Add in the long range correction.
if (!hasInitializedLongRangeCorrection || (globalParamsChanged && forceCopy != NULL)) { if (!hasInitializedLongRangeCorrection) {
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); longRangeCorrectionData = CustomNonbondedForceImpl::prepareLongRangeCorrection(*forceCopy);
ThreadPool threads;
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, threads);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
else if (globalParamsChanged && forceCopy != NULL) {
ThreadPool threads;
CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, threads);
}
double volume = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]; double volume = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2];
energy += longRangeCoefficient/volume; energy += longRangeCoefficient/volume;
for (int i = 0; i < longRangeCoefficientDerivs.size(); i++) for (int i = 0; i < longRangeCoefficientDerivs.size(); i++)
...@@ -1289,7 +1294,9 @@ void ReferenceCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImp ...@@ -1289,7 +1294,9 @@ void ReferenceCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImp
// If necessary, recompute the long range correction. // If necessary, recompute the long range correction.
if (forceCopy != NULL) { if (forceCopy != NULL) {
CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs); longRangeCorrectionData = CustomNonbondedForceImpl::prepareLongRangeCorrection(force);
ThreadPool threads;
CustomNonbondedForceImpl::calcLongRangeCorrection(force, longRangeCorrectionData, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs, threads);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
*forceCopy = force; *forceCopy = force;
} }
......
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