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