Unverified Commit 9d9ffb01 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Clarified multiple forces with the same global parameter (#3769)

parent 87a70daf
......@@ -465,6 +465,13 @@ example, if a :class:`CustomNonbondedForce` uses a long range correction, changi
a global parameter may require the correction coefficient to be recalculated,
which is expensive.
It is possible for multiple forces to depend on the same global parameter. To do this,
simply have each force specify a parameter with the same name. This can be useful
in certain cases. For example, in an alchemical simulation, you might have a
parameter that interpolates between two endpoints corresponding to different molecules.
Changing the one parameter would simultaneously modify multiple bonded and nonbonded
forces.
The other type of parameter is ones that record many values, one for each element
of the force, such as per-particle or per-bond parameters. These values are stored
directly in the force object itself, and hence are part of the system definition.
......
......@@ -188,6 +188,9 @@ void ContextImpl::initialize() {
for (size_t i = 0; i < forceImpls.size(); ++i) {
forceImpls[i]->initialize(*this);
map<string, double> forceParameters = forceImpls[i]->getDefaultParameters();
for (auto param : forceParameters)
if (parameters.find(param.first) != parameters.end() && parameters[param.first] != forceParameters[param.first])
throw OpenMMException("Two Forces define different default values for the parameter '"+param.first+"'");
parameters.insert(forceParameters.begin(), forceParameters.end());
}
integrator.initialize(*this);
......
......@@ -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-2016 Stanford University and the Authors. *
* Portions copyright (c) 2008-2022 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -148,6 +148,28 @@ void testIllegalVariable() {
ASSERT(threwException);
}
void testInconsistentParameters() {
// Specifying two inconsistent default values for a global parameter should throw an exception.
System system;
system.addParticle(1.0);
CustomBondForce* bonds1 = new CustomBondForce("k*r");
CustomBondForce* bonds2 = new CustomBondForce("k*r");
bonds1->addGlobalParameter("k", 1.0);
bonds2->addGlobalParameter("k", 2.0);
system.addForce(bonds1);
system.addForce(bonds2);
VerletIntegrator integrator(0.001);
bool threwException = false;
try {
Context context(system, integrator, platform);
}
catch (const exception& e) {
threwException = true;
}
ASSERT(threwException);
}
void testPeriodic() {
// Create a force that uses periodic boundary conditions.
......@@ -221,6 +243,7 @@ int main(int argc, char* argv[]) {
testBonds();
testManyParameters();
testIllegalVariable();
testInconsistentParameters();
testPeriodic();
testEnergyParameterDerivatives();
runPlatformTests();
......
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