GLAMERDOC++
Gravitational Lensing Code Library
Loading...
Searching...
No Matches
quadTree.h
1
7//**********************************************************************************************************
8/*
9 * quadTree.cpp
10 *
11 */
12
13/*
14 * Programmer: R Ben Metcalf
15 */
16#ifndef QUAD_TREE_H_
17#define QUAD_TREE_H_
18
19//#include "utilities_slsim.h"
20//#include "utilities.h"
21#include "Tree.h"
22#include "qTreeNB.h"
23//#include "lens_halos.h"
24
25//short const treeNBdim = 2;
26
27
46template<typename PType>
48public:
50 PType *xpt
51 ,IndexType Npoints
52 ,float mass_fixed = -1
53 ,float size_fixed = -1
54 ,PosType my_inv_area = 0
55 ,int bucket = 5
56 ,PosType theta_force = 0.1
57 ,bool my_periodic_buffer = false
58 ,PosType my_inv_screening_scale = 0
59 ,PosType maximum_range = -1
60 );
61
63
64 void force2D(PosType const *ray,PosType *alpha,KappaType *kappa,KappaType *gamma
65 ,KappaType *phi) const;
66
67 void force2D_recur(const PosType *ray,PosType *alpha,KappaType *kappa
68 ,KappaType *gamma,KappaType *phi);
69
71 void neighbors(PosType ray[],PosType rmax,std::list<IndexType> &neighbors) const;
72 //void neighbors(PosType ray[],PosType rmax,std::vector<PType *> &neighbors) const;
73
74 void printParticlesInBranch(unsigned long number);
75
76 void printBranchs(int level = -1);
77
78protected:
79
80 PType *xxp;
81 bool MultiMass;
82 double mass_fixed = 0.0;
83 bool MultiRadius;
84 double size_fixed = 0.0;
85 double inv_area;
86
87 IndexType Nparticles;
88 //PosType sigma_background;
89 int Nbucket;
90
91 PosType force_theta;
92 PosType max_range;
93
94 std::unique_ptr<QTreeNB<PType> > tree;
95 std::vector<IndexType> index;
96
97 std::vector<PosType> workspace;
98
99 //bool haloON;
100 //LensHaloHndl *halos;
101
102 PosType realray[2];
103 int incell,incell2;
104
107 PosType inv_screening_scale2;
108 PosType original_xl; // x-axis size of simulation used for peridic buffering. Requrement that it top branch be square my make it differ from the size of top branch.
109 PosType original_yl; // x-axis size of simulation used for peridic buffering.
110
111 //QTreeNB<PType> * BuildQTreeNB(PType *xp,IndexType Nparticles,IndexType *particles);
112 void BuildQTreeNB(PType *xp,IndexType Nparticles);
113 void _BuildQTreeNB(IndexType nparticles,IndexType *particles);
114
115 inline short WhichQuad(PosType *x,QBranchNB &branch);
116
117 //inline bool atLeaf();
118 inline bool inbox(const PosType *ray,const PosType *p1,const PosType *p2){
119 return (ray[0]>=p1[0])*(ray[0]<=p2[0])*(ray[1]>=p1[1])*(ray[1]<=p2[1]);
120 }
121 //int cutbox(PosType *ray,PosType *p1,PosType *p2,float rmax);
122
123 void CalcMoments();
124 void rotate_coordinates(PosType **coord);
125
126 // Internal profiles for a Gaussian particle
127 inline PosType alpha_h(PosType r2s2,PosType sigma) const{
128 return (sigma > 0.0 ) ? ( exp(-0.5*r2s2) - 1.0 ) : -1.0;
129 }
130 inline PosType kappa_h(PosType r2s2,PosType sigma) const{
131 return 0.5*r2s2*exp(-0.5*r2s2);
132 }
133 inline PosType gamma_h(PosType r2s2,PosType sigma) const{
134 return (sigma > 0.0 ) ? (-2.0 + (2.0 + r2s2)*exp(-0.5*r2s2) ) : -2.0;
135 }
136 inline PosType phi_h(PosType r2s2,PosType sigma) const{
137 //ERROR_MESSAGE(); // not yet written
138 //exit(1);
139 return 0;
140 }
141
142
143 /* cubic B-spline kernel for particle profile
144
145 The lensing quantities are added to and a point mass is subtracted
146 */
147 inline void b_spline_profile(
148 PosType *xcm // vector in Mpc connecting ray to center of particle
149 ,PosType r // distance from center in Mpc
150 ,PosType Mass // mass in solar masses
151 ,PosType size // size scale in Mpc
152 ,PosType *alpha // deflection angle times Sigma_crit
153 ,KappaType *kappa // surface density
154 ,KappaType *gamma // shear times Sigma_crit
155 ,KappaType *phi
156 ) const {
157
158 PosType q = r/size;
159 PosType M,sigma;
160 if(q > 2){
161 sigma = 0;
162 M = 1;
163 }else{
164 PosType q2=q*q,q3=q2*q,q4=q2*q2,q5=q4*q;
165
166 sigma = (8 - 12*q + 6*q2 - q3)/4;
167 if(q > 1){
168 sigma *= 10/size/size/7/PI;
169 M = (-1 + 20*q2*(1 - q + 3*q2/8 - q3/20) )/7;
170 *phi += Mass*(-1232. + 1200*q2 - 800.*q3 + 225.*q4 - 24*q5 + 120*log(2./q) )/840/PI;
171 }else{
172 sigma = 10*( sigma - 1 + 3*q - 3*q2 + q3)/size/size/7/PI;
173 M = 10*q2*(1 - 3*q/4 + 3*q3/10)/7;
174
175 *phi += Mass*( phiintconst + 10*(q2/2 - 3*q4/4 + 3*q5/50)/7
176 )/PI;
177 }
178 }
179
180 PosType alpha_r,gt; // deflection * Sig_crit / Mass
181 alpha_r = (M-1)/PI/r;
182 gt = alpha_r/r - sigma;
183
184 alpha[0] -= Mass*alpha_r*xcm[0]/r;
185 alpha[1] -= Mass*alpha_r*xcm[1]/r;
186 gamma[0] -= gt*Mass*(xcm[0]*xcm[0]-xcm[1]*xcm[1])/r/r;
187 gamma[1] -= gt*Mass*2*xcm[0]*xcm[1]/r/r;
188 *kappa += Mass*sigma;
189 *phi -= Mass*log(r)/PI;
190 }
191
192 /* Exponential kernel for particle profile
193
194 The lensing quantities are added to and a point mass is subtracted
195 */
196 inline void exponential_profile(
197 PosType *xcm
198 ,PosType rcm2 // distance from center in Mpc
199 ,PosType Mass
200 ,PosType size // size scale in Mpc
201 ,PosType *alpha
202 ,KappaType *kappa
203 ,KappaType *gamma
204 ,KappaType *phi
205 ) const {
206
207
208 PosType prefac = Mass/rcm2/PI;
209 PosType arg1 = rcm2/(size*size);
210
211 PosType tmp = (alpha_h(arg1,size) + 1.0)*prefac;
212 alpha[0] += tmp*xcm[0];
213 alpha[1] += tmp*xcm[1];
214
215
216 *kappa += kappa_h(arg1,size)*prefac;
217
218 tmp = (gamma_h(arg1,size) + 2.0)*prefac/rcm2;
219
220 gamma[0] += 0.5*(xcm[0]*xcm[0]-xcm[1]*xcm[1])*tmp;
221 gamma[1] += xcm[0]*xcm[1]*tmp;
222
223 // TODO: makes sure the normalization of phi_h agrees with this
224 //*phi += (phi_h(arg1,size) + 0.5*log(rcm2))*prefac*rcm2;
225 }
226
227 //QTreeNB<PType> * rotate_simulation(PType *xp,IndexType Nparticles,IndexType *particles
228 // ,PosType **coord,PosType theta,float *rsph,float *mass
229 // ,bool MultiRadius,bool MultiMass);
230 //QTreeNB<PType> * rotate_project(PType *xp,IndexType Nparticles,IndexType *particles
231 // ,PosType **coord,PosType theta,float *rsph,float *mass
232 // ,bool MultiRadius,bool MultiMass);
233 void cuttoffscale(QTreeNB<PType> * tree,PosType *theta);
234
235 void walkTree_recur(QBranchNB *branch,PosType const *ray,PosType *alpha,KappaType *kappa,KappaType *gamma,KappaType *phi);
236
237 void walkTree_iter(QBiterator<PType> &treeit, PosType const *ray,PosType *alpha,KappaType *kappa
238 ,KappaType *gamma,KappaType *phi) const;
239
240 PosType phiintconst;
241};
242
243
244
247template<typename PType>
249 PType *xpt
250 ,IndexType Npoints
251 ,float mass_fixed
252 ,float size_fixed
253 ,PosType my_inv_area
254 ,int bucket
255 ,PosType theta_force
256 ,bool my_periodic_buffer
257 ,PosType my_inv_screening_scale
258 ,PosType maximum_range
259
260):
261xxp(xpt)
262,inv_area(my_inv_area)
263,Nparticles(Npoints)
264,Nbucket(bucket)
265,force_theta(theta_force)
266,max_range(maximum_range)
267,periodic_buffer(my_periodic_buffer)
268,inv_screening_scale2(my_inv_screening_scale*my_inv_screening_scale)
269{
270 index.resize(Npoints);
271 IndexType ii;
272 if(mass_fixed <= 0 ) MultiMass = true; else MultiMass = false;
273 if(size_fixed <= 0 ) MultiRadius = true; else MultiRadius = false;
274
275 for(ii=0;ii<Npoints;++ii) index[ii] = ii;
276
277 if(Npoints > 0){
278 BuildQTreeNB(xxp,Npoints);
279 CalcMoments();
280 }
281
282 phiintconst = (120*log(2.) - 631.)/840 + 19./70;
283
284 return;
285}
286
288template<typename PType>
290{
291 if(Nparticles == 0) return;
292 return;
293}
294
295template<typename PType>
296//QTreeNB<PType> * TreeQuadParticles<PType>::BuildQTreeNB(PType *xxp,IndexType Nparticles,IndexType *particles){
297void TreeQuadParticles<PType>::BuildQTreeNB(PType *xxp,IndexType Nparticles){
298 IndexType i;
299 short j;
300 PosType p1[2],p2[2];
301
302 for(j=0;j<2;++j){
303 p1[j]=xxp[0][j];
304 p2[j]=xxp[0][j];
305 }
306
307 // Find borders that enclose all particles
308 for(i=0;i<Nparticles;++i){
309 for(j=0;j<2;++j){
310 if(xxp[i][j] < p1[j] ) p1[j]=xxp[i][j];
311 if(xxp[i][j] > p2[j] ) p2[j]=xxp[i][j];
312 }
313 }
314
315 if(Nparticles == 1){
316 p1[0]=-0.25;
317 p1[1]=-0.25;
318 p2[0]=0.25;
319 p2[1]=0.25;
320 }
321
322 // store true dimensions of simulation
323 PosType lengths[2] = {p2[0]-p1[0],p2[1]-p1[1]};
324 original_xl = lengths[0];
325 original_yl = lengths[1];
326
327 if(lengths[0] == 0 || lengths[1] == 0){
328 throw std::invalid_argument("particles in same place.");
329 }
330
331 // If region is not square, make it square.
332 j = lengths[0] > lengths[1] ? 1 : 0;
333 p2[j] = p1[j] + lengths[!j];
334
335 /* Initialize tree root */
336 //tree = new QTreeNB<PType>(xxp,particles,Nparticles,p1,p2);
337 tree.reset( new QTreeNB<PType>(xxp,index.data(),Nparticles,p1,p2) );
338
339 /* build the tree */
340 workspace.resize(Nparticles);
341 _BuildQTreeNB(Nparticles,index.data());
342 workspace.clear();
343 workspace.shrink_to_fit();
344
345 /* visit every branch to find center of mass and cutoff scale */
346 tree->moveTop();
347
348 //return tree;
349 return;
350}
351
353template<typename PType>
354inline short TreeQuadParticles<PType>::WhichQuad(PosType *x,QBranchNB &branch){
355 return (x[0] < branch.center[0]) + 2*(x[1] < branch.center[1]);
356}
357
359template<typename PType>
360void TreeQuadParticles<PType>::_BuildQTreeNB(IndexType nparticles,IndexType *particles){
361
362 QBranchNB *cbranch = tree->current; // pointer to current branch
363 IndexType i,j,cut,cut2;
364
365 cbranch->center[0] = (cbranch->boundary_p1[0] + cbranch->boundary_p2[0])/2;
366 cbranch->center[1] = (cbranch->boundary_p1[1] + cbranch->boundary_p2[1])/2;
367 cbranch->quad[0] = cbranch->quad[1]=cbranch->quad[2]=0;
368 cbranch->mass = 0.0;
369
370 double theta_range = 2*force_theta;
371 if(max_range > 0){
372 double boxsize = 1.732*(cbranch->boundary_p2[0] - cbranch->boundary_p1[0]);
373 theta_range = boxsize / MAX(sqrt(cbranch->center[0]*cbranch->center[0]
374 + cbranch->center[1]*cbranch->center[1] )
375 - max_range, boxsize );
376 }
377
378 // leaf case
379 if(cbranch->nparticles <= Nbucket
380 || force_theta > theta_range
381 ){
382 PosType r;
383 cbranch->Nbig_particles = 0;
384 for(i=0;i<cbranch->nparticles;++i){
385 r = xxp[particles[i]*MultiRadius].size();
386 if(r < (cbranch->boundary_p2[0]-cbranch->boundary_p1[0])) ++cbranch->Nbig_particles;
387 }
388 if(cbranch->Nbig_particles){
389 //cbranch->big_particles = new IndexType[cbranch->Nbig_particles];
390 cbranch->big_particles.reset(new IndexType[cbranch->Nbig_particles]);
391
392 for(i=0,j=0;i<cbranch->nparticles;++i){
393 r = xxp[particles[i]*MultiRadius].size();
394 if(r < (cbranch->boundary_p2[0]-cbranch->boundary_p1[0])) cbranch->big_particles[j++] = particles[i];
395 }
396 }else{
397 cbranch->big_particles.reset(nullptr);
398 }
399
400 return;
401 }
402
403 // find particles too big to be in children
404
405 //PosType *x = new PosType[cbranch->nparticles];
406 PosType *x = workspace.data();
407
408 cbranch->Nbig_particles=0;
409
410 if(MultiRadius){
411 // store the particles that are too large to be in a child at the end of the list of particles in cbranch
412 for(i=0;i<cbranch->nparticles;++i){
413 x[i] = xxp[particles[i]].size();
414 }
415 PosType maxsize = (cbranch->boundary_p2[0]-cbranch->boundary_p1[0])/2;
416
417 // sort particles in size
418 //quicksort(particles,x,cbranch->nparticles);
419 Utilities::quickPartition(maxsize,&cut,particles,x,cbranch->nparticles);
420
421 if(cut < cbranch->nparticles){
422 if(tree->atTop()){
423 cbranch->Nbig_particles = cut2 = cbranch->nparticles-cut;
424 }else{
425 Utilities::quickPartition(2*maxsize,&cut2,&particles[cut],&x[cut],cbranch->nparticles-cut);
426 cbranch->Nbig_particles = cut2;
427 }
428
429 cbranch->big_particles.reset(new IndexType[cbranch->Nbig_particles]);
430 for(i=cut;i<(cut+cut2);++i) cbranch->big_particles[i-cut] = particles[i];
431 }
432
433 }else{
434 //x[0] = xxp[0].Size();
435 x[0] = size_fixed;
436 if(x[0] > (cbranch->boundary_p2[0]-cbranch->boundary_p1[0])/2
437 && x[0] < (cbranch->boundary_p2[0]-cbranch->boundary_p1[0])){
438 cbranch->Nbig_particles = cbranch->nparticles;
439 //cbranch->big_particles = cbranch->particles;
440 cbranch->big_particles.reset(new IndexType[cbranch->Nbig_particles]);
441 for(i=0;i<cbranch->nparticles;++i) cbranch->big_particles[i] = cbranch->particles[particles[i]];
442 }
443 }
444
445 assert( cbranch->nparticles >= cbranch->Nbig_particles );
446 IndexType NpInChildren = cbranch->nparticles;// - cbranch->Nbig_particles;
447 assert(NpInChildren >= 0);
448
449 if(NpInChildren == 0){
450 //delete[] x;
451 return;
452 }
453
454 IndexType cutx,cuty;
455 PosType xcut,ycut;
456
457 QBranchNB *child0 = new QBranchNB(cbranch);
458 QBranchNB *child1 = new QBranchNB(cbranch);
459 QBranchNB *child2 = new QBranchNB(cbranch);
460 QBranchNB *child3 = new QBranchNB(cbranch);
461
462 tree->attachChildrenToCurrent(child0,child1,child2,child3);
463
464 // initialize boundaries of children
465
466 child0->boundary_p1[0]=cbranch->center[0];
467 child0->boundary_p1[1]=cbranch->center[1];
468 child0->boundary_p2[0]=cbranch->boundary_p2[0];
469 child0->boundary_p2[1]=cbranch->boundary_p2[1];
470
471 child1->boundary_p1[0]=cbranch->boundary_p1[0];
472 child1->boundary_p1[1]=cbranch->center[1];
473 child1->boundary_p2[0]=cbranch->center[0];
474 child1->boundary_p2[1]=cbranch->boundary_p2[1];
475
476 child2->boundary_p1[0]=cbranch->center[0];
477 child2->boundary_p1[1]=cbranch->boundary_p1[1];
478 child2->boundary_p2[0]=cbranch->boundary_p2[0];
479 child2->boundary_p2[1]=cbranch->center[1];
480
481 child3->boundary_p1[0]=cbranch->boundary_p1[0];
482 child3->boundary_p1[1]=cbranch->boundary_p1[1];
483 child3->boundary_p2[0]=cbranch->center[0];
484 child3->boundary_p2[1]=cbranch->center[1];
485
486
487 // **** makes sure force does not require nbucket at leaf
488
489 xcut = cbranch->center[0];
490 ycut = cbranch->center[1];
491
492 // divide along y direction
493 for(i=0;i<NpInChildren;++i) x[i] = tree->xxp[particles[i]][1];
494 Utilities::quickPartition(ycut,&cuty,particles,x,NpInChildren);
495
496 if(cuty > 0){
497 // divide first group in the x direction
498 for(i=0;i<cuty;++i) x[i] = tree->xxp[particles[i]][0];
499 Utilities::quickPartition(xcut,&cutx,particles,x,cuty);
500
501 child3->nparticles=cutx;
502 assert(child3->nparticles >= 0);
503 if(child3->nparticles > 0)
504 child3->particles = particles;
505 else child3->particles = NULL;
506
507 child2->nparticles = cuty - cutx;
508 assert(child2->nparticles >= 0);
509 if(child2->nparticles > 0)
510 child2->particles = &particles[cutx];
511 else child2->particles = NULL;
512
513 }else{
514 child3->nparticles = 0;
515 child3->particles = NULL;
516
517 child2->nparticles = 0;
518 child2->particles = NULL;
519 }
520
521 if(cuty < NpInChildren){
522 // divide second group in the x direction
523 for(i=cuty;i<NpInChildren;++i) x[i-cuty] = tree->xxp[particles[i]][0];
524 Utilities::quickPartition(xcut,&cutx,&particles[cuty],x,NpInChildren-cuty);
525
526 child1->nparticles=cutx;
527 assert(child1->nparticles >= 0);
528 if(child1->nparticles > 0)
529 child1->particles = &particles[cuty];
530 else child1->particles = NULL;
531
532 child0->nparticles=NpInChildren - cuty - cutx;
533 assert(child0->nparticles >= 0);
534 if(child0->nparticles > 0)
535 child0->particles = &particles[cuty + cutx];
536 else child0->particles = NULL;
537
538 }else{
539 child1->nparticles = 0;
540 child1->particles = NULL;
541
542 child0->nparticles = 0;
543 child0->particles = NULL;
544 }
545
546 //delete[] x;
547
548 tree->moveToChild(0);
549 _BuildQTreeNB(child0->nparticles,child0->particles);
550 tree->moveUp();
551
552 tree->moveToChild(1);
553 _BuildQTreeNB(child1->nparticles,child1->particles);
554 tree->moveUp();
555
556 tree->moveToChild(2);
557 _BuildQTreeNB(child2->nparticles,child2->particles);
558 tree->moveUp();
559
560 tree->moveToChild(3);
561 _BuildQTreeNB(child3->nparticles,child3->particles);
562 tree->moveUp();
563
564 return;
565}
566
567// calculates moments of the mass and the cutoff scale for each box
568template<typename PType>
570
571 //*** make compatable
572 IndexType i;
573 PosType rcom,xcm[2],xcut;
574 QBranchNB *cbranch;
575 PosType tmp;
576 double absmass; // absolute magnitude of mass
577
578 tree->moveTop();
579 do{
580 cbranch=tree->current; /* pointer to current branch */
581
582 cbranch->rmax = sqrt( pow(cbranch->boundary_p2[0]-cbranch->boundary_p1[0],2)
583 + pow(cbranch->boundary_p2[1]-cbranch->boundary_p1[1],2) );
584
585 // calculate mass
586 for(i=0,cbranch->mass=0,absmass=0;i<cbranch->nparticles;++i){
587 cbranch->mass += xxp[cbranch->particles[i]*MultiMass].mass();
588 absmass += fabs(xxp[cbranch->particles[i]*MultiMass].mass());
589 }
590 // calculate center of mass
591 cbranch->center[0]=cbranch->center[1]=0;
592 for(i=0;i<cbranch->nparticles;++i){
593 tmp = fabs(xxp[cbranch->particles[i]*MultiMass].mass());
594
595 //tmp = haloON ? halos[cbranch->particles[i]*MultiMass].mass : masses[cbranch->particles[i]*MultiMass];
596 cbranch->center[0] += tmp*tree->xxp[cbranch->particles[i]][0]/absmass;
597 cbranch->center[1] += tmp*tree->xxp[cbranch->particles[i]][1]/absmass;
598 }
600 // calculate quadropole moment of branch
602 cbranch->quad[0]=cbranch->quad[1]=cbranch->quad[2]=0;
603 for(i=0;i<cbranch->nparticles;++i){
604 xcm[0]=tree->xxp[cbranch->particles[i]][0]-cbranch->center[0];
605 xcm[1]=tree->xxp[cbranch->particles[i]][1]-cbranch->center[1];
606 xcut = pow(xcm[0],2) + pow(xcm[1],2);
607 tmp = xxp[cbranch->particles[i]*MultiMass].mass();
608
609 cbranch->quad[0] += (xcut-2*xcm[0]*xcm[0])*tmp;
610 cbranch->quad[1] += (xcut-2*xcm[1]*xcm[1])*tmp;
611 cbranch->quad[2] += -2*xcm[0]*xcm[1]*tmp;
612 }
613
614 // largest distance from center of mass of cell
615 for(i=0,rcom=0.0;i<2;++i) rcom += ( pow(cbranch->center[i]-cbranch->boundary_p1[i],2) > pow(cbranch->center[i]-cbranch->boundary_p2[i],2) ) ?
616 pow(cbranch->center[i]-cbranch->boundary_p1[i],2) : pow(cbranch->center[i]-cbranch->boundary_p2[i],2);
617
618 rcom=sqrt(rcom);
619
620 if(force_theta > 0.0){
621 cbranch->r2crit_angle = 1.15470*rcom/(force_theta);
622 cbranch->r2crit_angle *= cbranch->r2crit_angle;
623 }else cbranch->r2crit_angle=1.0e100;
624
625 }while(tree->WalkStep(true));
626
627 return;
628}
629
631template<typename PType>
633 IndexType i;
634 short j;
635 PosType tmp[3];
636
637 /* rotate particle positions */
638 for(i=0;i<tree->top->nparticles;++i){
639 for(j=0;j<3;++j) tmp[j]=0.0;
640 for(j=0;j<3;++j){
641 tmp[0]+=coord[0][j]*xxp[i][j];
642 tmp[1]+=coord[1][j]*xxp[i][j];
643 tmp[2]+=coord[2][j]*xxp[i][j];
644 }
645 for(j=0;j<3;++j) xxp[i][j]=tmp[j];
646 }
647 return;
648}
649
670template<typename PType>
671void TreeQuadParticles<PType>::force2D(const PosType *ray,PosType *alpha,KappaType *kappa,KappaType *gamma,KappaType *phi) const{
672
673 alpha[0]=alpha[1]=gamma[0]=gamma[1]=gamma[2]=0.0;
674 *kappa=*phi=0.0;
675
676 if(Nparticles == 0) return;
677
678 assert(tree);
679 QBiterator<PType> it(tree);
680
681 if(periodic_buffer){
682 PosType tmp_ray[2];
683
684 for(int i = -1;i<2;++i){
685 for(int j = -1;j<2;++j){
686 tmp_ray[0] = ray[0] + i*original_xl;
687 tmp_ray[1] = ray[1] + j*original_yl;
688 walkTree_iter(it,tmp_ray,alpha,kappa,gamma,phi);
689 }
690 }
691 }else{
692 walkTree_iter(it,ray,alpha,kappa,gamma,phi);
693 }
694
695 // Subtract off uniform mass sheet to compensate for the extra mass
696 // added to the universe in the halos.
697 //alpha[0] -= ray[0]*sigma_background*(inv_screening_scale2 == 0);
698 //alpha[1] -= ray[1]*sigma_background*(inv_screening_scale2 == 0);
699 //*kappa -= sigma_background;
700
701 return;
702}
703
706template<typename PType>
707void TreeQuadParticles<PType>::neighbors(PosType ray[],PosType rmax,std::list<IndexType> &neighbors) const{
708 QBiterator<PType> it(tree);
709 neighbors.clear();
710
711 PosType r2 = rmax*rmax;
712 bool decend=true;
713 it.movetop();
714 do{
715 int cut = Utilities::cutbox(ray,(*it)->boundary_p1,(*it)->boundary_p2,rmax);
716 decend = true;
717
718 if(cut == 0){ // box outside circle
719 decend = false;
720 }else if(cut == 1){ // whole box inside circle
721 for(int i=0;i<(*it)->nparticles;++i) neighbors.push_back((*it)->particles[i]);
722 decend = false;
723 }else if((*it)->child0 == NULL){ // at leaf
724 for(int i=0;i<(*it)->nparticles;++i){
725 if( (tree->xxp[(*it)->particles[i]][0] - ray[0])*(tree->xxp[(*it)->particles[i]][0] - ray[0])
726 + (tree->xxp[(*it)->particles[i]][1] - ray[1])*(tree->xxp[(*it)->particles[i]][1] - ray[1]) < r2) neighbors.push_back((*it)->particles[i]);
727 }
728 decend = false;
729 }
730 }while(it.TreeWalkStep(decend));
731
732}
733
734template<typename PType>
736 QBiterator<PType> &treeit,
737 const PosType *ray
738 ,PosType *alpha
739 ,KappaType *kappa
740 ,KappaType *gamma
741 ,KappaType *phi
742 ) const {
743
744 PosType xcm[2],rcm2cell,rcm2,tmp,boxsize2;
745 IndexType i;
746 bool allowDescent=true;
747 unsigned long count=0,tmp_index;
748 PosType prefac;
749 //bool notscreen = true;
750
751 assert(tree);
752
753 treeit.movetop();
754 //tree->moveTop();
755 do{
756 ++count;
757 allowDescent=false;
758
759 /*
760 if(inv_screening_scale2 != 0) notscreen = BoxIntersectCircle(ray,3*sqrt(1.0/inv_screening_scale2)
761 ,(*treeit)->boundary_p1
762 ,(*treeit)->boundary_p2);
763 else notscreen = true;
764 */
765 //if(tree->current->nparticles > 0)
766 if((*treeit)->nparticles > 0)
767 {
768
769 xcm[0]=(*treeit)->center[0]-ray[0];
770 xcm[1]=(*treeit)->center[1]-ray[1];
771
772 rcm2cell = xcm[0]*xcm[0] + xcm[1]*xcm[1];
773
774 boxsize2 = ((*treeit)->boundary_p2[0]-(*treeit)->boundary_p1[0])*((*treeit)->boundary_p2[0]-(*treeit)->boundary_p1[0]);
775
776 if( rcm2cell < ((*treeit)->rcrit_angle)*((*treeit)->rcrit_angle) || rcm2cell < 5.83*boxsize2)
777 {
778
779 // includes rcrit_particle constraint
780 allowDescent=true;
781
782
783 // Treat all particles in a leaf as a point particle
784 if(treeit.atLeaf())
785 {
786
787 for(i = 0 ; i < (*treeit)->nparticles ; ++i)
788 {
789
790 xcm[0] = tree->xp[(*treeit)->particles[i]][0] - ray[0];
791 xcm[1] = tree->xp[(*treeit)->particles[i]][1] - ray[1];
792
793 rcm2 = xcm[0]*xcm[0] + xcm[1]*xcm[1];
794 double screening = exp(-rcm2*inv_screening_scale2);
795 if(rcm2 < 1e-20) rcm2 = 1e-20;
796
797 //tmp_index = MultiMass*(*treeit)->particles[i];
798
799 //if(haloON){ prefac = halos[tmp_index]->get_mass(); }
800 //else{ prefac = masses[tmp_index]; }
801
802 double mass;
803 if(MultiMass) mass = xxp[(*treeit)->particles[i]].Mass();
804 else mass = mass_fixed;
805
806 prefac = mass/rcm2/PI*screening;
807 tmp = -mass*( screening/rcm2/PI - inv_area);
808
809 alpha[0] += tmp*xcm[0];
810 alpha[1] += tmp*xcm[1];
811
812 tmp = -2.0*prefac/rcm2;
813
814 gamma[0] += 0.5*(xcm[0]*xcm[0]-xcm[1]*xcm[1])*tmp;
815 gamma[1] += xcm[0]*xcm[1]*tmp;
816
817 *kappa -= mass*inv_area;
818 *phi += (prefac*log(rcm2) - mass*inv_area)*rcm2*0.5;
819
820 } // end of for
821 } // end of if(tree->atLeaf())
822
823
824 // Find the particles that intersect with ray and add them individually.
825 if(rcm2cell < 5.83*boxsize2)
826 {
827
828 for(i = 0 ; i < (*treeit)->Nbig_particles ; ++i)
829 {
830
831 tmp_index = (*treeit)->big_particles[i];
832
833 xcm[0] = tree->xp[tmp_index][0] - ray[0];
834 xcm[1] = tree->xp[tmp_index][1] - ray[1];
835
836 rcm2 = xcm[0]*xcm[0] + xcm[1]*xcm[1];
837
838 if(rcm2 < 1e-20) rcm2 = 1e-20;
839
840 //PosType size = sizes[tmp_index*MultiRadius];
841 PosType size = xxp[tmp_index*MultiRadius].size();
842
843 // intersecting, subtract the point particle
844 if(rcm2 < 4*size*size)
845 {
846 b_spline_profile(xcm,sqrt(rcm2),xxp[MultiMass*tmp_index].Mass(),size,alpha,kappa,gamma,phi);
847 }
848
849 }
850 }
851
852 }
853 else
854 { // use whole cell
855
856 allowDescent=false;
857
858 // monopole
859 double screening = exp(-rcm2cell*inv_screening_scale2);
860 //double tmp = -1.0*(*treeit)->mass/rcm2cell/PI*screening;
861 double tmp = (*treeit)->mass*( inv_area - screening/rcm2cell/PI );
862
863 alpha[0] += tmp*xcm[0];
864 alpha[1] += tmp*xcm[1];
865
866 { // taken out to speed up
867 tmp=-2.0*(*treeit)->mass/PI/rcm2cell/rcm2cell*screening;
868 gamma[0] += 0.5*(xcm[0]*xcm[0]-xcm[1]*xcm[1])*tmp;
869 gamma[1] += xcm[0]*xcm[1]*tmp;
870
871 *phi += 0.5*(*treeit)->mass*log( rcm2cell )/PI*screening;
872 *phi -= 0.5*( (*treeit)->quad[0]*xcm[0]*xcm[0] + (*treeit)->quad[1]*xcm[1]*xcm[1] + 2*(*treeit)->quad[2]*xcm[0]*xcm[1] )/(PI*rcm2cell*rcm2cell)*screening;
873 }
874
875 // quadrapole contribution
876 // the kappa and gamma are not calculated to this order
877 alpha[0] -= ((*treeit)->quad[0]*xcm[0] + (*treeit)->quad[2]*xcm[1])
878 /(rcm2cell*rcm2cell)/PI*screening;
879 alpha[1] -= ((*treeit)->quad[1]*xcm[1] + (*treeit)->quad[2]*xcm[0])
880 /(rcm2cell*rcm2cell)/PI*screening;
881
882 tmp = 4*((*treeit)->quad[0]*xcm[0]*xcm[0] + (*treeit)->quad[1]*xcm[1]*xcm[1]
883 + 2*(*treeit)->quad[2]*xcm[0]*xcm[1])/(rcm2cell*rcm2cell*rcm2cell)/PI*screening;
884
885 alpha[0] += tmp*xcm[0];
886 alpha[1] += tmp*xcm[1];
887
888 *kappa -= (*treeit)->mass * inv_area;
889 *phi -= 0.5*(*treeit)->mass*inv_area;
890 }
891 }
892 }while(treeit.TreeWalkStep(allowDescent));
893
894
895 // Subtract off uniform mass sheet to compensate for the extra mass
896 // added to the universe in the halos.
897 //alpha[0] -= ray[0]*sigma_background*(inv_screening_scale2 == 0.0);
898 //alpha[1] -= ray[1]*sigma_background*(inv_screening_scale2 == 0.0);
899 //{ // taken out to speed up
900 // *kappa -= sigma_background;
901 // // *phi -= sigma_background * sigma_background ;
902 //}
903
904 return;
905}
906
907
932template<typename PType>
933void TreeQuadParticles<PType>::force2D_recur(const PosType *ray,PosType *alpha,KappaType *kappa,KappaType *gamma,KappaType *phi){
934
935
936 alpha[0]=alpha[1]=gamma[0]=gamma[1]=gamma[2]=0.0;
937 *kappa=*phi=0.0;
938
939 if(Nparticles == 0) return;
940 assert(tree);
941
942 //walkTree_recur(tree->top,ray,&alpha[0],kappa,&gamma[0],phi);
943
944 if(periodic_buffer){
945 PosType tmp_ray[2],tmp_c[2];
946
947 // for points outside of primary zone shift to primary zone
948 //if(inbox(ray,tree->top->boundary_p1,tree->top->boundary_p2)){
949 tmp_c[0] = ray[0];
950 tmp_c[1] = ray[1];
951 /*}else{
952 int di[2];
953 PosType center[2] = { (tree->top->boundary_p1[0] + tree->top->boundary_p2[0])/2 ,
954 (tree->top->boundary_p1[1] + tree->top->boundary_p2[1])/2 };
955
956 di[0] = (int)( 2*(ray[0] - center[0])/lx );
957 di[1] = (int)( 2*(ray[1] - center[1])/ly );
958
959 di[0] = (di[0] > 0) ? (di[0] + 1)/2 : (di[0] - 1)/2;
960 di[1] = (di[1] > 0) ? (di[1] + 1)/2 : (di[1] - 1)/2;
961
962 tmp_c[0] = ray[0] - lx * di[0];
963 tmp_c[1] = ray[1] - ly * di[1];
964
965 assert(inbox(tmp_c,tree->top->boundary_p1,tree->top->boundary_p2));
966 }*/
967
968 for(int i = -1;i<2;++i){
969 for(int j = -1;j<2;++j){
970 tmp_ray[0] = tmp_c[0] + i*original_xl;
971 tmp_ray[1] = tmp_c[1] + j*original_yl;
972 walkTree_recur(tree->top,tmp_ray,alpha,kappa,gamma,phi);
973 }
974 }
975 }else{
976 walkTree_recur(tree->top,ray,alpha,kappa,gamma,phi);
977 }
978
979 // Subtract off uniform mass sheet to compensate for the extra mass
980 // added to the universe in the halos.
981 //alpha[0] -= ray[0]*sigma_background*(inv_screening_scale2 == 0);
982 //alpha[1] -= ray[1]*sigma_background*(inv_screening_scale2 == 0);
983
984 //*kappa -= sigma_background;
985
986 return;
987}
988
989
990template<typename PType>
991void TreeQuadParticles<PType>::walkTree_recur(QBranchNB *branch,PosType const *ray,PosType *alpha,KappaType *kappa,KappaType *gamma, KappaType *phi){
992
993 PosType xcm[2],rcm2cell,rcm2,tmp,boxsize2;
994 IndexType i;
995 std::size_t tmp_index;
996 PosType prefac;
997 /*bool notscreen = true;
998
999 if(inv_screening_scale2 != 0) notscreen = BoxIntersectCircle(ray,3*sqrt(1.0/inv_screening_scale2), branch->boundary_p1, branch->boundary_p2);
1000 */
1001 if(branch->nparticles > 0)
1002 {
1003 xcm[0]=branch->center[0]-ray[0];
1004 xcm[1]=branch->center[1]-ray[1];
1005
1006 rcm2cell = xcm[0]*xcm[0] + xcm[1]*xcm[1];
1007
1008 boxsize2 = (branch->boundary_p2[0]-branch->boundary_p1[0])*(branch->boundary_p2[0]-branch->boundary_p1[0]);
1009
1010 if( rcm2cell < branch->r2crit_angle || rcm2cell < 5.83*boxsize2)
1011 {
1012
1013 // Treat all particles in a leaf as a point particle
1014 if(tree->atLeaf(branch))
1015 {
1016
1017 for(i = 0 ; i < branch->nparticles ; ++i){
1018
1019 xcm[0] = tree->xxp[branch->particles[i]][0] - ray[0];
1020 xcm[1] = tree->xxp[branch->particles[i]][1] - ray[1];
1021
1022 rcm2 = xcm[0]*xcm[0] + xcm[1]*xcm[1];
1023 double screening = exp(-rcm2*inv_screening_scale2);
1024 if(rcm2 < 1e-20) rcm2 = 1e-20;
1025
1026 tmp_index = MultiMass*branch->particles[i];
1027
1028 //if(haloON ) { prefac = halos[tmp_index]->get_mass(); }
1029 //else{ prefac = masses[tmp_index]; }
1030 double mass = xxp[tmp_index].mass();
1031 prefac = mass*screening/rcm2/PI;
1032 //prefac /= rcm2*PI/screening;
1033
1034
1035 alpha[0] += (inv_area*mass - prefac)*xcm[0];
1036 alpha[1] += (inv_area*mass - prefac)*xcm[1];
1037
1038 {
1039 tmp = -2.0*prefac/rcm2;
1040
1041 gamma[0] += 0.5*(xcm[0]*xcm[0]-xcm[1]*xcm[1])*tmp;
1042 gamma[1] += xcm[0]*xcm[1]*tmp;
1043
1044 *kappa -= mass*inv_area;
1045 *phi += prefac*rcm2*0.5*log(rcm2) - mass*inv_area*rcm2/2;
1046 }
1047 }
1048 }
1049
1050 // Find the particles that intersect with ray and add them individually.
1051 if(rcm2cell < 5.83*boxsize2)
1052 {
1053
1054 for(i = 0 ; i < branch->Nbig_particles ; ++i)
1055 {
1056
1057 tmp_index = branch->big_particles[i];
1058
1059 xcm[0] = tree->xxp[tmp_index][0] - ray[0];
1060 xcm[1] = tree->xxp[tmp_index][1] - ray[1];
1061 rcm2 = xcm[0]*xcm[0] + xcm[1]*xcm[1];
1062
1064 if(rcm2 < 1e-20) rcm2 = 1e-20;
1065
1066 PosType size = xxp[tmp_index*MultiRadius].size();
1067
1068 // intersecting, subtract the point particle
1069 if(rcm2 < 4*size*size)
1070 {
1071
1072 b_spline_profile(xcm,sqrt(rcm2),xxp[MultiMass*tmp_index].mass(),size,alpha,kappa,gamma,phi);
1073
1074 }
1075
1076 }
1077 }
1078
1079 if(branch->child0 != NULL)
1080 walkTree_recur(branch->child0,&ray[0],&alpha[0],kappa,&gamma[0],&phi[0]);
1081 if(branch->child1 != NULL)
1082 walkTree_recur(branch->child1,&ray[0],&alpha[0],kappa,&gamma[0],&phi[0]);
1083 if(branch->child2 != NULL)
1084 walkTree_recur(branch->child2,&ray[0],&alpha[0],kappa,&gamma[0],&phi[0]);
1085 if(branch->child3 != NULL)
1086 walkTree_recur(branch->child3,&ray[0],&alpha[0],kappa,&gamma[0],&phi[0]);
1087
1088 }
1089 else
1090 { // use whole cell
1091
1092 double screening = exp(-rcm2cell*inv_screening_scale2);
1093 double tmp = branch->mass*inv_area - branch->mass/rcm2cell/PI*screening;
1094
1095 alpha[0] += tmp*xcm[0];
1096 alpha[1] += tmp*xcm[1];
1097
1098 { // taken out to speed up
1099 tmp=-2.0*branch->mass/PI/rcm2cell/rcm2cell*screening;
1100 gamma[0] += 0.5*(xcm[0]*xcm[0]-xcm[1]*xcm[1])*tmp;
1101 gamma[1] += xcm[0]*xcm[1]*tmp;
1102
1103 *phi += 0.5*tree->current->mass*log( rcm2cell )/PI*screening;
1104 *phi -= 0.5*( tree->current->quad[0]*xcm[0]*xcm[0] + tree->current->quad[1]*xcm[1]*xcm[1] + 2*tree->current->quad[2]*xcm[0]*xcm[1] )/(PI*rcm2cell*rcm2cell)*screening;
1105 }
1106
1107 // quadrapole contribution
1108 // the kappa and gamma are not calculated to this order
1109 alpha[0] -= (branch->quad[0]*xcm[0] + branch->quad[2]*xcm[1])
1110 /(rcm2cell*rcm2cell)/PI*screening;
1111 alpha[1] -= (branch->quad[1]*xcm[1] + branch->quad[2]*xcm[0])
1112 /(rcm2cell*rcm2cell)/PI*screening;
1113
1114 tmp = 4*(branch->quad[0]*xcm[0]*xcm[0] + branch->quad[1]*xcm[1]*xcm[1]
1115 + 2*branch->quad[2]*xcm[0]*xcm[1])/(rcm2cell*rcm2cell*rcm2cell)/PI*screening;
1116
1117 alpha[0] += tmp*xcm[0];
1118 alpha[1] += tmp*xcm[1];
1119
1120 *kappa -= inv_area * branch->mass;
1121 *phi -= 0.5*branch->mass*rcm2cell*inv_area;
1122
1123 return;
1124 }
1125
1126 }
1127 return;
1128}
1129
1133template<typename PType>
1135 unsigned long i;
1136
1137 tree->moveTop();
1138 do{
1139 if(tree->current->number == number){
1140 std::cout << tree->current->nparticles << std::endl;
1141 for(i=0;i<tree->current->nparticles;++i){
1142 std::cout << xxp[tree->current->particles[i]][0] << " "
1143 << xxp[tree->current->particles[i]][1] << std::endl;
1144 }
1145 return;
1146 }
1147 }while(tree->WalkStep(true));
1148
1149 return;
1150}
1155template<typename PType>
1157
1158 bool decend = true;
1159 tree->moveTop();
1160 do{
1161 std::cout << tree->current->boundary_p1[0] << " " << tree->current->boundary_p1[1] << " "
1162 << tree->current->boundary_p2[0] << " " << tree->current->boundary_p2[1] << std::endl;
1163 if(tree->current->level == level) decend = false;
1164 else decend = true;
1165 }while(tree->WalkStep(decend));
1166
1167 return;
1168};
1169
1170#endif /* QUAD_TREE_H_ */
A iterator class fore TreeStruct that allows for movement through the tree without changing anything ...
Definition qTreeNB.h:173
TreeQuadParticles is a class for calculating the deflection, kappa and gamma by tree method.
Definition quadTree.h:47
void force2D(PosType const *ray, PosType *alpha, KappaType *kappa, KappaType *gamma, KappaType *phi) const
Force2D calculates the defection, convergence and shear using the plane-lens approximation....
Definition quadTree.h:671
void _BuildQTreeNB(IndexType nparticles, IndexType *particles)
tree must be created and first branch must be set before start
Definition quadTree.h:360
~TreeQuadParticles()
Particle positions and other data are not destroyed.
Definition quadTree.h:289
void neighbors(PosType ray[], PosType rmax, std::list< IndexType > &neighbors) const
find all points within rmax of ray in 2D
Definition quadTree.h:707
void force2D_recur(const PosType *ray, PosType *alpha, KappaType *kappa, KappaType *gamma, KappaType *phi)
Force2D_recur calculates the defection, convergence and shear using the plane-lens approximation.
Definition quadTree.h:933
bool periodic_buffer
if true there is one layer of peridic buffering
Definition quadTree.h:106
void printParticlesInBranch(unsigned long number)
Definition quadTree.h:1134
void printBranchs(int level=-1)
Definition quadTree.h:1156
void rotate_coordinates(PosType **coord)
simple rotates the coordinates in the xp array
Definition quadTree.h:632
short WhichQuad(PosType *x, QBranchNB &branch)
returns an index for which of the four quadrangles of the branch the point x[] is in
Definition quadTree.h:354
TreeQuadParticles(PType *xpt, IndexType Npoints, float mass_fixed=-1, float size_fixed=-1, PosType my_inv_area=0, int bucket=5, PosType theta_force=0.1, bool my_periodic_buffer=false, PosType my_inv_screening_scale=0, PosType maximum_range=-1)
Constructor meant for point particles, simulation particles.
Definition quadTree.h:248
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
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