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