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

Converted more forces to use OpenCLBondedUtilities

parent 42b9d891
This diff is collapsed.
...@@ -217,7 +217,7 @@ private: ...@@ -217,7 +217,7 @@ private:
class OpenCLCalcCustomBondForceKernel : public CalcCustomBondForceKernel { class OpenCLCalcCustomBondForceKernel : public CalcCustomBondForceKernel {
public: public:
OpenCLCalcCustomBondForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomBondForceKernel(name, platform), OpenCLCalcCustomBondForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomBondForceKernel(name, platform),
hasInitializedKernel(false), cl(cl), system(system), params(NULL), indices(NULL), globals(NULL) { hasInitializedKernel(false), cl(cl), system(system), params(NULL), globals(NULL) {
} }
~OpenCLCalcCustomBondForceKernel(); ~OpenCLCalcCustomBondForceKernel();
/** /**
...@@ -242,11 +242,9 @@ private: ...@@ -242,11 +242,9 @@ private:
OpenCLContext& cl; OpenCLContext& cl;
System& system; System& system;
OpenCLParameterSet* params; OpenCLParameterSet* params;
OpenCLArray<mm_int4>* indices;
OpenCLArray<cl_float>* globals; OpenCLArray<cl_float>* globals;
std::vector<std::string> globalParamNames; std::vector<std::string> globalParamNames;
std::vector<cl_float> globalParamValues; std::vector<cl_float> globalParamValues;
cl::Kernel kernel;
}; };
/** /**
...@@ -288,7 +286,7 @@ private: ...@@ -288,7 +286,7 @@ private:
class OpenCLCalcCustomAngleForceKernel : public CalcCustomAngleForceKernel { class OpenCLCalcCustomAngleForceKernel : public CalcCustomAngleForceKernel {
public: public:
OpenCLCalcCustomAngleForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomAngleForceKernel(name, platform), OpenCLCalcCustomAngleForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomAngleForceKernel(name, platform),
hasInitializedKernel(false), cl(cl), system(system), params(NULL), indices(NULL), globals(NULL) { hasInitializedKernel(false), cl(cl), system(system), params(NULL), globals(NULL) {
} }
~OpenCLCalcCustomAngleForceKernel(); ~OpenCLCalcCustomAngleForceKernel();
/** /**
...@@ -313,11 +311,9 @@ private: ...@@ -313,11 +311,9 @@ private:
OpenCLContext& cl; OpenCLContext& cl;
System& system; System& system;
OpenCLParameterSet* params; OpenCLParameterSet* params;
OpenCLArray<mm_int8>* indices;
OpenCLArray<cl_float>* globals; OpenCLArray<cl_float>* globals;
std::vector<std::string> globalParamNames; std::vector<std::string> globalParamNames;
std::vector<cl_float> globalParamValues; std::vector<cl_float> globalParamValues;
cl::Kernel kernel;
}; };
/** /**
...@@ -392,7 +388,7 @@ private: ...@@ -392,7 +388,7 @@ private:
class OpenCLCalcCMAPTorsionForceKernel : public CalcCMAPTorsionForceKernel { class OpenCLCalcCMAPTorsionForceKernel : public CalcCMAPTorsionForceKernel {
public: public:
OpenCLCalcCMAPTorsionForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCMAPTorsionForceKernel(name, platform), OpenCLCalcCMAPTorsionForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCMAPTorsionForceKernel(name, platform),
hasInitializedKernel(false), cl(cl), system(system), coefficients(NULL), mapPositions(NULL), torsionIndices(NULL), torsionMaps(NULL) { hasInitializedKernel(false), cl(cl), system(system), coefficients(NULL), mapPositions(NULL), torsionMaps(NULL) {
} }
~OpenCLCalcCMAPTorsionForceKernel(); ~OpenCLCalcCMAPTorsionForceKernel();
/** /**
...@@ -418,9 +414,7 @@ private: ...@@ -418,9 +414,7 @@ private:
System& system; System& system;
OpenCLArray<mm_float4>* coefficients; OpenCLArray<mm_float4>* coefficients;
OpenCLArray<mm_int2>* mapPositions; OpenCLArray<mm_int2>* mapPositions;
OpenCLArray<mm_int16>* torsionIndices;
OpenCLArray<cl_int>* torsionMaps; OpenCLArray<cl_int>* torsionMaps;
cl::Kernel kernel;
}; };
/** /**
...@@ -429,7 +423,7 @@ private: ...@@ -429,7 +423,7 @@ private:
class OpenCLCalcCustomTorsionForceKernel : public CalcCustomTorsionForceKernel { class OpenCLCalcCustomTorsionForceKernel : public CalcCustomTorsionForceKernel {
public: public:
OpenCLCalcCustomTorsionForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomTorsionForceKernel(name, platform), OpenCLCalcCustomTorsionForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomTorsionForceKernel(name, platform),
hasInitializedKernel(false), cl(cl), system(system), params(NULL), indices(NULL), globals(NULL) { hasInitializedKernel(false), cl(cl), system(system), params(NULL), globals(NULL) {
} }
~OpenCLCalcCustomTorsionForceKernel(); ~OpenCLCalcCustomTorsionForceKernel();
/** /**
...@@ -454,11 +448,9 @@ private: ...@@ -454,11 +448,9 @@ private:
OpenCLContext& cl; OpenCLContext& cl;
System& system; System& system;
OpenCLParameterSet* params; OpenCLParameterSet* params;
OpenCLArray<mm_int8>* indices;
OpenCLArray<cl_float>* globals; OpenCLArray<cl_float>* globals;
std::vector<std::string> globalParamNames; std::vector<std::string> globalParamNames;
std::vector<cl_float> globalParamValues; std::vector<cl_float> globalParamValues;
cl::Kernel kernel;
}; };
/** /**
...@@ -651,7 +643,7 @@ private: ...@@ -651,7 +643,7 @@ private:
class OpenCLCalcCustomExternalForceKernel : public CalcCustomExternalForceKernel { class OpenCLCalcCustomExternalForceKernel : public CalcCustomExternalForceKernel {
public: public:
OpenCLCalcCustomExternalForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomExternalForceKernel(name, platform), OpenCLCalcCustomExternalForceKernel(std::string name, const Platform& platform, OpenCLContext& cl, System& system) : CalcCustomExternalForceKernel(name, platform),
hasInitializedKernel(false), cl(cl), system(system), params(NULL), indices(NULL), globals(NULL) { hasInitializedKernel(false), cl(cl), system(system), params(NULL), globals(NULL) {
} }
~OpenCLCalcCustomExternalForceKernel(); ~OpenCLCalcCustomExternalForceKernel();
/** /**
...@@ -676,11 +668,9 @@ private: ...@@ -676,11 +668,9 @@ private:
OpenCLContext& cl; OpenCLContext& cl;
System& system; System& system;
OpenCLParameterSet* params; OpenCLParameterSet* params;
OpenCLArray<cl_int>* indices;
OpenCLArray<cl_float>* globals; OpenCLArray<cl_float>* globals;
std::vector<std::string> globalParamNames; std::vector<std::string> globalParamNames;
std::vector<cl_float> globalParamValues; std::vector<cl_float> globalParamValues;
cl::Kernel kernel;
}; };
/** /**
......
/** const float PI = 3.14159265358979323846f;
* Compute CNAP torsion forces.
*/
__kernel void computeCMAPTorsionForces(int numAtoms, int numTorsions, __global float4* forceBuffers, __global float* energyBuffer, // Compute the first angle.
__global float4* posq, __global float4* coeff, __global int2* mapPositions, __global int16* indices, __global int* maps) {
const float PI = 3.14159265358979323846f;
float energy = 0.0f;
for (int index = get_global_id(0); index < numTorsions; index += get_global_size(0)) {
int16 atoms = indices[index];
float4 a1 = posq[atoms.s0];
float4 a2 = posq[atoms.s1];
float4 a3 = posq[atoms.s2];
float4 a4 = posq[atoms.s3];
float4 b1 = posq[atoms.s4];
float4 b2 = posq[atoms.s5];
float4 b3 = posq[atoms.s6];
float4 b4 = posq[atoms.s7];
// Compute the first angle. float4 v0a = (float4) (pos1.xyz-pos2.xyz, 0.0f);
float4 v1a = (float4) (pos3.xyz-pos2.xyz, 0.0f);
float4 v0a = (float4) (a1.xyz-a2.xyz, 0.0f); float4 v2a = (float4) (pos3.xyz-pos4.xyz, 0.0f);
float4 v1a = (float4) (a3.xyz-a2.xyz, 0.0f); float4 cp0a = cross(v0a, v1a);
float4 v2a = (float4) (a3.xyz-a4.xyz, 0.0f); float4 cp1a = cross(v1a, v2a);
float4 cp0a = cross(v0a, v1a); float cosangle = dot(normalize(cp0a), normalize(cp1a));
float4 cp1a = cross(v1a, v2a); float angleA;
float cosangle = dot(normalize(cp0a), normalize(cp1a)); if (cosangle > 0.99f || cosangle < -0.99f) {
float 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. // We're close to the singularity in acos(), so take the cross product and use asin() instead.
float4 cross_prod = cross(cp0a, cp1a); float4 cross_prod = cross(cp0a, cp1a);
...@@ -34,22 +17,22 @@ __kernel void computeCMAPTorsionForces(int numAtoms, int numTorsions, __global f ...@@ -34,22 +17,22 @@ __kernel void computeCMAPTorsionForces(int numAtoms, int numTorsions, __global f
angleA = asin(SQRT(dot(cross_prod, cross_prod)/scale)); angleA = asin(SQRT(dot(cross_prod, cross_prod)/scale));
if (cosangle < 0.0f) if (cosangle < 0.0f)
angleA = PI-angleA; angleA = PI-angleA;
} }
else else
angleA = acos(cosangle); angleA = acos(cosangle);
angleA = (dot(v0a, cp1a) >= 0 ? angleA : -angleA); angleA = (dot(v0a, cp1a) >= 0 ? angleA : -angleA);
angleA = fmod(angleA+2.0f*PI, 2.0f*PI); angleA = fmod(angleA+2.0f*PI, 2.0f*PI);
// Compute the second angle. // Compute the second angle.
float4 v0b = (float4) (b1.xyz-b2.xyz, 0.0f); float4 v0b = (float4) (pos5.xyz-pos6.xyz, 0.0f);
float4 v1b = (float4) (b3.xyz-b2.xyz, 0.0f); float4 v1b = (float4) (pos7.xyz-pos6.xyz, 0.0f);
float4 v2b = (float4) (b3.xyz-b4.xyz, 0.0f); float4 v2b = (float4) (pos7.xyz-pos8.xyz, 0.0f);
float4 cp0b = cross(v0b, v1b); float4 cp0b = cross(v0b, v1b);
float4 cp1b = cross(v1b, v2b); float4 cp1b = cross(v1b, v2b);
cosangle = dot(normalize(cp0b), normalize(cp1b)); cosangle = dot(normalize(cp0b), normalize(cp1b));
float angleB; float angleB;
if (cosangle > 0.99f || cosangle < -0.99f) { if (cosangle > 0.99f || cosangle < -0.99f) {
// We're close to the singularity in acos(), so take the cross product and use asin() instead. // We're close to the singularity in acos(), so take the cross product and use asin() instead.
float4 cross_prod = cross(cp0b, cp1b); float4 cross_prod = cross(cp0b, cp1b);
...@@ -57,98 +40,73 @@ __kernel void computeCMAPTorsionForces(int numAtoms, int numTorsions, __global f ...@@ -57,98 +40,73 @@ __kernel void computeCMAPTorsionForces(int numAtoms, int numTorsions, __global f
angleB = asin(SQRT(dot(cross_prod, cross_prod)/scale)); angleB = asin(SQRT(dot(cross_prod, cross_prod)/scale));
if (cosangle < 0.0f) if (cosangle < 0.0f)
angleB = PI-angleB; angleB = PI-angleB;
} }
else else
angleB = acos(cosangle); angleB = acos(cosangle);
angleB = (dot(v0b, cp1b) >= 0 ? angleB : -angleB); angleB = (dot(v0b, cp1b) >= 0 ? angleB : -angleB);
angleB = fmod(angleB+2.0f*PI, 2.0f*PI); angleB = fmod(angleB+2.0f*PI, 2.0f*PI);
// Identify which patch this is in. // Identify which patch this is in.
int2 pos = mapPositions[maps[index]]; int2 pos = MAP_POS[MAPS[index]];
int size = pos.y; int size = pos.y;
float delta = 2*PI/size; float delta = 2*PI/size;
int s = (int) (angleA/delta); int s = (int) (angleA/delta);
int t = (int) (angleB/delta); int t = (int) (angleB/delta);
float4 c[4]; float4 c[4];
int coeffIndex = pos.x+4*(s+size*t); int coeffIndex = pos.x+4*(s+size*t);
c[0] = coeff[coeffIndex]; c[0] = COEFF[coeffIndex];
c[1] = coeff[coeffIndex+1]; c[1] = COEFF[coeffIndex+1];
c[2] = coeff[coeffIndex+2]; c[2] = COEFF[coeffIndex+2];
c[3] = coeff[coeffIndex+3]; c[3] = COEFF[coeffIndex+3];
float da = angleA/delta-s; float da = angleA/delta-s;
float db = angleB/delta-t; float db = angleB/delta-t;
// Evaluate the spline to determine the energy and gradients. // Evaluate the spline to determine the energy and gradients.
float torsionEnergy = 0.0f; float torsionEnergy = 0.0f;
float dEdA = 0.0f; float dEdA = 0.0f;
float dEdB = 0.0f; float dEdB = 0.0f;
torsionEnergy = da*torsionEnergy + ((c[3].w*db + c[3].z)*db + c[3].y)*db + c[3].x; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; dEdB = da*dEdB + (3.0f*c[0].w*db + 2.0f*c[0].z)*db + c[0].y;
dEdA /= delta; dEdA /= delta;
dEdB /= delta; dEdB /= delta;
energy += torsionEnergy; energy += torsionEnergy;
// Apply the force to the first torsion. // Apply the force to the first torsion.
float normCross1 = dot(cp0a, cp0a); float normCross1 = dot(cp0a, cp0a);
float normSqrBC = dot(v1a, v1a); float normSqrBC = dot(v1a, v1a);
float normBC = SQRT(normSqrBC); float normBC = SQRT(normSqrBC);
float normCross2 = dot(cp1a, cp1a); float normCross2 = dot(cp1a, cp1a);
float dp = 1.0f/normSqrBC; float dp = 1.0f/normSqrBC;
float4 ff = (float4) ((-dEdA*normBC)/normCross1, dot(v0a, v1a)*dp, dot(v2a, v1a)*dp, (dEdA*normBC)/normCross2); float4 ff = (float4) ((-dEdA*normBC)/normCross1, dot(v0a, v1a)*dp, dot(v2a, v1a)*dp, (dEdA*normBC)/normCross2);
float4 internalF0 = ff.x*cp0a; float4 force1 = ff.x*cp0a;
float4 internalF3 = ff.w*cp1a; float4 force4 = ff.w*cp1a;
float4 d = ff.y*internalF0 - ff.z*internalF3; float4 d = ff.y*force1 - ff.z*force4;
int4 offset = atoms.lo.lo + numAtoms*atoms.hi.lo; float4 force2 = d-force1;
float4 forceA = forceBuffers[offset.x]; float4 force3 = -d-force4;
float4 forceB = forceBuffers[offset.y];
float4 forceC = forceBuffers[offset.z];
float4 forceD = forceBuffers[offset.w];
forceA.xyz += internalF0.xyz;
forceB.xyz += d.xyz-internalF0.xyz;
forceC.xyz += -d.xyz-internalF3.xyz;
forceD.xyz += internalF3.xyz;
forceBuffers[offset.x] = forceA;
forceBuffers[offset.y] = forceB;
forceBuffers[offset.z] = forceC;
forceBuffers[offset.w] = forceD;
// Apply the force to the second torsion. // Apply the force to the second torsion.
normCross1 = dot(cp0b, cp0b); normCross1 = dot(cp0b, cp0b);
normSqrBC = dot(v1b, v1b); normSqrBC = dot(v1b, v1b);
normBC = SQRT(normSqrBC); normBC = SQRT(normSqrBC);
normCross2 = dot(cp1b, cp1b); normCross2 = dot(cp1b, cp1b);
dp = 1.0f/normSqrBC; dp = 1.0f/normSqrBC;
ff = (float4) ((-dEdB*normBC)/normCross1, dot(v0b, v1b)*dp, dot(v2b, v1b)*dp, (dEdB*normBC)/normCross2); ff = (float4) ((-dEdB*normBC)/normCross1, dot(v0b, v1b)*dp, dot(v2b, v1b)*dp, (dEdB*normBC)/normCross2);
internalF0 = ff.x*cp0b; float4 force5 = ff.x*cp0b;
internalF3 = ff.w*cp1b; float4 force8 = ff.w*cp1b;
d = ff.y*internalF0 - ff.z*internalF3; d = ff.y*force5 - ff.z*force8;
offset = atoms.lo.hi + numAtoms*atoms.hi.hi; float4 force6 = d-force5;
forceA = forceBuffers[offset.x]; float4 force7 = -d-force8;
forceB = forceBuffers[offset.y];
forceC = forceBuffers[offset.z];
forceD = forceBuffers[offset.w];
forceA.xyz += internalF0.xyz;
forceB.xyz += d.xyz-internalF0.xyz;
forceC.xyz += -d.xyz-internalF3.xyz;
forceD.xyz += internalF3.xyz;
forceBuffers[offset.x] = forceA;
forceBuffers[offset.y] = forceB;
forceBuffers[offset.z] = forceC;
forceBuffers[offset.w] = forceD;
}
energyBuffer[get_global_id(0)] += energy;
}
/** float4 v0 = pos2-pos1;
* Compute custom angle forces. float4 v1 = pos2-pos3;
*/ float4 cp = cross(v0, v1);
float rp = cp.x*cp.x + cp.y*cp.y + cp.z*cp.z;
__kernel void computeCustomAngleForces(int numAtoms, int numAngles, __global float4* forceBuffers, __global float* energyBuffer, rp = max(sqrt(rp), 1.0e-06f);
__global float4* posq, __global int8* indices float r21 = v0.x*v0.x + v0.y*v0.y + v0.z*v0.z;
EXTRA_ARGUMENTS) { float r23 = v1.x*v1.x + v1.y*v1.y + v1.z*v1.z;
float energy = 0.0f; float dot = v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;
for (int index = get_global_id(0); index < numAngles; index += get_global_size(0)) { float cosine = clamp(dot/sqrt(r21*r23), -1.0f, 1.0f);
int8 atoms = indices[index]; float theta = acos(cosine);
float4 a1 = posq[atoms.s0]; COMPUTE_FORCE
float4 a2 = posq[atoms.s1]; float4 force1 = cross(v0, cp)*(dEdAngle/(r21*rp));
float4 a3 = posq[atoms.s2]; float4 force3 = cross(cp, v1)*(dEdAngle/(r23*rp));
float4 force2 = -force1-force3;
// Compute the force.
float4 v0 = a2-a1;
float4 v1 = a2-a3;
float4 cp = cross(v0, v1);
float rp = cp.x*cp.x + cp.y*cp.y + cp.z*cp.z;
rp = max(sqrt(rp), 1.0e-06f);
float r21 = v0.x*v0.x + v0.y*v0.y + v0.z*v0.z;
float r23 = v1.x*v1.x + v1.y*v1.y + v1.z*v1.z;
float dot = v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;
float cosine = clamp(dot/sqrt(r21*r23), -1.0f, 1.0f);
float theta = acos(cosine);
COMPUTE_FORCE
float4 c21 = cross(v0, cp)*(dEdAngle/(r21*rp));
float4 c23 = cross(cp, v1)*(dEdAngle/(r23*rp));
// Record the force on each of the three atoms.
unsigned int offsetA = atoms.s0+atoms.s3*numAtoms;
unsigned int offsetB = atoms.s1+atoms.s4*numAtoms;
unsigned int offsetC = atoms.s2+atoms.s5*numAtoms;
float4 forceA = forceBuffers[offsetA];
float4 forceB = forceBuffers[offsetB];
float4 forceC = forceBuffers[offsetC];
forceA.xyz += c21.xyz;
forceB.xyz -= c21.xyz+c23.xyz;
forceC.xyz += c23.xyz;
forceBuffers[offsetA] = forceA;
forceBuffers[offsetB] = forceB;
forceBuffers[offsetC] = forceC;
}
energyBuffer[get_global_id(0)] += energy;
}
/** float4 delta = pos2-pos1;
* Compute custom bond forces. float r = SQRT(delta.x*delta.x + delta.y*delta.y + delta.z*delta.z);
*/ COMPUTE_FORCE
delta.xyz *= -dEdR/r;
__kernel void computeCustomBondForces(int numAtoms, int numBonds, __global float4* forceBuffers, __global float* energyBuffer, float4 force1 = -delta;
__global float4* posq, __global int4* indices float4 force2 = delta;
EXTRA_ARGUMENTS) {
float energy = 0.0f;
for (int index = get_global_id(0); index < numBonds; index += get_global_size(0)) {
// Look up the data for this bond.
int4 atoms = indices[index];
float4 delta = posq[atoms.y]-posq[atoms.x];
// Compute the force.
float r = SQRT(delta.x*delta.x + delta.y*delta.y + delta.z*delta.z);
COMPUTE_FORCE
delta.xyz *= -dEdR/r;
// Record the force on each of the two atoms.
unsigned int offsetA = atoms.x+atoms.z*numAtoms;
unsigned int offsetB = atoms.y+atoms.w*numAtoms;
float4 forceA = forceBuffers[offsetA];
float4 forceB = forceBuffers[offsetB];
forceA.xyz -= delta.xyz;
forceB.xyz += delta.xyz;
forceBuffers[offsetA] = forceA;
forceBuffers[offsetB] = forceB;
}
energyBuffer[get_global_id(0)] += energy;
}
/** COMPUTE_FORCE
* Compute custom external forces. float4 force1 = (float4) (-dEdX, -dEdY, -dEdZ, 0.0f);
*/
__kernel void computeCustomExternalForces(int numTerms, __global float4* forceBuffers, __global float* energyBuffer,
__global float4* posq, __global int* indices
EXTRA_ARGUMENTS) {
float energy = 0.0f;
for (int index = get_global_id(0); index < numTerms; index += get_global_size(0)) {
// Look up the data for this particle.
int atom = indices[index];
float4 pos = posq[atom];
// Compute the force.
COMPUTE_FORCE
// Record the force on the atom.
float4 force = forceBuffers[atom];
force.x -= dEdX;
force.y -= dEdY;
force.z -= dEdZ;
forceBuffers[atom] = force;
}
energyBuffer[get_global_id(0)] += energy;
}
/** float4 v0 = (float4) (pos1.xyz-pos2.xyz, 0.0f);
* Compute custom torsion forces. float4 v1 = (float4) (pos3.xyz-pos2.xyz, 0.0f);
*/ float4 v2 = (float4) (pos3.xyz-pos4.xyz, 0.0f);
float4 cp0 = cross(v0, v1);
__kernel void computeCustomTorsionForces(int numAtoms, int numTorsions, __global float4* forceBuffers, __global float* energyBuffer, float4 cp1 = cross(v1, v2);
__global float4* posq, __global int8* indices float cosangle = dot(normalize(cp0), normalize(cp1));
EXTRA_ARGUMENTS) { float theta;
float energy = 0.0f; if (cosangle > 0.99f || cosangle < -0.99f) {
for (int index = get_global_id(0); index < numTorsions; index += get_global_size(0)) {
int8 atoms = indices[index];
float4 a1 = posq[atoms.s0];
float4 a2 = posq[atoms.s1];
float4 a3 = posq[atoms.s2];
float4 a4 = posq[atoms.s3];
// Compute the force.
float4 v0 = (float4) (a1.xyz-a2.xyz, 0.0f);
float4 v1 = (float4) (a3.xyz-a2.xyz, 0.0f);
float4 v2 = (float4) (a3.xyz-a4.xyz, 0.0f);
float4 cp0 = cross(v0, v1);
float4 cp1 = cross(v1, v2);
float cosangle = dot(normalize(cp0), normalize(cp1));
float 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. // We're close to the singularity in acos(), so take the cross product and use asin() instead.
float4 cross_prod = cross(cp0, cp1); float4 cross_prod = cross(cp0, cp1);
...@@ -30,39 +13,19 @@ __kernel void computeCustomTorsionForces(int numAtoms, int numTorsions, __global ...@@ -30,39 +13,19 @@ __kernel void computeCustomTorsionForces(int numAtoms, int numTorsions, __global
theta = asin(sqrt(dot(cross_prod, cross_prod)/scale)); theta = asin(sqrt(dot(cross_prod, cross_prod)/scale));
if (cosangle < 0.0f) if (cosangle < 0.0f)
theta = M_PI-theta; theta = M_PI-theta;
}
else
theta = acos(cosangle);
theta = (dot(v0, cp1) >= 0 ? theta : -theta);
COMPUTE_FORCE
float normCross1 = dot(cp0, cp0);
float normSqrBC = dot(v1, v1);
float normBC = sqrt(normSqrBC);
float normCross2 = dot(cp1, cp1);
float dp = 1.0f/normSqrBC;
float4 ff = (float4) ((-dEdAngle*normBC)/normCross1, dot(v0, v1)*dp, dot(v2, v1)*dp, (dEdAngle*normBC)/normCross2);
float4 internalF0 = ff.x*cp0;
float4 internalF3 = ff.w*cp1;
float4 s = ff.y*internalF0 - ff.z*internalF3;
// Record the force on each of the four atoms.
unsigned int offsetA = atoms.s0+atoms.s4*numAtoms;
unsigned int offsetB = atoms.s1+atoms.s5*numAtoms;
unsigned int offsetC = atoms.s2+atoms.s6*numAtoms;
unsigned int offsetD = atoms.s3+atoms.s7*numAtoms;
float4 forceA = forceBuffers[offsetA];
float4 forceB = forceBuffers[offsetB];
float4 forceC = forceBuffers[offsetC];
float4 forceD = forceBuffers[offsetD];
forceA.xyz += internalF0.xyz;
forceB.xyz += s.xyz-internalF0.xyz;
forceC.xyz += -s.xyz-internalF3.xyz;
forceD.xyz += internalF3.xyz;
forceBuffers[offsetA] = forceA;
forceBuffers[offsetB] = forceB;
forceBuffers[offsetC] = forceC;
forceBuffers[offsetD] = forceD;
}
energyBuffer[get_global_id(0)] += energy;
} }
else
theta = acos(cosangle);
theta = (dot(v0, cp1) >= 0 ? theta : -theta);
COMPUTE_FORCE
float normCross1 = dot(cp0, cp0);
float normSqrBC = dot(v1, v1);
float normBC = sqrt(normSqrBC);
float normCross2 = dot(cp1, cp1);
float dp = 1.0f/normSqrBC;
float4 ff = (float4) ((-dEdAngle*normBC)/normCross1, dot(v0, v1)*dp, dot(v2, v1)*dp, (dEdAngle*normBC)/normCross2);
float4 force1 = ff.x*cp0;
float4 force4 = ff.w*cp1;
float4 s = ff.y*force1 - ff.z*force4;
float4 force2 = s-force1;
float4 force3 = -s-force4;
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