changa  3.5
 All Classes Files Functions Variables Typedefs Enumerations Friends Macros Groups Pages
GenericTreeNode.h
Go to the documentation of this file.
1 
7 #ifndef GENERICTREENODE_H
8 #define GENERICTREENODE_H
9 
10 #include "pup.h"
11 
12 #include <map>
13 #include <vector>
14 #include <algorithm>
15 #include <set>
16 #include <list>
17 
18 #include "OrientedBox.h"
19 #include "MultipoleMoments.h"
20 #include "keytype.h"
21 #include "GravityParticle.h"
22 
23 namespace Tree {
24 
33  // C++11 syntax
34  // using NodeKey = KeyType;
35  typedef KeyType NodeKey;
36  static const int NodeKeyBits = 8*sizeof(NodeKey);
37 
39  enum NodeType {
40  Invalid = 1,
41  Bucket,
42  Internal,
43  Boundary,
44  NonLocal,
45  Empty,
46  Top,
47  NonLocalBucket,
48  Cached,
49  CachedBucket,
50  CachedEmpty
51  };
52 
54  extern int numEmptyNodes;
55 
56 class NodePool;
57 
60 #ifdef CHANGA_REFACTOR_WALKCHECK
61  public:
62  bool touched;
63  char by;
64 #endif
65  protected:
66  NodeType myType;
67  NodeKey key;
68 
69  GenericTreeNode() : myType(Invalid), key(0), parent(0), firstParticle(0),
71 #if COSMO_STATS > 0
72  used = false;
73 #endif
74 #if INTERLIST_VER > 0
76  startBucket=-1;
77 #ifdef CUDA
78  nodeArrayIndex = -1;
79  bucketArrayIndex = -1;
80 #endif
81 #endif
82 #ifdef CHANGA_REFACTOR_WALKCHECK
83  touched = false;
84  by = 'I';
85 #endif
86  }
87 
88  public:
89 #if COSMO_STATS > 0
90  bool used;
91 #endif
92 
98  OrientedBox<cosmoType> boundingBox;
100  OrientedBox<double> bndBoxBall;
102  unsigned int iParticleTypes;
104  int64_t nSPH;
115  unsigned int particleCount;
118 
122  int rungs;
123 
124 #if INTERLIST_VER > 0
125  int numBucketsBeneath;
129 #ifdef CUDA
130  int nodeArrayIndex;
132  int bucketArrayIndex;
133 #endif
134 #endif
135  Vector3D<double> centerSm;
138  double sizeSm;
140  double fKeyMax;
142  int iRank;
143 
150  GenericTreeNode(NodeKey k, NodeType type, int first, int last, GenericTreeNode *p) : myType(type), key(k), parent(p), firstParticle(first), lastParticle(last), remoteIndex(0) {
151 #if INTERLIST_VER > 0
153  startBucket=-1;
154 #ifdef CUDA
155  nodeArrayIndex = -1;
156  bucketArrayIndex = -1;
157 #endif
158 #endif
159  }
160 
161  virtual ~GenericTreeNode() { }
163  virtual void fullyDelete() = 0;
164 
166  inline NodeType getType() const { return myType; }
168  inline void setType(NodeType t) { myType = t; }
169 
171  inline NodeKey getKey() const { return key; }
172 
174  virtual unsigned int numChildren() const = 0;
176  virtual GenericTreeNode* getChildren(int) = 0;
178  virtual void setChildren(int, GenericTreeNode*) = 0;
180  virtual NodeKey getChildKey(int) = 0;
182  virtual NodeKey getParentKey() = 0;
184  virtual int whichChild(NodeKey childkey) = 0;
185 #if INTERLIST_VER > 0
186  virtual bool contains(NodeKey nodekey) = 0;
188 #endif
189 
191  bool isValid(){
192  return (myType != Invalid);
193  }
194 
196  bool isCached(){
197  return (myType == Cached ||
198  myType == CachedBucket ||
199  myType == CachedEmpty);
200  }
201 
203  bool isBucket(){
204  return (myType == Bucket ||
205  myType == CachedBucket ||
206  myType == NonLocalBucket);
207  }
208 
211  virtual void makeOctChildren(GravityParticle *part, int totalPart, int level, NodePool *pool = NULL) = 0;
212  virtual void makeOrbChildren(GravityParticle *part, int totalPart, int level, int rootsLevel, bool (*compFnPtr[])(GravityParticle, GravityParticle), bool spatial, NodePool *pool = NULL) = 0;
213 
216  virtual void getChunks(int num, NodeKey *&ret) = 0;
217 
219  inline void makeBucket(GravityParticle *part) {
220  myType = Bucket;
221  iRank = CkMyRank();
222 #if INTERLIST_VER > 0
223  numBucketsBeneath = 1;
224 #endif
225  calculateRadiusBox(moments, boundingBox); /* set initial size */
226  boundingBox.reset();
227  bndBoxBall.reset();
228  iParticleTypes = 0;
229  nSPH = 0;
230  rungs = 0;
231  for (int i = firstParticle; i <= lastParticle; ++i) {
232  moments += part[i];
233  boundingBox.grow(part[i].position);
234  if(TYPETest(&part[i], TYPE_GAS)) {
235  double fBallMax = part[i].fBallMax();
236  bndBoxBall.grow(part[i].position
237  + Vector3D<double>(fBallMax, fBallMax, fBallMax));
238  bndBoxBall.grow(part[i].position
239  - Vector3D<double>(fBallMax, fBallMax, fBallMax));
240  nSPH++;
241  }
242  iParticleTypes |= part[i].iType;
243  if (part[i].rung > rungs) rungs = part[i].rung;
244  }
245  if(particleCount > 1)
247  &part[lastParticle+1]);
248  }
249 
251  inline void makeEmpty() {
252  myType = Empty;
253  particleCount = 0;
254 #if INTERLIST_VER > 0
255  numBucketsBeneath = 0;
256 #endif
257  moments.clear();
258  boundingBox.reset();
259  bndBoxBall.reset();
260  iParticleTypes = 0;
261  nSPH = 0;
262  }
263 
265  void getGraphViz(std::ostream &out);
266 
268  virtual NodeKey getLongestCommonPrefix(NodeKey k1, NodeKey k2)
269  {
270  CkAbort("getLongestCommonPrefix not implemented\n");
271  return 0;
272  }
273 
275  virtual int getLevel(NodeKey k) = 0;
277  virtual GenericTreeNode *clone() const = 0;
278 
280  virtual void pup(PUP::er &p, int depth) = 0;
282  virtual void pup(PUP::er &p) {
283  int iType;
284  if(p.isUnpacking()) {
285  p | iType;
286  myType = (NodeType) iType;
287 #ifdef CUDA
288  // so that newly shipped nodes are not mistakenly assumed
289  // to be present on the GPU
290  nodeArrayIndex = -1;
291  bucketArrayIndex = -1;
292 #endif
293  } else {
294  iType = (int) myType;
295  p | iType;
296  }
297  p | key;
298  p | moments;
299  p | boundingBox;
300  p | bndBoxBall;
301  p | iParticleTypes;
302  p | nSPH;
303  p | firstParticle;
304  p | lastParticle;
305  p | remoteIndex;
306  p | particleCount;
307 #if INTERLIST_VER > 0
308  p | numBucketsBeneath;
309  p | startBucket;
310 #endif
311  p | centerSm;
312  p | sizeSm;
313  p | fKeyMax;
314 #ifdef CHANGA_REFACTOR_WALKCHECK
315  p | touched;
316  p | by;
317 #endif
318  }
319  };
320 
321 class BinaryTreeNode;
322 
324 class NodePool {
325  int next;
326  int szPool;
328  std::list<BinaryTreeNode *> pools;
329 public:
330  NodePool() {
331  next = szPool = 128; // Determines the size of the pools
332  }
333  ~NodePool();
336  BinaryTreeNode *alloc_one(NodeKey k, NodeType type, int first,
337  int nextlast, BinaryTreeNode *p);
338 
339  };
340 
344  typedef std::map<NodeKey, GenericTreeNode *> NodeLookupType;
345 
348  protected:
349  public:
350  BinaryTreeNode* children[2];
351 
353  children[0] = 0;
354  children[1] = 0;
355  }
356 
357  public:
358  BinaryTreeNode(NodeKey k, NodeType type, int first, int nextlast, BinaryTreeNode *p) : GenericTreeNode(k, type, first, nextlast, p) {
359  children[0] = 0;
360  children[1] = 0;
361  }
362 
363  void fullyDelete() {
364  if (children[0] != NULL) children[0]->fullyDelete();
365  delete children[0];
366  if (children[1] != NULL) children[1]->fullyDelete();
367  delete children[1];
368  }
369 
370  unsigned int numChildren() const {
371  return 2;
372  }
373 
375  CkAssert(i>=0 && i<2);
376  return children[i];
377  }
378 
379  void setChildren(int i, GenericTreeNode* node) {
380  CkAssert(i>=0 && i<2);
381  children[i] = (BinaryTreeNode*)node;
382  }
383 
384  NodeKey getChildKey(int i) {
385  CkAssert(i>=0 && i<2);
386  return (key<<1) + i;
387  }
388 
389  NodeKey getParentKey() {
390  return (key>>1);
391  }
392 
393  int getLevel(NodeKey k) {
394  int i = 0;
395  k >>= 1;
396  while (k!=0) {
397  k >>= 1;
398  ++i;
399  }
400  return i;
401  }
402 
403  NodeKey getLongestCommonPrefix(NodeKey k1, NodeKey k2){
404 
405  int l1 = getLevel(k1)+1;
406  int l2 = getLevel(k2)+1;
407 
408  NodeKey a1 = k1 << (NodeKeyBits-l1);
409  NodeKey a2 = k2 << (NodeKeyBits-l2);
410 
411  NodeKey a = a1 ^ a2;
412  int i = 0;
413  while( a < (NodeKey(1)<<(NodeKeyBits-1)) )
414  {
415  a = a << 1;
416  i++;
417  }
418  return (k1 >> (l1-i)); // or k2 >> (l2-i)
419  };
420 
421 
422  int whichChild(NodeKey child) {
423  int thisLevel = getLevel(key);
424  int childLevel = getLevel(child);
425  return ((child >> (childLevel-thisLevel-1)) ^ (key << 1));
426  }
427 
428 #if INTERLIST_VER > 0
429  bool contains(NodeKey node) {
430  int thisLevel = getLevel(key);
431  int nodeLevel = getLevel(node);
432 
433  if(nodeLevel<thisLevel) return false;
434 
435  return ((node>>(nodeLevel-thisLevel))==key);
436  }
437 #endif
438 
439  bool isLeftChild() const {
440  return (dynamic_cast<BinaryTreeNode *>(parent) && dynamic_cast<BinaryTreeNode *>(parent)->children[0] == this);
441  }
442 
443  bool isRightChild() const {
444  return (dynamic_cast<BinaryTreeNode *>(parent) && dynamic_cast<BinaryTreeNode *>(parent)->children[1] == this);
445  }
446 
447  BinaryTreeNode* getSibling() const {
448  BinaryTreeNode* p = dynamic_cast<BinaryTreeNode *>(parent);
449  if(p)
450  return (p->children[0] == this ? p->children[1] : p->children[0]);
451  else
452  return 0;
453  }
454 
465  void makeOctChildren(GravityParticle *part, int totalPart, int level,
466  NodePool *pool=NULL) {
467  if(pool) {
468  children[0] = pool->alloc_one();
469  children[1] = pool->alloc_one();
470  }
471  else {
472  children[0] = new BinaryTreeNode();
473  children[1] = new BinaryTreeNode();
474  }
475  children[0]->parent = this;
476  children[1]->parent = this;
477  children[0]->boundingBox = boundingBox;
478  children[1]->boundingBox = boundingBox;
479  double split;
480  switch (level%3) {
481  case 0:
482  split = 0.5 * (boundingBox.greater_corner.x + boundingBox.lesser_corner.x);
483  children[0]->boundingBox.greater_corner.x = split;
484  children[1]->boundingBox.lesser_corner.x = split;
485  break;
486  case 1:
487  split = 0.5 * (boundingBox.greater_corner.y + boundingBox.lesser_corner.y);
488  children[0]->boundingBox.greater_corner.y = split;
489  children[1]->boundingBox.lesser_corner.y = split;
490  break;
491  case 2:
492  split = 0.5 * (boundingBox.greater_corner.z + boundingBox.lesser_corner.z);
493  children[0]->boundingBox.greater_corner.z = split;
494  children[1]->boundingBox.lesser_corner.z = split;
495  break;
496  }
497  children[0]->key = key << 1;
498  children[1]->key = (key << 1) + 1;
499  children[0]->firstParticle = firstParticle;
500  children[1]->lastParticle = lastParticle;
501 
502  // mask holds the bit that determines a particle's membership in
503  // either the left (0) or right (1) child.
504  SFC::Key mask = SFC::Key(1) << ((SFC::KeyBits-1) - level);
505  SFC::Key leftBit = part[firstParticle].key & mask;
506  SFC::Key rightBit = part[lastParticle].key & mask;
507 
508  if (leftBit == rightBit) {
509  // we have only one child, the other is either NonLocal or Empty
510  if (leftBit) {
511  // left child missing
512  if (firstParticle == 0) {
513  // We are at the left domain boundary: the left child is
514  // completely on another TreePiece
515  children[0]->myType = NonLocal;
516  children[1]->myType = Boundary;
517  } else {
518  children[0]->makeEmpty();
519  children[1]->myType = lastParticle==totalPart+1 ? Boundary : Internal;
520  }
521  children[0]->lastParticle = firstParticle-1;
522  children[0]->particleCount = 0;
523  children[1]->firstParticle = firstParticle;
524  children[1]->particleCount = particleCount;
525  } else {
526  // right child missing
527  if (lastParticle == totalPart+1) {
528  // We are at the right domain boundary: the right child is
529  // completely on another TreePiece
530  children[1]->myType = NonLocal;
531  children[0]->myType = Boundary;
532  } else {
533  children[1]->makeEmpty();
534  children[0]->myType = firstParticle==0 ? Boundary : Internal;
535  }
536  children[1]->firstParticle = lastParticle+1;
537  children[1]->particleCount = 0;
538  children[0]->lastParticle = lastParticle;
539  children[0]->particleCount = particleCount;
540  }
541  } else if (leftBit < rightBit) {
542  // both children are present
543  if (firstParticle == 0 && leftBit != (part[1].key & mask)) {
544  // the left child is NonLocal: the boundary particle (from
545  // another TP) is in the left child, but the rest of the
546  // particles are in the right child.
547  children[0]->myType = NonLocal;
548  children[0]->lastParticle = firstParticle;
549  children[1]->myType = lastParticle==totalPart+1 ? Boundary : Internal;
550  children[1]->firstParticle = firstParticle+1;
551  children[1]->particleCount = particleCount;
552  } else if (lastParticle == totalPart+1 && rightBit != (part[totalPart].key & mask)) {
553  // the right child is NonLocal: the boundary particle (from
554  // another TP) is in the right child, but the rest of the
555  // particles are in the left child.
556  children[1]->myType = NonLocal;
557  children[1]->firstParticle = lastParticle;
558  children[0]->myType = firstParticle==0 ? Boundary : Internal;
559  children[0]->lastParticle = lastParticle-1;
560  children[0]->particleCount = particleCount;
561  } else {
562  // the splitting point is somewhere in the middle
563  // The following statement finds the first particle with
564  // splitting bit (see the variable 'mask' above) set.
565  GravityParticle *splitParticle = std::lower_bound(&part[firstParticle],
566  &part[lastParticle+1],
567  (GravityParticle)(part[lastParticle].key
568  & ((~ (SFC::Key)0) << ((SFC::KeyBits-1)-level))));
569  children[0]->lastParticle = splitParticle - part - 1;
570  children[1]->firstParticle = splitParticle - part;
571  children[0]->particleCount = children[0]->lastParticle - firstParticle + 1;
572  children[1]->particleCount = lastParticle - children[1]->firstParticle + 1;
573  children[0]->myType = children[0]->particleCount==0 ? Empty : (firstParticle==0 ? Boundary : Internal);
574  children[1]->myType = children[1]->particleCount==0 ? Empty : (lastParticle==totalPart+1 ? Boundary : Internal);
575  if (children[0]->myType==Empty) children[0]->makeEmpty();
576  if (children[1]->myType==Empty) children[1]->makeEmpty();
577  if (firstParticle == 0) children[0]->particleCount --;
578  if (lastParticle == totalPart+1) children[1]->particleCount --;
579  }
580  } else {
581  CkAbort("Ok, the particles should be ordered so, how the hell did we get here?!?");
582  }
583  children[0]->particlePointer = &part[children[0]->firstParticle];
584  children[1]->particlePointer = &part[children[1]->firstParticle];
585 #if INTERLIST_VER > 0
586  if(children[0]->myType == NonLocal) children[0]->numBucketsBeneath = 0;
587  if(children[1]->myType == NonLocal) children[1]->numBucketsBeneath = 0;
588  // empty nodes are makeEmpty()'ed, so that the numbucketsbeneath them are 0
589 #endif
590  }
591 
592  // Constructs 2 children of this node based on ORB decomposition
593  void makeOrbChildren(GravityParticle *part, int totalPart, int level,
594  int rootsLevel,
595  bool (*compFnPtr[])(GravityParticle, GravityParticle),
596  bool spatial, NodePool *pool=NULL) {
597 
598  if(pool) {
599  children[0] = pool->alloc_one();
600  children[1] = pool->alloc_one();
601  }
602  else {
603  children[0] = new BinaryTreeNode();
604  children[1] = new BinaryTreeNode();
605  }
606  children[0]->parent = this;
607  children[1]->parent = this;
608  children[0]->boundingBox = boundingBox;
609  children[1]->boundingBox = boundingBox;
610 
611  children[0]->key = key << 1;
612  children[1]->key = (key << 1) + 1;
613  children[0]->firstParticle = firstParticle;
614  children[1]->lastParticle = lastParticle;
615 
616  //CkPrintf("children keys:%lld,%lld\n",children[0]->key,children[1]->key);
617  if(level<rootsLevel){
618  //This branch is taken for levels above the TreePiece root level
619  //TreePiece root level is the level from where onwards data is internal
620  SFC::Key tmp = 1 << (level+1);
621  tmp = children[0]->key - tmp;
622  SFC::Key tmp2 = part[0].key >> (rootsLevel-level-1);
623 
624  if(level+1 != rootsLevel){
625  if(tmp==tmp2){
626  children[0]->myType = Boundary;
627  children[1]->myType = NonLocal;
628  children[1]->firstParticle = lastParticle+1;
629  children[0]->lastParticle = lastParticle;
630  children[0]->particleCount = particleCount;
631  }
632  else{
633  children[0]->myType = NonLocal;
634  children[1]->myType = Boundary;
635  children[0]->lastParticle = firstParticle-1;
636  children[1]->firstParticle = firstParticle;
637  children[1]->particleCount = particleCount;
638  }
639  }
640  else{ //Special case for TreePiece root level
641  if(tmp==tmp2){
642  children[0]->myType = Internal;
643  children[1]->myType = NonLocal;
644  children[1]->firstParticle = lastParticle+1;
645  children[0]->lastParticle = lastParticle;
646  children[0]->particleCount = particleCount;
647  if(firstParticle==0)
648  children[0]->firstParticle = firstParticle+1;
649  if(lastParticle==totalPart+1)
650  children[0]->lastParticle = lastParticle-1;
651  }
652  else{
653  children[0]->myType = NonLocal;
654  children[1]->myType = Internal;
655  children[0]->lastParticle = firstParticle-1;
656  children[1]->firstParticle = firstParticle;
657  children[1]->particleCount = particleCount;
658  if(firstParticle==0)
659  children[1]->firstParticle = firstParticle+1;
660  if(lastParticle==totalPart+1)
661  children[1]->lastParticle = lastParticle-1;
662  }
663  }
664  }
665  else{ //Below the TreePiece root level
666  float len=0.0,len2=0.0;
667  int dim;
668 
669  if(spatial) { // "squeeze" box before division
670  boundingBox.reset();
671  for (int i = firstParticle; i <= lastParticle; ++i)
672  boundingBox.grow(part[i].position);
673  }
674 
675  len=boundingBox.greater_corner.x-boundingBox.lesser_corner.x;
676  dim=0;
677  CkAssert(len>=0.0);
678  len2=boundingBox.greater_corner.y-boundingBox.lesser_corner.y;
679  CkAssert(len2>=0.0);
680  if(len2>len) { len = len2; dim=1; }
681  len2=boundingBox.greater_corner.z-boundingBox.lesser_corner.z;
682  CkAssert(len2>=0.0);
683  if(len2>len) { len = len2; dim=2; }
684 
685  //Sort the particles in longest dimension
686  std::sort(&part[firstParticle],&part[lastParticle+1],compFnPtr[dim]);
687 
688  //Middle particle is the splitting point to get 2 children
689 
690  //Compress the bounding box of this node
691  boundingBox.greater_corner[dim] = part[lastParticle].position[dim];
692  boundingBox.lesser_corner[dim] = part[firstParticle].position[dim];
693 
694  if(!spatial) {
695  if((lastParticle-firstParticle+1)%2==0){
696  children[0]->lastParticle = firstParticle + (lastParticle-firstParticle-1)/2;
697  children[1]->firstParticle = firstParticle + (lastParticle-firstParticle+1)/2;
698  children[0]->particleCount = (lastParticle-firstParticle+1)/2;
699  children[1]->particleCount = (lastParticle-firstParticle+1)/2;
700  }
701  else{
703  children[1]->firstParticle = firstParticle + (lastParticle-firstParticle+2)/2;
704  children[0]->particleCount = (lastParticle-firstParticle+2)/2;
705  children[1]->particleCount = (lastParticle-firstParticle)/2;
706  }
707  }
708  else {
709  GravityParticle dummy; // dummy for splitting
710  GravityParticle* divStart = &part[firstParticle];
711  Vector3D<double> divide(0.0,0.0,0.0);
712  divide[dim] = part[firstParticle].position[dim] + 0.5*len;
713  dummy.position = divide;
714  GravityParticle* divEnd
715  = std::upper_bound(&part[firstParticle],&part[lastParticle+1],
716  dummy,compFnPtr[dim]);
717  children[0]->lastParticle = firstParticle + (divEnd - divStart) - 1;
718  children[1]->firstParticle = firstParticle + (divEnd - divStart);
719  children[0]->particleCount = divEnd - divStart;
720  children[1]->particleCount = 1 + (lastParticle-firstParticle)
721  - (divEnd - divStart);
722  CkAssert(children[0]->particleCount > 0);
723  CkAssert(children[1]->particleCount > 0);
724  }
725 
726  children[0]->myType = Internal;
727  children[1]->myType = Internal;
728 
729  //Compress the bounding boxes of both children too
730  children[0]->boundingBox.lesser_corner = boundingBox.lesser_corner;
731  children[0]->boundingBox.greater_corner = boundingBox.greater_corner;
732  children[0]->boundingBox.greater_corner[dim] = part[children[0]->lastParticle].position[dim];
733 
734  children[1]->boundingBox.lesser_corner = boundingBox.lesser_corner;
735  children[1]->boundingBox.lesser_corner[dim] = part[children[1]->firstParticle].position[dim];
736  children[1]->boundingBox.greater_corner = boundingBox.greater_corner;
737 
738  }
739  children[0]->particlePointer = &part[children[0]->firstParticle];
740  children[1]->particlePointer = &part[children[1]->firstParticle];
741 
742  }
743 
744  // implemented in the .cpp
745  GenericTreeNode *clone() const;
746 
752  void getChunks(int num, NodeKey *&ret) {
753  int i = 0;
754  int base = num;
755  while (base > 1) {
756  base >>= 1;
757  i++;
758  }
759  base = 1 << i;
760  // base now contains the greatest power of two less or equal to num
761  int additional = num - base;
762  if (ret==NULL) ret = new NodeKey[num];
763  for (int j=additional, k=additional*2; j<base; ++j, ++k) ret[k] = j + base;
764  base <<= 1;
765  for (int j=0; j<additional*2; ++j) ret[j] = j + base;
766 
767  }
768 
769  int countDepth(int depth) {
770  int count = 1;
771  if (depth != 0) {
772  if (children[0] != NULL) count += children[0]->countDepth(depth-1);
773  if (children[1] != NULL) count += children[1]->countDepth(depth-1);
774  }
775  return count;
776  }
777 
778  // extraSpace is used by the CacheInterface to store a pointer to
779  // the message so it can be freed when we are finished.
780  int packNodes(BinaryTreeNode *buffer, int depth, int extraSpace=0) {
781  //CkPrintf("Entering packNodes: this=%p, buffer=%p, depth=%d\n",this,buffer,depth);
782  //*buffer = *this;
783  memcpy((void *)buffer, (void *)this, sizeof(*this));
784  buffer->parent = NULL;
785  buffer->particlePointer = NULL;
786 #if INTERLIST_VER > 0 && defined CUDA
787  buffer->nodeArrayIndex = -1;
788  buffer->bucketArrayIndex = -1;
789 #endif
790  int used = 1;
791  if (depth != 0) {
792  if (children[0] != NULL) {
793  BinaryTreeNode *nextBuf = (BinaryTreeNode *) (((char*)buffer) + used * ALIGN_DEFAULT(sizeof(BinaryTreeNode)+extraSpace));
794  buffer->children[0] = (BinaryTreeNode*)(((char*)nextBuf) - ((char*)buffer));
795  //CkPrintf("Entering child 0: offset %ld\n",buffer->children[0]);
796  used += children[0]->packNodes(nextBuf, depth-1, extraSpace);
797  } else {
798  //CkPrintf("Excluding child 0\n");
799  buffer->children[0] = NULL;
800  }
801  if (children[1] != NULL) {
802  BinaryTreeNode *nextBuf = (BinaryTreeNode *) (((char*)buffer) + used * ALIGN_DEFAULT(sizeof(BinaryTreeNode)+extraSpace));
803  buffer->children[1] = (BinaryTreeNode*)(((char*)nextBuf) - ((char*)buffer));
804  //CkPrintf("Entering child 1: offset %ld\n",buffer->children[1]);
805  used += children[1]->packNodes(nextBuf, depth-1, extraSpace);
806  } else {
807  //CkPrintf("Excluding child 1\n");
808  buffer->children[1] = NULL;
809  }
810  } else {
811  //CkPrintf("Depth reached\n");
812  buffer->children[0] = buffer->children[1] = NULL;
813  }
814  //CkAssert((long int)buffer->children[0] < 10000);
815  //CkAssert((long int)buffer->children[1] < 10000);
816  //CkPrintf("Returning used = %d\n",used);
817  return used;
818  }
819 
820  void unpackNodes() {
821  if (children[0] != NULL) {
822  //CkAssert((long int)children[0] < 10000);
823  children[0] = (BinaryTreeNode*)(((long int)children[0]) + ((char*)this));
824  children[0]->parent = this;
825  children[0]->unpackNodes();
826  }
827  if (children[1] != NULL) {
828  //CkAssert((long int)children[1] < 10000);
829  children[1] = (BinaryTreeNode*)(((long int)children[1]) + ((char*)this));
830  children[1]->parent = this;
831  children[1]->unpackNodes();
832  }
833  }
834 
835  void pup(PUP::er &p) { pup(p, -1); }
836  void pup(PUP::er &p, int depth);/* {
837  //CkPrintf("Pupper of BinaryTreeNode(%d) called for %s (%d)\n",depth,p.isPacking()?"Packing":p.isUnpacking()?"Unpacking":"Sizing",p.isSizing()?((PUP::sizer*)&p)->size():((PUP::mem*)&p)->size());
838  GenericTreeNode::pup(p);
839  int isNull;
840  for (int i=0; i<2; ++i) {
841  isNull = (children[i]==NULL || depth==0) ? 0 : 1;
842  p | isNull;
843  CkAssert(isNull==0 || isNull==1);
844  if (isNull != 0 && depth != 0) {
845  if (p.isUnpacking()) children[i] = new BinaryTreeNode();
846  children[i]->pup(p, depth-1);
847  if (p.isUnpacking()) children[i]->parent = this;
848  }
849  }
850  }*/
851  };
852 
853 inline
854 NodePool::~NodePool() {
855  while(!pools.empty()) {
856  delete [] pools.front();
857  pools.pop_front();
858  }
859  }
860 
861 inline BinaryTreeNode *
863  if(next >= szPool) { // need new pool block
864  BinaryTreeNode *nodes = new BinaryTreeNode[szPool];
865  next = 0;
866  pools.push_front(nodes);
867  }
868  return &pools.front()[next++];
869  }
870 
871 inline BinaryTreeNode *
872 NodePool::alloc_one(NodeKey k, NodeType type, int first, int nextlast,
873  BinaryTreeNode *p) {
874  BinaryTreeNode *one = alloc_one();
875  return new (one) BinaryTreeNode(k, type, first, nextlast, p);
876  }
877 
879  class OctTreeNode : public GenericTreeNode {
880  protected:
881  public:
883  OctTreeNode* children[8];
884 
886  for (int i = 0; i < 8; i++) {
887  children[i] = 0;
888  }
889  }
890 
891  public:
892  OctTreeNode(NodeKey k, NodeType type, int first, int last, BinaryTreeNode *p) : GenericTreeNode(k, type, first, last, p) {
893  for (int i = 0; i < 8; i++) {
894  children[i] = 0;
895  }
896  }
897 
898  void fullyDelete() {
899  for (int i = 0; i < numChildren(); i++) {
900  if (children[i] != NULL) {
901  children[i]->fullyDelete();
902  delete children[i];
903  }
904  }
905  }
906 
907  virtual unsigned int numChildren() const {
908  return 8;
909  }
910 
911  virtual GenericTreeNode* getChildren(int i) {
912  CkAssert(i>=0 && i<8);
913  return children[i];
914  }
915 
916  virtual void setChildren(int i, GenericTreeNode* node) {
917  CkAssert(i>=0 && i<8);
918  children[i] = (OctTreeNode*)node;
919  }
920 
921  NodeKey getChildKey(int i) {
922  CkAssert(i>=0 && i<8);
923  return (key<<3) + i;
924  }
925 
926  NodeKey getParentKey() {
927  return (key>>3);
928  }
929 
930  int whichChild(NodeKey child) {
931  return (child ^ (key<<3));
932  }
933 
934  int getLevel(NodeKey k) {
935  int i = 0;
936  k >>= 3;
937  while (k!=0) {
938  k >>= 3;
939  ++i;
940  }
941  return i;
942  }
943 
944 #if INTERLIST_VER > 0
945  bool contains(NodeKey node) {
946 
947  return true;
948  }
949 #endif
950 
951  void makeOctChildren(GravityParticle *part, int totalPart, int level,
952  NodePool *pool = NULL) {}
953 
954  void makeOrbChildren(GravityParticle *part, int totalPart, int level, int rootsLevel, bool (*compFnPtr[])(GravityParticle, GravityParticle), bool spatial,
955  NodePool *pool = NULL) {}
956 
958  OctTreeNode *tmp = new OctTreeNode();
959  *tmp = *this;
960  return tmp;
961  }
962 
963  /*
964  int getNumChunks(int num) {
965  int i = 0;
966  while (num > 1) {
967  num >>= 3;
968  i++;
969  }
970  return 1 << (3*i);
971  }
972  */
973 
974  void getChunks(int num, NodeKey *&ret) {
975  return;
976  }
977 
978  void pup(PUP::er &p);
979  void pup(PUP::er &p, int depth);
980  };
981 
987  enum GenericTrees {
988  Binary_Oct,
989  Oct_Oct,
990  Binary_ORB
991  };
992 
995  class compare{ //Defines the comparison operator on the map used in balancer
996  public:
997  compare(){}
998 
999  bool operator()(NodeKey key1, NodeKey key2) const {
1000 
1001  NodeKey tmp = NodeKey(1);
1002  int len1=0, len2=0;
1003  int cnt=1;
1004 
1005  while(tmp<=key1 || tmp<=key2){
1006  tmp<<=1;
1007  cnt++;
1008  if(len1==0 && tmp>key1){
1009  len1=cnt-1;
1010  }
1011  if(len2==0 && tmp>key2){
1012  len2=cnt-1;
1013  }
1014  }
1015 
1016  if(len1==len2){
1017  return key1<key2;
1018  }
1019  else if(len1>len2){
1020  key1>>=(len1-len2);
1021  return key1<key2;
1022  }
1023  else{
1024  key2>>=(len2-len1);
1025  return key1<key2;
1026  }
1027  }
1028  };
1029 
1031  inline void operator|(PUP::er &p, NodeType &nt) {
1032  int nti;
1033  if (p.isUnpacking()) {
1034  p | nti;
1035  nt = (NodeType)nti;
1036  } else {
1037  nti = (int)nt;
1038  p | nti;
1039  }
1040  }
1041 
1043  inline void operator|(PUP::er &p, GenericTrees &gt) {
1044  int gti;
1045  if (p.isUnpacking()) {
1046  p | gti;
1047  gt = (GenericTrees)gti;
1048  } else {
1049  gti = (int)gt;
1050  p | gti;
1051  }
1052  }
1053 
1054 } //close namespace Tree
1055 
1056 #endif //GENERICTREENODE_H
void setChildren(int i, GenericTreeNode *node)
set the specified child of this node to the passed pointer
Definition: GenericTreeNode.h:379
virtual GenericTreeNode * getChildren(int)=0
return the pointers to the specified child of this node
int whichChild(NodeKey child)
return an integer with the number of the child reflecting the key
Definition: GenericTreeNode.h:422
A representation of a multipole expansion.
Definition: MultipoleMoments.h:163
void setType(NodeType t)
set Tree::NodeType of node
Definition: GenericTreeNode.h:168
void getChunks(int num, NodeKey *&ret)
Definition: GenericTreeNode.h:974
unsigned int iParticleTypes
Mask of particle types contatained in this node.
Definition: GenericTreeNode.h:102
int remoteIndex
Definition: GenericTreeNode.h:113
void fullyDelete()
Recursively delete all nodes beneath this node.
Definition: GenericTreeNode.h:898
NodeType getType() const
return Tree::NodeType of node
Definition: GenericTreeNode.h:166
virtual NodeKey getChildKey(int)=0
return the keys for the specified child
unsigned int numChildren() const
return the number of children this node has
Definition: GenericTreeNode.h:370
virtual int whichChild(NodeKey childkey)=0
return an integer with the number of the child reflecting the key
GravityParticle * particlePointer
Pointer to the first particle in this node.
Definition: GenericTreeNode.h:117
double fKeyMax
Maximum smoothing radius of smoothActive particles.
Definition: GenericTreeNode.h:140
void makeOctChildren(GravityParticle *part, int totalPart, int level, NodePool *pool=NULL)
Definition: GenericTreeNode.h:465
bool isCached()
Is this a node in the cache.
Definition: GenericTreeNode.h:196
MultipoleMoments moments
The moments for the gravity computation.
Definition: GenericTreeNode.h:94
unsigned int iType
Bitmask to hold particle type information.
Definition: GravityParticle.h:330
unsigned int particleCount
Total number of particles contained (across all chares)
Definition: GenericTreeNode.h:115
BinaryTreeNode * alloc_one()
give out one node from the pool, allocating a new pool block if needed.
Definition: GenericTreeNode.h:862
void pup(PUP::er &p)
PUP just this node.
Definition: GenericTreeNode.h:835
int getLevel(NodeKey k)
depth of node corresponding to NodeKey
Definition: GenericTreeNode.h:934
int iRank
SMP rank of node owner.
Definition: GenericTreeNode.h:142
bool contains(NodeKey node)
Is nodekey contained by this node.
Definition: GenericTreeNode.h:429
virtual void getChunks(int num, NodeKey *&ret)=0
virtual int getLevel(NodeKey k)=0
depth of node corresponding to NodeKey
int startBucket
index of first bucket in this node
Definition: GenericTreeNode.h:128
void calculateRadiusBox(MultipoleMoments &m, const OrientedBox< double > &box)
Definition: MultipoleMoments.h:470
virtual NodeKey getParentKey()=0
return the key for the parent
void clear()
Reset this expansion to nothing.
Definition: MultipoleMoments.h:396
NodeKey getKey() const
return unique Tree::NodeKey
Definition: GenericTreeNode.h:171
double sizeSm
Radius of bounding sphere of smoothActive particles.
Definition: GenericTreeNode.h:138
NodeKey getParentKey()
return the key for the parent
Definition: GenericTreeNode.h:389
virtual NodeKey getLongestCommonPrefix(NodeKey k1, NodeKey k2)
return the NodeKey of the lowest common ancestor.
Definition: GenericTreeNode.h:268
GenericTreeNode * parent
The parent of this node, or null if none.
Definition: GenericTreeNode.h:96
virtual GenericTreeNode * clone() const =0
make a copy of the node
Base class for tree nodes.
Definition: GenericTreeNode.h:59
bool isValid()
Is the NodeType valid.
Definition: GenericTreeNode.h:191
virtual unsigned int numChildren() const =0
return the number of children this node has
void fullyDelete()
Recursively delete all nodes beneath this node.
Definition: GenericTreeNode.h:363
NodeKey getChildKey(int i)
return the keys for the specified child
Definition: GenericTreeNode.h:384
void getChunks(int num, NodeKey *&ret)
Get a number of top level NodeKeys which together make a complete tree.
Definition: GenericTreeNode.h:752
virtual void setChildren(int, GenericTreeNode *)=0
set the specified child of this node to the passed pointer
GenericTreeNode * clone() const
make a copy of the node
Definition: GenericTreeNode.cpp:6
int lastParticle
An index to the last particle contained by this node, myNumParticles+1 means outside the node...
Definition: GenericTreeNode.h:108
virtual void setChildren(int i, GenericTreeNode *node)
set the specified child of this node to the passed pointer
Definition: GenericTreeNode.h:916
GenericTreeNode * clone() const
make a copy of the node
Definition: GenericTreeNode.h:957
virtual unsigned int numChildren() const
return the number of children this node has
Definition: GenericTreeNode.h:907
int rungs
Definition: GenericTreeNode.h:122
int64_t nSPH
The number of SPH particles this node contains.
Definition: GenericTreeNode.h:104
int firstParticle
An index for the first particle contained by this node, 0 means outside the node. ...
Definition: GenericTreeNode.h:106
OrientedBox< cosmoType > boundingBox
The axis-aligned bounding box of this node.
Definition: GenericTreeNode.h:98
int numBucketsBeneath
Number of buckets in this node.
Definition: GenericTreeNode.h:126
void getGraphViz(std::ostream &out)
print out a visualization of the tree for diagnostics
Definition: ParallelGravity.cpp:4218
NodeKey getParentKey()
return the key for the parent
Definition: GenericTreeNode.h:926
bool contains(NodeKey node)
Is nodekey contained by this node.
Definition: GenericTreeNode.h:945
void calculateRadiusFarthestParticle(MultipoleMoments &m, const ParticleType *begin, const ParticleType *end)
Given the positions that make up a multipole expansion, set the distance to the farthest particle fro...
Definition: MultipoleMoments.h:483
bool isBucket()
Is this a node a bucket.
Definition: GenericTreeNode.h:203
virtual void pup(PUP::er &p)
PUP just this node.
Definition: GenericTreeNode.h:282
void makeOctChildren(GravityParticle *part, int totalPart, int level, NodePool *pool=NULL)
construct the children of the &quot;this&quot; node following the given logical criteria (Oct/Orb) ...
Definition: GenericTreeNode.h:951
Vector3D< double > centerSm
center of smoothActive particles during smooth operation
Definition: GenericTreeNode.h:136
NodeKey getLongestCommonPrefix(NodeKey k1, NodeKey k2)
return the NodeKey of the lowest common ancestor.
Definition: GenericTreeNode.h:403
Class for Oct tree where each node has 8 direct children.
Definition: GenericTreeNode.h:879
GenericTreeNode(NodeKey k, NodeType type, int first, int last, GenericTreeNode *p)
Construct GenericTreeNode.
Definition: GenericTreeNode.h:150
virtual bool contains(NodeKey nodekey)=0
Is nodekey contained by this node.
int TYPETest(const GravityParticle *a, unsigned int b)
Test for a type flag.
Definition: GravityParticle.h:525
Fundamental type for a particle.
Definition: GravityParticle.h:316
NodeKey getChildKey(int i)
return the keys for the specified child
Definition: GenericTreeNode.h:921
virtual GenericTreeNode * getChildren(int i)
return the pointers to the specified child of this node
Definition: GenericTreeNode.h:911
Utility to pool allocations of tree nodes.
Definition: GenericTreeNode.h:324
virtual void makeOctChildren(GravityParticle *part, int totalPart, int level, NodePool *pool=NULL)=0
construct the children of the &quot;this&quot; node following the given logical criteria (Oct/Orb) ...
OrientedBox< double > bndBoxBall
The bounding box including search balls of this node.
Definition: GenericTreeNode.h:100
GenericTreeNode * getChildren(int i)
return the pointers to the specified child of this node
Definition: GenericTreeNode.h:374
void makeEmpty()
initialize an empty node
Definition: GenericTreeNode.h:251
void makeBucket(GravityParticle *part)
transform an internal node into a bucket
Definition: GenericTreeNode.h:219
virtual void pup(PUP::er &p, int depth)=0
PUP node and children down to depth.
int getLevel(NodeKey k)
depth of node corresponding to NodeKey
Definition: GenericTreeNode.h:393
int whichChild(NodeKey child)
return an integer with the number of the child reflecting the key
Definition: GenericTreeNode.h:930
virtual void fullyDelete()=0
Recursively delete all nodes beneath this node.
A TreeNode with two children.
Definition: GenericTreeNode.h:347
int rung
the current rung (greater means faster)
Definition: GravityParticle.h:329
Definition: GenericTreeNode.h:995
void pup(PUP::er &p)
PUP just this node.