NAMD
ComputeAngles.C
Go to the documentation of this file.
1 
7 /*
8  Methods for ComputeAngles. Main code is for
9  loading in the AngleElem information and
10  for computing forces and energies for all angles on node's.
11  HomePatch(es)
12 */
13 
14 #include "InfoStream.h"
15 #include "ComputeAngles.h"
16 #include "Molecule.h"
17 #include "Parameters.h"
18 #include "Node.h"
19 #include "ReductionMgr.h"
20 #include "Lattice.h"
21 #include "PressureProfile.h"
22 #include "Debug.h"
23 
24 
25 // static initialization
30 
32  (Molecule* mol, int* count, int32*** byatom, Angle** structarray)
33 {
34 #ifdef MEM_OPT_VERSION
35  NAMD_die("Should not be called in AngleElem::getMoleculePointers in memory optimized version!");
36 #else
37  *count = mol->numAngles;
38  *byatom = mol->anglesByAtom;
39  *structarray = mol->angles;
40 #endif
41 }
42 
44  *v = p->angle_array;
45 }
46 
47 void AngleElem::computeForce(AngleElem *tuples, int ntuple, BigReal *reduction, BigReal *pressureProfileData)
48 {
49  const Lattice & lattice = tuples[0].p[0]->p->lattice;
50 
51  //fepb BKR
53  const int step = tuples[0].p[0]->p->flags.step;
54  const BigReal alchLambda = simParams->getCurrentLambda(step);
55  const BigReal alchLambda2 = simParams->getCurrentLambda2(step);
56  const BigReal bond_lambda_1 = simParams->getBondLambda(alchLambda);
57  const BigReal bond_lambda_2 = simParams->getBondLambda(1-alchLambda);
58  const BigReal bond_lambda_12 = simParams->getBondLambda(alchLambda2);
59  const BigReal bond_lambda_22 = simParams->getBondLambda(1-alchLambda2);
60  Molecule *const mol = Node::Object()->molecule;
61  //fepe
62 
63  for ( int ituple=0; ituple<ntuple; ++ituple ) {
64  const AngleElem &tup = tuples[ituple];
65  enum { size = 3 };
66  const AtomID (&atomID)[size](tup.atomID);
67  const int (&localIndex)[size](tup.localIndex);
68  TuplePatchElem * const(&p)[size](tup.p);
69  const Real (&scale)(tup.scale);
70  const AngleValue * const(&value)(tup.value);
71 
72 #if defined(DEBUG_PROTOCELL)
73  if ((PRMIN <= atomID[0] && atomID[0] <= PRMAX) &&
74  (PRMIN <= atomID[1] && atomID[1] <= PRMAX) &&
75  (PRMIN <= atomID[2] && atomID[2] <= PRMAX)) {
76  int i = atomID[0];
77  int j = atomID[1];
78  int k = atomID[2];
79  if (atomID[2] < atomID[0]) {
80  i = atomID[2];
81  j = atomID[1];
82  k = atomID[0];
83  }
84  double ktheta = value->k;
85  double theta0 = value->theta0;
86  double kub = value->k_ub;
87  double rub = value->r_ub;
88  CkPrintf("%11d %11d %11d k=%g theta0=%g kub=%g rub=%g\n",
89  i, j, k, ktheta, theta0, kub, rub);
90  }
91 #endif
92 
93  DebugM(3, "::computeForce() localIndex = " << localIndex[0] << " "
94  << localIndex[1] << " " << localIndex[2] << std::endl);
95 
96  const Position & pos1 = p[0]->x[localIndex[0]].position;
97  const Position & pos2 = p[1]->x[localIndex[1]].position;
98  Vector r12 = lattice.delta(pos1,pos2);
99  register BigReal d12inv = r12.rlength();
100  const Position & pos3 = p[2]->x[localIndex[2]].position;
101  Vector r32 = lattice.delta(pos3,pos2);
102  register BigReal d32inv = r32.rlength();
103  int normal = value->normal;
104 
105  BigReal cos_theta = (r12*r32)*(d12inv*d32inv);
106  // Make sure that the cosine value is acceptable. With roundoff, you
107  // can get values like 1.0+2e-16, which makes acos puke. So instead,
108  // just set these kinds of values to exactly 1.0
109  if (cos_theta > 1.0) cos_theta = 1.0;
110  else if (cos_theta < -1.0) cos_theta = -1.0;
111 
112  BigReal k = value->k * scale;
113  BigReal theta0 = value->theta0;
114 
115  // Get theta
116  BigReal theta = acos(cos_theta);
117 
118  // Compare it to the rest angle
119  BigReal diff;
120 
121  if (normal == 1) {
122  diff = theta - theta0;
123  } else {
124  diff = cos_theta - cos(theta0);
125  }
126 
127  // Add the energy from this angle to the total energy
128  BigReal energy = k *diff*diff;
129 
130  // Normalize vector r12 and r32
131  //BigReal d12inv = 1. / d12;
132  //BigReal d32inv = 1. / d32;
133 
134 
135  // Calculate constant factor 2k(theta-theta0)/sin(theta)
136  BigReal sin_theta = sqrt(1.0 - cos_theta*cos_theta);
137  if (normal != 1) {
138  diff *= (2.0* k);
139  } else if ( sin_theta < 1.e-6 ) {
140  // catch case where bonds are parallel
141  // this gets the force approximately right for theta0 of 0 or pi
142  // and at least avoids small division for other values
143  if ( diff < 0. ) diff = 2.0 * k;
144  else diff = -2.0 * k;
145  } else {
146  diff *= (-2.0* k) / sin_theta;
147  }
148  BigReal c1 = diff * d12inv;
149  BigReal c2 = diff * d32inv;
150 
151  // Calculate the actual forces
152  Force force1 = c1*(r12*(d12inv*cos_theta) - r32*d32inv);
153  Force force2 = force1;
154  Force force3 = c2*(r32*(d32inv*cos_theta) - r12*d12inv);
155  force2 += force3; force2 *= -1;
156 
157  // Check to see if we need to do the Urey-Bradley term
158  if (value->k_ub)
159  {
160  // Non-zero k_ub value, so calculate the harmonic
161  // potential between the 1-3 atoms
162 
163  if (normal != 1) {
164  NAMD_die("ERROR: Can't use cosAngles with Urey-Bradley angles");
165  }
166  BigReal k_ub = value->k_ub;
167  BigReal r_ub = value->r_ub;
168  Vector r13 = r12 - r32;
169  BigReal d13 = r13.length();
170  diff = d13- r_ub;
171 
172  energy += k_ub *diff*diff;
173 
174  diff *= -2.0*k_ub / d13;
175  r13 *= diff;
176 
177  force1 += r13;
178  force3 -= r13;
179  }
180 
181  //fepb - BKR scaling of alchemical bonded terms
182  // NB: TI derivative is the _unscaled_ energy.
183  if ( simParams->alchOn && !simParams->singleTopology) {
184  switch ( mol->get_fep_bonded_type(atomID, 3) ) {
185  case 1:
186  reduction[angleEnergyIndex_ti_1] += energy;
187  reduction[angleEnergyIndex_f] += (bond_lambda_12 - bond_lambda_1)*energy;
188  energy *= bond_lambda_1;
189  force1 *= bond_lambda_1;
190  force2 *= bond_lambda_1;
191  force3 *= bond_lambda_1;
192  break;
193  case 2:
194  reduction[angleEnergyIndex_ti_2] += energy;
195  reduction[angleEnergyIndex_f] += (bond_lambda_22 - bond_lambda_2)*energy;
196  energy *= bond_lambda_2;
197  force1 *= bond_lambda_2;
198  force2 *= bond_lambda_2;
199  force3 *= bond_lambda_2;
200  break;
201  }
202  }
203  //fepe
204 
205  p[0]->f[localIndex[0]].x += force1.x;
206  p[0]->f[localIndex[0]].y += force1.y;
207  p[0]->f[localIndex[0]].z += force1.z;
208 
209  p[1]->f[localIndex[1]].x += force2.x;
210  p[1]->f[localIndex[1]].y += force2.y;
211  p[1]->f[localIndex[1]].z += force2.z;
212 
213  p[2]->f[localIndex[2]].x += force3.x;
214  p[2]->f[localIndex[2]].y += force3.y;
215  p[2]->f[localIndex[2]].z += force3.z;
216 
217  DebugM(3, "::computeForce() -- ending with delta energy " << energy << std::endl);
218 
219  reduction[angleEnergyIndex] += energy;
220  reduction[virialIndex_XX] += ( force1.x * r12.x + force3.x * r32.x );
221  reduction[virialIndex_XY] += ( force1.x * r12.y + force3.x * r32.y );
222  reduction[virialIndex_XZ] += ( force1.x * r12.z + force3.x * r32.z );
223  reduction[virialIndex_YX] += ( force1.y * r12.x + force3.y * r32.x );
224  reduction[virialIndex_YY] += ( force1.y * r12.y + force3.y * r32.y );
225  reduction[virialIndex_YZ] += ( force1.y * r12.z + force3.y * r32.z );
226  reduction[virialIndex_ZX] += ( force1.z * r12.x + force3.z * r32.x );
227  reduction[virialIndex_ZY] += ( force1.z * r12.y + force3.z * r32.y );
228  reduction[virialIndex_ZZ] += ( force1.z * r12.z + force3.z * r32.z );
229 
230  if (pressureProfileData) {
231  BigReal z1 = p[0]->x[localIndex[0]].position.z;
232  BigReal z2 = p[1]->x[localIndex[1]].position.z;
233  BigReal z3 = p[2]->x[localIndex[2]].position.z;
234  int n1 = (int)floor((z1-pressureProfileMin)/pressureProfileThickness);
235  int n2 = (int)floor((z2-pressureProfileMin)/pressureProfileThickness);
236  int n3 = (int)floor((z3-pressureProfileMin)/pressureProfileThickness);
240  int p1 = p[0]->x[localIndex[0]].partition;
241  int p2 = p[1]->x[localIndex[1]].partition;
242  int p3 = p[2]->x[localIndex[2]].partition;
243  int pn = pressureProfileAtomTypes;
245  p1, p2, pn,
246  force1.x * r12.x, force1.y * r12.y, force1.z * r12.z,
247  pressureProfileData);
249  p3, p2, pn,
250  force3.x * r32.x, force3.y * r32.y, force3.z * r32.z,
251  pressureProfileData);
252  }
253 
254  }
255 }
256 
257 
259 {
260  reduction->item(REDUCTION_ANGLE_ENERGY) += data[angleEnergyIndex];
264  ADD_TENSOR(reduction,REDUCTION_VIRIAL_NORMAL,data,virialIndex);
265 }
266 
static Node * Object()
Definition: Node.h:86
TuplePatchElem * p[size]
Definition: ComputeAngles.h:22
static BigReal pressureProfileThickness
Definition: ComputeAngles.h:36
Lattice & lattice
Definition: Patch.h:127
#define ADD_TENSOR(R, RL, D, DL)
Definition: ReductionMgr.h:33
void pp_reduction(int nslabs, int n1, int n2, int atype1, int atype2, int numtypes, BigReal vxx, BigReal vyy, BigReal vzz, BigReal *reduction)
Definition: Vector.h:72
SimParameters * simParameters
Definition: Node.h:181
static void computeForce(AngleElem *, int, BigReal *, BigReal *)
Definition: ComputeAngles.C:47
float Real
Definition: common.h:118
int32_t int32
Definition: common.h:38
BigReal & item(int i)
Definition: ReductionMgr.h:313
#define DebugM(x, y)
Definition: Debug.h:75
BigReal z
Definition: Vector.h:74
Position position
Definition: NamdTypes.h:77
static BigReal pressureProfileMin
Definition: ComputeAngles.h:37
Molecule stores the structural information for the system.
Definition: Molecule.h:175
Flags flags
Definition: Patch.h:128
void pp_clamp(int &n, int nslabs)
NAMD_HOST_DEVICE BigReal length(void) const
Definition: Vector.h:202
static void getParameterPointers(Parameters *, const AngleValue **)
Definition: ComputeAngles.C:43
AtomID atomID[size]
Definition: ComputeAngles.h:20
static void getMoleculePointers(Molecule *, int *, int32 ***, Angle **)
Definition: ComputeAngles.C:32
uint8 partition
Definition: NamdTypes.h:80
BigReal x
Definition: Vector.h:74
int numAngles
Definition: Molecule.h:589
int get_fep_bonded_type(const int *atomID, unsigned int order) const
Definition: Molecule.h:1477
void NAMD_die(const char *err_msg)
Definition: common.C:147
int localIndex[size]
Definition: ComputeAngles.h:21
#define simParams
Definition: Output.C:129
int32 AtomID
Definition: NamdTypes.h:35
BigReal y
Definition: Vector.h:74
static int pressureProfileSlabs
Definition: ComputeAngles.h:34
static void submitReductionData(BigReal *, SubmitReduction *)
Real theta0
Definition: Parameters.h:112
const AngleValue * value
Definition: ComputeAngles.h:40
NAMD_HOST_DEVICE BigReal rlength(void) const
Definition: Vector.h:210
static int pressureProfileAtomTypes
Definition: ComputeAngles.h:35
Molecule * molecule
Definition: Node.h:179
double BigReal
Definition: common.h:123
NAMD_HOST_DEVICE Vector delta(const Position &pos1, const Position &pos2) const
Definition: Lattice.h:149
int step
Definition: PatchTypes.h:16