From 6f782b6d68d1622657df98d99f5656cf92119d1f Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Tue, 11 Aug 2020 13:27:18 -0500 Subject: [PATCH] Added 4-particle vecangle potential; untested, and configuration.cpp still needs to build the potential dictionary using type,filename tuples as keys --- src/Configuration.cpp | 45 +++++++++++++------ src/TabulatedPotential.h | 93 +++++++++++++++++++++++++++++----------- 2 files changed, 100 insertions(+), 38 deletions(-) diff --git a/src/Configuration.cpp b/src/Configuration.cpp index b08fdd3..5b3412a 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -2048,7 +2048,7 @@ void Configuration::readProductPotentials() { printf("\rDEBUG: reading line %d",numProductPotentials+1); // Legitimate ProductPotential inputs have at least 7 tokens - // BONDANGLE | INDEX1 | INDEX2 | INDEX3 | POT_FILENAME1 | INDEX4 | INDEX5 | POT_FILENAME2 ... + // BONDANGLE | INDEX1 | INDEX2 | INDEX3 | [TYPE1] | POT_FILENAME1 | INDEX4 | INDEX5 | [TYPE2] POT_FILENAME2 ... if (numTokens < 7) { printf("WARNING: Invalid product potential input line (too few tokens %d): %s\n", numTokens, line); continue; @@ -2058,27 +2058,44 @@ void Configuration::readProductPotentials() { if (tokenList == NULL) continue; + SimplePotentialType type = BOND; // initialize to suppress warning + bool type_specified = false; for (int i = 1; i < numTokens; ++i) { char *end; // printf("DEBUG: Working on token %d '%s'\n", i, tokenList[i].val()); + + // Try to convert token to integer int index = (int) strtol(tokenList[i].val(), &end, 10); if (tokenList[i].val() == end || *end != '\0' || errno == ERANGE) { - indices.push_back(tmp); - String& n = tokenList[i]; - pot_names.push_back( n ); - if ( simple_potential_ids.find(n) == simple_potential_ids.end() ) { - // Could not find fileName in dictionary, so read and add it - unsigned int s = tmp.size(); - if (s < 2 || s > 4) { - printf("WARNING: Invalid product potential input line (indices of potential %d == %d): %s\n", i, s, line); - continue; + // Failed to convert token to integer; therefore it must be a potential name or type + + // Try to match a type + String n = tokenList[i]; + n.lower(); + if (n == "bond") { type = DIHEDRAL; type_specified = true; } + else if (n == "angle") { type = DIHEDRAL; type_specified = true; } + else if (n == "dihedral") { type = DIHEDRAL; type_specified = true; } + else if (n == "vecangle") { type = VECANGLE; type_specified = true; } + else { // Not a type, therefore a path to a potential + n = tokenList[i]; + indices.push_back(tmp); + pot_names.push_back( n ); + // TODO: Key should be tuple of (type,n) + if ( simple_potential_ids.find(n) == simple_potential_ids.end() ) { + // Could not find fileName in dictionary, so read and add it + unsigned int s = tmp.size(); + if (s < 2 || s > 4) { + printf("WARNING: Invalid product potential input line (indices of potential %d == %d): %s\n", i, s, line); + continue; + } + simple_potential_ids[n] = simple_potentials.size(); + if (not type_specified) type = s==2? BOND: s==3? ANGLE: DIHEDRAL; + simple_potentials.push_back( SimplePotential(n.val(), type) ); } + tmp.clear(); + type_specified = false; - simple_potential_ids[n] = simple_potentials.size(); - SimplePotentialType t = s==2? BOND: s==3? ANGLE: DIHEDRAL; - simple_potentials.push_back( SimplePotential(n.val(), t) ); } - tmp.clear(); } else { if (index >= num) { continue; diff --git a/src/TabulatedPotential.h b/src/TabulatedPotential.h index 8c6f812..0aa73a0 100644 --- a/src/TabulatedPotential.h +++ b/src/TabulatedPotential.h @@ -207,7 +207,7 @@ private: /* } */ -enum SimplePotentialType { UNSET, BOND, ANGLE, DIHEDRAL }; +enum SimplePotentialType { UNSET, BOND, ANGLE, DIHEDRAL, VECANGLE }; // enum PotentialTypeAtoms { bond=2, angle=3, dihedral=4 }; @@ -250,6 +250,8 @@ public: val = compute_angle(pos, sys, particles[0], particles[1], particles[2]); else if (type == DIHEDRAL) val = compute_dihedral(pos, sys, particles[0], particles[1], particles[2], particles[3]); + else if (type == VECANGLE) + val = compute_vecangle(pos, sys, particles[0], particles[1], particles[2], particles[3]); return val; } @@ -275,18 +277,25 @@ public: const Vector3 ab = sys->wrapDiff(pos[j] - pos[i]); const Vector3 bc = sys->wrapDiff(pos[k] - pos[j]); const Vector3 ac = sys->wrapDiff(pos[k] - pos[i]); + return compute_angle( ab.length2(), bc.length2(), ac.length2() ); + } - // Find the distance between each pair of particles - float distab = ab.length2(); - float distbc = bc.length2(); - const float distac2 = ac.length2(); + HOST DEVICE inline float compute_vecangle(const Vector3* __restrict__ pos, + const BaseGrid* __restrict__ sys, + int i, int j, int k, int l) const { + const Vector3 ab = sys->wrapDiff(pos[j] - pos[i]); + const Vector3 bc = sys->wrapDiff(pos[l] - pos[k]); + const Vector3 ac = bc+ab; + return compute_angle( ab.length2(), bc.length2(), ac.length2() ); + } + HOST DEVICE inline float compute_angle(float distab2, float distbc2, float distac2) const { // Find the cosine of the angle we want - <ABC - float cos = (distab + distbc - distac2); + float cos = (distab2 + distbc2 - distac2); - distab = 1.0f/sqrt(distab); //TODO: test other functions - distbc = 1.0f/sqrt(distbc); - cos *= 0.5f * distbc * distab; + distab2 = 1.0f/sqrt(distab2); //TODO: test other functions + distbc2 = 1.0f/sqrt(distbc2); + cos *= 0.5f * distbc2 * distab2; // If the cosine is illegitimate, set it to 1 or -1 so that acos won't fail if (cos < -1.0f) cos = -1.0f; @@ -338,6 +347,9 @@ public: else if (type == DIHEDRAL) apply_dihedral_force(pos, sys, forces, particles[0], particles[1], particles[2], particles[3], energy_deriv); + else if (type == VECANGLE) + apply_vecangle_force(pos, sys, forces, particles[0], particles[1], + particles[2], particles[3], energy_deriv); } __device__ inline void apply_bond_force(const Vector3* __restrict__ pos, @@ -352,20 +364,18 @@ public: #endif } - DEVICE inline void apply_angle_force(const Vector3* __restrict__ pos, - const BaseGrid* __restrict__ sys, - Vector3* __restrict__ force, - int i, int j, int k, float energy_deriv) const { - -#ifdef __CUDA_ARCH__ - const Vector3 ab = -sys->wrapDiff(pos[j] - pos[i]); - const Vector3 bc = -sys->wrapDiff(pos[k] - pos[j]); - const Vector3 ac = sys->wrapDiff(pos[k] - pos[i]); + struct TwoVector3 { + Vector3 v1; + Vector3 v2; + }; + DEVICE inline TwoVector3 get_angle_force(const Vector3& ab, + const Vector3& bc, + float energy_deriv) const { // Find the distance between each pair of particles float distab = ab.length2(); float distbc = bc.length2(); - const float distac2 = ac.length2(); + const float distac2 = (ab+bc).length2(); // Find the cosine of the angle we want - <ABC float cos = (distab + distbc - distac2); @@ -382,12 +392,27 @@ public: energy_deriv /= abs(sin) > 1e-3 ? sin : 1e-3; // avoid singularity // Calculate the forces - Vector3 force1 = -(energy_deriv*distab) * (ab * (cos*distab) + bc * distbc); // force on particle 1 - Vector3 force3 = (energy_deriv*distbc) * (bc * (cos*distbc) + ab * distab); // force on particle 3 + TwoVector3 force; + force.v1 = (energy_deriv*distab) * (ab * (cos*distab) + bc * distbc); // force on 1st particle + force.v2 = -(energy_deriv*distbc) * (bc * (cos*distbc) + ab * distab); // force on last particle + return force; + } - atomicAdd( &force[i], force1 ); - atomicAdd( &force[j], -(force1 + force3) ); - atomicAdd( &force[k], force3 ); + DEVICE inline void apply_angle_force(const Vector3* __restrict__ pos, + const BaseGrid* __restrict__ sys, + Vector3* __restrict__ force, + int i, int j, int k, float energy_deriv) const { + +#ifdef __CUDA_ARCH__ + const Vector3 ab = sys->wrapDiff(pos[j] - pos[i]); + const Vector3 bc = sys->wrapDiff(pos[k] - pos[j]); + // const Vector3 ac = sys->wrapDiff(pos[k] - pos[i]); + + TwoVector3 f = get_angle_force(ab,bc, energy_deriv); + + atomicAdd( &force[i], f.v1 ); + atomicAdd( &force[j], -(f.v1 + f.v2) ); + atomicAdd( &force[k], f.v2 ); #endif } @@ -431,6 +456,26 @@ public: atomicAdd( &force[l], -f3 ); #endif } + DEVICE inline void apply_vecangle_force(const Vector3* __restrict__ pos, + const BaseGrid* __restrict__ sys, + Vector3* __restrict__ force, + int i, int j, int k, int l, float energy_deriv) const { + +#ifdef __CUDA_ARCH__ + + const Vector3 ab = -sys->wrapDiff(pos[j] - pos[i]); + const Vector3 bc = -sys->wrapDiff(pos[k] - pos[j]); + // const Vector3 ac = sys->wrapDiff(pos[k] - pos[i]); + + TwoVector3 f = get_angle_force(ab,bc, energy_deriv); + + atomicAdd( &force[i], f.v1 ); + atomicAdd( &force[j], -f.v1 ); + atomicAdd( &force[k], -f.v2 ); + atomicAdd( &force[l], f.v2 ); +#endif + } + }; #ifndef delgpuErrchk -- GitLab