12#include "utilities_slsim.h"
34template <
typename LensHaloType>
40 ,PosType my_inv_area = 0
42 ,PosType theta_force = 0.5
43 ,
bool my_periodic_buffer =
false
44 ,PosType my_inv_screening_scale = 0
45 ,PosType maximum_range = -1
50 void force2D(PosType
const *ray,PosType *alpha,KappaType *kappa,KappaType *gamma
51 ,KappaType *phi)
const;
57 void neighbors(PosType ray[],PosType rmax,std::list<IndexType> &neighbors)
const;
58 void neighbors(PosType ray[],PosType rmax,std::vector<LensHaloType *> &neighbors)
const;
60 void printParticlesInBranch(
unsigned long number);
62 void printBranchs(
int level = -1);
66 std::vector<PosType> workspace;
79 std::vector<IndexType> index;
89 PosType inv_screening_scale2;
93 QTreeNB<PosType *> * BuildQTreeNB(PosType **xp,IndexType Nparticles,IndexType *particles);
94 void _BuildQTreeNB(IndexType nparticles,IndexType *particles);
96 inline short WhichQuad(PosType *x,
QBranchNB &branch);
99 inline bool inbox(
const PosType *ray,
const PosType *p1,
const PosType *p2){
100 return (ray[0]>=p1[0])*(ray[0]<=p2[0])*(ray[1]>=p1[1])*(ray[1]<=p2[1]);
105 void rotate_coordinates(PosType **coord);
117 ,KappaType *gamma,KappaType *phi)
const;
128template <
typename LensHaloType>
129TreeQuadHalos<LensHaloType>::TreeQuadHalos(
134 ,PosType my_theta_force
135 ,
bool periodic_buffer
136 ,PosType my_inv_screening_scale
137 ,PosType maximum_range
139MultiMass(true),MultiRadius(true)
140,Nparticles(Npoints),inv_area(my_inv_area),Nbucket(bucket)
141,force_theta(my_theta_force)
142,max_range(maximum_range),halos(my_halos),periodic_buffer(periodic_buffer)
143,inv_screening_scale2(my_inv_screening_scale*my_inv_screening_scale)
145 index.resize(Npoints);
148 for(ii=0;ii<Npoints;++ii) index[ii] = ii;
151 xp = Utilities::PosTypeMatrix(Npoints,2);
152 for(ii=0;ii<Npoints;++ii) halos[ii]->getX(xp[ii]);
155 tree = BuildQTreeNB(xp,Npoints,index.data());
159 phiintconst = (120*log(2.) - 631.)/840 + 19./70;
164template <
typename LensHaloType>
165TreeQuadHalos<LensHaloType>::~TreeQuadHalos()
167 if(Nparticles == 0)
return;
169 Utilities::free_PosTypeMatrix(xp,Nparticles,2);
173template <
typename LensHaloType>
174QTreeNB<PosType *> * TreeQuadHalos<LensHaloType>::BuildQTreeNB(PosType **xp,IndexType Nparticles,IndexType *particles){
185 for(i=0;i<Nparticles;++i){
187 if(xp[i][j] < p1[j] ) p1[j]=xp[i][j];
188 if(xp[i][j] > p2[j] ) p2[j]=xp[i][j];
200 PosType lengths[2] = {p2[0]-p1[0],p2[1]-p1[1]};
201 original_xl = lengths[0];
202 original_yl = lengths[1];
204 if(lengths[0] == 0 || lengths[1] == 0){
205 throw std::invalid_argument(
"particles in same place.");
209 j = lengths[0] > lengths[1] ? 1 : 0;
210 p2[j] = p1[j] + lengths[!j];
216 workspace.resize(Nparticles);
217 _BuildQTreeNB(Nparticles,particles);
219 workspace.shrink_to_fit();
228template <
typename LensHaloType>
229inline short TreeQuadHalos<LensHaloType>::WhichQuad(PosType *x,
QBranchNB &branch){
230 return (x[0] < branch.
center[0]) + 2*(x[1] < branch.
center[1]);
234template <
typename LensHaloType>
235void TreeQuadHalos<LensHaloType>::_BuildQTreeNB(IndexType nparticles,IndexType *particles){
238 IndexType i,j,cut,cut2;
245 double theta_range = 2*force_theta;
248 theta_range = boxsize / MAX(sqrt(cbranch->
center[0]*cbranch->
center[0]
250 - max_range, boxsize );
254 if(cbranch->nparticles <= Nbucket
255 || force_theta > theta_range
259 cbranch->big_particles.reset(
new IndexType[cbranch->
Nbig_particles] );
260 for(i=0,j=0;i<cbranch->nparticles;++i){
261 cbranch->big_particles[i] = particles[i];
291 PosType *x = workspace.data();
297 for(i=0;i<cbranch->nparticles;++i){
298 x[i] = halos[particles[i]]->get_Rmax();
303 Utilities::quickPartition(half_box,&cut,particles,x,cbranch->nparticles);
305 if(cut < cbranch->nparticles){
309 Utilities::quickPartition(2*half_box,&cut2,&particles[cut],&x[cut],cbranch->nparticles-cut);
314 cbranch->big_particles.reset(
new IndexType[cbranch->
Nbig_particles] );
315 for(i=cut;i<(cut+cut2);++i) cbranch->big_particles[i-cut] = particles[i];
319 x[0] = halos[0]->get_Rmax();
323 cbranch->big_particles.reset(
new IndexType[cbranch->
Nbig_particles] );
324 for(i=0;i<cbranch->
Nbig_particles;++i) cbranch->big_particles[i] = particles[i];
330 IndexType NpInChildren = cbranch->nparticles;
331 assert(NpInChildren >= 0);
333 if(NpInChildren == 0){
346 tree->attachChildrenToCurrent(child0,child1,child2,child3);
376 xcut = cbranch->
center[0];
377 ycut = cbranch->
center[1];
380 for(i=0;i<NpInChildren;++i) x[i] = tree->
xxp[particles[i]][1];
381 Utilities::quickPartition(ycut,&cuty,particles,x,NpInChildren);
385 for(i=0;i<cuty;++i) x[i] = tree->
xxp[particles[i]][0];
386 Utilities::quickPartition(xcut,&cutx,particles,x,cuty);
388 child3->nparticles=cutx;
389 assert(child3->nparticles >= 0);
390 if(child3->nparticles > 0)
394 child2->nparticles = cuty - cutx;
395 assert(child2->nparticles >= 0);
396 if(child2->nparticles > 0)
401 child3->nparticles = 0;
404 child2->nparticles = 0;
408 if(cuty < NpInChildren){
410 for(i=cuty;i<NpInChildren;++i) x[i-cuty] = tree->
xxp[particles[i]][0];
411 Utilities::quickPartition(xcut,&cutx,&particles[cuty],x,NpInChildren-cuty);
413 child1->nparticles=cutx;
414 assert(child1->nparticles >= 0);
415 if(child1->nparticles > 0)
419 child0->nparticles=NpInChildren - cuty - cutx;
420 assert(child0->nparticles >= 0);
421 if(child0->nparticles > 0)
422 child0->
particles = &particles[cuty + cutx];
426 child1->nparticles = 0;
429 child0->nparticles = 0;
435 tree->moveToChild(0);
436 _BuildQTreeNB(child0->nparticles,child0->
particles);
439 tree->moveToChild(1);
440 _BuildQTreeNB(child1->nparticles,child1->
particles);
443 tree->moveToChild(2);
444 _BuildQTreeNB(child2->nparticles,child2->
particles);
447 tree->moveToChild(3);
448 _BuildQTreeNB(child3->nparticles,child3->
particles);
455template <
typename LensHaloType>
456void TreeQuadHalos<LensHaloType>::CalcMoments(){
460 PosType rcom,xcm[2],xcut;
466 cbranch=tree->current;
472 for(i=0,cbranch->mass=0;i<cbranch->nparticles;++i)
473 cbranch->mass += halos[cbranch->
particles[i]]->get_mass();
478 for(i=0;i<cbranch->nparticles;++i){
479 tmp = halos[cbranch->
particles[i]]->get_mass();
488 for(i=0;i<cbranch->nparticles;++i){
491 xcut = pow(xcm[0],2) + pow(xcm[1],2);
493 tmp = halos[cbranch->
particles[i]]->get_mass();
495 cbranch->
quad[0] += (xcut-2*xcm[0]*xcm[0])*tmp;
496 cbranch->
quad[1] += (xcut-2*xcm[1]*xcm[1])*tmp;
497 cbranch->
quad[2] += -2*xcm[0]*xcm[1]*tmp;
502 pow(cbranch->
center[i]-cbranch->
boundary_p1[i],2) : pow(cbranch->center[i]-cbranch->boundary_p2[i],2);
506 if(force_theta > 0.0){
511 }
while(tree->WalkStep(
true));
517template <
typename LensHaloType>
518void TreeQuadHalos<LensHaloType>::rotate_coordinates(PosType **coord){
524 for(i=0;i<tree->top->nparticles;++i){
525 for(j=0;j<3;++j) tmp[j]=0.0;
527 tmp[0]+=coord[0][j]*xp[i][j];
528 tmp[1]+=coord[1][j]*xp[i][j];
529 tmp[2]+=coord[2][j]*xp[i][j];
531 for(j=0;j<3;++j) xp[i][j]=tmp[j];
556template <
typename LensHaloType>
557void TreeQuadHalos<LensHaloType>::force2D(
const PosType *ray,PosType *alpha,KappaType *kappa,KappaType *gamma,KappaType *phi)
const{
559 alpha[0]=alpha[1]=gamma[0]=gamma[1]=gamma[2]=0.0;
562 if(Nparticles == 0)
return;
572 for(
int i = -1;i<2;++i){
573 for(
int j = -1;j<2;++j){
574 tmp_ray[0] = ray[0] + i*original_xl;
575 tmp_ray[1] = ray[1] + j*original_yl;
576 walkTree_iter(it,tmp_ray,alpha,kappa,gamma,phi);
580 walkTree_iter(it,ray,alpha,kappa,gamma,phi);
595template <
typename LensHaloType>
596void TreeQuadHalos<LensHaloType>::neighbors(PosType ray[],PosType rmax,std::list<IndexType> &neighbors)
const{
602 PosType r2 = rmax*rmax;
606 int cut = Utilities::cutbox(ray,(*it)->boundary_p1,(*it)->boundary_p2,rmax);
612 for(
int i=0;i<(*it)->nparticles;++i) neighbors.push_back((*it)->particles[i]);
614 }
else if((*it)->child0 == NULL){
615 for(
int i=0;i<(*it)->nparticles;++i){
616 if( (tree->
xxp[(*it)->particles[i]][0] - ray[0])*(tree->
xxp[(*it)->particles[i]][0] - ray[0])
617 + (tree->
xxp[(*it)->particles[i]][1] - ray[1])*(tree->
xxp[(*it)->particles[i]][1] - ray[1]) < r2) neighbors.push_back((*it)->particles[i]);
621 }
while(it.TreeWalkStep(decend));
626template <
typename LensHaloType>
627void TreeQuadHalos<LensHaloType>::neighbors(PosType ray[],PosType rmax,std::vector<LensHaloType *> &neighbors)
const{
631 std::cerr <<
"TreeQuadHalos<LensHaloType>::neighbors - The are no halos in this tree use other version of this function" << std::endl;
632 throw std::runtime_error(
"no halos");
636 std::list<IndexType> neighbor_indexes;
637 TreeQuadHalos<LensHaloType>::neighbors(ray,rmax,neighbor_indexes);
639 neighbors.resize(neighbor_indexes.size());
640 std::list<IndexType>::iterator it = neighbor_indexes.begin();
641 for(
size_t i=0;i<neighbors.size();++i,++it){
642 neighbors[i] = halos[*it];
648template <
typename LensHaloType>
649void TreeQuadHalos<LensHaloType>::walkTree_iter(
660 unsigned long count=0;
669 for(
size_t i = 0 ; i < (*treeit)->Nbig_particles ; ++i){
671 size_t tmp_index = (*treeit)->big_particles[i];
674 xcm[0] = tree->
xxp[tmp_index][0] - ray[0];
675 xcm[1] = tree->
xxp[tmp_index][1] - ray[1];
677 PosType rcm2 = xcm[0]*xcm[0] + xcm[1]*xcm[1];
679 double screening = exp(-rcm2*inv_screening_scale2);
680 halos[tmp_index]->force_halo(alpha,kappa,gamma,phi,xcm,
false,screening);
683 double mass = halos[tmp_index]->get_mass();
684 double prefac = mass * inv_area ;
686 alpha[0] += prefac*xcm[0];
687 alpha[1] += prefac*xcm[1];
689 *phi += - inv_area*rcm2 * mass*0.5;
690 *kappa -= mass * inv_area;
694 if( !(treeit.atLeaf()) ){
697 xcm_cell[0]=(*treeit)->center[0]-ray[0];
698 xcm_cell[1]=(*treeit)->center[1]-ray[1];
700 PosType rcm2cell = xcm_cell[0]*xcm_cell[0] + xcm_cell[1]*xcm_cell[1];
702 if(rcm2cell > (*treeit)->r2crit_angle ){
706 double screening = exp(-rcm2cell*inv_screening_scale2);
707 double tmp = (*treeit)->mass*(inv_area - screening/rcm2cell/PI);
709 alpha[0] += tmp*xcm_cell[0];
710 alpha[1] += tmp*xcm_cell[1];
713 tmp=-2.0*(*treeit)->mass/PI/rcm2cell/rcm2cell*screening;
714 gamma[0] += 0.5*(xcm_cell[0]*xcm_cell[0]-xcm_cell[1]*xcm_cell[1])*tmp;
715 gamma[1] += xcm_cell[0]*xcm_cell[1]*tmp;
717 *phi += 0.5*(*treeit)->mass*log( rcm2cell )/PI*screening;
718 *phi -= 0.5*( (*treeit)->quad[0]*xcm_cell[0]*xcm_cell[0] + (*treeit)->quad[1]*xcm_cell[1]*xcm_cell[1] + 2*(*treeit)->quad[2]*xcm_cell[0]*xcm_cell[1] )/(PI*rcm2cell*rcm2cell)*screening;
723 alpha[0] -= ((*treeit)->quad[0]*xcm_cell[0] + (*treeit)->quad[2]*xcm_cell[1])
724 /(rcm2cell*rcm2cell)/PI*screening;
725 alpha[1] -= ((*treeit)->quad[1]*xcm_cell[1] + (*treeit)->quad[2]*xcm_cell[0])
726 /(rcm2cell*rcm2cell)/PI*screening;
728 tmp = 4*((*treeit)->quad[0]*xcm_cell[0]*xcm_cell[0] + (*treeit)->quad[1]*xcm_cell[1]*xcm_cell[1]
729 + 2*(*treeit)->quad[2]*xcm_cell[0]*xcm_cell[1])/(rcm2cell*rcm2cell*rcm2cell)/PI*screening;
731 alpha[0] += tmp*xcm_cell[0];
732 alpha[1] += tmp*xcm_cell[1];
734 *kappa -= (*treeit)->mass*inv_area;
735 *phi -= (*treeit)->mass*inv_area*rcm2cell;
739 assert(count <= treeit.getNbranches());
740 }
while(treeit.TreeWalkStep(allowDescent));
1038template <
typename LensHaloType>
1039void TreeQuadHalos<LensHaloType>::printParticlesInBranch(
unsigned long number){
1044 if(tree->current->number == number){
1045 std::cout << tree->current->nparticles << std::endl;
1046 for(i=0;i<tree->current->nparticles;++i){
1047 std::cout << xp[tree->current->
particles[i]][0] <<
" " << xp[tree->current->
particles[i]][1] << std::endl;
1051 }
while(tree->WalkStep(
true));
1060template <
typename LensHaloType>
1061void TreeQuadHalos<LensHaloType>::printBranchs(
int level){
1068 if(tree->current->
level == level) decend =
false;
1070 }
while(tree->WalkStep(decend));
A LensPlane with a TreeQuad on it to calculate the deflection caused by field lenses.
Definition planes.h:35
A iterator class fore TreeStruct that allows for movement through the tree without changing anything ...
Definition qTreeNB.h:173
Box representing a branch in a tree. It has four children. Used in QTreeNB which is used in TreeQuad.
Definition qTreeNB.h:31
PosType r2crit_angle
the critical distance below which a branch is opened in the
Definition qTreeNB.h:84
PosType center[2]
center of mass
Definition qTreeNB.h:56
PosType quad[3]
quadropole moment of branch
Definition qTreeNB.h:80
int level
level in tree
Definition qTreeNB.h:59
PosType rmax
largest dimension of box
Definition qTreeNB.h:82
PosType boundary_p1[2]
bottom, left, back corner of box
Definition qTreeNB.h:62
IndexType * particles
array of particles in QBranchNB
Definition qTreeNB.h:48
IndexType Nbig_particles
the number of particles that aren't in children
Definition qTreeNB.h:52
PosType boundary_p2[2]
top, right, front corner of box
Definition qTreeNB.h:64
QTreeNB: Tree structure used for force calculation with particles (i.e. stars, Nbody or halos).
Definition qTreeNB.h:98
PType * xxp
Array of particle positions.
Definition qTreeNB.h:127