Commit 8e01339d authored by peastman's avatar peastman
Browse files

Continuing to implement derivatives with respect to parameters

parent cd566c63
...@@ -63,6 +63,10 @@ namespace OpenMM { ...@@ -63,6 +63,10 @@ namespace OpenMM {
* force->addPerAngleParameter("k"); * force->addPerAngleParameter("k");
* force->addPerAngleParameter("theta0"); * force->addPerAngleParameter("theta0");
* </pre></tt> * </pre></tt>
*
* This class also has the ability to compute derivatives of the potential energy with respect to global parameters.
* Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be
* computed. You can then query its value in a Context by calling getState() on it.
* *
* Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following * Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following
* functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions * functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions
...@@ -97,6 +101,13 @@ public: ...@@ -97,6 +101,13 @@ public:
int getNumGlobalParameters() const { int getNumGlobalParameters() const {
return globalParameters.size(); return globalParameters.size();
} }
/**
* Get the number of global parameters with respect to which the derivative of the energy
* should be computed.
*/
int getNumEnergyParameterDerivatives() const {
return energyParameterDerivatives.size();
}
/** /**
* Get the algebraic expression that gives the interaction energy for each angle * Get the algebraic expression that gives the interaction energy for each angle
*/ */
...@@ -162,6 +173,21 @@ public: ...@@ -162,6 +173,21 @@ public:
* @param defaultValue the default value of the parameter * @param defaultValue the default value of the parameter
*/ */
void setGlobalParameterDefaultValue(int index, double defaultValue); void setGlobalParameterDefaultValue(int index, double defaultValue);
/**
* Request that this Force compute the derivative of its energy with respect to a global parameter.
* The parameter must have already been added with addGlobalParameter().
*
* @param name the name of the parameter
*/
void addEnergyParameterDerivative(const std::string& name);
/**
* Get the name of a global parameter with respect to which this Force should compute the
* derivative of the energy.
*
* @param index the index of the parameter derivative, between 0 and getNumEnergyParameterDerivatives()
* @return the parameter name
*/
const std::string& getEnergyParameterDerivativeName(int index) const;
/** /**
* Add an angle term to the force field. * Add an angle term to the force field.
* *
...@@ -225,6 +251,7 @@ private: ...@@ -225,6 +251,7 @@ private:
std::vector<AngleParameterInfo> parameters; std::vector<AngleParameterInfo> parameters;
std::vector<GlobalParameterInfo> globalParameters; std::vector<GlobalParameterInfo> globalParameters;
std::vector<AngleInfo> angles; std::vector<AngleInfo> angles;
std::vector<int> energyParameterDerivatives;
bool usePeriodic; bool usePeriodic;
}; };
......
...@@ -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-2014 Stanford University and the Authors. * * Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -118,6 +118,10 @@ namespace OpenMM { ...@@ -118,6 +118,10 @@ namespace OpenMM {
* at the start of the simulation. Furthermore, that precomputation must be repeated every time a global parameter changes * at the start of the simulation. Furthermore, that precomputation must be repeated every time a global parameter changes
* (or when you modify per-particle parameters by calling updateParametersInContext()). This means that if parameters change * (or when you modify per-particle parameters by calling updateParametersInContext()). This means that if parameters change
* frequently, the long range correction can be very slow. For this reason, it is disabled by default. * frequently, the long range correction can be very slow. For this reason, it is disabled by default.
*
* This class also has the ability to compute derivatives of the potential energy with respect to global parameters.
* Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be
* computed. You can then query its value in a Context by calling getState() on it.
* *
* Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following * Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following
* functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions * functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions
...@@ -204,6 +208,13 @@ public: ...@@ -204,6 +208,13 @@ public:
int getNumInteractionGroups() const { int getNumInteractionGroups() const {
return interactionGroups.size(); return interactionGroups.size();
} }
/**
* Get the number of global parameters with respect to which the derivative of the energy
* should be computed.
*/
int getNumEnergyParameterDerivatives() const {
return energyParameterDerivatives.size();
}
/** /**
* Get the algebraic expression that gives the interaction energy between two particles * Get the algebraic expression that gives the interaction energy between two particles
*/ */
...@@ -321,6 +332,21 @@ public: ...@@ -321,6 +332,21 @@ public:
* @param defaultValue the default value of the parameter * @param defaultValue the default value of the parameter
*/ */
void setGlobalParameterDefaultValue(int index, double defaultValue); void setGlobalParameterDefaultValue(int index, double defaultValue);
/**
* Request that this Force compute the derivative of its energy with respect to a global parameter.
* The parameter must have already been added with addGlobalParameter().
*
* @param name the name of the parameter
*/
void addEnergyParameterDerivative(const std::string& name);
/**
* Get the name of a global parameter with respect to which this Force should compute the
* derivative of the energy.
*
* @param index the index of the parameter derivative, between 0 and getNumEnergyParameterDerivatives()
* @return the parameter name
*/
const std::string& getEnergyParameterDerivativeName(int index) const;
/** /**
* Add the nonbonded force parameters for a particle. This should be called once for each particle * Add the nonbonded force parameters for a particle. This should be called once for each particle
* in the System. When it is called for the i'th time, it specifies the parameters for the i'th particle. * in the System. When it is called for the i'th time, it specifies the parameters for the i'th particle.
...@@ -494,6 +520,7 @@ private: ...@@ -494,6 +520,7 @@ private:
std::vector<ExclusionInfo> exclusions; std::vector<ExclusionInfo> exclusions;
std::vector<FunctionInfo> functions; std::vector<FunctionInfo> functions;
std::vector<InteractionGroupInfo> interactionGroups; std::vector<InteractionGroupInfo> interactionGroups;
std::vector<int> energyParameterDerivatives;
}; };
/** /**
......
...@@ -63,6 +63,10 @@ namespace OpenMM { ...@@ -63,6 +63,10 @@ namespace OpenMM {
* force->addPerTorsionParameter("k"); * force->addPerTorsionParameter("k");
* force->addPerTorsionParameter("theta0"); * force->addPerTorsionParameter("theta0");
* </pre></tt> * </pre></tt>
*
* This class also has the ability to compute derivatives of the potential energy with respect to global parameters.
* Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be
* computed. You can then query its value in a Context by calling getState() on it.
* *
* Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following * Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following
* functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions * functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select. All trigonometric functions
...@@ -97,6 +101,13 @@ public: ...@@ -97,6 +101,13 @@ public:
int getNumGlobalParameters() const { int getNumGlobalParameters() const {
return globalParameters.size(); return globalParameters.size();
} }
/**
* Get the number of global parameters with respect to which the derivative of the energy
* should be computed.
*/
int getNumEnergyParameterDerivatives() const {
return energyParameterDerivatives.size();
}
/** /**
* Get the algebraic expression that gives the interaction energy for each torsion * Get the algebraic expression that gives the interaction energy for each torsion
*/ */
...@@ -162,6 +173,21 @@ public: ...@@ -162,6 +173,21 @@ public:
* @param defaultValue the default value of the parameter * @param defaultValue the default value of the parameter
*/ */
void setGlobalParameterDefaultValue(int index, double defaultValue); void setGlobalParameterDefaultValue(int index, double defaultValue);
/**
* Request that this Force compute the derivative of its energy with respect to a global parameter.
* The parameter must have already been added with addGlobalParameter().
*
* @param name the name of the parameter
*/
void addEnergyParameterDerivative(const std::string& name);
/**
* Get the name of a global parameter with respect to which this Force should compute the
* derivative of the energy.
*
* @param index the index of the parameter derivative, between 0 and getNumEnergyParameterDerivatives()
* @return the parameter name
*/
const std::string& getEnergyParameterDerivativeName(int index) const;
/** /**
* Add a torsion term to the force field. * Add a torsion term to the force field.
* *
...@@ -228,6 +254,7 @@ private: ...@@ -228,6 +254,7 @@ private:
std::vector<TorsionParameterInfo> parameters; std::vector<TorsionParameterInfo> parameters;
std::vector<GlobalParameterInfo> globalParameters; std::vector<GlobalParameterInfo> globalParameters;
std::vector<TorsionInfo> torsions; std::vector<TorsionInfo> torsions;
std::vector<int> energyParameterDerivatives;
bool usePeriodic; bool usePeriodic;
}; };
......
...@@ -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-2014 Stanford University and the Authors. * * Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -63,9 +63,10 @@ public: ...@@ -63,9 +63,10 @@ public:
void updateParametersInContext(ContextImpl& context); void updateParametersInContext(ContextImpl& context);
/** /**
* 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. * long range correction to the energy. If the Force computes parameter derivatives,
* also compute the corresponding derivatives of the correction.
*/ */
static double calcLongRangeCorrection(const CustomNonbondedForce& force, const Context& context); static void calcLongRangeCorrection(const CustomNonbondedForce& force, const Context& context, double& coefficient, std::vector<double>& derivatives);
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 CustomNonbondedForce& force, const Context& context);
......
...@@ -95,6 +95,20 @@ void CustomAngleForce::setGlobalParameterDefaultValue(int index, double defaultV ...@@ -95,6 +95,20 @@ void CustomAngleForce::setGlobalParameterDefaultValue(int index, double defaultV
globalParameters[index].defaultValue = defaultValue; globalParameters[index].defaultValue = defaultValue;
} }
void CustomAngleForce::addEnergyParameterDerivative(const string& name) {
for (int i = 0; i < globalParameters.size(); i++)
if (name == globalParameters[i].name) {
energyParameterDerivatives.push_back(i);
return;
}
throw OpenMMException(string("addEnergyParameterDerivative: Unknown global parameter '"+name+"'"));
}
const string& CustomAngleForce::getEnergyParameterDerivativeName(int index) const {
ASSERT_VALID_INDEX(index, energyParameterDerivatives);
return globalParameters[energyParameterDerivatives[index]].name;
}
int CustomAngleForce::addAngle(int particle1, int particle2, int particle3, const vector<double>& parameters) { int CustomAngleForce::addAngle(int particle1, int particle2, int particle3, const vector<double>& parameters) {
angles.push_back(AngleInfo(particle1, particle2, particle3, parameters)); angles.push_back(AngleInfo(particle1, particle2, particle3, parameters));
return angles.size()-1; return angles.size()-1;
......
...@@ -61,6 +61,7 @@ CustomNonbondedForce::CustomNonbondedForce(const CustomNonbondedForce& rhs) { ...@@ -61,6 +61,7 @@ CustomNonbondedForce::CustomNonbondedForce(const CustomNonbondedForce& rhs) {
useLongRangeCorrection = rhs.useLongRangeCorrection; useLongRangeCorrection = rhs.useLongRangeCorrection;
parameters = rhs.parameters; parameters = rhs.parameters;
globalParameters = rhs.globalParameters; globalParameters = rhs.globalParameters;
energyParameterDerivatives = rhs.energyParameterDerivatives;
particles = rhs.particles; particles = rhs.particles;
exclusions = rhs.exclusions; exclusions = rhs.exclusions;
interactionGroups = rhs.interactionGroups; interactionGroups = rhs.interactionGroups;
...@@ -161,6 +162,20 @@ void CustomNonbondedForce::setGlobalParameterDefaultValue(int index, double defa ...@@ -161,6 +162,20 @@ void CustomNonbondedForce::setGlobalParameterDefaultValue(int index, double defa
globalParameters[index].defaultValue = defaultValue; globalParameters[index].defaultValue = defaultValue;
} }
void CustomNonbondedForce::addEnergyParameterDerivative(const string& name) {
for (int i = 0; i < globalParameters.size(); i++)
if (name == globalParameters[i].name) {
energyParameterDerivatives.push_back(i);
return;
}
throw OpenMMException(string("addEnergyParameterDerivative: Unknown global parameter '"+name+"'"));
}
const string& CustomNonbondedForce::getEnergyParameterDerivativeName(int index) const {
ASSERT_VALID_INDEX(index, energyParameterDerivatives);
return globalParameters[energyParameterDerivatives[index]].name;
}
int CustomNonbondedForce::addParticle(const vector<double>& parameters) { int CustomNonbondedForce::addParticle(const vector<double>& parameters) {
particles.push_back(ParticleInfo(parameters)); particles.push_back(ParticleInfo(parameters));
return particles.size()-1; return particles.size()-1;
......
...@@ -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-2014 Stanford University and the Authors. * * Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -157,16 +157,11 @@ void CustomNonbondedForceImpl::updateParametersInContext(ContextImpl& context) { ...@@ -157,16 +157,11 @@ void CustomNonbondedForceImpl::updateParametersInContext(ContextImpl& context) {
kernel.getAs<CalcCustomNonbondedForceKernel>().copyParametersToContext(context, owner); kernel.getAs<CalcCustomNonbondedForceKernel>().copyParametersToContext(context, owner);
} }
double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForce& force, const Context& context) { void CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedForce& force, const Context& context, double& coefficient, vector<double>& derivatives) {
if (force.getNonbondedMethod() == CustomNonbondedForce::NoCutoff || force.getNonbondedMethod() == CustomNonbondedForce::CutoffNonPeriodic) if (force.getNonbondedMethod() == CustomNonbondedForce::NoCutoff || force.getNonbondedMethod() == CustomNonbondedForce::CutoffNonPeriodic) {
return 0.0; coefficient = 0.0;
return;
// Parse the energy expression. }
map<string, Lepton::CustomFunction*> functions;
for (int i = 0; i < force.getNumFunctions(); i++)
functions[force.getTabulatedFunctionName(i)] = createReferenceTabulatedFunction(force.getTabulatedFunction(i));
Lepton::CompiledExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).createCompiledExpression();
// 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.
...@@ -223,17 +218,35 @@ double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedFo ...@@ -223,17 +218,35 @@ double CustomNonbondedForceImpl::calcLongRangeCorrection(const CustomNonbondedFo
} }
} }
} }
// Loop over all pairs of classes to compute the coefficient. // Compute the coefficient.
map<string, Lepton::CustomFunction*> functions;
for (int i = 0; i < force.getNumFunctions(); i++)
functions[force.getTabulatedFunctionName(i)] = createReferenceTabulatedFunction(force.getTabulatedFunction(i));
double nPart = (double) numParticles;
double numInteractions = (nPart*(nPart+1))/2;
Lepton::CompiledExpression expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).createCompiledExpression();
double sum = 0; double sum = 0;
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++)
sum += interactionCount[make_pair(i, j)]*integrateInteraction(expression, classes[i], classes[j], force, context); sum += interactionCount[make_pair(i, j)]*integrateInteraction(expression, classes[i], classes[j], force, context);
double nPart = (double) numParticles;
double numInteractions = (nPart*(nPart+1))/2;
sum /= numInteractions; sum /= numInteractions;
return 2*M_PI*nPart*nPart*sum; coefficient = 2*M_PI*nPart*nPart*sum;
// Now do the same for parameter derivatives.
int numDerivs = force.getNumEnergyParameterDerivatives();
derivatives.resize(numDerivs);
for (int k = 0; k < numDerivs; k++) {
expression = Lepton::Parser::parse(force.getEnergyFunction(), functions).differentiate(force.getEnergyParameterDerivativeName(k)).createCompiledExpression();
sum = 0;
for (int i = 0; i < numClasses; i++)
for (int j = i; j < numClasses; j++)
sum += interactionCount[make_pair(i, j)]*integrateInteraction(expression, classes[i], classes[j], force, context);
sum /= numInteractions;
derivatives[k] = 2*M_PI*nPart*nPart*sum;
}
} }
double CustomNonbondedForceImpl::integrateInteraction(Lepton::CompiledExpression& expression, const vector<double>& params1, const vector<double>& params2, double CustomNonbondedForceImpl::integrateInteraction(Lepton::CompiledExpression& expression, const vector<double>& params1, const vector<double>& params2,
......
...@@ -95,6 +95,20 @@ void CustomTorsionForce::setGlobalParameterDefaultValue(int index, double defaul ...@@ -95,6 +95,20 @@ void CustomTorsionForce::setGlobalParameterDefaultValue(int index, double defaul
globalParameters[index].defaultValue = defaultValue; globalParameters[index].defaultValue = defaultValue;
} }
void CustomTorsionForce::addEnergyParameterDerivative(const string& name) {
for (int i = 0; i < globalParameters.size(); i++)
if (name == globalParameters[i].name) {
energyParameterDerivatives.push_back(i);
return;
}
throw OpenMMException(string("addEnergyParameterDerivative: Unknown global parameter '"+name+"'"));
}
const string& CustomTorsionForce::getEnergyParameterDerivativeName(int index) const {
ASSERT_VALID_INDEX(index, energyParameterDerivatives);
return globalParameters[energyParameterDerivatives[index]].name;
}
int CustomTorsionForce::addTorsion(int particle1, int particle2, int particle3, int particle4, const vector<double>& parameters) { int CustomTorsionForce::addTorsion(int particle1, int particle2, int particle3, int particle4, const vector<double>& parameters) {
torsions.push_back(TorsionInfo(particle1, particle2, particle3, particle4, parameters)); torsions.push_back(TorsionInfo(particle1, particle2, particle3, particle4, parameters));
return torsions.size()-1; return torsions.size()-1;
......
...@@ -315,6 +315,7 @@ private: ...@@ -315,6 +315,7 @@ private:
std::vector<std::set<int> > exclusions; std::vector<std::set<int> > exclusions;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<std::string> parameterNames, globalParameterNames;
std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups; std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups;
std::vector<double> longRangeCoefficientDerivs;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
CpuCustomNonbondedForce* nonbonded; CpuCustomNonbondedForce* nonbonded;
}; };
......
...@@ -880,7 +880,7 @@ double CpuCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool inc ...@@ -880,7 +880,7 @@ 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 || (globalParamsChanged && forceCopy != NULL)) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
energy += longRangeCoefficient/(boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]); energy += longRangeCoefficient/(boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]);
...@@ -905,7 +905,7 @@ void CpuCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& con ...@@ -905,7 +905,7 @@ 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) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
*forceCopy = force; *forceCopy = force;
} }
......
...@@ -735,6 +735,7 @@ private: ...@@ -735,6 +735,7 @@ private:
std::vector<float> globalParamValues; std::vector<float> globalParamValues;
std::vector<CudaArray*> tabulatedFunctions; std::vector<CudaArray*> tabulatedFunctions;
double longRangeCoefficient; double longRangeCoefficient;
std::vector<double> longRangeCoefficientDerivs;
bool hasInitializedLongRangeCorrection, hasInitializedKernel; bool hasInitializedLongRangeCorrection, hasInitializedKernel;
int numGroupThreadBlocks; int numGroupThreadBlocks;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
......
...@@ -2540,13 +2540,13 @@ double CudaCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool in ...@@ -2540,13 +2540,13 @@ double CudaCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool in
if (changed) { if (changed) {
globals->upload(globalParamValues); globals->upload(globalParamValues);
if (forceCopy != NULL) { if (forceCopy != NULL) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
} }
} }
if (!hasInitializedLongRangeCorrection) { if (!hasInitializedLongRangeCorrection) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
if (interactionGroupData != NULL) { if (interactionGroupData != NULL) {
...@@ -2596,7 +2596,7 @@ void CudaCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& co ...@@ -2596,7 +2596,7 @@ void CudaCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& co
// If necessary, recompute the long range correction. // If necessary, recompute the long range correction.
if (forceCopy != NULL) { if (forceCopy != NULL) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
*forceCopy = force; *forceCopy = force;
} }
......
...@@ -715,6 +715,7 @@ private: ...@@ -715,6 +715,7 @@ private:
std::vector<cl_float> globalParamValues; std::vector<cl_float> globalParamValues;
std::vector<OpenCLArray*> tabulatedFunctions; std::vector<OpenCLArray*> tabulatedFunctions;
double longRangeCoefficient; double longRangeCoefficient;
std::vector<double> longRangeCoefficientDerivs;
bool hasInitializedLongRangeCorrection, hasInitializedKernel; bool hasInitializedLongRangeCorrection, hasInitializedKernel;
int numGroupThreadBlocks; int numGroupThreadBlocks;
CustomNonbondedForce* forceCopy; CustomNonbondedForce* forceCopy;
......
...@@ -2608,13 +2608,13 @@ double OpenCLCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool ...@@ -2608,13 +2608,13 @@ double OpenCLCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bool
if (changed) { if (changed) {
globals->upload(globalParamValues); globals->upload(globalParamValues);
if (forceCopy != NULL) { if (forceCopy != NULL) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
} }
} }
if (!hasInitializedLongRangeCorrection) { if (!hasInitializedLongRangeCorrection) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
if (interactionGroupData != NULL) { if (interactionGroupData != NULL) {
...@@ -2662,7 +2662,7 @@ void OpenCLCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl& ...@@ -2662,7 +2662,7 @@ void OpenCLCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImpl&
// If necessary, recompute the long range correction. // If necessary, recompute the long range correction.
if (forceCopy != NULL) { if (forceCopy != NULL) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
*forceCopy = force; *forceCopy = force;
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define __ReferenceCustomAngleIxn_H__ #define __ReferenceCustomAngleIxn_H__
#include "ReferenceBondIxn.h" #include "ReferenceBondIxn.h"
#include "lepton/CompiledExpression.h" #include "openmm/internal/CompiledExpressionSet.h"
namespace OpenMM { namespace OpenMM {
...@@ -34,10 +34,10 @@ class ReferenceCustomAngleIxn : public ReferenceBondIxn { ...@@ -34,10 +34,10 @@ class ReferenceCustomAngleIxn : public ReferenceBondIxn {
private: private:
Lepton::CompiledExpression energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::CompiledExpression forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<double*> energyParams; std::vector<Lepton::CompiledExpression> energyParamDerivExpressions;
std::vector<double*> forceParams; CompiledExpressionSet expressionSet;
double* energyTheta; std::vector<int> angleParamIndex;
double* forceTheta; int thetaIndex;
int numParameters; int numParameters;
bool usePeriodic; bool usePeriodic;
RealVec boxVectors[3]; RealVec boxVectors[3];
...@@ -51,7 +51,8 @@ class ReferenceCustomAngleIxn : public ReferenceBondIxn { ...@@ -51,7 +51,8 @@ class ReferenceCustomAngleIxn : public ReferenceBondIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomAngleIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression, ReferenceCustomAngleIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters); const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters,
const std::vector<Lepton::CompiledExpression> energyParamDerivExpressions);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "ReferenceBondIxn.h" #include "ReferenceBondIxn.h"
#include "openmm/internal/CompiledExpressionSet.h" #include "openmm/internal/CompiledExpressionSet.h"
#include "lepton/CompiledExpression.h"
namespace OpenMM { namespace OpenMM {
......
/* Portions copyright (c) 2009-2013 Stanford University and Simbios. /* Portions copyright (c) 2009-2016 Stanford University and Simbios.
* Contributors: Peter Eastman * Contributors: Peter Eastman
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "ReferencePairIxn.h" #include "ReferencePairIxn.h"
#include "ReferenceNeighborList.h" #include "ReferenceNeighborList.h"
#include "lepton/CompiledExpression.h" #include "openmm/internal/CompiledExpressionSet.h"
#include <map> #include <map>
#include <set> #include <set>
#include <utility> #include <utility>
...@@ -48,10 +48,10 @@ class ReferenceCustomNonbondedIxn { ...@@ -48,10 +48,10 @@ class ReferenceCustomNonbondedIxn {
Lepton::CompiledExpression energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::CompiledExpression forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<std::string> paramNames; std::vector<std::string> paramNames;
std::vector<double*> energyParticleParams; std::vector<Lepton::CompiledExpression> energyParamDerivExpressions;
std::vector<double*> forceParticleParams; CompiledExpressionSet expressionSet;
double* energyR; std::vector<int> particleParamIndex;
double* forceR; int rIndex;
std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups; std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups;
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -69,7 +69,7 @@ class ReferenceCustomNonbondedIxn { ...@@ -69,7 +69,7 @@ class ReferenceCustomNonbondedIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
void calculateOneIxn(int atom1, int atom2, std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& forces, void calculateOneIxn(int atom1, int atom2, std::vector<OpenMM::RealVec>& atomCoordinates, std::vector<OpenMM::RealVec>& forces,
RealOpenMM* energyByAtom, RealOpenMM* totalEnergy); RealOpenMM* energyByAtom, RealOpenMM* totalEnergy, double* energyParamDerivs);
public: public:
...@@ -81,7 +81,7 @@ class ReferenceCustomNonbondedIxn { ...@@ -81,7 +81,7 @@ class ReferenceCustomNonbondedIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomNonbondedIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression, ReferenceCustomNonbondedIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames); const std::vector<std::string>& parameterNames, const std::vector<Lepton::CompiledExpression> energyParamDerivExpressions);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -155,7 +155,8 @@ class ReferenceCustomNonbondedIxn { ...@@ -155,7 +155,8 @@ class ReferenceCustomNonbondedIxn {
void calculatePairIxn(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates, void calculatePairIxn(int numberOfAtoms, std::vector<OpenMM::RealVec>& atomCoordinates,
RealOpenMM** atomParameters, std::vector<std::set<int> >& exclusions, RealOpenMM** atomParameters, std::vector<std::set<int> >& exclusions,
RealOpenMM* fixedParameters, const std::map<std::string, double>& globalParameters, RealOpenMM* fixedParameters, const std::map<std::string, double>& globalParameters,
std::vector<OpenMM::RealVec>& forces, RealOpenMM* energyByAtom, RealOpenMM* totalEnergy); std::vector<OpenMM::RealVec>& forces, RealOpenMM* energyByAtom, RealOpenMM* totalEnergy,
double* energyParamDerivs);
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define __ReferenceCustomTorsionIxn_H__ #define __ReferenceCustomTorsionIxn_H__
#include "ReferenceBondIxn.h" #include "ReferenceBondIxn.h"
#include "lepton/CompiledExpression.h" #include "openmm/internal/CompiledExpressionSet.h"
namespace OpenMM { namespace OpenMM {
...@@ -34,10 +34,10 @@ class ReferenceCustomTorsionIxn : public ReferenceBondIxn { ...@@ -34,10 +34,10 @@ class ReferenceCustomTorsionIxn : public ReferenceBondIxn {
private: private:
Lepton::CompiledExpression energyExpression; Lepton::CompiledExpression energyExpression;
Lepton::CompiledExpression forceExpression; Lepton::CompiledExpression forceExpression;
std::vector<double*> energyParams; std::vector<Lepton::CompiledExpression> energyParamDerivExpressions;
std::vector<double*> forceParams; CompiledExpressionSet expressionSet;
double* energyTheta; std::vector<int> torsionParamIndex;
double* forceTheta; int thetaIndex;
int numParameters; int numParameters;
bool usePeriodic; bool usePeriodic;
RealVec boxVectors[3]; RealVec boxVectors[3];
...@@ -51,7 +51,8 @@ class ReferenceCustomTorsionIxn : public ReferenceBondIxn { ...@@ -51,7 +51,8 @@ class ReferenceCustomTorsionIxn : public ReferenceBondIxn {
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceCustomTorsionIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression, ReferenceCustomTorsionIxn(const Lepton::CompiledExpression& energyExpression, const Lepton::CompiledExpression& forceExpression,
const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters); const std::vector<std::string>& parameterNames, std::map<std::string, double> globalParameters,
const std::vector<Lepton::CompiledExpression> energyParamDerivExpressions);
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
......
...@@ -404,7 +404,8 @@ private: ...@@ -404,7 +404,8 @@ private:
int **angleIndexArray; int **angleIndexArray;
RealOpenMM **angleParamArray; RealOpenMM **angleParamArray;
Lepton::CompiledExpression energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<Lepton::CompiledExpression> energyParamDerivExpressions;
std::vector<std::string> parameterNames, globalParameterNames, energyParamDerivNames;
bool usePeriodic; bool usePeriodic;
}; };
...@@ -557,7 +558,8 @@ private: ...@@ -557,7 +558,8 @@ private:
int **torsionIndexArray; int **torsionIndexArray;
RealOpenMM **torsionParamArray; RealOpenMM **torsionParamArray;
Lepton::CompiledExpression energyExpression, forceExpression; Lepton::CompiledExpression energyExpression, forceExpression;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<Lepton::CompiledExpression> energyParamDerivExpressions;
std::vector<std::string> parameterNames, globalParameterNames, energyParamDerivNames;
bool usePeriodic; bool usePeriodic;
}; };
...@@ -654,8 +656,10 @@ private: ...@@ -654,8 +656,10 @@ private:
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;
std::vector<std::string> parameterNames, globalParameterNames; std::vector<Lepton::CompiledExpression> energyParamDerivExpressions;
std::vector<std::string> parameterNames, globalParameterNames, energyParamDerivNames;
std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups; std::vector<std::pair<std::set<int>, std::set<int> > > interactionGroups;
std::vector<double> longRangeCoefficientDerivs;
NonbondedMethod nonbondedMethod; NonbondedMethod nonbondedMethod;
NeighborList* neighborList; NeighborList* neighborList;
}; };
......
...@@ -582,6 +582,11 @@ void ReferenceCalcCustomAngleForceKernel::initialize(const System& system, const ...@@ -582,6 +582,11 @@ void ReferenceCalcCustomAngleForceKernel::initialize(const System& system, const
parameterNames.push_back(force.getPerAngleParameterName(i)); parameterNames.push_back(force.getPerAngleParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) for (int i = 0; i < force.getNumGlobalParameters(); i++)
globalParameterNames.push_back(force.getGlobalParameterName(i)); globalParameterNames.push_back(force.getGlobalParameterName(i));
for (int i = 0; i < force.getNumEnergyParameterDerivatives(); i++) {
string param = force.getEnergyParameterDerivativeName(i);
energyParamDerivNames.push_back(param);
energyParamDerivExpressions.push_back(expression.differentiate(param).createCompiledExpression());
}
set<string> variables; set<string> variables;
variables.insert("theta"); variables.insert("theta");
variables.insert(parameterNames.begin(), parameterNames.end()); variables.insert(parameterNames.begin(), parameterNames.end());
...@@ -596,11 +601,15 @@ double ReferenceCalcCustomAngleForceKernel::execute(ContextImpl& context, bool i ...@@ -596,11 +601,15 @@ double ReferenceCalcCustomAngleForceKernel::execute(ContextImpl& context, bool i
map<string, double> globalParameters; map<string, double> globalParameters;
for (int i = 0; i < (int) globalParameterNames.size(); i++) for (int i = 0; i < (int) globalParameterNames.size(); i++)
globalParameters[globalParameterNames[i]] = context.getParameter(globalParameterNames[i]); globalParameters[globalParameterNames[i]] = context.getParameter(globalParameterNames[i]);
ReferenceBondForce refBondForce; ReferenceCustomAngleIxn customAngle(energyExpression, forceExpression, parameterNames, globalParameters, energyParamDerivExpressions);
ReferenceCustomAngleIxn customAngle(energyExpression, forceExpression, parameterNames, globalParameters);
if (usePeriodic) if (usePeriodic)
customAngle.setPeriodic(extractBoxVectors(context)); customAngle.setPeriodic(extractBoxVectors(context));
refBondForce.calculateForce(numAngles, angleIndexArray, posData, angleParamArray, forceData, includeEnergy ? &energy : NULL, customAngle); vector<double> energyParamDerivValues(energyParamDerivNames.size()+1, 0.0);
for (int i = 0; i < numAngles; i++)
customAngle.calculateBondIxn(angleIndexArray[i], posData, angleParamArray[i], forceData, includeEnergy ? &energy : NULL, &energyParamDerivValues[0]);
map<string, double>& energyParamDerivs = extractEnergyParameterDerivatives(context);
for (int i = 0; i < energyParamDerivNames.size(); i++)
energyParamDerivs[energyParamDerivNames[i]] += energyParamDerivValues[i];
return energy; return energy;
} }
...@@ -843,6 +852,11 @@ void ReferenceCalcCustomTorsionForceKernel::initialize(const System& system, con ...@@ -843,6 +852,11 @@ void ReferenceCalcCustomTorsionForceKernel::initialize(const System& system, con
parameterNames.push_back(force.getPerTorsionParameterName(i)); parameterNames.push_back(force.getPerTorsionParameterName(i));
for (int i = 0; i < force.getNumGlobalParameters(); i++) for (int i = 0; i < force.getNumGlobalParameters(); i++)
globalParameterNames.push_back(force.getGlobalParameterName(i)); globalParameterNames.push_back(force.getGlobalParameterName(i));
for (int i = 0; i < force.getNumEnergyParameterDerivatives(); i++) {
string param = force.getEnergyParameterDerivativeName(i);
energyParamDerivNames.push_back(param);
energyParamDerivExpressions.push_back(expression.differentiate(param).createCompiledExpression());
}
set<string> variables; set<string> variables;
variables.insert("theta"); variables.insert("theta");
variables.insert(parameterNames.begin(), parameterNames.end()); variables.insert(parameterNames.begin(), parameterNames.end());
...@@ -857,11 +871,15 @@ double ReferenceCalcCustomTorsionForceKernel::execute(ContextImpl& context, bool ...@@ -857,11 +871,15 @@ double ReferenceCalcCustomTorsionForceKernel::execute(ContextImpl& context, bool
map<string, double> globalParameters; map<string, double> globalParameters;
for (int i = 0; i < (int) globalParameterNames.size(); i++) for (int i = 0; i < (int) globalParameterNames.size(); i++)
globalParameters[globalParameterNames[i]] = context.getParameter(globalParameterNames[i]); globalParameters[globalParameterNames[i]] = context.getParameter(globalParameterNames[i]);
ReferenceBondForce refBondForce; ReferenceCustomTorsionIxn customTorsion(energyExpression, forceExpression, parameterNames, globalParameters, energyParamDerivExpressions);
ReferenceCustomTorsionIxn customTorsion(energyExpression, forceExpression, parameterNames, globalParameters);
if (usePeriodic) if (usePeriodic)
customTorsion.setPeriodic(extractBoxVectors(context)); customTorsion.setPeriodic(extractBoxVectors(context));
refBondForce.calculateForce(numTorsions, torsionIndexArray, posData, torsionParamArray, forceData, includeEnergy ? &energy : NULL, customTorsion); vector<double> energyParamDerivValues(energyParamDerivNames.size()+1, 0.0);
for (int i = 0; i < numTorsions; i++)
customTorsion.calculateBondIxn(torsionIndexArray[i], posData, torsionParamArray[i], forceData, includeEnergy ? &energy : NULL, &energyParamDerivValues[0]);
map<string, double>& energyParamDerivs = extractEnergyParameterDerivatives(context);
for (int i = 0; i < energyParamDerivNames.size(); i++)
energyParamDerivs[energyParamDerivNames[i]] += energyParamDerivValues[i];
return energy; return energy;
} }
...@@ -1108,6 +1126,11 @@ void ReferenceCalcCustomNonbondedForceKernel::initialize(const System& system, c ...@@ -1108,6 +1126,11 @@ void ReferenceCalcCustomNonbondedForceKernel::initialize(const System& system, c
globalParameterNames.push_back(force.getGlobalParameterName(i)); globalParameterNames.push_back(force.getGlobalParameterName(i));
globalParamValues[force.getGlobalParameterName(i)] = force.getGlobalParameterDefaultValue(i); globalParamValues[force.getGlobalParameterName(i)] = force.getGlobalParameterDefaultValue(i);
} }
for (int i = 0; i < force.getNumEnergyParameterDerivatives(); i++) {
string param = force.getEnergyParameterDerivativeName(i);
energyParamDerivNames.push_back(param);
energyParamDerivExpressions.push_back(expression.differentiate(param).createCompiledExpression());
}
set<string> variables; set<string> variables;
variables.insert("r"); variables.insert("r");
for (int i = 0; i < numParameters; i++) { for (int i = 0; i < numParameters; i++) {
...@@ -1147,7 +1170,7 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo ...@@ -1147,7 +1170,7 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo
vector<RealVec>& forceData = extractForces(context); vector<RealVec>& forceData = extractForces(context);
RealVec* boxVectors = extractBoxVectors(context); RealVec* boxVectors = extractBoxVectors(context);
RealOpenMM energy = 0; RealOpenMM energy = 0;
ReferenceCustomNonbondedIxn ixn(energyExpression, forceExpression, parameterNames); ReferenceCustomNonbondedIxn ixn(energyExpression, forceExpression, parameterNames, energyParamDerivExpressions);
bool periodic = (nonbondedMethod == CutoffPeriodic); bool periodic = (nonbondedMethod == CutoffPeriodic);
if (nonbondedMethod != NoCutoff) { if (nonbondedMethod != NoCutoff) {
computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxVectors(context), periodic, nonbondedCutoff, 0.0); computeNeighborListVoxelHash(*neighborList, numParticles, posData, exclusions, extractBoxVectors(context), periodic, nonbondedCutoff, 0.0);
...@@ -1170,15 +1193,22 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo ...@@ -1170,15 +1193,22 @@ double ReferenceCalcCustomNonbondedForceKernel::execute(ContextImpl& context, bo
} }
if (useSwitchingFunction) if (useSwitchingFunction)
ixn.setUseSwitchingFunction(switchingDistance); ixn.setUseSwitchingFunction(switchingDistance);
ixn.calculatePairIxn(numParticles, posData, particleParamArray, exclusions, 0, globalParamValues, forceData, 0, includeEnergy ? &energy : NULL); vector<double> energyParamDerivValues(energyParamDerivNames.size()+1, 0.0);
ixn.calculatePairIxn(numParticles, posData, particleParamArray, exclusions, 0, globalParamValues, forceData, 0, includeEnergy ? &energy : NULL, &energyParamDerivValues[0]);
map<string, double>& energyParamDerivs = extractEnergyParameterDerivatives(context);
for (int i = 0; i < energyParamDerivNames.size(); i++)
energyParamDerivs[energyParamDerivNames[i]] += energyParamDerivValues[i];
// Add in the long range correction. // Add in the long range correction.
if (!hasInitializedLongRangeCorrection || (globalParamsChanged && forceCopy != NULL)) { if (!hasInitializedLongRangeCorrection || (globalParamsChanged && forceCopy != NULL)) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(*forceCopy, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
hasInitializedLongRangeCorrection = true; hasInitializedLongRangeCorrection = true;
} }
energy += longRangeCoefficient/(boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2]); double volume = boxVectors[0][0]*boxVectors[1][1]*boxVectors[2][2];
energy += longRangeCoefficient/volume;
for (int i = 0; i < longRangeCoefficientDerivs.size(); i++)
energyParamDerivs[energyParamDerivNames[i]] += longRangeCoefficientDerivs[i]/volume;
return energy; return energy;
} }
...@@ -1200,7 +1230,7 @@ void ReferenceCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImp ...@@ -1200,7 +1230,7 @@ void ReferenceCalcCustomNonbondedForceKernel::copyParametersToContext(ContextImp
// If necessary, recompute the long range correction. // If necessary, recompute the long range correction.
if (forceCopy != NULL) { if (forceCopy != NULL) {
longRangeCoefficient = CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner()); CustomNonbondedForceImpl::calcLongRangeCorrection(force, context.getOwner(), longRangeCoefficient, longRangeCoefficientDerivs);
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