Commit 4c489434 authored by Peter Eastman's avatar Peter Eastman
Browse files

Bug fixes and simplifications to integration

parent d4d5e5c8
...@@ -126,7 +126,7 @@ void testTemperature() { ...@@ -126,7 +126,7 @@ void testTemperature() {
} }
ke /= 1000; ke /= 1000;
double expected = 0.5*numParticles*3*BOLTZ*temp; double expected = 0.5*numParticles*3*BOLTZ*temp;
ASSERT_EQUAL_TOL(expected, ke, 3*expected/std::sqrt(1000.0)); ASSERT_EQUAL_TOL(expected, ke, 3/std::sqrt(1000.0));
} }
void testConstraints() { void testConstraints() {
......
...@@ -67,12 +67,11 @@ struct OpenCLIntegrationUtilities::ShakeCluster { ...@@ -67,12 +67,11 @@ struct OpenCLIntegrationUtilities::ShakeCluster {
}; };
OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, const System& system) : context(context), OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, const System& system) : context(context),
oldPos(NULL), posDelta(NULL), settleAtoms(NULL), settleParams(NULL), shakeAtoms(NULL), shakeParams(NULL), posDelta(NULL), settleAtoms(NULL), settleParams(NULL), shakeAtoms(NULL), shakeParams(NULL),
random(NULL), randomSeed(NULL), randomPos(NULL) { random(NULL), randomSeed(NULL), randomPos(NULL) {
// Create workspace arrays. // Create workspace arrays.
posDelta = new OpenCLArray<mm_float4>(context, context.getPaddedNumAtoms(), "posDelta"); posDelta = new OpenCLArray<mm_float4>(context, context.getPaddedNumAtoms(), "posDelta");
oldPos = new OpenCLArray<mm_float4>(context, context.getPaddedNumAtoms(), "oldPos");
// Create kernels for enforcing constraints. // Create kernels for enforcing constraints.
...@@ -249,8 +248,6 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c ...@@ -249,8 +248,6 @@ OpenCLIntegrationUtilities::OpenCLIntegrationUtilities(OpenCLContext& context, c
OpenCLIntegrationUtilities::~OpenCLIntegrationUtilities() { OpenCLIntegrationUtilities::~OpenCLIntegrationUtilities() {
if (posDelta != NULL) if (posDelta != NULL)
delete posDelta; delete posDelta;
if (oldPos != NULL)
delete oldPos;
if (settleAtoms != NULL) if (settleAtoms != NULL)
delete settleAtoms; delete settleAtoms;
if (settleParams != NULL) if (settleParams != NULL)
...@@ -265,13 +262,13 @@ OpenCLIntegrationUtilities::~OpenCLIntegrationUtilities() { ...@@ -265,13 +262,13 @@ OpenCLIntegrationUtilities::~OpenCLIntegrationUtilities() {
delete randomSeed; delete randomSeed;
} }
void OpenCLIntegrationUtilities::applyConstraints(double tol, OpenCLArray<mm_float4>& oldPositions, OpenCLArray<mm_float4>& positionDeltas, OpenCLArray<mm_float4>& newDeltas) { void OpenCLIntegrationUtilities::applyConstraints(double tol) {
if (settleAtoms != NULL) { if (settleAtoms != NULL) {
settleKernel.setArg<cl_int>(0, settleAtoms->getSize()); settleKernel.setArg<cl_int>(0, settleAtoms->getSize());
settleKernel.setArg<cl_float>(1, tol); settleKernel.setArg<cl_float>(1, tol);
settleKernel.setArg<cl::Buffer>(2, oldPositions.getDeviceBuffer()); settleKernel.setArg<cl::Buffer>(2, context.getPosq().getDeviceBuffer());
settleKernel.setArg<cl::Buffer>(3, positionDeltas.getDeviceBuffer()); settleKernel.setArg<cl::Buffer>(3, posDelta->getDeviceBuffer());
settleKernel.setArg<cl::Buffer>(4, newDeltas.getDeviceBuffer()); settleKernel.setArg<cl::Buffer>(4, posDelta->getDeviceBuffer());
settleKernel.setArg<cl::Buffer>(5, context.getVelm().getDeviceBuffer()); settleKernel.setArg<cl::Buffer>(5, context.getVelm().getDeviceBuffer());
settleKernel.setArg<cl::Buffer>(6, settleAtoms->getDeviceBuffer()); settleKernel.setArg<cl::Buffer>(6, settleAtoms->getDeviceBuffer());
settleKernel.setArg<cl::Buffer>(7, settleParams->getDeviceBuffer()); settleKernel.setArg<cl::Buffer>(7, settleParams->getDeviceBuffer());
...@@ -280,9 +277,9 @@ void OpenCLIntegrationUtilities::applyConstraints(double tol, OpenCLArray<mm_flo ...@@ -280,9 +277,9 @@ void OpenCLIntegrationUtilities::applyConstraints(double tol, OpenCLArray<mm_flo
if (shakeAtoms != NULL) { if (shakeAtoms != NULL) {
shakeKernel.setArg<cl_int>(0, shakeAtoms->getSize()); shakeKernel.setArg<cl_int>(0, shakeAtoms->getSize());
shakeKernel.setArg<cl_float>(1, tol); shakeKernel.setArg<cl_float>(1, tol);
shakeKernel.setArg<cl::Buffer>(2, oldPositions.getDeviceBuffer()); shakeKernel.setArg<cl::Buffer>(2, context.getPosq().getDeviceBuffer());
shakeKernel.setArg<cl::Buffer>(3, positionDeltas.getDeviceBuffer()); shakeKernel.setArg<cl::Buffer>(3, posDelta->getDeviceBuffer());
shakeKernel.setArg<cl::Buffer>(4, newDeltas.getDeviceBuffer()); shakeKernel.setArg<cl::Buffer>(4, posDelta->getDeviceBuffer());
shakeKernel.setArg<cl::Buffer>(5, shakeAtoms->getDeviceBuffer()); shakeKernel.setArg<cl::Buffer>(5, shakeAtoms->getDeviceBuffer());
shakeKernel.setArg<cl::Buffer>(6, shakeParams->getDeviceBuffer()); shakeKernel.setArg<cl::Buffer>(6, shakeParams->getDeviceBuffer());
context.executeKernel(shakeKernel, shakeAtoms->getSize()); context.executeKernel(shakeKernel, shakeAtoms->getSize());
...@@ -299,7 +296,7 @@ void OpenCLIntegrationUtilities::initRandomNumberGenerator(unsigned int randomNu ...@@ -299,7 +296,7 @@ void OpenCLIntegrationUtilities::initRandomNumberGenerator(unsigned int randomNu
// Create the random number arrays. // Create the random number arrays.
lastSeed = randomNumberSeed; lastSeed = randomNumberSeed;
random = new OpenCLArray<mm_float4>(context, 32*context.getNumAtoms(), "random"); random = new OpenCLArray<mm_float4>(context, 32*context.getPaddedNumAtoms(), "random");
randomSeed = new OpenCLArray<mm_int4>(context, context.getNumThreadBlocks()*OpenCLContext::ThreadBlockSize, "randomSeed"); randomSeed = new OpenCLArray<mm_int4>(context, context.getNumThreadBlocks()*OpenCLContext::ThreadBlockSize, "randomSeed");
randomPos = random->getSize(); randomPos = random->getSize();
...@@ -328,7 +325,5 @@ int OpenCLIntegrationUtilities::prepareRandomNumbers(int numValues) { ...@@ -328,7 +325,5 @@ int OpenCLIntegrationUtilities::prepareRandomNumbers(int numValues) {
randomKernel.setArg<cl::Buffer>(2, randomSeed->getDeviceBuffer()); randomKernel.setArg<cl::Buffer>(2, randomSeed->getDeviceBuffer());
context.executeKernel(randomKernel, random->getSize()); context.executeKernel(randomKernel, random->getSize());
randomPos = numValues; randomPos = numValues;
vector<mm_float4> r(random->getSize());
random->download(r);
return 0; return 0;
} }
...@@ -47,12 +47,6 @@ public: ...@@ -47,12 +47,6 @@ public:
OpenCLArray<mm_float4>& getPosDelta() { OpenCLArray<mm_float4>& getPosDelta() {
return *posDelta; return *posDelta;
} }
/**
* Get the array which contains positions from before the current time step.
*/
OpenCLArray<mm_float4>& getOldPos() {
return *oldPos;
}
/** /**
* Get the array which contains random values. * Get the array which contains random values.
*/ */
...@@ -63,11 +57,8 @@ public: ...@@ -63,11 +57,8 @@ public:
* Apply constraints to the atom positions. * Apply constraints to the atom positions.
* *
* @param tol the constraint tolerance * @param tol the constraint tolerance
* @param oldPositions the atom positions from before the current time step
* @param positionDeltas the offsets being added to atom positions
* @param newDeltas the array to store constrained deltas into
*/ */
void applyConstraints(double tol, OpenCLArray<mm_float4>& oldPositions, OpenCLArray<mm_float4>& positionDeltas, OpenCLArray<mm_float4>& newDeltas); void applyConstraints(double tol);
/** /**
* Initialize the random number generator. * Initialize the random number generator.
*/ */
...@@ -85,7 +76,6 @@ private: ...@@ -85,7 +76,6 @@ private:
cl::Kernel shakeKernel; cl::Kernel shakeKernel;
cl::Kernel randomKernel; cl::Kernel randomKernel;
OpenCLArray<mm_float4>* posDelta; OpenCLArray<mm_float4>* posDelta;
OpenCLArray<mm_float4>* oldPos;
OpenCLArray<mm_int4>* settleAtoms; OpenCLArray<mm_int4>* settleAtoms;
OpenCLArray<mm_float2>* settleParams; OpenCLArray<mm_float2>* settleParams;
OpenCLArray<mm_int4>* shakeAtoms; OpenCLArray<mm_int4>* shakeAtoms;
......
...@@ -820,12 +820,11 @@ void OpenCLIntegrateVerletStepKernel::execute(ContextImpl& context, const Verlet ...@@ -820,12 +820,11 @@ void OpenCLIntegrateVerletStepKernel::execute(ContextImpl& context, const Verlet
kernel1.setArg<cl::Buffer>(3, cl.getVelm().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(3, cl.getVelm().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(4, cl.getForce().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(4, cl.getForce().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(5, integration.getPosDelta().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(5, integration.getPosDelta().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(6, integration.getOldPos().getDeviceBuffer());
cl.executeKernel(kernel1, numAtoms); cl.executeKernel(kernel1, numAtoms);
// Apply constraints. // Apply constraints.
integration.applyConstraints(integrator.getConstraintTolerance(), integration.getOldPos(), integration.getPosDelta(), integration.getPosDelta()); integration.applyConstraints(integrator.getConstraintTolerance());
// Call the second integration kernel. // Call the second integration kernel.
...@@ -869,6 +868,7 @@ void OpenCLIntegrateLangevinStepKernel::initialize(const System& system, const L ...@@ -869,6 +868,7 @@ void OpenCLIntegrateLangevinStepKernel::initialize(const System& system, const L
void OpenCLIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) { void OpenCLIntegrateLangevinStepKernel::execute(ContextImpl& context, const LangevinIntegrator& integrator) {
OpenCLIntegrationUtilities& integration = cl.getIntegrationUtilties(); OpenCLIntegrationUtilities& integration = cl.getIntegrationUtilties();
int numAtoms = cl.getNumAtoms(); int numAtoms = cl.getNumAtoms();
int numThreads = cl.getNumThreadBlocks()*cl.ThreadBlockSize;
double temperature = integrator.getTemperature(); double temperature = integrator.getTemperature();
double friction = integrator.getFriction(); double friction = integrator.getFriction();
double stepSize = integrator.getStepSize(); double stepSize = integrator.getStepSize();
...@@ -940,21 +940,20 @@ void OpenCLIntegrateLangevinStepKernel::execute(ContextImpl& context, const Lang ...@@ -940,21 +940,20 @@ void OpenCLIntegrateLangevinStepKernel::execute(ContextImpl& context, const Lang
// Call the first integration kernel. // Call the first integration kernel.
kernel1.setArg<cl_int>(0, numAtoms); kernel1.setArg<cl_int>(0, numAtoms);
kernel1.setArg<cl::Buffer>(1, cl.getPosq().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(1, cl.getVelm().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(2, cl.getVelm().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(2, cl.getForce().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(3, cl.getForce().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(3, integration.getPosDelta().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(4, integration.getPosDelta().getDeviceBuffer()); kernel1.setArg<cl::Buffer>(4, params->getDeviceBuffer());
kernel1.setArg<cl::Buffer>(5, params->getDeviceBuffer()); kernel1.setArg(5, params->getSize()*sizeof(cl_float), NULL);
kernel1.setArg(6, params->getSize()*sizeof(cl_float), NULL); kernel1.setArg<cl::Buffer>(6, xVector->getDeviceBuffer());
kernel1.setArg<cl::Buffer>(7, xVector->getDeviceBuffer()); kernel1.setArg<cl::Buffer>(7, vVector->getDeviceBuffer());
kernel1.setArg<cl::Buffer>(8, vVector->getDeviceBuffer()); kernel1.setArg<cl::Buffer>(8,integration.getRandom().getDeviceBuffer());
kernel1.setArg<cl::Buffer>(9,integration.getRandom().getDeviceBuffer()); kernel1.setArg<cl_uint>(9, integration.prepareRandomNumbers(2*numThreads));
kernel1.setArg<cl_uint>(10, integration.prepareRandomNumbers(2*cl.getPaddedNumAtoms()));
cl.executeKernel(kernel1, numAtoms); cl.executeKernel(kernel1, numAtoms);
// Apply constraints. // Apply constraints.
integration.applyConstraints(integrator.getConstraintTolerance(), integration.getOldPos(), integration.getPosDelta(), integration.getPosDelta()); integration.applyConstraints(integrator.getConstraintTolerance());
// Call the second integration kernel. // Call the second integration kernel.
...@@ -966,12 +965,12 @@ void OpenCLIntegrateLangevinStepKernel::execute(ContextImpl& context, const Lang ...@@ -966,12 +965,12 @@ void OpenCLIntegrateLangevinStepKernel::execute(ContextImpl& context, const Lang
kernel2.setArg<cl::Buffer>(5, xVector->getDeviceBuffer()); kernel2.setArg<cl::Buffer>(5, xVector->getDeviceBuffer());
kernel2.setArg<cl::Buffer>(6, vVector->getDeviceBuffer()); kernel2.setArg<cl::Buffer>(6, vVector->getDeviceBuffer());
kernel2.setArg<cl::Buffer>(7,integration.getRandom().getDeviceBuffer()); kernel2.setArg<cl::Buffer>(7,integration.getRandom().getDeviceBuffer());
kernel2.setArg<cl_uint>(8, integration.prepareRandomNumbers(2*cl.getPaddedNumAtoms())); kernel2.setArg<cl_uint>(8, integration.prepareRandomNumbers(2*numThreads));
cl.executeKernel(kernel2, numAtoms); cl.executeKernel(kernel2, numAtoms);
// Reapply constraints. // Reapply constraints.
integration.applyConstraints(integrator.getConstraintTolerance(), integration.getOldPos(), integration.getPosDelta(), cl.getPosq()); integration.applyConstraints(integrator.getConstraintTolerance());
// Call the third integration kernel. // Call the third integration kernel.
......
...@@ -4,9 +4,9 @@ enum {EM, EM_V, DOverTauC, TauOneMinusEM_V, TauDOverEMMinusOne, V, X, Yv, Yx, Fi ...@@ -4,9 +4,9 @@ enum {EM, EM_V, DOverTauC, TauOneMinusEM_V, TauDOverEMMinusOne, V, X, Yv, Yx, Fi
* Perform the first step of Langevin integration. * Perform the first step of Langevin integration.
*/ */
__kernel void integrateLangevinPart1(int numAtoms, __global float4* posq, __global float4* velm, __global float4* force, __kernel void integrateLangevinPart1(int numAtoms, __global float4* velm, __global float4* force, __global float4* posDelta,
__global float4* posDelta, __global float* paramBuffer, __local float* params, __global float4* xVector, __global float* paramBuffer, __local float* params, __global float4* xVector, __global float4* vVector,
__global float4* vVector, __global float4* random, unsigned int randomIndex) { __global float4* random, unsigned int randomIndex) {
// Load the parameters into local memory for faster access. // Load the parameters into local memory for faster access.
...@@ -47,7 +47,7 @@ __kernel void integrateLangevinPart2(int numAtoms, __global float4* velm, __glob ...@@ -47,7 +47,7 @@ __kernel void integrateLangevinPart2(int numAtoms, __global float4* velm, __glob
while (index < numAtoms) { while (index < numAtoms) {
float4 delta = posDelta[index]; float4 delta = posDelta[index];
float4 velocity = velm[index]; float4 velocity = velm[index];
float sqrtInvMass = 0.0f;//sqrt(velocity.w); float sqrtInvMass = sqrt(velocity.w);
velocity.xyz = delta.xyz*params[OneOverFix1]; velocity.xyz = delta.xyz*params[OneOverFix1];
float4 xmh = (float4) (vVector[index].xyz*params[TauDOverEMMinusOne] + sqrtInvMass*params[Yx]*random[randomIndex].xyz, 0.0f); float4 xmh = (float4) (vVector[index].xyz*params[TauDOverEMMinusOne] + sqrtInvMass*params[Yx]*random[randomIndex].xyz, 0.0f);
randomIndex += get_global_size(0); randomIndex += get_global_size(0);
......
...@@ -2,12 +2,11 @@ ...@@ -2,12 +2,11 @@
* Perform the first step of verlet integration. * Perform the first step of verlet integration.
*/ */
__kernel void integrateVerletPart1(int numAtoms, float dt, __global float4* posq, __global float4* velm, __global float4* force, __global float4* posDelta, __global float4* oldPos) { __kernel void integrateVerletPart1(int numAtoms, float dt, __global float4* posq, __global float4* velm, __global float4* force, __global float4* posDelta) {
int index = get_global_id(0); int index = get_global_id(0);
while (index < numAtoms) { while (index < numAtoms) {
float4 pos = posq[index]; float4 pos = posq[index];
float4 velocity = velm[index]; float4 velocity = velm[index];
oldPos[index] = pos;
velocity.xyz += force[index].xyz*dt*velocity.w; velocity.xyz += force[index].xyz*dt*velocity.w;
pos.xyz = velocity.xyz*dt; pos.xyz = velocity.xyz*dt;
posDelta[index] = pos; posDelta[index] = pos;
......
...@@ -126,7 +126,7 @@ void testTemperature() { ...@@ -126,7 +126,7 @@ void testTemperature() {
} }
ke /= 1000; ke /= 1000;
double expected = 0.5*numParticles*3*BOLTZ*temp; double expected = 0.5*numParticles*3*BOLTZ*temp;
ASSERT_EQUAL_TOL(expected, ke, 3*expected/std::sqrt(1000.0)); ASSERT_EQUAL_TOL(expected, ke, 3/std::sqrt(1000.0));
} }
void testConstraints() { void testConstraints() {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include "OpenCLPlatform.h" #include "OpenCLPlatform.h"
#include "openmm/NonbondedForce.h" #include "openmm/NonbondedForce.h"
#include "openmm/System.h" #include "openmm/System.h"
#include "openmm/VerletIntegrator.h" #include "openmm/LangevinIntegrator.h"
#include "../src/sfmt/SFMT.h" #include "../src/sfmt/SFMT.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
...@@ -54,7 +54,7 @@ void testConstraints() { ...@@ -54,7 +54,7 @@ void testConstraints() {
const double temp = 100.0; const double temp = 100.0;
OpenCLPlatform platform; OpenCLPlatform platform;
System system; System system;
VerletIntegrator integrator(0.001); LangevinIntegrator integrator(temp, 2.0, 0.001);
integrator.setConstraintTolerance(1e-5); integrator.setConstraintTolerance(1e-5);
NonbondedForce* forceField = new NonbondedForce(); NonbondedForce* forceField = new NonbondedForce();
for (int i = 0; i < numMolecules; ++i) { for (int i = 0; i < numMolecules; ++i) {
......
...@@ -126,7 +126,7 @@ void testTemperature() { ...@@ -126,7 +126,7 @@ void testTemperature() {
} }
ke /= 1000; ke /= 1000;
double expected = 0.5*numParticles*3*BOLTZ*temp; double expected = 0.5*numParticles*3*BOLTZ*temp;
ASSERT_EQUAL_TOL(expected, ke, 3*expected/std::sqrt(1000.0)); ASSERT_EQUAL_TOL(expected, ke, 3/std::sqrt(1000.0));
} }
void testConstraints() { void testConstraints() {
......
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