Commit 1f7866ad authored by peastman's avatar peastman Committed by GitHub
Browse files

Merge pull request #1547 from peastman/paramderivs

Energy derivatives with respect to global parameters
parents 37787af9 7851bad8
......@@ -1086,6 +1086,24 @@ is exactly equivalent to
The definition of an intermediate value may itself involve other intermediate
values. All uses of a value must appear *before* that value’s definition.
Parameter Derivatives
*********************
Many custom forces have the ability to compute derivatives of the potential energy
with respect to global parameters. To use this feature, first define a global
parameter that the energy depends on. Then instruct the custom force to compute
the derivative with respect to that parameter by calling :meth:`addEnergyParameterDerivative()`
on it. Whenever forces and energies are computed, the specified derivative will
then also be computed at the same time. You can query it by calling :meth:`getState()`
on a :class:`Context`, just as you would query forces or energies.
An important application of this feature is to use it in combination with a
:class:`CustomIntegrator` (described in section :ref:`custom-integrator`\ ). The
derivative can appear directly in expressions that define the integration
algorithm. This can be used to implement algorithms such as lambda-dynamics,
where a global parameter is integrated as a dynamic variable.
Integrators
###########
......@@ -1235,6 +1253,8 @@ Furthermore, because Langevin dynamics involves a random force, it can never be
symplectic and therefore the fixed step size Verlet integrator’s advantages do
not apply to the Langevin integrator.
.. _custom-integrator:
CustomIntegrator
****************
......
......@@ -48,7 +48,7 @@ public:
virtual ~CustomFunction() {
}
/**
* Get the number of arguments this function exprects.
* Get the number of arguments this function expects.
*/
virtual int getNumArguments() const = 0;
/**
......
......@@ -109,7 +109,7 @@ ExpressionTreeNode ParsedExpression::precalculateConstantSubexpressions(const Ex
for (int i = 0; i < (int) children.size(); i++)
children[i] = precalculateConstantSubexpressions(node.getChildren()[i]);
ExpressionTreeNode result = ExpressionTreeNode(node.getOperation().clone(), children);
if (node.getOperation().getId() == Operation::VARIABLE)
if (node.getOperation().getId() == Operation::VARIABLE || node.getOperation().getId() == Operation::CUSTOM)
return result;
for (int i = 0; i < (int) children.size(); i++)
if (children[i].getOperation().getId() != Operation::CONSTANT)
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -172,6 +172,12 @@ public:
* @param forces on exit, this contains the forces
*/
virtual void getForces(ContextImpl& context, std::vector<Vec3>& forces) = 0;
/**
* Get the current derivatives of the energy with respect to context parameters.
*
* @param derivs on exit, this contains the derivatives
*/
virtual void getEnergyParameterDerivatives(ContextImpl& context, std::map<std::string, double>& derivs) = 0;
/**
* Get the current periodic box vectors.
*
......
......@@ -63,6 +63,10 @@ namespace OpenMM {
* force->addPerAngleParameter("k");
* force->addPerAngleParameter("theta0");
* </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
* 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:
int getNumGlobalParameters() const {
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
*/
......@@ -162,6 +173,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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.
*
......@@ -225,6 +251,7 @@ private:
std::vector<AngleParameterInfo> parameters;
std::vector<GlobalParameterInfo> globalParameters;
std::vector<AngleInfo> angles;
std::vector<int> energyParameterDerivatives;
bool usePeriodic;
};
......
......@@ -63,6 +63,10 @@ namespace OpenMM {
* force->addPerBondParameter("k");
* force->addPerBondParameter("r0");
* </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
* 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:
int getNumGlobalParameters() const {
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 bond
*/
......@@ -162,6 +173,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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 bond term to the force field.
*
......@@ -222,6 +248,7 @@ private:
std::vector<BondParameterInfo> parameters;
std::vector<GlobalParameterInfo> globalParameters;
std::vector<BondInfo> bonds;
std::vector<int> energyParameterDerivatives;
bool usePeriodic;
};
......
......@@ -98,6 +98,10 @@ namespace OpenMM {
* bondParameters.push_back(k);
* force->addBond(bondGroups, bondParameters);
* </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
* 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
......@@ -150,6 +154,13 @@ public:
int getNumGlobalParameters() const {
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 number of tabulated functions that have been defined.
*/
......@@ -229,6 +240,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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 particle group.
*
......@@ -351,6 +377,7 @@ private:
std::vector<GroupInfo> groups;
std::vector<BondInfo> bonds;
std::vector<FunctionInfo> functions;
std::vector<int> energyParameterDerivatives;
bool usePeriodic;
};
......
......@@ -87,6 +87,10 @@ namespace OpenMM {
* force->addPerBondParameter("theta0");
* force->addPerBondParameter("r0");
* </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
* 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
......@@ -133,6 +137,13 @@ public:
int getNumGlobalParameters() const {
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 number of tabulated functions that have been defined.
*/
......@@ -212,6 +223,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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 bond to the force
*
......@@ -323,6 +349,7 @@ private:
std::vector<GlobalParameterInfo> globalParameters;
std::vector<BondInfo> bonds;
std::vector<FunctionInfo> functions;
std::vector<int> energyParameterDerivatives;
bool usePeriodic;
};
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* 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 *
* Contributors: *
* *
......@@ -127,6 +127,10 @@ namespace OpenMM {
* omitted from calculations. This is most often used for particles that are bonded to each other. Even if you specify exclusions,
* however, you can use the computation type ParticlePairNoExclusions to indicate that exclusions should not be applied to a
* particular piece of the computation.
*
* 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
* 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
......@@ -207,6 +211,13 @@ public:
int getNumGlobalParameters() const {
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 number of tabulated functions that have been defined.
*/
......@@ -312,6 +323,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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
* in the System. When it is called for the i'th time, it specifies the parameters for the i'th particle.
......@@ -550,6 +576,7 @@ private:
std::vector<FunctionInfo> functions;
std::vector<ComputationInfo> computedValues;
std::vector<ComputationInfo> energyTerms;
std::vector<int> energyParameterDerivatives;
};
/**
......
......@@ -201,6 +201,16 @@ namespace OpenMM {
* only involve global variables, not per-DOF ones. It may use any of the
* following comparison operators: =, <. >, !=, <=, >=. Blocks may be nested
* inside each other.
*
* Another feature of CustomIntegrator is that it can use derivatives of the
* potential energy with respect to context parameters. These derivatives are
* typically computed by custom forces, and are only computed if a Force object
* has been specifically told to compute them by calling addEnergyParameterDerivative()
* on it. CustomIntegrator provides a deriv() function for accessing these
* derivatives in global or per-DOF expressions. For example, "deriv(energy, lambda)"
* is the derivative of the total potentially energy with respect to the parameter
* lambda. You can also restrict it to a single force group by specifying a different
* variable for the first argument, such as "deriv(energy1, lambda)".
*
* An Integrator has one other job in addition to evolving the equations of motion:
* it defines how to compute the kinetic energy of the system. Depending on the
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* 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 *
* Contributors: *
* *
......@@ -118,6 +118,10 @@ namespace OpenMM {
* 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
* 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
* 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:
int getNumInteractionGroups() const {
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
*/
......@@ -321,6 +332,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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
* 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:
std::vector<ExclusionInfo> exclusions;
std::vector<FunctionInfo> functions;
std::vector<InteractionGroupInfo> interactionGroups;
std::vector<int> energyParameterDerivatives;
};
/**
......
......@@ -63,6 +63,10 @@ namespace OpenMM {
* force->addPerTorsionParameter("k");
* force->addPerTorsionParameter("theta0");
* </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
* 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:
int getNumGlobalParameters() const {
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
*/
......@@ -162,6 +173,21 @@ public:
* @param defaultValue the default value of the parameter
*/
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.
*
......@@ -228,6 +254,7 @@ private:
std::vector<TorsionParameterInfo> parameters;
std::vector<GlobalParameterInfo> globalParameters;
std::vector<TorsionInfo> torsions;
std::vector<int> energyParameterDerivatives;
bool usePeriodic;
};
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -58,7 +58,7 @@ public:
* This is an enumeration of the types of data which may be stored in a State. When you create
* a State, use these values to specify which data types it should contain.
*/
enum DataType {Positions=1, Velocities=2, Forces=4, Energy=8, Parameters=16};
enum DataType {Positions=1, Velocities=2, Forces=4, Energy=8, Parameters=16, ParameterDerivatives=32};
/**
* Construct an empty State containing no data. This exists so State objects can be used in STL containers.
*/
......@@ -108,6 +108,17 @@ public:
* Get a map containing the values of all parameters. If this State does not contain parameters, this will throw an exception.
*/
const std::map<std::string, double>& getParameters() const;
/**
* Get a map containing derivatives of the potential energy with respect to context parameters.
* In most cases derivatives are only calculated if the corresponding Force objects have been
* specifically told to compute them. Otherwise, the values in the map will be zero. Likewise,
* if multiple Forces depend on the same parameter but only some have been told to compute
* derivatives with respect to it, the returned value will include only the contributions from
* the Forces that were told to compute it.
*
* If this State does not contain parameter derivatives, this will throw an exception.
*/
const std::map<std::string, double>& getEnergyParameterDerivatives() const;
/**
* Get which data types are stored in this State. The return value is a sum of DataType flags.
*/
......@@ -118,6 +129,7 @@ private:
void setVelocities(const std::vector<Vec3>& vel);
void setForces(const std::vector<Vec3>& force);
void setParameters(const std::map<std::string, double>& params);
void setEnergyParameterDerivatives(const std::map<std::string, double>& derivs);
void setEnergy(double ke, double pe);
void setPeriodicBoxVectors(const Vec3& a, const Vec3& b, const Vec3& c);
int types;
......@@ -126,7 +138,7 @@ private:
std::vector<Vec3> velocities;
std::vector<Vec3> forces;
Vec3 periodicBoxVectors[3];
std::map<std::string, double> parameters;
std::map<std::string, double> parameters, energyParameterDerivatives;
};
/**
......@@ -142,6 +154,7 @@ public:
void setVelocities(const std::vector<Vec3>& vel);
void setForces(const std::vector<Vec3>& force);
void setParameters(const std::map<std::string, double>& params);
void setEnergyParameterDerivatives(const std::map<std::string, double>& params);
void setEnergy(double ke, double pe);
void setPeriodicBoxVectors(const Vec3& a, const Vec3& b, const Vec3& c);
private:
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2013 Stanford University and the Authors. *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -138,6 +138,10 @@ public:
* @param value the value of the parameter
*/
void setParameter(std::string name, double value);
/**
* Get the derivatives of the energy with respect to parameters.
*/
void getEnergyParameterDerivatives(std::map<std::string, double>& derivs);
/**
* Get the vectors defining the axes of the periodic box (measured in nm). They will affect
* any Force that uses periodic boundary conditions.
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2015 Stanford University and the Authors. *
* Portions copyright (c) 2015-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -34,8 +34,10 @@
#include "openmm/CustomIntegrator.h"
#include "openmm/internal/ContextImpl.h"
#include "lepton/CustomFunction.h"
#include "lepton/ParsedExpression.h"
#include <map>
#include <string>
#include <vector>
namespace OpenMM {
......@@ -48,6 +50,7 @@ class System;
class OPENMM_EXPORT CustomIntegratorUtilities {
public:
class DerivFunction;
enum Comparison {
EQUAL = 0, LESS_THAN = 1, GREATER_THAN = 2, NOT_EQUAL = 3, LESS_THAN_OR_EQUAL = 4, GREATER_THAN_OR_EQUAL = 5
};
......@@ -82,6 +85,28 @@ private:
const std::vector<bool>& invalidatesForces, const std::vector<int>& forceGroup, std::vector<bool>& computeBoth);
static void analyzeForceComputationsForPath(std::vector<int>& steps, const std::vector<bool>& needsForces, const std::vector<bool>& needsEnergy,
const std::vector<bool>& invalidatesForces, const std::vector<int>& forceGroup, std::vector<bool>& computeBoth);
static void validateDerivatives(const Lepton::ExpressionTreeNode& node, const std::vector<std::string>& derivNames);
};
/**
* This class is used to implement the deriv() function when it appears in expressions.
*/
class CustomIntegratorUtilities::DerivFunction : public Lepton::CustomFunction {
public:
DerivFunction() {
}
int getNumArguments() const {
return 2;
}
double evaluate(const double* arguments) const {
return 0.0;
}
double evaluateDerivative(const double* arguments, const int* derivOrder) const {
return 0.0;
}
CustomFunction* clone() const {
return new DerivFunction();
}
};
} // namespace OpenMM
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* 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 *
* Contributors: *
* *
......@@ -63,9 +63,10 @@ public:
void updateParametersInContext(ContextImpl& context);
/**
* 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:
static double integrateInteraction(Lepton::CompiledExpression& expression, const std::vector<double>& params1, const std::vector<double>& params2,
const CustomNonbondedForce& force, const Context& context);
......
......@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2015 Stanford University and the Authors. *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -84,8 +84,9 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
builder.setPeriodicBoxVectors(periodicBoxSize[0], periodicBoxSize[1], periodicBoxSize[2]);
bool includeForces = types&State::Forces;
bool includeEnergy = types&State::Energy;
if (includeForces || includeEnergy) {
double energy = impl->calcForcesAndEnergy(includeForces || includeEnergy, includeEnergy, groups);
bool includeParameterDerivs = types&State::ParameterDerivatives;
if (includeForces || includeEnergy || includeParameterDerivs) {
double energy = impl->calcForcesAndEnergy(includeForces || includeEnergy || includeParameterDerivs, includeEnergy, groups);
if (includeEnergy)
builder.setEnergy(impl->calcKineticEnergy(), energy);
if (includeForces) {
......@@ -100,6 +101,11 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
params[iter->first] = iter->second;
builder.setParameters(params);
}
if (types&State::ParameterDerivatives) {
map<string, double> derivs;
impl->getEnergyParameterDerivatives(derivs);
builder.setEnergyParameterDerivatives(derivs);
}
if (types&State::Positions) {
vector<Vec3> positions;
impl->getPositions(positions);
......
......@@ -240,6 +240,10 @@ void ContextImpl::setParameter(std::string name, double value) {
integrator.stateChanged(State::Parameters);
}
void ContextImpl::getEnergyParameterDerivatives(std::map<std::string, double>& derivs) {
updateStateDataKernel.getAs<UpdateStateDataKernel>().getEnergyParameterDerivatives(*this, derivs);
}
void ContextImpl::getPeriodicBoxVectors(Vec3& a, Vec3& b, Vec3& c) {
updateStateDataKernel.getAs<UpdateStateDataKernel>().getPeriodicBoxVectors(*this, a, b, c);
}
......
......@@ -95,6 +95,20 @@ void CustomAngleForce::setGlobalParameterDefaultValue(int index, double defaultV
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) {
angles.push_back(AngleInfo(particle1, particle2, particle3, parameters));
return angles.size()-1;
......
......@@ -95,6 +95,20 @@ void CustomBondForce::setGlobalParameterDefaultValue(int index, double defaultVa
globalParameters[index].defaultValue = defaultValue;
}
void CustomBondForce::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& CustomBondForce::getEnergyParameterDerivativeName(int index) const {
ASSERT_VALID_INDEX(index, energyParameterDerivatives);
return globalParameters[energyParameterDerivatives[index]].name;
}
int CustomBondForce::addBond(int particle1, int particle2, const vector<double>& parameters) {
bonds.push_back(BondInfo(particle1, particle2, parameters));
return bonds.size()-1;
......
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