/*! \file bgfield.cxx * \brief this file contains routines to characterize the background velocity field */ //-- Background Velocity Routines #include "logging.h" #include "stf.h" ///\name Cell construction using binary kd-tree //@{ ///Decompose Halo/system using KDTree /*! Serial Decomposition of halo/system local (to processor if mpi is invoked). The binary kd-tree decomposition using anything other than a tree in configuration space constructed using the shannon entropy criteron is allowed but is not \e \b advised. Building a physical tree with shannon entropy ensures that regions have uniform M(R)/r or more specifically uniform inter particle spacing \todo need to alter pglist array. Much smoother if use particles themselves to find nearest cells Instead of storing pglist which is memory intensive (nbodies*ncells) just calculate it when needed. */ KDTree* InitializeTreeGrid(Options &opt, const Int_t nbodies, Particle *Part){ //First rotate into eigenvector frame. #ifdef SCALING Double_t q=1,s=1; Coordinate vel; Matrix eigvec(0.); Int_t i; GetGlobalMorphologyWithMass(nbodies,Part, q, s, 1e-3, eigvec); //GetGlobalMorphologyWithMass(nbodies, Part, q, s, 1e-3); //and rotate velocities to new frame #ifdef USEOPENMP #pragma omp parallel default(shared) \ private(i,vel) if (nbodies > ompsubsearchnum) { #pragma omp for #endif for (i=0;iTPHYS, ikerntype = tree->KEPAN, isplittingcriterion = 0, ianiso = 0 , iscale = 0; bool runomp = (nbodies > ompsubsearchnum); LOG(trace) << "Grid system using leaf nodes with maximum size of " << opt.Ncell; if (opt.gridtype==PHYSGRID) { LOG(trace) << "Building Physical Tree using simple spatial extend as splitting criterion"; //tree=new KDTree(Part,nbodies,opt.Ncell,tree->TPHYS); } else if (opt.gridtype==PHYSENGRID) { LOG(trace) << "Building physical Tree using minimum shannon entropy as splitting criterion"; isplittingcriterion = 1; //tree=new KDTree(*S,opt.Ncell,tree->TPHYS,tree->KEPAN,100,1); //tree=new KDTree(Part,nbodies,opt.Ncell,tree->TPHYS,tree->KEPAN,100,1); } else if (opt.gridtype==PHASEENGRID) { LOG(trace) << "Building Phase-space Tree using minimum shannon entropy as splitting criterion"; itreetype = tree->TPHS; isplittingcriterion = 1; ianiso = 1; //tree=new KDTree(*S,opt.Ncell,tree->TPHS,tree->KEPAN,100,1,1);//if phase tree, use entropy criterion with anisotropic kernel //if phase tree, use entropy criterion with anisotropic kernel //tree=new KDTree(Part,nbodies,opt.Ncell,tree->TPHS,tree->KEPAN,100,1,1); } tree=new KDTree(Part,nbodies,opt.Ncell,itreetype,ikerntype,100,isplittingcriterion,ianiso,iscale,NULL,NULL,runomp); return tree; } ///Fills the GridCell struct using KD-Tree initialized by \ref InitializeTreeGrid void FillTreeGrid(Options &opt, const Int_t nbodies, const Int_t ngrid, KDTree *&tree, Particle *Part, GridCell* &grid) //void FillTreeGrid(Options &opt, const Int_t nbodies, const Int_t ngrid, KDTree *tree, Particle *Part, GridCell* grid, PartCellNum *pglist) { Int_t gridcount=0,ncount=0; //this is used to create tree and search for near neighbours Particle *ptemp=new Particle[ngrid]; int treetype=tree->GetTreeType(); int ND; if (treetype==tree->TPHYS) ND=3; else if (treetype==tree->TPHS) ND=6; LOG(trace) << "Filling KD-Tree Grid"; //this loop works well for large cells but for small cells may have to replace this with a for loop which goes through every particle //and stores nid and size of node, then builds grid based on these values and then places the particles in the cells. //for leaf nodes, use starts and ends indices (ie what particles in the system are in the node) while (ncountFindLeafNode((Int_t)ncount)); Int_t start=((LeafNode*)np)->GetStart(); Int_t end=((LeafNode*)np)->GetEnd(); //this while loop ensures that if there is a particle out of place, one still proceeds to move through //the tree appropriately. while (!(ncount>=start&&ncountFindLeafNode((Int_t)ncount)); start=((LeafNode*)np)->GetStart(); end=((LeafNode*)np)->GetEnd(); } grid[gridcount].ndim=ND; //get center of mass and boundaries of grid cell for (int j=0;jGetBoundary(j,0); grid[gridcount].xbu[j]=np->GetBoundary(j,1); } grid[gridcount].nparts=np->GetCount(); grid[gridcount].gid=np->GetID(); grid[gridcount].nindex=new Int_t[grid[gridcount].nparts]; Double_t mtot=0.; for (Int_t k=start,l=0;k ompsubsearchnum) { #pragma omp for #endif for (i=0;i ompsubsearchnum) { #pragma omp for #endif for (i=0;i