void ReferenceVariableVerletDynamics::update(const OpenMM::System& system, vector<Vec3>& atomCoordinates, vector<Vec3>& velocities, vector<Vec3>& forces, vector<double>& masses, double maxStepSize, double tolerance) { // first-time-through initialization int numberOfAtoms = system.getNumParticles(); if (getTimeStep() == 0) { // invert masses for (int ii = 0; ii < numberOfAtoms; ii++) { if (masses[ii] == 0.0) inverseMasses[ii] = 0.0; else inverseMasses[ii] = 1.0/masses[ii]; } } double error = 0.0; for (int i = 0; i < numberOfAtoms; ++i) { for (int j = 0; j < 3; ++j) { double xerror = inverseMasses[i]*forces[i][j]; error += xerror*xerror; } } error = sqrt(error/(numberOfAtoms*3)); double newStepSize = sqrt(getAccuracy()/error); if (getDeltaT() > 0.0f) newStepSize = std::min(newStepSize, getDeltaT()*2.0f); // For safety, limit how quickly dt can increase. if (newStepSize > getDeltaT() && newStepSize < 1.2f*getDeltaT()) newStepSize = getDeltaT(); // Keeping dt constant between steps improves the behavior of the integrator. if (newStepSize > maxStepSize) newStepSize = maxStepSize; double vstep = 0.5f*(newStepSize+getDeltaT()); // The time interval by which to advance the velocities setDeltaT(newStepSize); for (int i = 0; i < numberOfAtoms; ++i) { if (masses[i] != 0.0) for (int j = 0; j < 3; ++j) { double vPrime = velocities[i][j] + inverseMasses[i]*forces[i][j]*vstep; xPrime[i][j] = atomCoordinates[i][j] + vPrime*getDeltaT(); } } ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm(); if (referenceConstraintAlgorithm) referenceConstraintAlgorithm->apply(atomCoordinates, xPrime, inverseMasses, tolerance); // Update the positions and velocities. double velocityScale = 1.0/getDeltaT(); for (int i = 0; i < numberOfAtoms; ++i) { if (masses[i] != 0.0) for (int j = 0; j < 3; ++j) { velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]); atomCoordinates[i][j] = xPrime[i][j]; } } ReferenceVirtualSites::computePositions(system, atomCoordinates); incrementTimeStep(); }
void ReferenceVerletDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates, vector<RealVec>& velocities, vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM tolerance) { // --------------------------------------------------------------------------------------- static const char* methodName = "\nReferenceVerletDynamics::update"; static const RealOpenMM zero = 0.0; static const RealOpenMM one = 1.0; // --------------------------------------------------------------------------------------- // first-time-through initialization int numberOfAtoms = system.getNumParticles(); if( getTimeStep() == 0 ){ // invert masses for( int ii = 0; ii < numberOfAtoms; ii++ ){ if (masses[ii] == zero) inverseMasses[ii] = zero; else inverseMasses[ii] = one/masses[ii]; } } // Perform the integration. for (int i = 0; i < numberOfAtoms; ++i) { if (masses[i] != zero) for (int j = 0; j < 3; ++j) { velocities[i][j] += inverseMasses[i]*forces[i][j]*getDeltaT(); xPrime[i][j] = atomCoordinates[i][j] + velocities[i][j]*getDeltaT(); } } ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm(); if (referenceConstraintAlgorithm) referenceConstraintAlgorithm->apply(atomCoordinates, xPrime, inverseMasses, tolerance); // Update the positions and velocities. RealOpenMM velocityScale = static_cast<RealOpenMM>( 1.0/getDeltaT() ); for (int i = 0; i < numberOfAtoms; ++i) { if (masses[i] != zero) for (int j = 0; j < 3; ++j) { velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]); atomCoordinates[i][j] = xPrime[i][j]; } } ReferenceVirtualSites::computePositions(system, atomCoordinates); incrementTimeStep(); }
void ReferenceBrownianDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates, vector<RealVec>& velocities, vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM tolerance) { // --------------------------------------------------------------------------------------- static const char* methodName = "\nReferenceBrownianDynamics::update"; static const RealOpenMM zero = 0.0; static const RealOpenMM one = 1.0; // --------------------------------------------------------------------------------------- // first-time-through initialization int numberOfAtoms = system.getNumParticles(); if( getTimeStep() == 0 ){ // invert masses for( int ii = 0; ii < numberOfAtoms; ii++ ){ if (masses[ii] == zero) inverseMasses[ii] = zero; else inverseMasses[ii] = one/masses[ii]; } } // Perform the integration. const RealOpenMM noiseAmplitude = static_cast<RealOpenMM>( sqrt(2.0*BOLTZ*getTemperature()*getDeltaT()/getFriction()) ); const RealOpenMM forceScale = getDeltaT()/getFriction(); for (int i = 0; i < numberOfAtoms; ++i) { if (masses[i] != zero) for (int j = 0; j < 3; ++j) { xPrime[i][j] = atomCoordinates[i][j] + forceScale*inverseMasses[i]*forces[i][j] + noiseAmplitude*SQRT(inverseMasses[i])*SimTKOpenMMUtilities::getNormallyDistributedRandomNumber(); } } ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm(); if (referenceConstraintAlgorithm) referenceConstraintAlgorithm->apply(atomCoordinates, xPrime, inverseMasses, tolerance); // Update the positions and velocities. RealOpenMM velocityScale = static_cast<RealOpenMM>( 1.0/getDeltaT() ); for (int i = 0; i < numberOfAtoms; ++i) { if (masses[i] != zero) for (int j = 0; j < 3; ++j) { velocities[i][j] = velocityScale*(xPrime[i][j] - atomCoordinates[i][j]); atomCoordinates[i][j] = xPrime[i][j]; } } ReferenceVirtualSites::computePositions(system, atomCoordinates); incrementTimeStep(); }
void ReferenceStochasticDynamics::update(const OpenMM::System& system, vector<RealVec>& atomCoordinates, vector<RealVec>& velocities, vector<RealVec>& forces, vector<RealOpenMM>& masses, RealOpenMM tolerance) { // --------------------------------------------------------------------------------------- static const char* methodName = "\nReferenceStochasticDynamics::update"; static const RealOpenMM zero = 0.0; static const RealOpenMM one = 1.0; // --------------------------------------------------------------------------------------- // first-time-through initialization int numberOfAtoms = system.getNumParticles(); if( getTimeStep() == 0 ){ // invert masses for( int ii = 0; ii < numberOfAtoms; ii++ ){ if (masses[ii] == zero) inverseMasses[ii] = zero; else inverseMasses[ii] = one/masses[ii]; } } // 1st update updatePart1( numberOfAtoms, atomCoordinates, velocities, forces, inverseMasses, xPrime ); // 2nd update updatePart2( numberOfAtoms, atomCoordinates, velocities, forces, inverseMasses, xPrime ); ReferenceConstraintAlgorithm* referenceConstraintAlgorithm = getReferenceConstraintAlgorithm(); if (referenceConstraintAlgorithm) referenceConstraintAlgorithm->apply(atomCoordinates, xPrime, inverseMasses, tolerance); // copy xPrime -> atomCoordinates RealOpenMM invStepSize = 1.0/getDeltaT(); for (int i = 0; i < numberOfAtoms; ++i) if (masses[i] != zero) for (int j = 0; j < 3; ++j) { velocities[i][j] = invStepSize*(xPrime[i][j]-atomCoordinates[i][j]); atomCoordinates[i][j] = xPrime[i][j]; } ReferenceVirtualSites::computePositions(system, atomCoordinates); incrementTimeStep(); }