/*! \file localbgcomp.cxx * \brief this file contains routines to compare the local velocity density function of a particle relative to that predicted by the backgound and then calculates the normalized deviation or outlier value ellprob \todo once ratio is calculated, must figure out best way to do global mpi fit. Probably best to combine the binned distribution and fit that */ #include "exceptions.h" #include "logging.h" #include "stf.h" /*! This calculates the logarithmic ratio of the measured velocity density and the expected velocity density assuming a bg muiltivariate gaussian distribution \todo must adjust interpolation scheme so that if NN has cells in a neighbouring MPI domain, the information is stored locally. This may require a rewrite of the grid cell structure or the near neighbour list so that if grid cell has NN in another processor, actually physically store the information cm, cmvel, veldisp locally to that grid cell. Another option is to determine all cells that are NN of a cell in another mpi's domain, build a grid export list that contains the relevant information and an index that is easily accessible when searching the list of NN cells locally. */ void GetDenVRatio(Options &opt, const Int_t nbodies, Particle *Part, Int_t ngrid, GridCell *grid, Coordinate *gvel, Matrix *gveldisp) { Int_t i; int nthreads,tid; Double_t **dist; Double_t norm=pow(2.0*M_PI,-1.5); Int_t **nn; Double_t w,wsum,maxdist,sv,vsv,fbg,tempdenv; Coordinate vp,vmweighted; Matrix isvweighted; Particle *ptemp; KDTree *tree; LOG(trace) << "Calculating denvratios using grid"; //take inverse for interpolation #ifdef USEOPENMP #pragma omp parallel default(shared) \ private(i) if (nbodies > ompsubsearchnum) { #pragma omp for schedule(static) #endif for (i=0;iTPHYS, tree->KEPAN,100,0,0,0,NULL,NULL,false); #ifndef USEOPENMP nthreads=1; #else #pragma omp parallel { if (omp_get_thread_num()==0) nthreads=omp_get_num_threads(); } #endif dist=new Double_t*[nthreads]; for (int j=0;j ompsubsearchnum) { #pragma omp for schedule(static) #endif for (i=0;i 0)) { throw vr::non_positive_density(Part[i], __PRETTY_FUNCTION__); } tempdenv=Part[i].GetDensity()/opt.Nsearch; #ifdef USEOPENMP tid=omp_get_thread_num(); #else tid=0; #endif //try inverse distance weighting scheme based using Shepard's method. fbg=0.; wsum=0.; maxdist=0.; vmweighted[0]=vmweighted[1]=vmweighted[2]=0.; for (int j=0;j<3;j++) for (int k=0;k<3;k++) isvweighted(j,k)=0.0; Coordinate xpos(Part[i].GetPosition()); tree->FindNearestPos(xpos,nn[tid],dist[tid],MAXNGRID+1); for (int j=0;j<=MAXNGRID;j++) { dist[tid][j]=sqrt(dist[tid][j]+1e-16); if (dist[tid][j]>maxdist)maxdist=dist[tid][j]; } for (int j=0;j<=MAXNGRID;j++) { w=(maxdist-dist[tid][j])/(maxdist*dist[tid][j]);w=w*w; //w=1.0/dist[tid][j]; wsum+=w; vmweighted=vmweighted+gvel[ptemp[nn[tid][j]].GetID()]*w; isvweighted=isvweighted+gveldisp[ptemp[nn[tid][j]].GetID()]*w; } vmweighted=vmweighted*(1.0/wsum); isvweighted=isvweighted*(1.0/wsum); sv=sqrt(abs(isvweighted.Det())); for (int m=0;m<3;m++) vp[m]=Part[i].GetVelocity(m)-vmweighted[m]; vsv=0.;for (int m=0;m<3;m++) for (int n=0;n<3;n++) vsv+=vp[m]*vp[n]*isvweighted(m,n); fbg=log(sv)-0.5*vsv; Part[i].SetPotential(log(tempdenv)-log(norm)-fbg); } #ifdef USEOPENMP } #endif LOG(trace) << "Done"; for (int j=0;j ompsubsearchnum) #endif for (auto i=0;i0) tempell*=temp2; else tempell*=temp3; Part[i].SetPotential(tempell); nsubset+=(Part[i].GetPotential()>opt.ellthreshold); } LOG(trace) << "Done"; return nsubset; }