source: XIOS/dev/branch_yushan_merged/extern/remap/src/node.cpp @ 1172

Last change on this file since 1172 was 1172, checked in by yushan, 7 years ago

save dev. need to unify the file type when using EP

File size: 19.3 KB
Line 
1#include "mpi.hpp"
2#include <cstdlib>
3#include <cmath>
4#include <iostream>
5#include <cassert>
6#include "tree.hpp"
7#include "elt.hpp"
8#include "intersect.hpp"
9#include <vector>
10#include <set>
11#include <algorithm>
12
13#include "node.hpp"
14
15namespace sphereRemap {
16
17
18#define UPDATE_EVERY 1
19
20using namespace std;
21
22//#ifdef DEBUG
23//std::map<void*, struct mem_info> _mem_deb; // reference counter
24//
25//void NodePtr::unlink()
26//{
27//      _mem_deb[ptr].ref_cnt -= 1;
28//      if (_mem_deb[ptr].ref_cnt == 0) // we were last reference
29//      {
30//              if (_mem_deb[ptr].stat == DELETED) // delete has already been called, everything is fine, free memory now
31//              {
32//                      _mem_deb.erase(ptr);
33//                      ::delete [] ((char *) ptr);
34//              }
35//              else // no more pointer, but memory not freed -> memory leak !!
36//              {
37//                      std::cerr << "WARNING: Memory leak created at address " << ptr << ".";
38//                      assert(_mem_deb[ptr].stat == ALLOCATED); // and not BORROWED
39//#ifdef AUTO_LEAK_FIX
40//                      // free automatically, just for fun
41//                      _mem_deb.erase(ptr);
42//                      ptr->~Node(); // call destructor, since `Node::delete` has not been applied it has not been called
43//                      ::delete [] ((char *) ptr);
44//                      std::cerr << " LEAK FIXED.";
45//#endif
46//
47//                      std::cerr << std::endl;
48//              }
49//      }
50//}
51//
52//void memory_report()
53//{
54//      for (std::map<void*, struct mem_info>::iterator it = _mem_deb.begin(); it != _mem_deb.end(); it++)
55//      {
56//              if (it->second.stat == BORROWED) continue;
57//              std::cerr << "Node at " << it->first << " has " << it->second.ref_cnt << " references to it and "
58//                        << ((it->second.stat == DELETED) ? "has" : "has *not*") << " been deleted." << std::endl;
59//#ifdef AUTO_LEAK_FIX
60//              if (it->second.stat == ALLOCATED) // `Node::delete` has not been called
61//                      ((Node *) it->first)->~Node();
62//              delete [] ((char *)  it->first);
63//#endif
64//      }
65//}
66//
67//int ref_cnt(void *ptr)
68//{
69//      return _mem_deb[ptr].ref_cnt;
70//}
71//#endif
72
73int compareDist(NodePtr n1, NodePtr n2)
74{
75        return squaredist(n1->tree->ref->centre, n1->centre)
76             < squaredist(n2->tree->ref->centre, n2->centre);
77}
78
79/* On level `level` find the node in our subtree that is closest to `src` and return through argument `closest`.
80   The return value is just for recursive calling */
81void Node::findClosest(int level, NodePtr src, double& minDist2, NodePtr &closest)
82{
83        double r2;
84
85        r2 = squaredist(src->centre, this->centre);
86        if (level == this->level)
87        {
88                if (r2 < minDist2 || closest == NULL)
89                {
90                        minDist2 = r2;
91                        closest = this;
92                }
93        }
94        else if (r2 < radius*radius)
95        {
96                for(int i = 0; i < child.size(); i++)
97                        child[i]->findClosest(level, src, minDist2, closest);
98        }
99}
100
101NodePtr Node::farthest(vector<NodePtr >& list)
102{
103        assert(this);
104        double dmax = -HUGE_VAL;
105        NodePtr node = NULL;
106        for (size_t i=0; i < list.size(); i++)
107        {
108                double d = ds(this->centre, list[i]->centre);
109                if (d > dmax) {
110                        node = list[i];
111                        dmax = d;
112                }
113        }
114        return node;
115}
116
117/* returns element in `list` cosest to us (`this`) by meassure `ds`.
118   If `n` is negative finds element furthest away instead. */
119NodePtr Node::closest(vector<NodePtr >& list, int n)
120{
121        assert(this);
122        double dmin2 = (n>0) ? HUGE_VAL : -HUGE_VAL;
123        NodePtr node = NULL;
124        for (int i = 0; i < list.size(); i++)
125        {
126                double d2 = squaredist(this->centre, list[i]->centre);
127                if (n * (d2 - dmin2) < 0)
128                {
129                        node = list[i];
130                        dmin2 = d2;
131                }
132        }
133        return node;
134}
135
136// make sure we will be able to accomodate `node`
137void Node::move(const NodePtr node)   // this->leafCount may be 0
138{
139        double w = double(node->leafCount)/double(node->leafCount + this->leafCount);
140        Coord oldCentre = this->centre;
141        this->centre = proj(this->centre * (1-w) + node->centre * w);
142        this->leafCount += node->leafCount;
143        this->radius += arcdist(oldCentre, this->centre) + 1e-9;
144}
145
146void Node::remove(const NodePtr node)
147{
148        if (&node == NULL) return;
149        double w = double(node->leafCount) / this->leafCount;
150        Coord newCentre = proj(this->centre - node->centre * w);
151        this->leafCount -= node->leafCount;
152        this->radius += arcdist(newCentre, this->centre) + 1e-9;
153        this->centre = newCentre;
154        this->updateCount++;
155}
156
157void Node::inflate(const NodePtr node)
158{
159        double d = arcdist(this->centre, node->centre);
160        double r = node->radius;
161        if (this->radius < d + r)
162                this->radius = d + r + 1e-9;
163}
164
165/* recomputes the radius which currently might be much larger than necessary */
166void Node::update()
167{
168        Coord centre = ORIGIN;
169        int n = 0;
170        for (int i = 0; i < this->child.size(); i++) {
171                centre = centre + this->child[i]->centre * this->child[i]->leafCount;
172                n += this->child[i]->leafCount;
173        }
174        this->centre = proj(centre);
175        this->leafCount = n;
176
177        double R = 0;
178        for (int i = 0; i < this->child.size(); i++)
179        {
180                double d = arcdist(this->centre, this->child[i]->centre);
181                double r = this->child[i]->radius;
182                if (R < d + r) R = d + r;
183        }
184        this->radius = R + 1e-9;
185        this->updateCount = 0;
186        if (child.size())
187                level = child[0]->level + 1;
188}
189
190void Node::output(ostream& flux, int level, int color)
191{
192  if (level==this->level)
193  {
194    flux<<centre.x<<" , "<<centre.y<<" , "<<centre.z<<" , "<<radius<<endl ;
195  }
196  else
197  {
198    for (int i = 0; i < this->child.size(); i++) child[i]->output(flux,level,color) ;
199  }
200}
201
202
203/* void Node::append(NodePtr node);
204{
205        if (node->level == this->level -1)
206        {
207                // new node is one level lower (correct level)
208                this->child.append(node);
209                node->parent = this;
210        }
211        else if (node->level < this->level -1)
212        {
213                // if new node is on even lower level, recursively append to closest child
214                node->closest(this->child)->append(node);
215        }
216        else
217        {
218                cerr << "Error: Attempted node insertion with invalid level." << endl;
219                exit(1);
220        }
221}*/
222
223bool find_in_tree1(Node* node)
224{
225        if (node == node->tree->root) return true;
226        if (node->parent == NULL)
227        {
228                cerr << "Cannot find!" << endl;
229                return false;
230        }
231        return find_in_tree1(node->parent);
232}
233
234bool find_in_tree2(NodePtr node, NodePtr ref)
235{
236        for (int i = 0; i < ref->child.size(); i++)
237        {
238                if (node == ref->child[i])
239                {
240                        cerr << "find2: " << ref << " -> " << ref->child[i] << endl;
241                        return true;
242                }
243                else if (find_in_tree2(node, ref->child[i]))
244                {
245                        cerr << "find2: " << ref << " -> " << ref->child[i] << endl;
246                        return true;
247                }
248        }
249        return false;
250}
251
252
253/* This appends `this` to the node `node` */
254NodePtr insert(NodePtr thIs, NodePtr node)
255{
256  int la = thIs->level; // node to be inserted
257  int lb = node->level; // node where insertation
258  assert(la < lb); // node to be inserted must have lower level then parent
259  //if (thIs->parent) assert(find_in_tree1(thIs) == true);
260  NodePtr q = NULL;
261  NodePtr chd = NULL;
262  node->move(thIs);
263  if (la == lb - 1)
264  {
265    node->child.push_back(thIs);
266    thIs->parent = node;
267    if (node->child.size() > MAX_NODE_SZ &&  node->tree->canSplit() ) // with us as additional child `node` is now too large :(
268    return (node->reinserted || node->parent == NULL) ? split(node) : reinsert(node);
269  }
270  else // la < lb - 1
271  {
272    chd = thIs->closest(node->child);
273    q = insert(thIs, chd);
274  }
275  if ((node->updateCount + 1) % UPDATE_EVERY == 0)
276    node->update();
277  else
278  {
279    if (q) node->remove(q);
280    node->inflate(chd);
281  }
282
283  return q;
284}
285
286typedef NodePtr pNode;
287
288/* move `frac` of our children to a new node which is returned */
289NodePtr reinsert(NodePtr thIs)
290{
291        thIs->tree->ref = thIs;
292        std::sort(thIs->child.begin(), thIs->child.end(), compareDist);
293        int out = (int) (frac*thIs->child.size());
294
295        /* make sure out is only so big that there are still MIN_NODE_SZ children after removing out */
296        if (thIs->child.size() - out < MIN_NODE_SZ) out = thIs->child.size() - MIN_NODE_SZ;
297
298 
299        /* transfere out children from us to a new node q which will be returned */
300        NodePtr q = new Node;
301        q->tree = thIs->tree;
302        q->child.resize(out);
303        for (int i = thIs->child.size() - out; i < thIs->child.size(); i++)
304        {
305                thIs->tree->push_back(thIs->child[i]);
306                int k = i - (thIs->child.size() - out);
307                q->child[k] = thIs->child[i];
308                q->child[k]->parent = q;
309        }
310        thIs->child.resize(thIs->child.size() - out);
311        thIs->update();
312        q->update();
313        thIs->reinserted = true; // avoid infinite loop of reinserting the same node, by marking it as reinserted and stop if same node arrives at same place again
314        thIs->tree->ri = 1;
315
316        return q;
317}
318
319/* move around nodes that are far away from the centre of their parents in order reduce radia of the circles
320   leading to faster look-up times because of less redundancies between nodes.
321   TODO cite paper for Slim SS-tree */
322void slim2(NodePtr thIs, int level, int minNodeSize)
323{
324        bool out;
325        double distChild;
326
327#ifdef DEBUG
328//      assert(ref_cnt(thIs) >= thIs->child.size() + 1 /*parent*/ + 1 /*thIs*/);
329#endif
330        if (thIs->level==level)
331        {
332/*
333                out = false;
334                while (!out)
335                {
336                        // remove child which is farthest away from the centre and try to reinsert it into the tree
337                        double distMax = 0;
338                        int itMax = -1;
339
340                        for (int i = 0; i < thIs->child.size(); i++)
341                        {
342                                distChild = arcdist(thIs->centre, thIs->child[i]->centre) + thIs->child[i]->radius;
343                                if (distChild > distMax)
344                                {
345                                        distMax = distChild;
346                                        itMax = i;
347                                }
348                        }
349                        if (transferNode(thIs->tree->root, thIs, thIs->child[itMax]))
350                        {
351                                thIs->child.erase(thIs->child.begin()+itMax);
352                                out = false;
353                        }
354                        else
355                                out = true;
356
357                        if (thIs->child.size() < minNodeSize) out = true;
358                }
359*/
360    if (thIs->tree-> isActiveOkSplit && thIs->tree->levelSize[thIs->tree->assignLevel] <= thIs->tree->keepNodes)
361    {
362
363      return ;
364    }
365    for (int i = 0; i < thIs->child.size(); i++)
366                {
367      std::vector<NodePtr> before;
368      if (transferNode(thIs->tree->root, thIs, thIs->child[i]))
369      {
370        before=thIs->child ;
371        thIs->child.erase(thIs->child.begin()+i);
372        i--;
373      }
374    }
375       
376
377                if (thIs->child.size() < minNodeSize  && thIs->level < thIs->tree->root->level)
378                {
379                        thIs->tree->decreaseLevelSize(thIs->level);
380                        for(int i = 0; i < thIs->child.size(); i++)
381                                thIs->tree->push_back(thIs->child[i]);
382                        thIs->child.resize(0);
383                }
384                else thIs->update();
385        }
386        else
387        {
388                int newChildCount = 0;
389                for (int i = 0; i < thIs->child.size(); i++)
390                {
391                        if (thIs == thIs->tree->root)
392                        {
393                                // keep at least one child for root
394                                if (i == thIs->child.size()-1 && newChildCount == 0)
395                                {
396                                        thIs->child[newChildCount] = thIs->child[i];
397                                        newChildCount++;
398                                        break;
399                                }
400                        }
401
402                        slim2(thIs->child[i], level);
403                        if (thIs->child[i]->child.size() != 0) // thIs->child[i] is not a leaf
404                        {
405                                thIs->child[newChildCount] = thIs->child[i];
406                                newChildCount++;
407                        } /* else FIXME sometimes this child must be deleted (otherwise leak) sometimes not (otherwise segfault)
408                                        maybe delete not here but when transfered
409                                delete thIs->child[i]; // if our child does not make any grand-children what good is it? -> remove!
410*/
411
412                }
413                thIs->child.resize(newChildCount);
414
415                if (thIs->child.size() < MIN_NODE_SZ && thIs->level < thIs->tree->root->level)
416                {
417                        thIs->tree->decreaseLevelSize(thIs->level);
418                        for (int i = 0; i < thIs->child.size(); i++)
419                                thIs->tree->push_front(thIs->child[i]);
420                        thIs->child.resize(0);
421                }
422                else thIs->update();
423        }
424
425}
426
427bool transferNode(NodePtr thIs, NodePtr parent, NodePtr node)
428{
429  if (parent == thIs) return false;
430
431        if (thIs->level == parent->level)
432        {
433                if ( (thIs->child.size() < MAX_NODE_SZ || thIs->tree->isActiveOkSplit) && thIs->child.size() >= MIN_NODE_SZ)
434                {
435                        insert(node, thIs);
436                        return true;
437                }
438                else
439                        return false;
440        }
441        else
442        {
443                for (int i = 0; i < thIs->child.size(); i++)
444                {
445                        if (arcdist(thIs->child[i]->centre, node->centre) + node->radius < thIs->child[i]->radius)
446                        {
447                                if (transferNode(thIs->child[i], parent, node))
448                                {
449                                        thIs->update();
450                                        return true;
451                                }
452                        }
453                }
454                return false;
455        }
456}
457
458
459
460NodePtr split(NodePtr thIs)
461{
462        thIs->tree->increaseLevelSize(thIs->level);
463        NodePtr p = new Node;
464        NodePtr q = new Node;
465        p->level = q->level = thIs->level;
466        p->reinserted = q->reinserted = false;
467        p->parent = q->parent = thIs->parent;
468        p->tree = q->tree = thIs->tree;
469
470
471        p->child.resize(MAX_NODE_SZ/2);
472        q->child.resize(MAX_NODE_SZ/2 + 1);
473        assert(thIs->child.size() == MAX_NODE_SZ+1);
474        if(thIs->closest(thIs->child, FARTHEST) == 0) 
475          thIs->tree->ref = thIs->closest(thIs->child, FARTHEST); // farthest from centre
476         
477        thIs->tree->ref = thIs->closest(thIs->child, FARTHEST); // farthest from centre
478       
479         
480        std::sort(thIs->child.begin(), thIs->child.end(), compareDist);
481        for (int i = 0; i < MAX_NODE_SZ+1; i++)
482                assert(thIs->child[i]->parent == thIs);
483        for (int i = 0; i < MAX_NODE_SZ/2 + 1; i++)
484                q->child[i] = thIs->child[i];
485        for (int i = MAX_NODE_SZ/2+1; i<MAX_NODE_SZ+1; i++)
486                p->child[i-MAX_NODE_SZ/2-1] = thIs->child[i];
487        for (int i = 0; i < MAX_NODE_SZ/2 + 1; i++)
488                q->child[i]->parent = q;
489        for (int i = MAX_NODE_SZ/2+1; i < MAX_NODE_SZ+1; i++)
490                p->child[i-MAX_NODE_SZ/2-1]->parent = p;
491        p->update();
492        q->update();
493   
494        if (squaredist(thIs->centre, q->centre) < squaredist(thIs->centre, p->centre))
495                swap(p, q);
496
497        thIs->child = p->child; // now our children do not know we are their parents and believe p is their parent
498        for (int i = 0; i < thIs->child.size(); i++)
499                thIs->child[i]->parent = thIs;
500        thIs->reinserted = p->reinserted;
501        thIs->update();
502        delete p;
503
504        if (thIs == thIs->tree->root) // root split
505        {
506                // since we currently are root, make new root and make us and q its children
507                thIs->tree->newRoot(thIs->level + 1);
508                thIs->tree->root->child.push_back(thIs);  thIs->parent = thIs->tree->root;
509                thIs->tree->root->child.push_back(q);     q->parent    = thIs->tree->root;
510                thIs->tree->root->update();
511        }
512        else
513        {
514                thIs->tree->push_front(q);
515        }  // push_front?
516
517        return q;
518}
519
520/* Assuming we are a leaf push all leafs into our list of intersectors
521   that are descendant of node and whoes circle intersects ours.
522*/
523void Node::search(NodePtr node)
524{
525        assert(this->level == 0);
526        int Nchild = node->child.size();
527        if (this->intersects(node)) {
528                if (node->level == 0)
529                        this->intersectors.push_back(node);
530                else
531                        for (int i=0; i<Nchild; i++)
532                                search(node->child[i]);
533        }
534}
535
536/* FIXME this should not be in node.cpp and getNeighbours should not be part of the SS-tree
537   this is mapper specific */
538void findNeighbour(NodePtr thIs, NodePtr node, set<NodePtr >& neighbourList)
539{
540        if (thIs->level==0)
541        {
542                Elt* elt1= (Elt*)(thIs->data);
543                Elt* elt2= (Elt*)(node->data);
544                if (isNeighbour(*elt1, *elt2)) neighbourList.insert(thIs);
545        }
546        else
547        {
548                for(int i=0; i<thIs->child.size(); i++)
549                        if (thIs->child[i]->intersects(node)) findNeighbour(thIs->child[i], node, neighbourList);
550        }
551}
552
553bool Node::intersects(NodePtr node)
554{
555        double d = arcdist(this->centre, node->centre);
556        double r = this->radius;
557        double R = node->radius;
558        return (d < r + R + 1e-9) ? true : false;
559}
560
561bool Node::centreInside(Node &node)
562{
563        double d = arcdist(this->centre, node.centre);
564        double R = node.radius;
565        return (d < R + 1e-9) ? true : false;
566}
567
568bool Node::isInside(Node &node)
569{
570        double d = arcdist(this->centre, node.centre);
571        double r = this->radius;
572        double R = node.radius;
573        return (d + r < R + 1e-9) ? true : false;
574}
575
576int Node::incluCheck()
577{
578        if (this->level == 0) return 0;
579        int nOutside = 0;
580        int n = this->child.size();  // cout << "n = " << n << endl;
581        for (int i=0; i<n; i++)
582        {
583                if (!this->child[i]->isInside(*this))
584                {
585                        cout << "Node of level " << this->level << " does not contain its "
586                                << i << "th child\n";
587                        nOutside++;
588                }
589                nOutside += this->child[i]->incluCheck();
590        }
591        return nOutside;
592}
593
594void Node::checkParent(void)
595{
596  int childSize = child.size() ;
597 
598  for (int i = 0; i < childSize; i++)
599                assert(child[i]->parent == this);
600
601  if (level>0) for (int i = 0; i < childSize; i++) child[i]->checkParent() ;
602}
603 
604void Node::printChildren()
605{
606        cout << "level " << this->level << ", centre ";
607        cout << "level " << this->level << ", centre " << this->centre << "\t r = " << this->radius << endl;
608        cout << this << " p: " << this->parent << endl;
609        int n = this->child.size();
610        for (int i=0; i<n; i++)
611        {
612                NodePtr child = this->child[i];
613                cout << "fils " << i << ": centre " << child->centre << "\t r = " << child->radius << endl;
614                cout << "dist to center " << arcdist(this->centre, child->centre) <<
615                        " d + R = " << arcdist(this->centre,child->centre)+child->radius << endl;
616        }
617}
618
619void Node::assignRoute(std::vector<int>::iterator& rank, int level)
620{
621        if (this->level==level)
622        {
623                route = *rank;
624                rank++;
625        }
626        else
627        {
628                for (int i = 0; i < child.size(); i++)
629                        child[i]->assignRoute(rank, level);
630        }
631}
632
633void Node::assignCircleAndPropagateUp(Coord *centres, double *radia, int level)
634{
635        if (this->level == level)
636        {
637                // assign
638                centre = centres[route];
639                radius = radia[route];
640                free_descendants(); // levels of sample tree beyond `level` will not be used any more
641                child.resize(0);
642                this->level = 0;
643        }
644        else
645        {
646                for (int i = 0; i < child.size(); i++)
647                        child[i]->assignCircleAndPropagateUp(centres, radia, level);
648                update(); // propagate up
649        }
650}
651
652/* Route node `node` within the subtree attached to us.
653 `level` is the level one which to assign
654*/
655// Each sample node has a rank randomly assigned to it, assign `node` from full tree
656void Node::routeNode(NodePtr node, int level)
657{
658        NodePtr closest;
659
660        double distMin2 = 0; // squared distance
661        closest = NULL;
662        if (tree->root == this)
663                findClosest(level, node, distMin2, closest);
664
665        if (closest != NULL && tree->root == this)
666                /* When is this point reached?
667                   if the preceeding findClosest was called and succesed to set closest
668                   findClosest sets closest if we are `level` or src is in our circle (=> belongs to child of ours)
669                   => reached if we are not `level` and node is not child of us
670                */
671                node->route = closest->route;
672        else  /* find closest was not successfull or we were not root */
673        {
674                if (this->level == level)
675                        node->route = this->route;
676                else /* not yet right level => go down one more */
677                        node->closest(this->child)->routeNode(node, level);
678        }
679}
680
681void Node::routeIntersection(vector<int>& routes, NodePtr node)
682{
683        if (level == 0)
684        {
685                routes.push_back(this->route);
686        }
687        else
688        {
689                for (int i = 0; i < child.size(); i++) {
690                        if (child[i]->intersects(node))
691                                child[i]->routeIntersection(routes, node);
692                }
693        }
694}
695
696void Node::routingIntersecting(vector<Node> *routingList, NodePtr node)
697{
698        if (level==0)
699        {
700                int rank = route;
701                routingList[rank].push_back(*node);
702        }
703        else
704        {
705                for (int i = 0; i < child.size(); i++) {
706                        if (child[i]->intersects(node))
707                                child[i]->routingIntersecting(routingList, node);
708                }
709        }
710}
711
712void Node::free_descendants()
713{
714        for (int i = 0; i < child.size(); i++)
715        {
716                child[i]->free_descendants();
717                if (child[i]->level) // do not attempt to delete leafs, they are delete through leafs vector
718                        delete child[i];
719        }
720}
721
722void Node::getNodeLevel(int assignLevel, std::list<NodePtr>& NodeList)
723{
724  if (level==assignLevel) NodeList.push_back(this) ;
725  else if (level>0) for (int i = 0; i < child.size(); i++) child[i]->getNodeLevel(assignLevel,NodeList) ;
726  return ;
727}
728
729bool Node::removeDeletedNodes(int assignLevel)
730{
731  std::vector<NodePtr> newChild ;
732
733  if (level==assignLevel+1)
734  {
735    bool isUpdate=false ;
736    for (int i = 0; i < child.size(); i++)
737    {
738      if (child[i]->toDelete)
739      {
740        isUpdate=true ;
741        for (int j = 0; j < child[i]->child.size(); j++) tree->push_back(child[i]->child[j]) ;
742        tree->decreaseLevelSize(assignLevel) ;
743        delete child[i] ;
744      }
745      else newChild.push_back(child[i]) ;
746    }
747
748    if (isUpdate)
749    {
750      child=newChild ;
751      update() ;
752      return true ;
753    }
754    else return false ;
755  }
756  else
757  {
758    bool isUpdate=false ;
759    for (int i = 0; i < child.size(); i++) isUpdate |= child[i]->removeDeletedNodes(assignLevel) ;
760    if (isUpdate) update() ;
761    return isUpdate ;
762  }
763}
764
765}
Note: See TracBrowser for help on using the repository browser.