GLAMERDOC++
Gravitational Lensing Code Library
qTreeNB.h
1 //
2 // qTreeNB.h
3 // GLAMER
4 //
5 // Created by Ben Metcalf on 11/11/2018.
6 //
7 
8 #ifndef qTreeNB_h
9 #define qTreeNB_h
10 
11 #include "utilities.h"
12 #include "cosmo.h"
13 
14 #ifndef PI
15 #define PI 3.141593
16 #endif
17 
18 #ifndef treeNBdim
19 #define treeNBdim 2 // dimension of boxes in tree
20 #endif
21 
24 #ifndef IndexType_declare
25 #define IndexType_declare
26 typedef unsigned long IndexType;
27 #endif
28 
31 struct QBranchNB{
32  QBranchNB(QBranchNB *parent):prev(parent){
33  static unsigned long n=0;
34  child0 = NULL;
35  child1 = NULL;
36  child2 = NULL;
37  child3 = NULL;
38  brother = NULL;
39  particles = NULL;
40  nparticles = 0;
41  number = n;
42  ++n;
43  };
44 
45  ~QBranchNB(){ };
46 
48  IndexType *particles;
49  std::unique_ptr<IndexType[]> big_particles;
50  IndexType nparticles;
52  IndexType Nbig_particles;
54  PosType maxrsph;
56  PosType center[2];
57  PosType mass;
59  int level;
60  unsigned long number;
62  PosType boundary_p1[2];
64  PosType boundary_p2[2];
65  PosType boxsize2;
66 
67  QBranchNB *child0;
68  QBranchNB *child1;
69  QBranchNB *child2;
70  QBranchNB *child3;
71 
77 
78  /* projected quantities */
80  PosType quad[3];
82  PosType rmax;
84  PosType r2crit_angle;
85  /* force calculation */
86  PosType rcrit_part;
87  //PosType cm[2]; /* projected center of mass */
88 };
89 
97 template<typename PType = double*>
98 struct QTreeNB{
99  QTreeNB(PType *xp,IndexType *particles,IndexType nparticles
100  ,PosType boundary_p1[],PosType boundary_p2[]);
102 
103  const bool isEmpty();
104  const bool atTop();
105  const bool noChild();
106  const bool offEnd();
107  const unsigned long getNbranches();
108  const bool atLeaf(QBranchNB *branch){
109  return (branch->child0 == NULL)*(branch->child1 == NULL)
110  *(branch->child2 == NULL)*(branch->child3 == NULL);
111  }
112 
113 
114  void getCurrent(IndexType *particles,IndexType *nparticles);
115  void moveTop();
116  void moveUp();
117  void moveToChild(int child);
118  bool WalkStep(bool allowDescent);
119 
120  short empty();
121  void attachChildrenToCurrent(QBranchNB *branch0,QBranchNB *branch1
122  ,QBranchNB *branch2,QBranchNB *branch3);
123 
124  QBranchNB *top;
125  QBranchNB *current;
127  PType *xxp;
128 
129 private:
131  unsigned long Nbranches;
132  void _freeQTree(short child);
133 };
134 
135 /************************************************************************
136  * This constructor just creates a root branch. To construct a full tree
137  * an external function must be used. For example, TreeQuad uses QTreeNB
138  ************************************************************************/
139 template<typename PType>
140 QTreeNB<PType>::QTreeNB(PType *xp,IndexType *particles,IndexType nparticles
141  ,PosType boundary_p1[],PosType boundary_p2[]): xxp(xp) {
142 
143  top = new QBranchNB(nullptr);
144 
145  top->boundary_p1[0] = boundary_p1[0];
146  top->boundary_p1[1] = boundary_p1[1];
147  top->boundary_p2[0] = boundary_p2[0];
148  top->boundary_p2[1] = boundary_p2[1];
149 
150  top->boxsize2 = (boundary_p2[0]-boundary_p1[0])*(boundary_p2[0]-boundary_p1[0]);
151 
152  top->nparticles = nparticles;
153  top->level = 0;
154  top->particles = particles;
155 
156  top->center[0] = (boundary_p1[0] + boundary_p2[0])/2;
157  top->center[1] = (boundary_p1[1] + boundary_p2[1])/2;
158 
159  Nbranches = 1;
160  current = top;
161 
162 }
163 
164 
172 template<typename PType>
174 
175 private:
176  QBranchNB *current;
177  QBranchNB *top;
178  size_t nbranches;
179 
180 public:
182  QBiterator(QTreeNB<PType> * tree){current = top = tree->top; nbranches = tree->getNbranches(); }
184  QBiterator(QBranchNB *branch){current = top = branch;}
185 
187  QBranchNB *operator*(){return current;}
188 
189  void movetop(){current = top;}
190 
192  bool operator++(){ return up();}
193 
195  bool operator++(int){ return up();}
196 
197  bool up();
199  bool down(short child);
200  const bool atLeaf(){
201  return (current->child0 == NULL)*(current->child1 == NULL)
202  *(current->child2 == NULL)*(current->child3 == NULL);
203  }
204  bool TreeWalkStep(bool allowDescent);
205 
206  size_t getNbranches(){return nbranches;}
207 };
208 
209 
210 
212 template<typename PType>
214  // void TreeQuad::freeQTreeNB(QTreeNBHndl tree){
215 
216  empty();
217  delete top;
218  --Nbranches;
219 
220  assert(Nbranches ==0);
221  return;
222 }
223 
224 template<typename PType>
225 short QTreeNB<PType>::empty(){
226 
227  if(Nbranches <= 1) return 1;
228  moveTop();
229  _freeQTree(0);
230 
231  assert(Nbranches == 1);
232 
233  return 1;
234 }
235 
236 template<typename PType>
237 void QTreeNB<PType>::_freeQTree(short child){
238  QBranchNB *branch;
239 
240  assert(current);
241  //if(current->particles != current->big_particles
242  // && current->big_particles != NULL) delete[] current->big_particles;
243 
244  if(current->child0 != NULL){
245  moveToChild(0);
246  _freeQTree(0);
247  }
248 
249  if(current->child1 != NULL){
250  moveToChild(1);
251  _freeQTree(1);
252  }
253 
254  if(current->child2 != NULL){
255  moveToChild(2);
256  _freeQTree(2);
257  }
258 
259  if(current->child3 != NULL){
260  moveToChild(3);
261  _freeQTree(3);
262  }
263 
264  if( atLeaf(current) ){
265 
266  if(atTop()) return;
267 
268  branch = current;
269  moveUp();
270  delete branch;
271  --Nbranches;
272 
273  /*printf("*** removing branch %i number of branches %i\n",branch->number
274  ,Nbranches-1);*/
275 
276  if(child==0) current->child0 = NULL;
277  if(child==1) current->child1 = NULL;
278  if(child==2) current->child2 = NULL;
279  if(child==3) current->child3 = NULL;
280 
281 
282  return;
283  }
284 
285  return;
286 }
287 
288 /************************************************************************
289  * isEmpty
290  * Returns "true" if the QTreeNB is empty and "false" otherwise. Exported.
291  ************************************************************************/
292 template<typename PType>
293 const bool QTreeNB<PType>::isEmpty(){
294 
295  return(Nbranches == 0);
296 }
297 
298 /************************************************************************
299  * atTop
300  * Returns "true" if current is the same as top and "false" otherwise.
301  * Exported.
302  * Pre: !isEmptyNB(tree)
303  ************************************************************************/
304 template<typename PType>
305 const bool QTreeNB<PType>::atTop(){
306 
307  if( isEmpty() ){
308  ERROR_MESSAGE();
309  std::cerr << "QTreeNB Error: calling atTop() on empty tree" << std::endl;
310  exit(1);
311  }
312  return(current == top);
313 }
314 
315 /************************************************************************
316  * offEndNB
317  * Returns "true" if current is off end and "false" otherwise. Exported.
318  ************************************************************************/
319 template<typename PType>
320 const bool QTreeNB<PType>::offEnd(){
321 
322  return(current == NULL);
323 }
324 
325 /************************************************************************
326  * getCurrentNB
327  * Returns the particles of current. Exported.
328  * Pre: !offEnd()
329  ************************************************************************/
330 template<typename PType>
331 void QTreeNB<PType>::getCurrent(IndexType *particles,IndexType *nparticles){
332 
333  if( offEnd() ){
334  ERROR_MESSAGE();
335  std::cerr << "QTreeNB Error: calling getCurrent() when current is off end" << std::endl;
336  exit(1);
337  }
338 
339  *nparticles = current->nparticles;
340  particles = current->particles;
341 
342  return;
343 }
344 
345 /************************************************************************
346  * getNbranches
347  * Returns the NbranchNBes of tree. Exported.
348  ************************************************************************/
349 template<typename PType>
350 const unsigned long QTreeNB<PType>::getNbranches(){
351 
352  return(Nbranches);
353 }
354 
355 /***** Manipulation procedures *****/
356 
357 /************************************************************************
358  * moveTop
359  * Moves current to the front of tree. Exported.
360  * Pre: !isEmpty(tree)
361  ************************************************************************/
362 template<typename PType>
364  //std::cout << tree << std::endl;
365  //std::cout << tree->current << std::endl;
366  //std::cout << tree->top << std::endl;
367 
368  if( isEmpty() ){
369  ERROR_MESSAGE();
370  std::cerr << "QTreeNB Error: calling moveTop() on empty tree" << std::endl;
371  exit(1);
372  }
373 
374  current = top;
375 
376  return;
377 }
378 
379 /************************************************************************
380  * movePrev
381  * Moves current to the branchNB before it in tree. This can move current
382  * off end. Exported.
383  * Pre: !offEndNB(tree)
384  ************************************************************************/
385 template<typename PType>
387 
388  if( offEnd() ){
389  ERROR_MESSAGE();
390  std::cerr << "QTreeNB Error: call to moveUp() when current is off end" << std::endl;
391  exit(1);
392  }
393  if( current == top ){
394  ERROR_MESSAGE();
395  std::cerr << "QTreeNB Error: call to moveUp() tried to move off the top" << std::endl;
396  exit(1);
397  }
398 
399  current = current->prev; /* can move off end */
400  return;
401 }
402 
403 /************************************************************************
404  * moveToChild
405  * Moves current to child branchNB after it in tree. This can move current off
406  * end. Exported.
407  * Pre: !offEnd(tree)
408  ************************************************************************/
409 template<typename PType>
410 void QTreeNB<PType>::moveToChild(int child){
411 
412  if( offEnd() ){
413  ERROR_MESSAGE(); std::cout << "QTreeNB Error: calling moveChildren() when current is off end" << std::endl;
414  exit(1);
415  }
416  if(child==0){
417  if( current->child0 == NULL ){
418  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child1 when it doesn't exist" << std::endl;
419  exit(1);
420  }
421  current = current->child0;
422  }
423  if(child==1){
424  if( current->child1 == NULL ){
425  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child1 when it doesn't exist" << std::endl;
426  exit(1);
427  }
428  current = current->child1;
429  }
430  if(child==2){
431  if( current->child2 == NULL ){
432  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child2 when it doesn't exist" << std::endl;
433  exit(1);
434  }
435  current = current->child2;
436  }
437  if(child==3){
438  if( current->child3 == NULL ){
439  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child2 when it doesn't exist" << std::endl;
440  exit(1);
441  }
442  current = current->child3;
443  }
444  return;
445 }
446 
447 template<typename PType>
449  ,QBranchNB *branch2,QBranchNB *branch3){
450 
451  Nbranches += 4;
452  current->child0 = branch0;
453  current->child1 = branch1;
454  current->child2 = branch2;
455  current->child3 = branch3;
456 
457  int level = current->level+1;
458  branch0->level = level;
459  branch1->level = level;
460  branch2->level = level;
461  branch3->level = level;
462 
463  // work out brothers for children
464  branch0->brother = branch1;
465  branch1->brother = branch2;
466  branch2->brother = branch3;
467  branch3->brother = current->brother;
468 
469  branch0->prev = current;
470  branch1->prev = current;
471  branch2->prev = current;
472  branch3->prev = current;
473 
474  return;
475 }
476 
477 // step for walking tree by iteration instead of recursion
478 template<typename PType>
479 bool QTreeNB<PType>::WalkStep(bool allowDescent){
480  if(allowDescent && current->child0 != NULL){
481  moveToChild(0);
482  return true;
483  }
484 
485  if(current->brother != NULL){
486  current=current->brother;
487  return true;
488  }
489  return false;
490 }
491 
492 template<typename PType>
493 bool QBiterator<PType>::up(){
494  if( current == top ){
495  return false;
496  }
497  current = current->prev; /* can move off end */
498  return true;
499 }
500 
502 template<typename PType>
503 bool QBiterator<PType>::down(short child){
504 
505  if(child==0){
506  if( current->child0 == NULL ){
507  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child1 when it doesn't exist" << std::endl;
508  return false;
509  }
510  current = current->child0;
511  return true;
512  }
513  if(child==1){
514  if( current->child1 == NULL ){
515  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child1 when it doesn't exist" << std::endl;
516  return false;
517  }
518  current = current->child1;
519  return true;
520  }
521  if(child==2){
522  if( current->child2 == NULL ){
523  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child2 when it doesn't exist" << std::endl;
524  return false;
525  }
526  current = current->child2;
527  return true;
528  }
529  if(child==3){
530  if( current->child3 == NULL ){
531  ERROR_MESSAGE(); std::cout << "QTreeNB Error: moveToChild() typing to move to child2 when it doesn't exist" << std::endl;
532  return false;
533  }
534  current = current->child3;
535  return true;
536  }
537  return true;
538 }
539 
540 template<typename PType>
541 bool QBiterator<PType>::TreeWalkStep(bool allowDescent){
542  if(allowDescent && current->child0 != NULL){
543  down(0);
544  return true;
545  }
546 
547  if(current->brother != NULL){
548  current=current->brother;
549  return true;
550  }
551  return false;
552 }
553 
554 #endif /* qTreeNB_h */
QBranchNB::level
int level
level in tree
Definition: qTreeNB.h:59
QTreeNB::xxp
PType * xxp
Array of particle positions.
Definition: qTreeNB.h:127
QBranchNB::Nbig_particles
IndexType Nbig_particles
the number of particles that aren't in children
Definition: qTreeNB.h:52
QBranchNB::brother
QBranchNB * brother
Definition: qTreeNB.h:76
QBiterator::down
bool down(short child)
Move to child.
Definition: qTreeNB.h:503
QBranchNB::maxrsph
PosType maxrsph
Size of largest particle in branch.
Definition: qTreeNB.h:54
QBiterator::operator*
QBranchNB * operator*()
Returns a pointer to the current Branch.
Definition: qTreeNB.h:187
QBiterator::operator++
bool operator++(int)
Same as up()
Definition: qTreeNB.h:195
QBranchNB::rmax
PosType rmax
largest dimension of box
Definition: qTreeNB.h:82
QBiterator::operator++
bool operator++()
Same as up()
Definition: qTreeNB.h:192
QBiterator
A iterator class fore TreeStruct that allows for movement through the tree without changing anything ...
Definition: qTreeNB.h:173
QBranchNB::particles
IndexType * particles
array of particles in QBranchNB
Definition: qTreeNB.h:45
QBranchNB::boundary_p1
PosType boundary_p1[2]
bottom, left, back corner of box
Definition: qTreeNB.h:62
QBranchNB::r2crit_angle
PosType r2crit_angle
the critical distance below which a branch is opened in the
Definition: qTreeNB.h:84
QTreeNB::~QTreeNB
~QTreeNB()
Free treeNB. Does not free the particle positions, masses or sizes.
Definition: qTreeNB.h:213
QBranchNB::quad
PosType quad[3]
quadropole moment of branch
Definition: qTreeNB.h:80
QBranchNB
Box representing a branch in a tree. It has four children. Used in QTreeNB which is used in TreeQuad.
Definition: qTreeNB.h:31
QBiterator::QBiterator
QBiterator(QBranchNB *branch)
Sets the root to the input branch so that this will be a subtree in branch is not the real root.
Definition: qTreeNB.h:184
QBranchNB::center
PosType center[2]
center of mass
Definition: qTreeNB.h:56
QBiterator::QBiterator
QBiterator(QTreeNB< PType > *tree)
Sets the top or root to the top of "tree".
Definition: qTreeNB.h:182
QBranchNB::boundary_p2
PosType boundary_p2[2]
top, right, front corner of box
Definition: qTreeNB.h:64
QBranchNB::prev
QBranchNB * prev
father of branch
Definition: qTreeNB.h:73
QTreeNB
QTreeNB: Tree structure used for force calculation with particles (i.e. stars, Nbody or halos).
Definition: qTreeNB.h:98