Unverified Commit 8dd60914 authored by Tristan Croll's avatar Tristan Croll Committed by GitHub
Browse files

Merge pull request #3 from openmm/master

Sync with official repo
parents 3475b790 75c1fcb6
...@@ -96,8 +96,9 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const { ...@@ -96,8 +96,9 @@ State Context::getState(int types, bool enforcePeriodicBox, int groups) const {
bool includeForces = types&State::Forces; bool includeForces = types&State::Forces;
bool includeEnergy = types&State::Energy; bool includeEnergy = types&State::Energy;
bool includeParameterDerivs = types&State::ParameterDerivatives; bool includeParameterDerivs = types&State::ParameterDerivatives;
bool needForcesForEnergy = (includeEnergy && getIntegrator().kineticEnergyRequiresForce());
if (includeForces || includeEnergy || includeParameterDerivs) { if (includeForces || includeEnergy || includeParameterDerivs) {
double energy = impl->calcForcesAndEnergy(includeForces || includeEnergy || includeParameterDerivs, includeEnergy, groups); double energy = impl->calcForcesAndEnergy(includeForces || needForcesForEnergy || includeParameterDerivs, includeEnergy, groups);
if (includeEnergy) if (includeEnergy)
builder.setEnergy(impl->calcKineticEnergy(), energy); builder.setEnergy(impl->calcKineticEnergy(), energy);
if (includeForces) { if (includeForces) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2017 Stanford University and the Authors. * * Portions copyright (c) 2011-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ParsedExpression.h"
#include "lepton/Parser.h"
#include <set> #include <set>
#include <string> #include <string>
...@@ -45,7 +48,7 @@ CustomIntegrator::CustomIntegrator(double stepSize) : globalsAreCurrent(true), f ...@@ -45,7 +48,7 @@ CustomIntegrator::CustomIntegrator(double stepSize) : globalsAreCurrent(true), f
setStepSize(stepSize); setStepSize(stepSize);
setConstraintTolerance(1e-5); setConstraintTolerance(1e-5);
setRandomNumberSeed(0); setRandomNumberSeed(0);
kineticEnergy = "m*v*v/2"; setKineticEnergyExpression("m*v*v/2");
} }
CustomIntegrator::~CustomIntegrator() { CustomIntegrator::~CustomIntegrator() {
...@@ -103,9 +106,14 @@ vector<string> CustomIntegrator::getKernelNames() { ...@@ -103,9 +106,14 @@ vector<string> CustomIntegrator::getKernelNames() {
} }
double CustomIntegrator::computeKineticEnergy() { double CustomIntegrator::computeKineticEnergy() {
forcesAreValid = keNeedsForce;
return kernel.getAs<IntegrateCustomStepKernel>().computeKineticEnergy(*context, *this, forcesAreValid); return kernel.getAs<IntegrateCustomStepKernel>().computeKineticEnergy(*context, *this, forcesAreValid);
} }
bool CustomIntegrator::kineticEnergyRequiresForce() const {
return keNeedsForce;
}
void CustomIntegrator::step(int steps) { void CustomIntegrator::step(int steps) {
if (context == NULL) if (context == NULL)
throw OpenMMException("This Integrator is not bound to a context!"); throw OpenMMException("This Integrator is not bound to a context!");
...@@ -312,4 +320,6 @@ const string& CustomIntegrator::getKineticEnergyExpression() const { ...@@ -312,4 +320,6 @@ const string& CustomIntegrator::getKineticEnergyExpression() const {
void CustomIntegrator::setKineticEnergyExpression(const string& expression) { void CustomIntegrator::setKineticEnergyExpression(const string& expression) {
kineticEnergy = expression; kineticEnergy = expression;
Lepton::CompiledExpression expr = Lepton::Parser::parse(kineticEnergy).createCompiledExpression();
keNeedsForce = (expr.getVariables().find("f") != expr.getVariables().end());
} }
...@@ -65,7 +65,7 @@ CustomNonbondedForce::CustomNonbondedForce(const CustomNonbondedForce& rhs) { ...@@ -65,7 +65,7 @@ CustomNonbondedForce::CustomNonbondedForce(const CustomNonbondedForce& rhs) {
particles = rhs.particles; particles = rhs.particles;
exclusions = rhs.exclusions; exclusions = rhs.exclusions;
interactionGroups = rhs.interactionGroups; interactionGroups = rhs.interactionGroups;
for (vector<FunctionInfo>::const_iterator it = rhs.functions.begin(); it != rhs.functions.end(); it++) for (vector<FunctionInfo>::const_iterator it = rhs.functions.begin(); it != rhs.functions.end(); ++it)
functions.push_back(FunctionInfo(it->name, it->function->Copy())); functions.push_back(FunctionInfo(it->name, it->function->Copy()));
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. * * Portions copyright (c) 2010-2019 Stanford University and the Authors. *
* Authors: Peter Eastman, Lee-Ping Wang * * Authors: Peter Eastman, Lee-Ping Wang *
* Contributors: * * Contributors: *
* * * *
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "SimTKOpenMMUtilities.h"
#include <cmath> #include <cmath>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
...@@ -43,11 +44,6 @@ using namespace OpenMM; ...@@ -43,11 +44,6 @@ using namespace OpenMM;
using namespace OpenMM_SFMT; using namespace OpenMM_SFMT;
using std::vector; using std::vector;
const float BOLTZMANN = 1.380658e-23f; // (J/K)
const float AVOGADRO = 6.0221367e23f;
const float RGAS = BOLTZMANN*AVOGADRO; // (J/(mol K))
const float BOLTZ = RGAS/1000; // (kJ/(mol K))
MonteCarloAnisotropicBarostatImpl::MonteCarloAnisotropicBarostatImpl(const MonteCarloAnisotropicBarostat& owner) : owner(owner), step(0) { MonteCarloAnisotropicBarostatImpl::MonteCarloAnisotropicBarostatImpl(const MonteCarloAnisotropicBarostat& owner) : owner(owner), step(0) {
} }
...@@ -64,10 +60,7 @@ void MonteCarloAnisotropicBarostatImpl::initialize(ContextImpl& context) { ...@@ -64,10 +60,7 @@ void MonteCarloAnisotropicBarostatImpl::initialize(ContextImpl& context) {
numAttempted[i] = 0; numAttempted[i] = 0;
numAccepted[i] = 0; numAccepted[i] = 0;
} }
int randSeed = owner.getRandomNumberSeed(); SimTKOpenMMUtilities::setRandomNumberSeed(owner.getRandomNumberSeed());
// A random seed of 0 means use a unique one
if (randSeed == 0) randSeed = osrngseed();
init_gen_rand(randSeed, random);
} }
void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context) { void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context) {
...@@ -85,7 +78,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context) ...@@ -85,7 +78,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
// Choose which axis to modify at random. // Choose which axis to modify at random.
int axis; int axis;
while (true) { while (true) {
double rnd = genrand_real2(random)*3.0; double rnd = SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber()*3.0;
if (rnd < 1.0) { if (rnd < 1.0) {
if (owner.getScaleX()) { if (owner.getScaleX()) {
axis = 0; axis = 0;
...@@ -110,7 +103,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context) ...@@ -110,7 +103,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
Vec3 box[3]; Vec3 box[3];
context.getPeriodicBoxVectors(box[0], box[1], box[2]); context.getPeriodicBoxVectors(box[0], box[1], box[2]);
double volume = box[0][0]*box[1][1]*box[2][2]; double volume = box[0][0]*box[1][1]*box[2][2];
double deltaVolume = volumeScale[axis]*2*(genrand_real2(random)-0.5); double deltaVolume = volumeScale[axis]*2*(SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber()-0.5);
double newVolume = volume+deltaVolume; double newVolume = volume+deltaVolume;
Vec3 lengthScale(1.0, 1.0, 1.0); Vec3 lengthScale(1.0, 1.0, 1.0);
lengthScale[axis] = newVolume/volume; lengthScale[axis] = newVolume/volume;
...@@ -124,7 +117,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context) ...@@ -124,7 +117,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy();
double kT = BOLTZ*context.getParameter(MonteCarloAnisotropicBarostat::Temperature()); double kT = BOLTZ*context.getParameter(MonteCarloAnisotropicBarostat::Temperature());
double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume); double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume);
if (w > 0 && genrand_real2(random) > std::exp(-w/kT)) { if (w > 0 && SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() > std::exp(-w/kT)) {
// Reject the step. // Reject the step.
kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context); kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2010-2017 Stanford University and the Authors. * * Portions copyright (c) 2010-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "SimTKOpenMMUtilities.h"
#include <cmath> #include <cmath>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
...@@ -43,11 +44,6 @@ using namespace OpenMM; ...@@ -43,11 +44,6 @@ using namespace OpenMM;
using namespace OpenMM_SFMT; using namespace OpenMM_SFMT;
using std::vector; using std::vector;
const float BOLTZMANN = 1.380658e-23f; // (J/K)
const float AVOGADRO = 6.0221367e23f;
const float RGAS = BOLTZMANN*AVOGADRO; // (J/(mol K))
const float BOLTZ = RGAS/1000; // (kJ/(mol K))
MonteCarloBarostatImpl::MonteCarloBarostatImpl(const MonteCarloBarostat& owner) : owner(owner), step(0) { MonteCarloBarostatImpl::MonteCarloBarostatImpl(const MonteCarloBarostat& owner) : owner(owner), step(0) {
} }
...@@ -62,10 +58,7 @@ void MonteCarloBarostatImpl::initialize(ContextImpl& context) { ...@@ -62,10 +58,7 @@ void MonteCarloBarostatImpl::initialize(ContextImpl& context) {
volumeScale = 0.01*volume; volumeScale = 0.01*volume;
numAttempted = 0; numAttempted = 0;
numAccepted = 0; numAccepted = 0;
int randSeed = owner.getRandomNumberSeed(); SimTKOpenMMUtilities::setRandomNumberSeed(owner.getRandomNumberSeed());
// A random seed of 0 means use a unique one
if (randSeed == 0) randSeed = osrngseed();
init_gen_rand(randSeed, random);
} }
void MonteCarloBarostatImpl::updateContextState(ContextImpl& context, bool& forcesInvalid) { void MonteCarloBarostatImpl::updateContextState(ContextImpl& context, bool& forcesInvalid) {
...@@ -82,7 +75,7 @@ void MonteCarloBarostatImpl::updateContextState(ContextImpl& context, bool& forc ...@@ -82,7 +75,7 @@ void MonteCarloBarostatImpl::updateContextState(ContextImpl& context, bool& forc
Vec3 box[3]; Vec3 box[3];
context.getPeriodicBoxVectors(box[0], box[1], box[2]); context.getPeriodicBoxVectors(box[0], box[1], box[2]);
double volume = box[0][0]*box[1][1]*box[2][2]; double volume = box[0][0]*box[1][1]*box[2][2];
double deltaVolume = volumeScale*2*(genrand_real2(random)-0.5); double deltaVolume = volumeScale*2*(SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber()-0.5);
double newVolume = volume+deltaVolume; double newVolume = volume+deltaVolume;
double lengthScale = std::pow(newVolume/volume, 1.0/3.0); double lengthScale = std::pow(newVolume/volume, 1.0/3.0);
kernel.getAs<ApplyMonteCarloBarostatKernel>().scaleCoordinates(context, lengthScale, lengthScale, lengthScale); kernel.getAs<ApplyMonteCarloBarostatKernel>().scaleCoordinates(context, lengthScale, lengthScale, lengthScale);
...@@ -94,7 +87,7 @@ void MonteCarloBarostatImpl::updateContextState(ContextImpl& context, bool& forc ...@@ -94,7 +87,7 @@ void MonteCarloBarostatImpl::updateContextState(ContextImpl& context, bool& forc
double pressure = context.getParameter(MonteCarloBarostat::Pressure())*(AVOGADRO*1e-25); double pressure = context.getParameter(MonteCarloBarostat::Pressure())*(AVOGADRO*1e-25);
double kT = BOLTZ*context.getParameter(MonteCarloBarostat::Temperature()); double kT = BOLTZ*context.getParameter(MonteCarloBarostat::Temperature());
double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume); double w = finalEnergy-initialEnergy + pressure*deltaVolume - context.getMolecules().size()*kT*std::log(newVolume/volume);
if (w > 0 && genrand_real2(random) > std::exp(-w/kT)) { if (w > 0 && SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() > std::exp(-w/kT)) {
// Reject the step. // Reject the step.
kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context); kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2010-2016 Stanford University and the Authors. * * Portions copyright (c) 2010-2019 Stanford University and the Authors. *
* Authors: Peter Eastman, Lee-Ping Wang * * Authors: Peter Eastman, Lee-Ping Wang *
* Contributors: * * Contributors: *
* * * *
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/kernels.h" #include "openmm/kernels.h"
#include "openmm/OpenMMException.h" #include "openmm/OpenMMException.h"
#include "SimTKOpenMMUtilities.h"
#include <cmath> #include <cmath>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
...@@ -43,11 +44,6 @@ using namespace OpenMM; ...@@ -43,11 +44,6 @@ using namespace OpenMM;
using namespace OpenMM_SFMT; using namespace OpenMM_SFMT;
using std::vector; using std::vector;
const float BOLTZMANN = 1.380658e-23f; // (J/K)
const float AVOGADRO = 6.0221367e23f;
const float RGAS = BOLTZMANN*AVOGADRO; // (J/(mol K))
const float BOLTZ = RGAS/1000; // (kJ/(mol K))
MonteCarloMembraneBarostatImpl::MonteCarloMembraneBarostatImpl(const MonteCarloMembraneBarostat& owner) : owner(owner), step(0) { MonteCarloMembraneBarostatImpl::MonteCarloMembraneBarostatImpl(const MonteCarloMembraneBarostat& owner) : owner(owner), step(0) {
} }
...@@ -64,10 +60,7 @@ void MonteCarloMembraneBarostatImpl::initialize(ContextImpl& context) { ...@@ -64,10 +60,7 @@ void MonteCarloMembraneBarostatImpl::initialize(ContextImpl& context) {
numAttempted[i] = 0; numAttempted[i] = 0;
numAccepted[i] = 0; numAccepted[i] = 0;
} }
int randSeed = owner.getRandomNumberSeed(); SimTKOpenMMUtilities::setRandomNumberSeed(owner.getRandomNumberSeed());
// A random seed of 0 means use a unique one
if (randSeed == 0) randSeed = osrngseed();
init_gen_rand(randSeed, random);
} }
void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) { void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) {
...@@ -84,7 +77,7 @@ void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) { ...@@ -84,7 +77,7 @@ void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) {
// Choose which axis to modify at random. // Choose which axis to modify at random.
int axis; int axis;
while (true) { while (true) {
double rnd = genrand_real2(random)*3.0; double rnd = SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber()*3.0;
if (rnd < 1.0) { if (rnd < 1.0) {
axis = 0; axis = 0;
break; break;
...@@ -102,7 +95,7 @@ void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) { ...@@ -102,7 +95,7 @@ void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) {
Vec3 box[3]; Vec3 box[3];
context.getPeriodicBoxVectors(box[0], box[1], box[2]); context.getPeriodicBoxVectors(box[0], box[1], box[2]);
double volume = box[0][0]*box[1][1]*box[2][2]; double volume = box[0][0]*box[1][1]*box[2][2];
double deltaVolume = volumeScale[axis]*2*(genrand_real2(random)-0.5); double deltaVolume = volumeScale[axis]*2*(SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber()-0.5);
double newVolume = volume+deltaVolume; double newVolume = volume+deltaVolume;
Vec3 lengthScale(1.0, 1.0, 1.0); Vec3 lengthScale(1.0, 1.0, 1.0);
if ((axis == 0 || axis == 1) && owner.getXYMode() == MonteCarloMembraneBarostat::XYIsotropic) if ((axis == 0 || axis == 1) && owner.getXYMode() == MonteCarloMembraneBarostat::XYIsotropic)
...@@ -125,7 +118,7 @@ void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) { ...@@ -125,7 +118,7 @@ void MonteCarloMembraneBarostatImpl::updateContextState(ContextImpl& context) {
double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy(); double finalEnergy = context.getOwner().getState(State::Energy).getPotentialEnergy();
double kT = BOLTZ*context.getParameter(MonteCarloMembraneBarostat::Temperature()); double kT = BOLTZ*context.getParameter(MonteCarloMembraneBarostat::Temperature());
double w = finalEnergy-initialEnergy + pressure*deltaVolume - tension*deltaArea - context.getMolecules().size()*kT*std::log(newVolume/volume); double w = finalEnergy-initialEnergy + pressure*deltaVolume - tension*deltaArea - context.getMolecules().size()*kT*std::log(newVolume/volume);
if (w > 0 && genrand_real2(random) > std::exp(-w/kT)) { if (w > 0 && SimTKOpenMMUtilities::getUniformlyDistributedRandomNumber() > std::exp(-w/kT)) {
// Reject the step. // Reject the step.
kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context); kernel.getAs<ApplyMonteCarloBarostatKernel>().restoreCoordinates(context);
......
...@@ -138,7 +138,7 @@ bool System::usesPeriodicBoundaryConditions() const { ...@@ -138,7 +138,7 @@ bool System::usesPeriodicBoundaryConditions() const {
bool uses_pbc = false; bool uses_pbc = false;
bool all_forces_implement = true; bool all_forces_implement = true;
for (std::vector<Force*>::const_iterator it = forces.begin(); for (std::vector<Force*>::const_iterator it = forces.begin();
it != forces.end(); it++) { it != forces.end(); ++it) {
try { try {
if ((*it)->usesPeriodicBoundaryConditions()) if ((*it)->usesPeriodicBoundaryConditions())
uses_pbc = true; uses_pbc = true;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2012 Stanford University and the Authors. * * Portions copyright (c) 2008-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -46,6 +46,7 @@ VariableLangevinIntegrator::VariableLangevinIntegrator(double temperature, doubl ...@@ -46,6 +46,7 @@ VariableLangevinIntegrator::VariableLangevinIntegrator(double temperature, doubl
setTemperature(temperature); setTemperature(temperature);
setFriction(frictionCoeff); setFriction(frictionCoeff);
setErrorTolerance(errorTol); setErrorTolerance(errorTol);
setMaximumStepSize(0.0);
setConstraintTolerance(1e-5); setConstraintTolerance(1e-5);
setRandomNumberSeed(0); setRandomNumberSeed(0);
setStepSize(0.0); setStepSize(0.0);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2012 Stanford University and the Authors. * * Portions copyright (c) 2008-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -41,7 +41,7 @@ using namespace OpenMM; ...@@ -41,7 +41,7 @@ using namespace OpenMM;
using std::string; using std::string;
using std::vector; using std::vector;
VariableVerletIntegrator::VariableVerletIntegrator(double errorTol) : errorTol(errorTol) { VariableVerletIntegrator::VariableVerletIntegrator(double errorTol) : errorTol(errorTol), maxStepSize(0.0) {
setConstraintTolerance(1e-5); setConstraintTolerance(1e-5);
setStepSize(0.0); setStepSize(0.0);
} }
......
/* Portions copyright (c) 2013-2019 Stanford University and Simbios.
* Authors: Peter Eastman
* Contributors:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __CPU_BAOAB_DYNAMICS_H__
#define __CPU_BAOAB_DYNAMICS_H__
#include "ReferenceBAOABDynamics.h"
#include "CpuRandom.h"
#include "openmm/internal/ThreadPool.h"
#include "sfmt/SFMT.h"
namespace OpenMM {
class CpuBAOABDynamics : public ReferenceBAOABDynamics {
public:
/**
* Constructor.
*
* @param numberOfAtoms number of atoms
* @param deltaT delta t for dynamics
* @param friction friction coefficient
* @param temperature temperature
* @param threads thread pool for parallelizing computation
* @param random random number generator
*/
CpuBAOABDynamics(int numberOfAtoms, double deltaT, double friction, double temperature, OpenMM::ThreadPool& threads, OpenMM::CpuRandom& random);
/**
* Destructor.
*/
~CpuBAOABDynamics();
/**
* First update step.
*
* @param numberOfAtoms number of atoms
* @param atomCoordinates atom coordinates
* @param velocities velocities
* @param forces forces
* @param inverseMasses inverse atom masses
* @param xPrime xPrime
*/
void updatePart1(int numberOfAtoms, std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& velocities,
std::vector<OpenMM::Vec3>& forces, std::vector<double>& inverseMasses, std::vector<OpenMM::Vec3>& xPrime);
/**
* Second update step.
*
* @param numberOfAtoms number of atoms
* @param atomCoordinates atom coordinates
* @param velocities velocities
* @param inverseMasses inverse atom masses
* @param xPrime xPrime
*/
void updatePart2(int numberOfAtoms, std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& velocities,
std::vector<double>& inverseMasses, std::vector<OpenMM::Vec3>& xPrime);
/**
* Third update
*
* @param context the context this integrator is updating
* @param numberOfAtoms number of atoms
* @param atomCoordinates atom coordinates
* @param velocities velocities
* @param inverseMasses inverse atom masses
* @param xPrime xPrime
*/
void updatePart3(OpenMM::ContextImpl& context, int numberOfAtoms, std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& velocities,
std::vector<double>& inverseMasses, std::vector<OpenMM::Vec3>& xPrime);
private:
void threadUpdate1(int threadIndex);
void threadUpdate2(int threadIndex);
void threadUpdate3(int threadIndex);
void threadUpdate4(int threadIndex);
OpenMM::ThreadPool& threads;
OpenMM::CpuRandom& random;
std::vector<OpenMM_SFMT::SFMT> threadRandom;
// The following variables are used to make information accessible to the individual threads.
int numberOfAtoms;
OpenMM::Vec3* atomCoordinates;
OpenMM::Vec3* velocities;
OpenMM::Vec3* forces;
double* inverseMasses;
OpenMM::Vec3* xPrime;
};
} // namespace OpenMM
#endif // __CPU_BAOAB_DYNAMICS_H__
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2018 Stanford University and the Authors. * * Portions copyright (c) 2013-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "CpuBAOABDynamics.h"
#include "CpuBondForce.h" #include "CpuBondForce.h"
#include "CpuCustomGBForce.h" #include "CpuCustomGBForce.h"
#include "CpuCustomManyParticleForce.h" #include "CpuCustomManyParticleForce.h"
...@@ -536,6 +537,47 @@ private: ...@@ -536,6 +537,47 @@ private:
double prevTemp, prevFriction, prevStepSize; double prevTemp, prevFriction, prevStepSize;
}; };
/**
* This kernel is invoked by BAOABLangevinIntegrator to take one time step.
*/
class CpuIntegrateBAOABStepKernel : public IntegrateBAOABStepKernel {
public:
CpuIntegrateBAOABStepKernel(std::string name, const Platform& platform, CpuPlatform::PlatformData& data) : IntegrateBAOABStepKernel(name, platform),
data(data), dynamics(0) {
}
~CpuIntegrateBAOABStepKernel();
/**
* Initialize the kernel, setting up the particle masses.
*
* @param system the System this kernel will be applied to
* @param integrator the BAOABLangevinIntegrator this kernel will be used for
*/
void initialize(const System& system, const BAOABLangevinIntegrator& integrator);
/**
* Execute the kernel.
*
* @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for
* @param forcesAreValid if the context has been modified since the last time step, this will be
* false to show that cached forces are invalid and must be recalculated.
* On exit, this should specify whether the cached forces are valid at the
* end of the step.
*/
void execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid);
/**
* Compute the kinetic energy.
*
* @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for
*/
double computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator);
private:
CpuPlatform::PlatformData& data;
CpuBAOABDynamics* dynamics;
std::vector<double> masses;
double prevTemp, prevFriction, prevStepSize;
};
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_CPUKERNELS_H_*/ #endif /*OPENMM_CPUKERNELS_H_*/
......
/* Portions copyright (c) 2006-2019 Stanford University and Simbios.
* Authors: Peter Eastman
* Contributors:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "SimTKOpenMMUtilities.h"
#include "CpuBAOABDynamics.h"
using namespace OpenMM;
using namespace std;
CpuBAOABDynamics::CpuBAOABDynamics(int numberOfAtoms, double deltaT, double friction, double temperature, ThreadPool& threads, CpuRandom& random) :
ReferenceBAOABDynamics(numberOfAtoms, deltaT, friction, temperature), threads(threads), random(random) {
}
CpuBAOABDynamics::~CpuBAOABDynamics() {
}
void CpuBAOABDynamics::updatePart1(int numberOfAtoms, vector<Vec3>& atomCoordinates, vector<Vec3>& velocities,
vector<Vec3>& forces, vector<double>& inverseMasses, vector<Vec3>& xPrime) {
// Record the parameters for the threads.
this->numberOfAtoms = numberOfAtoms;
this->atomCoordinates = &atomCoordinates[0];
this->velocities = &velocities[0];
this->forces = &forces[0];
this->inverseMasses = &inverseMasses[0];
this->xPrime = &xPrime[0];
// Signal the threads to start running and wait for them to finish.
threads.execute([&] (ThreadPool& threads, int threadIndex) { threadUpdate1(threadIndex); });
threads.waitForThreads();
}
void CpuBAOABDynamics::updatePart2(int numberOfAtoms, vector<Vec3>& atomCoordinates, vector<Vec3>& velocities,
vector<double>& inverseMasses, vector<Vec3>& xPrime) {
// Record the parameters for the threads.
this->numberOfAtoms = numberOfAtoms;
this->atomCoordinates = &atomCoordinates[0];
this->velocities = &velocities[0];
this->inverseMasses = &inverseMasses[0];
this->xPrime = &xPrime[0];
// Signal the threads to start running and wait for them to finish.
threads.execute([&] (ThreadPool& threads, int threadIndex) { threadUpdate2(threadIndex); });
threads.waitForThreads();
}
void CpuBAOABDynamics::updatePart3(ContextImpl& context, int numberOfAtoms, vector<Vec3>& atomCoordinates, vector<Vec3>& velocities,
vector<double>& inverseMasses, vector<Vec3>& xPrime) {
// Record the parameters for the threads.
this->numberOfAtoms = numberOfAtoms;
this->atomCoordinates = &atomCoordinates[0];
this->velocities = &velocities[0];
this->inverseMasses = &inverseMasses[0];
this->xPrime = &xPrime[0];
// Signal the threads to start running and wait for them to finish.
threads.execute([&] (ThreadPool& threads, int threadIndex) { threadUpdate3(threadIndex); });
threads.waitForThreads();
context.calcForcesAndEnergy(true, false);
threads.execute([&] (ThreadPool& threads, int threadIndex) { threadUpdate4(threadIndex); });
threads.waitForThreads();
}
void CpuBAOABDynamics::threadUpdate1(int threadIndex) {
const double halfdt = 0.5*getDeltaT();
int start = threadIndex*numberOfAtoms/threads.getNumThreads();
int end = (threadIndex+1)*numberOfAtoms/threads.getNumThreads();
for (int i = start; i < end; i++) {
if (inverseMasses[i] != 0.0) {
velocities[i] += (halfdt*inverseMasses[i])*forces[i];
xPrime[i] = atomCoordinates[i] + velocities[i]*halfdt;
oldx[i] = xPrime[i];
}
}
}
void CpuBAOABDynamics::threadUpdate2(int threadIndex) {
const double halfdt = 0.5*getDeltaT();
const double kT = BOLTZ*getTemperature();
const double friction = getFriction();
const double vscale = exp(-getDeltaT()*friction);
const double noisescale = sqrt(1-vscale*vscale);
int start = threadIndex*numberOfAtoms/threads.getNumThreads();
int end = (threadIndex+1)*numberOfAtoms/threads.getNumThreads();
for (int i = start; i < end; i++) {
if (inverseMasses[i] != 0.0) {
velocities[i] += (xPrime[i]-oldx[i])/halfdt;
Vec3 noise(random.getGaussianRandom(threadIndex), random.getGaussianRandom(threadIndex), random.getGaussianRandom(threadIndex));
velocities[i] = vscale*velocities[i] + noisescale*sqrt(kT*inverseMasses[i])*noise;
atomCoordinates[i] = xPrime[i];
xPrime[i] = atomCoordinates[i] + velocities[i]*halfdt;
oldx[i] = xPrime[i];
}
}
}
void CpuBAOABDynamics::threadUpdate3(int threadIndex) {
const double halfdt = 0.5*getDeltaT();
int start = threadIndex*numberOfAtoms/threads.getNumThreads();
int end = (threadIndex+1)*numberOfAtoms/threads.getNumThreads();
for (int i = start; i < end; ++i)
if (inverseMasses[i] != 0.0) {
velocities[i] += (xPrime[i]-oldx[i])/halfdt;
atomCoordinates[i] = xPrime[i];
}
}
void CpuBAOABDynamics::threadUpdate4(int threadIndex) {
const double halfdt = 0.5*getDeltaT();
int start = threadIndex*numberOfAtoms/threads.getNumThreads();
int end = (threadIndex+1)*numberOfAtoms/threads.getNumThreads();
for (int i = start; i < end; ++i)
if (inverseMasses[i] != 0.0)
velocities[i] += (halfdt*inverseMasses[i])*forces[i];
}
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2016 Stanford University and the Authors. * * Portions copyright (c) 2013-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -61,5 +61,7 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform& ...@@ -61,5 +61,7 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform&
return new CpuCalcGayBerneForceKernel(name, platform, data); return new CpuCalcGayBerneForceKernel(name, platform, data);
if (name == IntegrateLangevinStepKernel::Name()) if (name == IntegrateLangevinStepKernel::Name())
return new CpuIntegrateLangevinStepKernel(name, platform, data); return new CpuIntegrateLangevinStepKernel(name, platform, data);
if (name == IntegrateBAOABStepKernel::Name())
return new CpuIntegrateBAOABStepKernel(name, platform, data);
throw OpenMMException((std::string("Tried to create kernel with illegal kernel name '") + name + "'").c_str()); throw OpenMMException((std::string("Tried to create kernel with illegal kernel name '") + name + "'").c_str());
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2018 Stanford University and the Authors. * * Portions copyright (c) 2013-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -58,37 +58,37 @@ using namespace std; ...@@ -58,37 +58,37 @@ using namespace std;
static vector<Vec3>& extractPositions(ContextImpl& context) { static vector<Vec3>& extractPositions(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *((vector<Vec3>*) data->positions); return *data->positions;
} }
static vector<Vec3>& extractVelocities(ContextImpl& context) { static vector<Vec3>& extractVelocities(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *((vector<Vec3>*) data->velocities); return *data->velocities;
} }
static vector<Vec3>& extractForces(ContextImpl& context) { static vector<Vec3>& extractForces(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *((vector<Vec3>*) data->forces); return *data->forces;
} }
static Vec3& extractBoxSize(ContextImpl& context) { static Vec3& extractBoxSize(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *(Vec3*) data->periodicBoxSize; return *data->periodicBoxSize;
} }
static Vec3* extractBoxVectors(ContextImpl& context) { static Vec3* extractBoxVectors(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return (Vec3*) data->periodicBoxVectors; return data->periodicBoxVectors;
} }
static ReferenceConstraints& extractConstraints(ContextImpl& context) { static ReferenceConstraints& extractConstraints(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *(ReferenceConstraints*) data->constraints; return *data->constraints;
} }
static map<string, double>& extractEnergyParameterDerivatives(ContextImpl& context) { static map<string, double>& extractEnergyParameterDerivatives(ContextImpl& context) {
ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData()); ReferencePlatform::PlatformData* data = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
return *((map<string, double>*) data->energyParameterDerivatives); return *data->energyParameterDerivatives;
} }
/** /**
...@@ -1352,3 +1352,43 @@ void CpuIntegrateLangevinStepKernel::execute(ContextImpl& context, const Langevi ...@@ -1352,3 +1352,43 @@ void CpuIntegrateLangevinStepKernel::execute(ContextImpl& context, const Langevi
double CpuIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator) { double CpuIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator) {
return computeShiftedKineticEnergy(context, masses, 0.5*integrator.getStepSize()); return computeShiftedKineticEnergy(context, masses, 0.5*integrator.getStepSize());
} }
CpuIntegrateBAOABStepKernel::~CpuIntegrateBAOABStepKernel() {
if (dynamics)
delete dynamics;
}
void CpuIntegrateBAOABStepKernel::initialize(const System& system, const BAOABLangevinIntegrator& integrator) {
int numParticles = system.getNumParticles();
masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i)
masses[i] = system.getParticleMass(i);
data.random.initialize(integrator.getRandomNumberSeed(), data.threads.getNumThreads());
}
void CpuIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid) {
double temperature = integrator.getTemperature();
double friction = integrator.getFriction();
double stepSize = integrator.getStepSize();
vector<Vec3>& posData = extractPositions(context);
vector<Vec3>& velData = extractVelocities(context);
if (dynamics == 0 || temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
// Recreate the computation objects with the new parameters.
if (dynamics)
delete dynamics;
dynamics = new CpuBAOABDynamics(context.getSystem().getNumParticles(), stepSize, friction, temperature, data.threads, data.random);
dynamics->setReferenceConstraintAlgorithm(&extractConstraints(context));
prevTemp = temperature;
prevFriction = friction;
prevStepSize = stepSize;
}
dynamics->update(context, posData, velData, masses, forcesAreValid, integrator.getConstraintTolerance());
ReferencePlatform::PlatformData* refData = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
refData->time += stepSize;
refData->stepCount++;
}
double CpuIntegrateBAOABStepKernel::computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator) {
return computeShiftedKineticEnergy(context, masses, 0.0);
}
...@@ -80,8 +80,8 @@ public: ...@@ -80,8 +80,8 @@ public:
voxelSizeZ = boxVectors[2][2]/nz; voxelSizeZ = boxVectors[2][2]/nz;
} }
else { else {
ny = max(1, (int) floorf((maxy-miny)/voxelSizeY+0.5f)); ny = max(1, min(500, (int) floorf((maxy-miny)/voxelSizeY+0.5f)));
nz = max(1, (int) floorf((maxz-minz)/voxelSizeZ+0.5f)); nz = max(1, min(500, (int) floorf((maxz-minz)/voxelSizeZ+0.5f)));
if (maxy > miny) if (maxy > miny)
voxelSizeY = (maxy-miny)/ny; voxelSizeY = (maxy-miny)/ny;
if (maxz > minz) if (maxz > minz)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2013-2018 Stanford University and the Authors. * * Portions copyright (c) 2013-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -74,6 +74,7 @@ CpuPlatform::CpuPlatform() { ...@@ -74,6 +74,7 @@ CpuPlatform::CpuPlatform() {
registerKernelFactory(CalcCustomGBForceKernel::Name(), factory); registerKernelFactory(CalcCustomGBForceKernel::Name(), factory);
registerKernelFactory(CalcGayBerneForceKernel::Name(), factory); registerKernelFactory(CalcGayBerneForceKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory); registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory);
registerKernelFactory(IntegrateBAOABStepKernel::Name(), factory);
platformProperties.push_back(CpuThreads()); platformProperties.push_back(CpuThreads());
platformProperties.push_back(CpuDeterministicForces()); platformProperties.push_back(CpuDeterministicForces());
int threads = getNumProcessors(); int threads = getNumProcessors();
......
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2019 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "CpuTests.h"
#include "TestBAOABLangevinIntegrator.h"
void runPlatformTests() {
}
...@@ -1401,6 +1401,45 @@ private: ...@@ -1401,6 +1401,45 @@ private:
CUfunction kernel1, kernel2; CUfunction kernel1, kernel2;
}; };
/**
* This kernel is invoked by BAOABLangevinIntegrator to take one time step.
*/
class CudaIntegrateBAOABStepKernel : public IntegrateBAOABStepKernel {
public:
CudaIntegrateBAOABStepKernel(std::string name, const Platform& platform, CudaContext& cu) : IntegrateBAOABStepKernel(name, platform), cu(cu) {
}
/**
* Initialize the kernel, setting up the particle masses.
*
* @param system the System this kernel will be applied to
* @param integrator the BAOABLangevinIntegrator this kernel will be used for
*/
void initialize(const System& system, const BAOABLangevinIntegrator& integrator);
/**
* Execute the kernel.
*
* @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for
* @param forcesAreValid if the context has been modified since the last time step, this will be
* false to show that cached forces are invalid and must be recalculated.
* On exit, this should specify whether the cached forces are valid at the
* end of the step.
*/
void execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid);
/**
* Compute the kinetic energy.
*
* @param context the context in which to execute this kernel
* @param integrator the BAOABLangevinIntegrator this kernel is being used for
*/
double computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator);
private:
CudaContext& cu;
double prevTemp, prevFriction, prevStepSize;
CudaArray params, oldDelta;
CUfunction kernel1, kernel2, kernel3, kernel4;
};
/** /**
* This kernel is invoked by BrownianIntegrator to take one time step. * This kernel is invoked by BrownianIntegrator to take one time step.
*/ */
...@@ -1594,7 +1633,7 @@ private: ...@@ -1594,7 +1633,7 @@ private:
double energy; double energy;
float energyFloat; float energyFloat;
int numGlobalVariables, sumWorkGroupSize; int numGlobalVariables, sumWorkGroupSize;
bool hasInitializedKernels, deviceGlobalsAreCurrent, modifiesParameters, keNeedsForce, hasAnyConstraints, needsEnergyParamDerivs; bool hasInitializedKernels, deviceGlobalsAreCurrent, modifiesParameters, hasAnyConstraints, needsEnergyParamDerivs;
std::vector<bool> deviceValuesAreCurrent; std::vector<bool> deviceValuesAreCurrent;
mutable std::vector<bool> localValuesAreCurrent; mutable std::vector<bool> localValuesAreCurrent;
CudaArray globalValues; CudaArray globalValues;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008-2016 Stanford University and the Authors. * * Portions copyright (c) 2008-2019 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -120,6 +120,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform ...@@ -120,6 +120,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
return new CudaIntegrateVerletStepKernel(name, platform, cu); return new CudaIntegrateVerletStepKernel(name, platform, cu);
if (name == IntegrateLangevinStepKernel::Name()) if (name == IntegrateLangevinStepKernel::Name())
return new CudaIntegrateLangevinStepKernel(name, platform, cu); return new CudaIntegrateLangevinStepKernel(name, platform, cu);
if (name == IntegrateBAOABStepKernel::Name())
return new CudaIntegrateBAOABStepKernel(name, platform, cu);
if (name == IntegrateBrownianStepKernel::Name()) if (name == IntegrateBrownianStepKernel::Name())
return new CudaIntegrateBrownianStepKernel(name, platform, cu); return new CudaIntegrateBrownianStepKernel(name, platform, cu);
if (name == IntegrateVariableVerletStepKernel::Name()) if (name == IntegrateVariableVerletStepKernel::Name())
......
...@@ -120,6 +120,7 @@ void CudaCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool ...@@ -120,6 +120,7 @@ void CudaCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool
} }
double CudaCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, bool includeForces, bool includeEnergy, int groups, bool& valid) { double CudaCalcForcesAndEnergyKernel::finishComputation(ContextImpl& context, bool includeForces, bool includeEnergy, int groups, bool& valid) {
cu.setAsCurrent();
cu.getBondedUtilities().computeInteractions(groups); cu.getBondedUtilities().computeInteractions(groups);
cu.getNonbondedUtilities().computeInteractions(groups, includeForces, includeEnergy); cu.getNonbondedUtilities().computeInteractions(groups, includeForces, includeEnergy);
double sum = 0.0; double sum = 0.0;
...@@ -7142,6 +7143,95 @@ double CudaIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& contex ...@@ -7142,6 +7143,95 @@ double CudaIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& contex
return cu.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize()); return cu.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize());
} }
void CudaIntegrateBAOABStepKernel::initialize(const System& system, const BAOABLangevinIntegrator& integrator) {
cu.getPlatformData().initializeContexts(system);
cu.setAsCurrent();
cu.getIntegrationUtilities().initRandomNumberGenerator(integrator.getRandomNumberSeed());
map<string, string> defines;
CUmodule module = cu.createModule(CudaKernelSources::baoab, defines, "");
kernel1 = cu.getKernel(module, "integrateBAOABPart1");
kernel2 = cu.getKernel(module, "integrateBAOABPart2");
kernel3 = cu.getKernel(module, "integrateBAOABPart3");
kernel4 = cu.getKernel(module, "integrateBAOABPart4");
if (cu.getUseDoublePrecision() || cu.getUseMixedPrecision()) {
params.initialize<double>(cu, 3, "baoabParams");
oldDelta.initialize<double4>(cu, cu.getPaddedNumAtoms(), "oldDelta");
}
else {
params.initialize<float>(cu, 3, "baoabParams");
oldDelta.initialize<float4>(cu, cu.getPaddedNumAtoms(), "oldDelta");
}
prevStepSize = -1.0;
}
void CudaIntegrateBAOABStepKernel::execute(ContextImpl& context, const BAOABLangevinIntegrator& integrator, bool& forcesAreValid) {
CudaIntegrationUtilities& integration = cu.getIntegrationUtilities();
int numAtoms = cu.getNumAtoms();
int paddedNumAtoms = cu.getPaddedNumAtoms();
if (!forcesAreValid) {
context.calcForcesAndEnergy(true, false);
forcesAreValid = true;
}
double temperature = integrator.getTemperature();
double friction = integrator.getFriction();
double stepSize = integrator.getStepSize();
cu.getIntegrationUtilities().setNextStepSize(stepSize);
if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
// Calculate the integration parameters.
double kT = BOLTZ*temperature;
double vscale = exp(-stepSize*friction);
double noisescale = sqrt(kT*(1-vscale*vscale));
vector<double> p(params.getSize());
p[0] = vscale;
p[1] = noisescale;
params.upload(p, true);
prevTemp = temperature;
prevFriction = friction;
prevStepSize = stepSize;
}
// Perform the integrator.
int randomIndex = integration.prepareRandomNumbers(cu.getPaddedNumAtoms());
CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0);
void* args1[] = {&numAtoms, &paddedNumAtoms, &cu.getVelm().getDevicePointer(), &cu.getForce().getDevicePointer(), &integration.getPosDelta().getDevicePointer(),
&oldDelta.getDevicePointer(), &integration.getStepSize().getDevicePointer()};
cu.executeKernel(kernel1, args1, numAtoms, 128);
integration.applyConstraints(integrator.getConstraintTolerance());
void* args2[] = {&numAtoms, &cu.getPosq().getDevicePointer(), &posCorrection, &cu.getVelm().getDevicePointer(), &integration.getPosDelta().getDevicePointer(),
&oldDelta.getDevicePointer(), &params.getDevicePointer(), &integration.getStepSize().getDevicePointer(), &integration.getRandom().getDevicePointer(), &randomIndex};
cu.executeKernel(kernel2, args2, numAtoms, 128);
integration.applyConstraints(integrator.getConstraintTolerance());
void* args3[] = {&numAtoms, &cu.getPosq().getDevicePointer(), &posCorrection, &cu.getVelm().getDevicePointer(),
&integration.getPosDelta().getDevicePointer(), &oldDelta.getDevicePointer(), &integration.getStepSize().getDevicePointer()};
cu.executeKernel(kernel3, args3, numAtoms, 128);
context.calcForcesAndEnergy(true, false);
void* args4[] = {&numAtoms, &paddedNumAtoms, &cu.getVelm().getDevicePointer(),
&cu.getForce().getDevicePointer(), &integration.getStepSize().getDevicePointer()};
cu.executeKernel(kernel4, args4, numAtoms, 128);
integration.applyVelocityConstraints(integrator.getConstraintTolerance());
integration.computeVirtualSites();
// Update the time and step count.
cu.setTime(cu.getTime()+stepSize);
cu.setStepCount(cu.getStepCount()+1);
cu.reorderAtoms();
if (cu.getAtomsWereReordered())
forcesAreValid = false;
// Reduce UI lag.
#ifdef WIN32
cu.getQueue().flush();
#endif
}
double CudaIntegrateBAOABStepKernel::computeKineticEnergy(ContextImpl& context, const BAOABLangevinIntegrator& integrator) {
return cu.getIntegrationUtilities().computeKineticEnergy(0.0);
}
void CudaIntegrateBrownianStepKernel::initialize(const System& system, const BrownianIntegrator& integrator) { void CudaIntegrateBrownianStepKernel::initialize(const System& system, const BrownianIntegrator& integrator) {
cu.getPlatformData().initializeContexts(system); cu.getPlatformData().initializeContexts(system);
cu.setAsCurrent(); cu.setAsCurrent();
...@@ -7221,6 +7311,8 @@ double CudaIntegrateVariableVerletStepKernel::execute(ContextImpl& context, cons ...@@ -7221,6 +7311,8 @@ double CudaIntegrateVariableVerletStepKernel::execute(ContextImpl& context, cons
// Select the step size to use. // Select the step size to use.
double maxStepSize = maxTime-cu.getTime(); double maxStepSize = maxTime-cu.getTime();
if (integrator.getMaximumStepSize() > 0)
maxStepSize = min(integrator.getMaximumStepSize(), maxStepSize);
float maxStepSizeFloat = (float) maxStepSize; float maxStepSizeFloat = (float) maxStepSize;
double tol = integrator.getErrorTolerance(); double tol = integrator.getErrorTolerance();
float tolFloat = (float) tol; float tolFloat = (float) tol;
...@@ -7295,6 +7387,8 @@ double CudaIntegrateVariableLangevinStepKernel::execute(ContextImpl& context, co ...@@ -7295,6 +7387,8 @@ double CudaIntegrateVariableLangevinStepKernel::execute(ContextImpl& context, co
// Select the step size to use. // Select the step size to use.
double maxStepSize = maxTime-cu.getTime(); double maxStepSize = maxTime-cu.getTime();
if (integrator.getMaximumStepSize() > 0)
maxStepSize = min(integrator.getMaximumStepSize(), maxStepSize);
float maxStepSizeFloat = (float) maxStepSize; float maxStepSizeFloat = (float) maxStepSize;
double tol = integrator.getErrorTolerance(); double tol = integrator.getErrorTolerance();
float tolFloat = (float) tol; float tolFloat = (float) tol;
...@@ -7863,7 +7957,6 @@ void CudaIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context, ...@@ -7863,7 +7957,6 @@ void CudaIntegrateCustomStepKernel::prepareForComputation(ContextImpl& context,
kineticEnergyArgs.push_back(&array.getDevicePointer()); kineticEnergyArgs.push_back(&array.getDevicePointer());
for (auto& array : tabulatedFunctions) for (auto& array : tabulatedFunctions)
kineticEnergyArgs.push_back(&array.getDevicePointer()); kineticEnergyArgs.push_back(&array.getDevicePointer());
keNeedsForce = usesVariable(keExpression, "f");
// Create a second kernel to sum the values. // Create a second kernel to sum the values.
...@@ -8119,17 +8212,6 @@ bool CudaIntegrateCustomStepKernel::evaluateCondition(int step) { ...@@ -8119,17 +8212,6 @@ bool CudaIntegrateCustomStepKernel::evaluateCondition(int step) {
double CudaIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& context, CustomIntegrator& integrator, bool& forcesAreValid) { double CudaIntegrateCustomStepKernel::computeKineticEnergy(ContextImpl& context, CustomIntegrator& integrator, bool& forcesAreValid) {
prepareForComputation(context, integrator, forcesAreValid); prepareForComputation(context, integrator, forcesAreValid);
if (keNeedsForce && !forcesAreValid) {
// Compute the force. We want to then mark that forces are valid, which means also computing
// potential energy if any steps will expect it to be valid too.
bool willNeedEnergy = false;
for (int i = 0; i < integrator.getNumComputations(); i++)
willNeedEnergy |= needsEnergy[i];
energy = context.calcForcesAndEnergy(true, willNeedEnergy, -1);
energyFloat = (float) energy;
forcesAreValid = true;
}
CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0); CUdeviceptr posCorrection = (cu.getUseMixedPrecision() ? cu.getPosqCorrection().getDevicePointer() : 0);
int randomIndex = 0; int randomIndex = 0;
kineticEnergyArgs[1] = &posCorrection; kineticEnergyArgs[1] = &posCorrection;
......
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