"csrc/vscode:/vscode.git/clone" did not exist on "7e8acdf753007483097ae807eef691fcffe88dee"
Commit 9cad8b27 authored by Peter Eastman's avatar Peter Eastman
Browse files

Improved algorithm for VariableVerletIntegrator

parent 4eb99b87
...@@ -63,10 +63,9 @@ public: ...@@ -63,10 +63,9 @@ public:
/** /**
* Create a VariableVerletIntegrator. * Create a VariableVerletIntegrator.
* *
* @param stepSize the initial step size to use (in picoseconds)
* @param tol the error tolerance * @param tol the error tolerance
*/ */
VariableVerletIntegrator(double stepSize, double errorTol); VariableVerletIntegrator(double errorTol);
/** /**
* Get the error tolerance. * Get the error tolerance.
*/ */
......
...@@ -39,8 +39,7 @@ using namespace OpenMM; ...@@ -39,8 +39,7 @@ using namespace OpenMM;
using std::string; using std::string;
using std::vector; using std::vector;
VariableVerletIntegrator::VariableVerletIntegrator(double stepSize, double errorTol) : errorTol(errorTol) { VariableVerletIntegrator::VariableVerletIntegrator(double errorTol) : errorTol(errorTol) {
setStepSize(stepSize);
setConstraintTolerance(1e-4); setConstraintTolerance(1e-4);
} }
......
...@@ -814,7 +814,7 @@ void ReferenceIntegrateVariableVerletStepKernel::execute(OpenMMContextImpl& cont ...@@ -814,7 +814,7 @@ void ReferenceIntegrateVariableVerletStepKernel::execute(OpenMMContextImpl& cont
delete dynamics; delete dynamics;
delete constraints; delete constraints;
} }
dynamics = new ReferenceVariableVerletDynamics(context.getSystem().getNumParticles(), static_cast<RealOpenMM>(stepSize), errorTol); dynamics = new ReferenceVariableVerletDynamics(context.getSystem().getNumParticles(), (RealOpenMM) errorTol);
vector<ReferenceCCMAAlgorithm::AngleInfo> angles; vector<ReferenceCCMAAlgorithm::AngleInfo> angles;
findAnglesForCCMA(context.getSystem(), angles); findAnglesForCCMA(context.getSystem(), angles);
constraints = new ReferenceCCMAAlgorithm(context.getSystem().getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance()); constraints = new ReferenceCCMAAlgorithm(context.getSystem().getNumParticles(), numConstraints, constraintIndices, constraintDistances, masses, angles, (RealOpenMM)integrator.getConstraintTolerance());
...@@ -823,7 +823,7 @@ void ReferenceIntegrateVariableVerletStepKernel::execute(OpenMMContextImpl& cont ...@@ -823,7 +823,7 @@ void ReferenceIntegrateVariableVerletStepKernel::execute(OpenMMContextImpl& cont
prevErrorTol = errorTol; prevErrorTol = errorTol;
} }
dynamics->update(context.getSystem().getNumParticles(), posData, velData, forceData, masses); dynamics->update(context.getSystem().getNumParticles(), posData, velData, forceData, masses);
data.time += dynamics->getLastStepSize(); data.time += dynamics->getDeltaT();
} }
ReferenceApplyAndersenThermostatKernel::~ReferenceApplyAndersenThermostatKernel() { ReferenceApplyAndersenThermostatKernel::~ReferenceApplyAndersenThermostatKernel() {
......
...@@ -40,9 +40,8 @@ ...@@ -40,9 +40,8 @@
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceVariableVerletDynamics::ReferenceVariableVerletDynamics( int numberOfAtoms, ReferenceVariableVerletDynamics::ReferenceVariableVerletDynamics( int numberOfAtoms, RealOpenMM accuracy ) :
RealOpenMM deltaT, RealOpenMM accuracy ) : ReferenceDynamics( numberOfAtoms, 0.0f, 0.0f ), _accuracy(accuracy) {
ReferenceDynamics( numberOfAtoms, deltaT, 0.0 ), _accuracy(accuracy) {
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
...@@ -96,18 +95,6 @@ void ReferenceVariableVerletDynamics::setAccuracy( RealOpenMM accuracy ) { ...@@ -96,18 +95,6 @@ void ReferenceVariableVerletDynamics::setAccuracy( RealOpenMM accuracy ) {
_accuracy = accuracy; _accuracy = accuracy;
} }
/**---------------------------------------------------------------------------------------
Get the actual size of the last step that was taken
@return step size
--------------------------------------------------------------------------------------- */
RealOpenMM ReferenceVariableVerletDynamics::getLastStepSize( void ) const {
return _lastStepSize;
}
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Print parameters Print parameters
...@@ -195,58 +182,34 @@ int ReferenceVariableVerletDynamics::update( int numberOfAtoms, RealOpenMM** ato ...@@ -195,58 +182,34 @@ int ReferenceVariableVerletDynamics::update( int numberOfAtoms, RealOpenMM** ato
} }
} }
// Try different step sizes until the accuracy is acceptable. RealOpenMM error = zero;
for (int i = 0; i < numberOfAtoms; ++i) {
bool success = false; for (int j = 0; j < 3; ++j) {
RealOpenMM maxStepSize = 5.0f*getDeltaT(); RealOpenMM xerror = inverseMasses[i]*forces[i][j];
while (!success) { error += xerror*xerror;
// Perform the integration and estimate the error.
_lastStepSize = getDeltaT();
RealOpenMM error = zero;
for (int i = 0; i < numberOfAtoms; ++i) {
for (int j = 0; j < 3; ++j) {
RealOpenMM xref = atomCoordinates[i][j] + velocities[i][j]*getDeltaT();
RealOpenMM vPrime = velocities[i][j] + inverseMasses[i]*forces[i][j]*getDeltaT();
xPrime[i][j] = atomCoordinates[i][j] + vPrime*getDeltaT();
RealOpenMM xerror = xPrime[i][j]-xref;
error += xerror*xerror;
}
} }
error = SQRT(error/(numberOfAtoms*3)); }
error = SQRT(error/(numberOfAtoms*3));
// Select a new step size. RealOpenMM newStepSize = SQRT(getAccuracy()/error);
if (getDeltaT() > 0.0f)
const RealOpenMM Safety = 0.9f, MinShrink = 0.1f; newStepSize = std::min(newStepSize, getDeltaT()*2.0f); // For safety, limit how quickly dt can increase.
const RealOpenMM HysteresisLow = 0.9f, HysteresisHigh = 1.0f, ErrorOrder = 2.0f; if (newStepSize > getDeltaT() && newStepSize < 1.2f*getDeltaT())
newStepSize = getDeltaT(); // Keeping dt constant between steps improves the behavior of the integrator.
RealOpenMM newStepSize = Safety*getDeltaT()*POW(getAccuracy()/error, 1.0f/ErrorOrder); RealOpenMM vstep = 0.5f*(newStepSize+getDeltaT()); // The time interval by which to advance the velocities
if (newStepSize > getDeltaT()) { setDeltaT(newStepSize);
if (newStepSize < HysteresisHigh*getDeltaT()) for (int i = 0; i < numberOfAtoms; ++i) {
newStepSize = getDeltaT(); for (int j = 0; j < 3; ++j) {
} RealOpenMM vPrime = velocities[i][j] + inverseMasses[i]*forces[i][j]*vstep;
if (newStepSize < getDeltaT() && error <= getAccuracy()) xPrime[i][j] = atomCoordinates[i][j] + vPrime*getDeltaT();
newStepSize = getDeltaT();
newStepSize = std::min(newStepSize, maxStepSize);
newStepSize = std::max(newStepSize, MinShrink*getDeltaT());
if (newStepSize < getDeltaT())
newStepSize = std::min(newStepSize, HysteresisLow*getDeltaT());
success = (newStepSize >= getDeltaT());
if (success) {
ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm();
if (referenceConstraintAlgorithm)
success = (referenceConstraintAlgorithm->apply(numberOfAtoms, atomCoordinates, xPrime, inverseMasses) != ErrorReturn);
if (!success) {
newStepSize *= 0.5f;
maxStepSize = newStepSize;
}
} }
setDeltaT(newStepSize); }
} ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm();
if (referenceConstraintAlgorithm)
referenceConstraintAlgorithm->apply(numberOfAtoms, atomCoordinates, xPrime, inverseMasses);
// Update the positions and velocities. // Update the positions and velocities.
RealOpenMM velocityScale = static_cast<RealOpenMM>( 1.0/_lastStepSize ); RealOpenMM velocityScale = one/getDeltaT();
for (int i = 0; i < numberOfAtoms; ++i) { for (int i = 0; i < numberOfAtoms; ++i) {
for (int j = 0; j < 3; ++j) { for (int j = 0; j < 3; ++j) {
velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]); velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]);
......
...@@ -35,7 +35,7 @@ class ReferenceVariableVerletDynamics : public ReferenceDynamics { ...@@ -35,7 +35,7 @@ class ReferenceVariableVerletDynamics : public ReferenceDynamics {
enum TwoDArrayIndicies { xPrime2D, Max2DArrays }; enum TwoDArrayIndicies { xPrime2D, Max2DArrays };
enum OneDArrayIndicies { InverseMasses, Max1DArrays }; enum OneDArrayIndicies { InverseMasses, Max1DArrays };
RealOpenMM _accuracy, _lastStepSize; RealOpenMM _accuracy;
public: public:
...@@ -44,12 +44,11 @@ class ReferenceVariableVerletDynamics : public ReferenceDynamics { ...@@ -44,12 +44,11 @@ class ReferenceVariableVerletDynamics : public ReferenceDynamics {
Constructor Constructor
@param numberOfAtoms number of atoms @param numberOfAtoms number of atoms
@param deltaT initial delta t for dynamics
@param accuracy required accuracy @param accuracy required accuracy
--------------------------------------------------------------------------------------- */ --------------------------------------------------------------------------------------- */
ReferenceVariableVerletDynamics( int numberOfAtoms, RealOpenMM deltaT, RealOpenMM accuracy ); ReferenceVariableVerletDynamics( int numberOfAtoms, RealOpenMM accuracy );
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
...@@ -77,16 +76,6 @@ class ReferenceVariableVerletDynamics : public ReferenceDynamics { ...@@ -77,16 +76,6 @@ class ReferenceVariableVerletDynamics : public ReferenceDynamics {
void setAccuracy( RealOpenMM accuracy ); void setAccuracy( RealOpenMM accuracy );
/**---------------------------------------------------------------------------------------
Get the actual size of the last step that was taken
@return step size
--------------------------------------------------------------------------------------- */
RealOpenMM getLastStepSize( void ) const;
/**--------------------------------------------------------------------------------------- /**---------------------------------------------------------------------------------------
Print parameters Print parameters
......
...@@ -55,7 +55,7 @@ void testSingleBond() { ...@@ -55,7 +55,7 @@ void testSingleBond() {
System system; System system;
system.addParticle(2.0); system.addParticle(2.0);
system.addParticle(2.0); system.addParticle(2.0);
VariableVerletIntegrator integrator(0.01, 1e-6); VariableVerletIntegrator integrator(1e-6);
HarmonicBondForce* forceField = new HarmonicBondForce(); HarmonicBondForce* forceField = new HarmonicBondForce();
forceField->addBond(0, 1, 1.5, 1); forceField->addBond(0, 1, 1.5, 1);
system.addForce(forceField); system.addForce(forceField);
...@@ -91,7 +91,7 @@ void testConstraints() { ...@@ -91,7 +91,7 @@ void testConstraints() {
const double temp = 500.0; const double temp = 500.0;
ReferencePlatform platform; ReferencePlatform platform;
System system; System system;
VariableVerletIntegrator integrator(0.002, 1e-5); VariableVerletIntegrator integrator(1e-5);
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
...@@ -141,7 +141,7 @@ void testConstrainedClusters() { ...@@ -141,7 +141,7 @@ void testConstrainedClusters() {
const double temp = 500.0; const double temp = 500.0;
ReferencePlatform platform; ReferencePlatform platform;
System system; System system;
VariableVerletIntegrator integrator(0.002, 1e-5); VariableVerletIntegrator integrator(1e-5);
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numParticles; ++i) { for (int i = 0; i < numParticles; ++i) {
......
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