"vscode:/vscode.git/clone" did not exist on "98c30a3f4117dfd71a021ed951fd2fb36a69cef1"
Commit 00c4b747 authored by Peter Eastman's avatar Peter Eastman
Browse files

Continuing to implement new CUDA platform: HarmonicAngleForce,...

Continuing to implement new CUDA platform: HarmonicAngleForce, PeriodicTorsionForce, RBTorsionForce, CMAPTorsionForce
parent 6e434a02
...@@ -74,7 +74,7 @@ void CudaBondedUtilities::initialize(const System& system) { ...@@ -74,7 +74,7 @@ void CudaBondedUtilities::initialize(const System& system) {
int numAtoms = forceAtoms[i][0].size(); int numAtoms = forceAtoms[i][0].size();
int startAtom = 0; int startAtom = 0;
while (startAtom < numAtoms) { while (startAtom < numAtoms) {
int width = max(numAtoms-startAtom, 4); int width = min(numAtoms-startAtom, 4);
if (width == 3) if (width == 3)
width = 4; width = 4;
vector<unsigned int> indexVec(width*numBonds); vector<unsigned int> indexVec(width*numBonds);
...@@ -136,7 +136,7 @@ string CudaBondedUtilities::createForceSource(int forceIndex, int numBonds, int ...@@ -136,7 +136,7 @@ string CudaBondedUtilities::createForceSource(int forceIndex, int numBonds, int
int atomsToLoad = min(indexWidth, numAtoms-startAtom); int atomsToLoad = min(indexWidth, numAtoms-startAtom);
for (int j = 0; j < atomsToLoad; j++) { for (int j = 0; j < atomsToLoad; j++) {
s<<" unsigned int atom"<<(startAtom+j+1)<<" = atoms"<<i<<suffix[j]<<";\n"; s<<" unsigned int atom"<<(startAtom+j+1)<<" = atoms"<<i<<suffix[j]<<";\n";
s<<" real4 pos"<<(j+1)<<" = posq[atom"<<(j+1)<<"];\n"; s<<" real4 pos"<<(startAtom+j+1)<<" = posq[atom"<<(startAtom+j+1)<<"];\n";
} }
startAtom += indexWidth; startAtom += indexWidth;
} }
......
...@@ -80,16 +80,16 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform ...@@ -80,16 +80,16 @@ KernelImpl* CudaKernelFactory::createKernelImpl(std::string name, const Platform
return new CudaCalcHarmonicBondForceKernel(name, platform, cu, context.getSystem()); return new CudaCalcHarmonicBondForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcCustomBondForceKernel::Name()) // if (name == CalcCustomBondForceKernel::Name())
// return new CudaCalcCustomBondForceKernel(name, platform, cu, context.getSystem()); // return new CudaCalcCustomBondForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcHarmonicAngleForceKernel::Name()) if (name == CalcHarmonicAngleForceKernel::Name())
// return new CudaCalcHarmonicAngleForceKernel(name, platform, cu, context.getSystem()); return new CudaCalcHarmonicAngleForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcCustomAngleForceKernel::Name()) // if (name == CalcCustomAngleForceKernel::Name())
// return new CudaCalcCustomAngleForceKernel(name, platform, cu, context.getSystem()); // return new CudaCalcCustomAngleForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcPeriodicTorsionForceKernel::Name()) if (name == CalcPeriodicTorsionForceKernel::Name())
// return new CudaCalcPeriodicTorsionForceKernel(name, platform, cu, context.getSystem()); return new CudaCalcPeriodicTorsionForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcRBTorsionForceKernel::Name()) if (name == CalcRBTorsionForceKernel::Name())
// return new CudaCalcRBTorsionForceKernel(name, platform, cu, context.getSystem()); return new CudaCalcRBTorsionForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcCMAPTorsionForceKernel::Name()) if (name == CalcCMAPTorsionForceKernel::Name())
// return new CudaCalcCMAPTorsionForceKernel(name, platform, cu, context.getSystem()); return new CudaCalcCMAPTorsionForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcCustomTorsionForceKernel::Name()) // if (name == CalcCustomTorsionForceKernel::Name())
// return new CudaCalcCustomTorsionForceKernel(name, platform, cu, context.getSystem()); // return new CudaCalcCustomTorsionForceKernel(name, platform, cu, context.getSystem());
// if (name == CalcNonbondedForceKernel::Name()) // if (name == CalcNonbondedForceKernel::Name())
......
...@@ -82,6 +82,7 @@ void CudaCalcForcesAndEnergyKernel::initialize(const System& system) { ...@@ -82,6 +82,7 @@ void CudaCalcForcesAndEnergyKernel::initialize(const System& system) {
} }
void CudaCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool includeForces, bool includeEnergy, int groups) { void CudaCalcForcesAndEnergyKernel::beginComputation(ContextImpl& context, bool includeForces, bool includeEnergy, int groups) {
cuCtxSetCurrent(cu.getContext());
// CudaNonbondedUtilities& nb = cu.getNonbondedUtilities(); // CudaNonbondedUtilities& nb = cu.getNonbondedUtilities();
// bool includeNonbonded = ((groups&(1<<nb.getForceGroup())) != 0); // bool includeNonbonded = ((groups&(1<<nb.getForceGroup())) != 0);
// cu.setAtomsWereReordered(false); // cu.setAtomsWereReordered(false);
...@@ -133,6 +134,7 @@ void CudaUpdateStateDataKernel::setTime(ContextImpl& context, double time) { ...@@ -133,6 +134,7 @@ void CudaUpdateStateDataKernel::setTime(ContextImpl& context, double time) {
} }
void CudaUpdateStateDataKernel::getPositions(ContextImpl& context, vector<Vec3>& positions) { void CudaUpdateStateDataKernel::getPositions(ContextImpl& context, vector<Vec3>& positions) {
cuCtxSetCurrent(cu.getContext());
const vector<int>& order = cu.getAtomIndex(); const vector<int>& order = cu.getAtomIndex();
int numParticles = context.getSystem().getNumParticles(); int numParticles = context.getSystem().getNumParticles();
positions.resize(numParticles); positions.resize(numParticles);
...@@ -158,6 +160,7 @@ void CudaUpdateStateDataKernel::getPositions(ContextImpl& context, vector<Vec3>& ...@@ -158,6 +160,7 @@ void CudaUpdateStateDataKernel::getPositions(ContextImpl& context, vector<Vec3>&
} }
void CudaUpdateStateDataKernel::setPositions(ContextImpl& context, const vector<Vec3>& positions) { void CudaUpdateStateDataKernel::setPositions(ContextImpl& context, const vector<Vec3>& positions) {
cuCtxSetCurrent(cu.getContext());
const vector<int>& order = cu.getAtomIndex(); const vector<int>& order = cu.getAtomIndex();
int numParticles = context.getSystem().getNumParticles(); int numParticles = context.getSystem().getNumParticles();
if (cu.getUseDoublePrecision()) { if (cu.getUseDoublePrecision()) {
...@@ -193,6 +196,7 @@ void CudaUpdateStateDataKernel::setPositions(ContextImpl& context, const vector< ...@@ -193,6 +196,7 @@ void CudaUpdateStateDataKernel::setPositions(ContextImpl& context, const vector<
} }
void CudaUpdateStateDataKernel::getVelocities(ContextImpl& context, vector<Vec3>& velocities) { void CudaUpdateStateDataKernel::getVelocities(ContextImpl& context, vector<Vec3>& velocities) {
cuCtxSetCurrent(cu.getContext());
const vector<int>& order = cu.getAtomIndex(); const vector<int>& order = cu.getAtomIndex();
int numParticles = context.getSystem().getNumParticles(); int numParticles = context.getSystem().getNumParticles();
velocities.resize(numParticles); velocities.resize(numParticles);
...@@ -217,6 +221,7 @@ void CudaUpdateStateDataKernel::getVelocities(ContextImpl& context, vector<Vec3> ...@@ -217,6 +221,7 @@ void CudaUpdateStateDataKernel::getVelocities(ContextImpl& context, vector<Vec3>
} }
void CudaUpdateStateDataKernel::setVelocities(ContextImpl& context, const vector<Vec3>& velocities) { void CudaUpdateStateDataKernel::setVelocities(ContextImpl& context, const vector<Vec3>& velocities) {
cuCtxSetCurrent(cu.getContext());
const vector<int>& order = cu.getAtomIndex(); const vector<int>& order = cu.getAtomIndex();
int numParticles = context.getSystem().getNumParticles(); int numParticles = context.getSystem().getNumParticles();
if (cu.getUseDoublePrecision()) { if (cu.getUseDoublePrecision()) {
...@@ -250,6 +255,7 @@ void CudaUpdateStateDataKernel::setVelocities(ContextImpl& context, const vector ...@@ -250,6 +255,7 @@ void CudaUpdateStateDataKernel::setVelocities(ContextImpl& context, const vector
} }
void CudaUpdateStateDataKernel::getForces(ContextImpl& context, vector<Vec3>& forces) { void CudaUpdateStateDataKernel::getForces(ContextImpl& context, vector<Vec3>& forces) {
cuCtxSetCurrent(cu.getContext());
long long* force = (long long*) cu.getPinnedBuffer(); long long* force = (long long*) cu.getPinnedBuffer();
cu.getForce().download(force); cu.getForce().download(force);
const vector<int>& order = cu.getAtomIndex(); const vector<int>& order = cu.getAtomIndex();
...@@ -275,6 +281,7 @@ void CudaUpdateStateDataKernel::setPeriodicBoxVectors(ContextImpl& context, cons ...@@ -275,6 +281,7 @@ void CudaUpdateStateDataKernel::setPeriodicBoxVectors(ContextImpl& context, cons
} }
void CudaUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostream& stream) { void CudaUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostream& stream) {
cuCtxSetCurrent(cu.getContext());
// int version = 1; // int version = 1;
// stream.write((char*) &version, sizeof(int)); // stream.write((char*) &version, sizeof(int));
// double time = cu.getTime(); // double time = cu.getTime();
...@@ -292,6 +299,7 @@ void CudaUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostream& ...@@ -292,6 +299,7 @@ void CudaUpdateStateDataKernel::createCheckpoint(ContextImpl& context, ostream&
} }
void CudaUpdateStateDataKernel::loadCheckpoint(ContextImpl& context, istream& stream) { void CudaUpdateStateDataKernel::loadCheckpoint(ContextImpl& context, istream& stream) {
cuCtxSetCurrent(cu.getContext());
// int version; // int version;
// stream.read((char*) &version, sizeof(int)); // stream.read((char*) &version, sizeof(int));
// if (version != 1) // if (version != 1)
...@@ -566,90 +574,90 @@ void CudaCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& conte ...@@ -566,90 +574,90 @@ void CudaCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& conte
// //
// cu.invalidateMolecules(); // cu.invalidateMolecules();
//} //}
//
//class CudaHarmonicAngleForceInfo : public CudaForceInfo { class CudaHarmonicAngleForceInfo : public CudaForceInfo {
//public: public:
// CudaHarmonicAngleForceInfo(const HarmonicAngleForce& force) : CudaForceInfo(0), force(force) { CudaHarmonicAngleForceInfo(const HarmonicAngleForce& force) : force(force) {
// } }
// int getNumParticleGroups() { int getNumParticleGroups() {
// return force.getNumAngles(); return force.getNumAngles();
// } }
// void getParticlesInGroup(int index, vector<int>& particles) { void getParticlesInGroup(int index, vector<int>& particles) {
// int particle1, particle2, particle3; int particle1, particle2, particle3;
// double angle, k; double angle, k;
// force.getAngleParameters(index, particle1, particle2, particle3, angle, k); force.getAngleParameters(index, particle1, particle2, particle3, angle, k);
// particles.resize(3); particles.resize(3);
// particles[0] = particle1; particles[0] = particle1;
// particles[1] = particle2; particles[1] = particle2;
// particles[2] = particle3; particles[2] = particle3;
// } }
// bool areGroupsIdentical(int group1, int group2) { bool areGroupsIdentical(int group1, int group2) {
// int particle1, particle2, particle3; int particle1, particle2, particle3;
// double angle1, angle2, k1, k2; double angle1, angle2, k1, k2;
// force.getAngleParameters(group1, particle1, particle2, particle3, angle1, k1); force.getAngleParameters(group1, particle1, particle2, particle3, angle1, k1);
// force.getAngleParameters(group2, particle1, particle2, particle3, angle2, k2); force.getAngleParameters(group2, particle1, particle2, particle3, angle2, k2);
// return (angle1 == angle2 && k1 == k2); return (angle1 == angle2 && k1 == k2);
// } }
//private: private:
// const HarmonicAngleForce& force; const HarmonicAngleForce& force;
//}; };
//
//CudaCalcHarmonicAngleForceKernel::~CudaCalcHarmonicAngleForceKernel() { CudaCalcHarmonicAngleForceKernel::~CudaCalcHarmonicAngleForceKernel() {
// if (params != NULL) if (params != NULL)
// delete params; delete params;
//} }
//
//void CudaCalcHarmonicAngleForceKernel::initialize(const System& system, const HarmonicAngleForce& force) { void CudaCalcHarmonicAngleForceKernel::initialize(const System& system, const HarmonicAngleForce& force) {
// int numContexts = cu.getPlatformData().contexts.size(); int numContexts = cu.getPlatformData().contexts.size();
// int startIndex = cu.getContextIndex()*force.getNumAngles()/numContexts; int startIndex = cu.getContextIndex()*force.getNumAngles()/numContexts;
// int endIndex = (cu.getContextIndex()+1)*force.getNumAngles()/numContexts; int endIndex = (cu.getContextIndex()+1)*force.getNumAngles()/numContexts;
// numAngles = endIndex-startIndex; numAngles = endIndex-startIndex;
// if (numAngles == 0) if (numAngles == 0)
// return; return;
// vector<vector<int> > atoms(numAngles, vector<int>(3)); vector<vector<int> > atoms(numAngles, vector<int>(3));
// params = new CudaArray<mm_float2>(cu, numAngles, "angleParams"); params = CudaArray::create<float2>(numAngles, "angleParams");
// vector<mm_float2> paramVector(numAngles); vector<float2> paramVector(numAngles);
// for (int i = 0; i < numAngles; i++) { for (int i = 0; i < numAngles; i++) {
// double angle, k; double angle, k;
// force.getAngleParameters(startIndex+i, atoms[i][0], atoms[i][1], atoms[i][2], angle, k); force.getAngleParameters(startIndex+i, atoms[i][0], atoms[i][1], atoms[i][2], angle, k);
// paramVector[i] = mm_float2((cl_float) angle, (cl_float) k); paramVector[i] = make_float2((float) angle, (float) k);
//
// } }
// params->upload(paramVector); params->upload(paramVector);
// map<string, string> replacements; map<string, string> replacements;
// replacements["COMPUTE_FORCE"] = CudaKernelSources::harmonicAngleForce; replacements["COMPUTE_FORCE"] = CudaKernelSources::harmonicAngleForce;
// replacements["PARAMS"] = cu.getBondedUtilities().addArgument(params->getDeviceBuffer(), "float2"); replacements["PARAMS"] = cu.getBondedUtilities().addArgument(params->getDevicePointer(), "float2");
// cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::angleForce, replacements), force.getForceGroup()); cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::angleForce, replacements), force.getForceGroup());
// cu.addForce(new CudaHarmonicAngleForceInfo(force)); cu.addForce(new CudaHarmonicAngleForceInfo(force));
//} }
//
//double CudaCalcHarmonicAngleForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { double CudaCalcHarmonicAngleForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) {
// return 0.0; return 0.0;
//} }
//
//void CudaCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force) { void CudaCalcHarmonicAngleForceKernel::copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force) {
// int numContexts = cu.getPlatformData().contexts.size(); int numContexts = cu.getPlatformData().contexts.size();
// int startIndex = cu.getContextIndex()*force.getNumAngles()/numContexts; int startIndex = cu.getContextIndex()*force.getNumAngles()/numContexts;
// int endIndex = (cu.getContextIndex()+1)*force.getNumAngles()/numContexts; int endIndex = (cu.getContextIndex()+1)*force.getNumAngles()/numContexts;
// if (numAngles != endIndex-startIndex) if (numAngles != endIndex-startIndex)
// throw OpenMMException("updateParametersInContext: The number of angles has changed"); throw OpenMMException("updateParametersInContext: The number of angles has changed");
//
// // Record the per-angle parameters. // Record the per-angle parameters.
//
// vector<mm_float2> paramVector(numAngles); vector<float2> paramVector(numAngles);
// for (int i = 0; i < numAngles; i++) { for (int i = 0; i < numAngles; i++) {
// int atom1, atom2, atom3; int atom1, atom2, atom3;
// double angle, k; double angle, k;
// force.getAngleParameters(startIndex+i, atom1, atom2, atom3, angle, k); force.getAngleParameters(startIndex+i, atom1, atom2, atom3, angle, k);
// paramVector[i] = mm_float2((cl_float) angle, (cl_float) k); paramVector[i] = make_float2((float) angle, (float) k);
// } }
// params->upload(paramVector); params->upload(paramVector);
//
// // Mark that the current reordering may be invalid. // Mark that the current reordering may be invalid.
//
// cu.invalidateMolecules(); cu.invalidateMolecules();
//} }
//
//class CudaCustomAngleForceInfo : public CudaForceInfo { //class CudaCustomAngleForceInfo : public CudaForceInfo {
//public: //public:
// CudaCustomAngleForceInfo(const CustomAngleForce& force) : CudaForceInfo(0), force(force) { // CudaCustomAngleForceInfo(const CustomAngleForce& force) : CudaForceInfo(0), force(force) {
...@@ -791,262 +799,272 @@ void CudaCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& conte ...@@ -791,262 +799,272 @@ void CudaCalcHarmonicBondForceKernel::copyParametersToContext(ContextImpl& conte
// //
// cu.invalidateMolecules(); // cu.invalidateMolecules();
//} //}
//
//class CudaPeriodicTorsionForceInfo : public CudaForceInfo { class CudaPeriodicTorsionForceInfo : public CudaForceInfo {
//public: public:
// CudaPeriodicTorsionForceInfo(const PeriodicTorsionForce& force) : CudaForceInfo(0), force(force) { CudaPeriodicTorsionForceInfo(const PeriodicTorsionForce& force) : force(force) {
// } }
// int getNumParticleGroups() { int getNumParticleGroups() {
// return force.getNumTorsions(); return force.getNumTorsions();
// } }
// void getParticlesInGroup(int index, vector<int>& particles) { void getParticlesInGroup(int index, vector<int>& particles) {
// int particle1, particle2, particle3, particle4, periodicity; int particle1, particle2, particle3, particle4, periodicity;
// double phase, k; double phase, k;
// force.getTorsionParameters(index, particle1, particle2, particle3, particle4, periodicity, phase, k); force.getTorsionParameters(index, particle1, particle2, particle3, particle4, periodicity, phase, k);
// particles.resize(4); particles.resize(4);
// particles[0] = particle1; particles[0] = particle1;
// particles[1] = particle2; particles[1] = particle2;
// particles[2] = particle3; particles[2] = particle3;
// particles[3] = particle4; particles[3] = particle4;
// } }
// bool areGroupsIdentical(int group1, int group2) { bool areGroupsIdentical(int group1, int group2) {
// int particle1, particle2, particle3, particle4, periodicity1, periodicity2; int particle1, particle2, particle3, particle4, periodicity1, periodicity2;
// double phase1, phase2, k1, k2; double phase1, phase2, k1, k2;
// force.getTorsionParameters(group1, particle1, particle2, particle3, particle4, periodicity1, phase1, k1); force.getTorsionParameters(group1, particle1, particle2, particle3, particle4, periodicity1, phase1, k1);
// force.getTorsionParameters(group2, particle1, particle2, particle3, particle4, periodicity2, phase2, k2); force.getTorsionParameters(group2, particle1, particle2, particle3, particle4, periodicity2, phase2, k2);
// return (periodicity1 == periodicity2 && phase1 == phase2 && k1 == k2); return (periodicity1 == periodicity2 && phase1 == phase2 && k1 == k2);
// } }
//private: private:
// const PeriodicTorsionForce& force; const PeriodicTorsionForce& force;
//}; };
//
//CudaCalcPeriodicTorsionForceKernel::~CudaCalcPeriodicTorsionForceKernel() { CudaCalcPeriodicTorsionForceKernel::~CudaCalcPeriodicTorsionForceKernel() {
// if (params != NULL) if (params != NULL)
// delete params; delete params;
//} }
//
//void CudaCalcPeriodicTorsionForceKernel::initialize(const System& system, const PeriodicTorsionForce& force) { void CudaCalcPeriodicTorsionForceKernel::initialize(const System& system, const PeriodicTorsionForce& force) {
// int numContexts = cu.getPlatformData().contexts.size(); int numContexts = cu.getPlatformData().contexts.size();
// int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts; int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts;
// int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts; int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts;
// numTorsions = endIndex-startIndex; numTorsions = endIndex-startIndex;
// if (numTorsions == 0) if (numTorsions == 0)
// return; return;
// vector<vector<int> > atoms(numTorsions, vector<int>(4)); vector<vector<int> > atoms(numTorsions, vector<int>(4));
// params = new CudaArray<mm_float4>(cu, numTorsions, "periodicTorsionParams"); params = CudaArray::create<float4>(numTorsions, "periodicTorsionParams");
// vector<mm_float4> paramVector(numTorsions); vector<float4> paramVector(numTorsions);
// for (int i = 0; i < numTorsions; i++) { for (int i = 0; i < numTorsions; i++) {
// int periodicity; int periodicity;
// double phase, k; double phase, k;
// force.getTorsionParameters(startIndex+i, atoms[i][0], atoms[i][1], atoms[i][2], atoms[i][3], periodicity, phase, k); force.getTorsionParameters(startIndex+i, atoms[i][0], atoms[i][1], atoms[i][2], atoms[i][3], periodicity, phase, k);
// paramVector[i] = mm_float4((cl_float) k, (cl_float) phase, (cl_float) periodicity, 0.0f); paramVector[i] = make_float4((float) k, (float) phase, (float) periodicity, 0.0f);
// } }
// params->upload(paramVector); params->upload(paramVector);
// map<string, string> replacements; map<string, string> replacements;
// replacements["COMPUTE_FORCE"] = CudaKernelSources::periodicTorsionForce; replacements["COMPUTE_FORCE"] = CudaKernelSources::periodicTorsionForce;
// replacements["PARAMS"] = cu.getBondedUtilities().addArgument(params->getDeviceBuffer(), "float4"); replacements["PARAMS"] = cu.getBondedUtilities().addArgument(params->getDevicePointer(), "float4");
// cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::torsionForce, replacements), force.getForceGroup()); cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::torsionForce, replacements), force.getForceGroup());
// cu.addForce(new CudaPeriodicTorsionForceInfo(force)); cu.addForce(new CudaPeriodicTorsionForceInfo(force));
//} }
//
//double CudaCalcPeriodicTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { double CudaCalcPeriodicTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) {
// return 0.0; return 0.0;
//} }
//
//void CudaCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force) { void CudaCalcPeriodicTorsionForceKernel::copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force) {
// int numContexts = cu.getPlatformData().contexts.size(); int numContexts = cu.getPlatformData().contexts.size();
// int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts; int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts;
// int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts; int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts;
// if (numTorsions != endIndex-startIndex) if (numTorsions != endIndex-startIndex)
// throw OpenMMException("updateParametersInContext: The number of torsions has changed"); throw OpenMMException("updateParametersInContext: The number of torsions has changed");
//
// // Record the per-torsion parameters. // Record the per-torsion parameters.
//
// vector<mm_float4> paramVector(numTorsions); vector<float4> paramVector(numTorsions);
// for (int i = 0; i < numTorsions; i++) { for (int i = 0; i < numTorsions; i++) {
// int atom1, atom2, atom3, atom4, periodicity; int atom1, atom2, atom3, atom4, periodicity;
// double phase, k; double phase, k;
// force.getTorsionParameters(startIndex+i, atom1, atom2, atom3, atom4, periodicity, phase, k); force.getTorsionParameters(startIndex+i, atom1, atom2, atom3, atom4, periodicity, phase, k);
// paramVector[i] = mm_float4((cl_float) k, (cl_float) phase, (cl_float) periodicity, 0.0f); paramVector[i] = make_float4((float) k, (float) phase, (float) periodicity, 0.0f);
// } }
// params->upload(paramVector); params->upload(paramVector);
//
// // Mark that the current reordering may be invalid. // Mark that the current reordering may be invalid.
//
// cu.invalidateMolecules(); cu.invalidateMolecules();
//} }
//
//class CudaRBTorsionForceInfo : public CudaForceInfo { class CudaRBTorsionForceInfo : public CudaForceInfo {
//public: public:
// CudaRBTorsionForceInfo(const RBTorsionForce& force) : CudaForceInfo(0), force(force) { CudaRBTorsionForceInfo(const RBTorsionForce& force) : force(force) {
// } }
// int getNumParticleGroups() { int getNumParticleGroups() {
// return force.getNumTorsions(); return force.getNumTorsions();
// } }
// void getParticlesInGroup(int index, vector<int>& particles) { void getParticlesInGroup(int index, vector<int>& particles) {
// int particle1, particle2, particle3, particle4; int particle1, particle2, particle3, particle4;
// double c0, c1, c2, c3, c4, c5; double c0, c1, c2, c3, c4, c5;
// force.getTorsionParameters(index, particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5); force.getTorsionParameters(index, particle1, particle2, particle3, particle4, c0, c1, c2, c3, c4, c5);
// particles.resize(4); particles.resize(4);
// particles[0] = particle1; particles[0] = particle1;
// particles[1] = particle2; particles[1] = particle2;
// particles[2] = particle3; particles[2] = particle3;
// particles[3] = particle4; particles[3] = particle4;
// } }
// bool areGroupsIdentical(int group1, int group2) { bool areGroupsIdentical(int group1, int group2) {
// int particle1, particle2, particle3, particle4; int particle1, particle2, particle3, particle4;
// double c0a, c0b, c1a, c1b, c2a, c2b, c3a, c3b, c4a, c4b, c5a, c5b; double c0a, c0b, c1a, c1b, c2a, c2b, c3a, c3b, c4a, c4b, c5a, c5b;
// force.getTorsionParameters(group1, particle1, particle2, particle3, particle4, c0a, c1a, c2a, c3a, c4a, c5a); force.getTorsionParameters(group1, particle1, particle2, particle3, particle4, c0a, c1a, c2a, c3a, c4a, c5a);
// force.getTorsionParameters(group2, particle1, particle2, particle3, particle4, c0b, c1b, c2b, c3b, c4b, c5b); force.getTorsionParameters(group2, particle1, particle2, particle3, particle4, c0b, c1b, c2b, c3b, c4b, c5b);
// return (c0a == c0b && c1a == c1b && c2a == c2b && c3a == c3b && c4a == c4b && c5a == c5b); return (c0a == c0b && c1a == c1b && c2a == c2b && c3a == c3b && c4a == c4b && c5a == c5b);
// } }
//private: private:
// const RBTorsionForce& force; const RBTorsionForce& force;
//}; };
//
//CudaCalcRBTorsionForceKernel::~CudaCalcRBTorsionForceKernel() { CudaCalcRBTorsionForceKernel::~CudaCalcRBTorsionForceKernel() {
// if (params != NULL) if (params1 != NULL)
// delete params; delete params1;
//} if (params2 != NULL)
// delete params2;
//void CudaCalcRBTorsionForceKernel::initialize(const System& system, const RBTorsionForce& force) { }
// int numContexts = cu.getPlatformData().contexts.size();
// int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts; void CudaCalcRBTorsionForceKernel::initialize(const System& system, const RBTorsionForce& force) {
// int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts; int numContexts = cu.getPlatformData().contexts.size();
// numTorsions = endIndex-startIndex; int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts;
// if (numTorsions == 0) int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts;
// return; numTorsions = endIndex-startIndex;
// vector<vector<int> > atoms(numTorsions, vector<int>(4)); if (numTorsions == 0)
// params = new CudaArray<mm_float8>(cu, numTorsions, "rbTorsionParams"); return;
// vector<mm_float8> paramVector(numTorsions); vector<vector<int> > atoms(numTorsions, vector<int>(4));
// for (int i = 0; i < numTorsions; i++) { params1 = CudaArray::create<float4>(numTorsions, "rbTorsionParams1");
// double c0, c1, c2, c3, c4, c5; params2 = CudaArray::create<float2>(numTorsions, "rbTorsionParams2");
// force.getTorsionParameters(startIndex+i, atoms[i][0], atoms[i][1], atoms[i][2], atoms[i][3], c0, c1, c2, c3, c4, c5); vector<float4> paramVector1(numTorsions);
// paramVector[i] = mm_float8((cl_float) c0, (cl_float) c1, (cl_float) c2, (cl_float) c3, (cl_float) c4, (cl_float) c5, 0.0f, 0.0f); vector<float2> paramVector2(numTorsions);
// for (int i = 0; i < numTorsions; i++) {
// } double c0, c1, c2, c3, c4, c5;
// params->upload(paramVector); force.getTorsionParameters(startIndex+i, atoms[i][0], atoms[i][1], atoms[i][2], atoms[i][3], c0, c1, c2, c3, c4, c5);
// map<string, string> replacements; paramVector1[i] = make_float4((float) c0, (float) c1, (float) c2, (float) c3);
// replacements["COMPUTE_FORCE"] = CudaKernelSources::rbTorsionForce; paramVector2[i] = make_float2((float) c4, (float) c5);
// replacements["PARAMS"] = cu.getBondedUtilities().addArgument(params->getDeviceBuffer(), "float8");
// cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::torsionForce, replacements), force.getForceGroup()); }
// cu.addForce(new CudaRBTorsionForceInfo(force)); params1->upload(paramVector1);
//} params2->upload(paramVector2);
// map<string, string> replacements;
//double CudaCalcRBTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { replacements["COMPUTE_FORCE"] = CudaKernelSources::rbTorsionForce;
// return 0.0; replacements["PARAMS1"] = cu.getBondedUtilities().addArgument(params1->getDevicePointer(), "float4");
//} replacements["PARAMS2"] = cu.getBondedUtilities().addArgument(params2->getDevicePointer(), "float2");
// cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::torsionForce, replacements), force.getForceGroup());
//void CudaCalcRBTorsionForceKernel::copyParametersToContext(ContextImpl& context, const RBTorsionForce& force) { cu.addForce(new CudaRBTorsionForceInfo(force));
// int numContexts = cu.getPlatformData().contexts.size(); }
// int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts;
// int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts; double CudaCalcRBTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) {
// if (numTorsions != endIndex-startIndex) return 0.0;
// throw OpenMMException("updateParametersInContext: The number of torsions has changed"); }
//
// // Record the per-torsion parameters. void CudaCalcRBTorsionForceKernel::copyParametersToContext(ContextImpl& context, const RBTorsionForce& force) {
// int numContexts = cu.getPlatformData().contexts.size();
// vector<mm_float8> paramVector(numTorsions); int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts;
// for (int i = 0; i < numTorsions; i++) { int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts;
// int atom1, atom2, atom3, atom4; if (numTorsions != endIndex-startIndex)
// double c0, c1, c2, c3, c4, c5; throw OpenMMException("updateParametersInContext: The number of torsions has changed");
// force.getTorsionParameters(startIndex+i, atom1, atom2, atom3, atom4, c0, c1, c2, c3, c4, c5);
// paramVector[i] = mm_float8((cl_float) c0, (cl_float) c1, (cl_float) c2, (cl_float) c3, (cl_float) c4, (cl_float) c5, 0.0f, 0.0f); // Record the per-torsion parameters.
// }
// params->upload(paramVector); vector<float4> paramVector1(numTorsions);
// vector<float2> paramVector2(numTorsions);
// // Mark that the current reordering may be invalid. for (int i = 0; i < numTorsions; i++) {
// int atom1, atom2, atom3, atom4;
// cu.invalidateMolecules(); double c0, c1, c2, c3, c4, c5;
//} force.getTorsionParameters(startIndex+i, atom1, atom2, atom3, atom4, c0, c1, c2, c3, c4, c5);
// paramVector1[i] = make_float4((float) c0, (float) c1, (float) c2, (float) c3);
//class CudaCMAPTorsionForceInfo : public CudaForceInfo { paramVector2[i] = make_float2((float) c4, (float) c5);
//public: }
// CudaCMAPTorsionForceInfo(const CMAPTorsionForce& force) : CudaForceInfo(0), force(force) { params1->upload(paramVector1);
// } params2->upload(paramVector2);
// int getNumParticleGroups() {
// return force.getNumTorsions(); // Mark that the current reordering may be invalid.
// }
// void getParticlesInGroup(int index, vector<int>& particles) { cu.invalidateMolecules();
// int map, a1, a2, a3, a4, b1, b2, b3, b4; }
// force.getTorsionParameters(index, map, a1, a2, a3, a4, b1, b2, b3, b4);
// particles.resize(8); class CudaCMAPTorsionForceInfo : public CudaForceInfo {
// particles[0] = a1; public:
// particles[1] = a2; CudaCMAPTorsionForceInfo(const CMAPTorsionForce& force) : force(force) {
// particles[2] = a3; }
// particles[3] = a4; int getNumParticleGroups() {
// particles[4] = b1; return force.getNumTorsions();
// particles[5] = b2; }
// particles[6] = b3; void getParticlesInGroup(int index, vector<int>& particles) {
// particles[7] = b4; int map, a1, a2, a3, a4, b1, b2, b3, b4;
// } force.getTorsionParameters(index, map, a1, a2, a3, a4, b1, b2, b3, b4);
// bool areGroupsIdentical(int group1, int group2) { particles.resize(8);
// int map1, map2, a1, a2, a3, a4, b1, b2, b3, b4; particles[0] = a1;
// force.getTorsionParameters(group1, map1, a1, a2, a3, a4, b1, b2, b3, b4); particles[1] = a2;
// force.getTorsionParameters(group2, map2, a1, a2, a3, a4, b1, b2, b3, b4); particles[2] = a3;
// return (map1 == map2); particles[3] = a4;
// } particles[4] = b1;
//private: particles[5] = b2;
// const CMAPTorsionForce& force; particles[6] = b3;
//}; particles[7] = b4;
// }
//CudaCalcCMAPTorsionForceKernel::~CudaCalcCMAPTorsionForceKernel() { bool areGroupsIdentical(int group1, int group2) {
// if (coefficients != NULL) int map1, map2, a1, a2, a3, a4, b1, b2, b3, b4;
// delete coefficients; force.getTorsionParameters(group1, map1, a1, a2, a3, a4, b1, b2, b3, b4);
// if (mapPositions != NULL) force.getTorsionParameters(group2, map2, a1, a2, a3, a4, b1, b2, b3, b4);
// delete mapPositions; return (map1 == map2);
// if (torsionMaps != NULL) }
// delete torsionMaps; private:
//} const CMAPTorsionForce& force;
// };
//void CudaCalcCMAPTorsionForceKernel::initialize(const System& system, const CMAPTorsionForce& force) {
// int numContexts = cu.getPlatformData().contexts.size(); CudaCalcCMAPTorsionForceKernel::~CudaCalcCMAPTorsionForceKernel() {
// int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts; if (coefficients != NULL)
// int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts; delete coefficients;
// numTorsions = endIndex-startIndex; if (mapPositions != NULL)
// if (numTorsions == 0) delete mapPositions;
// return; if (torsionMaps != NULL)
// int numMaps = force.getNumMaps(); delete torsionMaps;
// vector<mm_float4> coeffVec; }
// vector<mm_int2> mapPositionsVec(numMaps);
// vector<double> energy; void CudaCalcCMAPTorsionForceKernel::initialize(const System& system, const CMAPTorsionForce& force) {
// vector<vector<double> > c; int numContexts = cu.getPlatformData().contexts.size();
// int currentPosition = 0; int startIndex = cu.getContextIndex()*force.getNumTorsions()/numContexts;
// for (int i = 0; i < numMaps; i++) { int endIndex = (cu.getContextIndex()+1)*force.getNumTorsions()/numContexts;
// int size; numTorsions = endIndex-startIndex;
// force.getMapParameters(i, size, energy); if (numTorsions == 0)
// CMAPTorsionForceImpl::calcMapDerivatives(size, energy, c); return;
// mapPositionsVec[i] = mm_int2(currentPosition, size); int numMaps = force.getNumMaps();
// currentPosition += 4*size*size; vector<float4> coeffVec;
// for (int j = 0; j < size*size; j++) { vector<int2> mapPositionsVec(numMaps);
// coeffVec.push_back(mm_float4((float) c[j][0], (float) c[j][1], (float) c[j][2], (float) c[j][3])); vector<double> energy;
// coeffVec.push_back(mm_float4((float) c[j][4], (float) c[j][5], (float) c[j][6], (float) c[j][7])); vector<vector<double> > c;
// coeffVec.push_back(mm_float4((float) c[j][8], (float) c[j][9], (float) c[j][10], (float) c[j][11])); int currentPosition = 0;
// coeffVec.push_back(mm_float4((float) c[j][12], (float) c[j][13], (float) c[j][14], (float) c[j][15])); for (int i = 0; i < numMaps; i++) {
// } int size;
// } force.getMapParameters(i, size, energy);
// vector<vector<int> > atoms(numTorsions, vector<int>(8)); CMAPTorsionForceImpl::calcMapDerivatives(size, energy, c);
// vector<cl_int> torsionMapsVec(numTorsions); mapPositionsVec[i] = make_int2(currentPosition, size);
// for (int i = 0; i < numTorsions; i++) currentPosition += 4*size*size;
// force.getTorsionParameters(startIndex+i, torsionMapsVec[i], atoms[i][0], atoms[i][1], atoms[i][2], atoms[i][3], atoms[i][4], atoms[i][5], atoms[i][6], atoms[i][7]); for (int j = 0; j < size*size; j++) {
// coefficients = new CudaArray<mm_float4>(cu, coeffVec.size(), "cmapTorsionCoefficients"); coeffVec.push_back(make_float4((float) c[j][0], (float) c[j][1], (float) c[j][2], (float) c[j][3]));
// mapPositions = new CudaArray<mm_int2>(cu, numMaps, "cmapTorsionMapPositions"); coeffVec.push_back(make_float4((float) c[j][4], (float) c[j][5], (float) c[j][6], (float) c[j][7]));
// torsionMaps = new CudaArray<cl_int>(cu, numTorsions, "cmapTorsionMaps"); coeffVec.push_back(make_float4((float) c[j][8], (float) c[j][9], (float) c[j][10], (float) c[j][11]));
// coefficients->upload(coeffVec); coeffVec.push_back(make_float4((float) c[j][12], (float) c[j][13], (float) c[j][14], (float) c[j][15]));
// mapPositions->upload(mapPositionsVec); }
// torsionMaps->upload(torsionMapsVec); }
// map<string, string> replacements; vector<vector<int> > atoms(numTorsions, vector<int>(8));
// replacements["COEFF"] = cu.getBondedUtilities().addArgument(coefficients->getDeviceBuffer(), "float4"); vector<int> torsionMapsVec(numTorsions);
// replacements["MAP_POS"] = cu.getBondedUtilities().addArgument(mapPositions->getDeviceBuffer(), "int2"); for (int i = 0; i < numTorsions; i++)
// replacements["MAPS"] = cu.getBondedUtilities().addArgument(torsionMaps->getDeviceBuffer(), "int"); force.getTorsionParameters(startIndex+i, torsionMapsVec[i], atoms[i][0], atoms[i][1], atoms[i][2], atoms[i][3], atoms[i][4], atoms[i][5], atoms[i][6], atoms[i][7]);
// cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::cmapTorsionForce, replacements), force.getForceGroup()); coefficients = CudaArray::create<float4>(coeffVec.size(), "cmapTorsionCoefficients");
// cu.addForce(new CudaCMAPTorsionForceInfo(force)); mapPositions = CudaArray::create<int2>(numMaps, "cmapTorsionMapPositions");
//} torsionMaps = CudaArray::create<int>(numTorsions, "cmapTorsionMaps");
// coefficients->upload(coeffVec);
//double CudaCalcCMAPTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) { mapPositions->upload(mapPositionsVec);
// return 0.0; torsionMaps->upload(torsionMapsVec);
//} map<string, string> replacements;
// replacements["COEFF"] = cu.getBondedUtilities().addArgument(coefficients->getDevicePointer(), "float4");
replacements["MAP_POS"] = cu.getBondedUtilities().addArgument(mapPositions->getDevicePointer(), "int2");
replacements["MAPS"] = cu.getBondedUtilities().addArgument(torsionMaps->getDevicePointer(), "int");
cu.getBondedUtilities().addInteraction(atoms, cu.replaceStrings(CudaKernelSources::cmapTorsionForce, replacements), force.getForceGroup());
cu.addForce(new CudaCMAPTorsionForceInfo(force));
}
double CudaCalcCMAPTorsionForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) {
return 0.0;
}
//class CudaCustomTorsionForceInfo : public CudaForceInfo { //class CudaCustomTorsionForceInfo : public CudaForceInfo {
//public: //public:
// CudaCustomTorsionForceInfo(const CustomTorsionForce& force) : CudaForceInfo(0), force(force) { // CudaCustomTorsionForceInfo(const CustomTorsionForce& force) : CudaForceInfo(0), force(force) {
......
...@@ -299,47 +299,47 @@ private: ...@@ -299,47 +299,47 @@ private:
// std::vector<std::string> globalParamNames; // std::vector<std::string> globalParamNames;
// std::vector<cl_float> globalParamValues; // std::vector<cl_float> globalParamValues;
//}; //};
//
///** /**
// * This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system. * This kernel is invoked by HarmonicAngleForce to calculate the forces acting on the system and the energy of the system.
// */ */
//class CudaCalcHarmonicAngleForceKernel : public CalcHarmonicAngleForceKernel { class CudaCalcHarmonicAngleForceKernel : public CalcHarmonicAngleForceKernel {
//public: public:
// CudaCalcHarmonicAngleForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcHarmonicAngleForceKernel(name, platform), CudaCalcHarmonicAngleForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcHarmonicAngleForceKernel(name, platform),
// hasInitializedKernel(false), cu(cu), system(system), params(NULL) { hasInitializedKernel(false), cu(cu), system(system), params(NULL) {
// } }
// ~CudaCalcHarmonicAngleForceKernel(); ~CudaCalcHarmonicAngleForceKernel();
// /** /**
// * 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 force the HarmonicAngleForce this kernel will be used for * @param force the HarmonicAngleForce this kernel will be used for
// */ */
// void initialize(const System& system, const HarmonicAngleForce& force); void initialize(const System& system, const HarmonicAngleForce& force);
// /** /**
// * Execute the kernel to calculate the forces and/or energy. * Execute the kernel to calculate the forces and/or energy.
// * *
// * @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
// * @param includeForces true if forces should be calculated * @param includeForces true if forces should be calculated
// * @param includeEnergy true if the energy should be calculated * @param includeEnergy true if the energy should be calculated
// * @return the potential energy due to the force * @return the potential energy due to the force
// */ */
// double execute(ContextImpl& context, bool includeForces, bool includeEnergy); double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
// /** /**
// * Copy changed parameters over to a context. * Copy changed parameters over to a context.
// * *
// * @param context the context to copy parameters to * @param context the context to copy parameters to
// * @param force the HarmonicAngleForce to copy the parameters from * @param force the HarmonicAngleForce to copy the parameters from
// */ */
// void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force); void copyParametersToContext(ContextImpl& context, const HarmonicAngleForce& force);
//private: private:
// int numAngles; int numAngles;
// bool hasInitializedKernel; bool hasInitializedKernel;
// CudaContext& cu; CudaContext& cu;
// System& system; System& system;
// CudaArray<mm_float2>* params; CudaArray* params;
//}; };
//
///** ///**
// * This kernel is invoked by CustomAngleForce to calculate the forces acting on the system and the energy of the system. // * This kernel is invoked by CustomAngleForce to calculate the forces acting on the system and the energy of the system.
// */ // */
...@@ -382,122 +382,123 @@ private: ...@@ -382,122 +382,123 @@ private:
// std::vector<std::string> globalParamNames; // std::vector<std::string> globalParamNames;
// std::vector<cl_float> globalParamValues; // std::vector<cl_float> globalParamValues;
//}; //};
//
///** /**
// * This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system. * This kernel is invoked by PeriodicTorsionForce to calculate the forces acting on the system and the energy of the system.
// */ */
//class CudaCalcPeriodicTorsionForceKernel : public CalcPeriodicTorsionForceKernel { class CudaCalcPeriodicTorsionForceKernel : public CalcPeriodicTorsionForceKernel {
//public: public:
// CudaCalcPeriodicTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcPeriodicTorsionForceKernel(name, platform), CudaCalcPeriodicTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcPeriodicTorsionForceKernel(name, platform),
// hasInitializedKernel(false), cu(cu), system(system), params(NULL) { hasInitializedKernel(false), cu(cu), system(system), params(NULL) {
// } }
// ~CudaCalcPeriodicTorsionForceKernel(); ~CudaCalcPeriodicTorsionForceKernel();
// /** /**
// * 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 force the PeriodicTorsionForce this kernel will be used for * @param force the PeriodicTorsionForce this kernel will be used for
// */ */
// void initialize(const System& system, const PeriodicTorsionForce& force); void initialize(const System& system, const PeriodicTorsionForce& force);
// /** /**
// * Execute the kernel to calculate the forces and/or energy. * Execute the kernel to calculate the forces and/or energy.
// * *
// * @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
// * @param includeForces true if forces should be calculated * @param includeForces true if forces should be calculated
// * @param includeEnergy true if the energy should be calculated * @param includeEnergy true if the energy should be calculated
// * @return the potential energy due to the force * @return the potential energy due to the force
// */ */
// double execute(ContextImpl& context, bool includeForces, bool includeEnergy); double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
// /** /**
// * Copy changed parameters over to a context. * Copy changed parameters over to a context.
// * *
// * @param context the context to copy parameters to * @param context the context to copy parameters to
// * @param force the PeriodicTorsionForce to copy the parameters from * @param force the PeriodicTorsionForce to copy the parameters from
// */ */
// void copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force); void copyParametersToContext(ContextImpl& context, const PeriodicTorsionForce& force);
//private: private:
// int numTorsions; int numTorsions;
// bool hasInitializedKernel; bool hasInitializedKernel;
// CudaContext& cu; CudaContext& cu;
// System& system; System& system;
// CudaArray<mm_float4>* params; CudaArray* params;
//}; };
//
///** /**
// * This kernel is invoked by RBTorsionForce to calculate the forces acting on the system and the energy of the system. * This kernel is invoked by RBTorsionForce to calculate the forces acting on the system and the energy of the system.
// */ */
//class CudaCalcRBTorsionForceKernel : public CalcRBTorsionForceKernel { class CudaCalcRBTorsionForceKernel : public CalcRBTorsionForceKernel {
//public: public:
// CudaCalcRBTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcRBTorsionForceKernel(name, platform), CudaCalcRBTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcRBTorsionForceKernel(name, platform),
// hasInitializedKernel(false), cu(cu), system(system), params(NULL) { hasInitializedKernel(false), cu(cu), system(system), params1(NULL), params2(NULL) {
// } }
// ~CudaCalcRBTorsionForceKernel(); ~CudaCalcRBTorsionForceKernel();
// /** /**
// * 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 force the RBTorsionForce this kernel will be used for * @param force the RBTorsionForce this kernel will be used for
// */ */
// void initialize(const System& system, const RBTorsionForce& force); void initialize(const System& system, const RBTorsionForce& force);
// /** /**
// * Execute the kernel to calculate the forces and/or energy. * Execute the kernel to calculate the forces and/or energy.
// * *
// * @param context the context in which to execute this kernel * @param context the context in which to execute this kernel
// * @param includeForces true if forces should be calculated * @param includeForces true if forces should be calculated
// * @param includeEnergy true if the energy should be calculated * @param includeEnergy true if the energy should be calculated
// * @return the potential energy due to the force * @return the potential energy due to the force
// */ */
// double execute(ContextImpl& context, bool includeForces, bool includeEnergy); double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
// /** /**
// * Copy changed parameters over to a context. * Copy changed parameters over to a context.
// * *
// * @param context the context to copy parameters to * @param context the context to copy parameters to
// * @param force the RBTorsionForce to copy the parameters from * @param force the RBTorsionForce to copy the parameters from
// */ */
// void copyParametersToContext(ContextImpl& context, const RBTorsionForce& force); void copyParametersToContext(ContextImpl& context, const RBTorsionForce& force);
//private: private:
// int numTorsions; int numTorsions;
// bool hasInitializedKernel; bool hasInitializedKernel;
// CudaContext& cu; CudaContext& cu;
// System& system; System& system;
// CudaArray<mm_float8>* params; CudaArray* params1;
//}; CudaArray* params2;
// };
///**
// * This kernel is invoked by CMAPTorsionForce to calculate the forces acting on the system and the energy of the system. /**
// */ * This kernel is invoked by CMAPTorsionForce to calculate the forces acting on the system and the energy of the system.
//class CudaCalcCMAPTorsionForceKernel : public CalcCMAPTorsionForceKernel { */
//public: class CudaCalcCMAPTorsionForceKernel : public CalcCMAPTorsionForceKernel {
// CudaCalcCMAPTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcCMAPTorsionForceKernel(name, platform), public:
// hasInitializedKernel(false), cu(cu), system(system), coefficients(NULL), mapPositions(NULL), torsionMaps(NULL) { CudaCalcCMAPTorsionForceKernel(std::string name, const Platform& platform, CudaContext& cu, System& system) : CalcCMAPTorsionForceKernel(name, platform),
// } hasInitializedKernel(false), cu(cu), system(system), coefficients(NULL), mapPositions(NULL), torsionMaps(NULL) {
// ~CudaCalcCMAPTorsionForceKernel(); }
// /** ~CudaCalcCMAPTorsionForceKernel();
// * Initialize the kernel. /**
// * * Initialize the kernel.
// * @param system the System this kernel will be applied to *
// * @param force the CMAPTorsionForce this kernel will be used for * @param system the System this kernel will be applied to
// */ * @param force the CMAPTorsionForce this kernel will be used for
// void initialize(const System& system, const CMAPTorsionForce& force); */
// /** void initialize(const System& system, const CMAPTorsionForce& force);
// * Execute the kernel to calculate the forces and/or energy. /**
// * * Execute the kernel to calculate the forces and/or energy.
// * @param context the context in which to execute this kernel *
// * @param includeForces true if forces should be calculated * @param context the context in which to execute this kernel
// * @param includeEnergy true if the energy should be calculated * @param includeForces true if forces should be calculated
// * @return the potential energy due to the force * @param includeEnergy true if the energy should be calculated
// */ * @return the potential energy due to the force
// double execute(ContextImpl& context, bool includeForces, bool includeEnergy); */
//private: double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
// int numTorsions; private:
// bool hasInitializedKernel; int numTorsions;
// CudaContext& cu; bool hasInitializedKernel;
// System& system; CudaContext& cu;
// CudaArray<mm_float4>* coefficients; System& system;
// CudaArray<mm_int2>* mapPositions; CudaArray* coefficients;
// CudaArray<cl_int>* torsionMaps; CudaArray* mapPositions;
//}; CudaArray* torsionMaps;
// };
///** ///**
// * This kernel is invoked by CustomTorsionForce to calculate the forces acting on the system and the energy of the system. // * This kernel is invoked by CustomTorsionForce to calculate the forces acting on the system and the energy of the system.
// */ // */
......
real3 v0 = make_real3(pos2.x-pos1.x, pos2.y-pos1.y, pos2.z-pos1.z);
real3 v1 = make_real3(pos2.x-pos3.x, pos2.y-pos3.y, pos2.z-pos3.z);
real3 cp = cross(v0, v1);
real rp = cp.x*cp.x + cp.y*cp.y + cp.z*cp.z;
rp = max(SQRT(rp), (real) 1.0e-06f);
real r21 = v0.x*v0.x + v0.y*v0.y + v0.z*v0.z;
real r23 = v1.x*v1.x + v1.y*v1.y + v1.z*v1.z;
real dot = v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;
real cosine = min(max(dot*RSQRT(r21*r23), (real) -1), (real) 1);
real theta = ACOS(cosine);
COMPUTE_FORCE
real3 force1 = cross(v0, cp)*(dEdAngle/(r21*rp));
real3 force3 = cross(cp, v1)*(dEdAngle/(r23*rp));
real3 force2 = -force1-force3;
const real PI = (real) 3.14159265358979323846;
// Compute the first angle.
real3 v0a = make_real3(pos1.x-pos2.x, pos1.y-pos2.y, pos1.z-pos2.z);
real3 v1a = make_real3(pos3.x-pos2.x, pos3.y-pos2.y, pos3.z-pos2.z);
real3 v2a = make_real3(pos3.x-pos4.x, pos3.y-pos4.y, pos3.z-pos4.z);
real3 cp0a = cross(v0a, v1a);
real3 cp1a = cross(v1a, v2a);
real cosangle = dot(normalize(cp0a), normalize(cp1a));
real angleA;
if (cosangle > 0.99f || cosangle < -0.99f) {
// We're close to the singularity in acos(), so take the cross product and use asin() instead.
real3 cross_prod = cross(cp0a, cp1a);
real scale = dot(cp0a, cp0a)*dot(cp1a, cp1a);
angleA = ASIN(SQRT(dot(cross_prod, cross_prod)/scale));
if (cosangle < 0.0f)
angleA = PI-angleA;
}
else
angleA = ACOS(cosangle);
angleA = (dot(v0a, cp1a) >= 0 ? angleA : -angleA);
angleA = fmod(angleA+2.0f*PI, 2.0f*PI);
// Compute the second angle.
real3 v0b = make_real3(pos5.x-pos6.x, pos5.y-pos6.y, pos5.z-pos6.z);
real3 v1b = make_real3(pos7.x-pos6.x, pos7.y-pos6.y, pos7.z-pos6.z);
real3 v2b = make_real3(pos7.x-pos8.x, pos7.y-pos8.y, pos7.z-pos8.z);
real3 cp0b = cross(v0b, v1b);
real3 cp1b = cross(v1b, v2b);
cosangle = dot(normalize(cp0b), normalize(cp1b));
real angleB;
if (cosangle > 0.99f || cosangle < -0.99f) {
// We're close to the singularity in acos(), so take the cross product and use asin() instead.
real3 cross_prod = cross(cp0b, cp1b);
real scale = dot(cp0b, cp0b)*dot(cp1b, cp1b);
angleB = ASIN(SQRT(dot(cross_prod, cross_prod)/scale));
if (cosangle < 0.0f)
angleB = PI-angleB;
}
else
angleB = ACOS(cosangle);
angleB = (dot(v0b, cp1b) >= 0 ? angleB : -angleB);
angleB = fmod(angleB+2.0f*PI, 2.0f*PI);
// Identify which patch this is in.
int2 pos = MAP_POS[MAPS[index]];
int size = pos.y;
real delta = 2*PI/size;
int s = (int) (angleA/delta);
int t = (int) (angleB/delta);
float4 c[4];
int coeffIndex = pos.x+4*(s+size*t);
c[0] = COEFF[coeffIndex];
c[1] = COEFF[coeffIndex+1];
c[2] = COEFF[coeffIndex+2];
c[3] = COEFF[coeffIndex+3];
real da = angleA/delta-s;
real db = angleB/delta-t;
// Evaluate the spline to determine the energy and gradients.
real torsionEnergy = 0.0f;
real dEdA = 0.0f;
real dEdB = 0.0f;
torsionEnergy = da*torsionEnergy + ((c[3].w*db + c[3].z)*db + c[3].y)*db + c[3].x;
dEdA = db*dEdA + (3.0f*c[3].w*da + 2.0f*c[2].w)*da + c[1].w;
dEdB = da*dEdB + (3.0f*c[3].w*db + 2.0f*c[3].z)*db + c[3].y;
torsionEnergy = da*torsionEnergy + ((c[2].w*db + c[2].z)*db + c[2].y)*db + c[2].x;
dEdA = db*dEdA + (3.0f*c[3].z*da + 2.0f*c[2].z)*da + c[1].z;
dEdB = da*dEdB + (3.0f*c[2].w*db + 2.0f*c[2].z)*db + c[2].y;
torsionEnergy = da*torsionEnergy + ((c[1].w*db + c[1].z)*db + c[1].y)*db + c[1].x;
dEdA = db*dEdA + (3.0f*c[3].y*da + 2.0f*c[2].y)*da + c[1].y;
dEdB = da*dEdB + (3.0f*c[1].w*db + 2.0f*c[1].z)*db + c[1].y;
torsionEnergy = da*torsionEnergy + ((c[0].w*db + c[0].z)*db + c[0].y)*db + c[0].x;
dEdA = db*dEdA + (3.0f*c[3].x*da + 2.0f*c[2].x)*da + c[1].x;
dEdB = da*dEdB + (3.0f*c[0].w*db + 2.0f*c[0].z)*db + c[0].y;
dEdA /= delta;
dEdB /= delta;
energy += torsionEnergy;
// Apply the force to the first torsion.
real normCross1 = dot(cp0a, cp0a);
real normSqrBC = dot(v1a, v1a);
real normBC = SQRT(normSqrBC);
real normCross2 = dot(cp1a, cp1a);
real dp = RECIP(normSqrBC);
real4 ff = make_real4((-dEdA*normBC)/normCross1, dot(v0a, v1a)*dp, dot(v2a, v1a)*dp, (dEdA*normBC)/normCross2);
real3 force1 = ff.x*cp0a;
real3 force4 = ff.w*cp1a;
real3 d = ff.y*force1 - ff.z*force4;
real3 force2 = d-force1;
real3 force3 = -d-force4;
// Apply the force to the second torsion.
normCross1 = dot(cp0b, cp0b);
normSqrBC = dot(v1b, v1b);
normBC = SQRT(normSqrBC);
normCross2 = dot(cp1b, cp1b);
dp = RECIP(normSqrBC);
ff = make_real4((-dEdB*normBC)/normCross1, dot(v0b, v1b)*dp, dot(v2b, v1b)*dp, (dEdB*normBC)/normCross2);
real3 force5 = ff.x*cp0b;
real3 force8 = ff.w*cp1b;
d = ff.y*force5 - ff.z*force8;
real3 force6 = d-force5;
real3 force7 = -d-force8;
float2 angleParams = PARAMS[index];
real deltaIdeal = theta-angleParams.x;
energy += 0.5f*angleParams.y*deltaIdeal*deltaIdeal;
real dEdAngle = angleParams.y*deltaIdeal;
real4 torsionParams = PARAMS[index];
real deltaAngle = torsionParams.z*theta-torsionParams.y;
energy += torsionParams.x*(1.0f+COS(deltaAngle));
real sinDeltaAngle = SIN(deltaAngle);
real dEdAngle = -torsionParams.x*torsionParams.z*sinDeltaAngle;
real4 torsionParams1 = PARAMS1[index];
real2 torsionParams2 = PARAMS2[index];
if (theta < 0)
theta += PI;
else
theta -= PI;
cosangle = -cosangle;
real cosFactor = cosangle;
real dEdAngle = -torsionParams1.y;
real rbEnergy = torsionParams1.x;
rbEnergy += torsionParams1.y*cosFactor;
dEdAngle -= 2.0f*torsionParams1.z*cosFactor;
cosFactor *= cosangle;
dEdAngle -= 3.0f*torsionParams1.w*cosFactor;
rbEnergy += torsionParams1.z*cosFactor;
cosFactor *= cosangle;
dEdAngle -= 4.0f*torsionParams2.x*cosFactor;
rbEnergy += torsionParams1.w*cosFactor;
cosFactor *= cosangle;
dEdAngle -= 5.0f*torsionParams2.y*cosFactor;
rbEnergy += torsionParams2.x*cosFactor;
rbEnergy += torsionParams2.y*cosFactor*cosangle;
energy += rbEnergy;
dEdAngle *= SIN(theta);
const real PI = (real) 3.14159265358979323846;
real3 v0 = make_real3(pos1.x-pos2.x, pos1.y-pos2.y, pos1.z-pos2.z);
real3 v1 = make_real3(pos3.x-pos2.x, pos3.y-pos2.y, pos3.z-pos2.z);
real3 v2 = make_real3(pos3.x-pos4.x, pos3.y-pos4.y, pos3.z-pos4.z);
real3 cp0 = cross(v0, v1);
real3 cp1 = cross(v1, v2);
real cosangle = dot(normalize(cp0), normalize(cp1));
real theta;
if (cosangle > 0.99f || cosangle < -0.99f) {
// We're close to the singularity in acos(), so take the cross product and use asin() instead.
real3 cross_prod = cross(cp0, cp1);
real scale = dot(cp0, cp0)*dot(cp1, cp1);
theta = ASIN(SQRT(dot(cross_prod, cross_prod)/scale));
if (cosangle < 0)
theta = PI-theta;
}
else
theta = acos(cosangle);
theta = (dot(v0, cp1) >= 0 ? theta : -theta);
COMPUTE_FORCE
real normCross1 = dot(cp0, cp0);
real normSqrBC = dot(v1, v1);
real normBC = sqrt(normSqrBC);
real normCross2 = dot(cp1, cp1);
real dp = RECIP(normSqrBC);
real4 ff = make_real4((-dEdAngle*normBC)/normCross1, dot(v0, v1)*dp, dot(v2, v1)*dp, (dEdAngle*normBC)/normCross2);
real3 force1 = ff.x*cp0;
real3 force4 = ff.w*cp1;
real3 s = ff.y*force1 - ff.z*force4;
real3 force2 = s-force1;
real3 force3 = -s-force4;
...@@ -493,3 +493,57 @@ inline __device__ void operator*=(double3& a, double b) { ...@@ -493,3 +493,57 @@ inline __device__ void operator*=(double3& a, double b) {
inline __device__ void operator*=(double4& a, double b) { inline __device__ void operator*=(double4& a, double b) {
a.x *= b; a.y *= b; a.z *= b; a.w *= b; a.x *= b; a.y *= b; a.z *= b; a.w *= b;
} }
// Dot product
inline __device__ float dot(float3 a, float3 b) {
return a.x*b.x+a.y*b.y+a.z*b.z;
}
inline __device__ double dot(double3 a, double3 b) {
return a.x*b.x+a.y*b.y+a.z*b.z;
}
// Cross product
inline __device__ float3 cross(float3 a, float3 b) {
return make_float3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}
inline __device__ float3 cross(float4 a, float4 b) {
return make_float3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}
inline __device__ double3 cross(double3 a, double3 b) {
return make_double3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}
inline __device__ double3 cross(double4 a, double4 b) {
return make_double3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}
// Normalize a vector
inline __device__ float2 normalize(float2 a) {
return a*rsqrtf(a.x*a.x+a.y*a.y);
}
inline __device__ float3 normalize(float3 a) {
return a*rsqrtf(a.x*a.x+a.y*a.y+a.z*a.z);
}
inline __device__ float4 normalize(float4 a) {
return a*rsqrtf(a.x*a.x+a.y*a.y+a.z*a.z+a.w*a.w);
}
inline __device__ double2 normalize(double2 a) {
return a*rsqrt(a.x*a.x+a.y*a.y);
}
inline __device__ double3 normalize(double3 a) {
return a*rsqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}
inline __device__ double4 normalize(double4 a) {
return a*rsqrt(a.x*a.x+a.y*a.y+a.z*a.z+a.w*a.w);
}
/* -------------------------------------------------------------------------- *
* 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) 2010-2012 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 CMAPTorsionForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CudaPlatform.h"
#include "openmm/CMAPTorsionForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include "sfmt/SFMT.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testCMAPTorsions() {
const int mapSize = 36;
// Create two systems: one with a pair of periodic torsions, and one with a CMAP torsion
// that approximates the same force.
CudaPlatform platform;
System system1;
for (int i = 0; i < 5; i++)
system1.addParticle(1.0);
PeriodicTorsionForce* periodic = new PeriodicTorsionForce();
periodic->addTorsion(0, 1, 2, 3, 2, M_PI/4, 1.5);
periodic->addTorsion(1, 2, 3, 4, 3, M_PI/3, 2.0);
system1.addForce(periodic);
System system2;
for (int i = 0; i < 5; i++)
system2.addParticle(1.0);
CMAPTorsionForce* cmap = new CMAPTorsionForce();
vector<double> mapEnergy(mapSize*mapSize);
for (int i = 0; i < mapSize; i++) {
double angle1 = i*2*M_PI/mapSize;
double energy1 = 1.5*(1+cos(2*angle1-M_PI/4));
for (int j = 0; j < mapSize; j++) {
double angle2 = j*2*M_PI/mapSize;
double energy2 = 2.0*(1+cos(3*angle2-M_PI/3));
mapEnergy[i+j*mapSize] = energy1+energy2;
}
}
cmap->addMap(mapSize, mapEnergy);
cmap->addTorsion(0, 0, 1, 2, 3, 1, 2, 3, 4);
system2.addForce(cmap);
// Set the atoms in various positions, and verify that both systems give equal forces and energy.
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
vector<Vec3> positions(5);
VerletIntegrator integrator1(0.01);
VerletIntegrator integrator2(0.01);
Context c1(system1, integrator1, platform);
Context c2(system2, integrator2, platform);
for (int i = 0; i < 50; i++) {
for (int j = 0; j < (int) positions.size(); j++)
positions[j] = Vec3(5.0*genrand_real2(sfmt), 5.0*genrand_real2(sfmt), 5.0*genrand_real2(sfmt));
c1.setPositions(positions);
c2.setPositions(positions);
State s1 = c1.getState(State::Forces | State::Energy);
State s2 = c2.getState(State::Forces | State::Energy);
for (int i = 0; i < system1.getNumParticles(); i++)
ASSERT_EQUAL_VEC(s1.getForces()[i], s2.getForces()[i], 0.05);
ASSERT_EQUAL_TOL(s1.getPotentialEnergy(), s2.getPotentialEnergy(), 1e-3);
}
}
int main() {
try {
testCMAPTorsions();
}
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-2012 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 HarmonicAngleForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CudaPlatform.h"
#include "openmm/HarmonicAngleForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testAngles() {
CudaPlatform platform;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
VerletIntegrator integrator(0.01);
HarmonicAngleForce* forceField = new HarmonicAngleForce();
forceField->addAngle(0, 1, 2, PI_M/3, 1.1);
forceField->addAngle(1, 2, 3, PI_M/2, 1.2);
system.addForce(forceField);
Context context(system, integrator, platform);
vector<Vec3> positions(4);
positions[0] = Vec3(0, 1, 0);
positions[1] = Vec3(0, 0, 0);
positions[2] = Vec3(1, 0, 0);
positions[3] = Vec3(2, 1, 0);
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
{
const vector<Vec3>& forces = state.getForces();
double torque1 = 1.1*PI_M/6;
double torque2 = 1.2*PI_M/4;
ASSERT_EQUAL_VEC(Vec3(torque1, 0, 0), forces[0], TOL);
ASSERT_EQUAL_VEC(Vec3(-0.5*torque2, 0.5*torque2, 0), forces[3], TOL); // reduced by sqrt(2) due to the bond length, another sqrt(2) due to the angle
ASSERT_EQUAL_VEC(Vec3(forces[0][0]+forces[1][0]+forces[2][0]+forces[3][0], forces[0][1]+forces[1][1]+forces[2][1]+forces[3][1], forces[0][2]+forces[1][2]+forces[2][2]+forces[3][2]), Vec3(0, 0, 0), TOL);
ASSERT_EQUAL_TOL(0.5*1.1*(PI_M/6)*(PI_M/6) + 0.5*1.2*(PI_M/4)*(PI_M/4), state.getPotentialEnergy(), TOL);
}
// Try changing the angle parameters and make sure it's still correct.
forceField->setAngleParameters(0, 0, 1, 2, PI_M/3.1, 1.3);
forceField->setAngleParameters(1, 1, 2, 3, PI_M/2.1, 1.4);
forceField->updateParametersInContext(context);
state = context.getState(State::Forces | State::Energy);
{
const vector<Vec3>& forces = state.getForces();
double dtheta1 = (PI_M/2)-(PI_M/3.1);
double dtheta2 = (3*PI_M/4)-(PI_M/2.1);
double torque1 = 1.3*dtheta1;
double torque2 = 1.4*dtheta2;
ASSERT_EQUAL_VEC(Vec3(torque1, 0, 0), forces[0], TOL);
ASSERT_EQUAL_VEC(Vec3(-0.5*torque2, 0.5*torque2, 0), forces[3], TOL); // reduced by sqrt(2) due to the bond length, another sqrt(2) due to the angle
ASSERT_EQUAL_VEC(Vec3(forces[0][0]+forces[1][0]+forces[2][0]+forces[3][0], forces[0][1]+forces[1][1]+forces[2][1]+forces[3][1], forces[0][2]+forces[1][2]+forces[2][2]+forces[3][2]), Vec3(0, 0, 0), TOL);
ASSERT_EQUAL_TOL(0.5*1.3*dtheta1*dtheta1 + 0.5*1.4*dtheta2*dtheta2, state.getPotentialEnergy(), TOL);
}
}
void testParallelComputation() {
CudaPlatform platform;
System system;
const int numParticles = 200;
for (int i = 0; i < numParticles; i++)
system.addParticle(1.0);
HarmonicAngleForce* force = new HarmonicAngleForce();
for (int i = 2; i < numParticles; i++)
force->addAngle(i-2, i-1, i, 1.1, i);
system.addForce(force);
vector<Vec3> positions(numParticles);
for (int i = 0; i < numParticles; i++)
positions[i] = Vec3(i, i%2, 0);
VerletIntegrator integrator1(0.01);
Context context1(system, integrator1, platform);
context1.setPositions(positions);
State state1 = context1.getState(State::Forces | State::Energy);
VerletIntegrator integrator2(0.01);
string deviceIndex = platform.getPropertyValue(context1, CudaPlatform::CudaDeviceIndex());
map<string, string> props;
props[CudaPlatform::CudaDeviceIndex()] = deviceIndex+","+deviceIndex;
Context context2(system, integrator2, platform, props);
context2.setPositions(positions);
State state2 = context2.getState(State::Forces | State::Energy);
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
}
int main() {
try {
testAngles();
// testParallelComputation();
}
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-2012 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 PeriodicTorsionForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CudaPlatform.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testPeriodicTorsions() {
CudaPlatform platform;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
VerletIntegrator integrator(0.01);
PeriodicTorsionForce* forceField = new PeriodicTorsionForce();
forceField->addTorsion(0, 1, 2, 3, 2, PI_M/3, 1.1);
system.addForce(forceField);
Context context(system, integrator, platform);
vector<Vec3> positions(4);
positions[0] = Vec3(0, 1, 0);
positions[1] = Vec3(0, 0, 0);
positions[2] = Vec3(1, 0, 0);
positions[3] = Vec3(1, 0, 2);
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
{
const vector<Vec3>& forces = state.getForces();
double torque = -2*1.1*std::sin(2*PI_M/3);
ASSERT_EQUAL_VEC(Vec3(0, 0, torque), forces[0], TOL);
ASSERT_EQUAL_VEC(Vec3(0, 0.5*torque, 0), forces[3], TOL);
ASSERT_EQUAL_VEC(Vec3(forces[0][0]+forces[1][0]+forces[2][0]+forces[3][0], forces[0][1]+forces[1][1]+forces[2][1]+forces[3][1], forces[0][2]+forces[1][2]+forces[2][2]+forces[3][2]), Vec3(0, 0, 0), TOL);
ASSERT_EQUAL_TOL(1.1*(1+std::cos(2*PI_M/3)), state.getPotentialEnergy(), TOL);
}
// Try changing the torsion parameters and make sure it's still correct.
forceField->setTorsionParameters(0, 0, 1, 2, 3, 3, PI_M/3.2, 1.3);
forceField->updateParametersInContext(context);
state = context.getState(State::Forces | State::Energy);
{
const vector<Vec3>& forces = state.getForces();
double dtheta = (3*PI_M/2)-(PI_M/3.2);
double torque = -3*1.3*std::sin(dtheta);
ASSERT_EQUAL_VEC(Vec3(0, 0, torque), forces[0], TOL);
ASSERT_EQUAL_VEC(Vec3(0, 0.5*torque, 0), forces[3], TOL);
ASSERT_EQUAL_VEC(Vec3(forces[0][0]+forces[1][0]+forces[2][0]+forces[3][0], forces[0][1]+forces[1][1]+forces[2][1]+forces[3][1], forces[0][2]+forces[1][2]+forces[2][2]+forces[3][2]), Vec3(0, 0, 0), TOL);
ASSERT_EQUAL_TOL(1.3*(1+std::cos(dtheta)), state.getPotentialEnergy(), TOL);
}
}
void testParallelComputation() {
CudaPlatform platform;
System system;
const int numParticles = 200;
for (int i = 0; i < numParticles; i++)
system.addParticle(1.0);
PeriodicTorsionForce* force = new PeriodicTorsionForce();
for (int i = 3; i < numParticles; i++)
force->addTorsion(i-3, i-2, i-1, i, 2, 1.1, i);
system.addForce(force);
vector<Vec3> positions(numParticles);
for (int i = 0; i < numParticles; i++)
positions[i] = Vec3(i, i%2, i%3);
VerletIntegrator integrator1(0.01);
Context context1(system, integrator1, platform);
context1.setPositions(positions);
State state1 = context1.getState(State::Forces | State::Energy);
VerletIntegrator integrator2(0.01);
string deviceIndex = platform.getPropertyValue(context1, CudaPlatform::CudaDeviceIndex());
map<string, string> props;
props[CudaPlatform::CudaDeviceIndex()] = deviceIndex+","+deviceIndex;
Context context2(system, integrator2, platform, props);
context2.setPositions(positions);
State state2 = context2.getState(State::Forces | State::Energy);
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
}
int main() {
try {
testPeriodicTorsions();
// testParallelComputation();
}
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-2012 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 RBTorsionForce.
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/Context.h"
#include "CudaPlatform.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/System.h"
#include "openmm/VerletIntegrator.h"
#include "../src/SimTKUtilities/SimTKOpenMMRealType.h"
#include <iostream>
#include <vector>
using namespace OpenMM;
using namespace std;
const double TOL = 1e-5;
void testRBTorsions() {
CudaPlatform platform;
System system;
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
system.addParticle(1.0);
VerletIntegrator integrator(0.01);
RBTorsionForce* forceField = new RBTorsionForce();
forceField->addTorsion(0, 1, 2, 3, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6);
system.addForce(forceField);
Context context(system, integrator, platform);
vector<Vec3> positions(4);
positions[0] = Vec3(0, 1, 0);
positions[1] = Vec3(0, 0, 0);
positions[2] = Vec3(1, 0, 0);
positions[3] = Vec3(1, 1, 1);
context.setPositions(positions);
State state = context.getState(State::Forces | State::Energy);
{
const vector<Vec3>& forces = state.getForces();
double psi = 0.25*PI_M - PI_M;
double torque = 0.0;
for (int i = 1; i < 6; ++i) {
double c = 0.1*(i+1);
torque += -c*i*std::pow(std::cos(psi), i-1)*std::sin(psi);
}
ASSERT_EQUAL_VEC(Vec3(0, 0, torque), forces[0], TOL);
ASSERT_EQUAL_VEC(Vec3(0, 0.5*torque, -0.5*torque), forces[3], TOL);
ASSERT_EQUAL_VEC(Vec3(forces[0][0]+forces[1][0]+forces[2][0]+forces[3][0], forces[0][1]+forces[1][1]+forces[2][1]+forces[3][1], forces[0][2]+forces[1][2]+forces[2][2]+forces[3][2]), Vec3(0, 0, 0), TOL);
double energy = 0.0;
for (int i = 0; i < 6; ++i) {
double c = 0.1*(i+1);
energy += c*std::pow(std::cos(psi), i);
}
ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL);
}
// Try changing the torsion parameters and make sure it's still correct.
forceField->setTorsionParameters(0, 0, 1, 2, 3, 0.11, 0.22, 0.33, 0.44, 0.55, 0.66);
forceField->updateParametersInContext(context);
state = context.getState(State::Forces | State::Energy);
{
const vector<Vec3>& forces = state.getForces();
double psi = 0.25*PI_M - PI_M;
double torque = 0.0;
for (int i = 1; i < 6; ++i) {
double c = 0.11*(i+1);
torque += -c*i*std::pow(std::cos(psi), i-1)*std::sin(psi);
}
ASSERT_EQUAL_VEC(Vec3(0, 0, torque), forces[0], TOL);
ASSERT_EQUAL_VEC(Vec3(0, 0.5*torque, -0.5*torque), forces[3], TOL);
ASSERT_EQUAL_VEC(Vec3(forces[0][0]+forces[1][0]+forces[2][0]+forces[3][0], forces[0][1]+forces[1][1]+forces[2][1]+forces[3][1], forces[0][2]+forces[1][2]+forces[2][2]+forces[3][2]), Vec3(0, 0, 0), TOL);
double energy = 0.0;
for (int i = 0; i < 6; ++i) {
double c = 0.11*(i+1);
energy += c*std::pow(std::cos(psi), i);
}
ASSERT_EQUAL_TOL(energy, state.getPotentialEnergy(), TOL);
}
}
void testParallelComputation() {
CudaPlatform platform;
System system;
const int numParticles = 200;
for (int i = 0; i < numParticles; i++)
system.addParticle(1.0);
RBTorsionForce* force = new RBTorsionForce();
for (int i = 3; i < numParticles; i++)
force->addTorsion(i-3, i-2, i-1, i, 2, 0.1*i, 0.5*i, i, 1, 1);
system.addForce(force);
vector<Vec3> positions(numParticles);
for (int i = 0; i < numParticles; i++)
positions[i] = Vec3(i, i%2, i%3);
VerletIntegrator integrator1(0.01);
Context context1(system, integrator1, platform);
context1.setPositions(positions);
State state1 = context1.getState(State::Forces | State::Energy);
VerletIntegrator integrator2(0.01);
string deviceIndex = platform.getPropertyValue(context1, CudaPlatform::CudaDeviceIndex());
map<string, string> props;
props[CudaPlatform::CudaDeviceIndex()] = deviceIndex+","+deviceIndex;
Context context2(system, integrator2, platform, props);
context2.setPositions(positions);
State state2 = context2.getState(State::Forces | State::Energy);
ASSERT_EQUAL_TOL(state1.getPotentialEnergy(), state2.getPotentialEnergy(), 1e-5);
for (int i = 0; i < numParticles; i++)
ASSERT_EQUAL_VEC(state1.getForces()[i], state2.getForces()[i], 1e-5);
}
int main() {
try {
testRBTorsions();
// testParallelComputation();
}
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