Commit 88812cd1 authored by Peter Eastman's avatar Peter Eastman
Browse files

RPMDIntegrator invokes updateContextState() (see bug 1798)

parent 60406edd
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2012 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -128,9 +128,8 @@ void CudaIntegrateRPMDStepKernel::initialize(const System& system, const RPMDInt ...@@ -128,9 +128,8 @@ void CudaIntegrateRPMDStepKernel::initialize(const System& system, const RPMDInt
pileKernel = cu.getKernel(module, "applyPileThermostat"); pileKernel = cu.getKernel(module, "applyPileThermostat");
stepKernel = cu.getKernel(module, "integrateStep"); stepKernel = cu.getKernel(module, "integrateStep");
velocitiesKernel = cu.getKernel(module, "advanceVelocities"); velocitiesKernel = cu.getKernel(module, "advanceVelocities");
copyPositionsToContextKernel = cu.getKernel(module, "copyPositionsToContext"); copyToContextKernel = cu.getKernel(module, "copyDataToContext");
copyVelocitiesToContextKernel = cu.getKernel(module, "copyVelocitiesToContext"); copyFromContextKernel = cu.getKernel(module, "copyDataFromContext");
copyForcesFromContextKernel = cu.getKernel(module, "copyForcesFromContext");
translateKernel = cu.getKernel(module, "applyCellTranslations"); translateKernel = cu.getKernel(module, "applyCellTranslations");
} }
...@@ -185,11 +184,11 @@ void CudaIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDIntegr ...@@ -185,11 +184,11 @@ void CudaIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDIntegr
void CudaIntegrateRPMDStepKernel::computeForces(ContextImpl& context) { void CudaIntegrateRPMDStepKernel::computeForces(ContextImpl& context) {
for (int i = 0; i < numCopies; i++) { for (int i = 0; i < numCopies; i++) {
void* copyToContextArgs[] = {&positions->getDevicePointer(), &cu.getPosq().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &i}; void* copyToContextArgs[] = {&velocities->getDevicePointer(), &cu.getVelm().getDevicePointer(), &positions->getDevicePointer(),
cu.executeKernel(copyPositionsToContextKernel, copyToContextArgs, cu.getNumAtoms()); &cu.getPosq().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &i};
cu.executeKernel(copyToContextKernel, copyToContextArgs, cu.getNumAtoms());
context.updateContextState();
context.calcForcesAndEnergy(true, false); context.calcForcesAndEnergy(true, false);
void* copyFromContextArgs[] = {&cu.getForce().getDevicePointer(), &forces->getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &i};
cu.executeKernel(copyForcesFromContextKernel, copyFromContextArgs, cu.getNumAtoms());
if (cu.getAtomsWereReordered() && cu.getNonbondedUtilities().getUsePeriodic()) { if (cu.getAtomsWereReordered() && cu.getNonbondedUtilities().getUsePeriodic()) {
// Atoms may have been translated into a different periodic box, so apply // Atoms may have been translated into a different periodic box, so apply
// the same translation to all the beads. // the same translation to all the beads.
...@@ -197,6 +196,9 @@ void CudaIntegrateRPMDStepKernel::computeForces(ContextImpl& context) { ...@@ -197,6 +196,9 @@ void CudaIntegrateRPMDStepKernel::computeForces(ContextImpl& context) {
void* args[] = {&positions->getDevicePointer(), &cu.getPosq().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &i}; void* args[] = {&positions->getDevicePointer(), &cu.getPosq().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &i};
cu.executeKernel(translateKernel, args, cu.getNumAtoms()); cu.executeKernel(translateKernel, args, cu.getNumAtoms());
} }
void* copyFromContextArgs[] = {&cu.getForce().getDevicePointer(), &forces->getDevicePointer(), &cu.getVelm().getDevicePointer(),
&velocities->getDevicePointer(), &cu.getPosq().getDevicePointer(), &positions->getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &i};
cu.executeKernel(copyFromContextKernel, copyFromContextArgs, cu.getNumAtoms());
} }
} }
...@@ -267,10 +269,9 @@ void CudaIntegrateRPMDStepKernel::setVelocities(int copy, const vector<Vec3>& ve ...@@ -267,10 +269,9 @@ void CudaIntegrateRPMDStepKernel::setVelocities(int copy, const vector<Vec3>& ve
} }
void CudaIntegrateRPMDStepKernel::copyToContext(int copy, ContextImpl& context) { void CudaIntegrateRPMDStepKernel::copyToContext(int copy, ContextImpl& context) {
void* copyPositionsArgs[] = {&positions->getDevicePointer(), &cu.getPosq().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &copy}; void* copyArgs[] = {&velocities->getDevicePointer(), &cu.getVelm().getDevicePointer(), &positions->getDevicePointer(),
cu.executeKernel(copyPositionsToContextKernel, copyPositionsArgs, cu.getNumAtoms()); &cu.getPosq().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &copy};
void* copyVelocitiesArgs[] = {&velocities->getDevicePointer(), &cu.getVelm().getDevicePointer(), &cu.getAtomIndexArray().getDevicePointer(), &copy}; cu.executeKernel(copyToContextKernel, copyArgs, cu.getNumAtoms());
cu.executeKernel(copyVelocitiesToContextKernel, copyVelocitiesArgs, cu.getNumAtoms());
} }
string CudaIntegrateRPMDStepKernel::createFFT(int size, const string& variable, bool forward) { string CudaIntegrateRPMDStepKernel::createFFT(int size, const string& variable, bool forward) {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2012 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -91,7 +91,7 @@ private: ...@@ -91,7 +91,7 @@ private:
CudaArray* forces; CudaArray* forces;
CudaArray* positions; CudaArray* positions;
CudaArray* velocities; CudaArray* velocities;
CUfunction pileKernel, stepKernel, velocitiesKernel, copyPositionsToContextKernel, copyVelocitiesToContextKernel, copyForcesFromContextKernel, translateKernel; CUfunction pileKernel, stepKernel, velocitiesKernel, copyToContextKernel, copyFromContextKernel, translateKernel;
}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -181,35 +181,33 @@ extern "C" __global__ void advanceVelocities(mixed4* velm, long long* force, mix ...@@ -181,35 +181,33 @@ extern "C" __global__ void advanceVelocities(mixed4* velm, long long* force, mix
} }
/** /**
* Copy a set of positions from the integrator's arrays to the context. * Copy a set of positions and velocities from the integrator's arrays to the context.
*/ */
extern "C" __global__ void copyPositionsToContext(mixed4* src, real4* dst, int* order, int copy) { extern "C" __global__ void copyDataToContext(mixed4* srcVel, mixed4* dstVel, mixed4* srcPos, real4* dstPos, int* order, int copy) {
const int base = copy*PADDED_NUM_ATOMS; const int base = copy*PADDED_NUM_ATOMS;
for (int particle = blockIdx.x*blockDim.x+threadIdx.x; particle < NUM_ATOMS; particle += blockDim.x*gridDim.x) { for (int particle = blockIdx.x*blockDim.x+threadIdx.x; particle < NUM_ATOMS; particle += blockDim.x*gridDim.x) {
mixed4 posq = src[base+order[particle]]; int index = base+order[particle];
dst[particle] = make_real4(posq.x, posq.y, posq.z, posq.w); dstVel[particle] = srcVel[index];
mixed4 posq = srcPos[index];
dstPos[particle] = make_real4(posq.x, posq.y, posq.z, posq.w);
} }
} }
/** /**
* Copy a set of velocities from the integrator's arrays to the context. * Copy a set of positions, velocities, and forces from the context to the integrator's arrays.
*/ */
extern "C" __global__ void copyVelocitiesToContext(mixed4* src, mixed4* dst, int* order, int copy) { extern "C" __global__ void copyDataFromContext(long long* srcForce, long long* dstForce, mixed4* srcVel, mixed4* dstVel,
real4* srcPos, mixed4* dstPos, int* order, int copy) {
const int base = copy*PADDED_NUM_ATOMS; const int base = copy*PADDED_NUM_ATOMS;
for (int particle = blockIdx.x*blockDim.x+threadIdx.x; particle < NUM_ATOMS; particle += blockDim.x*gridDim.x) { for (int particle = blockIdx.x*blockDim.x+threadIdx.x; particle < NUM_ATOMS; particle += blockDim.x*gridDim.x) {
dst[particle] = src[base+order[particle]]; int index = order[particle];
} dstForce[base*3+index] = srcForce[particle];
} dstForce[base*3+index+PADDED_NUM_ATOMS] = srcForce[particle+PADDED_NUM_ATOMS];
dstForce[base*3+index+PADDED_NUM_ATOMS*2] = srcForce[particle+PADDED_NUM_ATOMS*2];
dstVel[base+index] = srcVel[particle];
real4 posq = srcPos[particle];
dstPos[base+index] = make_mixed4(posq.x, posq.y, posq.z, posq.w);
/**
* Copy a set of forces from the context to the integrator's arrays.
*/
extern "C" __global__ void copyForcesFromContext(long long* src, long long* dst, int* order, int copy) {
const int base = copy*PADDED_NUM_ATOMS*3;
for (int particle = blockIdx.x*blockDim.x+threadIdx.x; particle < NUM_ATOMS; particle += blockDim.x*gridDim.x) {
dst[base+order[particle]] = src[particle];
dst[base+order[particle]+PADDED_NUM_ATOMS] = src[particle+PADDED_NUM_ATOMS];
dst[base+order[particle]+PADDED_NUM_ATOMS*2] = src[particle+PADDED_NUM_ATOMS*2];
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/CustomNonbondedForce.h" #include "openmm/CustomNonbondedForce.h"
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
...@@ -222,6 +223,55 @@ void testParaHydrogen() { ...@@ -222,6 +223,55 @@ void testParaHydrogen() {
ASSERT_USUALLY_EQUAL_TOL(60.0, 1.5*temperature+meanKE, 0.02); ASSERT_USUALLY_EQUAL_TOL(60.0, 1.5*temperature+meanKE, 0.02);
} }
Vec3 calcCM(const vector<Vec3>& values, System& system) {
Vec3 cm;
for (int j = 0; j < system.getNumParticles(); ++j) {
cm[0] += values[j][0]*system.getParticleMass(j);
cm[1] += values[j][1]*system.getParticleMass(j);
cm[2] += values[j][2]*system.getParticleMass(j);
}
return cm;
}
void testCMMotionRemoval() {
const int numParticles = 100;
const int numCopies = 30;
const double temperature = 300.0;
const double mass = 1.0;
System system;
for (int i = 0; i < numParticles; i++)
system.addParticle(mass);
system.addForce(new CMMotionRemover());
RPMDIntegrator integ(numCopies, temperature, 10.0, 0.001);
Platform& platform = Platform::getPlatformByName("CUDA");
Context context(system, integ, platform);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
vector<Vec3> positions(numParticles);
for (int i = 0; i < numCopies; i++)
{
for (int j = 0; j < numParticles; j++)
positions[j] = Vec3(0.02*genrand_real2(sfmt), 0.02*genrand_real2(sfmt), 0.02*genrand_real2(sfmt));
Vec3 cmPos = calcCM(positions, system);
for (int j = 0; j < numParticles; j++)
positions[j] -= cmPos*(1/(mass*numParticles));
integ.setPositions(i, positions);
}
// Make sure the CMMotionRemover is getting applied.
for (int i = 0; i < 200; ++i) {
integ.step(1);
Vec3 pos;
for (int j = 0; j < numCopies; j++) {
State state = integ.getState(0, State::Positions | State::Velocities);
pos += calcCM(state.getPositions(), system);
}
pos *= 1.0/numCopies;
ASSERT_EQUAL_VEC(Vec3(), pos, 0.5);
}
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
try { try {
registerRPMDCudaKernelFactories(); registerRPMDCudaKernelFactories();
...@@ -229,6 +279,7 @@ int main(int argc, char* argv[]) { ...@@ -229,6 +279,7 @@ int main(int argc, char* argv[]) {
Platform::getPlatformByName("CUDA").setPropertyDefaultValue("CudaPrecision", string(argv[1])); Platform::getPlatformByName("CUDA").setPropertyDefaultValue("CudaPrecision", string(argv[1]));
testFreeParticles(); testFreeParticles();
testParaHydrogen(); testParaHydrogen();
testCMMotionRemoval();
} }
catch(const std::exception& e) { catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl; std::cout << "exception: " << e.what() << std::endl;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2012 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -108,15 +108,12 @@ void OpenCLIntegrateRPMDStepKernel::initialize(const System& system, const RPMDI ...@@ -108,15 +108,12 @@ void OpenCLIntegrateRPMDStepKernel::initialize(const System& system, const RPMDI
pileKernel = cl::Kernel(program, "applyPileThermostat"); pileKernel = cl::Kernel(program, "applyPileThermostat");
stepKernel = cl::Kernel(program, "integrateStep"); stepKernel = cl::Kernel(program, "integrateStep");
velocitiesKernel = cl::Kernel(program, "advanceVelocities"); velocitiesKernel = cl::Kernel(program, "advanceVelocities");
copyPositionsToContextKernel = cl::Kernel(program, "copyPositionsToContext"); copyToContextKernel = cl::Kernel(program, "copyDataToContext");
copyVelocitiesToContextKernel = cl::Kernel(program, "copyVelocitiesToContext"); copyFromContextKernel = cl::Kernel(program, "copyDataFromContext");
copyForcesFromContextKernel = cl::Kernel(program, "copyForcesFromContext");
translateKernel = cl::Kernel(program, "applyCellTranslations"); translateKernel = cl::Kernel(program, "applyCellTranslations");
} }
void OpenCLIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDIntegrator& integrator, bool forcesAreValid) { void OpenCLIntegrateRPMDStepKernel::initializeKernels(ContextImpl& context) {
OpenCLIntegrationUtilities& integration = cl.getIntegrationUtilities();
if (!hasInitializedKernel) {
hasInitializedKernel = true; hasInitializedKernel = true;
pileKernel.setArg<cl::Buffer>(0, velocities->getDeviceBuffer()); pileKernel.setArg<cl::Buffer>(0, velocities->getDeviceBuffer());
stepKernel.setArg<cl::Buffer>(0, positions->getDeviceBuffer()); stepKernel.setArg<cl::Buffer>(0, positions->getDeviceBuffer());
...@@ -127,16 +124,24 @@ void OpenCLIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDInte ...@@ -127,16 +124,24 @@ void OpenCLIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDInte
translateKernel.setArg<cl::Buffer>(0, positions->getDeviceBuffer()); translateKernel.setArg<cl::Buffer>(0, positions->getDeviceBuffer());
translateKernel.setArg<cl::Buffer>(1, cl.getPosq().getDeviceBuffer()); translateKernel.setArg<cl::Buffer>(1, cl.getPosq().getDeviceBuffer());
translateKernel.setArg<cl::Buffer>(2, cl.getAtomIndexArray().getDeviceBuffer()); translateKernel.setArg<cl::Buffer>(2, cl.getAtomIndexArray().getDeviceBuffer());
copyPositionsToContextKernel.setArg<cl::Buffer>(0, positions->getDeviceBuffer()); copyToContextKernel.setArg<cl::Buffer>(0, velocities->getDeviceBuffer());
copyPositionsToContextKernel.setArg<cl::Buffer>(1, cl.getPosq().getDeviceBuffer()); copyToContextKernel.setArg<cl::Buffer>(1, cl.getVelm().getDeviceBuffer());
copyPositionsToContextKernel.setArg<cl::Buffer>(2, cl.getAtomIndexArray().getDeviceBuffer()); copyToContextKernel.setArg<cl::Buffer>(2, positions->getDeviceBuffer());
copyVelocitiesToContextKernel.setArg<cl::Buffer>(0, velocities->getDeviceBuffer()); copyToContextKernel.setArg<cl::Buffer>(3, cl.getPosq().getDeviceBuffer());
copyVelocitiesToContextKernel.setArg<cl::Buffer>(1, cl.getVelm().getDeviceBuffer()); copyToContextKernel.setArg<cl::Buffer>(4, cl.getAtomIndexArray().getDeviceBuffer());
copyVelocitiesToContextKernel.setArg<cl::Buffer>(2, cl.getAtomIndexArray().getDeviceBuffer()); copyFromContextKernel.setArg<cl::Buffer>(0, cl.getForce().getDeviceBuffer());
copyForcesFromContextKernel.setArg<cl::Buffer>(0, cl.getForce().getDeviceBuffer()); copyFromContextKernel.setArg<cl::Buffer>(1, forces->getDeviceBuffer());
copyForcesFromContextKernel.setArg<cl::Buffer>(1, forces->getDeviceBuffer()); copyFromContextKernel.setArg<cl::Buffer>(2, cl.getVelm().getDeviceBuffer());
copyForcesFromContextKernel.setArg<cl::Buffer>(2, cl.getAtomIndexArray().getDeviceBuffer()); copyFromContextKernel.setArg<cl::Buffer>(3, velocities->getDeviceBuffer());
} copyFromContextKernel.setArg<cl::Buffer>(4, cl.getPosq().getDeviceBuffer());
copyFromContextKernel.setArg<cl::Buffer>(5, positions->getDeviceBuffer());
copyFromContextKernel.setArg<cl::Buffer>(6, cl.getAtomIndexArray().getDeviceBuffer());
}
void OpenCLIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDIntegrator& integrator, bool forcesAreValid) {
OpenCLIntegrationUtilities& integration = cl.getIntegrationUtilities();
if (!hasInitializedKernel)
initializeKernels(context);
// Loop over copies and compute the force on each one. // Loop over copies and compute the force on each one.
...@@ -191,11 +196,10 @@ void OpenCLIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDInte ...@@ -191,11 +196,10 @@ void OpenCLIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDInte
void OpenCLIntegrateRPMDStepKernel::computeForces(ContextImpl& context) { void OpenCLIntegrateRPMDStepKernel::computeForces(ContextImpl& context) {
for (int i = 0; i < numCopies; i++) { for (int i = 0; i < numCopies; i++) {
copyPositionsToContextKernel.setArg<cl_int>(3, i); copyToContextKernel.setArg<cl_int>(5, i);
cl.executeKernel(copyPositionsToContextKernel, cl.getNumAtoms()); cl.executeKernel(copyToContextKernel, cl.getNumAtoms());
context.updateContextState();
context.calcForcesAndEnergy(true, false); context.calcForcesAndEnergy(true, false);
copyForcesFromContextKernel.setArg<cl_int>(3, i);
cl.executeKernel(copyForcesFromContextKernel, cl.getNumAtoms());
if (cl.getAtomsWereReordered() && cl.getNonbondedUtilities().getUsePeriodic()) { if (cl.getAtomsWereReordered() && cl.getNonbondedUtilities().getUsePeriodic()) {
// Atoms may have been translated into a different periodic box, so apply // Atoms may have been translated into a different periodic box, so apply
// the same translation to all the beads. // the same translation to all the beads.
...@@ -203,6 +207,8 @@ void OpenCLIntegrateRPMDStepKernel::computeForces(ContextImpl& context) { ...@@ -203,6 +207,8 @@ void OpenCLIntegrateRPMDStepKernel::computeForces(ContextImpl& context) {
translateKernel.setArg<cl_int>(3, i); translateKernel.setArg<cl_int>(3, i);
cl.executeKernel(translateKernel, cl.getNumAtoms()); cl.executeKernel(translateKernel, cl.getNumAtoms());
} }
copyFromContextKernel.setArg<cl_int>(7, i);
cl.executeKernel(copyFromContextKernel, cl.getNumAtoms());
} }
} }
...@@ -261,10 +267,10 @@ void OpenCLIntegrateRPMDStepKernel::setVelocities(int copy, const vector<Vec3>& ...@@ -261,10 +267,10 @@ void OpenCLIntegrateRPMDStepKernel::setVelocities(int copy, const vector<Vec3>&
} }
void OpenCLIntegrateRPMDStepKernel::copyToContext(int copy, ContextImpl& context) { void OpenCLIntegrateRPMDStepKernel::copyToContext(int copy, ContextImpl& context) {
copyPositionsToContextKernel.setArg<cl_int>(3, copy); if (!hasInitializedKernel)
cl.executeKernel(copyPositionsToContextKernel, cl.getNumAtoms()); initializeKernels(context);
copyVelocitiesToContextKernel.setArg<cl_int>(3, copy); copyToContextKernel.setArg<cl_int>(5, copy);
cl.executeKernel(copyVelocitiesToContextKernel, cl.getNumAtoms()); cl.executeKernel(copyToContextKernel, cl.getNumAtoms());
} }
string OpenCLIntegrateRPMDStepKernel::createFFT(int size, const string& variable, bool forward) { string OpenCLIntegrateRPMDStepKernel::createFFT(int size, const string& variable, bool forward) {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2012 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -84,6 +84,7 @@ public: ...@@ -84,6 +84,7 @@ public:
*/ */
void copyToContext(int copy, ContextImpl& context); void copyToContext(int copy, ContextImpl& context);
private: private:
void initializeKernels(ContextImpl& context);
void computeForces(ContextImpl& context); void computeForces(ContextImpl& context);
std::string createFFT(int size, const std::string& variable, bool forward); std::string createFFT(int size, const std::string& variable, bool forward);
OpenCLContext& cl; OpenCLContext& cl;
...@@ -92,7 +93,7 @@ private: ...@@ -92,7 +93,7 @@ private:
OpenCLArray* forces; OpenCLArray* forces;
OpenCLArray* positions; OpenCLArray* positions;
OpenCLArray* velocities; OpenCLArray* velocities;
cl::Kernel pileKernel, stepKernel, velocitiesKernel, copyPositionsToContextKernel, copyVelocitiesToContextKernel, copyForcesFromContextKernel, translateKernel; cl::Kernel pileKernel, stepKernel, velocitiesKernel, copyToContextKernel, copyFromContextKernel, translateKernel;
}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -172,32 +172,29 @@ __kernel void advanceVelocities(__global mixed4* velm, __global real4* force, mi ...@@ -172,32 +172,29 @@ __kernel void advanceVelocities(__global mixed4* velm, __global real4* force, mi
} }
/** /**
* Copy a set of positions from the integrator's arrays to the context. * Copy a set of positions and velocities from the integrator's arrays to the context.
*/ */
__kernel void copyPositionsToContext(__global mixed4* src, __global real4* dst, __global int* order, int copy) { __kernel void copyDataToContext(__global mixed4* srcVel, __global mixed4* dstVel, __global mixed4* srcPos,
__global real4* dstPos, __global int* order, int copy) {
const int base = copy*PADDED_NUM_ATOMS; const int base = copy*PADDED_NUM_ATOMS;
for (int particle = get_global_id(0); particle < NUM_ATOMS; particle += get_global_size(0)) { for (int particle = get_global_id(0); particle < NUM_ATOMS; particle += get_global_size(0)) {
dst[particle] = convert_real4(src[base+order[particle]]); int index = base+order[particle];
dstVel[particle] = srcVel[index];
dstPos[particle] = convert_real4(srcPos[index]);
} }
} }
/** /**
* Copy a set of velocities from the integrator's arrays to the context. * Copy a set of positions, velocities, and forces from the context to the integrator's arrays.
*/ */
__kernel void copyVelocitiesToContext(__global mixed4* src, __global mixed4* dst, __global int* order, int copy) { __kernel void copyDataFromContext(__global real4* srcForce, __global real4* dstForce, __global mixed4* srcVel,
__global mixed4* dstVel, __global real4* srcPos, __global mixed4* dstPos, __global int* order, int copy) {
const int base = copy*PADDED_NUM_ATOMS; const int base = copy*PADDED_NUM_ATOMS;
for (int particle = get_global_id(0); particle < NUM_ATOMS; particle += get_global_size(0)) { for (int particle = get_global_id(0); particle < NUM_ATOMS; particle += get_global_size(0)) {
dst[particle] = src[base+order[particle]]; int index = base+order[particle];
} dstForce[index] = srcForce[particle];
} dstVel[index] = srcVel[particle];
dstPos[index] = convert_mixed4(srcPos[particle]);
/**
* Copy a set forces from the context to the integrator's arrays.
*/
__kernel void copyForcesFromContext(__global real4* src, __global real4* dst, __global int* order, int copy) {
const int base = copy*PADDED_NUM_ATOMS;
for (int particle = get_global_id(0); particle < NUM_ATOMS; particle += get_global_size(0)) {
dst[base+order[particle]] = src[particle];
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011-2012 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/CustomNonbondedForce.h" #include "openmm/CustomNonbondedForce.h"
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
...@@ -223,6 +224,55 @@ void testParaHydrogen() { ...@@ -223,6 +224,55 @@ void testParaHydrogen() {
ASSERT_USUALLY_EQUAL_TOL(60.0, 1.5*temperature+meanKE, 0.02); ASSERT_USUALLY_EQUAL_TOL(60.0, 1.5*temperature+meanKE, 0.02);
} }
Vec3 calcCM(const vector<Vec3>& values, System& system) {
Vec3 cm;
for (int j = 0; j < system.getNumParticles(); ++j) {
cm[0] += values[j][0]*system.getParticleMass(j);
cm[1] += values[j][1]*system.getParticleMass(j);
cm[2] += values[j][2]*system.getParticleMass(j);
}
return cm;
}
void testCMMotionRemoval() {
const int numParticles = 100;
const int numCopies = 30;
const double temperature = 300.0;
const double mass = 1.0;
System system;
for (int i = 0; i < numParticles; i++)
system.addParticle(mass);
system.addForce(new CMMotionRemover());
RPMDIntegrator integ(numCopies, temperature, 10.0, 0.001);
Platform& platform = Platform::getPlatformByName("OpenCL");
Context context(system, integ, platform);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
vector<Vec3> positions(numParticles);
for (int i = 0; i < numCopies; i++)
{
for (int j = 0; j < numParticles; j++)
positions[j] = Vec3(0.02*genrand_real2(sfmt), 0.02*genrand_real2(sfmt), 0.02*genrand_real2(sfmt));
Vec3 cmPos = calcCM(positions, system);
for (int j = 0; j < numParticles; j++)
positions[j] -= cmPos*(1/(mass*numParticles));
integ.setPositions(i, positions);
}
// Make sure the CMMotionRemover is getting applied.
for (int i = 0; i < 200; ++i) {
integ.step(1);
Vec3 pos;
for (int j = 0; j < numCopies; j++) {
State state = integ.getState(0, State::Positions | State::Velocities);
pos += calcCM(state.getPositions(), system);
}
pos *= 1.0/numCopies;
ASSERT_EQUAL_VEC(Vec3(), pos, 0.5);
}
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
try { try {
registerRPMDOpenCLKernelFactories(); registerRPMDOpenCLKernelFactories();
...@@ -230,6 +280,7 @@ int main(int argc, char* argv[]) { ...@@ -230,6 +280,7 @@ int main(int argc, char* argv[]) {
Platform::getPlatformByName("OpenCL").setPropertyDefaultValue("OpenCLPrecision", string(argv[1])); Platform::getPlatformByName("OpenCL").setPropertyDefaultValue("OpenCLPrecision", string(argv[1]));
testFreeParticles(); testFreeParticles();
testParaHydrogen(); testParaHydrogen();
testCMMotionRemoval();
} }
catch(const std::exception& e) { catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl; std::cout << "exception: " << e.what() << std::endl;
......
...@@ -186,7 +186,6 @@ void ReferenceIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDI ...@@ -186,7 +186,6 @@ void ReferenceIntegrateRPMDStepKernel::execute(ContextImpl& context, const RPMDI
for (int j = 0; j < numParticles; j++) for (int j = 0; j < numParticles; j++)
velocities[i][j] += forces[i][j]*(halfdt/system.getParticleMass(j)); velocities[i][j] += forces[i][j]*(halfdt/system.getParticleMass(j));
// Apply the PILE-L thermostat again. // Apply the PILE-L thermostat again.
for (int particle = 0; particle < numParticles; particle++) { for (int particle = 0; particle < numParticles; particle++) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2011 Stanford University and the Authors. * * Portions copyright (c) 2011-2013 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
#include "openmm/internal/AssertionUtilities.h" #include "openmm/internal/AssertionUtilities.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/HarmonicBondForce.h" #include "openmm/HarmonicBondForce.h"
#include "openmm/Platform.h" #include "openmm/Platform.h"
...@@ -104,9 +105,59 @@ void testFreeParticles() { ...@@ -104,9 +105,59 @@ void testFreeParticles() {
ASSERT_USUALLY_EQUAL_TOL(expectedRg, sqrt(meanRg2), 1e-3); ASSERT_USUALLY_EQUAL_TOL(expectedRg, sqrt(meanRg2), 1e-3);
} }
Vec3 calcCM(const vector<Vec3>& values, System& system) {
Vec3 cm;
for (int j = 0; j < system.getNumParticles(); ++j) {
cm[0] += values[j][0]*system.getParticleMass(j);
cm[1] += values[j][1]*system.getParticleMass(j);
cm[2] += values[j][2]*system.getParticleMass(j);
}
return cm;
}
void testCMMotionRemoval() {
const int numParticles = 100;
const int numCopies = 30;
const double temperature = 300.0;
const double mass = 1.0;
System system;
for (int i = 0; i < numParticles; i++)
system.addParticle(mass);
system.addForce(new CMMotionRemover());
RPMDIntegrator integ(numCopies, temperature, 10.0, 0.001);
Platform& platform = Platform::getPlatformByName("Reference");
Context context(system, integ, platform);
OpenMM_SFMT::SFMT sfmt;
init_gen_rand(0, sfmt);
vector<Vec3> positions(numParticles);
for (int i = 0; i < numCopies; i++)
{
for (int j = 0; j < numParticles; j++)
positions[j] = Vec3(0.02*genrand_real2(sfmt), 0.02*genrand_real2(sfmt), 0.02*genrand_real2(sfmt));
Vec3 cmPos = calcCM(positions, system);
for (int j = 0; j < numParticles; j++)
positions[j] -= cmPos*(1/(mass*numParticles));
integ.setPositions(i, positions);
}
// Make sure the CMMotionRemover is getting applied.
for (int i = 0; i < 200; ++i) {
integ.step(1);
Vec3 pos;
for (int j = 0; j < numCopies; j++) {
State state = integ.getState(0, State::Positions | State::Velocities);
pos += calcCM(state.getPositions(), system);
}
pos *= 1.0/numCopies;
ASSERT_EQUAL_VEC(Vec3(), pos, 0.5);
}
}
int main() { int main() {
try { try {
testFreeParticles(); testFreeParticles();
testCMMotionRemoval();
} }
catch(const std::exception& e) { catch(const std::exception& e) {
std::cout << "exception: " << e.what() << std::endl; std::cout << "exception: " << e.what() << std::endl;
......
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