NAMD
ComputeHomeTuples.h
Go to the documentation of this file.
1 
7 #ifndef COMPUTEHOMETUPLES_H
8 #define COMPUTEHOMETUPLES_H
9 
10 #ifdef USE_HOMETUPLES
11 #include <vector>
12 #endif
13 #include "NamdTypes.h"
14 #include "common.h"
15 #include "structures.h"
16 #include "Compute.h"
17 #include "HomePatch.h"
18 
19 #include "Box.h"
20 #include "OwnerBox.h"
21 #include "UniqueSet.h"
22 
23 #include "Node.h"
24 #include "SimParameters.h"
25 #include "PatchMap.inl"
26 #include "AtomMap.h"
27 #include "PatchMgr.h"
28 #include "ProxyMgr.h"
29 #include "HomePatchList.h"
30 #include "Molecule.h"
31 #include "Parameters.h"
32 #include "ReductionMgr.h"
33 #include "UniqueSet.h"
34 #include "UniqueSetIter.h"
35 #include "Priorities.h"
36 #include "LdbCoordinator.h"
37 
39  public:
41  Patch *p;
49  Force *f;
51 
52  int hash() const { return patchID; }
53 
54  TuplePatchElem(PatchID pid = -1) {
55  patchID = pid;
56  p = NULL;
57  positionBox = NULL;
58  avgPositionBox = NULL;
59  forceBox = NULL;
60  x = NULL;
61  xExt = NULL;
62  x_avg = NULL;
63  r = NULL;
64  f = NULL;
65  af = NULL;
66  }
67 
68  TuplePatchElem(Patch *p_param, Compute *cid) {
69  patchID = p_param->getPatchID();
70  p = p_param;
71  positionBox = p_param->registerPositionPickup(cid);
73  forceBox = p_param->registerForceDeposit(cid);
74  x = NULL;
75  xExt = NULL;
76  x_avg = NULL;
77  r = NULL;
78  f = NULL;
79  af = NULL;
80  }
81 
83 
84  int operator==(const TuplePatchElem &elem) const {
85  return (elem.patchID == patchID);
86  }
87 
88  int operator<(const TuplePatchElem &elem) const {
89  return (patchID < elem.patchID);
90  }
91 };
92 
95 
96 class AtomMap;
97 class ReductionMgr;
98 
99 #ifdef MEM_OPT_VERSION
100 template <class T> struct ElemTraits {
101  typedef AtomSignature signature;
102  static signature* get_sig_pointer(Molecule *mol) { return mol->atomSigPool; }
103  static int get_sig_id(const CompAtomExt &a) { return a.sigId; }
104 };
105 
106 template <> struct ElemTraits <ExclElem> {
107  typedef ExclusionSignature signature;
108  static signature* get_sig_pointer(Molecule *mol) { return mol->exclSigPool; }
109  static int get_sig_id(const CompAtomExt &a) { return a.exclId; }
110 };
111 #endif
112 
113 #ifdef USE_HOMETUPLES
114 //
115 // Simple base class for HomeTuples and SelfTuples that stores the type of the tuple
116 //
117 class Tuples {
118 private:
119  int type;
120 protected:
121  Tuples(int type) : type(type) {}
122 public:
123  // Tuple types
124  enum {BOND=0, ANGLE, DIHEDRAL, IMPROPER, EXCLUSION, CROSSTERM, NUM_TUPLE_TYPES};
125 
126  int getType() {return type;}
127  virtual void submitTupleCount(SubmitReduction *reduction, int tupleCount)=0;
128  // virtual void copyTupleData(void* tupleData)=0;
129  virtual int getNumTuples()=0;
130  virtual void* getTupleList()=0;
131  virtual void loadTuples(TuplePatchList& tuplePatchList, const char* isBasePatch, AtomMap *atomMap,
132  const std::vector<int>& pids = std::vector<int>())=0;
133 };
134 
135 //
136 // HomeTuples class. These are created and stored in ComputeBondedCUDA::registerCompute()
137 // e.g.: new HomeTuples<BondElem, Bond, BondValue>(BOND)
138 //
139 template <class T, class S, class P> class HomeTuples : public Tuples {
140  protected:
141  std::vector<T> tupleList;
142 
143  public:
144 
145  HomeTuples(int type=-1) : Tuples(type) {}
146 
147 #if __cplusplus < 201103L
148 #define final
149 #endif
150 
151  virtual void* getTupleList() final {
152  return (void*)tupleList.data();
153  }
154 
155  virtual void submitTupleCount(SubmitReduction *reduction, int tupleCount) final {
156  reduction->item(T::reductionChecksumLabel) += (BigReal)tupleCount;
157  }
158 
159  // virtual void copyTupleData(void* tupleData) final {
160  // for (int i=0;i < tupleList.size();i++) {
161  // tupleData[i] =
162  // }
163  // T::loadTupleData(tupleData);
164  // }
165 
166  virtual int getNumTuples() final {
167  return tupleList.size();
168  }
169 
170  virtual void loadTuples(TuplePatchList& tuplePatchList, const char* isBasePatch, AtomMap *atomMap,
171  const std::vector<int>& pids = std::vector<int>()) {
172 
173  if (isBasePatch == NULL) {
174  NAMD_bug("NULL isBasePatch detected in HomeTuples::loadTuples()");
175  }
176 
177  int numTuples;
178 
179 #ifdef MEM_OPT_VERSION
180  typename ElemTraits<T>::signature *allSigs;
181 #else
182  int32 **tuplesByAtom;
183  /* const (need to propagate const) */ S *tupleStructs;
184 #endif
185 
186  const P *tupleValues;
187  Node *node = Node::Object();
188  PatchMap *patchMap = PatchMap::Object();
189  // AtomMap *atomMap = AtomMap::Object();
190 
191 #ifdef MEM_OPT_VERSION
192  allSigs = ElemTraits<T>::get_sig_pointer(node->molecule);
193 #else
194  T::getMoleculePointers(node->molecule,
195  &numTuples, &tuplesByAtom, &tupleStructs);
196 #endif
197 
198  T::getParameterPointers(node->parameters, &tupleValues);
199 
200  tupleList.clear();
201 
202  LocalID aid[T::size];
203  int partition[T::size];
204 
205  const int lesOn = node->simParameters->lesOn;
206  const int soluteScalingOn = node->simParameters->soluteScalingOn;
207  const int fepOn = node->simParameters->singleTopology;
208  const int sdScaling = node->simParameters->sdScaling;
209  Real invLesFactor = lesOn ?
210  1.0/node->simParameters->lesFactor :
211  1.0;
212  const Real soluteScalingFactor = node->simParameters->soluteScalingFactor;
213  const Bool soluteScalingAll = node->simParameters->soluteScalingAll;
214  BigReal OneMinusLambda = 1.0 - node->simParameters->alchLambda;
215  BigReal Lambda = node->simParameters->alchLambda;
216  const int num_unpert_bonds = node->molecule->num_alch_unpert_Bonds;
217  const int num_unpert_angles = node->molecule->num_alch_unpert_Angles;
218  const int num_unpert_dihedrals = node->molecule->num_alch_unpert_Dihedrals;
219  Bond *unpert_bonds = node->molecule->alch_unpert_bonds;
220  Angle *unpert_angles = node->molecule->alch_unpert_angles;
221  Dihedral *unpert_dihedrals = node->molecule->alch_unpert_dihedrals;
222 
223  // cycle through each patch and gather all tuples
224  TuplePatchListIter ai(tuplePatchList);
225  if (pids.size() == 0) ai = ai.begin();
226 
227  int numPid = (pids.size() == 0) ? tuplePatchList.size() : pids.size();
228 
229  for (int ipid=0;ipid < numPid;ipid++) {
230  // Patch *patch;
231  int numAtoms;
232  CompAtomExt *atomExt;
233  // Take next patch
234  if (pids.size() == 0) {
235  Patch* patch = (*ai).p;
236  numAtoms = patch->getNumAtoms();
237  atomExt = (*ai).xExt;
238  ai++;
239  } else {
240  TuplePatchElem *tpe = tuplePatchList.find(TuplePatchElem(pids[ipid]));
241  Patch* patch = tpe->p;
242  numAtoms = patch->getNumAtoms();
243  atomExt = tpe->xExt;
244  //fprintf(stderr, "::loadTuples(%p) PE[%d] PID[%d] ipid %d atomExt = %p\n", this, CkMyPe(), tpe->p->getPatchID(),
245  // ipid, atomExt);
246  }
247 
248  // cycle through each atom in the patch and load up tuples
249  for (int j=0; j < numAtoms; j++)
250  {
251  /* cycle through each tuple */
252 #ifdef MEM_OPT_VERSION
253  typename ElemTraits<T>::signature *thisAtomSig =
254  &allSigs[ElemTraits<T>::get_sig_id(atomExt[j])];
255  TupleSignature *allTuples;
256  T::getTupleInfo(thisAtomSig, &numTuples, &allTuples);
257  for(int k=0; k<numTuples; k++) {
258  T t(atomExt[j].id, &allTuples[k], tupleValues);
259 #else
260  /* get list of all tuples for the atom */
261  int32 *curTuple = tuplesByAtom[atomExt[j].id];
262  for( ; *curTuple != -1; ++curTuple) {
263  T t(&tupleStructs[*curTuple],tupleValues);
264 #endif
265  register int i;
266  aid[0] = atomMap->localID(t.atomID[0]);
267  int homepatch = aid[0].pid;
268  int samepatch = 1;
269  partition[0] = fepOn ? node->molecule->get_fep_type(t.atomID[0]) : 0; //using atom partition to determine if a bonded term to be scaled by lambda or 1-lambda in single topology relative FEP.
270  int has_les = lesOn ? node->molecule->get_fep_type(t.atomID[0]) : 0;
271  int has_ss = soluteScalingOn ? node->molecule->get_ss_type(t.atomID[0]) : 0;
272  int is_fep_ss = partition[0] > 2;
273  int is_fep_sd = 0;
274  int fep_tuple_type = 0;
275  for (i=1; i < T::size; i++) {
276  aid[i] = atomMap->localID(t.atomID[i]);
277  samepatch = samepatch && ( homepatch == aid[i].pid );
278  partition[i] = fepOn ? node->molecule->get_fep_type(t.atomID[i]) : 0;
279  has_les |= lesOn ? node->molecule->get_fep_type(t.atomID[i]) : 0;
280  has_ss |= soluteScalingOn ? node->molecule->get_ss_type(t.atomID[i]) : 0;
281  if (fepOn) {
282  is_fep_ss &= partition[i] > 2;
283  is_fep_sd |= (abs(partition[i] - partition[0]) == 2);
284  fep_tuple_type = partition[i]; }
285  }
286  if (sdScaling && is_fep_sd) {
287  // check if this bonded term is one of Shobana term.
288  // This segment looks ugly and not GPU friendly,
289  // and might not appear in GPU code.
290  //
291  // XXX Could optimize in a number of ways:
292  // - could switch on T::size, then loop for that sized tuple
293  // - could use hash table to look up unpert_*[] elements
294  // - could add flag field to BondElem, et al., classes
295  for (i=0; i < num_unpert_bonds; i++) {
296  if (T::size == 2
297  && t.atomID[0]==unpert_bonds[i].atom1
298  && t.atomID[1]==unpert_bonds[i].atom2) is_fep_sd = 0;
299  }
300  for (i=0; i < num_unpert_angles; i++) {
301  if (T::size == 3
302  && t.atomID[0]==unpert_angles[i].atom1
303  && t.atomID[1]==unpert_angles[i].atom2
304  && t.atomID[2]==unpert_angles[i].atom3) is_fep_sd = 0;
305  }
306  for (i=0; i < num_unpert_dihedrals; i++) {
307  if (T::size == 4
308  && t.atomID[0]==unpert_dihedrals[i].atom1
309  && t.atomID[1]==unpert_dihedrals[i].atom2
310  && t.atomID[2]==unpert_dihedrals[i].atom3
311  && t.atomID[3]==unpert_dihedrals[i].atom4) is_fep_sd = 0;
312  }
313  }
314  if (T::size < 4 && !soluteScalingAll) has_ss = false;
315  if ( samepatch ) continue;
316  t.scale = (!has_les && !has_ss) ? 1.0 : ( has_les ? invLesFactor : soluteScalingFactor );
317  if (is_fep_ss) t.scale = (fep_tuple_type == 4) ? OneMinusLambda : Lambda;
318  if (is_fep_sd && sdScaling) t.scale = (fep_tuple_type == 4 || fep_tuple_type == 2) ? OneMinusLambda : Lambda;
319 
320  for (i=1; i < T::size; i++) {
321  homepatch = patchMap->downstream(homepatch,aid[i].pid);
322  }
323  if ( homepatch != notUsed && isBasePatch[homepatch] ) {
324  TuplePatchElem *p;
325  for (i=0; i < T::size; i++) {
326  t.p[i] = p = tuplePatchList.find(TuplePatchElem(aid[i].pid));
327  if ( ! p ) {
328 #ifdef MEM_OPT_VERSION
329  iout << iWARN << "Tuple with atoms ";
330 #else
331  iout << iWARN << "Tuple " << *curTuple << " with atoms ";
332 #endif
333  int erri;
334  for( erri = 0; erri < T::size; erri++ ) {
335  iout << t.atomID[erri] << "(" << aid[erri].pid << ") ";
336  }
337  iout << "missing patch " << aid[i].pid << "\n" << endi;
338  break;
339  }
340  t.localIndex[i] = aid[i].index;
341  }
342  if ( ! p ) continue;
343 #ifdef MEM_OPT_VERSION
344  //avoid adding Tuples whose atoms are all fixed
346  int allfixed = 1;
347  for(i=0; i<T::size; i++){
348  CompAtomExt *one = &(t.p[i]->xExt[aid[i].index]);
349  allfixed = allfixed & one->atomFixed;
350  }
351  if(!allfixed) tupleList.push_back(t);
352  }else{
353  tupleList.push_back(t);
354  }
355 #else
356  tupleList.push_back(t);
357 #endif
358  }
359  }
360  }
361  }
362  }
363 
364 };
365 #endif
366 
367 template <class T, class S, class P> class ComputeHomeTuples : public Compute {
368 
369  protected:
370 
371 #ifndef USE_HOMETUPLES
372  virtual void loadTuples(void) {
373  int numTuples;
374 
375  #ifdef MEM_OPT_VERSION
376  typename ElemTraits<T>::signature *allSigs;
377  #else
378  int32 **tuplesByAtom;
379  /* const (need to propagate const) */ S *tupleStructs;
380  #endif
381 
382  const P *tupleValues;
383  Node *node = Node::Object();
384 
385  #ifdef MEM_OPT_VERSION
386  allSigs = ElemTraits<T>::get_sig_pointer(node->molecule);
387  #else
388  T::getMoleculePointers(node->molecule,
389  &numTuples, &tuplesByAtom, &tupleStructs);
390  #endif
391 
392  T::getParameterPointers(node->parameters, &tupleValues);
393 
394  tupleList.resize(0);
395 
396  LocalID aid[T::size];
397  int partition[T::size];
398 
399  const int lesOn = node->simParameters->lesOn;
400  const int soluteScalingOn = node->simParameters->soluteScalingOn;
401  const int fepOn = node->simParameters->singleTopology;
402  const int sdScaling = node->simParameters->sdScaling;
403  Real invLesFactor = lesOn ?
404  1.0/node->simParameters->lesFactor :
405  1.0;
406  const Real soluteScalingFactor = node->simParameters->soluteScalingFactor;
407  const Bool soluteScalingAll = node->simParameters->soluteScalingAll;
408  BigReal OneMinusLambda = 1.0 - node->simParameters->alchLambda;
409  BigReal Lambda = node->simParameters->alchLambda;
410  const int num_unpert_bonds = node->molecule->num_alch_unpert_Bonds;
411  const int num_unpert_angles = node->molecule->num_alch_unpert_Angles;
412  const int num_unpert_dihedrals = node->molecule->num_alch_unpert_Dihedrals;
413  Bond *unpert_bonds = node->molecule->alch_unpert_bonds;
414  Angle *unpert_angles = node->molecule->alch_unpert_angles;
415  Dihedral *unpert_dihedrals = node->molecule->alch_unpert_dihedrals;
416 
417  // cycle through each patch and gather all tuples
418  TuplePatchListIter ai(tuplePatchList);
419 
420  for ( ai = ai.begin(); ai != ai.end(); ai++ )
421  {
422  // CompAtom *atom = (*ai).x;
423  Patch *patch = (*ai).p;
424  int numAtoms = patch->getNumAtoms();
425  CompAtomExt *atomExt = (*ai).xExt; //patch->getCompAtomExtInfo();
426 
427  // cycle through each atom in the patch and load up tuples
428  for (int j=0; j < numAtoms; j++)
429  {
430  /* cycle through each tuple */
431  #ifdef MEM_OPT_VERSION
432  typename ElemTraits<T>::signature *thisAtomSig =
433  &allSigs[ElemTraits<T>::get_sig_id(atomExt[j])];
434  TupleSignature *allTuples;
435  T::getTupleInfo(thisAtomSig, &numTuples, &allTuples);
436  for(int k=0; k<numTuples; k++) {
437  T t(atomExt[j].id, &allTuples[k], tupleValues);
438  #else
439  /* get list of all tuples for the atom */
440  int32 *curTuple = tuplesByAtom[atomExt[j].id];
441  for( ; *curTuple != -1; ++curTuple) {
442  T t(&tupleStructs[*curTuple],tupleValues);
443  #endif
444  register int i;
445  aid[0] = atomMap->localID(t.atomID[0]);
446  int homepatch = aid[0].pid;
447  int samepatch = 1;
448  partition[0] = fepOn ? node->molecule->get_fep_type(t.atomID[0]) : 0;
449  int has_les = lesOn ? node->molecule->get_fep_type(t.atomID[0]) : 0;
450  int has_ss = soluteScalingOn ? node->molecule->get_ss_type(t.atomID[0]) : 0;
451  int is_fep_ss = partition[0] > 2;
452  int is_fep_sd = 0;
453  int fep_tuple_type = 0;
454  for (i=1; i < T::size; i++) {
455  aid[i] = atomMap->localID(t.atomID[i]);
456  samepatch = samepatch && ( homepatch == aid[i].pid );
457  partition[i] = fepOn ? node->molecule->get_fep_type(t.atomID[i]) : 0;
458  has_les |= lesOn ? node->molecule->get_fep_type(t.atomID[i]) : 0;
459  has_ss |= soluteScalingOn ? node->molecule->get_ss_type(t.atomID[i]) : 0;
460  if (fepOn) {
461  is_fep_ss &= partition[i] > 2;
462  is_fep_sd |= (abs(partition[i] - partition[0]) == 2);
463  fep_tuple_type = partition[i];
464  }
465  }
466  if (sdScaling && is_fep_sd) {
467  for (i=0; i < num_unpert_bonds; i++) {
468  if (T::size == 2
469  && t.atomID[0]==unpert_bonds[i].atom1
470  && t.atomID[1]==unpert_bonds[i].atom2) is_fep_sd = 0;
471  }
472  for (i=0; i < num_unpert_angles; i++) {
473  if (T::size == 3
474  && t.atomID[0]==unpert_angles[i].atom1
475  && t.atomID[1]==unpert_angles[i].atom2
476  && t.atomID[2]==unpert_angles[i].atom3) is_fep_sd = 0;
477  }
478  for (i=0; i < num_unpert_dihedrals; i++) {
479  if (T::size == 4
480  && t.atomID[0]==unpert_dihedrals[i].atom1
481  && t.atomID[1]==unpert_dihedrals[i].atom2
482  && t.atomID[2]==unpert_dihedrals[i].atom3
483  && t.atomID[3]==unpert_dihedrals[i].atom4) is_fep_sd = 0;
484  }
485  }
486  if (T::size < 4 && !soluteScalingAll) has_ss = false;
487  if ( samepatch ) continue;
488  t.scale = (!has_les && !has_ss) ? 1.0 : ( has_les ? invLesFactor : soluteScalingFactor );
489  if (is_fep_ss) t.scale = (fep_tuple_type == 4) ? OneMinusLambda : Lambda;
490  if (is_fep_sd && sdScaling) t.scale = (fep_tuple_type == 4 || fep_tuple_type == 2) ? OneMinusLambda : Lambda;
491 
492  for (i=1; i < T::size; i++) {
493  homepatch = patchMap->downstream(homepatch,aid[i].pid);
494  }
495  if ( homepatch != notUsed && isBasePatch[homepatch] ) {
496  TuplePatchElem *p;
497  for (i=0; i < T::size; i++) {
498  t.p[i] = p = tuplePatchList.find(TuplePatchElem(aid[i].pid));
499  if ( ! p ) {
500  #ifdef MEM_OPT_VERSION
501  iout << iWARN << "Tuple with atoms ";
502  #else
503  iout << iWARN << "Tuple " << *curTuple << " with atoms ";
504  #endif
505  int erri;
506  for( erri = 0; erri < T::size; erri++ ) {
507  iout << t.atomID[erri] << "(" << aid[erri].pid << ") ";
508  }
509  iout << "missing patch " << aid[i].pid << "\n" << endi;
510  break;
511  }
512  t.localIndex[i] = aid[i].index;
513  }
514  if ( ! p ) continue;
515  #ifdef MEM_OPT_VERSION
516  //avoid adding Tuples whose atoms are all fixed
517  if(node->simParameters->fixedAtomsOn &&
519  int allfixed = 1;
520  for(i=0; i<T::size; i++){
521  CompAtomExt *one = &(t.p[i]->xExt[aid[i].index]);
522  allfixed = allfixed & one->atomFixed;
523  }
524  if(!allfixed) tupleList.add(t);
525  }else{
526  tupleList.add(t);
527  }
528  #else
529  tupleList.add(t);
530  #endif
531  }
532  }
533  }
534  }
535  }
536 #endif
537 
539 
540  protected:
541 
542 #ifdef USE_HOMETUPLES
543  HomeTuples<T, S, P>* tuples;
544  TuplePatchList tuplePatchList;
545 #else
548 #endif
549 
557  char *isBasePatch;
558 
560  patchMap = PatchMap::Object();
561  atomMap = AtomMap::Object();
563 
565  accelMDdoDihe=false;
566  if (params->accelMDOn) {
567  if (params->accelMDdihe || params->accelMDdual) accelMDdoDihe=true;
568  }
569  if (params->pressureProfileOn) {
570  pressureProfileSlabs = T::pressureProfileSlabs =
571  params->pressureProfileSlabs;
572  int n = T::pressureProfileAtomTypes = params->pressureProfileAtomTypes;
573  pressureProfileReduction = ReductionMgr::Object()->willSubmit(
574  REDUCTIONS_PPROF_BONDED, 3*pressureProfileSlabs*((n*(n+1))/2));
575  int numAtomTypePairs = n*n;
576  pressureProfileData = new BigReal[3*pressureProfileSlabs*numAtomTypePairs];
577  } else {
578  pressureProfileReduction = NULL;
579  pressureProfileData = NULL;
580  }
581  doLoadTuples = false;
582  isBasePatch = 0;
583 #ifdef USE_HOMETUPLES
584  tuples = NULL;
585 #endif
586  }
587 
589  patchMap = PatchMap::Object();
590  atomMap = AtomMap::Object();
593  accelMDdoDihe=false;
594  if (params->accelMDOn) {
595  if (params->accelMDdihe || params->accelMDdual) accelMDdoDihe=true;
596  }
597  if (params->pressureProfileOn) {
598  pressureProfileSlabs = T::pressureProfileSlabs =
599  params->pressureProfileSlabs;
600  int n = T::pressureProfileAtomTypes = params->pressureProfileAtomTypes;
601  pressureProfileReduction = ReductionMgr::Object()->willSubmit(
602  REDUCTIONS_PPROF_BONDED, 3*pressureProfileSlabs*((n*(n+1))/2));
603  int numAtomTypePairs = n*n;
604  pressureProfileData = new BigReal[3*pressureProfileSlabs*numAtomTypePairs];
605  } else {
606  pressureProfileReduction = NULL;
607  pressureProfileData = NULL;
608  }
609  doLoadTuples = false;
610  int nPatches = patchMap->numPatches();
611  isBasePatch = new char[nPatches];
612  int i;
613  for (i=0; i<nPatches; ++i) { isBasePatch[i] = 0; }
614  for (i=0; i<pids.size(); ++i) { isBasePatch[pids[i]] = 1; }
615 #ifdef USE_HOMETUPLES
616  tuples = NULL;
617 #endif
618  }
619 
620  public:
621 
622  virtual ~ComputeHomeTuples() {
623  delete reduction;
624  delete [] isBasePatch;
625  delete pressureProfileReduction;
626  delete pressureProfileData;
627 #ifdef USE_HOMETUPLES
628  if (tuples != NULL) delete tuples;
629 #endif
630  }
631 
632  //======================================================================
633  // initialize() - Method is invoked only the first time
634  // atom maps, patchmaps etc are ready and we are about to start computations
635  //======================================================================
636  virtual void initialize(void) {
637 
638 #if defined(NAMD_CUDA) || defined(NAMD_HIP)
639  ProxyMgr *proxyMgr = ProxyMgr::Object();
640 #endif
641 
642 #ifdef USE_HOMETUPLES
643  tuples = new HomeTuples<T, S, P>();
644 #endif
645 
646  // Start with empty list
647  tuplePatchList.clear();
648 
649  int nPatches = patchMap->numPatches();
650  int pid;
651  for (pid=0; pid<nPatches; ++pid) {
652  if ( isBasePatch[pid] ) {
653 #if defined(NAMD_CUDA) || defined(NAMD_HIP)
654  proxyMgr->createProxy(pid);
655 #endif
656  Patch *patch = patchMap->patch(pid);
657  tuplePatchList.add(TuplePatchElem(patch, this));
658  }
659  }
660 
661  // Gather all proxy patches (neighbors, that is)
663 
664  for (pid=0; pid<nPatches; ++pid) if ( isBasePatch[pid] ) {
665  int numNeighbors = patchMap->upstreamNeighbors(pid,neighbors);
666  for ( int i = 0; i < numNeighbors; ++i ) {
667  if ( ! tuplePatchList.find(TuplePatchElem(neighbors[i])) ) {
668 #if defined(NAMD_CUDA) || defined(NAMD_HIP)
669  proxyMgr->createProxy(neighbors[i]);
670 #endif
671  Patch *patch = patchMap->patch(neighbors[i]);
672  tuplePatchList.add(TuplePatchElem(patch, this));
673  }
674  }
675  }
676  setNumPatches(tuplePatchList.size());
677  doLoadTuples = true;
678 
679  basePriority = COMPUTE_PROXY_PRIORITY; // no patch dependence
680  }
681 
682  //======================================================================
683  // atomUpdate() - Method is invoked after anytime that atoms have been
684  // changed in patches used by this Compute object.
685  //======================================================================
686  void atomUpdate(void) {
687  doLoadTuples = true;
688  }
689 
690 //-------------------------------------------------------------------
691 // Routine which is called by enqueued work msg. It wraps
692 // actualy Force computation with the apparatus needed
693 // to get access to atom positions, return forces etc.
694 //-------------------------------------------------------------------
695  virtual void doWork(void) {
696 
697  LdbCoordinator::Object()->startWork(ldObjHandle);
698  // Open Boxes - register that we are using Positions
699  // and will be depositing Forces.
700  UniqueSetIter<TuplePatchElem> ap(tuplePatchList);
701  for (ap = ap.begin(); ap != ap.end(); ap++) {
702  ap->x = ap->positionBox->open();
703  ap->xExt = ap->p->getCompAtomExtInfo();
704  if ( ap->p->flags.doMolly ) ap->x_avg = ap->avgPositionBox->open();
705  ap->r = ap->forceBox->open();
706  ap->f = ap->r->f[Results::normal];
707  if (accelMDdoDihe) ap->af = ap->r->f[Results::amdf]; // for dihedral-only or dual-boost accelMD
708  }
709 
710  BigReal reductionData[T::reductionDataSize];
711  int tupleCount = 0;
712  int numAtomTypes = T::pressureProfileAtomTypes;
713  int numAtomTypePairs = numAtomTypes*numAtomTypes;
714 
715  for ( int i = 0; i < T::reductionDataSize; ++i ) reductionData[i] = 0;
716  if (pressureProfileData) {
717  memset(pressureProfileData, 0, 3*pressureProfileSlabs*numAtomTypePairs*sizeof(BigReal));
718  // Silly variable hiding of the previous iterator
719  UniqueSetIter<TuplePatchElem> newap(tuplePatchList);
720  newap = newap.begin();
721  const Lattice &lattice = newap->p->lattice;
722  T::pressureProfileThickness = lattice.c().z / pressureProfileSlabs;
723  T::pressureProfileMin = lattice.origin().z - 0.5*lattice.c().z;
724  }
725 
726  if ( ! Node::Object()->simParameters->commOnly ) {
727  if ( doLoadTuples ) {
728 #ifdef USE_HOMETUPLES
729  tuples->loadTuples(tuplePatchList, isBasePatch, AtomMap::Object());
730 #else
731  loadTuples();
732 #endif
733  doLoadTuples = false;
734  }
735  // take triplet and pass with tuple info to force eval
736 #ifdef USE_HOMETUPLES
737  T *al = (T *)tuples->getTupleList();
738  const int ntuple = tuples->getNumTuples();
739 #else
740  T *al = tupleList.begin();
741  const int ntuple = tupleList.size();
742 #endif
743  if ( ntuple ) T::computeForce(al, ntuple, reductionData, pressureProfileData);
744  tupleCount += ntuple;
745  }
746 
747  LdbCoordinator::Object()->endWork(ldObjHandle);
748 
749  T::submitReductionData(reductionData,reduction);
750  reduction->item(T::reductionChecksumLabel) += (BigReal)tupleCount;
751  reduction->submit();
752 
753  if (pressureProfileReduction) {
754  // For ease of calculation we stored interactions between types
755  // i and j in (ni+j). For efficiency now we coalesce the
756  // cross interactions so that just i<=j are stored.
757  const int arraysize = 3*pressureProfileSlabs;
758  const BigReal *data = pressureProfileData;
759  for (int i=0; i<numAtomTypes; i++) {
760  for (int j=0; j<numAtomTypes; j++) {
761  int ii=i;
762  int jj=j;
763  if (ii > jj) { int tmp=ii; ii=jj; jj=tmp; }
764  const int reductionOffset =
765  (ii*numAtomTypes - (ii*(ii+1))/2 + jj)*arraysize;
766  for (int k=0; k<arraysize; k++) {
767  pressureProfileReduction->item(reductionOffset+k) += data[k];
768  }
769  data += arraysize;
770  }
771  }
772  pressureProfileReduction->submit();
773  }
774 
775  // Close boxes - i.e. signal we are done with Positions and
776  // AtomProperties and that we are depositing Forces
777  for (ap = ap.begin(); ap != ap.end(); ap++) {
778  ap->positionBox->close(&(ap->x));
779  if ( ap->p->flags.doMolly ) ap->avgPositionBox->close(&(ap->x_avg));
780  ap->forceBox->close(&(ap->r));
781  }
782  }
783 };
784 
785 
786 #endif
787 
static Node * Object()
Definition: Node.h:86
Elem * find(const Elem &elem)
Definition: UniqueSet.h:60
UniqueSet< TuplePatchElem > TuplePatchList
#define COMPUTE_PROXY_PRIORITY
Definition: Priorities.h:71
int num_alch_unpert_Dihedrals
Definition: Molecule.h:603
Box< Patch, CompAtom > * registerAvgPositionPickup(Compute *cid)
Definition: Patch.C:133
int getNumAtoms() const
Definition: Patch.h:105
int size(void) const
Definition: ResizeArray.h:131
int size(void) const
Definition: UniqueSet.h:58
NAMD_HOST_DEVICE Vector c() const
Definition: Lattice.h:270
static ProxyMgr * Object()
Definition: ProxyMgr.h:394
Definition: Node.h:78
void clear(void)
Definition: UniqueSet.h:62
int32 ComputeID
Definition: NamdTypes.h:278
Lattice & lattice
Definition: Patch.h:127
static void partition(int *order, const FullAtom *atoms, int begin, int end)
Definition: SortAtoms.C:45
int32 atom3
Definition: structures.h:67
static PatchMap * Object()
Definition: PatchMap.h:27
Angle * alch_unpert_angles
Definition: Molecule.h:605
Definition: Vector.h:72
SimParameters * simParameters
Definition: Node.h:181
int num_alch_unpert_Bonds
Definition: Molecule.h:601
float Real
Definition: common.h:118
int32_t int32
Definition: common.h:38
BigReal & item(int i)
Definition: ReductionMgr.h:313
BigReal * pressureProfileData
void startWork(const LDObjHandle &handle)
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
BigReal z
Definition: Vector.h:74
virtual ~ComputeHomeTuples()
int downstream(int pid1, int pid2)
Definition: PatchMap.inl:51
int upstreamNeighbors(int pid, PatchID *neighbor_ids)
Definition: PatchMap.C:669
TuplePatchList tuplePatchList
ComputeHomeTuples(ComputeID c)
SubmitReduction * pressureProfileReduction
SubmitReduction * willSubmit(int setID, int size=-1)
Definition: ReductionMgr.C:366
std::ostream & iWARN(std::ostream &s)
Definition: InfoStream.C:82
int num_alch_unpert_Angles
Definition: Molecule.h:602
unsigned char get_ss_type(int anum) const
Definition: Molecule.h:1443
int add(const Elem &elem)
Definition: UniqueSet.h:52
static ReductionMgr * Object(void)
Definition: ReductionMgr.h:279
#define iout
Definition: InfoStream.h:51
int pressureProfileSlabs
Patch * patch(PatchID pid)
Definition: PatchMap.h:244
virtual void initialize(void)
BigReal alchLambda
Dihedral * alch_unpert_dihedrals
Definition: Molecule.h:606
Molecule stores the structural information for the system.
Definition: Molecule.h:175
Definition: Patch.h:35
Flags flags
Definition: Patch.h:128
UniqueSetIter< T > begin(void) const
Definition: UniqueSetIter.h:55
int32 index
Definition: NamdTypes.h:290
uint32 id
Definition: NamdTypes.h:156
int32 atom4
Definition: structures.h:68
int32 atom1
Definition: structures.h:50
TuplePatchElem(Patch *p_param, Compute *cid)
int numPatches(void) const
Definition: PatchMap.h:59
void NAMD_bug(const char *err_msg)
Definition: common.C:195
int32 atom2
Definition: structures.h:58
TuplePatchElem(PatchID pid=-1)
BigReal soluteScalingFactor
int32 atom1
Definition: structures.h:57
int Bool
Definition: common.h:142
Force * f[maxNumForces]
Definition: PatchTypes.h:146
int operator<(const TuplePatchElem &elem) const
CompAtomList p
Definition: Patch.h:153
LocalID localID(AtomID id)
Definition: AtomMap.h:78
int32 atom3
Definition: structures.h:59
Bond * alch_unpert_bonds
Definition: Molecule.h:604
PatchID getPatchID() const
Definition: Patch.h:114
Box< Patch, CompAtom > * positionBox
void createProxy(PatchID pid)
Definition: ProxyMgr.C:492
UniqueSetIter< T > end(void) const
Definition: UniqueSetIter.h:64
virtual void doWork(void)
static LdbCoordinator * Object()
PatchID pid
Definition: NamdTypes.h:289
static AtomMap * Object()
Definition: AtomMap.h:37
int32 atom2
Definition: structures.h:66
unsigned char get_fep_type(int anum) const
Definition: Molecule.h:1432
Parameters * parameters
Definition: Node.h:180
void endWork(const LDObjHandle &handle)
ResizeArray< T > tupleList
int pressureProfileAtomTypes
int operator==(const TuplePatchElem &elem) const
iterator begin(void)
Definition: ResizeArray.h:36
int hash() const
SubmitReduction * reduction
ComputeHomeTuples(ComputeID c, PatchIDList &pids)
Bool pressureProfileOn
virtual void loadTuples(void)
Box< Patch, CompAtom > * avgPositionBox
CompAtomExt * xExt
void submit(void)
Definition: ReductionMgr.h:324
uint32 atomFixed
Definition: NamdTypes.h:158
Data * open(void)
Definition: Box.h:39
int32 PatchID
Definition: NamdTypes.h:277
Molecule * molecule
Definition: Node.h:179
UniqueSetIter< TuplePatchElem > TuplePatchListIter
Box< Patch, Results > * forceBox
NAMD_HOST_DEVICE Vector origin() const
Definition: Lattice.h:278
int32 atom1
Definition: structures.h:65
int32 atom2
Definition: structures.h:51
void close(Data **const t)
Definition: Box.h:49
int doMolly
Definition: PatchTypes.h:24
Box< Patch, CompAtom > * registerPositionPickup(Compute *cid)
Definition: Patch.C:106
double BigReal
Definition: common.h:123
CompAtomExt * getCompAtomExtInfo()
Definition: Patch.h:117
Box< Patch, Results > * registerForceDeposit(Compute *cid)
Definition: Patch.C:227