NAMD
ComputeNonbondedCUDAExcl.C
Go to the documentation of this file.
1 
7 #include "InfoStream.h"
9 #include "Molecule.h"
10 #include "Parameters.h"
11 #include "LJTable.h"
12 #include "Node.h"
13 #include "ReductionMgr.h"
14 #include "Lattice.h"
15 #include "PressureProfile.h"
16 #include "Debug.h"
17 
18 
19 // static initialization
24 int ExclElem::pswitchTable[3*3] = {0,1,2,1,1,99,2,99,2};
25 
27  (Molecule* mol, int* count, int32*** byatom, Exclusion** structarray)
28 {
29 #ifdef MEM_OPT_VERSION
30  NAMD_die("Should not be called in ExclElem::getMoleculePointers in memory optimized version!");
31 #else
32  *count = mol->numExclusions;
33  *byatom = mol->exclusionsByAtom;
34  *structarray = mol->exclusions;
35 #endif
36 }
37 
38 void ExclElem::getParameterPointers(Parameters *p, const int **v) {
39  *v = 0;
40 }
41 
42 
44  ExclElem *tuples,
45  int ntuple,
46  BigReal *reduction,
47  BigReal *pressureProfileData
48  )
49 {
50  //
51  // Use the following from ComputeNonbondedUtil:
52  // cutoff2
53  // switchOn2
54  // alchFepOn
55  // alchVdwShiftCoeff
56  // alchDecouple
57  // scaling
58  // scale14
59  // dielectric_1
60  // ljTable
61  // r2_table
62  // table_noshort
63  // fast_table
64  // slow_table
65  //
66  const Lattice & lattice = tuples[0].p[0]->p->lattice;
67  const Flags &flags = tuples[0].p[0]->p->flags;
68  if ( ! flags.doNonbonded ) return;
70  const int doFull = flags.doFullElectrostatics;
71  const int doEnergy = flags.doEnergy;
72 
73  /* ALCH STUFF */
74  BigReal lambdaUp, lambdaDown, lambda2Up, lambda2Down, switchfactor;
75  BigReal vdwLambdaUp, vdwLambdaDown, elecLambdaUp, elecLambdaDown;
76  BigReal elecLambda2Up, elecLambda2Down, vdwLambda2Up, vdwLambda2Down;
77  BigReal vdwShiftUp, vdwShift2Up, vdwShiftDown, vdwShift2Down;
78  BigReal myVdwLambda, myVdwLambda2, myElecLambda, myElecLambda2, myVdwShift, myVdwShift2;
79  //bool isAlch = simParams->alchFepOn;
80  int pswitch, ref, alch, dec, up, down;
81 
82  if (alchFepOn || alchThermIntOn) {
83  BigReal lambdaUp = simParams->getCurrentLambda(flags.step);
84  BigReal lambda2Up = simParams->getCurrentLambda2(flags.step);
85  BigReal lambdaDown = 1 - lambdaUp;
86  BigReal lambda2Down = 1 - lambda2Up;
87  switchfactor = 1./((cutoff2 - switchOn2)*
89  vdwLambdaUp = simParams->getVdwLambda(lambdaUp);
90  vdwLambdaDown = simParams->getVdwLambda(lambdaDown);
91  elecLambdaUp = simParams->getElecLambda(lambdaUp);
92  elecLambdaDown = simParams->getElecLambda(lambdaDown);
93  elecLambda2Up = simParams->getElecLambda(lambda2Up);
94  elecLambda2Down = simParams->getElecLambda(lambda2Down);
95  vdwLambda2Up = simParams->getVdwLambda(lambda2Up);
96  vdwLambda2Down = simParams->getVdwLambda(lambda2Down);
97  vdwShiftUp = alchVdwShiftCoeff*(1 - vdwLambdaUp);
98  vdwShiftDown = alchVdwShiftCoeff*(1 - vdwLambdaDown);
99  vdwShift2Up = alchVdwShiftCoeff*(1 - vdwLambda2Up);
100  vdwShift2Down = alchVdwShiftCoeff*(1 - vdwLambda2Down);
101 
102  if (alchDecouple) {
103  // decoupling: PME calculates extra grids so that while PME
104  // interaction with the full system is switched off, a new PME grid
105  // containing only alchemical atoms is switched on. Full interactions
106  // between alchemical atoms are maintained; potentials within one
107  // partition need not be scaled here.
108  pswitchTable[1+3*1] = 0;
109  pswitchTable[2+3*2] = 0;
110  }
111  }
112 
113  for ( int ituple=0; ituple<ntuple; ++ituple ) {
114  // ENERGIES FOR REDUCTION
115  BigReal energyVdw = 0.0, energyElec = 0.0, energySlow = 0.0;
116  // FEP Energies
117  BigReal energyVdw_s = 0.0, energyElec_s = 0.0, energySlow_s = 0.0;
118 
119  const ExclElem &tup = tuples[ituple];
120  enum { size = 2 };
121  const AtomID (&atomID)[size](tup.atomID);
122  const int (&localIndex)[size](tup.localIndex);
123  TuplePatchElem * const(&p)[size](tup.p);
124  const Real (&scale)(tup.scale);
125  const int (&modified)(tup.modified);
126 
127  const CompAtom &p_i = p[0]->x[localIndex[0]];
128  const CompAtom &p_j = p[1]->x[localIndex[1]];
129 
130  const unsigned char p1 = p_i.partition;
131  const unsigned char p2 = p_j.partition;
132 
133  BigReal alch_vdw_energy = 0.0;
134  BigReal alch_vdw_energy_2 = 0.0;
135  BigReal alch_vdw_force = 0.0;
136  BigReal alch_vdw_dUdl = 0.0;
137 
138  // compute vectors between atoms and their distances
139  const Vector r12 = lattice.delta(p_i.position, p_j.position);
140  BigReal r2 = r12.length2();
141 
142  if ( r2 > cutoff2 ) continue;
143 
144  if ( modified && r2 < 1.0 ) r2 = 1.0; // match CUDA interpolation
145 
146  r2 += r2_delta;
147 
148  pswitch = pswitchTable[p1 + 3*p2];
149  if (alchFepOn || alchThermIntOn) {
150  switch (pswitch) {
151  case 0:
152  myVdwLambda = 1.0; myElecLambda = 1.0;
153  myVdwLambda2 = 1.0; myElecLambda2 = 1.0;
154  break;
155  case 1:
156  myVdwLambda = vdwLambdaUp; myElecLambda = elecLambdaUp; myVdwShift = vdwShiftUp;
157  myVdwLambda2 = vdwLambda2Up; myElecLambda2 = elecLambda2Up; myVdwShift2 = vdwShift2Up;
158  break;
159  case 2:
160  myVdwLambda = vdwLambdaDown; myElecLambda = elecLambdaDown; myVdwShift = vdwShiftDown;
161  myVdwLambda2 = vdwLambda2Down; myElecLambda2 = elecLambda2Down; myVdwShift2 = vdwShift2Down;
162  break;
163  default:
164  myVdwLambda = 0.0; myElecLambda = 0.0;
165  myVdwLambda2 = 0.0; myElecLambda2 = 0.0;
166  break;
167  }
168  }
169  else {
170  myVdwLambda = 1.0; myElecLambda = 1.0;
171  myVdwLambda2 = 1.0; myElecLambda2 = 1.0;
172  }
173 
174  union { double f; int64 i; } r2i;
175  r2i.f = r2;
176  const int r2_delta_expc = 64 * (r2_delta_exp - 1023);
177  int table_i = (r2i.i >> (32+14)) + r2_delta_expc; // table_i >= 0
178 
179  const BigReal* const table_four_i = table_noshort + 16*table_i;
180 
181  BigReal diffa = r2 - r2_table[table_i];
182 
183  BigReal fast_a = 0., fast_b = 0., fast_c = 0., fast_d = 0.;
184  BigReal slow_a, slow_b, slow_c, slow_d;
185 
186  if ( modified ) { // fix modified 1-4 interactions
187 
188  const LJTable::TableEntry * lj_pars =
189  ljTable->table_row(p_i.vdwType) + 2 * p_j.vdwType;
190 
191  // modified - normal = correction
192  const BigReal A = scaling * ( (lj_pars+1)->A - lj_pars->A );
193  const BigReal B = scaling * ( (lj_pars+1)->B - lj_pars->B );
194 
195  BigReal vdw_d = A * table_four_i[0] - B * table_four_i[4];
196  BigReal vdw_c = A * table_four_i[1] - B * table_four_i[5];
197  BigReal vdw_b = A * table_four_i[2] - B * table_four_i[6];
198  BigReal vdw_a = A * table_four_i[3] - B * table_four_i[7];
199 
200  const BigReal kqq = (1.0 - scale14) *
201  COULOMB * p_i.charge * p_j.charge * scaling * dielectric_1;
202 
203  fast_a = kqq * fast_table[4*table_i+0]; // not used!
204  fast_b = 2. * kqq * fast_table[4*table_i+1];
205  fast_c = 4. * kqq * fast_table[4*table_i+2];
206  fast_d = 6. * kqq * fast_table[4*table_i+3];
207 
208  if ( doFull ) {
209  slow_a = kqq * slow_table[4*table_i+3]; // not used!
210  slow_b = 2. * kqq * slow_table[4*table_i+2];
211  slow_c = 4. * kqq * slow_table[4*table_i+1];
212  slow_d = 6. * kqq * slow_table[4*table_i+0];
213  }
214 
215  if ( doEnergy ) {
216  energyElec = (( ( diffa * (1./6.)*fast_d + 0.25*fast_c ) * diffa
217  + 0.5*fast_b ) * diffa + fast_a);
218  if ( doFull ) {
219  energySlow = (( ( diffa * (1./6.)*slow_d + 0.25*slow_c ) * diffa
220  + 0.5*slow_b ) * diffa + slow_a);
221  }
222  }
223 
224  if (pswitch == 0) {
225  fast_a += vdw_a;
226  fast_b += vdw_b;
227  fast_c += vdw_c;
228  fast_d += vdw_d;
229  if (doEnergy) {
230  energyVdw = (( ( diffa * (1./6.)*vdw_d + 0.25*vdw_c ) * diffa
231  + 0.5*vdw_b ) * diffa + vdw_a);
232  }
233  }
234  else if(pswitch != 99) {
235  // Special alch forces should be calculated here
236  if(alchFepOn){
237  const BigReal r2_1 = 1./(r2 + myVdwShift);
238  const BigReal r2_2 = 1./(r2 + myVdwShift2);
239  const BigReal r6_1 = r2_1*r2_1*r2_1;
240  const BigReal r6_2 = r2_2*r2_2*r2_2;
241  const BigReal U1 = A*r6_1*r6_1 - B*r6_1; // NB: unscaled, shorthand only
242  const BigReal U2 = A*r6_2*r6_2 - B*r6_2;
243 
244  const BigReal switchmul = (r2 > switchOn2 ?
245  switchfactor * (cutoff2 - r2) * (cutoff2 - r2) *
246  (cutoff2 - 3.*switchOn2 + 2.*r2) : 1.);
247 
248  const BigReal switchmul2 = (r2 > switchOn2 ?
249  12.*switchfactor * (cutoff2 - r2) * (r2 - switchOn2) : 0.);
250  BigReal rinv = namd_rsqrt(r2);
251  alch_vdw_energy = myVdwLambda*switchmul*U1;
252  alch_vdw_energy_2 = myVdwLambda2*switchmul*U2;
253  alch_vdw_force = myVdwLambda*((switchmul*(12.*U1 + 6.*B*r6_1)*r2_1 +
254  switchmul2*U1));
255  if (doEnergy) {
256  reduction[vdwEnergyIndex] += alch_vdw_energy;
257  reduction[vdwEnergyIndex_s] += alch_vdw_energy_2;
258  }
259  }else if(alchThermIntOn){
260  const BigReal r2_1 = 1./(r2 + myVdwShift);
261  const BigReal r6_1 = r2_1*r2_1*r2_1;
262  // switching function (this is correct whether switching is active or not)
263  const BigReal switchmul = (r2 > switchOn2 ? switchfactor*(cutoff2 - r2) \
264  *(cutoff2 - r2) \
265  *(cutoff2 - 3.*switchOn2 + 2.*r2) : 1.);
266  const BigReal switchmul2 = (r2 > switchOn2 ? \
267  12.*switchfactor*(cutoff2 - r2) \
268  *(r2 - switchOn2) : 0.);
269 
270  // separation-shifted vdW force and energy
271  const BigReal U = A*r6_1*r6_1 - B*r6_1; // NB: unscaled! for shorthand only!
272  alch_vdw_energy = myVdwLambda*switchmul*U;
273  alch_vdw_force = (myVdwLambda*(switchmul*(12.*U + 6.*B*r6_1)*r2_1 \
274  + switchmul2*U));
275  alch_vdw_dUdl = (switchmul*(U + myVdwLambda*alchVdwShiftCoeff \
276  *(6.*U + 3.*B*r6_1)*r2_1));
277  if (doEnergy) {
278  reduction[vdwEnergyIndex] += alch_vdw_energy;
279  reduction[vdwEnergyIndex_ti_1] += alch_vdw_dUdl*(pswitch == 1);
280  reduction[vdwEnergyIndex_ti_2] += alch_vdw_dUdl*(pswitch == 2);
281  }
282  }//alchFepOn
283  }
284  } // end if modified
285  else if ( doFull ) { // full exclusion
286 
287  const BigReal kqq =
288  COULOMB * p_i.charge * p_j.charge * scaling * dielectric_1;
289 
290  slow_d = kqq * ( table_four_i[8] - table_four_i[12] );
291  slow_c = kqq * ( table_four_i[9] - table_four_i[13] );
292  slow_b = kqq * ( table_four_i[10] - table_four_i[14] );
293  slow_a = kqq * ( table_four_i[11] - table_four_i[15] ); // not used!
294 
295  if ( doEnergy ) {
296  energySlow = (( ( diffa * (1./6.)*slow_d + 0.25*slow_c ) * diffa
297  + 0.5*slow_b ) * diffa + slow_a);
298  }
299  }
300 
301  register BigReal fast_dir = (diffa * fast_d + fast_c) * diffa + fast_b;
302 
303  fast_dir = (fast_dir*myElecLambda) + alch_vdw_force*(pswitch == 1 || pswitch == 2);
304  const Force f12 = fast_dir * r12;
305 
306  // Now add the forces to each force vector
307  p[0]->r->f[Results::nbond][localIndex[0]] += f12;
308  p[1]->r->f[Results::nbond][localIndex[1]] -= f12;
309 
310  // reduction[nonbondedEnergyIndex] += energy;
311  reduction[virialIndex_XX] += f12.x * r12.x;
312  //reduction[virialIndex_XY] += f12.x * r12.y;
313  //reduction[virialIndex_XZ] += f12.x * r12.z;
314  reduction[virialIndex_YX] += f12.y * r12.x;
315  reduction[virialIndex_YY] += f12.y * r12.y;
316  //reduction[virialIndex_YZ] += f12.y * r12.z;
317  reduction[virialIndex_ZX] += f12.z * r12.x;
318  reduction[virialIndex_ZY] += f12.z * r12.y;
319  reduction[virialIndex_ZZ] += f12.z * r12.z;
320 
321  if ( doFull ) {
322  register BigReal slow_dir = (diffa * slow_d + slow_c) * diffa + slow_b;
323 
324  slow_dir = (slow_dir * myElecLambda);
325  const Force slow_f12 = slow_dir * r12;
326 
327  p[0]->r->f[Results::slow][localIndex[0]] += slow_f12;
328  p[1]->r->f[Results::slow][localIndex[1]] -= slow_f12;
329 
330  // reduction[nonbondedEnergyIndex] += energy;
331  reduction[slowVirialIndex_XX] += slow_f12.x * r12.x;
332  //reduction[slowVirialIndex_XY] += slow_f12.x * r12.y;
333  //reduction[slowVirialIndex_XZ] += slow_f12.x * r12.z;
334  reduction[slowVirialIndex_YX] += slow_f12.y * r12.x;
335  reduction[slowVirialIndex_YY] += slow_f12.y * r12.y;
336  //reduction[slowVirialIndex_YZ] += slow_f12.y * r12.z;
337  reduction[slowVirialIndex_ZX] += slow_f12.z * r12.x;
338  reduction[slowVirialIndex_ZY] += slow_f12.z * r12.y;
339  reduction[slowVirialIndex_ZZ] += slow_f12.z * r12.z;
340  }
341 
342  // Scale the energies here
343  if (doEnergy) {
344  reduction[vdwEnergyIndex] -= energyVdw*myElecLambda;
345  reduction[electEnergyIndex] -= energyElec*myElecLambda;
346  if (doFull) {
347  reduction[fullElectEnergyIndex] -= energySlow*myElecLambda;
348  }
349  if (alchFepOn) {
350  reduction[vdwEnergyIndex_s] -= energyVdw*myElecLambda2;
351  reduction[electEnergyIndex_s] -= energyElec*myElecLambda2;
352  if (doFull) {
353  reduction[fullElectEnergyIndex_s] -= energySlow*myElecLambda2;
354  }
355  }else if (alchThermIntOn){
356  if(pswitch == 1){
357  //Those aren't defined here. What should I do?
358  //reduction[vdwEnergyIndex_ti_1] -= alch_vdw_dUdl;
359  reduction[electEnergyIndex_ti_1] -= energyElec;
360  if (doFull) reduction[fullElectEnergyIndex_ti_1] -= energySlow;
361  }
362  else if (pswitch == 2){
363  //reduction[vdwEnergyIndex_ti_2] -= alch_vdw_dUdl;
364  reduction[electEnergyIndex_ti_2] -= energyElec;
365  if (doFull) reduction[fullElectEnergyIndex_ti_2] -= energySlow; //should I be scaling those?
366  }
367  }
368  } // end if doEnergy
369  } // end for loop
370 } // end computeForce()
371 
372 
374 {
375  //bool isAlch = Node::Object()->simParameters->alchFepOn;
376 
377  reduction->item(REDUCTION_ELECT_ENERGY) += data[electEnergyIndex];
378  reduction->item(REDUCTION_LJ_ENERGY) += data[vdwEnergyIndex];
380  if (alchFepOn) {
381  reduction->item(REDUCTION_ELECT_ENERGY_F) += data[electEnergyIndex_s];
383  reduction->item(REDUCTION_LJ_ENERGY_F) += data[vdwEnergyIndex_s];
384  }else if (alchThermIntOn){
391  }
392  //transposes the virial tensor after calculation
393  data[virialIndex_XY] = data[virialIndex_YX];
394  data[virialIndex_XZ] = data[virialIndex_ZX];
395  data[virialIndex_YZ] = data[virialIndex_ZY];
396 
397  data[slowVirialIndex_XY] = data[slowVirialIndex_YX];
398  data[slowVirialIndex_XZ] = data[slowVirialIndex_ZX];
399  data[slowVirialIndex_YZ] = data[slowVirialIndex_ZY];
400 
401  ADD_TENSOR(reduction,REDUCTION_VIRIAL_NBOND,data,virialIndex);
402  ADD_TENSOR(reduction,REDUCTION_VIRIAL_SLOW,data,slowVirialIndex);
403 }
404 
static Node * Object()
Definition: Node.h:86
static BigReal * fast_table
static int pressureProfileAtomTypes
const TableEntry * table_row(unsigned int i) const
Definition: LJTable.h:31
Lattice & lattice
Definition: Patch.h:127
#define ADD_TENSOR(R, RL, D, DL)
Definition: ReductionMgr.h:33
Definition: Vector.h:72
static void submitReductionData(BigReal *, SubmitReduction *)
SimParameters * simParameters
Definition: Node.h:181
static void computeForce(ExclElem *, int, BigReal *, BigReal *)
float Real
Definition: common.h:118
#define COULOMB
Definition: common.h:53
int32_t int32
Definition: common.h:38
BigReal & item(int i)
Definition: ReductionMgr.h:313
#define table_four_i
BigReal z
Definition: Vector.h:74
Position position
Definition: NamdTypes.h:77
static void getParameterPointers(Parameters *, const int **)
#define p_j
Molecule stores the structural information for the system.
Definition: Molecule.h:175
#define lj_pars
Flags flags
Definition: Patch.h:128
#define namd_rsqrt(x)
Definition: Vector.h:68
Charge charge
Definition: NamdTypes.h:78
static BigReal * table_noshort
static int pswitchTable[3 *3]
int doEnergy
Definition: PatchTypes.h:20
int doFullElectrostatics
Definition: PatchTypes.h:23
int16 vdwType
Definition: NamdTypes.h:79
Force * f[maxNumForces]
Definition: PatchTypes.h:146
NAMD_HOST_DEVICE BigReal length2(void) const
Definition: Vector.h:206
uint8 partition
Definition: NamdTypes.h:80
BigReal x
Definition: Vector.h:74
int doNonbonded
Definition: PatchTypes.h:22
void NAMD_die(const char *err_msg)
Definition: common.C:147
TuplePatchElem * p[size]
static int pressureProfileSlabs
AtomID atomID[size]
static BigReal * slow_table
#define simParams
Definition: Output.C:129
int32 AtomID
Definition: NamdTypes.h:35
BigReal y
Definition: Vector.h:74
static const LJTable * ljTable
static BigReal pressureProfileThickness
static BigReal alchVdwShiftCoeff
int64_t int64
Definition: common.h:39
static BigReal pressureProfileMin
static void getMoleculePointers(Molecule *, int *, int32 ***, Exclusion **)
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
int numExclusions
Definition: Molecule.h:599