Commit b880b5d9 authored by Peter Eastman's avatar Peter Eastman
Browse files

Fixed bug in PME when atoms were far outside the periodic box (see bug 1144)

parent a8a36d75
...@@ -108,9 +108,12 @@ void kUpdateGridIndexAndFraction_kernel() ...@@ -108,9 +108,12 @@ void kUpdateGridIndexAndFraction_kernel()
for (int i = tid; i < cSim.atoms; i += tnb) for (int i = tid; i < cSim.atoms; i += tnb)
{ {
float4 posq = cSim.pPosq[i]; float4 posq = cSim.pPosq[i];
float3 t = make_float3((posq.x*cSim.invPeriodicBoxSizeX+1.0f)*cSim.pmeGridSize.x, posq.x -= floor(posq.x*cSim.invPeriodicBoxSizeX)*cSim.periodicBoxSizeX;
(posq.y*cSim.invPeriodicBoxSizeY+1.0f)*cSim.pmeGridSize.y, posq.y -= floor(posq.y*cSim.invPeriodicBoxSizeY)*cSim.periodicBoxSizeY;
(posq.z*cSim.invPeriodicBoxSizeZ+1.0f)*cSim.pmeGridSize.z); posq.z -= floor(posq.z*cSim.invPeriodicBoxSizeZ)*cSim.periodicBoxSizeZ;
float3 t = make_float3((posq.x*cSim.invPeriodicBoxSizeX)*cSim.pmeGridSize.x,
(posq.y*cSim.invPeriodicBoxSizeY)*cSim.pmeGridSize.y,
(posq.z*cSim.invPeriodicBoxSizeZ)*cSim.pmeGridSize.z);
int3 gridIndex = make_int3(((int) t.x) % cSim.pmeGridSize.x, int3 gridIndex = make_int3(((int) t.x) % cSim.pmeGridSize.x,
((int) t.y) % cSim.pmeGridSize.y, ((int) t.y) % cSim.pmeGridSize.y,
((int) t.z) % cSim.pmeGridSize.z); ((int) t.z) % cSim.pmeGridSize.z);
...@@ -192,9 +195,12 @@ void kUpdateBsplines_kernel() ...@@ -192,9 +195,12 @@ void kUpdateBsplines_kernel()
} }
float4 posq = cSim.pPosq[i]; float4 posq = cSim.pPosq[i];
float3 t = make_float3((posq.x*cSim.invPeriodicBoxSizeX+1.0f)*cSim.pmeGridSize.x, posq.x -= floor(posq.x*cSim.invPeriodicBoxSizeX)*cSim.periodicBoxSizeX;
(posq.y*cSim.invPeriodicBoxSizeY+1.0f)*cSim.pmeGridSize.y, posq.y -= floor(posq.y*cSim.invPeriodicBoxSizeY)*cSim.periodicBoxSizeY;
(posq.z*cSim.invPeriodicBoxSizeZ+1.0f)*cSim.pmeGridSize.z); posq.z -= floor(posq.z*cSim.invPeriodicBoxSizeZ)*cSim.periodicBoxSizeZ;
float3 t = make_float3((posq.x*cSim.invPeriodicBoxSizeX)*cSim.pmeGridSize.x,
(posq.y*cSim.invPeriodicBoxSizeY)*cSim.pmeGridSize.y,
(posq.z*cSim.invPeriodicBoxSizeZ)*cSim.pmeGridSize.z);
float4 dr = make_float4(t.x-(int) t.x, t.y-(int) t.y, t.z-(int) t.z, 0.0f); float4 dr = make_float4(t.x-(int) t.x, t.y-(int) t.y, t.z-(int) t.z, 0.0f);
data[PME_ORDER - 1] = make_float4(0.0f); data[PME_ORDER - 1] = make_float4(0.0f);
...@@ -341,9 +347,12 @@ void kGridInterpolateForce_kernel() ...@@ -341,9 +347,12 @@ void kGridInterpolateForce_kernel()
{ {
float3 force = make_float3(0.0f, 0.0f, 0.0f); float3 force = make_float3(0.0f, 0.0f, 0.0f);
float4 posq = cSim.pPosq[atom]; float4 posq = cSim.pPosq[atom];
float3 t = make_float3((posq.x*cSim.invPeriodicBoxSizeX+1.0f)*cSim.pmeGridSize.x, posq.x -= floor(posq.x*cSim.invPeriodicBoxSizeX)*cSim.periodicBoxSizeX;
(posq.y*cSim.invPeriodicBoxSizeY+1.0f)*cSim.pmeGridSize.y, posq.y -= floor(posq.y*cSim.invPeriodicBoxSizeY)*cSim.periodicBoxSizeY;
(posq.z*cSim.invPeriodicBoxSizeZ+1.0f)*cSim.pmeGridSize.z); posq.z -= floor(posq.z*cSim.invPeriodicBoxSizeZ)*cSim.periodicBoxSizeZ;
float3 t = make_float3((posq.x*cSim.invPeriodicBoxSizeX)*cSim.pmeGridSize.x,
(posq.y*cSim.invPeriodicBoxSizeY)*cSim.pmeGridSize.y,
(posq.z*cSim.invPeriodicBoxSizeZ)*cSim.pmeGridSize.z);
int3 gridIndex = make_int3(((int) t.x) % cSim.pmeGridSize.x, int3 gridIndex = make_int3(((int) t.x) % cSim.pmeGridSize.x,
((int) t.y) % cSim.pmeGridSize.y, ((int) t.y) % cSim.pmeGridSize.y,
((int) t.z) % cSim.pmeGridSize.z); ((int) t.z) % cSim.pmeGridSize.z);
......
...@@ -1296,9 +1296,8 @@ void OpenCLCalcNonbondedForceKernel::executeForces(ContextImpl& context) { ...@@ -1296,9 +1296,8 @@ void OpenCLCalcNonbondedForceKernel::executeForces(ContextImpl& context) {
pmeInterpolateForceKernel = cl::Kernel(program, "gridInterpolateForce"); pmeInterpolateForceKernel = cl::Kernel(program, "gridInterpolateForce");
pmeGridIndexKernel.setArg<cl::Buffer>(0, cl.getPosq().getDeviceBuffer()); pmeGridIndexKernel.setArg<cl::Buffer>(0, cl.getPosq().getDeviceBuffer());
pmeGridIndexKernel.setArg<cl::Buffer>(1, pmeAtomGridIndex->getDeviceBuffer()); pmeGridIndexKernel.setArg<cl::Buffer>(1, pmeAtomGridIndex->getDeviceBuffer());
pmeAtomRangeKernel.setArg<cl::Buffer>(0, cl.getPosq().getDeviceBuffer()); pmeAtomRangeKernel.setArg<cl::Buffer>(0, pmeAtomGridIndex->getDeviceBuffer());
pmeAtomRangeKernel.setArg<cl::Buffer>(1, pmeAtomGridIndex->getDeviceBuffer()); pmeAtomRangeKernel.setArg<cl::Buffer>(1, pmeAtomRange->getDeviceBuffer());
pmeAtomRangeKernel.setArg<cl::Buffer>(2, pmeAtomRange->getDeviceBuffer());
pmeUpdateBsplinesKernel.setArg<cl::Buffer>(0, cl.getPosq().getDeviceBuffer()); pmeUpdateBsplinesKernel.setArg<cl::Buffer>(0, cl.getPosq().getDeviceBuffer());
pmeUpdateBsplinesKernel.setArg<cl::Buffer>(1, pmeBsplineTheta->getDeviceBuffer()); pmeUpdateBsplinesKernel.setArg<cl::Buffer>(1, pmeBsplineTheta->getDeviceBuffer());
pmeUpdateBsplinesKernel.setArg<cl::Buffer>(2, pmeBsplineDtheta->getDeviceBuffer()); pmeUpdateBsplinesKernel.setArg<cl::Buffer>(2, pmeBsplineDtheta->getDeviceBuffer());
...@@ -1336,11 +1335,13 @@ void OpenCLCalcNonbondedForceKernel::executeForces(ContextImpl& context) { ...@@ -1336,11 +1335,13 @@ void OpenCLCalcNonbondedForceKernel::executeForces(ContextImpl& context) {
if (pmeGrid != NULL) { if (pmeGrid != NULL) {
mm_float4 boxSize = cl.getPeriodicBoxSize(); mm_float4 boxSize = cl.getPeriodicBoxSize();
mm_float4 invBoxSize = cl.getInvPeriodicBoxSize(); mm_float4 invBoxSize = cl.getInvPeriodicBoxSize();
pmeGridIndexKernel.setArg<mm_float4>(2, invBoxSize); pmeGridIndexKernel.setArg<mm_float4>(2, boxSize);
pmeGridIndexKernel.setArg<mm_float4>(3, invBoxSize);
cl.executeKernel(pmeGridIndexKernel, cl.getNumAtoms()); cl.executeKernel(pmeGridIndexKernel, cl.getNumAtoms());
sort->sort(*pmeAtomGridIndex); sort->sort(*pmeAtomGridIndex);
cl.executeKernel(pmeAtomRangeKernel, cl.getNumAtoms()); cl.executeKernel(pmeAtomRangeKernel, cl.getNumAtoms());
pmeUpdateBsplinesKernel.setArg<mm_float4>(5, invBoxSize); pmeUpdateBsplinesKernel.setArg<mm_float4>(5, boxSize);
pmeUpdateBsplinesKernel.setArg<mm_float4>(6, invBoxSize);
cl.executeKernel(pmeUpdateBsplinesKernel, cl.getNumAtoms()); cl.executeKernel(pmeUpdateBsplinesKernel, cl.getNumAtoms());
cl.executeKernel(pmeSpreadChargeKernel, cl.getNumAtoms()); cl.executeKernel(pmeSpreadChargeKernel, cl.getNumAtoms());
fft->execFFT(*pmeGrid, true); fft->execFFT(*pmeGrid, true);
...@@ -1348,7 +1349,8 @@ void OpenCLCalcNonbondedForceKernel::executeForces(ContextImpl& context) { ...@@ -1348,7 +1349,8 @@ void OpenCLCalcNonbondedForceKernel::executeForces(ContextImpl& context) {
pmeConvolutionKernel.setArg<cl_float>(6, (float) (1.0/(M_PI*boxSize.x*boxSize.y*boxSize.z))); pmeConvolutionKernel.setArg<cl_float>(6, (float) (1.0/(M_PI*boxSize.x*boxSize.y*boxSize.z)));
cl.executeKernel(pmeConvolutionKernel, cl.getNumAtoms()); cl.executeKernel(pmeConvolutionKernel, cl.getNumAtoms());
fft->execFFT(*pmeGrid, false); fft->execFFT(*pmeGrid, false);
pmeInterpolateForceKernel.setArg<mm_float4>(5, invBoxSize); pmeInterpolateForceKernel.setArg<mm_float4>(5, boxSize);
pmeInterpolateForceKernel.setArg<mm_float4>(6, invBoxSize);
cl.executeKernel(pmeInterpolateForceKernel, cl.getNumAtoms()); cl.executeKernel(pmeInterpolateForceKernel, cl.getNumAtoms());
} }
} }
......
__kernel void updateGridIndexAndFraction(__global float4* posq, __global float2* pmeAtomGridIndex, float4 invPeriodicBoxSize) { __kernel void updateGridIndexAndFraction(__global float4* posq, __global float2* pmeAtomGridIndex, float4 periodicBoxSize, float4 invPeriodicBoxSize) {
for (int i = get_global_id(0); i < NUM_ATOMS; i += get_global_size(0)) { for (int i = get_global_id(0); i < NUM_ATOMS; i += get_global_size(0)) {
float4 pos = posq[i]; float4 pos = posq[i];
float4 t = (float4) ((pos.x*invPeriodicBoxSize.x+1.0f)*GRID_SIZE_X, pos.x -= floor(pos.x*invPeriodicBoxSize.x)*periodicBoxSize.x;
(pos.y*invPeriodicBoxSize.y+1.0f)*GRID_SIZE_Y, pos.y -= floor(pos.y*invPeriodicBoxSize.y)*periodicBoxSize.y;
(pos.z*invPeriodicBoxSize.z+1.0f)*GRID_SIZE_Z, 0.0f); pos.z -= floor(pos.z*invPeriodicBoxSize.z)*periodicBoxSize.z;
float4 t = (float4) ((pos.x*invPeriodicBoxSize.x)*GRID_SIZE_X,
(pos.y*invPeriodicBoxSize.y)*GRID_SIZE_Y,
(pos.z*invPeriodicBoxSize.z)*GRID_SIZE_Z, 0.0f);
int4 gridIndex = (int4) (((int) t.x) % GRID_SIZE_X, int4 gridIndex = (int4) (((int) t.x) % GRID_SIZE_X,
((int) t.y) % GRID_SIZE_Y, ((int) t.y) % GRID_SIZE_Y,
((int) t.z) % GRID_SIZE_Z, 0); ((int) t.z) % GRID_SIZE_Z, 0);
...@@ -15,7 +18,7 @@ __kernel void updateGridIndexAndFraction(__global float4* posq, __global float2* ...@@ -15,7 +18,7 @@ __kernel void updateGridIndexAndFraction(__global float4* posq, __global float2*
* For each grid point, find the range of sorted atoms associated with that point. * For each grid point, find the range of sorted atoms associated with that point.
*/ */
__kernel void findAtomRangeForGrid(__global float4* posq, __global float2* pmeAtomGridIndex, __global int* pmeAtomRange) { __kernel void findAtomRangeForGrid(__global float2* pmeAtomGridIndex, __global int* pmeAtomRange) {
int start = (NUM_ATOMS*get_global_id(0))/get_global_size(0); int start = (NUM_ATOMS*get_global_id(0))/get_global_size(0);
int end = (NUM_ATOMS*(get_global_id(0)+1))/get_global_size(0); int end = (NUM_ATOMS*(get_global_id(0)+1))/get_global_size(0);
int last = (start == 0 ? -1 : pmeAtomGridIndex[start-1].y); int last = (start == 0 ? -1 : pmeAtomGridIndex[start-1].y);
...@@ -38,7 +41,7 @@ __kernel void findAtomRangeForGrid(__global float4* posq, __global float2* pmeAt ...@@ -38,7 +41,7 @@ __kernel void findAtomRangeForGrid(__global float4* posq, __global float2* pmeAt
} }
} }
__kernel void updateBsplines(__global float4* posq, __global float4* pmeBsplineTheta, __global float4* pmeBsplineDTheta, __local float4* bsplinesCache, __global float2* pmeAtomGridIndex, float4 invPeriodicBoxSize) { __kernel void updateBsplines(__global float4* posq, __global float4* pmeBsplineTheta, __global float4* pmeBsplineDTheta, __local float4* bsplinesCache, __global float2* pmeAtomGridIndex, float4 periodicBoxSize, float4 invPeriodicBoxSize) {
const float4 scale = 1.0f/(PME_ORDER-1); const float4 scale = 1.0f/(PME_ORDER-1);
for (int i = get_global_id(0); i < NUM_ATOMS; i += get_global_size(0)) { for (int i = get_global_id(0); i < NUM_ATOMS; i += get_global_size(0)) {
__local float4* data = &bsplinesCache[get_local_id(0)*PME_ORDER]; __local float4* data = &bsplinesCache[get_local_id(0)*PME_ORDER];
...@@ -48,9 +51,12 @@ __kernel void updateBsplines(__global float4* posq, __global float4* pmeBsplineT ...@@ -48,9 +51,12 @@ __kernel void updateBsplines(__global float4* posq, __global float4* pmeBsplineT
ddata[j] = 0.0f; ddata[j] = 0.0f;
} }
float4 pos = posq[i]; float4 pos = posq[i];
float4 t = (float4) ((pos.x*invPeriodicBoxSize.x+1.0f)*GRID_SIZE_X, pos.x -= floor(pos.x*invPeriodicBoxSize.x)*periodicBoxSize.x;
(pos.y*invPeriodicBoxSize.y+1.0f)*GRID_SIZE_Y, pos.y -= floor(pos.y*invPeriodicBoxSize.y)*periodicBoxSize.y;
(pos.z*invPeriodicBoxSize.z+1.0f)*GRID_SIZE_Z, 0.0f); pos.z -= floor(pos.z*invPeriodicBoxSize.z)*periodicBoxSize.z;
float4 t = (float4) ((pos.x*invPeriodicBoxSize.x)*GRID_SIZE_X,
(pos.y*invPeriodicBoxSize.y)*GRID_SIZE_Y,
(pos.z*invPeriodicBoxSize.z)*GRID_SIZE_Z, 0.0f);
float4 dr = (float4) (t.x-(int) t.x, t.y-(int) t.y, t.z-(int) t.z, 0.0f); float4 dr = (float4) (t.x-(int) t.x, t.y-(int) t.y, t.z-(int) t.z, 0.0f);
data[PME_ORDER-1] = 0.0f; data[PME_ORDER-1] = 0.0f;
data[1] = dr; data[1] = dr;
...@@ -148,13 +154,16 @@ __kernel void reciprocalConvolution(__global float2* pmeGrid, __global float* en ...@@ -148,13 +154,16 @@ __kernel void reciprocalConvolution(__global float2* pmeGrid, __global float* en
energyBuffer[get_global_id(0)] += 0.5f*energy; energyBuffer[get_global_id(0)] += 0.5f*energy;
} }
__kernel void gridInterpolateForce(__global float4* posq, __global float4* forceBuffers, __global float4* pmeBsplineTheta, __global float4* pmeBsplineDTheta, __global float2* pmeGrid, float4 invPeriodicBoxSize) { __kernel void gridInterpolateForce(__global float4* posq, __global float4* forceBuffers, __global float4* pmeBsplineTheta, __global float4* pmeBsplineDTheta, __global float2* pmeGrid, float4 periodicBoxSize, float4 invPeriodicBoxSize) {
for (int atom = get_global_id(0); atom < NUM_ATOMS; atom += get_global_size(0)) { for (int atom = get_global_id(0); atom < NUM_ATOMS; atom += get_global_size(0)) {
float4 force = 0.0f; float4 force = 0.0f;
float4 pos = posq[atom]; float4 pos = posq[atom];
float4 t = (float4) ((pos.x*invPeriodicBoxSize.x+1.0f)*GRID_SIZE_X, pos.x -= floor(pos.x*invPeriodicBoxSize.x)*periodicBoxSize.x;
(pos.y*invPeriodicBoxSize.y+1.0f)*GRID_SIZE_Y, pos.y -= floor(pos.y*invPeriodicBoxSize.y)*periodicBoxSize.y;
(pos.z*invPeriodicBoxSize.z+1.0f)*GRID_SIZE_Z, 0.0f); pos.z -= floor(pos.z*invPeriodicBoxSize.z)*periodicBoxSize.z;
float4 t = (float4) ((pos.x*invPeriodicBoxSize.x)*GRID_SIZE_X,
(pos.y*invPeriodicBoxSize.y)*GRID_SIZE_Y,
(pos.z*invPeriodicBoxSize.z)*GRID_SIZE_Z, 0.0f);
int4 gridIndex = (int4) (((int) t.x) % GRID_SIZE_X, int4 gridIndex = (int4) (((int) t.x) % GRID_SIZE_X,
((int) t.y) % GRID_SIZE_Y, ((int) t.y) % GRID_SIZE_Y,
((int) t.z) % GRID_SIZE_Z, 0); ((int) t.z) % GRID_SIZE_Z, 0);
......
...@@ -241,7 +241,9 @@ pme_update_grid_index_and_fraction(pme_t pme, ...@@ -241,7 +241,9 @@ pme_update_grid_index_and_fraction(pme_t pme,
* numerical problems, so this shouldnt cause any problems. * numerical problems, so this shouldnt cause any problems.
* (And, by adding 100.0 box lengths, we would lose a bit of numerical accuracy here!) * (And, by adding 100.0 box lengths, we would lose a bit of numerical accuracy here!)
*/ */
t = (atomCoordinates[i][d] / periodicBoxSize[d] + 1)*pme->ngrid[d]; RealOpenMM coord = atomCoordinates[i][d];
coord -= floor(coord/periodicBoxSize[d])*periodicBoxSize[d];
t = (coord / periodicBoxSize[d])*pme->ngrid[d];
ti = (int) t; ti = (int) t;
pme->particlefraction[i][d] = t - ti; pme->particlefraction[i][d] = t - ti;
......
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