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
 
   49  friend class LensPlaneTree;
 
   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;
 
   78  QTreeNB<PosType *> * tree;
 
   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);
 
  113  void cuttoffscale(QTreeNB<PosType *> * tree,PosType *theta);
 
  116  void walkTree_iter(QBiterator<PosType *> &treeit, PosType 
const *ray,PosType *alpha,KappaType *kappa
 
  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 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