"platforms/vscode:/vscode.git/clone" did not exist on "a5a368d091ef6814300658fea3dcf86ae2b62ba9"
Commit fc973cdc authored by Peter Eastman's avatar Peter Eastman
Browse files

Created Cuda implementation of VerletIntegrator

parent 39557436
...@@ -49,8 +49,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform ...@@ -49,8 +49,8 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
return new CudaCalcNonbondedForceKernel(name, platform, data, context.getSystem()); return new CudaCalcNonbondedForceKernel(name, platform, data, context.getSystem());
if (name == CalcGBSAOBCForceFieldKernel::Name()) if (name == CalcGBSAOBCForceFieldKernel::Name())
return new CudaCalcGBSAOBCForceFieldKernel(name, platform, data); return new CudaCalcGBSAOBCForceFieldKernel(name, platform, data);
// if (name == IntegrateVerletStepKernel::Name()) if (name == IntegrateVerletStepKernel::Name())
// return new CudaIntegrateVerletStepKernel(name, platform); return new CudaIntegrateVerletStepKernel(name, platform, data);
if (name == IntegrateLangevinStepKernel::Name()) if (name == IntegrateLangevinStepKernel::Name())
return new CudaIntegrateLangevinStepKernel(name, platform, data); return new CudaIntegrateLangevinStepKernel(name, platform, data);
if (name == IntegrateBrownianStepKernel::Name()) if (name == IntegrateBrownianStepKernel::Name())
......
...@@ -311,22 +311,7 @@ void CudaCalcGBSAOBCForceFieldKernel::initialize(const System& system, const GBS ...@@ -311,22 +311,7 @@ void CudaCalcGBSAOBCForceFieldKernel::initialize(const System& system, const GBS
void CudaCalcGBSAOBCForceFieldKernel::executeForces(OpenMMContextImpl& context) { void CudaCalcGBSAOBCForceFieldKernel::executeForces(OpenMMContextImpl& context) {
} }
double CudaCalcGBSAOBCForceFieldKernel::executeEnergy(OpenMMContextImpl& context) { static void initializeIntegration(const System& system, CudaPlatform::PlatformData& data) {
}
//CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
//}
//
//void CudaIntegrateVerletStepKernel::initialize(const System& system, const VerletIntegrator& integrator) {
//}
//
//void CudaIntegrateVerletStepKernel::execute(OpenMMContextImpl& context, const VerletIntegrator& integrator) {
//}
CudaIntegrateLangevinStepKernel::~CudaIntegrateLangevinStepKernel() {
}
void CudaIntegrateLangevinStepKernel::initialize(const System& system, const LangevinIntegrator& integrator) {
// Set masses. // Set masses.
...@@ -384,6 +369,45 @@ void CudaIntegrateLangevinStepKernel::initialize(const System& system, const Lan ...@@ -384,6 +369,45 @@ void CudaIntegrateLangevinStepKernel::initialize(const System& system, const Lan
kClearBornForces(gpu); kClearBornForces(gpu);
kClearForces(gpu); kClearForces(gpu);
cudaThreadSynchronize(); cudaThreadSynchronize();
}
double CudaCalcGBSAOBCForceFieldKernel::executeEnergy(OpenMMContextImpl& context) {
}
CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
}
void CudaIntegrateVerletStepKernel::initialize(const System& system, const VerletIntegrator& integrator) {
initializeIntegration(system, data);
prevStepSize = -1.0;
}
void CudaIntegrateVerletStepKernel::execute(OpenMMContextImpl& context, const VerletIntegrator& integrator) {
_gpuContext* gpu = data.gpu;
double stepSize = integrator.getStepSize();
if (stepSize != prevStepSize) {
// Initialize the GPU parameters.
gpuSetVerletIntegrationParameters(gpu, stepSize);
gpuSetConstants(gpu);
kGenerateRandoms(gpu);
prevStepSize = stepSize;
}
kVerletUpdatePart1(gpu);
kApplyFirstShake(gpu);
if (data.removeCM) {
int step = context.getTime()/stepSize;
if (step%data.cmMotionFrequency == 0)
gpu->bCalculateCM = true;
}
kVerletUpdatePart2(gpu);
}
CudaIntegrateLangevinStepKernel::~CudaIntegrateLangevinStepKernel() {
}
void CudaIntegrateLangevinStepKernel::initialize(const System& system, const LangevinIntegrator& integrator) {
initializeIntegration(system, data);
prevStepSize = -1.0; prevStepSize = -1.0;
} }
...@@ -418,63 +442,7 @@ CudaIntegrateBrownianStepKernel::~CudaIntegrateBrownianStepKernel() { ...@@ -418,63 +442,7 @@ CudaIntegrateBrownianStepKernel::~CudaIntegrateBrownianStepKernel() {
} }
void CudaIntegrateBrownianStepKernel::initialize(const System& system, const BrownianIntegrator& integrator) { void CudaIntegrateBrownianStepKernel::initialize(const System& system, const BrownianIntegrator& integrator) {
initializeIntegration(system, data);
// Set masses.
_gpuContext* gpu = data.gpu;
int numParticles = system.getNumParticles();
vector<float> mass(numParticles);
for (int i = 0; i < numParticles; i++)
mass[i] = (float) system.getParticleMass(i);
gpuSetMass(gpu, mass);
// Set constraints.
int numConstraints = system.getNumConstraints();
vector<int> particle1(numConstraints);
vector<int> particle2(numConstraints);
vector<float> distance(numConstraints);
vector<float> invMass1(numConstraints);
vector<float> invMass2(numConstraints);
for (int i = 0; i < numConstraints; i++) {
int particle1Index, particle2Index;
double constraintDistance;
system.getConstraintParameters(i, particle1Index, particle2Index, constraintDistance);
particle1[i] = particle1Index;
particle2[i] = particle2Index;
distance[i] = (float) constraintDistance;
invMass1[i] = 1.0f/mass[particle1Index];
invMass2[i] = 1.0f/mass[particle2Index];
}
gpuSetShakeParameters(gpu, particle1, particle2, distance, invMass1, invMass2);
// Initialize any terms that haven't already been handled by a Force.
if (!data.hasBonds)
gpuSetBondParameters(gpu, vector<int>(), vector<int>(), vector<float>(), vector<float>());
if (!data.hasAngles)
gpuSetBondAngleParameters(gpu, vector<int>(), vector<int>(), vector<int>(), vector<float>(), vector<float>());
if (!data.hasPeriodicTorsions)
gpuSetDihedralParameters(gpu, vector<int>(), vector<int>(), vector<int>(), vector<int>(), vector<float>(), vector<float>(), vector<int>());
if (!data.hasRB)
gpuSetRbDihedralParameters(gpu, vector<int>(), vector<int>(), vector<int>(), vector<int>(), vector<float>(), vector<float>(),
vector<float>(), vector<float>(), vector<float>(), vector<float>());
if (!data.hasNonbonded) {
gpuSetCoulombParameters(gpu, 138.935485f, vector<int>(), vector<float>(), vector<float>(), vector<float>(), vector<char>(), vector<vector<int> >());
gpuSetLJ14Parameters(gpu, 138.935485f, 1.0f, vector<int>(), vector<int>(), vector<float>(), vector<float>(), vector<float>(), vector<float>());
}
// Finish initialization.
gpuBuildThreadBlockWorkList(gpu);
gpuBuildExclusionList(gpu);
gpuBuildOutputBuffers(gpu);
gpuSetConstants(gpu);
kCalculateObcGbsaBornSum(gpu);
kReduceObcGbsaBornSum(gpu);
kClearBornForces(gpu);
kClearForces(gpu);
cudaThreadSynchronize();
prevStepSize = -1.0; prevStepSize = -1.0;
} }
......
...@@ -250,39 +250,33 @@ public: ...@@ -250,39 +250,33 @@ public:
private: private:
CudaPlatform::PlatformData& data; CudaPlatform::PlatformData& data;
}; };
//
///** /**
// * This kernel is invoked by VerletIntegrator to take one time step. * This kernel is invoked by VerletIntegrator to take one time step.
// */ */
//class CudaIntegrateVerletStepKernel : public IntegrateVerletStepKernel { class CudaIntegrateVerletStepKernel : public IntegrateVerletStepKernel {
//public: public:
// CudaIntegrateVerletStepKernel(std::string name, const Platform& platform) : IntegrateVerletStepKernel(name, platform), CudaIntegrateVerletStepKernel(std::string name, const Platform& platform, CudaPlatform::PlatformData& data) : IntegrateVerletStepKernel(name, platform), data(data) {
// dynamics(0), shake(0), masses(0), shakeParameters(0), constraintIndices(0) { }
// } ~CudaIntegrateVerletStepKernel();
// ~CudaIntegrateVerletStepKernel(); /**
// /** * Initialize the kernel.
// * Initialize the kernel. *
// * * @param system the System this kernel will be applied to
// * @param system the System this kernel will be applied to * @param integrator the VerletIntegrator this kernel will be used for
// * @param integrator the VerletIntegrator this kernel will be used for */
// */ void initialize(const System& system, const VerletIntegrator& integrator);
// void initialize(const System& system, const VerletIntegrator& integrator); /**
// /** * Execute the kernel.
// * Execute the kernel. *
// * * @param context the context in which to execute this kernel
// * @param context the context in which to execute this kernel * @param integrator the VerletIntegrator this kernel is being used for
// * @param integrator the VerletIntegrator this kernel is being used for */
// */ void execute(OpenMMContextImpl& context, const VerletIntegrator& integrator);
// void execute(OpenMMContextImpl& context, const VerletIntegrator& integrator); private:
//private: CudaPlatform::PlatformData& data;
// CudaVerletDynamics* dynamics; double prevStepSize;
// CudaShakeAlgorithm* shake; };
// RealOpenMM* masses;
// RealOpenMM** shakeParameters;
// int** constraintIndices;
// int numConstraints;
// double prevStepSize;
//};
/** /**
* This kernel is invoked by LangevinIntegrator to take one time step. * This kernel is invoked by LangevinIntegrator to take one time step.
......
...@@ -46,7 +46,7 @@ CudaPlatform::CudaPlatform() { ...@@ -46,7 +46,7 @@ CudaPlatform::CudaPlatform() {
registerKernelFactory(CalcRBTorsionForceKernel::Name(), factory); registerKernelFactory(CalcRBTorsionForceKernel::Name(), factory);
registerKernelFactory(CalcNonbondedForceKernel::Name(), factory); registerKernelFactory(CalcNonbondedForceKernel::Name(), factory);
registerKernelFactory(CalcGBSAOBCForceFieldKernel::Name(), factory); registerKernelFactory(CalcGBSAOBCForceFieldKernel::Name(), factory);
// registerKernelFactory(IntegrateVerletStepKernel::Name(), factory); registerKernelFactory(IntegrateVerletStepKernel::Name(), factory);
registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory); registerKernelFactory(IntegrateLangevinStepKernel::Name(), factory);
registerKernelFactory(IntegrateBrownianStepKernel::Name(), factory); registerKernelFactory(IntegrateBrownianStepKernel::Name(), factory);
// registerKernelFactory(ApplyAndersenThermostatKernel::Name(), factory); // registerKernelFactory(ApplyAndersenThermostatKernel::Name(), factory);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "NonbondedForce.h" #include "NonbondedForce.h"
#include "System.h" #include "System.h"
#include "LangevinIntegrator.h" #include "LangevinIntegrator.h"
#include "VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h" #include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h" #include "../src/sfmt/SFMT.h"
#include <iostream> #include <iostream>
...@@ -59,11 +60,10 @@ Vec3 calcCM(const vector<Vec3>& values, System& system) { ...@@ -59,11 +60,10 @@ Vec3 calcCM(const vector<Vec3>& values, System& system) {
return cm; return cm;
} }
void testMotionRemoval() { void testMotionRemoval(Integrator& integrator) {
const int numParticles = 8; const int numParticles = 8;
CudaPlatform platform; CudaPlatform platform;
System system(numParticles, 0); System system(numParticles, 0);
LangevinIntegrator integrator(0.0, 1e-5, 0.01);
HarmonicBondForce* bonds = new HarmonicBondForce(1); HarmonicBondForce* bonds = new HarmonicBondForce(1);
bonds->setBondParameters(0, 2, 3, 2.0, 0.5); bonds->setBondParameters(0, 2, 3, 2.0, 0.5);
system.addForce(bonds); system.addForce(bonds);
...@@ -103,7 +103,10 @@ void testMotionRemoval() { ...@@ -103,7 +103,10 @@ void testMotionRemoval() {
int main() { int main() {
try { try {
testMotionRemoval(); LangevinIntegrator langevin(0.0, 1e-5, 0.01);
testMotionRemoval(langevin);
VerletIntegrator verlet(0.01);
testMotionRemoval(verlet);
} }
catch(const exception& e) { catch(const exception& e) {
cout << "exception: " << e.what() << endl; cout << "exception: " << e.what() << endl;
......
/* -------------------------------------------------------------------------- *
* 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) 2008 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. *
* -------------------------------------------------------------------------- */
/**
* This tests the Cuda implementation of VerletIntegrator.
*/
#include "../../../tests/AssertionUtilities.h"
#include "OpenMMContext.h"
#include "CudaPlatform.h"
#include "HarmonicBondForce.h"
#include "NonbondedForce.h"
#include "System.h"
#include "VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testSingleBond() {
CudaPlatform platform;
System system(2, 0);
system.setParticleMass(0, 2.0);
system.setParticleMass(1, 2.0);
VerletIntegrator integrator(0.01);
HarmonicBondForce* forceField = new HarmonicBondForce(1);
forceField->setBondParameters(0, 0, 1, 1.5, 1);
system.addForce(forceField);
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(2);
positions[0] = Vec3(-1, 0, 0);
positions[1] = Vec3(1, 0, 0);
context.setPositions(positions);
// This is simply a harmonic oscillator, so compare it to the analytical solution.
const double freq = 1.0;;
State state = context.getState(State::Energy);
const double initialEnergy = state.getKineticEnergy()+state.getPotentialEnergy();
for (int i = 0; i < 1000; ++i) {
state = context.getState(State::Positions | State::Velocities | State::Energy);
double time = state.getTime();
double expectedDist = 1.5+0.5*std::cos(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedDist, 0, 0), state.getPositions()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedDist, 0, 0), state.getPositions()[1], 0.02);
double expectedSpeed = -0.5*freq*std::sin(freq*time);
ASSERT_EQUAL_VEC(Vec3(-0.5*expectedSpeed, 0, 0), state.getVelocities()[0], 0.02);
ASSERT_EQUAL_VEC(Vec3(0.5*expectedSpeed, 0, 0), state.getVelocities()[1], 0.02);
double energy = state.getKineticEnergy()+state.getPotentialEnergy();
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.01);
integrator.step(1);
}
}
void testConstraints() {
const int numParticles = 8;
const int numConstraints = numParticles/2;
const double temp = 100.0;
CudaPlatform platform;
System system(numParticles, numConstraints);
VerletIntegrator integrator(0.001);
NonbondedForce* forceField = new NonbondedForce(numParticles, 0);
for (int i = 0; i < numParticles; ++i) {
system.setParticleMass(i, 10.0);
forceField->setParticleParameters(i, (i%2 == 0 ? 0.2 : -0.2), 0.5, 5.0);
}
for (int i = 0; i < numConstraints; ++i)
system.setConstraintParameters(i, 2*i, 2*i+1, 1.0);
system.addForce(forceField);
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(numParticles);
vector<Vec3> velocities(numParticles);
init_gen_rand(0);
for (int i = 0; i < numParticles; ++i) {
positions[i] = Vec3(i/2, (i+1)/2, 0);
velocities[i] = Vec3(genrand_real2()-0.5, genrand_real2()-0.5, genrand_real2()-0.5);
}
context.setPositions(positions);
context.setVelocities(velocities);
// Simulate it and see whether the constraints remain satisfied.
double initialEnergy = 0.0;
for (int i = 0; i < 1000; ++i) {
State state = context.getState(State::Positions | State::Energy);
for (int j = 0; j < numConstraints; ++j) {
int particle1, particle2;
double distance;
system.getConstraintParameters(j, particle1, particle2, distance);
Vec3 p1 = state.getPositions()[particle1];
Vec3 p2 = state.getPositions()[particle2];
double dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2]));
ASSERT_EQUAL_TOL(distance, dist, 2e-4);
}
double energy = state.getKineticEnergy()+state.getPotentialEnergy();
if (i == 1)
initialEnergy = energy;
else if (i > 1)
ASSERT_EQUAL_TOL(initialEnergy, energy, 0.02);
integrator.step(1);
}
}
int main() {
try {
testSingleBond();
testConstraints();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
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