Commit 099b8e55 authored by Peter Eastman's avatar Peter Eastman
Browse files

Finished incorporating Cuda code into OpenMM

parent 5c4a033f
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include "Platform.h" #include "Platform.h"
#include "CudaStreamFactory.h" #include "CudaStreamFactory.h"
class _gpuContext;
namespace OpenMM { namespace OpenMM {
/** /**
...@@ -43,6 +45,7 @@ namespace OpenMM { ...@@ -43,6 +45,7 @@ namespace OpenMM {
class OPENMM_EXPORT CudaPlatform : public Platform { class OPENMM_EXPORT CudaPlatform : public Platform {
public: public:
class PlatformData;
CudaPlatform(); CudaPlatform();
std::string getName() const { std::string getName() const {
return "Cuda"; return "Cuda";
...@@ -58,6 +61,15 @@ private: ...@@ -58,6 +61,15 @@ private:
CudaStreamFactory defaultStreamFactory; CudaStreamFactory defaultStreamFactory;
}; };
class CudaPlatform::PlatformData {
public:
PlatformData(_gpuContext* gpu) : gpu(gpu), removeCM(false), useOBC(false) {
}
_gpuContext* gpu;
bool removeCM;
bool useOBC;
};
} // namespace OpenMM } // namespace OpenMM
#endif /*OPENMM_CUDAPLATFORM_H_*/ #endif /*OPENMM_CUDAPLATFORM_H_*/
...@@ -36,21 +36,21 @@ ...@@ -36,21 +36,21 @@
using namespace OpenMM; using namespace OpenMM;
KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform& platform, OpenMMContextImpl& context) const { KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform& platform, OpenMMContextImpl& context) const {
_gpuContext* gpu = static_cast<_gpuContext*>(context.getPlatformData()); CudaPlatform::PlatformData& data = *static_cast<CudaPlatform::PlatformData*>(context.getPlatformData());
if (name == CalcStandardMMForceFieldKernel::Name()) if (name == CalcStandardMMForceFieldKernel::Name())
return new CudaCalcStandardMMForceFieldKernel(name, platform, gpu, context.getSystem()); return new CudaCalcStandardMMForceFieldKernel(name, platform, data, context.getSystem());
// if (name == CalcGBSAOBCForceFieldKernel::Name()) if (name == CalcGBSAOBCForceFieldKernel::Name())
// return new CudaCalcGBSAOBCForceFieldKernel(name, platform); return new CudaCalcGBSAOBCForceFieldKernel(name, platform, data);
// if (name == IntegrateVerletStepKernel::Name()) // if (name == IntegrateVerletStepKernel::Name())
// return new CudaIntegrateVerletStepKernel(name, platform); // return new CudaIntegrateVerletStepKernel(name, platform);
if (name == IntegrateLangevinStepKernel::Name()) if (name == IntegrateLangevinStepKernel::Name())
return new CudaIntegrateLangevinStepKernel(name, platform, gpu); return new CudaIntegrateLangevinStepKernel(name, platform, data);
// if (name == IntegrateBrownianStepKernel::Name()) // if (name == IntegrateBrownianStepKernel::Name())
// return new CudaIntegrateBrownianStepKernel(name, platform); // return new CudaIntegrateBrownianStepKernel(name, platform);
// if (name == ApplyAndersenThermostatKernel::Name()) // if (name == ApplyAndersenThermostatKernel::Name())
// return new CudaApplyAndersenThermostatKernel(name, platform); // return new CudaApplyAndersenThermostatKernel(name, platform);
if (name == CalcKineticEnergyKernel::Name()) if (name == CalcKineticEnergyKernel::Name())
return new CudaCalcKineticEnergyKernel(name, platform); return new CudaCalcKineticEnergyKernel(name, platform);
// if (name == RemoveCMMotionKernel::Name()) if (name == RemoveCMMotionKernel::Name())
// return new CudaRemoveCMMotionKernel(name, platform); return new CudaRemoveCMMotionKernel(name, platform, data);
} }
...@@ -61,6 +61,7 @@ void CudaCalcStandardMMForceFieldKernel::initialize(const vector<vector<int> >& ...@@ -61,6 +61,7 @@ void CudaCalcStandardMMForceFieldKernel::initialize(const vector<vector<int> >&
numRBTorsions = rbTorsionIndices.size(); numRBTorsions = rbTorsionIndices.size();
num14 = bonded14Indices.size(); num14 = bonded14Indices.size();
const float RadiansToDegrees = 180.0/3.14159265; const float RadiansToDegrees = 180.0/3.14159265;
_gpuContext* gpu = data.gpu;
// Initialize bonds. // Initialize bonds.
...@@ -187,20 +188,19 @@ void CudaCalcStandardMMForceFieldKernel::initialize(const vector<vector<int> >& ...@@ -187,20 +188,19 @@ void CudaCalcStandardMMForceFieldKernel::initialize(const vector<vector<int> >&
} }
gpuSetLJ14Parameters(gpu, 138.935485f, (float) coulomb14Scale, atom1, atom2, c6, c12, q1, q2); gpuSetLJ14Parameters(gpu, 138.935485f, (float) coulomb14Scale, atom1, atom2, c6, c12, q1, q2);
} }
// Finish initialization.
gpuBuildThreadBlockWorkList(gpu);
gpuBuildExclusionList(gpu);
gpuBuildOutputBuffers(gpu);
gpuSetConstants(gpu);
kClearBornForces(gpu);
kClearForces(gpu);
} }
void CudaCalcStandardMMForceFieldKernel::executeForces(const Stream& positions, Stream& forces) { void CudaCalcStandardMMForceFieldKernel::executeForces(const Stream& positions, Stream& forces) {
_gpuContext* gpu = data.gpu;
if (data.useOBC) {
kCalculateCDLJObcGbsaForces1(gpu);
kReduceObcGbsaBornForces(gpu);
kCalculateObcGbsaForces2(gpu);
}
else {
kClearForces(gpu); kClearForces(gpu);
kCalculateCDLJForces(gpu); kCalculateCDLJForces(gpu);
}
kCalculateLocalForces(gpu); kCalculateLocalForces(gpu);
kReduceBornSumAndForces(gpu); kReduceBornSumAndForces(gpu);
} }
...@@ -222,18 +222,30 @@ double CudaCalcStandardMMForceFieldKernel::executeEnergy(const Stream& positions ...@@ -222,18 +222,30 @@ double CudaCalcStandardMMForceFieldKernel::executeEnergy(const Stream& positions
return context.getState(State::Energy).getPotentialEnergy(); return context.getState(State::Energy).getPotentialEnergy();
} }
//CudaCalcGBSAOBCForceFieldKernel::~CudaCalcGBSAOBCForceFieldKernel() { CudaCalcGBSAOBCForceFieldKernel::~CudaCalcGBSAOBCForceFieldKernel() {
//} }
//
//void CudaCalcGBSAOBCForceFieldKernel::initialize(const vector<vector<double> >& atomParameters, double solventDielectric, double soluteDielectric) { void CudaCalcGBSAOBCForceFieldKernel::initialize(const vector<vector<double> >& atomParameters, double solventDielectric, double soluteDielectric) {
//} int numAtoms = atomParameters.size();
// _gpuContext* gpu = data.gpu;
//void CudaCalcGBSAOBCForceFieldKernel::executeForces(const Stream& positions, Stream& forces) { vector<int> atom(numAtoms);
//} vector<float> radius(numAtoms);
// vector<float> scale(numAtoms);
//double CudaCalcGBSAOBCForceFieldKernel::executeEnergy(const Stream& positions) { for (int i = 0; i < numAtoms; i++) {
//} atom[i] = i;
// radius[i] = (float) atomParameters[i][1];
scale[i] = (float) atomParameters[i][2];
}
gpuSetObcParameters(gpu, soluteDielectric, solventDielectric, atom, radius, scale);
data.useOBC = true;
}
void CudaCalcGBSAOBCForceFieldKernel::executeForces(const Stream& positions, Stream& forces) {
}
double CudaCalcGBSAOBCForceFieldKernel::executeEnergy(const Stream& positions) {
}
//CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() { //CudaIntegrateVerletStepKernel::~CudaIntegrateVerletStepKernel() {
//} //}
// //
...@@ -251,6 +263,7 @@ void CudaIntegrateLangevinStepKernel::initialize(const vector<double>& masses, c ...@@ -251,6 +263,7 @@ void CudaIntegrateLangevinStepKernel::initialize(const vector<double>& masses, c
// Set masses. // Set masses.
_gpuContext* gpu = data.gpu;
vector<float> mass(masses.size()); vector<float> mass(masses.size());
for (int i = 0; i < (int) mass.size(); i++) for (int i = 0; i < (int) mass.size(); i++)
mass[i] = (float) masses[i]; mass[i] = (float) masses[i];
...@@ -272,11 +285,20 @@ void CudaIntegrateLangevinStepKernel::initialize(const vector<double>& masses, c ...@@ -272,11 +285,20 @@ void CudaIntegrateLangevinStepKernel::initialize(const vector<double>& masses, c
invMass2[i] = 1.0f/mass[atom2[i]]; invMass2[i] = 1.0f/mass[atom2[i]];
} }
gpuSetShakeParameters(gpu, atom1, atom2, distance, invMass1, invMass2); gpuSetShakeParameters(gpu, atom1, atom2, distance, invMass1, invMass2);
gpuBuildThreadBlockWorkList(gpu);
gpuBuildExclusionList(gpu);
gpuBuildOutputBuffers(gpu);
gpuSetConstants(gpu); gpuSetConstants(gpu);
kCalculateObcGbsaBornSum(gpu);
kReduceObcGbsaBornSum(gpu);
kClearBornForces(gpu);
kClearForces(gpu);
cudaThreadSynchronize();
prevStepSize = -1.0; prevStepSize = -1.0;
} }
void CudaIntegrateLangevinStepKernel::execute(Stream& positions, Stream& velocities, const Stream& forces, double temperature, double friction, double stepSize) { void CudaIntegrateLangevinStepKernel::execute(Stream& positions, Stream& velocities, const Stream& forces, double temperature, double friction, double stepSize) {
_gpuContext* gpu = data.gpu;
if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) { if (temperature != prevTemp || friction != prevFriction || stepSize != prevStepSize) {
// Initialize the GPU parameters. // Initialize the GPU parameters.
...@@ -290,6 +312,8 @@ void CudaIntegrateLangevinStepKernel::execute(Stream& positions, Stream& velocit ...@@ -290,6 +312,8 @@ void CudaIntegrateLangevinStepKernel::execute(Stream& positions, Stream& velocit
} }
kUpdatePart1(gpu); kUpdatePart1(gpu);
kApplyFirstShake(gpu); kApplyFirstShake(gpu);
if (data.removeCM)
gpu->bCalculateCM = true;
kUpdatePart2(gpu); kUpdatePart2(gpu);
kApplySecondShake(gpu); kApplySecondShake(gpu);
} }
...@@ -329,9 +353,10 @@ double CudaCalcKineticEnergyKernel::execute(const Stream& velocities) { ...@@ -329,9 +353,10 @@ double CudaCalcKineticEnergyKernel::execute(const Stream& velocities) {
delete v; delete v;
return 0.5*energy; return 0.5*energy;
} }
//
//void CudaRemoveCMMotionKernel::initialize(const vector<double>& masses) { void CudaRemoveCMMotionKernel::initialize(const vector<double>& masses) {
//} data.removeCM = true;
// }
//void CudaRemoveCMMotionKernel::execute(Stream& velocities) {
//} void CudaRemoveCMMotionKernel::execute(Stream& velocities) {
}
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "CudaPlatform.h"
#include "kernels.h" #include "kernels.h"
#include "kernels/gpuTypes.h" #include "kernels/gpuTypes.h"
#include "System.h" #include "System.h"
...@@ -49,7 +50,7 @@ namespace OpenMM { ...@@ -49,7 +50,7 @@ namespace OpenMM {
*/ */
class CudaCalcStandardMMForceFieldKernel : public CalcStandardMMForceFieldKernel { class CudaCalcStandardMMForceFieldKernel : public CalcStandardMMForceFieldKernel {
public: public:
CudaCalcStandardMMForceFieldKernel(std::string name, const Platform& platform, _gpuContext* gpu, System& system) : CalcStandardMMForceFieldKernel(name, platform), gpu(gpu), system(system) { CudaCalcStandardMMForceFieldKernel(std::string name, const Platform& platform, CudaPlatform::PlatformData& data, System& system) : CalcStandardMMForceFieldKernel(name, platform), data(data), system(system) {
} }
~CudaCalcStandardMMForceFieldKernel(); ~CudaCalcStandardMMForceFieldKernel();
/** /**
...@@ -95,46 +96,45 @@ public: ...@@ -95,46 +96,45 @@ public:
*/ */
double executeEnergy(const Stream& positions); double executeEnergy(const Stream& positions);
private: private:
_gpuContext* gpu; CudaPlatform::PlatformData& data;
int numAtoms, numBonds, numAngles, numPeriodicTorsions, numRBTorsions, num14; int numAtoms, numBonds, numAngles, numPeriodicTorsions, numRBTorsions, num14;
System& system; System& system;
}; };
///** /**
// * This kernel is invoked by GBSAOBCForceField to calculate the forces acting on the system. * This kernel is invoked by GBSAOBCForceField to calculate the forces acting on the system.
// */ */
//class CudaCalcGBSAOBCForceFieldKernel : public CalcGBSAOBCForceFieldKernel { class CudaCalcGBSAOBCForceFieldKernel : public CalcGBSAOBCForceFieldKernel {
//public: public:
// CudaCalcGBSAOBCForceFieldKernel(std::string name, const Platform& platform) : CalcGBSAOBCForceFieldKernel(name, platform) { CudaCalcGBSAOBCForceFieldKernel(std::string name, const Platform& platform, CudaPlatform::PlatformData& data) : CalcGBSAOBCForceFieldKernel(name, platform), data(data) {
// } }
// ~CudaCalcGBSAOBCForceFieldKernel(); ~CudaCalcGBSAOBCForceFieldKernel();
// /** /**
// * Initialize the kernel, setting up the values of all the force field parameters. * Initialize the kernel, setting up the values of all the force field parameters.
// * *
// * @param atomParameters the force parameters (charge, atomic radius, scaling factor) for each atom * @param atomParameters the force parameters (charge, atomic radius, scaling factor) for each atom
// * @param solventDielectric the dielectric constant of the solvent * @param solventDielectric the dielectric constant of the solvent
// * @param soluteDielectric the dielectric constant of the solute * @param soluteDielectric the dielectric constant of the solute
// */ */
// void initialize(const std::vector<std::vector<double> >& atomParameters, double solventDielectric, double soluteDielectric); void initialize(const std::vector<std::vector<double> >& atomParameters, double solventDielectric, double soluteDielectric);
// /** /**
// * Execute the kernel to calculate the forces. * Execute the kernel to calculate the forces.
// * *
// * @param positions a Stream of type Double3 containing the position (x, y, z) of each atom * @param positions a Stream of type Double3 containing the position (x, y, z) of each atom
// * @param forces a Stream of type Double3 containing the force (x, y, z) on each atom. On entry, this contains the forces that * @param forces a Stream of type Double3 containing the force (x, y, z) on each atom. On entry, this contains the forces that
// * have been calculated so far. The kernel should add its own forces to the values already in the stream. * have been calculated so far. The kernel should add its own forces to the values already in the stream.
// */ */
// void executeForces(const Stream& positions, Stream& forces); void executeForces(const Stream& positions, Stream& forces);
// /** /**
// * Execute the kernel to calculate the energy. * Execute the kernel to calculate the energy.
// * *
// * @param positions a Stream of type Double3 containing the position (x, y, z) of each atom * @param positions a Stream of type Double3 containing the position (x, y, z) of each atom
// * @return the potential energy due to the GBSAOBCForceField * @return the potential energy due to the GBSAOBCForceField
// */ */
// double executeEnergy(const Stream& positions); double executeEnergy(const Stream& positions);
//private: private:
// CpuObc* obc; CudaPlatform::PlatformData& data;
// std::vector<RealOpenMM> charges; };
//};
// //
///** ///**
// * This kernel is invoked by VerletIntegrator to take one time step. // * This kernel is invoked by VerletIntegrator to take one time step.
...@@ -178,7 +178,7 @@ private: ...@@ -178,7 +178,7 @@ private:
*/ */
class CudaIntegrateLangevinStepKernel : public IntegrateLangevinStepKernel { class CudaIntegrateLangevinStepKernel : public IntegrateLangevinStepKernel {
public: public:
CudaIntegrateLangevinStepKernel(std::string name, const Platform& platform, _gpuContext* gpu) : IntegrateLangevinStepKernel(name, platform), gpu(gpu) { CudaIntegrateLangevinStepKernel(std::string name, const Platform& platform, CudaPlatform::PlatformData& data) : IntegrateLangevinStepKernel(name, platform), data(data) {
} }
~CudaIntegrateLangevinStepKernel(); ~CudaIntegrateLangevinStepKernel();
/** /**
...@@ -202,7 +202,7 @@ public: ...@@ -202,7 +202,7 @@ public:
*/ */
void execute(Stream& positions, Stream& velocities, const Stream& forces, double temperature, double friction, double stepSize); void execute(Stream& positions, Stream& velocities, const Stream& forces, double temperature, double friction, double stepSize);
private: private:
_gpuContext* gpu; CudaPlatform::PlatformData& data;
double prevTemp, prevFriction, prevStepSize; double prevTemp, prevFriction, prevStepSize;
}; };
// //
...@@ -296,29 +296,29 @@ public: ...@@ -296,29 +296,29 @@ public:
private: private:
std::vector<double> masses; std::vector<double> masses;
}; };
//
///** /**
// * This kernel is invoked to remove center of mass motion from the system. * This kernel is invoked to remove center of mass motion from the system.
// */ */
//class CudaRemoveCMMotionKernel : public RemoveCMMotionKernel { class CudaRemoveCMMotionKernel : public RemoveCMMotionKernel {
//public: public:
// CudaRemoveCMMotionKernel(std::string name, const Platform& platform) : RemoveCMMotionKernel(name, platform) { CudaRemoveCMMotionKernel(std::string name, const Platform& platform, CudaPlatform::PlatformData& data) : RemoveCMMotionKernel(name, platform), data(data) {
// } }
// /** /**
// * Initialize the kernel, setting up the atomic masses. * Initialize the kernel, setting up the atomic masses.
// * *
// * @param masses the mass of each atom * @param masses the mass of each atom
// */ */
// void initialize(const std::vector<double>& masses); void initialize(const std::vector<double>& masses);
// /** /**
// * Execute the kernel. * Execute the kernel.
// * *
// * @param velocities a Stream of type Double3 containing the velocity (x, y, z) of each atom * @param velocities a Stream of type Double3 containing the velocity (x, y, z) of each atom
// */ */
// void execute(Stream& velocities); void execute(Stream& velocities);
//private: private:
// std::vector<double> masses; CudaPlatform::PlatformData& data;
//}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -41,13 +41,13 @@ using namespace OpenMM; ...@@ -41,13 +41,13 @@ using namespace OpenMM;
CudaPlatform::CudaPlatform() { CudaPlatform::CudaPlatform() {
CudaKernelFactory* factory = new CudaKernelFactory(); CudaKernelFactory* factory = new CudaKernelFactory();
registerKernelFactory(CalcStandardMMForceFieldKernel::Name(), factory); registerKernelFactory(CalcStandardMMForceFieldKernel::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);
registerKernelFactory(CalcKineticEnergyKernel::Name(), factory); registerKernelFactory(CalcKineticEnergyKernel::Name(), factory);
// registerKernelFactory(RemoveCMMotionKernel::Name(), factory); registerKernelFactory(RemoveCMMotionKernel::Name(), factory);
} }
bool CudaPlatform::supportsDoublePrecision() const { bool CudaPlatform::supportsDoublePrecision() const {
...@@ -61,10 +61,11 @@ const StreamFactory& CudaPlatform::getDefaultStreamFactory() const { ...@@ -61,10 +61,11 @@ const StreamFactory& CudaPlatform::getDefaultStreamFactory() const {
void CudaPlatform::contextCreated(OpenMMContextImpl& context) const { void CudaPlatform::contextCreated(OpenMMContextImpl& context) const {
int numAtoms = context.getSystem().getNumAtoms(); int numAtoms = context.getSystem().getNumAtoms();
_gpuContext* gpu = (_gpuContext*) gpuInit(numAtoms); _gpuContext* gpu = (_gpuContext*) gpuInit(numAtoms);
context.setPlatformData(gpu); context.setPlatformData(new PlatformData(gpu));
} }
void CudaPlatform::contextDestroyed(OpenMMContextImpl& context) const { void CudaPlatform::contextDestroyed(OpenMMContextImpl& context) const {
_gpuContext* data = reinterpret_cast<_gpuContext*>(context.getPlatformData()); PlatformData* data = reinterpret_cast<PlatformData*>(context.getPlatformData());
gpuShutDown(data); gpuShutDown(data->gpu);
delete data;
} }
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. * * USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#include "CudaPlatform.h"
#include "CudaStreamFactory.h" #include "CudaStreamFactory.h"
#include "CudaStreamImpl.h" #include "CudaStreamImpl.h"
#include "OpenMMException.h" #include "OpenMMException.h"
...@@ -39,19 +40,19 @@ using namespace OpenMM; ...@@ -39,19 +40,19 @@ using namespace OpenMM;
StreamImpl* CudaStreamFactory::createStreamImpl(std::string name, int size, Stream::DataType type, const Platform& platform, OpenMMContextImpl& context) const { StreamImpl* CudaStreamFactory::createStreamImpl(std::string name, int size, Stream::DataType type, const Platform& platform, OpenMMContextImpl& context) const {
if (name == "atomPositions") { if (name == "atomPositions") {
_gpuContext& gpu = *reinterpret_cast<_gpuContext*>(context.getPlatformData()); CudaPlatform::PlatformData& data = *static_cast<CudaPlatform::PlatformData*>(context.getPlatformData());
float padding[] = {100000.0f, 100000.0f, 100000.0f, 0.2f}; float padding[] = {100000.0f, 100000.0f, 100000.0f, 0.2f};
return new CudaStreamImpl<float4>(name, size, type, platform, gpu.psPosq4, 4, padding); return new CudaStreamImpl<float4>(name, size, type, platform, data.gpu->psPosq4, 4, padding);
} }
if (name == "atomVelocities") { if (name == "atomVelocities") {
_gpuContext& gpu = *reinterpret_cast<_gpuContext*>(context.getPlatformData()); CudaPlatform::PlatformData& data = *static_cast<CudaPlatform::PlatformData*>(context.getPlatformData());
float padding[] = {0.0f, 0.0f, 0.0f, 0.0f}; float padding[] = {0.0f, 0.0f, 0.0f, 0.0f};
return new CudaStreamImpl<float4>(name, size, type, platform, gpu.psVelm4, 4, padding); return new CudaStreamImpl<float4>(name, size, type, platform, data.gpu->psVelm4, 4, padding);
} }
if (name == "atomForces") { if (name == "atomForces") {
_gpuContext& gpu = *reinterpret_cast<_gpuContext*>(context.getPlatformData()); CudaPlatform::PlatformData& data = *static_cast<CudaPlatform::PlatformData*>(context.getPlatformData());
float padding[] = {0.0f, 0.0f, 0.0f, 0.0f}; float padding[] = {0.0f, 0.0f, 0.0f, 0.0f};
return new CudaStreamImpl<float4>(name, size, type, platform, gpu.psForce4, 4, padding); return new CudaStreamImpl<float4>(name, size, type, platform, data.gpu->psForce4, 4, padding);
} }
switch (type) { switch (type) {
case Stream::Float: case Stream::Float:
......
/* -------------------------------------------------------------------------- *
* 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 AndersenThermostat.
*/
#include "../../../tests/AssertionUtilities.h"
#include "CMMotionRemover.h"
#include "OpenMMContext.h"
#include "CudaPlatform.h"
#include "StandardMMForceField.h"
#include "System.h"
#include "LangevinIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
Vec3 calcCM(const vector<Vec3>& values, System& system) {
Vec3 cm;
for (int j = 0; j < system.getNumAtoms(); ++j) {
cm[0] += values[j][0]*system.getAtomMass(j);
cm[1] += values[j][1]*system.getAtomMass(j);
cm[2] += values[j][2]*system.getAtomMass(j);
}
return cm;
}
void testMotionRemoval() {
const int numAtoms = 8;
CudaPlatform platform;
System system(numAtoms, 0);
LangevinIntegrator integrator(0.0, 1e-5, 0.01);
StandardMMForceField* forceField = new StandardMMForceField(numAtoms, 1, 0, 0, 0);
for (int i = 0; i < numAtoms; ++i) {
system.setAtomMass(i, i+1);
forceField->setAtomParameters(i, (i%2 == 0 ? 1.0 : -1.0), 1.0, 5.0);
}
forceField->setBondParameters(0, 2, 3, 2.0, 0.5);
system.addForce(forceField);
CMMotionRemover* remover = new CMMotionRemover();
system.addForce(remover);
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(numAtoms);
vector<Vec3> velocities(numAtoms);
init_gen_rand(0);
for (int i = 0; i < numAtoms; ++i) {
positions[i] = Vec3((i%2 == 0 ? 2 : -2), (i%4 < 2 ? 2 : -2), (i < 4 ? 2 : -2));
velocities[i] = Vec3(genrand_real2()-0.5, genrand_real2()-0.5, genrand_real2()-0.5);
}
context.setPositions(positions);
context.setVelocities(velocities);
// Now run it for a while and see if the center of mass remains fixed.
Vec3 cmPos = calcCM(context.getState(State::Positions).getPositions(), system);
for (int i = 0; i < 1000; ++i) {
integrator.step(1);
State state = context.getState(State::Positions | State::Velocities);
Vec3 pos = calcCM(state.getPositions(), system);
ASSERT_EQUAL_VEC(cmPos, pos, 1e-2);
Vec3 vel = calcCM(state.getVelocities(), system);
if (i > 0) {
ASSERT_EQUAL_VEC(Vec3(0, 0, 0), vel, 1e-2);
}
}
}
int main() {
try {
testMotionRemoval();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
/* -------------------------------------------------------------------------- *
* 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 GBSAOBCForceField.
*/
#include "../../../tests/AssertionUtilities.h"
#include "OpenMMContext.h"
#include "CudaPlatform.h"
#include "GBSAOBCForceField.h"
#include "System.h"
#include "LangevinIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "../src/sfmt/SFMT.h"
#include "StandardMMForceField.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testSingleAtom() {
CudaPlatform platform;
System system(1, 0);
system.setAtomMass(0, 2.0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBSAOBCForceField* forceField = new GBSAOBCForceField(1);
forceField->setAtomParameters(0, 0.5, 0.15, 1);
system.addForce(forceField);
system.addForce(new StandardMMForceField(1, 0, 0, 0, 0));
OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(1);
positions[0] = Vec3(0, 0, 0);
context.setPositions(positions);
State state = context.getState(State::Energy);
double bornRadius = 0.15-0.09; // dielectric offset
double eps0 = EPSILON0;
double bornEnergy = (-0.5*0.5/(8*PI_M*eps0))*(1.0/forceField->getSoluteDielectric()-1.0/forceField->getSolventDielectric())/bornRadius;
double extendedRadius = bornRadius+0.14; // probe radius
double nonpolarEnergy = CAL2JOULE*PI_M*0.0216*(10*extendedRadius)*(10*extendedRadius)*std::pow(0.15/bornRadius, 6.0); // Where did this formula come from? Just copied it from CpuImplicitSolvent.cpp
ASSERT_EQUAL_TOL((bornEnergy+nonpolarEnergy), state.getPotentialEnergy(), 0.01);
}
void testForce() {
CudaPlatform platform;
const int numAtoms = 10;
System system(numAtoms, 0);
LangevinIntegrator integrator(0, 0.1, 0.01);
GBSAOBCForceField* forceField = new GBSAOBCForceField(numAtoms);
for (int i = 0; i < numAtoms; ++i)
forceField->setAtomParameters(i, i%2 == 0 ? -1 : 1, 0.15, 1);
system.addForce(forceField);
system.addForce(new StandardMMForceField(numAtoms, 0, 0, 0, 0));
OpenMMContext context(system, integrator, platform);
// Set random positions for all the atoms.
vector<Vec3> positions(numAtoms);
init_gen_rand(0);
for (int i = 0; i < numAtoms; ++i)
positions[i] = Vec3(5.0*genrand_real2(), 5.0*genrand_real2(), 5.0*genrand_real2());
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
// Take a small step in the direction of the energy gradient.
double norm = 0.0;
for (int i = 0; i < numAtoms; ++i) {
Vec3 f = state.getForces()[i];
norm += f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
}
norm = std::sqrt(norm);
const double delta = 1e-3;
double step = delta/norm;
for (int i = 0; i < numAtoms; ++i) {
Vec3 p = positions[i];
Vec3 f = state.getForces()[i];
positions[i] = Vec3(p[0]-f[0]*step, p[1]-f[1]*step, p[2]-f[2]*step);
}
context.setPositions(positions);
// See whether the potential energy changed by the expected amount.
State state2 = context.getState(State::Energy);
ASSERT_EQUAL_TOL(norm, (state2.getPotentialEnergy()-state.getPotentialEnergy())/delta, 0.01)
}
int main() {
try {
testSingleAtom();
testForce();
}
catch(const exception& e) {
cout << "exception: " << e.what() << endl;
return 1;
}
cout << "Done" << endl;
return 0;
}
...@@ -130,7 +130,7 @@ void testTemperature() { ...@@ -130,7 +130,7 @@ void testTemperature() {
void testConstraints() { void testConstraints() {
const int numAtoms = 8; const int numAtoms = 8;
const int numConstraints = numAtoms-1; const int numConstraints = 4;
const double temp = 100.0; const double temp = 100.0;
CudaPlatform platform; CudaPlatform platform;
System system(numAtoms, numConstraints); System system(numAtoms, numConstraints);
...@@ -141,7 +141,7 @@ void testConstraints() { ...@@ -141,7 +141,7 @@ void testConstraints() {
forceField->setAtomParameters(i, (i%2 == 0 ? 0.2 : -0.2), 0.5, 5.0); forceField->setAtomParameters(i, (i%2 == 0 ? 0.2 : -0.2), 0.5, 5.0);
} }
for (int i = 0; i < numConstraints; ++i) for (int i = 0; i < numConstraints; ++i)
system.setConstraintParameters(i, i, i+1, 1.0); system.setConstraintParameters(i, 2*i, 2*i+1, 1.0);
system.addForce(forceField); system.addForce(forceField);
OpenMMContext context(system, integrator, platform); OpenMMContext context(system, integrator, platform);
vector<Vec3> positions(numAtoms); vector<Vec3> positions(numAtoms);
...@@ -159,10 +159,13 @@ void testConstraints() { ...@@ -159,10 +159,13 @@ void testConstraints() {
for (int i = 0; i < 1000; ++i) { for (int i = 0; i < 1000; ++i) {
State state = context.getState(State::Positions); State state = context.getState(State::Positions);
for (int j = 0; j < numConstraints; ++j) { for (int j = 0; j < numConstraints; ++j) {
Vec3 p1 = state.getPositions()[j]; int atom1, atom2;
Vec3 p2 = state.getPositions()[j+1]; double distance;
system.getConstraintParameters(j, atom1, atom2, distance);
Vec3 p1 = state.getPositions()[atom1];
Vec3 p2 = state.getPositions()[atom2];
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])); 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(1.0, dist, 2e-4); ASSERT_EQUAL_TOL(distance, dist, 2e-4);
} }
integrator.step(1); integrator.step(1);
} }
......
...@@ -62,7 +62,7 @@ void testSingleAtom() { ...@@ -62,7 +62,7 @@ void testSingleAtom() {
positions[0] = Vec3(0, 0, 0); positions[0] = Vec3(0, 0, 0);
context.setPositions(positions); context.setPositions(positions);
State state = context.getState(State::Energy); State state = context.getState(State::Energy);
double bornRadius = 0.15-0.009; // dielectric offset double bornRadius = 0.15-0.09; // dielectric offset
double eps0 = EPSILON0; double eps0 = EPSILON0;
double bornEnergy = (-0.5*0.5/(8*PI_M*eps0))*(1.0/forceField->getSoluteDielectric()-1.0/forceField->getSolventDielectric())/bornRadius; double bornEnergy = (-0.5*0.5/(8*PI_M*eps0))*(1.0/forceField->getSoluteDielectric()-1.0/forceField->getSolventDielectric())/bornRadius;
double extendedRadius = bornRadius+0.14; // probe radius double extendedRadius = bornRadius+0.14; // probe radius
......
...@@ -56,9 +56,9 @@ void throwException(const char* file, int line, const std::string& details) { ...@@ -56,9 +56,9 @@ void throwException(const char* file, int line, const std::string& details) {
#define ASSERT(cond) {if (!(cond)) throwException(__FILE__, __LINE__, "");}; #define ASSERT(cond) {if (!(cond)) throwException(__FILE__, __LINE__, "");};
#define ASSERT_EQUAL(expected, found) {if ((expected) != (found)) {std::stringstream details; details << "Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}}; #define ASSERT_EQUAL(expected, found) {if (!((expected) == (found))) {std::stringstream details; details << "Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_TOL(expected, found, tol) {double _scale_ = std::fabs(expected) > 1.0 ? std::fabs(expected) : 1.0; if (std::fabs((expected)-(found))/_scale_ > (tol)) {std::stringstream details; details << "Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}}; #define ASSERT_EQUAL_TOL(expected, found, tol) {double _scale_ = std::fabs(expected) > 1.0 ? std::fabs(expected) : 1.0; if (!(std::fabs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << "Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_VEC(expected, found, tol) {ASSERT_EQUAL_TOL((expected)[0], (found)[0], (tol)); ASSERT_EQUAL_TOL((expected)[1], (found)[1], (tol)); ASSERT_EQUAL_TOL((expected)[2], (found)[2], (tol));}; #define ASSERT_EQUAL_VEC(expected, found, tol) {ASSERT_EQUAL_TOL((expected)[0], (found)[0], (tol)); ASSERT_EQUAL_TOL((expected)[1], (found)[1], (tol)); ASSERT_EQUAL_TOL((expected)[2], (found)[2], (tol));};
......
...@@ -28,5 +28,5 @@ FOREACH(TEST_PROG ${TEST_PROGS}) ...@@ -28,5 +28,5 @@ FOREACH(TEST_PROG ${TEST_PROGS})
ENDFOREACH(TEST_PROG ${TEST_PROGS}) ENDFOREACH(TEST_PROG ${TEST_PROGS})
ADD_SUBDIRECTORY(platforms) #ADD_SUBDIRECTORY(platforms)
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