source: XIOS/dev/branch_openmp/extern/remap/src/node.cpp @ 1328

Last change on this file since 1328 was 1328, checked in by yushan, 6 years ago

dev_omp

File size: 19.1 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        thIs->tree->ref = thIs->closest(thIs->child, FARTHEST); // farthest from centre
475        std::sort(thIs->child.begin(), thIs->child.end(), compareDist);
476        for (int i = 0; i < MAX_NODE_SZ+1; i++)
477                assert(thIs->child[i]->parent == thIs);
478        for (int i = 0; i < MAX_NODE_SZ/2 + 1; i++)
479                q->child[i] = thIs->child[i];
480        for (int i = MAX_NODE_SZ/2+1; i<MAX_NODE_SZ+1; i++)
481                p->child[i-MAX_NODE_SZ/2-1] = thIs->child[i];
482        for (int i = 0; i < MAX_NODE_SZ/2 + 1; i++)
483                q->child[i]->parent = q;
484        for (int i = MAX_NODE_SZ/2+1; i < MAX_NODE_SZ+1; i++)
485                p->child[i-MAX_NODE_SZ/2-1]->parent = p;
486        p->update();
487        q->update();
488   
489        if (squaredist(thIs->centre, q->centre) < squaredist(thIs->centre, p->centre))
490                swap(p, q);
491
492        thIs->child = p->child; // now our children do not know we are their parents and believe p is their parent
493        for (int i = 0; i < thIs->child.size(); i++)
494                thIs->child[i]->parent = thIs;
495        thIs->reinserted = p->reinserted;
496        thIs->update();
497        delete p;
498
499        if (thIs == thIs->tree->root) // root split
500        {
501                // since we currently are root, make new root and make us and q its children
502                thIs->tree->newRoot(thIs->level + 1);
503                thIs->tree->root->child.push_back(thIs);  thIs->parent = thIs->tree->root;
504                thIs->tree->root->child.push_back(q);     q->parent    = thIs->tree->root;
505                thIs->tree->root->update();
506        }
507        else
508        {
509                thIs->tree->push_front(q);
510        }  // push_front?
511
512        return q;
513}
514
515/* Assuming we are a leaf push all leafs into our list of intersectors
516   that are descendant of node and whoes circle intersects ours.
517*/
518void Node::search(NodePtr node)
519{
520        assert(this->level == 0);
521        int Nchild = node->child.size();
522        if (this->intersects(node)) {
523                if (node->level == 0)
524                        this->intersectors.push_back(node);
525                else
526                        for (int i=0; i<Nchild; i++)
527                                search(node->child[i]);
528        }
529}
530
531/* FIXME this should not be in node.cpp and getNeighbours should not be part of the SS-tree
532   this is mapper specific */
533void findNeighbour(NodePtr thIs, NodePtr node, set<NodePtr >& neighbourList)
534{
535        if (thIs->level==0)
536        {
537                Elt* elt1= (Elt*)(thIs->data);
538                Elt* elt2= (Elt*)(node->data);
539                if (isNeighbour(*elt1, *elt2)) neighbourList.insert(thIs);
540        }
541        else
542        {
543                for(int i=0; i<thIs->child.size(); i++)
544                        if (thIs->child[i]->intersects(node)) findNeighbour(thIs->child[i], node, neighbourList);
545        }
546}
547
548bool Node::intersects(NodePtr node)
549{
550        double d = arcdist(this->centre, node->centre);
551        double r = this->radius;
552        double R = node->radius;
553        return (d < r + R + 1e-9) ? true : false;
554}
555
556bool Node::centreInside(Node &node)
557{
558        double d = arcdist(this->centre, node.centre);
559        double R = node.radius;
560        return (d < R + 1e-9) ? true : false;
561}
562
563bool Node::isInside(Node &node)
564{
565        double d = arcdist(this->centre, node.centre);
566        double r = this->radius;
567        double R = node.radius;
568        return (d + r < R + 1e-9) ? true : false;
569}
570
571int Node::incluCheck()
572{
573        if (this->level == 0) return 0;
574        int nOutside = 0;
575        int n = this->child.size();  // cout << "n = " << n << endl;
576        for (int i=0; i<n; i++)
577        {
578                if (!this->child[i]->isInside(*this))
579                {
580                        cout << "Node of level " << this->level << " does not contain its "
581                                << i << "th child\n";
582                        nOutside++;
583                }
584                nOutside += this->child[i]->incluCheck();
585        }
586        return nOutside;
587}
588
589void Node::checkParent(void)
590{
591  int childSize = child.size() ;
592 
593  for (int i = 0; i < childSize; i++)
594                assert(child[i]->parent == this);
595
596  if (level>0) for (int i = 0; i < childSize; i++) child[i]->checkParent() ;
597}
598 
599void Node::printChildren()
600{
601        cout << "level " << this->level << ", centre ";
602        cout << "level " << this->level << ", centre " << this->centre << "\t r = " << this->radius << endl;
603        cout << this << " p: " << this->parent << endl;
604        int n = this->child.size();
605        for (int i=0; i<n; i++)
606        {
607                NodePtr child = this->child[i];
608                cout << "fils " << i << ": centre " << child->centre << "\t r = " << child->radius << endl;
609                cout << "dist to center " << arcdist(this->centre, child->centre) <<
610                        " d + R = " << arcdist(this->centre,child->centre)+child->radius << endl;
611        }
612}
613
614void Node::assignRoute(std::vector<int>::iterator& rank, int level)
615{
616        if (this->level==level)
617        {
618                route = *rank;
619                rank++;
620        }
621        else
622        {
623                for (int i = 0; i < child.size(); i++)
624                        child[i]->assignRoute(rank, level);
625        }
626}
627
628void Node::assignCircleAndPropagateUp(Coord *centres, double *radia, int level)
629{
630        if (this->level == level)
631        {
632                // assign
633                centre = centres[route];
634                radius = radia[route];
635                free_descendants(); // levels of sample tree beyond `level` will not be used any more
636                child.resize(0);
637                this->level = 0;
638        }
639        else
640        {
641                for (int i = 0; i < child.size(); i++)
642                        child[i]->assignCircleAndPropagateUp(centres, radia, level);
643                update(); // propagate up
644        }
645}
646
647/* Route node `node` within the subtree attached to us.
648 `level` is the level one which to assign
649*/
650// Each sample node has a rank randomly assigned to it, assign `node` from full tree
651void Node::routeNode(NodePtr node, int level)
652{
653        NodePtr closest;
654
655        double distMin2 = 0; // squared distance
656        closest = NULL;
657        if (tree->root == this)
658                findClosest(level, node, distMin2, closest);
659
660        if (closest != NULL && tree->root == this)
661                /* When is this point reached?
662                   if the preceeding findClosest was called and succesed to set closest
663                   findClosest sets closest if we are `level` or src is in our circle (=> belongs to child of ours)
664                   => reached if we are not `level` and node is not child of us
665                */
666                node->route = closest->route;
667        else  /* find closest was not successfull or we were not root */
668        {
669                if (this->level == level)
670                        node->route = this->route;
671                else /* not yet right level => go down one more */
672                        node->closest(this->child)->routeNode(node, level);
673        }
674}
675
676void Node::routeIntersection(vector<int>& routes, NodePtr node)
677{
678        if (level == 0)
679        {
680                routes.push_back(this->route);
681        }
682        else
683        {
684                for (int i = 0; i < child.size(); i++) {
685                        if (child[i]->intersects(node))
686                                child[i]->routeIntersection(routes, node);
687                }
688        }
689}
690
691void Node::routingIntersecting(vector<Node> *routingList, NodePtr node)
692{
693        if (level==0)
694        {
695                int rank = route;
696                routingList[rank].push_back(*node);
697        }
698        else
699        {
700                for (int i = 0; i < child.size(); i++) {
701                        if (child[i]->intersects(node))
702                                child[i]->routingIntersecting(routingList, node);
703                }
704        }
705}
706
707void Node::free_descendants()
708{
709        for (int i = 0; i < child.size(); i++)
710        {
711                child[i]->free_descendants();
712                if (child[i]->level) // do not attempt to delete leafs, they are delete through leafs vector
713                        delete child[i];
714        }
715}
716
717void Node::getNodeLevel(int assignLevel, std::list<NodePtr>& NodeList)
718{
719  if (level==assignLevel) NodeList.push_back(this) ;
720  else if (level>0) for (int i = 0; i < child.size(); i++) child[i]->getNodeLevel(assignLevel,NodeList) ;
721  return ;
722}
723
724bool Node::removeDeletedNodes(int assignLevel)
725{
726  std::vector<NodePtr> newChild ;
727
728  if (level==assignLevel+1)
729  {
730    bool isUpdate=false ;
731    for (int i = 0; i < child.size(); i++)
732    {
733      if (child[i]->toDelete)
734      {
735        isUpdate=true ;
736        for (int j = 0; j < child[i]->child.size(); j++) tree->push_back(child[i]->child[j]) ;
737        tree->decreaseLevelSize(assignLevel) ;
738        delete child[i] ;
739      }
740      else newChild.push_back(child[i]) ;
741    }
742
743    if (isUpdate)
744    {
745      child=newChild ;
746      update() ;
747      return true ;
748    }
749    else return false ;
750  }
751  else
752  {
753    bool isUpdate=false ;
754    for (int i = 0; i < child.size(); i++) isUpdate |= child[i]->removeDeletedNodes(assignLevel) ;
755    if (isUpdate) update() ;
756    return isUpdate ;
757  }
758}
759
760}
Note: See TracBrowser for help on using the repository browser.