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