From 0a62f60085e943e8d6b1a9e59c1da5e565235221 Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Wed, 24 Jun 2020 18:03:20 -0500 Subject: [PATCH] Changed BondAngle to be the product of the energy of potentials applied to the central bond and two angles formed by four particles --- src/Angle.cu | 20 +++---- src/Angle.h | 73 ++++++++++++------------- src/ComputeForce.cu | 18 +++---- src/ComputeForce.cuh | 17 +++--- src/ComputeForce.h | 4 +- src/Configuration.cpp | 18 ++++--- src/GrandBrownTown.cu | 14 ++--- src/GrandBrownTown.h | 2 +- src/TabulatedMethods.cuh | 112 ++++++++++++++++++++++++--------------- 9 files changed, 154 insertions(+), 124 deletions(-) diff --git a/src/Angle.cu b/src/Angle.cu index 28facb7..2201187 100644 --- a/src/Angle.cu +++ b/src/Angle.cu @@ -15,15 +15,15 @@ String Angle::toString() return String("ANGLE ") + ind1 + " " + ind2 + " " + ind3 + " " + fileName; } -void BondAngle::print() -{ -// printf("about to print fileName %p\n", fileName.val()); -// fileName.print(); - printf("BONDANGLE (%d %d %d) %s; %s; %s\n", ind1, ind2, ind3, angleFileName.val(), bondFileName1.val(), bondFileName2.val()); -} +// void BondAngle::print() +// { +// // printf("about to print fileName %p\n", fileName.val()); +// // fileName.print(); +// printf("BONDANGLE (%d %d %d) %s; %s; %s\n", ind1, ind2, ind3, angleFileName.val(), bondFileName1.val(), bondFileName2.val()); +// } -String BondAngle::toString() -{ - return String("BONDANGLE ") + ind1 + " " + ind2 + " " + ind3 + " " + angleFileName + " " + bondFileName1 + " " + bondFileName2; -} +// String BondAngle::toString() +// { +// return String("BONDANGLE ") + ind1 + " " + ind2 + " " + ind3 + " " + angleFileName + " " + bondFileName1 + " " + bondFileName2; +// } diff --git a/src/Angle.h b/src/Angle.h index a8794e8..e03a779 100644 --- a/src/Angle.h +++ b/src/Angle.h @@ -65,14 +65,14 @@ class BondAngle { public: BondAngle() {} - BondAngle(int ind1, int ind2, int ind3, String angleFileName, String bondFileName1, String bondFileName2) : - ind1(ind1), ind2(ind2), ind3(ind3), angleFileName(angleFileName), bondFileName1(bondFileName1), bondFileName2(bondFileName2), tabFileIndex1(-1), tabFileIndex2(-1), tabFileIndex3(-1) { } + BondAngle(int ind1, int ind2, int ind3, int ind4, String angleFileName1, String bondFileName, String angleFileName2) : + ind1(ind1), ind2(ind2), ind3(ind3), ind4(ind4), angleFileName1(angleFileName1), bondFileName(bondFileName), angleFileName2(angleFileName2), tabFileIndex1(-1), tabFileIndex2(-1), tabFileIndex3(-1) { } - int ind1, ind2, ind3; + int ind1, ind2, ind3, ind4; - String angleFileName; - String bondFileName1; - String bondFileName2; + String angleFileName1; + String bondFileName; + String angleFileName2; // tabFileIndex will be assigned after ComputeForce loads the // TabulatedAnglePotentials. The tabefileIndex is used by ComputeForce to // discern which TabulatedAnglePotential this Angle uses. @@ -80,38 +80,35 @@ public: int tabFileIndex2; int tabFileIndex3; - inline BondAngle(const BondAngle& a) : ind1(a.ind1), ind2(a.ind2), ind3(a.ind3), - angleFileName(a.angleFileName), - bondFileName1(a.bondFileName1), - bondFileName2(a.bondFileName2), - tabFileIndex1(a.tabFileIndex1), - tabFileIndex2(a.tabFileIndex2), - tabFileIndex3(a.tabFileIndex3) { } - - HOST DEVICE inline float calcAngle(Vector3* pos, BaseGrid* sys) { - const Vector3& posa = pos[ind1]; - const Vector3& posb = pos[ind2]; - const Vector3& posc = pos[ind3]; - const float distab = sys->wrapDiff(posa - posb).length(); - const float distbc = sys->wrapDiff(posb - posc).length(); - const float distac = sys->wrapDiff(posc - posa).length(); - float cos = (distbc * distbc + distab * distab - distac * distac) - / (2.0f * distbc * distab); - if (cos < -1.0f) cos = -1.0f; - else if (cos > 1.0f) cos = 1.0f; - float angle = acos(cos); - return angle; - } - - HOST DEVICE inline int getIndex(int index) { - if (index == ind1) return 1; - if (index == ind2) return 2; - if (index == ind3) return 3; - return -1; - } - - String toString(); - void print(); + inline BondAngle(const BondAngle& a) : ind1(a.ind1), ind2(a.ind2), ind3(a.ind3), ind4(a.ind4), + angleFileName1(a.angleFileName1), bondFileName(a.bondFileName), angleFileName2(a.angleFileName2), + tabFileIndex1(a.tabFileIndex1), tabFileIndex2(a.tabFileIndex2), tabFileIndex3(a.tabFileIndex3) { } + + // HOST DEVICE inline float calcAngle(Vector3* pos, BaseGrid* sys) { + // const Vector3& posa = pos[ind1]; + // const Vector3& posb = pos[ind2]; + // const Vector3& posc = pos[ind3]; + // const float distab = sys->wrapDiff(posa - posb).length(); + // const float distbc = sys->wrapDiff(posb - posc).length(); + // const float distac = sys->wrapDiff(posc - posa).length(); + // float cos = (distbc * distbc + distab * distab - distac * distac) + // / (2.0f * distbc * distab); + // if (cos < -1.0f) cos = -1.0f; + // else if (cos > 1.0f) cos = 1.0f; + // float angle = acos(cos); + // return angle; + // } + + // HOST DEVICE inline int getIndex(int index) { + // if (index == ind1) return 1; + // if (index == ind2) return 2; + // if (index == ind3) return 3; + // if (index == ind4) return 4; + // return -1; + // } + + // String toString(); + // void print(); }; #endif diff --git a/src/ComputeForce.cu b/src/ComputeForce.cu index c66fb14..60bc945 100644 --- a/src/ComputeForce.cu +++ b/src/ComputeForce.cu @@ -419,10 +419,8 @@ bool ComputeForce::addBondPotential(String fileName, int ind, Bond bonds[], Bond for (int i = 0; i < numBondAngles; i++) { - if (bondAngles[i].bondFileName1 == fileName) + if (bondAngles[i].bondFileName == fileName) bondAngles[i].tabFileIndex2 = ind; - if (bondAngles[i].bondFileName2 == fileName) - bondAngles[i].tabFileIndex3 = ind; } gpuErrchk(cudaMemcpyAsync(bonds_d, bonds, sizeof(Bond) * numBonds, cudaMemcpyHostToDevice)); @@ -462,10 +460,12 @@ bool ComputeForce::addAnglePotential(String fileName, int ind, Angle* angles, Bo if (angles[i].fileName == fileName) angles[i].tabFileIndex = ind; - for (int i = 0; i < numBondAngles; i++) - if (bondAngles[i].angleFileName == fileName) - bondAngles[i].tabFileIndex1 = ind; - + for (int i = 0; i < numBondAngles; i++) { + if (bondAngles[i].angleFileName1 == fileName) + bondAngles[i].tabFileIndex1 = ind; + if (bondAngles[i].angleFileName2 == fileName) + bondAngles[i].tabFileIndex3 = ind; + } gpuErrchk(cudaMemcpy(angles_d, angles, sizeof(Angle) * numAngles, cudaMemcpyHostToDevice)); return true; @@ -979,7 +979,7 @@ void ComputeForce::copyToCUDA(int simNum, int *type, Bond* bonds, int2* bondMap, // } // } -void ComputeForce::copyBondedListsToGPU(int3 *bondList, int4 *angleList, int4 *dihedralList, int *dihedralPotList, int2* bondAngleList) { +void ComputeForce::copyBondedListsToGPU(int3 *bondList, int4 *angleList, int4 *dihedralList, int *dihedralPotList, int4* bondAngleList) { size_t size; @@ -1007,7 +1007,7 @@ void ComputeForce::copyBondedListsToGPU(int3 *bondList, int4 *angleList, int4 *d } if (numBondAngles > 0) { - size = 3*numBondAngles * numReplicas * sizeof(int2); + size = 2*numBondAngles * numReplicas * sizeof(int4); gpuErrchk( cudaMalloc( &bondAngleList_d, size ) ); gpuErrchk( cudaMemcpyAsync( bondAngleList_d, bondAngleList, size, cudaMemcpyHostToDevice) ); } diff --git a/src/ComputeForce.cuh b/src/ComputeForce.cuh index 16de742..bbbce8c 100644 --- a/src/ComputeForce.cuh +++ b/src/ComputeForce.cuh @@ -869,20 +869,21 @@ __global__ void computeTabulatedBondAngles(Vector3* force, Vector3* __restrict__ pos, BaseGrid* __restrict__ sys, - int numBondAngles, int2* __restrict__ bondAngleList_d, TabulatedAnglePotential** tableAngle, + int numBondAngles, int4* __restrict__ bondAngleList_d, TabulatedAnglePotential** tableAngle, TabulatedPotential** tableBond, float* energy, bool get_energy) { // Loop over ALL angles in ALL replicas for (int i = threadIdx.x+blockIdx.x*blockDim.x; i<numBondAngles; i+=blockDim.x*gridDim.x) { - int atom1 = bondAngleList_d[3*i ].x; - int atom2 = bondAngleList_d[3*i ].y; - int atom3 = bondAngleList_d[3*i+1].x; + int atom1 = bondAngleList_d[2*i].x; + int atom2 = bondAngleList_d[2*i].y; + int atom3 = bondAngleList_d[2*i].z; + int atom4 = bondAngleList_d[2*i].w; - int angleInd = bondAngleList_d[3*i+1].y; - int bondInd1 = bondAngleList_d[3*i+2].x; - int bondInd2 = bondAngleList_d[3*i+2].y; + int angleInd1 = bondAngleList_d[2*i+1].x; + int bondInd = bondAngleList_d[2*i+1].y; + int angleInd2 = bondAngleList_d[2*i+1].z; - computeBondAngle(tableAngle[ angleInd ], tableBond[ bondInd1 ], tableBond[ bondInd2 ], sys, force, pos, atom1, atom2, atom3, energy, get_energy); + computeBondAngle(tableAngle[ angleInd1 ], tableBond[ bondInd ], tableAngle[ angleInd2 ], sys, force, pos, atom1, atom2, atom3, atom4, energy, get_energy); } } diff --git a/src/ComputeForce.h b/src/ComputeForce.h index 08269d5..d4b8322 100644 --- a/src/ComputeForce.h +++ b/src/ComputeForce.h @@ -80,7 +80,7 @@ public: void copyToCUDA(Vector3* forceInternal, Vector3* pos, Vector3* mom, float* random); // void createBondList(int3 *bondList); - void copyBondedListsToGPU(int3 *bondList, int4 *angleList, int4 *dihedralList, int *dihedralPotList, int2 *bondAngleList); + void copyBondedListsToGPU(int3 *bondList, int4 *angleList, int4 *dihedralList, int *dihedralPotList, int4 *bondAngleList); //MLog: because of the move of a lot of private variables, some functions get starved necessary memory access to these variables, below is a list of functions that return the specified private variable. std::vector<Vector3*> getPos_d() @@ -251,7 +251,7 @@ private: int numBondAngles; BondAngle* bondAngles_d; - int2* bondAngleList_d; + int4* bondAngleList_d; int3* bondList_d; int4* angleList_d; diff --git a/src/Configuration.cpp b/src/Configuration.cpp index a6f06b8..e12f811 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -1962,7 +1962,7 @@ void Configuration::readBondAngles() { // Legitimate BONDANGLE inputs have 7 tokens // BONDANGLE | INDEX1 | INDEX2 | INDEX3 | ANGLE_FILENAME | BOND_FILENAME1 | BOND_FILENAME2 // Any angle input line without exactly 5 tokens should be discarded - if (numTokens != 7) { + if (numTokens != 8) { printf("WARNING: Invalid bond_angle input line: %s\n", line); continue; } @@ -1974,11 +1974,12 @@ void Configuration::readBondAngles() { int ind1 = atoi(tokenList[1].val()); int ind2 = atoi(tokenList[2].val()); int ind3 = atoi(tokenList[3].val()); - String file_name1 = tokenList[4]; - String file_name2 = tokenList[5]; - String file_name3 = tokenList[6]; + int ind4 = atoi(tokenList[4].val()); + String file_name1 = tokenList[5]; + String file_name2 = tokenList[6]; + String file_name3 = tokenList[7]; //printf("file_name %s\n", file_name.val()); - if (ind1 >= num or ind2 >= num or ind3 >= num) + if (ind1 >= num or ind2 >= num or ind3 >= num or ind4 >= num) continue; if (numBondAngles >= capacity) { @@ -1990,7 +1991,7 @@ void Configuration::readBondAngles() { delete[] temp; } - BondAngle a(ind1, ind2, ind3, file_name1, file_name2, file_name3); + BondAngle a(ind1, ind2, ind3, ind4, file_name1, file_name2, file_name3); bondAngles[numBondAngles++] = a; delete[] tokenList; } @@ -2607,5 +2608,8 @@ bool Configuration::compare::operator()(const BondAngle& lhs, const BondAngle& r diff = lhs.ind2 - rhs.ind2; if (diff != 0) return lhs.ind2 < rhs.ind2; - return lhs.ind3 < rhs.ind3; + diff = lhs.ind3 - rhs.ind3; + if (diff != 0) + return lhs.ind3 < rhs.ind3; + return lhs.ind4 < rhs.ind4; } diff --git a/src/GrandBrownTown.cu b/src/GrandBrownTown.cu index 7ea4cd2..6353b8a 100644 --- a/src/GrandBrownTown.cu +++ b/src/GrandBrownTown.cu @@ -379,25 +379,25 @@ GrandBrownTown::GrandBrownTown(const Configuration& c, const char* outArg, } if (numBondAngles > 0) { - bondAngleList = new int2[ (numBondAngles*3) * numReplicas ]; + bondAngleList = new int4[ (numBondAngles*2) * numReplicas ]; for(int k = 0 ; k < numReplicas; k++) { for(int i = 0; i < numBondAngles; ++i) { if (bondAngles[i].tabFileIndex1 == -1) { - fprintf(stderr,"Error: bondanglefile '%s' was not read with tabulatedAngleFile command.\n", bondAngles[i].angleFileName.val()); + fprintf(stderr,"Error: bondanglefile '%s' was not read with tabulatedAngleFile command.\n", bondAngles[i].angleFileName1.val()); exit(1); } if (bondAngles[i].tabFileIndex2 == -1) { - fprintf(stderr,"Error: bondanglefile1 '%s' was not read with tabulatedBondFile command.\n", bondAngles[i].bondFileName1.val()); + fprintf(stderr,"Error: bondanglefile1 '%s' was not read with tabulatedBondFile command.\n", bondAngles[i].bondFileName.val()); exit(1); } if (bondAngles[i].tabFileIndex3 == -1) { - fprintf(stderr,"Error: bondanglefile2 '%s' was not read with tabulatedBondFile command.\n", bondAngles[i].bondFileName2.val()); + fprintf(stderr,"Error: bondanglefile2 '%s' was not read with tabulatedBondFile command.\n", bondAngles[i].angleFileName2.val()); exit(1); } int idx = i+k*numBondAngles; - bondAngleList[idx*3] = make_int2( bondAngles[i].ind1+k*num, bondAngles[i].ind2+k*num ); - bondAngleList[idx*3+1] = make_int2( bondAngles[i].ind3+k*num, bondAngles[i].tabFileIndex1 ); - bondAngleList[idx*3+2] = make_int2( bondAngles[i].tabFileIndex2, bondAngles[i].tabFileIndex3 ); + bondAngleList[idx*2] = make_int4( bondAngles[i].ind1+k*num, bondAngles[i].ind2+k*num, + bondAngles[i].ind3+k*num, bondAngles[i].ind4+k*num ); + bondAngleList[idx*2+1] = make_int4( bondAngles[i].tabFileIndex1, bondAngles[i].tabFileIndex2, bondAngles[i].tabFileIndex3, -1 ); } } } diff --git a/src/GrandBrownTown.h b/src/GrandBrownTown.h index c74ca2b..ce7f19c 100644 --- a/src/GrandBrownTown.h +++ b/src/GrandBrownTown.h @@ -277,7 +277,7 @@ private: int numBondAngles; BondAngle* bondAngles; - int2 *bondAngleList; + int4 *bondAngleList; //Han-Yi Chou String particle_dynamic; diff --git a/src/TabulatedMethods.cuh b/src/TabulatedMethods.cuh index 7965c77..c775a6b 100644 --- a/src/TabulatedMethods.cuh +++ b/src/TabulatedMethods.cuh @@ -2,6 +2,14 @@ // Defined elsewhere: constexpr float BD_PI = 3.1415927f; +struct AngleForce { + __host__ __device__ + AngleForce(Vector3 f1, Vector3 f3, float e) : f1(f1), f3(f3), e(e) { } + Vector3 f1; + Vector3 f3; + float e; +}; + __device__ inline void computeAngle(const TabulatedAnglePotential* __restrict__ a, const BaseGrid* __restrict__ sys, Vector3* force, const Vector3* __restrict__ pos, const int& i, const int& j, const int& k, float* energy, bool get_energy) { @@ -77,43 +85,31 @@ __device__ inline void computeAngle(const TabulatedAnglePotential* __restrict__ atomicAdd( &force[k], force3 ); } -__device__ inline void computeBondAngle(const TabulatedAnglePotential* __restrict__ a, - const TabulatedPotential* __restrict__ b1, const TabulatedPotential* __restrict__ b2, - const BaseGrid* __restrict__ sys, Vector3* force, const Vector3* __restrict__ pos, - const int& i, const int& j, const int& k, float* energy, bool get_energy) { - - // Particle's type and position - Vector3 posa = pos[i]; - Vector3 posb = pos[j]; - Vector3 posc = pos[k]; - - // The vectors between each pair of particles - const Vector3 ab = sys->wrapDiff(posa - posb); - const Vector3 bc = sys->wrapDiff(posb - posc); - const Vector3 ac = sys->wrapDiff(posc - posa); - +__device__ inline AngleForce calcAngle(const TabulatedAnglePotential* __restrict__ a, const Vector3 ab, const Vector3 bc, const Vector3 ac) { + // // The vectors between each pair of particles + // const Vector3 ab = sys->wrapDiff(posa - posb); + // const Vector3 bc = sys->wrapDiff(posb - posc); + // const Vector3 ac = sys->wrapDiff(posc - posa); + // Find the distance between each pair of particles float distab = ab.length2(); float distbc = bc.length2(); - EnergyForce fe_b1 = b1->compute(ab,distab); - EnergyForce fe_b2 = b2->compute(bc,distbc); - const float distac2 = ac.length2(); - - // Find the cosine of the angle we want - <ABC + + // Find the cosine of the angle we want - <ABC float cos = (distab + distbc - distac2); distab = 1.0f/sqrt(distab); //TODO: test other functiosn distbc = 1.0f/sqrt(distbc); cos *= 0.5f * distbc * distab; - + // If the cosine is illegitimate, set it to 1 or -1 so that acos won't fail if (cos < -1.0f) cos = -1.0f; if (cos > 1.0f) cos = 1.0f; // Find the sine while we're at it. - // Now we can use the cosine to find the actual angle (in radians) + // Now we can use the cosine to find the actual angle (in radians) float angle = acos(cos); // transform angle to units of tabulated array index @@ -121,42 +117,74 @@ __device__ inline void computeBondAngle(const TabulatedAnglePotential* __restric // tableAngle[0] stores the potential at angle_step // tableAngle[1] stores the potential at angle_step * 2, etc. - // 'home' is the index after which 'convertedAngle' would appear if it were stored in the table + // 'home' is the index after which 'convertedAngle' would appear if it were stored in the table int home = int(floorf(angle)); - home = (home >= a->size) ? (a->size)-1 : home; + home = (home >= a->size) ? (a->size)-1 : home; //assert(home >= 0); //assert(home+1 < a->size); // // Make angle the distance from [0,1) from the first index in the potential array index // angle -= home; - - // Linearly interpolate the potential + + // Linearly interpolate the potential float U0 = a->pot[home]; float dUdx = (a->pot[(((home+1)==(a->size)) ? (a->size)-1 : home+1)] - U0) * a->angle_step_inv; - float a_e = (dUdx * (angle-home)) + U0; - if(get_energy) - { - float e = a_e * fe_b1.e * fe_b2.e * 0.3333333333f; - atomicAdd( &energy[i], e); - atomicAdd( &energy[j], e); - atomicAdd( &energy[k], e); - } + float e = ((dUdx * (angle-home)) + U0); + float sin = sqrtf(1.0f - cos*cos); - dUdx /= abs(sin) > 1e-3 ? sin : 1e-3; // avoid singularity + dUdx /= abs(sin) > 1e-3 ? sin : 1e-3; // avoid singularity // Calculate the forces Vector3 force1 = -(dUdx*distab) * (ab * (cos*distab) + bc * distbc); // force on particle 1 Vector3 force3 = (dUdx*distbc) * (bc * (cos*distbc) + ab * distab); // force on particle 3 - force1 = (force1 * fe_b1.e - a_e * fe_b1.f) * fe_b2.e; - force3 = (force3 * fe_b2.e + a_e * fe_b2.f) * fe_b1.e; + return AngleForce(force1,force3,e); +} - // assert( force1.length() < 10000.0f ); - // assert( force3.length() < 10000.0f ); +__device__ inline void computeBondAngle(const TabulatedAnglePotential* __restrict__ a1, + const TabulatedPotential* __restrict__ b, const TabulatedAnglePotential* __restrict__ a2, + const BaseGrid* __restrict__ sys, Vector3* force, const Vector3* __restrict__ pos, + const int& i, const int& j, const int& k, const int& l, float* energy, bool get_energy) { - atomicAdd( &force[i], force1 ); - atomicAdd( &force[j], -(force1 + force3) ); - atomicAdd( &force[k], force3 ); + // Particle's type and position + Vector3 posa = pos[i]; + Vector3 posb = pos[j]; + Vector3 posc = pos[k]; + Vector3 posd = pos[l]; + + // The vectors between each pair of particles + const Vector3 ab = sys->wrapDiff(posb - posa); + const Vector3 bc = sys->wrapDiff(posc - posb); + const Vector3 ca = sys->wrapDiff(posc - posa); + AngleForce fe_a1 = calcAngle(a1, -ab,-bc,ca); + + float distbc = bc.length2(); + EnergyForce fe_b = b->compute(bc,distbc); + + const Vector3 cd = sys->wrapDiff(posd - posc); + const Vector3 db = sys->wrapDiff(posd - posb); + AngleForce fe_a2 = calcAngle(a2, -bc,-cd,db); + + if(get_energy) + { + float e = fe_a1.e * fe_b.e * fe_a2.e * 0.25f; + atomicAdd( &energy[i], e); + atomicAdd( &energy[j], e); + atomicAdd( &energy[k], e); + atomicAdd( &energy[l], e); + } + atomicAdd( &force[i], fe_a1.f1 * fe_b.e * fe_a2.e ); + atomicAdd( &force[j], + -(fe_a1.f1 + fe_a1.f3) * fe_b.e * fe_a2.e + + fe_b.f * fe_a1.e * fe_a2.e + + fe_a2.f1 * fe_b.e * fe_a1.e + ); + atomicAdd( &force[k], + fe_a1.f3 * fe_b.e * fe_a2.e + - fe_b.f * fe_a1.e * fe_a2.e + - (fe_a2.f1 + fe_a2.f3) * fe_b.e * fe_a1.e + ); + atomicAdd( &force[l], fe_a2.f3 * fe_b.e * fe_a1.e ); } -- GitLab