Commit 7b383c7e authored by Peter Eastman's avatar Peter Eastman
Browse files

Fixed bugs in CustomIntegrator, including incorrect examples of velocity verlet with constraints

parent dee35ab2
...@@ -144,27 +144,19 @@ namespace OpenMM { ...@@ -144,27 +144,19 @@ namespace OpenMM {
* time step so that, for example, an AndersenThermostat can randomize velocities * time step so that, for example, an AndersenThermostat can randomize velocities
* or a MonteCarloBarostat can scale particle positions. You need to add a * or a MonteCarloBarostat can scale particle positions. You need to add a
* step to tell the integrator when to do this. The following example corrects * step to tell the integrator when to do this. The following example corrects
* both these problems: * both these problems, using the RATTLE algorithm to apply constraints:
* *
* <tt><pre> * <tt><pre>
* CustomIntegrator integrator(0.001); * CustomIntegrator integrator(0.001);
* integrator.addPerDofVariable("x1", 0);
* integrator.addUpdateContextState();
* integrator.addComputePerDof("v", "v+0.5*dt*f/m"); * integrator.addComputePerDof("v", "v+0.5*dt*f/m");
* integrator.addComputePerDof("x", "x+dt*v"); * integrator.addComputePerDof("x", "x+dt*v");
* integrator.addConstrainPositions(); * integrator.addConstrainPositions();
* integrator.addUpdateContextState(); * integrator.addComputePerDof("v", "v+0.5*dt*f/m+(x-x1)/dt");
* integrator.addComputePerDof("v", "v+0.5*dt*f/m");
* integrator.addConstrainVelocities(); * integrator.addConstrainVelocities();
* </pre></tt> * </pre></tt>
* *
* This integrator includes two steps that require forces (the two velocity
* updates) and three steps that can potentially change particle positions and
* thus invalidate the forces (the position update, applying position constraints,
* and allowing Forces to update the context state). We put all three of these
* steps together to minimize the number of force computations needed. If we had
* put addUpdateContextState() at the beginning of the algorithm instead, that would
* risk invalidating the forces just before the first velocity update, thus
* requiring two force evaluations per time step instead of one.
*
* CustomIntegrator can be used to implement multiple time step integrators. The * CustomIntegrator can be used to implement multiple time step integrators. The
* following example shows an r-RESPA integrator. It assumes the quickly changing * following example shows an r-RESPA integrator. It assumes the quickly changing
* forces are in force group 0 and the slowly changing ones are in force group 1. * forces are in force group 0 and the slowly changing ones are in force group 1.
...@@ -173,7 +165,7 @@ namespace OpenMM { ...@@ -173,7 +165,7 @@ namespace OpenMM {
* <tt><pre> * <tt><pre>
* CustomIntegrator integrator(0.004); * CustomIntegrator integrator(0.004);
* integrator.addComputePerDof("v", "v+0.5*dt*f1/m"); * integrator.addComputePerDof("v", "v+0.5*dt*f1/m");
* for (int i = 0; i < 4; i++) { * for (int i = 0; i &lt; 4; i++) {
* integrator.addComputePerDof("v", "v+0.5*(dt/4)*f0/m"); * integrator.addComputePerDof("v", "v+0.5*(dt/4)*f0/m");
* integrator.addComputePerDof("x", "x+(dt/4)*v"); * integrator.addComputePerDof("x", "x+(dt/4)*v");
* integrator.addComputePerDof("v", "v+0.5*(dt/4)*f0/m"); * integrator.addComputePerDof("v", "v+0.5*(dt/4)*f0/m");
......
...@@ -3787,12 +3787,11 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr ...@@ -3787,12 +3787,11 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
// Identify steps that can be merged into a single kernel. // Identify steps that can be merged into a single kernel.
for (int step = 1; step < numSteps; step++) { for (int step = 1; step < numSteps; step++) {
if ((needsForces[step] || needsEnergy[step]) && (invalidatesForces[step-1] || forceGroup[step] != forceGroup[step-1])) if (needsForces[step] || needsEnergy[step])
continue; continue;
if (stepType[step-1] == CustomIntegrator::ComputeGlobal && stepType[step] == CustomIntegrator::ComputeGlobal) if (stepType[step-1] == CustomIntegrator::ComputeGlobal && stepType[step] == CustomIntegrator::ComputeGlobal)
merged[step] = true; merged[step] = true;
if (stepType[step-1] == CustomIntegrator::ComputePerDof && stepType[step] == CustomIntegrator::ComputePerDof && if (stepType[step-1] == CustomIntegrator::ComputePerDof && stepType[step] == CustomIntegrator::ComputePerDof &&
storePosAsDelta[step-1] == storePosAsDelta[step] && loadPosAsDelta[step-1] == loadPosAsDelta[step] &&
!usesVariable(expression[step], "uniform")) !usesVariable(expression[step], "uniform"))
merged[step] = true; merged[step] = true;
} }
...@@ -3828,12 +3827,14 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr ...@@ -3828,12 +3827,14 @@ void OpenCLIntegrateCustomStepKernel::execute(ContextImpl& context, CustomIntegr
} }
else if (variable[j] == "v") else if (variable[j] == "v")
compute << "velm[index] = " << convert << "velocity);\n"; compute << "velm[index] = " << convert << "velocity);\n";
else {
for (int i = 0; i < (int) perDofValues->getBuffers().size(); i++) { for (int i = 0; i < (int) perDofValues->getBuffers().size(); i++) {
const OpenCLNonbondedUtilities::ParameterInfo& buffer = perDofValues->getBuffers()[i]; const OpenCLNonbondedUtilities::ParameterInfo& buffer = perDofValues->getBuffers()[i];
compute << "perDofValues"<<intToString(i+1)<<"[3*index] = perDofx"<<intToString(i+1)<<";\n"; compute << "perDofValues"<<intToString(i+1)<<"[3*index] = perDofx"<<intToString(i+1)<<";\n";
compute << "perDofValues"<<intToString(i+1)<<"[3*index+1] = perDofy"<<intToString(i+1)<<";\n"; compute << "perDofValues"<<intToString(i+1)<<"[3*index+1] = perDofy"<<intToString(i+1)<<";\n";
compute << "perDofValues"<<intToString(i+1)<<"[3*index+2] = perDofz"<<intToString(i+1)<<";\n"; compute << "perDofValues"<<intToString(i+1)<<"[3*index+2] = perDofz"<<intToString(i+1)<<";\n";
} }
}
compute << "}\n"; compute << "}\n";
numGaussian += numAtoms*usesVariable(expression[j], "gaussian"); numGaussian += numAtoms*usesVariable(expression[j], "gaussian");
numUniform += numAtoms*usesVariable(expression[j], "uniform"); numUniform += numAtoms*usesVariable(expression[j], "uniform");
......
...@@ -146,7 +146,7 @@ void testConstraints() { ...@@ -146,7 +146,7 @@ void testConstraints() {
if (i == 1) if (i == 1)
initialEnergy = energy; initialEnergy = energy;
else if (i > 1) else if (i > 1)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.05); ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1); integrator.step(1);
} }
} }
...@@ -159,10 +159,12 @@ void testVelocityConstraints() { ...@@ -159,10 +159,12 @@ void testVelocityConstraints() {
OpenCLPlatform platform; OpenCLPlatform platform;
System system; System system;
CustomIntegrator integrator(0.002); CustomIntegrator integrator(0.002);
integrator.addPerDofVariable("x1", 0);
integrator.addComputePerDof("v", "v+0.5*dt*f/m"); integrator.addComputePerDof("v", "v+0.5*dt*f/m");
integrator.addComputePerDof("x", "x+dt*v"); integrator.addComputePerDof("x", "x+dt*v");
integrator.addComputePerDof("x1", "x");
integrator.addConstrainPositions(); integrator.addConstrainPositions();
integrator.addComputePerDof("v", "v+0.5*dt*f/m"); integrator.addComputePerDof("v", "v+0.5*dt*f/m+(x-x1)/dt");
integrator.addConstrainVelocities(); integrator.addConstrainVelocities();
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
...@@ -225,7 +227,7 @@ void testVelocityConstraints() { ...@@ -225,7 +227,7 @@ void testVelocityConstraints() {
if (i == 0) if (i == 0)
initialEnergy = energy; initialEnergy = energy;
else if (i > 0) else if (i > 0)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.05); ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
} }
} }
......
...@@ -146,7 +146,7 @@ void testConstraints() { ...@@ -146,7 +146,7 @@ void testConstraints() {
if (i == 1) if (i == 1)
initialEnergy = energy; initialEnergy = energy;
else if (i > 1) else if (i > 1)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.05); ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1); integrator.step(1);
} }
} }
...@@ -159,10 +159,12 @@ void testVelocityConstraints() { ...@@ -159,10 +159,12 @@ void testVelocityConstraints() {
ReferencePlatform platform; ReferencePlatform platform;
System system; System system;
CustomIntegrator integrator(0.002); CustomIntegrator integrator(0.002);
integrator.addPerDofVariable("x1", 0);
integrator.addComputePerDof("v", "v+0.5*dt*f/m"); integrator.addComputePerDof("v", "v+0.5*dt*f/m");
integrator.addComputePerDof("x", "x+dt*v"); integrator.addComputePerDof("x", "x+dt*v");
integrator.addComputePerDof("x1", "x");
integrator.addConstrainPositions(); integrator.addConstrainPositions();
integrator.addComputePerDof("v", "v+0.5*dt*f/m"); integrator.addComputePerDof("v", "v+0.5*dt*f/m+(x-x1)/dt");
integrator.addConstrainVelocities(); integrator.addConstrainVelocities();
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
...@@ -210,7 +212,7 @@ void testVelocityConstraints() { ...@@ -210,7 +212,7 @@ void testVelocityConstraints() {
if (i == 1) if (i == 1)
initialEnergy = energy; initialEnergy = energy;
else if (i > 1) else if (i > 1)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.05); ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(2); integrator.step(2);
} }
} }
......
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