GLAMERDOC++
Gravitational Lensing Code Library
simpleTreeVec.h
1 
8 #ifndef SIMP_TREE_V_
9 #define SIMP_TREE_V_
10 
11 #include <memory>
12 #include "standard.h"
13 #include "Tree.h"
14 
21 template <typename T,typename D = PosType>
23 public:
24 
26  T *xpt
27  ,IndexType Npoints
28  ,int bucket = 5
29  ,int dimensions = 2
30  ,bool median = true
31  // ,PosType *(*Mypos)(T&) = defaultposition /// function that takes
32  ,D *(*Mypos)(T&) = [](T& in){return in.x;}
33  ):Nparticles(Npoints),median_cut(median),Nbucket(bucket),realray(dimensions),
34  points(xpt),position(Mypos),Nbranches(0),Ndimensions(dimensions)
35  {
36  index.resize(Nparticles);
37  for(IndexType ii=0;ii<Npoints;++ii) index[ii] = ii;
38 
39  BuildTree();
40  }
41 
42  virtual ~TreeSimpleVec()
43  {
44  //delete top_ptr;
45  //freeTree();
46  //delete[] index;
47  //assert(Nbranches == 0);
48  //return;
49  };
50 
52  void PointsWithinCircle(D center[2],float radius,std::list<unsigned long> &neighborkist);
54  void PointsWithinEllipse(D center[2],float a_max,float a_min,float posangle,std::list<unsigned long> &neighborkist);
56  void NearestNeighbors(D *ray,int Nneighbors,std::vector<D> &radii
57  ,std::vector<IndexType> &neighbors);
58  void NearestNeighbor(D *ray,D &radius,IndexType &neighbor);
59 
61  void pop(IndexType index_of_point){
62 
63  //print();
64 
65  size_t n = 0;
66  while(index[n] != index_of_point && n < Nparticles) ++n;
67  if(n == Nparticles) return; // particle not in tree
68 
69  std::shared_ptr<BranchV> leaf;
70 
71  //bool leaf_found = false;
72  moveTop();
73  do{
74  long p = current->branch_index - index.data();
75  if(atLeaf() && n >= p && n < p + current->nparticles ){
76  leaf=current;
77  }
78  if(p > n){
79  current->branch_index -= 1;
80  }
81  }while(TreeWalkStep(true));
82 
83  assert(leaf->child1_ptr==nullptr);
84  assert(leaf->child2_ptr==nullptr);
85 
86  //BranchV *tmp = leaf;
87  while(leaf != top_ptr){
88  if(leaf->nparticles > 0) leaf->nparticles -= 1;
89  leaf = leaf->prev_ptr;
90  }
91  leaf->nparticles -= 1;
92 
93  // remove from index
94  for(size_t i = n ; i < Nparticles - 1 ; ++i){
95  index[i] = index[i+1];
96  }
97  --Nparticles;
98  index.pop_back();
99 
100  //print();
101 
102  }
103 
105  std::vector<IndexType> get_index() const{
106  return index;
107  }
108 
109  void print(){
110  moveTop();
111  do{
112  for(int i=0 ; i<current->level ; ++i ) std::cout << " ";
113  std::cout << current->level << " " << current->nparticles << " : ";
114  for(int i=0 ; i<current->nparticles ; ++i){
115  std::cout << *(current->branch_index+i) << " " ;
116  }
117  std::cout << std::endl;
118  }while(TreeWalkStep(true));
119  std::cout << std::endl;
120  }
121 
125  struct BranchV{
126 
127  int Ndim;
129  IndexType *branch_index;
130  IndexType nparticles;
132  int level;
133  unsigned long number;
135  D *boundary_p1 = nullptr;
137  D *boundary_p2 = nullptr;
138  std::vector<D> bank;
139 
140  std::shared_ptr<BranchV> child1_ptr;
141  std::shared_ptr<BranchV> child2_ptr;
143  std::shared_ptr<BranchV> prev_ptr;
146  std::shared_ptr<BranchV> brother_ptr;
147 
148 
149  BranchV(int my_Ndim,IndexType *my_branch_index,IndexType my_nparticles
150  ,D my_boundary_p1[],D my_boundary_p2[]
151  ,int my_level,unsigned long my_BranchVnumber)
152  :Ndim(my_Ndim),branch_index(my_branch_index),nparticles(my_nparticles)
153  ,level(my_level),number(my_BranchVnumber)
154  {
155 
156  bank.resize(Ndim*2);
157  boundary_p1 = bank.data();
158  boundary_p2 = bank.data() + Ndim;
159 
160  for(size_t i=0;i<Ndim;++i){
161  boundary_p1[i]= my_boundary_p1[i];
162  boundary_p2[i]= my_boundary_p2[i];
163  }
164 
165  child1_ptr = nullptr;
166  child2_ptr = nullptr;
167  prev_ptr = nullptr;
168  brother_ptr = nullptr;
169  };
170  BranchV(BranchV &branch){
171 
172  Ndim = branch.Ndim;
173  branch_index = branch.branch_index;
174  nparticles = branch.nparticles;
175  level = branch.level;
176  number = branch.number;
177 
178  bank.resize(Ndim*2);
179  boundary_p1 = bank.data();
180  boundary_p2 = bank.data() + Ndim;
181 
182  for(size_t i=0;i<Ndim;++i){
183  boundary_p1[i]= branch.boundary_p1[i];
184  boundary_p2[i]= branch.boundary_p2[i];
185  }
186 
187  child1_ptr = nullptr;
188  child2_ptr = nullptr;
189  prev_ptr = nullptr;
190  brother_ptr = nullptr;
191  };
192 
193  ~BranchV(){
194  //delete child1_ptr;
195  //delete child2_ptr;
196  };
197  };
198 
199 protected:
200 
201  int incell,incell2;
202  std::vector<IndexType> index;
203  IndexType Nparticles;
204  bool median_cut;
205  int Nbucket;
206  Point_nd<D> realray;
207  T *points;
208  D *(*position)(T&);
209 
210  std::vector<D> workspace;
211 
212  std::shared_ptr<BranchV> top_ptr;
213  std::shared_ptr<BranchV> current;
215  unsigned long Nbranches;
217  short Ndimensions;
218 
219  void BuildTree();
220 
221  void _BuildTree(IndexType nparticles,IndexType *tmp_index);
222 
223  void _PointsWithin(D *ray,float *rmax,std::list<unsigned long> &neighborkist);
224  void _NearestNeighbors(D *ray,int Nneighbors,unsigned long *neighbors,D *rneighbors);
225 
226  void freeTree();
227 
228  //short clearTree();
229  //void _freeTree(short child);
230  bool isEmpty();
231  bool atTop();
232  bool noChild();
233  bool offEnd();
234  void getCurrent(IndexType *branch_index,IndexType *nparticles);
235  unsigned long getNbranches();
236  void moveTop();
237  void moveUp();
238  void moveToChild(int child);
239  void attachChildToCurrent(IndexType *branch_index,IndexType nparticles
240  ,D boundary_p1[],D boundary_p2[]
241  ,int child);
242  void attachChildToCurrent(BranchV &data,int child);
243  bool TreeWalkStep(bool allowDescent);
244 
245  inline bool atLeaf(){
246  return (current->child1_ptr == nullptr)*(current->child2_ptr == nullptr);
247  }
248  inline bool inbox(const D* center,D *p1,D *p2){
249  int tt=1;
250  for(int i=0;i<Ndimensions;++i) tt *= (center[i]>=p1[i]);
251 
252  return tt;
253  // return (center[0]>=p1[0])*(center[0]<=p2[0])*(center[1]>=p1[1])*(center[1]<=p2[1]);
254  }
255 
256 
257  int cutbox(const D *center,D *p1,D *p2,float rmax);
258 };
259 /*
260 template <class T>
261 TreeSimpleVec<T>::TreeSimpleVec<T>(T *xpt,IndexType Npoints,int bucket,int dimensions,bool median){
262  index = new IndexType[Npoints];
263  IndexType ii;
264 
265  Nbucket = bucket;
266  Ndimensions = dimensions;
267  median_cut = median;
268  Nparticles = Npoints;
269 
270  points = xpt;
271 
272  for(ii=0;ii<Npoints;++ii) index[ii] = ii;
273 
274  BuildTree();
275 };*/
276 
277 /************************************************************************
278  * NewBranchV
279  * Returns pointer to new BranchV struct. Initializes children pointers to nullptr,
280  * and sets data field to input. Private.
281  ************************************************************************/
282 
283 
284 
285 template <typename T,typename D>
287  D *ray
288  ,float rmax
289  ,float rmin
290  ,float posangle
291  ,std::list <unsigned long> &neighborlist
292  ){
293  D x,y,cs,sn;
294 
295 
296  if(rmax < rmin){float tmp = rmax; rmax=rmin; rmin=tmp;}
297 
298  if(rmax <=0.0 || rmin <= 0.0){ neighborlist.clear(); return; }
299 
300  // find point within a circle circumscribes the ellipse
301  PointsWithinCircle(ray,rmax,neighborlist);
302 
303  cs = cos(posangle);
304  sn = sin(posangle);
305  // go through points within the circle and reject points outside the ellipse
306  for( std::list<unsigned long>::iterator it = neighborlist.begin();it != neighborlist.end();){
307  x = points[*it][0]*cs - points[*it][1]*sn;
308  y = points[*it][0]*sn + points[*it][1]*cs;
309  if( ( pow(x/rmax,2) + pow(y/rmin,2) ) > 1) it = neighborlist.erase(it);
310  else ++it;
311  }
312  return;
313 }
314 
315 template <typename T,typename D>
317  D *ray
318  ,float rmax
319  ,std::list <unsigned long> &neighborlist
320  ){
321 
322  neighborlist.clear();
323 
324  //realray[0]=ray[0];
325  //realray[1]=ray[1];
326  for(int j=0 ; j<Ndimensions ; ++j) realray[j]=ray[j];
327 
328  //cout << "ray = " << ray[0] << " " << ray[1] << " rmax = " << rmax << endl;
329  moveTop();
330  if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
331 
332  for(int i=0 ; i<Ndimensions ; ++i){
333  ray[i] = (ray[i] > current->boundary_p1[i]) ? ray[i] : current->boundary_p1[i];
334  ray[i] = (ray[i] < current->boundary_p2[i]) ? ray[i] : current->boundary_p2[i];
335  }
336 
337  }
338  incell=1;
339 
340  _PointsWithin(ray,&rmax,neighborlist);
341 
342  //for(auto i : neighborlist){
343  // assert( rmax*rmax > (position(points[i])[0]-ray[0])*(position(points[i])[0]-ray[0]) + (position(points[i])[1]-ray[1])*(position(points[i])[1]-ray[1]) );
344  //}
345  return;
346 }
349 template <typename T,typename D>
350 void TreeSimpleVec<T,D>::_PointsWithin(D *ray,float *rmax,std::list <unsigned long> &neighborlist){
351 
352  int j,incell2=1;
353  unsigned long i;
354  D radius;
355  short pass;
356 
357  if(incell){ // not found cell yet
358 
359  if( inbox(ray,current->boundary_p1,current->boundary_p2) ){
360  //cout << " In box" << endl;
361 
362  // found the box small enough
363  //if( cutbox(ray,current->boundary_p1,current->boundary_p2,*rmax)==1
364  // || atLeaf() ){
365  if( atLeaf() ){
366  //cout << " Found cell" << endl;
367 
368  // whole box in circle or a leaf with ray in it
369 
370  incell=0;
371 
372  //ray[0]=realray[0];
373  //ray[1]=realray[1];
374  for(int j=0;j<Ndimensions;++j) ray[j]=realray[j];
375  if( atLeaf() ){
376  // if leaf calculate the distance to all the points in cell
377  for(i=0;i<current->nparticles;++i){
378  for(j=0,radius=0.0;j<2;++j) radius+=pow(position(points[current->branch_index[i]])[j]-ray[j],2);
379  if( radius < *rmax**rmax ){
380  neighborlist.push_back(current->branch_index[i]);
381  //cout << "add point to list" << neighborlist.size() << endl;
382  //InsertAfterCurrentKist(neighborlist,current->branch_index[i]);
383  }
384  }
385  }else{ // put all of points in box into getCurrentKist(imagelist)
386  for(i=0;i<current->nparticles;++i){
387  neighborlist.push_back(current->branch_index[i]);
388  //InsertAfterCurrentKist(neighborlist,current->branch_index[i]);
389  //cout << "add point to list" << neighborlist.size() << endl;
390 
391  }
392  }
393 
394  }else{ // keep going down the tree
395 
396  if(current->child1_ptr != nullptr){
397  moveToChild(1);
398  _PointsWithin(ray,rmax,neighborlist);
399  moveUp();
400 
401  incell2=incell;
402  }
403 
404  if(current->child2_ptr != nullptr){
405  moveToChild(2);
406  _PointsWithin(ray,rmax,neighborlist);
407  moveUp();
408  }
409 
410  // if ray found in second child go back to first to search for neighbors
411  if( (incell2==1) && (incell==0) ){
412  if(current->child1_ptr != nullptr){
413  moveToChild(1);
414  _PointsWithin(ray,rmax,neighborlist);
415  moveUp();
416  }
417  }
418  }
419  } // not in the box
420 
421  }else{ // found cell
422 
423  pass = cutbox(ray,current->boundary_p1,current->boundary_p2,*rmax);
424  // does radius cut into the box
425  if( pass ){
426  //cout << " Cell found searching other cells" << endl;
427  if( atLeaf() ){ /* leaf case */
428 
429  for(i=0;i<current->nparticles;++i){
430  for(j=0,radius=0.0;j<2;++j) radius+=pow(position(points[current->branch_index[i]])[j]-ray[j],2);
431  if( radius < *rmax**rmax ){
432  neighborlist.push_back(current->branch_index[i]);
433  }
434  }
435  //}else if(pass==1){ // whole box is inside radius
436 
437  // for(i=0;i<current->nparticles;++i){
438  // neighborlist.push_back(current->branch_index[i]); ?????
439  // }
440  }else{
441  if(current->child1_ptr != nullptr){
442  moveToChild(1);
443  _PointsWithin(ray,rmax,neighborlist);
444  moveUp();
445  }
446 
447  if(current->child2_ptr != nullptr){
448  moveToChild(2);
449  _PointsWithin(ray,rmax,neighborlist);
450  moveUp();
451  }
452  }
453 
454  }
455  }
456 
457  return;
458 }
459 
462 template <typename T,typename D>
464  D *ray
465  ,int Nneighbors
466  ,std::vector<D> &radii
467  ,std::vector<IndexType> &neighbors
468  ){
469  IndexType i;
470  short j;
471 
472 
473  if(top_ptr->nparticles <= Nneighbors){
474 
475  std::vector<D> tmp(Nparticles);
476  std::vector<size_t> sort_index(Nparticles);
477  for(int i = 0 ; i< Nparticles ; ++i){
478  tmp[i] = pow(position(points[i])[0]-ray[0],2) + pow(position(points[i])[1]-ray[1],2);
479  sort_index[i]=i;
480  }
481 
482  std::sort(sort_index.begin(),sort_index.end(),[&tmp](size_t i,size_t j){return tmp[i] < tmp[j];});
483 
484  radii.resize(Nparticles);
485  neighbors.resize(Nparticles);
486 
487  for(int i = 0 ; i< Nparticles ; ++i){
488  neighbors[i] = index[sort_index[i]];
489  radii[i] = tmp[sort_index[i]];
490  }
491 
492  return;
493  }
494 
495  radii.resize(Nneighbors+Nbucket);
496  neighbors.resize(Nneighbors+Nbucket);
497 
498 
499  /* initalize distance to neighbors to a large number */
500  for(i=0;i<Nbucket+Nneighbors;++i){
501  radii[i] = (10*(top_ptr->boundary_p2[0]-top_ptr->boundary_p1[0]));
502  neighbors[i] = 0;
503  }
504 
505  for(int j=0;j<Ndimensions;++j) realray[j]=ray[j];
506 
507  moveTop();
508  if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
509  //ERROR_MESSAGE();
510 
511  for(j=0;j<Ndimensions;++j){
512  ray[j] = (ray[j] > current->boundary_p1[j]) ? ray[j] : current->boundary_p1[j];
513  ray[j] = (ray[j] < current->boundary_p2[j]) ? ray[j] : current->boundary_p2[j];
514  }
515  }
516  incell = 1;
517 
518  _NearestNeighbors(ray,Nneighbors,neighbors.data(),radii.data());
519 
520  neighbors.resize(Nneighbors);
521  radii.resize(Nneighbors);
522 
523  return;
524 }
525 
528 template <typename T,typename D>
530  D *ray
531  ,D &radius
532  ,IndexType &neighbor
533  ){
534  IndexType i;
535  //static int count=0,oldNneighbors=-1;
536  //short j;
537 
538  D rneighbors[1+Nbucket];
539  IndexType neighbors[1+Nbucket];
540 
541  if(top_ptr->nparticles < 1){
542  ERROR_MESSAGE();
543  printf("ERROR: in NearestNeighbors, number of neighbors > total number of particles\n");
544  throw std::runtime_error("Asked for too many neighbors");
545  }
546 
547  /* initalize distance to neighbors to a large number */
548  for(i=0;i<Nbucket+1;++i){
549  rneighbors[i] = (10*(top_ptr->boundary_p2[0]-top_ptr->boundary_p1[0]));
550  neighbors[i] = 0;
551  }
552 
553  for(int j=0;j<Ndimensions;++j) realray.x[j]=ray[j];
554 
555  moveTop();
556  if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
557  //ERROR_MESSAGE();
558 
559  for(int j=0;j<Ndimensions;++j){
560  ray[j] = (ray[j] > current->boundary_p1[j]) ? ray[j] : current->boundary_p1[j];
561  ray[j] = (ray[j] < current->boundary_p2[j]) ? ray[j] : current->boundary_p2[j];
562  }
563  }
564  incell = 1;
565 
566  _NearestNeighbors(ray,1,neighbors,rneighbors);
567 
568  neighbor = neighbors[0];
569  radius = rneighbors[0];
570 
571  return;
572 }
573 
574 template <typename T,typename D>
575 void TreeSimpleVec<T,D>::_NearestNeighbors(D *ray,int Nneighbors,unsigned long *neighbors,D *rneighbors){
576 
577  int incellNB2=1;
578  IndexType i;
579  short j;
580 
581  if(incell){ /* not found cell yet */
582 
583  if( inbox(ray,current->boundary_p1,current->boundary_p2) ){
584 
585  /* found the box small enough */
586  if( current->nparticles <= Nneighbors+Nbucket ){
587  incell=0;
588  for(j=0;j<Ndimensions;++j) ray[j]=realray[j];
589 
590  /* calculate the distance to all the particles in cell */
591  for(i=0;i<current->nparticles;++i){
592  for(j=0,rneighbors[i]=0.0;j<Ndimensions;++j){
593  rneighbors[i] += pow(position(points[current->branch_index[i]])[j]-ray[j],2);
594  }
595  rneighbors[i]=sqrt( rneighbors[i] );
596  //assert(rneighbors[i] < 10);
597  neighbors[i]=current->branch_index[i];
598  }
599 
600  Utilities::quicksort(neighbors,rneighbors,current->nparticles);
601 
602  }else{ /* keep going down the tree */
603 
604  if(current->child1_ptr !=nullptr){
605  moveToChild(1);
606  _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
607  /*printf("moving up from level %i\n",current->level);*/
608  moveUp();
609 
610  incellNB2=incell;
611  }
612 
613  if(current->child2_ptr !=nullptr){
614  /*printf("moving to child2 from level %i\n",current->level);*/
615  moveToChild(2);
616  _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
617  /*printf("moving up from level %i\n",current->level);*/
618  moveUp();
619  }
620 
622  if( (incellNB2==1) && (incell==0) ){
623  if(current->child1_ptr !=nullptr){
624  moveToChild(1);
625  _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
626  moveUp();
627  }
628  }
629  }
630  }
631  }else{ // found cell
632  // does radius cut into the box
633  if( cutbox(ray,current->boundary_p1,current->boundary_p2,rneighbors[Nneighbors-1]) ){
634 
635  if( (current->child1_ptr == nullptr)*(current->child2_ptr == nullptr)){ /* leaf case */
636 
637  /* combine found neighbors with particles in box and resort */
638  for(i=Nneighbors;i<(current->nparticles+Nneighbors);++i){
639  for(j=0,rneighbors[i]=0.0;j<Ndimensions;++j){
640  rneighbors[i]+=pow(position(points[current->branch_index[i-Nneighbors]])[j]-ray[j],2);
641  }
642  rneighbors[i]=sqrt( rneighbors[i] );
643  //assert(rneighbors[i] < 10);
644  neighbors[i]=current->branch_index[i-Nneighbors];
645  }
646 
647  Utilities::quicksort(neighbors,rneighbors,Nneighbors+Nbucket);
648 
649  }else{
650 
651  if(current->child1_ptr !=nullptr){
652  moveToChild(1);
653  _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
654  moveUp();
655  }
656 
657  if(current->child2_ptr !=nullptr){
658  moveToChild(2);
659  _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
660  moveUp();
661  }
662  }
663  }
664  }
665  return;
666 }
667 
668 template <typename T,typename D>
670  IndexType i;
671  short j;
672  std::vector<D> p1(Ndimensions),p2(Ndimensions);
673 
674  if(Nparticles > 0){
675  for(j=0;j<Ndimensions;++j){
676  p1[j] = position(points[0])[j];
677  p2[j] = position(points[0])[j];
678  }
679 
680  for(i=0;i<Nparticles;++i){
681  for(j=0;j<Ndimensions;++j){
682  if(position(points[i])[j] < p1[j] ) p1[j] = position(points[i])[j];
683  if(position(points[i])[j] > p2[j] ) p2[j] = position(points[i])[j];
684  }
685  }
686 
687  /* Initialize tree root */
688  top_ptr.reset(new BranchV(Ndimensions,index.data(),Nparticles,p1.data(),p2.data(),0,0));
689  current = top_ptr;
690  ++Nbranches;
691  if (!(top_ptr)){
692  ERROR_MESSAGE(); fprintf(stderr,"allocation failure in NewTree()\n");
693  exit(1);
694  }
695 
696 
697  /* build the tree */
698  workspace.resize(Nparticles);
699  _BuildTree(Nparticles,index.data());
700  workspace.clear();
701  workspace.shrink_to_fit();
702  }else{
703 
704  for(j=0;j<Ndimensions;++j){
705  p1[j] *= 0;
706  p2[j] *= 0;
707  }
708 
709  top_ptr.reset(new BranchV(Ndimensions,index.data(),0,p1.data(),p2.data(),0,0));
710  current = top_ptr;
711  ++Nbranches;
712  if (!(top_ptr)){
713  ERROR_MESSAGE(); fprintf(stderr,"allocation failure in NewTree()\n");
714  exit(1);
715  }
716  }
717  /* visit every branch to find center of mass and cutoff scale */
718  moveTop();
719 }
720 
721 
722 // tree must be created and first branch must be set before start
723 template <typename T,typename D>
724 void TreeSimpleVec<T,D>::_BuildTree(IndexType nparticles,IndexType *tmp_index){
725  IndexType i,cut,dimension;
726  BranchV branch1(*current),branch2(*current);
727  D xcut;
728  std::shared_ptr<BranchV> cbranch;
729 
730  cbranch=current; // pointer to current branch
731 
732  // leaf case
733  if(cbranch->nparticles <= Nbucket){
734  return;
735  }
736  //cbranch->big_particle=0;
737 
738  // **** makes sure force does not require nbucket at leaf
739 
740  // set dimension to cut box
741  dimension=(cbranch->level % Ndimensions);
742 
743  // D *x = new D[cbranch->nparticles];
744  D *x = workspace.data();
745  for(i=0;i<cbranch->nparticles;++i) x[i] = position(points[tmp_index[i]])[dimension];
746 
747  if(median_cut){
748  Utilities::quicksort(tmp_index,x,cbranch->nparticles);
749 
750  cut=(cbranch->nparticles)/2;
751  branch1.boundary_p2[dimension]=x[cut];
752  branch2.boundary_p1[dimension]=x[cut];
753  }else{
754  xcut=(cbranch->boundary_p1[dimension]+cbranch->boundary_p2[dimension])/2;
755  branch1.boundary_p2[dimension]=xcut;
756  branch2.boundary_p1[dimension]=xcut;
757 
758  Utilities::quickPartition(xcut,&cut,tmp_index
759  ,x,cbranch->nparticles);
760  }
761 
762  // set particle numbers and pointers to my_index
763  branch1.prev_ptr = cbranch;
764  branch1.nparticles=cut;
765 
766  branch2.prev_ptr = cbranch;
767  branch2.nparticles=cbranch->nparticles - cut;
768  if(cut < (cbranch->nparticles) )
769  branch2.branch_index = &tmp_index[cut];
770  else branch2.branch_index=nullptr;
771 
772  if(branch1.nparticles > 0) attachChildToCurrent(branch1,1);
773  if(branch2.nparticles > 0) attachChildToCurrent(branch2,2);
774 
775  // work out brothers for children
776  if( (cbranch->child1_ptr != nullptr) && (cbranch->child2_ptr != nullptr) ){
777  cbranch->child1_ptr->brother_ptr = cbranch->child2_ptr;
778  cbranch->child2_ptr->brother_ptr = cbranch->brother_ptr;
779  }
780  if( (cbranch->child1_ptr == nullptr) && (cbranch->child2_ptr != nullptr) )
781  cbranch->child2_ptr->brother_ptr = cbranch->brother_ptr;
782  if( (cbranch->child1_ptr != nullptr) && (cbranch->child2_ptr == nullptr) )
783  cbranch->child1_ptr->brother_ptr = cbranch->brother_ptr;
784 
785 
786  if( branch1.nparticles > 0 ){
787  moveToChild(1);
788  _BuildTree(branch1.nparticles,branch1.branch_index);
789  moveUp();
790  }
791 
792  if(branch2.nparticles > 0 ){
793  moveToChild(2);
794  _BuildTree(branch2.nparticles,branch2.branch_index);
795  moveUp();
796  }
797 
798  return;
799 }
800 
802 template <typename T,typename D>
804 
805  //clearTree();
806  delete top_ptr;
807  Nbranches=0;
808 
809  return;
810 }
811 
812 //template <typename T,typename D>
813 //short TreeSimpleVec<T,D>::clearTree(){
814 //
815 // moveTop();
816 // _freeTree(0);
817 //
818 // assert(Nbranches == 1);
819 //
820 // return 1;
821 //}
822 
823 //template <typename T,typename D>
824 //void TreeSimpleVec<T,D>::_freeTree(short child){
825 // BranchV *branch;
826 //
827 // assert( current);
828 //
829 // if(current->child1 != nullptr){
830 // moveToChild(1);
831 // _freeTree(1);
832 // }
833 //
834 // if(current->child2 != nullptr){
835 // moveToChild(2);
836 // _freeTree(2);
837 // }
838 //
839 // if( (current->child1 == nullptr)*(current->child2 == nullptr) ){
840 //
841 // if(atTop()) return;
842 //
843 // branch = current;
844 // moveUp();
845 // delete branch;
846 // --Nbranches;
847 //
848 // /*printf("*** removing branch %i number of branches %i\n",branch->number
849 // ,Nbranches-1);*/
850 //
851 // if(child==1) current->child1 = nullptr;
852 // if(child==2) current->child2 = nullptr;
853 //
854 // return;
855 // }
856 //
857 // return;
858 //}
859 
860 /************************************************************************
861  * isEmpty
862  * Returns "true" if the Tree is empty and "false" otherwise. Exported.
863  ************************************************************************/
864 template <typename T,typename D>
866  return(Nbranches == 0);
867 }
868 
869 /************************************************************************
870  * atTop
871  * Returns "true" if current is the same as top and "false" otherwise.
872  * Exported.
873  * Pre: !isEmpty()
874  ************************************************************************/
875 template <typename T,typename D>
877 
878  if( isEmpty() ){
879  ERROR_MESSAGE();
880  fprintf(stderr, "Tree Error: calling atTop() on empty tree\n");
881  exit(1);
882  }
883  return(current == top_ptr);
884 }
885 
886 /************************************************************************
887  * noChild
888  * Returns "true" if the child of the current BranchV does not exist and "false" otherwise.
889  * Exported.
890  * Pre: !isEmpty()
891  ************************************************************************/
892 template <typename T,typename D>
894 
895  if( isEmpty() ){
896 
897  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling atTop() on empty tree\n");
898  exit(1);
899  }
900 
901  if( (current->child1 == nullptr) || (current->child2 == nullptr) ) return true;
902  return false;
903 }
904 
905 /************************************************************************
906  * offEnd
907  * Returns "true" if current is off end and "false" otherwise. Exported.
908  ************************************************************************/
909 template <typename T,typename D>
911 
912  return(current == nullptr);
913 }
914 
915 /************************************************************************
916  * getCurrent
917  * Returns the particuls of current. Exported.
918  * Pre: !offEnd()
919  ************************************************************************/
920 template <typename T,typename D>
921 void TreeSimpleVec<T,D>::getCurrent(IndexType *branch_index,IndexType *nparticles){
922 
923  if( offEnd() ){
924 
925  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling getCurrent() when current is off end\n");
926  exit(1);
927  }
928 
929  *nparticles = current->nparticles;
930  branch_index = current->branch_index;
931 
932  return;
933 }
934 
935 /************************************************************************
936  * getNbranches
937  * Returns the NBranchVes of tree. Exported.
938  ************************************************************************/
939 template <typename T,typename D>
941 
942  return(Nbranches);
943 }
944 
945 /***** Manipulation procedures *****/
946 
947 /************************************************************************
948  * moveTop
949  * Moves current to the front of tree. Exported.
950  * Pre: !isEmpty()
951  ************************************************************************/
952 template <typename T,typename D>
954 
955  if( isEmpty() ){
956 
957  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling moveTop() on empty tree\n");
958  exit(1);
959  }
960 
961  current = top_ptr;
962 
963  return;
964 }
965 
966 /************************************************************************
967  * movePrev
968  * Moves current to the BranchV before it in tree. This can move current
969  * off end. Exported.
970  * Pre: !offEnd()
971  ************************************************************************/
972 template <typename T,typename D>
974 
975  if( offEnd() ){
976  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: call to moveUp() when current is off end\n");
977  exit(1);
978  }
979  if( current == top_ptr ){
980  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: call to moveUp() tried to move off the top\n");
981  exit(1);
982  }
983 
984  current = current->prev_ptr; /* can move off end */
985  return;
986 }
987 
988 /************************************************************************
989  * moveToChild
990  * Moves current to child BranchV after it in tree. This can move current off
991  * end. Exported.
992  * Pre: !offEnd()
993  ************************************************************************/
994 template <typename T,typename D>
995 void TreeSimpleVec<T,D>::moveToChild(int child){
996 
997  if( offEnd() ){
998 
999  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling moveChildren() when current is off end\n");
1000  exit(1);
1001  }
1002  if(child==1){
1003  if( current->child1_ptr == nullptr ){
1004  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: moveToChild() typing to move to child1 when it doesn't exist\n");
1005  exit(1);
1006  }
1007  current = current->child1_ptr;
1008  }
1009  if(child==2){
1010  if( current->child2_ptr == nullptr ){
1011  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: moveToChild() typing to move to child2 when it doesn't exist\n");
1012  exit(1);
1013  }
1014  current = current->child2_ptr;
1015  }
1016  return;
1017 }
1018 
1019 /************************************************************************
1020  * insertAfterCurrent
1021  * Inserts a new BranchV after the current BranchV in the tree and sets the
1022  * data field of the new BranchV to input. Exported.
1023  * Pre: !offEnd()
1024  ************************************************************************/
1025 template <typename T,typename D>
1026 void TreeSimpleVec<T,D>::attachChildToCurrent(IndexType *branch_index,IndexType nparticles
1027  ,D boundary_p1[],D boundary_p2[]
1028  ,int child){
1029 
1030  /*printf("attaching child%i current paricle number %i\n",child,current->nparticles);*/
1031  std::shared_ptr<BranchV> branchV(new BranchV(Ndimensions,branch_index,nparticles,boundary_p1,boundary_p2
1032  ,current->level+1,Nbranches));
1033 
1034  ++Nbranches;
1035 
1036 
1037  if( offEnd() ){
1038 
1039  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling attachChildToCurrent() when current is off end\n");
1040  exit(1);
1041  }
1042 
1043  branchV->prev_ptr = current;
1044 
1045  if(child==1){
1046  if(current->child1_ptr != nullptr){
1047  ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling attachChildToCurrent() when child1 alread exists\n");
1048  exit(1);
1049  }
1050  current->child1_ptr = branchV;
1051  }
1052  if(child==2){
1053  if(current->child2_ptr != nullptr){
1054  ERROR_MESSAGE();
1055  fprintf(stderr, "Tree Error: calling attachChildToCurrent() when child2 alread exists\n current level=%i Nbranches=%li\n"
1056  ,current->level,Nbranches);
1057  exit(1);
1058  }
1059  current->child2_ptr = branchV;
1060  }
1061 
1062  return;
1063 }
1064 
1065 /* same as above but takes a BranchV structure */
1066 template <typename T,typename D>
1067 void TreeSimpleVec<T,D>::attachChildToCurrent(BranchV &data,int child){
1068 
1069  attachChildToCurrent(data.branch_index,data.nparticles
1070  ,data.boundary_p1,data.boundary_p2,child);
1071  return;
1072 }
1073 
1074 // step for walking tree by iteration instead of recursion
1075 template <typename T,typename D>
1076 bool TreeSimpleVec<T,D>::TreeWalkStep(bool allowDescent){
1077  if(allowDescent && current->child1_ptr != nullptr){
1078  moveToChild(1);
1079  return true;
1080  }
1081  if(allowDescent && current->child2_ptr != nullptr){
1082  moveToChild(2);
1083  return true;
1084  }
1085 
1086  if(current->brother_ptr != nullptr){
1087  current = current->brother_ptr;
1088  return true;
1089  }
1090  return false;
1091 }
1092 
1093 // = 0 if not possibly intersection
1094 // > 0 sphere might intersect box
1095 // = 2 sphere completely inside box
1096 template <typename T,typename D>
1097 int TreeSimpleVec<T,D>::cutbox(const D *center,D *p1,D *p2,float rmax){
1098  int intersection = 1,inside=1;
1099  for(int i=0 ; i<Ndimensions ; ++i){
1100  intersection *= ( (center[i] + rmax) > p1[i] )*( (center[i] - rmax) < p2[i] );
1101  inside *= ( (center[i] - rmax) > p1[i] )*( (center[i] + rmax) < p2[i] );
1102  }
1103 
1104  return intersection + inside;
1105 }
1106 #endif /* SIMP_TREE_V_ */
TreeSimpleVec::BranchV::prev_ptr
std::shared_ptr< BranchV > prev_ptr
father of branch
Definition: simpleTreeVec.h:143
TreeSimpleVec::BranchV
Box representing a branch in a tree. It has four children. Used in TreeNBStruct which is used in Tree...
Definition: simpleTreeVec.h:125
TreeSimpleVec::BranchV::branch_index
IndexType * branch_index
array of branch_index in BranchV
Definition: simpleTreeVec.h:129
TreeSimpleVec::TreeSimpleVec
TreeSimpleVec(T *xpt, IndexType Npoints, int bucket=5, int dimensions=2, bool median=true, D *(*Mypos)(T &)=[](T &in){return in.x;})
Definition: simpleTreeVec.h:25
TreeSimpleVec::freeTree
void freeTree()
Free all the tree branches.
Definition: simpleTreeVec.h:803
TreeSimpleVec
A tree for doing quick searches in multidimensional space. A pointer to an array of objects type T is...
Definition: simpleTreeVec.h:22
TreeSimpleVec::PointsWithinCircle
void PointsWithinCircle(D center[2], float radius, std::list< unsigned long > &neighborkist)
Finds the points within a circle around center and puts their index numbers in a list.
Definition: simpleTreeVec.h:316
TreeSimpleVec::BranchV::brother_ptr
std::shared_ptr< BranchV > brother_ptr
Definition: simpleTreeVec.h:146
TreeSimpleVec::NearestNeighbors
void NearestNeighbors(D *ray, int Nneighbors, std::vector< D > &radii, std::vector< IndexType > &neighbors)
Finds the nearest N neighbors and puts their index numbers in an array, also returns the distance to ...
Definition: simpleTreeVec.h:463
TreeSimpleVec::PointsWithinEllipse
void PointsWithinEllipse(D center[2], float a_max, float a_min, float posangle, std::list< unsigned long > &neighborkist)
Finds the points within an ellipse around center and puts their index numbers in a list.
Definition: simpleTreeVec.h:286
standard.h
Point_nd
Definition: point.h:1271
TreeSimpleVec::pop
void pop(IndexType index_of_point)
pop this point out of the tree
Definition: simpleTreeVec.h:61
TreeSimpleVec::BranchV::level
int level
level in tree
Definition: simpleTreeVec.h:132
TreeSimpleVec::NearestNeighbor
void NearestNeighbor(D *ray, D &radius, IndexType &neighbor)
finds the nearest neighbors in whatever dimensions tree is defined in
Definition: simpleTreeVec.h:529
TreeSimpleVec::get_index
std::vector< IndexType > get_index() const
returns the index numbers of the remaining points which are less than the original if pop() was used.
Definition: simpleTreeVec.h:105
TreeSimpleVec::BranchV::boundary_p2
D * boundary_p2
top, right, front corner of box
Definition: simpleTreeVec.h:137
TreeSimpleVec::Nbranches
unsigned long Nbranches
number of branches in tree
Definition: simpleTreeVec.h:215
TreeSimpleVec::_PointsWithin
void _PointsWithin(D *ray, float *rmax, std::list< unsigned long > &neighborkist)
Definition: simpleTreeVec.h:350
TreeSimpleVec::BranchV::boundary_p1
D * boundary_p1
bottom, left, back corner of box
Definition: simpleTreeVec.h:135
TreeSimpleVec::_NearestNeighbors
void _NearestNeighbors(D *ray, int Nneighbors, unsigned long *neighbors, D *rneighbors)
Definition: simpleTreeVec.h:575
TreeSimpleVec::Ndimensions
short Ndimensions
Dimension of tree, 2 or 3. This will dictate how the force is calculated.
Definition: simpleTreeVec.h:217