Unverified Commit 86988b90 authored by Peter Eastman's avatar Peter Eastman Committed by GitHub
Browse files

Use LF-Middle for LangevinIntegrator and VariableLangevinIntegrator (#4440)

* Made LangevinIntegrator identical to LangevinMiddleIntegrator

* Removed unused code

* VariableLangevinIntegrator uses LFMiddle
parent e62bdf6a
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -54,7 +54,6 @@
#include "openmm/HarmonicAngleForce.h"
#include "openmm/HarmonicBondForce.h"
#include "openmm/KernelImpl.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/MonteCarloBarostat.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/RBTorsionForce.h"
......@@ -1177,39 +1176,6 @@ public:
virtual void setChainStates(ContextImpl& context, const std::vector<std::vector<double> >& positions, const std::vector<std::vector<double> >& velocities) = 0;
};
/**
* This kernel is invoked by LangevinIntegrator to take one time step.
*/
class IntegrateLangevinStepKernel : public KernelImpl {
public:
static std::string Name() {
return "IntegrateLangevinStep";
}
IntegrateLangevinStepKernel(std::string name, const Platform& platform) : KernelImpl(name, platform) {
}
/**
* Initialize the kernel.
*
* @param system the System this kernel will be applied to
* @param integrator the LangevinIntegrator this kernel will be used for
*/
virtual void initialize(const System& system, const LangevinIntegrator& integrator) = 0;
/**
* Execute the kernel.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
virtual void execute(ContextImpl& context, const LangevinIntegrator& integrator) = 0;
/**
* Compute the kinetic energy.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
virtual double computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator) = 0;
};
/**
* This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2021 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -32,17 +32,19 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "Integrator.h"
#include "openmm/Kernel.h"
#include "LangevinMiddleIntegrator.h"
#include "internal/windowsExport.h"
namespace OpenMM {
/**
* This is an Integrator which simulates a System using Langevin dynamics.
* This is an Integrator which simulates a System using Langevin dynamics. It
* is identical to LangevinMiddleIntegrator. (It simply subclasses it without
* adding or changing anything.) The two different classes exist only for
* historical reasons.
*/
class OPENMM_EXPORT LangevinIntegrator : public Integrator {
class OPENMM_EXPORT LangevinIntegrator : public LangevinMiddleIntegrator {
public:
/**
* Create a LangevinIntegrator.
......@@ -52,94 +54,6 @@ public:
* @param stepSize the step size with which to integrate the system (in picoseconds)
*/
LangevinIntegrator(double temperature, double frictionCoeff, double stepSize);
/**
* Get the temperature of the heat bath (in Kelvin).
*
* @return the temperature of the heat bath, measured in Kelvin
*/
double getTemperature() const {
return temperature;
}
/**
* Set the temperature of the heat bath (in Kelvin).
*
* @param temp the temperature of the heat bath, measured in Kelvin
*/
void setTemperature(double temp);
/**
* Get the friction coefficient which determines how strongly the system is coupled to
* the heat bath (in inverse ps).
*
* @return the friction coefficient, measured in 1/ps
*/
double getFriction() const {
return friction;
}
/**
* Set the friction coefficient which determines how strongly the system is coupled to
* the heat bath (in inverse ps).
*
* @param coeff the friction coefficient, measured in 1/ps
*/
void setFriction(double coeff);
/**
* Get the random number seed. See setRandomNumberSeed() for details.
*/
int getRandomNumberSeed() const {
return randomNumberSeed;
}
/**
* Set the random number seed. The precise meaning of this parameter is undefined, and is left up
* to each Platform to interpret in an appropriate way. It is guaranteed that if two simulations
* are run with different random number seeds, the sequence of random forces will be different. On
* the other hand, no guarantees are made about the behavior of simulations that use the same seed.
* In particular, Platforms are permitted to use non-deterministic algorithms which produce different
* results on successive runs, even if those runs were initialized identically.
*
* If seed is set to 0 (which is the default value assigned), a unique seed is chosen when a Context
* is created from this Force. This is done to ensure that each Context receives unique random seeds
* without you needing to set them explicitly.
*/
void setRandomNumberSeed(int seed) {
randomNumberSeed = seed;
}
/**
* Advance a simulation through time by taking a series of time steps.
*
* @param steps the number of time steps to take
*/
void step(int steps);
protected:
/**
* This will be called by the Context when it is created. It informs the Integrator
* of what context it will be integrating, and gives it a chance to do any necessary initialization.
* It will also get called again if the application calls reinitialize() on the Context.
*/
void initialize(ContextImpl& context);
/**
* This will be called by the Context when it is destroyed to let the Integrator do any necessary
* cleanup. It will also get called again if the application calls reinitialize() on the Context.
*/
void cleanup();
/**
* Get the names of all Kernels used by this Integrator.
*/
std::vector<std::string> getKernelNames();
/**
* Compute the kinetic energy of the system at the current time.
*/
double computeKineticEnergy();
/**
* Get the time interval by which velocities are offset from positions. This is used to
* adjust velocities when setVelocitiesToTemperature() is called on a Context.
*/
double getVelocityTimeOffset() const {
return getStepSize()/2;
}
private:
double temperature, friction;
int randomNumberSeed;
Kernel kernel;
};
} // namespace OpenMM
......
......@@ -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-2021 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -30,65 +30,9 @@
* -------------------------------------------------------------------------- */
#include "openmm/LangevinIntegrator.h"
#include "openmm/Context.h"
#include "openmm/OpenMMException.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/kernels.h"
#include <string>
using namespace OpenMM;
using std::string;
using std::vector;
LangevinIntegrator::LangevinIntegrator(double temperature, double frictionCoeff, double stepSize) {
setTemperature(temperature);
setFriction(frictionCoeff);
setStepSize(stepSize);
setConstraintTolerance(1e-5);
setRandomNumberSeed(0);
}
void LangevinIntegrator::initialize(ContextImpl& contextRef) {
if (owner != NULL && &contextRef.getOwner() != owner)
throw OpenMMException("This Integrator is already bound to a context");
context = &contextRef;
owner = &contextRef.getOwner();
kernel = context->getPlatform().createKernel(IntegrateLangevinStepKernel::Name(), contextRef);
kernel.getAs<IntegrateLangevinStepKernel>().initialize(contextRef.getSystem(), *this);
}
void LangevinIntegrator::setTemperature(double temp) {
if (temp < 0)
throw OpenMMException("Temperature cannot be negative");
temperature = temp;
}
void LangevinIntegrator::setFriction(double coeff) {
if (coeff < 0)
throw OpenMMException("Friction cannot be negative");
friction = coeff;
}
void LangevinIntegrator::cleanup() {
kernel = Kernel();
}
vector<string> LangevinIntegrator::getKernelNames() {
std::vector<std::string> names;
names.push_back(IntegrateLangevinStepKernel::Name());
return names;
}
double LangevinIntegrator::computeKineticEnergy() {
return kernel.getAs<IntegrateLangevinStepKernel>().computeKineticEnergy(*context, *this);
}
void LangevinIntegrator::step(int steps) {
if (context == NULL)
throw OpenMMException("This Integrator is not bound to a context!");
for (int i = 0; i < steps; ++i) {
context->updateContextState();
context->calcForcesAndEnergy(true, false, getIntegrationForceGroups());
kernel.getAs<IntegrateLangevinStepKernel>().execute(*context, *this);
}
LangevinIntegrator::LangevinIntegrator(double temperature, double frictionCoeff, double stepSize) :
LangevinMiddleIntegrator(temperature, frictionCoeff, stepSize) {
}
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -1114,43 +1114,6 @@ private:
ComputeKernel kernel1, kernel2;
};
/**
* This kernel is invoked by LangevinIntegrator to take one time step.
*/
class CommonIntegrateLangevinStepKernel : public IntegrateLangevinStepKernel {
public:
CommonIntegrateLangevinStepKernel(std::string name, const Platform& platform, ComputeContext& cc) : IntegrateLangevinStepKernel(name, platform), cc(cc),
hasInitializedKernels(false) {
}
/**
* Initialize the kernel, setting up the particle masses.
*
* @param system the System this kernel will be applied to
* @param integrator the LangevinIntegrator this kernel will be used for
*/
void initialize(const System& system, const LangevinIntegrator& integrator);
/**
* Execute the kernel.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
void execute(ContextImpl& context, const LangevinIntegrator& integrator);
/**
* Compute the kinetic energy.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
double computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator);
private:
ComputeContext& cc;
double prevTemp, prevFriction, prevStepSize;
bool hasInitializedKernels;
ComputeArray params;
ComputeKernel kernel1, kernel2;
};
/**
* This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/
......@@ -1411,8 +1374,8 @@ private:
ComputeContext& cc;
bool hasInitializedKernels;
int blockSize;
ComputeArray params;
ComputeKernel kernel1, kernel2, selectSizeKernel;
ComputeArray params, oldDelta;
ComputeKernel kernel1, kernel2, kernel3, selectSizeKernel;
double prevTemp, prevFriction, prevErrorTol;
};
......
......@@ -5677,91 +5677,6 @@ double CommonIntegrateVerletStepKernel::computeKineticEnergy(ContextImpl& contex
return cc.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize());
}
void CommonIntegrateLangevinStepKernel::initialize(const System& system, const LangevinIntegrator& integrator) {
cc.initializeContexts();
ContextSelector selector(cc);
cc.getIntegrationUtilities().initRandomNumberGenerator(integrator.getRandomNumberSeed());
ComputeProgram program = cc.compileProgram(CommonKernelSources::langevin);
kernel1 = program->createKernel("integrateLangevinPart1");
kernel2 = program->createKernel("integrateLangevinPart2");
params.initialize(cc, 3, cc.getUseDoublePrecision() || cc.getUseMixedPrecision() ? sizeof(double) : sizeof(float), "langevinParams");
prevStepSize = -1.0;
}
void CommonIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) {
ContextSelector selector(cc);
IntegrationUtilities& integration = cc.getIntegrationUtilities();
int numAtoms = cc.getNumAtoms();
int paddedNumAtoms = cc.getPaddedNumAtoms();
if (!hasInitializedKernels) {
hasInitializedKernels = true;
kernel1->addArg(numAtoms);
kernel1->addArg(paddedNumAtoms);
kernel1->addArg(cc.getVelm());
kernel1->addArg(cc.getLongForceBuffer());
kernel1->addArg(integration.getPosDelta());
kernel1->addArg(params);
kernel1->addArg(integration.getStepSize());
kernel1->addArg(integration.getRandom());
kernel1->addArg();
kernel2->addArg(numAtoms);
kernel2->addArg(cc.getPosq());
kernel2->addArg(integration.getPosDelta());
kernel2->addArg(cc.getVelm());
kernel2->addArg(integration.getStepSize());
if (cc.getUseMixedPrecision())
kernel2->addArg(cc.getPosqCorrection());
}
double temperature = integrator.getTemperature();
double friction = integrator.getFriction();
double stepSize = integrator.getStepSize();
cc.getIntegrationUtilities().setNextStepSize(stepSize);
if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
// Calculate the integration parameters.
double kT = BOLTZ*temperature;
double vscale = exp(-stepSize*friction);
double fscale = (friction == 0 ? stepSize : (1-vscale)/friction);
double noisescale = sqrt(kT*(1-vscale*vscale));
vector<double> p(params.getSize());
p[0] = vscale;
p[1] = fscale;
p[2] = noisescale;
params.upload(p, true);
prevTemp = temperature;
prevFriction = friction;
prevStepSize = stepSize;
}
// Call the first integration kernel.
kernel1->setArg(8, integration.prepareRandomNumbers(cc.getPaddedNumAtoms()));
kernel1->execute(numAtoms);
// Apply constraints.
integration.applyConstraints(integrator.getConstraintTolerance());
// Call the second integration kernel.
kernel2->execute(numAtoms);
integration.computeVirtualSites();
// Update the time and step count.
cc.setTime(cc.getTime()+stepSize);
cc.setStepCount(cc.getStepCount()+1);
cc.reorderAtoms();
// Reduce UI lag.
flushPeriodically(cc);
}
double CommonIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator) {
return cc.getIntegrationUtilities().computeKineticEnergy(0.5*integrator.getStepSize());
}
void CommonIntegrateLangevinMiddleStepKernel::initialize(const System& system, const LangevinMiddleIntegrator& integrator) {
cc.initializeContexts();
ContextSelector selector(cc);
......@@ -6709,11 +6624,19 @@ void CommonIntegrateVariableLangevinStepKernel::initialize(const System& system,
cc.initializeContexts();
ContextSelector selector(cc);
cc.getIntegrationUtilities().initRandomNumberGenerator(integrator.getRandomNumberSeed());
ComputeProgram program = cc.compileProgram(CommonKernelSources::langevin);
kernel1 = program->createKernel("integrateLangevinPart1");
kernel2 = program->createKernel("integrateLangevinPart2");
ComputeProgram program = cc.compileProgram(CommonKernelSources::langevinMiddle);
kernel1 = program->createKernel("integrateLangevinMiddlePart1");
kernel2 = program->createKernel("integrateLangevinMiddlePart2");
kernel3 = program->createKernel("integrateLangevinMiddlePart3");
if (cc.getUseDoublePrecision() || cc.getUseMixedPrecision()) {
params.initialize<double>(cc, 3, "langevinMiddleParams");
oldDelta.initialize<mm_double4>(cc, cc.getPaddedNumAtoms(), "oldDelta");
}
else {
params.initialize<float>(cc, 3, "langevinMiddleParams");
oldDelta.initialize<mm_float4>(cc, cc.getPaddedNumAtoms(), "oldDelta");
}
selectSizeKernel = program->createKernel("selectLangevinStepSize");
params.initialize(cc, 3, cc.getUseDoublePrecision() || cc.getUseMixedPrecision() ? sizeof(double) : sizeof(float), "langevinParams");
blockSize = min(256, system.getNumParticles());
blockSize = max(blockSize, (int) params.getSize());
}
......@@ -6730,18 +6653,23 @@ double CommonIntegrateVariableLangevinStepKernel::execute(ContextImpl& context,
kernel1->addArg(paddedNumAtoms);
kernel1->addArg(cc.getVelm());
kernel1->addArg(cc.getLongForceBuffer());
kernel1->addArg(integration.getPosDelta());
kernel1->addArg(params);
kernel1->addArg(integration.getStepSize());
kernel1->addArg(integration.getRandom());
kernel1->addArg();
kernel2->addArg(numAtoms);
kernel2->addArg(cc.getPosq());
kernel2->addArg(integration.getPosDelta());
kernel2->addArg(cc.getVelm());
kernel2->addArg(integration.getPosDelta());
kernel2->addArg(oldDelta);
kernel2->addArg(params);
kernel2->addArg(integration.getStepSize());
kernel2->addArg(integration.getRandom());
kernel2->addArg(); // Random index will be set just before it is executed.
kernel3->addArg(numAtoms);
kernel3->addArg(cc.getPosq());
kernel3->addArg(cc.getVelm());
kernel3->addArg(integration.getPosDelta());
kernel3->addArg(oldDelta);
kernel3->addArg(integration.getStepSize());
if (cc.getUseMixedPrecision())
kernel2->addArg(cc.getPosqCorrection());
kernel3->addArg(cc.getPosqCorrection());
selectSizeKernel->addArg(numAtoms);
selectSizeKernel->addArg(paddedNumAtoms);
for (int i = 0; i < 4; i++)
......@@ -6772,18 +6700,14 @@ double CommonIntegrateVariableLangevinStepKernel::execute(ContextImpl& context,
}
selectSizeKernel->execute(blockSize, blockSize);
// Call the first integration kernel.
// Perform the integration.
kernel1->setArg(8, integration.prepareRandomNumbers(cc.getPaddedNumAtoms()));
kernel2->setArg(7, integration.prepareRandomNumbers(cc.getPaddedNumAtoms()));
kernel1->execute(numAtoms);
// Apply constraints.
integration.applyConstraints(integrator.getConstraintTolerance());
// Call the second integration kernel.
integration.applyVelocityConstraints(integrator.getConstraintTolerance());
kernel2->execute(numAtoms);
integration.applyConstraints(integrator.getConstraintTolerance());
kernel3->execute(numAtoms);
integration.computeVirtualSites();
// Reduce UI lag.
......
enum {VelScale, ForceScale, NoiseScale, MaxParams};
/**
* Perform the first step of Langevin integration.
*/
KERNEL void integrateLangevinPart1(int numAtoms, int paddedNumAtoms, GLOBAL mixed4* RESTRICT velm, GLOBAL const mm_long* RESTRICT force, GLOBAL mixed4* RESTRICT posDelta,
GLOBAL const mixed* RESTRICT paramBuffer, GLOBAL const mixed2* RESTRICT dt, GLOBAL const float4* RESTRICT random, unsigned int randomIndex) {
mixed vscale = paramBuffer[VelScale];
mixed fscale = paramBuffer[ForceScale]/(mixed) 0x100000000;
mixed noisescale = paramBuffer[NoiseScale];
mixed stepSize = dt[0].y;
int index = GLOBAL_ID;
randomIndex += index;
while (index < numAtoms) {
mixed4 velocity = velm[index];
if (velocity.w != 0) {
mixed sqrtInvMass = SQRT(velocity.w);
velocity.x = vscale*velocity.x + fscale*velocity.w*force[index] + noisescale*sqrtInvMass*random[randomIndex].x;
velocity.y = vscale*velocity.y + fscale*velocity.w*force[index+paddedNumAtoms] + noisescale*sqrtInvMass*random[randomIndex].y;
velocity.z = vscale*velocity.z + fscale*velocity.w*force[index+paddedNumAtoms*2] + noisescale*sqrtInvMass*random[randomIndex].z;
velm[index] = velocity;
posDelta[index] = make_mixed4(stepSize*velocity.x, stepSize*velocity.y, stepSize*velocity.z, 0);
}
randomIndex += GLOBAL_SIZE;
index += GLOBAL_SIZE;
}
}
/**
* Perform the second step of Langevin integration.
*/
KERNEL void integrateLangevinPart2(int numAtoms, GLOBAL real4* RESTRICT posq, GLOBAL const mixed4* RESTRICT posDelta, GLOBAL mixed4* RESTRICT velm, GLOBAL const mixed2* RESTRICT dt
#ifdef USE_MIXED_PRECISION
, GLOBAL real4* RESTRICT posqCorrection
#endif
) {
#ifdef SUPPORTS_DOUBLE_PRECISION
double invStepSize = 1.0/dt[0].y;
#else
float invStepSize = 1.0f/dt[0].y;
float correction = (1.0f-invStepSize*dt[0].y)/dt[0].y;
#endif
int index = GLOBAL_ID;
while (index < numAtoms) {
mixed4 vel = velm[index];
if (vel.w != 0) {
#ifdef USE_MIXED_PRECISION
real4 pos1 = posq[index];
real4 pos2 = posqCorrection[index];
mixed4 pos = make_mixed4(pos1.x+(mixed)pos2.x, pos1.y+(mixed)pos2.y, pos1.z+(mixed)pos2.z, pos1.w);
#else
real4 pos = posq[index];
#endif
mixed4 delta = posDelta[index];
pos.x += delta.x;
pos.y += delta.y;
pos.z += delta.z;
#ifdef SUPPORTS_DOUBLE_PRECISION
vel.x = (mixed) (invStepSize*delta.x);
vel.y = (mixed) (invStepSize*delta.y);
vel.z = (mixed) (invStepSize*delta.z);
#else
vel.x = invStepSize*delta.x + correction*delta.x;
vel.y = invStepSize*delta.y + correction*delta.y;
vel.z = invStepSize*delta.z + correction*delta.z;
#endif
#ifdef USE_MIXED_PRECISION
posq[index] = make_real4((real) pos.x, (real) pos.y, (real) pos.z, (real) pos.w);
posqCorrection[index] = make_real4(pos.x-(real) pos.x, pos.y-(real) pos.y, pos.z-(real) pos.z, 0);
#else
posq[index] = pos;
#endif
velm[index] = vel;
}
index += GLOBAL_SIZE;
}
}
/**
* Select the step size to use for the next step.
*/
KERNEL void selectLangevinStepSize(int numAtoms, int paddedNumAtoms, mixed maxStepSize, mixed errorTol, mixed friction, mixed kT, GLOBAL mixed2* RESTRICT dt,
GLOBAL const mixed4* RESTRICT velm, GLOBAL const mm_long* RESTRICT force, GLOBAL mixed* RESTRICT paramBuffer) {
// Calculate the error.
LOCAL mixed error[256];
LOCAL mixed params[MaxParams];
mixed err = 0;
const mixed scale = RECIP((mixed) 0x100000000);
for (int index = LOCAL_ID; index < numAtoms; index += LOCAL_SIZE) {
mixed3 f = make_mixed3(scale*force[index], scale*force[index+paddedNumAtoms], scale*force[index+paddedNumAtoms*2]);
mixed invMass = velm[index].w;
err += (f.x*f.x + f.y*f.y + f.z*f.z)*invMass*invMass;
}
error[LOCAL_ID] = err;
SYNC_THREADS;
// Sum the errors from all threads.
for (unsigned int offset = 1; offset < LOCAL_SIZE; offset *= 2) {
if (LOCAL_ID+offset < LOCAL_SIZE && (LOCAL_ID&(2*offset-1)) == 0)
error[LOCAL_ID] += error[LOCAL_ID+offset];
SYNC_THREADS;
}
if (GLOBAL_ID == 0) {
// Select the new step size.
mixed totalError = SQRT(error[0]/(numAtoms*3));
mixed newStepSize = SQRT(errorTol/totalError);
mixed oldStepSize = dt[0].y;
if (oldStepSize > 0.0f)
newStepSize = min(newStepSize, oldStepSize*2.0f); // For safety, limit how quickly dt can increase.
if (newStepSize > oldStepSize && newStepSize < 1.1f*oldStepSize)
newStepSize = oldStepSize; // Keeping dt constant between steps improves the behavior of the integrator.
if (newStepSize > maxStepSize)
newStepSize = maxStepSize;
dt[0].y = newStepSize;
// Recalculate the integration parameters.
mixed vscale = exp(-newStepSize*friction);
mixed fscale = (friction == 0 ? newStepSize : (1-vscale)/friction);
mixed noisescale = sqrt(kT*(1-vscale*vscale));
params[VelScale] = vscale;
params[ForceScale] = fscale;
params[NoiseScale] = noisescale;
}
SYNC_THREADS;
if (LOCAL_ID < MaxParams)
paramBuffer[LOCAL_ID] = params[LOCAL_ID];
}
enum {VelScale, NoiseScale};
enum {VelScale, NoiseScale, MaxParams};
/**
* Perform the first part of integration: velocity step.
......@@ -88,3 +88,56 @@ KERNEL void integrateLangevinMiddlePart3(int numAtoms, GLOBAL real4* RESTRICT po
}
}
}
/**
* Select the step size to use for the next step.
*/
KERNEL void selectLangevinStepSize(int numAtoms, int paddedNumAtoms, mixed maxStepSize, mixed errorTol, mixed friction, mixed kT, GLOBAL mixed2* RESTRICT dt,
GLOBAL const mixed4* RESTRICT velm, GLOBAL const mm_long* RESTRICT force, GLOBAL mixed* RESTRICT paramBuffer) {
// Calculate the error.
LOCAL mixed error[256];
LOCAL mixed params[MaxParams];
mixed err = 0;
const mixed scale = RECIP((mixed) 0x100000000);
for (int index = LOCAL_ID; index < numAtoms; index += LOCAL_SIZE) {
mixed3 f = make_mixed3(scale*force[index], scale*force[index+paddedNumAtoms], scale*force[index+paddedNumAtoms*2]);
mixed invMass = velm[index].w;
err += (f.x*f.x + f.y*f.y + f.z*f.z)*invMass*invMass;
}
error[LOCAL_ID] = err;
SYNC_THREADS;
// Sum the errors from all threads.
for (unsigned int offset = 1; offset < LOCAL_SIZE; offset *= 2) {
if (LOCAL_ID+offset < LOCAL_SIZE && (LOCAL_ID&(2*offset-1)) == 0)
error[LOCAL_ID] += error[LOCAL_ID+offset];
SYNC_THREADS;
}
if (GLOBAL_ID == 0) {
// Select the new step size.
mixed totalError = SQRT(error[0]/(numAtoms*3));
mixed newStepSize = SQRT(errorTol/totalError);
mixed oldStepSize = dt[0].y;
if (oldStepSize > 0.0f)
newStepSize = min(newStepSize, oldStepSize*2.0f); // For safety, limit how quickly dt can increase.
if (newStepSize > oldStepSize && newStepSize < 1.1f*oldStepSize)
newStepSize = oldStepSize; // Keeping dt constant between steps improves the behavior of the integrator.
if (newStepSize > maxStepSize)
newStepSize = maxStepSize;
dt[0].y = newStepSize;
// Recalculate the integration parameters.
mixed vscale = exp(-newStepSize*friction);
mixed noisescale = sqrt(kT*(1-vscale*vscale));
params[VelScale] = vscale;
params[NoiseScale] = noisescale;
}
SYNC_THREADS;
if (LOCAL_ID < MaxParams)
paramBuffer[LOCAL_ID] = params[LOCAL_ID];
}
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013-2022 Stanford University and the Authors. *
* Portions copyright (c) 2013-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -38,7 +38,6 @@
#include "CpuCustomNonbondedForce.h"
#include "CpuGayBerneForce.h"
#include "CpuGBSAOBCForce.h"
#include "CpuLangevinDynamics.h"
#include "CpuLangevinMiddleDynamics.h"
#include "CpuNeighborList.h"
#include "CpuNonbondedForce.h"
......@@ -507,43 +506,6 @@ private:
CpuGayBerneForce* ixn;
};
/**
* This kernel is invoked by LangevinIntegrator to take one time step.
*/
class CpuIntegrateLangevinStepKernel : public IntegrateLangevinStepKernel {
public:
CpuIntegrateLangevinStepKernel(std::string name, const Platform& platform, CpuPlatform::PlatformData& data) : IntegrateLangevinStepKernel(name, platform),
data(data), dynamics(NULL) {
}
~CpuIntegrateLangevinStepKernel();
/**
* Initialize the kernel, setting up the particle masses.
*
* @param system the System this kernel will be applied to
* @param integrator the LangevinIntegrator this kernel will be used for
*/
void initialize(const System& system, const LangevinIntegrator& integrator);
/**
* Execute the kernel.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
void execute(ContextImpl& context, const LangevinIntegrator& integrator);
/**
* Compute the kinetic energy.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
double computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator);
private:
CpuPlatform::PlatformData& data;
CpuLangevinDynamics* dynamics;
std::vector<double> masses;
double prevTemp, prevFriction, prevStepSize;
};
/**
* This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/
......
/* Portions copyright (c) 2013-2017 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_LANGEVIN_DYNAMICS_H__
#define __CPU_LANGEVIN_DYNAMICS_H__
#include "ReferenceStochasticDynamics.h"
#include "CpuRandom.h"
#include "openmm/internal/ThreadPool.h"
#include "sfmt/SFMT.h"
namespace OpenMM {
class CpuLangevinDynamics : public ReferenceStochasticDynamics {
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
*/
CpuLangevinDynamics(int numberOfAtoms, double deltaT, double friction, double temperature, OpenMM::ThreadPool& threads, OpenMM::CpuRandom& random);
/**
* Destructor.
*/
~CpuLangevinDynamics();
/**
* 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 forces forces
* @param inverseMasses inverse atom masses
* @param xPrime xPrime
*/
void updatePart2(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);
/**
* Third update
*
* @param numberOfAtoms number of atoms
* @param atomCoordinates atom coordinates
* @param velocities velocities
* @param inverseMasses inverse atom masses
*/
void updatePart3(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);
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_LANGEVIN_DYNAMICS_H__
......@@ -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) 2013-2019 Stanford University and the Authors. *
* Portions copyright (c) 2013-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -59,8 +59,6 @@ KernelImpl* CpuKernelFactory::createKernelImpl(std::string name, const Platform&
return new CpuCalcCustomGBForceKernel(name, platform, data);
if (name == CalcGayBerneForceKernel::Name())
return new CpuCalcGayBerneForceKernel(name, platform, data);
if (name == IntegrateLangevinStepKernel::Name())
return new CpuIntegrateLangevinStepKernel(name, platform, data);
if (name == IntegrateLangevinMiddleStepKernel::Name())
return new CpuIntegrateLangevinMiddleStepKernel(name, platform, data);
throw OpenMMException((std::string("Tried to create kernel with illegal kernel name '") + name + "'").c_str());
......
......@@ -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) 2013-2023 Stanford University and the Authors. *
* Portions copyright (c) 2013-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -1439,48 +1439,6 @@ void CpuCalcGayBerneForceKernel::copyParametersToContext(ContextImpl& context, c
ixn = new CpuGayBerneForce(force);
}
CpuIntegrateLangevinStepKernel::~CpuIntegrateLangevinStepKernel() {
if (dynamics)
delete dynamics;
}
void CpuIntegrateLangevinStepKernel::initialize(const System& system, const LangevinIntegrator& integrator) {
int numParticles = system.getNumParticles();
masses.resize(numParticles);
for (int i = 0; i < numParticles; ++i)
masses[i] = static_cast<double>(system.getParticleMass(i));
data.random.initialize(integrator.getRandomNumberSeed(), data.threads.getNumThreads());
}
void CpuIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) {
double temperature = integrator.getTemperature();
double friction = integrator.getFriction();
double stepSize = integrator.getStepSize();
vector<Vec3>& posData = extractPositions(context);
vector<Vec3>& velData = extractVelocities(context);
vector<Vec3>& forceData = extractForces(context);
if (dynamics == 0 || temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
// Recreate the computation objects with the new parameters.
if (dynamics)
delete dynamics;
dynamics = new CpuLangevinDynamics(context.getSystem().getNumParticles(), stepSize, friction, temperature, data.threads, data.random);
dynamics->setReferenceConstraintAlgorithm(&extractConstraints(context));
dynamics->setVirtualSites(extractVirtualSites(context));
prevTemp = temperature;
prevFriction = friction;
prevStepSize = stepSize;
}
dynamics->update(context.getSystem(), posData, velData, forceData, masses, integrator.getConstraintTolerance());
ReferencePlatform::PlatformData* refData = reinterpret_cast<ReferencePlatform::PlatformData*>(context.getPlatformData());
refData->time += stepSize;
refData->stepCount++;
}
double CpuIntegrateLangevinStepKernel::computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator) {
return computeShiftedKineticEnergy(context, masses, 0.5*integrator.getStepSize());
}
CpuIntegrateLangevinMiddleStepKernel::~CpuIntegrateLangevinMiddleStepKernel() {
if (dynamics)
delete dynamics;
......
/* Portions copyright (c) 2006-2017 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 "CpuLangevinDynamics.h"
using namespace OpenMM;
using namespace std;
CpuLangevinDynamics::CpuLangevinDynamics(int numberOfAtoms, double deltaT, double friction, double temperature, ThreadPool& threads, CpuRandom& random) :
ReferenceStochasticDynamics(numberOfAtoms, deltaT, friction, temperature), threads(threads), random(random) {
}
CpuLangevinDynamics::~CpuLangevinDynamics() {
}
void CpuLangevinDynamics::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 CpuLangevinDynamics::updatePart2(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) { threadUpdate2(threadIndex); });
threads.waitForThreads();
}
void CpuLangevinDynamics::updatePart3(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();
}
void CpuLangevinDynamics::threadUpdate1(int threadIndex) {
double dt = getDeltaT();
double friction = getFriction();
const double vscale = exp(-dt*friction);
const double fscale = (friction == 0 ? dt : (1-vscale)/friction);
const double kT = BOLTZ*getTemperature();
const double noisescale = sqrt(kT*(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) {
double sqrtInvMass = sqrt(inverseMasses[i]);
Vec3 noise(random.getGaussianRandom(threadIndex), random.getGaussianRandom(threadIndex), random.getGaussianRandom(threadIndex));
velocities[i] = velocities[i]*vscale + forces[i]*(fscale*inverseMasses[i]) + noise*(noisescale*sqrtInvMass);
}
}
}
void CpuLangevinDynamics::threadUpdate2(int threadIndex) {
const double dt = 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) {
xPrime[i] = atomCoordinates[i]+velocities[i]*dt;
}
}
}
void CpuLangevinDynamics::threadUpdate3(int threadIndex) {
const double invStepSize = 1.0/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]-atomCoordinates[i])*invStepSize;
atomCoordinates[i] = xPrime[i];
}
}
......@@ -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) 2013-2022 Stanford University and the Authors. *
* Portions copyright (c) 2013-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -73,7 +73,6 @@ CpuPlatform::CpuPlatform() {
registerKernelFactory(CalcGBSAOBCForceKernel::Name(), factory);
registerKernelFactory(CalcCustomGBForceKernel::Name(), factory);
registerKernelFactory(CalcGayBerneForceKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinMiddleStepKernel::Name(), factory);
platformProperties.push_back(CpuThreads());
platformProperties.push_back(CpuDeterministicForces());
......
......@@ -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-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -123,8 +123,6 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
return new CommonCalcGayBerneForceKernel(name, platform, cu);
if (name == IntegrateVerletStepKernel::Name())
return new CommonIntegrateVerletStepKernel(name, platform, cu);
if (name == IntegrateLangevinStepKernel::Name())
return new CommonIntegrateLangevinStepKernel(name, platform, cu);
if (name == IntegrateLangevinMiddleStepKernel::Name())
return new CommonIntegrateLangevinMiddleStepKernel(name, platform, cu);
if (name == IntegrateBrownianStepKernel::Name())
......
......@@ -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-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -99,7 +99,6 @@ CudaPlatform::CudaPlatform() {
registerKernelFactory(CalcGayBerneForceKernel::Name(), factory);
registerKernelFactory(IntegrateVerletStepKernel::Name(), factory);
registerKernelFactory(IntegrateNoseHooverStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinMiddleStepKernel::Name(), factory);
registerKernelFactory(IntegrateBrownianStepKernel::Name(), factory);
registerKernelFactory(IntegrateVariableVerletStepKernel::Name(), factory);
......
......@@ -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-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -121,8 +121,6 @@ KernelImpl* OpenCLKernelFactory::createKernelImpl(std::string name, const Platfo
return new CommonCalcGayBerneForceKernel(name, platform, cl);
if (name == IntegrateVerletStepKernel::Name())
return new CommonIntegrateVerletStepKernel(name, platform, cl);
if (name == IntegrateLangevinStepKernel::Name())
return new CommonIntegrateLangevinStepKernel(name, platform, cl);
if (name == IntegrateLangevinMiddleStepKernel::Name())
return new CommonIntegrateLangevinMiddleStepKernel(name, platform, cl);
if (name == IntegrateBrownianStepKernel::Name())
......
......@@ -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-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -90,7 +90,6 @@ OpenCLPlatform::OpenCLPlatform() {
registerKernelFactory(CalcGayBerneForceKernel::Name(), factory);
registerKernelFactory(IntegrateVerletStepKernel::Name(), factory);
registerKernelFactory(IntegrateNoseHooverStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinMiddleStepKernel::Name(), factory);
registerKernelFactory(IntegrateBrownianStepKernel::Name(), factory);
registerKernelFactory(IntegrateVariableVerletStepKernel::Name(), factory);
......
......@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2023 Stanford University and the Authors. *
* Portions copyright (c) 2008-2024 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
......@@ -59,7 +59,6 @@ class ReferenceCustomHbondIxn;
class ReferenceCustomManyParticleIxn;
class ReferenceGayBerneForce;
class ReferenceBrownianDynamics;
class ReferenceStochasticDynamics;
class ReferenceConstraintAlgorithm;
class ReferenceNoseHooverChain;
class ReferenceMonteCarloBarostat;
......@@ -1269,43 +1268,6 @@ private:
double prevStepSize;
};
/**
* This kernel is invoked by LangevinIntegrator to take one time step.
*/
class ReferenceIntegrateLangevinStepKernel : public IntegrateLangevinStepKernel {
public:
ReferenceIntegrateLangevinStepKernel(std::string name, const Platform& platform, ReferencePlatform::PlatformData& data) : IntegrateLangevinStepKernel(name, platform),
data(data), dynamics(0) {
}
~ReferenceIntegrateLangevinStepKernel();
/**
* Initialize the kernel, setting up the particle masses.
*
* @param system the System this kernel will be applied to
* @param integrator the LangevinIntegrator this kernel will be used for
*/
void initialize(const System& system, const LangevinIntegrator& integrator);
/**
* Execute the kernel.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
void execute(ContextImpl& context, const LangevinIntegrator& integrator);
/**
* Compute the kinetic energy.
*
* @param context the context in which to execute this kernel
* @param integrator the LangevinIntegrator this kernel is being used for
*/
double computeKineticEnergy(ContextImpl& context, const LangevinIntegrator& integrator);
private:
ReferencePlatform::PlatformData& data;
ReferenceStochasticDynamics* dynamics;
std::vector<double> masses;
double prevTemp, prevFriction, prevStepSize;
};
/**
* This kernel is invoked by LangevinMiddleIntegrator to take one time step.
*/
......
......@@ -87,9 +87,7 @@ class OPENMM_EXPORT ReferenceLangevinMiddleDynamics : public ReferenceDynamics {
std::vector<OpenMM::Vec3>& velocities, std::vector<double>& masses, double tolerance);
/**---------------------------------------------------------------------------------------
First update; based on code in update.c do_update_sd() Gromacs 3.1.4
@param numberOfAtoms number of atoms
@param velocities velocities
@param forces forces
......
/* Portions copyright (c) 2006-2016 Stanford University and Simbios.
* Contributors: Pande Group
*
* 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 __ReferenceStochasticDynamics_H__
#define __ReferenceStochasticDynamics_H__
#include "ReferenceDynamics.h"
#include "openmm/internal/windowsExport.h"
namespace OpenMM {
class OPENMM_EXPORT ReferenceStochasticDynamics : public ReferenceDynamics {
protected:
std::vector<OpenMM::Vec3> xPrime;
std::vector<double> inverseMasses;
double friction;
public:
/**---------------------------------------------------------------------------------------
Constructor
@param numberOfAtoms number of atoms
@param deltaT delta t for dynamics
@param friction friction coefficient
@param temperature temperature
--------------------------------------------------------------------------------------- */
ReferenceStochasticDynamics(int numberOfAtoms, double deltaT, double friction, double temperature);
/**---------------------------------------------------------------------------------------
Destructor
--------------------------------------------------------------------------------------- */
~ReferenceStochasticDynamics();
/**---------------------------------------------------------------------------------------
Get friction coefficient
--------------------------------------------------------------------------------------- */
double getFriction() const;
/**---------------------------------------------------------------------------------------
Update
@param system the System to be integrated
@param atomCoordinates atom coordinates
@param velocities velocities
@param forces forces
@param masses atom masses
@param tolerance the constraint tolerance
--------------------------------------------------------------------------------------- */
void update(const OpenMM::System& system, std::vector<OpenMM::Vec3>& atomCoordinates,
std::vector<OpenMM::Vec3>& velocities, std::vector<OpenMM::Vec3>& forces, std::vector<double>& masses, double tolerance);
/**---------------------------------------------------------------------------------------
First update; based on code in update.c do_update_sd() Gromacs 3.1.4
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param velocities velocities
@param forces forces
@param inverseMasses inverse atom masses
@param xPrime xPrime
--------------------------------------------------------------------------------------- */
virtual 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
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param velocities velocities
@param forces forces
@param inverseMasses inverse atom masses
--------------------------------------------------------------------------------------- */
virtual void updatePart2(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);
/**---------------------------------------------------------------------------------------
Third update
@param numberOfAtoms number of atoms
@param atomCoordinates atom coordinates
@param velocities velocities
@param inverseMasses inverse atom masses
--------------------------------------------------------------------------------------- */
virtual void updatePart3(int numberOfAtoms, std::vector<OpenMM::Vec3>& atomCoordinates, std::vector<OpenMM::Vec3>& velocities,
std::vector<double>& inverseMasses, std::vector<OpenMM::Vec3>& xPrime);
};
} // namespace OpenMM
#endif // __ReferenceStochasticDynamics_H__
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