23 center =
new PosType[Ndim*3];
61template<
typename PType>
85template<
typename PType>
88 TreeSimple(PType *xp,IndexType Npoints,
int bucket = 5,
int dimensions = 2,
bool median =
true);
97 void PointsWithinEllipse(T center[2],
float a_max,
float a_min,
float posangle,std::list<unsigned long> &neighborkist);
110 current = top = branch;
112 iterator(
const iterator &it){
113 current = it.current;
117 iterator & operator=(
const iterator &it){
118 if(&it ==
this)
return *
this;
119 current = it.current;
125 bool operator==(
const iterator &it){
126 return (current == it.current)*(top == it.top);
129 BranchNB *operator*(){
return current;}
132 bool walk(
bool decend){
135 if(decend && current->child1 != NULL){
136 current = current->child1;
139 if(decend && current->child2 != NULL){
140 current = current->child2;
152 if(current == top)
return false;
153 current = current->
prev;
157 bool down(
int child){
160 if(current->child1 == NULL)
return false;
161 current = current->child1;
165 if(current->child2 == NULL)
return false;
166 current = current->child2;
177 return (current->child1 == NULL)*(current->child2 == NULL);
180 return (current == top);
183 size_t getcout(){
return count;}
195 IndexType Nparticles;
201 TreeNBStruct<PType>* BuildTreeNB(PType *xxp,IndexType Nparticles,IndexType *particles,
int Ndimensions,PosType theta);
204 template <
typename T>
205 void _findleaf(T *ray,TreeSimple::iterator &it)
const;
209 void _PointsWithin(T *ray,
float *rmax,std::list<unsigned long> &neighborkist);
212 void _NearestNeighbors(T *ray,
int Nneighbors,
unsigned long *neighbors,PosType *rneighbors);
219 ,PosType boundary_p1[],PosType boundary_p2[]
220 ,PosType center[],
int level,
unsigned long branchNBnumber);
221 void FreeBranchNB(
BranchNB *branchNB);
223 ,PosType boundary_p1[],PosType boundary_p2[],
224 PosType center[],
short Ndimensions);
237 void insertChildToCurrentNB(
TreeNBStruct<PType> * tree, IndexType *particles,IndexType nparticles
238 ,PosType boundary_p1[],PosType boundary_p2[]
239 ,PosType center[],
int child);
243 inline bool atLeaf(){
244 return (tree->current->child1 == NULL)*(tree->current->child2 == NULL);
247 inline bool inbox(
const T* center,PosType *p1,PosType *p2)
const{
248 return (center[0]>=p1[0])*(center[0]<=p2[0])*(center[1]>=p1[1])*(center[1]<=p2[1]);
263template<
typename PType>
265 index =
new IndexType[Npoints];
271 Nparticles = Npoints;
275 for(ii=0;ii<Npoints;++ii) index[ii] = ii;
277 tree = TreeSimple::BuildTreeNB(xxp,Npoints,index,Ndimensions,0);
282template<
typename PType>
290template<
typename PType>
297 ,std::list <unsigned long> &neighborlist
302 if(rmax < rmin){
float tmp = rmax; rmax=rmin; rmin=tmp;}
304 if(rmax <=0.0 || rmin <= 0.0){ neighborlist.clear();
return; }
307 PointsWithinCircle(ray,rmax,neighborlist);
312 for( std::list<unsigned long>::iterator it = neighborlist.begin();it != neighborlist.end();){
313 x = xxp[*it][0]*cs - xxp[*it][1]*sn;
314 y = xxp[*it][0]*sn + xxp[*it][1]*cs;
315 if( ( pow(x/rmax,2) + pow(y/rmin,2) ) > 1) it = neighborlist.erase(it);
321template<
typename PType>
326 ,std::list <unsigned long> &neighborlist
329 neighborlist.clear();
353 _PointsWithin<T>(ray,&rmax,neighborlist);
359template<
typename PType>
387 for(i=0;i<tree->current->nparticles;++i){
388 for(j=0,radius=0.0;j<2;++j) radius+=pow(xxp[tree->current->
particles[i]][j]-ray[j],2);
389 if( radius < *rmax**rmax ){
390 neighborlist.push_back(tree->current->
particles[i]);
396 for(i=0;i<tree->current->nparticles;++i){
397 neighborlist.push_back(tree->current->
particles[i]);
406 if(tree->current->child1 !=NULL){
407 moveToChildNB(tree,1);
408 _PointsWithin(ray,rmax,neighborlist);
414 if(tree->current->child2 !=NULL){
415 moveToChildNB(tree,2);
416 _PointsWithin(ray,rmax,neighborlist);
421 if( (incell2==1) && (incell==0) ){
422 if(tree->current->child1 !=NULL){
423 moveToChildNB(tree,1);
424 _PointsWithin(ray,rmax,neighborlist);
439 for(i=0;i<tree->current->nparticles;++i){
440 for(j=0,radius=0.0;j<2;++j) radius+=pow(xxp[tree->current->
particles[i]][j]-ray[j],2);
441 if( radius < *rmax**rmax ){
442 neighborlist.push_back(tree->current->
particles[i]);
450 for(i=0;i<tree->current->nparticles;++i){
451 neighborlist.push_back(tree->current->
particles[i]);
457 if(tree->current->child1 !=NULL){
458 moveToChildNB(tree,1);
459 _PointsWithin(ray,rmax,neighborlist);
463 if(tree->current->child2 !=NULL){
464 moveToChildNB(tree,2);
465 _PointsWithin(ray,rmax,neighborlist);
481template<
typename PType>
488 if(tree->top->nparticles <= Nneighbors){
490 printf(
"ERROR: in TreeSimple::NearestNeighbors, number of neighbors > total number of particles\n");
494 std::vector<PosType> tmp(Ndim);
495 TreeSimple::iterator iter(tree->top);
506 _findleaf(tmp.data(),iter);
511 while((*iter)->nparticles < Nneighbors){ iter.up(); ++levelup;}
515 std::priority_queue<PosType> r2heap;
518 for(i=0 ; i < Nneighbors ;++i){
520 for(
int j=0;j<Ndim;++j){
522 r2 += pow(tree->
pp[(*iter)->particles[i]][j]-ray[j],2);
527 for(; i < (*iter)->nparticles ;++i){
529 for(
int j=0;j<Ndim;++j){
531 r2 += pow(tree->
pp[(*iter)->particles[i]][j]-ray[j],2);
533 if(r2 < r2heap.top()){
544 PosType bestr = sqrt( r2heap.top() );
582 short dim = (cbranch->
level-1) % Ndim;
584 if(( (ray[dim] + bestr) > cbranch->
boundary_p1[dim] )
585 *( (ray[dim] - bestr) < cbranch->
boundary_p2[dim] ) ){
590 for(
int i=0 ; i< cbranch->nparticles ;++i){
592 for(
int j=0;j<Ndim;++j){
593 r2 += pow(tree->
pp[cbranch->
particles[i]][j]-ray[j],2);
596 if(r2 < bestr*bestr){
600 bestr = sqrt( r2heap.top() );
617 }
while(iter.walk(decend));
623template<
typename PType>
627 if( it.atleaf() )
return;
629 int d = (*it)->level % Ndim;
631 if( (*it)->child1->boundary_p2[d] > ray[d] ){
746template<
typename PType>
759 if( tree->current->nparticles <= Nneighbors+Nbucket ){
761 for(j=0;j<tree->
Ndimensions;++j) ray[j]=realray[j];
764 for(i=0;i<tree->current->nparticles;++i){
765 for(j=0,rneighbors[i]=0.0;j<tree->
Ndimensions;++j){
766 rneighbors[i] += pow(tree->xp[tree->current->
particles[i]][j]-ray[j],2);
768 rneighbors[i]=sqrt( rneighbors[i] );
769 assert(rneighbors[i] < 10);
770 neighbors[i]=tree->current->
particles[i];
773 Utilities::quicksort(neighbors,rneighbors,tree->current->nparticles);
777 if(tree->current->child1 !=NULL){
778 moveToChildNB(tree,1);
779 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
786 if(tree->current->child2 !=NULL){
788 moveToChildNB(tree,2);
789 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
795 if( (incellNB2==1) && (incell==0) ){
796 if(tree->current->child1 !=NULL){
797 moveToChildNB(tree,1);
798 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
806 if( Utilities::cutbox(ray,tree->current->
boundary_p1,tree->current->
boundary_p2,rneighbors[Nneighbors-1]) ){
808 if( (tree->current->child1 == NULL)*(tree->current->child2 == NULL)){
811 for(i=Nneighbors;i<(tree->current->nparticles+Nneighbors);++i){
812 for(j=0,rneighbors[i]=0.0;j<tree->
Ndimensions;++j){
813 rneighbors[i]+=pow(tree->xp[tree->current->
particles[i-Nneighbors]][j]-ray[j],2);
815 rneighbors[i]=sqrt( rneighbors[i] );
816 assert(rneighbors[i] < 10);
817 neighbors[i]=tree->current->
particles[i-Nneighbors];
820 Utilities::quicksort(neighbors,rneighbors,Nneighbors+Nbucket);
824 if(tree->current->child1 !=NULL){
825 moveToChildNB(tree,1);
826 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
830 if(tree->current->child2 !=NULL){
831 moveToChildNB(tree,2);
832 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
841template<
typename PType>
847 PosType p1[3],p2[3],center[3];
849 assert(Ndim == Ndims);
856 for(i=0;i<Nparticles;++i){
858 if(xp[i][j] < p1[j] ) p1[j]=xp[i][j];
859 if(xp[i][j] > p2[j] ) p2[j]=xp[i][j];
863 for(j=0;j<Ndim;++j) center[j]=(p1[j]+p2[j])/2;
866 tree=NewTreeNB(particles,Nparticles,p1,p2,center,Ndim);
871 _BuildTreeNB(tree,Nparticles,particles);
881template<
typename PType>
883 IndexType i,cut,dimension;
885 BranchNB *cbranch,branch1(Ndim),branch2(Ndim);
889 cbranch=tree->current;
896 if(cbranch->nparticles <= Nbucket){
914 dimension=(cbranch->
level % Ndim);
916 x=(PosType *)malloc((cbranch->nparticles-cbranch->
big_particle)*
sizeof(PosType));
917 for(i=cbranch->
big_particle;i<cbranch->nparticles;++i) x[i]=tree->
pp[particles[i]][dimension];
920 Utilities::quicksort(particles,x,cbranch->nparticles-cbranch->
big_particle);
923 branch1.boundary_p2[dimension]=x[cut];
924 branch2.boundary_p1[dimension]=x[cut];
927 branch1.boundary_p2[dimension]=xcut;
928 branch2.boundary_p1[dimension]=xcut;
930 Utilities::quickPartition(xcut,&cut,particles
935 branch1.prev=cbranch;
936 branch1.nparticles=cut;
939 branch2.prev=cbranch;
940 branch2.nparticles=cbranch->nparticles-cbranch->
big_particle - cut;
942 branch2.particles=&particles[cut+cbranch->
big_particle];
943 else branch2.particles=NULL;
947 if(branch1.nparticles > 0) attachChildToCurrentNB(tree,branch1,1);
948 if(branch2.nparticles > 0) attachChildToCurrentNB(tree,branch2,2);
951 if( (cbranch->child1 != NULL) && (cbranch->child2 != NULL) ){
952 cbranch->child1->
brother = cbranch->child2;
955 if( (cbranch->child1 == NULL) && (cbranch->child2 != NULL) )
957 if( (cbranch->child1 != NULL) && (cbranch->child2 == NULL) )
961 if( branch1.nparticles > 0 ){
962 moveToChildNB(tree,1);
963 _BuildTreeNB(tree,branch1.nparticles,branch1.particles);
967 if(branch2.nparticles > 0 ){
968 moveToChildNB(tree,2);
969 _BuildTreeNB(tree,branch2.nparticles,branch2.particles);
992template<
typename PType>
994 ,PosType boundary_p1[],PosType boundary_p2[]
995 ,PosType center[],
int level,
unsigned long branchNBnumber){
1001 ERROR_MESSAGE(); fprintf(stderr,
"allocation failure in NewBranchNB()\n");
1005 branchNB->nparticles = nparticles;
1007 for(i=0;i<Ndim;++i) branchNB->
center[i]=center[i];
1008 branchNB->
level=level;
1010 for(i=0;i<Ndim;++i){
1015 branchNB->number=branchNBnumber;
1017 branchNB->child1 = NULL;
1018 branchNB->child2 = NULL;
1019 branchNB->
prev = NULL;
1029template<
typename PType>
1032 assert( branchNB != NULL);
1043template<
typename PType>
1045 ,PosType boundary_p1[],PosType boundary_p2[],
1046 PosType center[],
short Ndimensions){
1052 ERROR_MESSAGE(); fprintf(stderr,
"allocation failure in NewTreeNB()\n");
1056 tree->top= NewBranchNB(particles,nparticles,boundary_p1,boundary_p2,center,0,0);
1058 ERROR_MESSAGE(); fprintf(stderr,
"allocation failure in NewTreeNB()\n");
1063 tree->current = tree->top;
1069template<
typename PType>
1075 if(tree == NULL)
return;
1078 FreeBranchNB(tree->top);
1084template<
typename PType>
1088 _freeTreeNB(tree,0);
1095template<
typename PType>
1100 assert( tree->current);
1102 if(tree->current->child1 != NULL){
1103 moveToChildNB(tree,1);
1104 _freeTreeNB(tree,1);
1107 if(tree->current->child2 != NULL){
1108 moveToChildNB(tree,2);
1109 _freeTreeNB(tree,2);
1112 if( (tree->current->child1 == NULL)*(tree->current->child2 == NULL) ){
1114 if(atTopNB(tree))
return;
1116 branch = tree->current;
1118 FreeBranchNB(branch);
1123 if(child==1) tree->current->child1 = NULL;
1124 if(child==2) tree->current->child2 = NULL;
1138template<
typename PType>
1141 assert(tree != NULL);
1151template<
typename PType>
1154 assert(tree != NULL);
1155 if( isEmptyNB(tree) ){
1157 fprintf(stderr,
"TreeNB Error: calling atTop() on empty tree\n");
1160 return(tree->current == tree->top);
1169template<
typename PType>
1172 assert(tree != NULL);
1173 if( isEmptyNB(tree) ){
1175 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: calling atTop() on empty tree\n");
1179 if( (tree->current->child1 == NULL) || (tree->current->child2 == NULL) )
return true;
1187template<
typename PType>
1190 assert(tree != NULL);
1191 return(tree->current == NULL);
1199template<
typename PType>
1202 assert(tree != NULL);
1203 if( offEndNB(tree) ){
1205 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: calling getCurrent() when current is off end\n");
1209 *nparticles=tree->current->nparticles;
1219template<
typename PType>
1222 assert(tree != NULL);
1233template<
typename PType>
1239 assert(tree != NULL);
1240 if( isEmptyNB(tree) ){
1242 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: calling moveTopNB() on empty tree\n");
1247 tree->current = tree->top;
1258template<
typename PType>
1261 assert(tree != NULL);
1262 if( offEndNB(tree) ){
1263 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: call to moveUpNB() when current is off end\n");
1266 if( tree->current == tree->top ){
1267 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: call to moveUpNB() tried to move off the top\n");
1271 tree->current = tree->current->
prev;
1281template<
typename PType>
1284 assert(tree != NULL);
1285 if( offEndNB(tree) ){
1287 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: calling moveChildren() when current is off end\n");
1291 if( tree->current->child1 == NULL ){
1292 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: moveToChildNB() typing to move to child1 when it doesn't exist\n");
1295 tree->current = tree->current->child1;
1298 if( tree->current->child2 == NULL ){
1299 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: moveToChildNB() typing to move to child2 when it doesn't exist\n");
1302 tree->current = tree->current->child2;
1313template<
typename PType>
1315 ,PosType boundary_p1[],PosType boundary_p2[]
1316 ,PosType center[],
int child){
1322 branchNB = NewBranchNB(particles,nparticles,boundary_p1,boundary_p2,center
1325 assert(tree != NULL);
1327 if( offEndNB(tree) ){
1329 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: calling insertChildToCurrentNB() when current is off end\n");
1333 branchNB->
prev = tree->current;
1336 if(tree->current->child1 != NULL){
1337 ERROR_MESSAGE(); fprintf(stderr,
"TreeNB Error: calling insertChildToCurrentNB() when child1 alread exists\n");
1340 tree->current->child1 = branchNB;
1343 if(tree->current->child2 != NULL){
1345 fprintf(stderr,
"TreeNB Error: calling insertChildToCurrentNB() when child2 alread exists\n current level=%i Nbranches=%li\n"
1349 tree->current->child2 = branchNB;
1358template<
typename PType>
1361 insertChildToCurrentNB(tree,data.
particles,data.nparticles
1367template<
typename PType>
1369 if(allowDescent && tree->current->child1 != NULL){
1370 moveToChildNB(tree,1);
1373 if(allowDescent && tree->current->child2 != NULL){
1374 moveToChildNB(tree,2);
1378 if(tree->current->
brother != NULL){
1379 tree->current=tree->current->
brother;
A C++ class wrapper for the bianary treeNB used in the Nbody force calculation, but also useful for g...
Definition simpleTree.h:86
void _PointsWithin(T *ray, float *rmax, std::list< unsigned long > &neighborkist)
Definition simpleTree.h:361
BranchNB * NewBranchNB(IndexType *particles, IndexType nparticles, PosType boundary_p1[], PosType boundary_p2[], PosType center[], int level, unsigned long branchNBnumber)
Definition simpleTree.h:993
void PointsWithinEllipse(T 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.
T NNDistance(T *ray, int Nneighbors) const
Finds the nearest N neighbors and puts their index numbers in an array, also returns the distance to ...
Definition simpleTree.h:483
void _NearestNeighbors(T *ray, int Nneighbors, unsigned long *neighbors, PosType *rneighbors)
Definition simpleTree.h:748
void PointsWithinCircle(T 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.
T median(std::vector< T > vec)
find median of vector
Definition utilities.h:234
Box representing a branch in a tree. It has four children. Used in TreeNBStruct which is used in Tree...
Definition simpleTree.h:20
int level
level in tree
Definition simpleTree.h:39
IndexType * particles
array of particles in BranchNB
Definition simpleTree.h:32
BranchNB * prev
father of branch
Definition simpleTree.h:48
BranchNB * brother
Definition simpleTree.h:51
PosType * center
center of mass
Definition simpleTree.h:37
PosType * boundary_p2
top, right, front corner of box
Definition simpleTree.h:44
IndexType big_particle
the number of particles that aren't in children
Definition simpleTree.h:35
PosType * boundary_p1
bottom, left, back corner of box
Definition simpleTree.h:42
TreeNBStruct: Tree structure used for force calculation with particles (i.e. stars,...
Definition simpleTree.h:62
short Ndimensions
Dimension of tree, 2 or 3. This will dictate how the force is calculated.
Definition simpleTree.h:68
PType * pp
Array of particle positions.
Definition simpleTree.h:70
unsigned long Nbranches
number of branches in tree
Definition simpleTree.h:66