#include "sopnamsp.h" #include "machdefs.h" #include #include #include #include #include #include #include "timing.h" #include "tarray.h" #include "pexceptions.h" #include "perandom.h" #include "srandgen.h" #include "fabtcolread.h" #include "fabtwriter.h" #include "fioarr.h" #include "arrctcast.h" #include "constcosmo.h" #include "integfunc.h" #include "geneutils.h" #include "genefluct3d.h" //#define FFTW_THREAD #define MODULE2(_x_) ((double)((_x_).real()*(_x_).real() + (_x_).imag()*(_x_).imag())) //------------------------------------------------------- GeneFluct3D::GeneFluct3D(TArray< complex >& T) : T_(T) , array_allocated_(false) { SetNThread(); } GeneFluct3D::~GeneFluct3D(void) { fftw_destroy_plan(pf_); fftw_destroy_plan(pb_); #ifdef FFTW_THREAD if(nthread_>0) fftw_cleanup_threads(); #endif } //------------------------------------------------------- void GeneFluct3D::SetSize(long nx,long ny,long nz,double dx,double dy,double dz) { setsize(nx,ny,nz,dx,dy,dz); setalloc(); setpointers(false); } void GeneFluct3D::setsize(long nx,long ny,long nz,double dx,double dy,double dz) { if(nx<=0 || dx<=0.) { cout<<"GeneFluct3D::SetSize_Error: bad value(s)"< // ATTENTION: TArray adresse en memoire a l'envers du C // Tarray(n1,n2,n3) == Carray[n3][n2][n1] sa_size_t SzK_[3] = {NCz_,Ny_,Nx_}; // a l'envers try { T_.ReSize(3,SzK_); array_allocated_ = true; } catch (...) { cout<<"GeneFluct3D::SetSize_Error: Problem allocating T_"< ou le TArray > { cout<<"GeneFluct3D::WritePPF: Writing Cube (real="< >"<> PPFNameTag("pkgen") >> T_; from_real = false; } else { cout<<" ...reading space into TArray"<> PPFNameTag("rgen") >> R_; } int_8 nx = R_.Info()["NX"]; int_8 ny = R_.Info()["NY"]; int_8 nz = R_.Info()["NZ"]; r_8 dx = R_.Info()["DX"]; r_8 dy = R_.Info()["DY"]; r_8 dz = R_.Info()["DZ"]; setsize(nx,ny,nz,dx,dy,dz); setpointers(from_real); } catch (PThrowable & exc) { cout<<"Exception : "<<(string)typeid(exc).name() <<" - Msg= "<1) PrtTim("--- ComputeFourier0: before fftw_plan ---"); #ifdef FFTW_THREAD if(nthread_>0) { cout<<"Computing with "<1) PrtTim("--- ComputeFourier0: after fftw_plan ---"); // --- realisation d'un tableau de tirage gaussiens if(lp>1) PrtTim("--- ComputeFourier0: before gaussian filling ---"); // On tient compte du pb de normalisation de FFTW3 double sntot = sqrt((double)NRtot_); for(long i=0;i1) PrtTim("--- ComputeFourier0: after gaussian filling ---"); // --- realisation d'un tableau de tirage gaussiens if(lp>1) PrtTim("--- ComputeFourier0: before fft real ---"); fftw_execute(pf_); if(lp>1) PrtTim("--- ComputeFourier0: after fft real ---"); // --- On remplit avec une realisation if(lp>1) PrtTim("--- ComputeFourier0: before Fourier realization filling ---"); T_(0,0,0) = complex(0.); // on coupe le continue et on l'initialise long lmod = Nx_/10; if(lmod<1) lmod=1; for(long i=0;iNx_/2) ? Nx_-i : i; double kx = ii*Dkx_; kx *= kx; if(lp>1 && i%lmod==0) cout<<"i="<1) PrtTim("--- ComputeFourier0: after Fourier realization filling ---"); double p = compute_power_carte(); cout<<"Puissance dans la realisation: "<1) PrtTim("--- ComputeFourier0: after Computing power ---"); } //------------------------------------------------------- void GeneFluct3D::ComputeFourier(GenericFunc& pk_at_z) // Calcule une realisation du spectre "pk_at_z" // Attention: dans TArray le premier indice varie le + vite // Explication normalisation: see Coles & Lucchin, Cosmology, p264-265 // FFTW3: on note N=Nx*Ny*Nz // f --(FFT)--> F = TF(f) --(FFT^-1)--> fb = TF^-1(F) = TF^-1(TF(f)) // sum(f(x_i)^2) = S // sum(F(nu_i)^2) = S*N // sum(fb(x_i)^2) = S*N^2 { int lp=2; // --- Initialisation de fftw3 (attention data est sur-ecrit a l'init) if(lp>1) PrtTim("--- ComputeFourier: before fftw_plan ---"); #ifdef FFTW_THREAD if(nthread_>0) { cout<<"Computing with "<1) PrtTim("--- ComputeFourier: after fftw_plan ---"); // --- RaZ du tableau T_ = complex(0.); // --- On remplit avec une realisation if(lp>1) PrtTim("--- ComputeFourier: before Fourier realization filling ---"); long lmod = Nx_/10; if(lmod<1) lmod=1; for(long i=0;iNx_/2) ? Nx_-i : i; double kx = ii*Dkx_; kx *= kx; if(lp>1 && i%lmod==0) cout<<"i="<1) PrtTim("--- ComputeFourier: after managing coefficients ---"); double p = compute_power_carte(); cout<<"Puissance dans la realisation: "<1) PrtTim("--- ComputeFourier: after before Computing power ---"); } long GeneFluct3D::manage_coefficients(void) // Take into account the real and complexe conjugate coefficients // because we want a realization of a real data in real space { check_array_alloc(); // 1./ Le Continu et Nyquist sont reels long nreal = 0; for(long kk=0;kk<2;kk++) { long k=0; // continu if(kk==1) {if(Nz_%2!=0) continue; else k = Nz_/2;} // Nyquist for(long jj=0;jj<2;jj++) { long j=0; if(jj==1) {if( Ny_%2!=0) continue; else j = Ny_/2;} for(long ii=0;ii<2;ii++) { long i=0; if(ii==1) {if( Nx_%2!=0) continue; else i = Nx_/2;} int_8 ip = IndexC(i,j,k); //cout<<"i="<Nx_/2) ? Nx_-i : i; double kx = ii*Dkx_ *Dx_/2; double pk_x = pixelfilter(kx); for(long j=0;jNy_/2) ? Ny_-j : j; double ky = jj*Dky_ *Dy_/2; double pk_y = pixelfilter(ky); for(long l=0;l1) PrtTim("--- FilterByPixel: after ---"); } //------------------------------------------------------------------- void GeneFluct3D::ComputeReal(void) // Calcule une realisation dans l'espace reel { int lp=2; check_array_alloc(); // On fait la FFT if(lp>1) PrtTim("--- ComputeReal: before fftw backward ---"); fftw_execute(pb_); if(lp>1) PrtTim("--- ComputeReal: after fftw backward ---"); } //------------------------------------------------------------------- void GeneFluct3D::ReComputeFourier(void) { int lp=2; check_array_alloc(); // On fait la FFT if(lp>1) PrtTim("--- ComputeReal: before fftw forward ---"); fftw_execute(pf_); // On corrige du pb de la normalisation de FFTW3 double v = (double)NRtot_; for(long i=0;i(v); if(lp>1) PrtTim("--- ComputeReal: after fftw forward ---"); } //------------------------------------------------------------------- int GeneFluct3D::ComputeSpectrum(HistoErr& herr) // Compute spectrum from "T" and fill HistoErr "herr" // T : dans le format standard de GeneFuct3D: T(nz,ny,nx) // cad T(kz,ky,kx) avec 0Nx_/2) ? Nx_-i : i; double kx = ii*Dkx_; kx *= kx; for(long j=0;jNy_/2) ? Ny_-j : j; double ky = jj*Dky_; ky *= ky; for(long l=0;lNx_/2) ? Nx_-i : i; double kx = ii*Dkx_; kx *= kx; for(long j=0;jNy_/2) ? Ny_-j : j; double ky = jj*Dky_; ky *= ky; double kt = sqrt(kx+ky); for(long l=0;l1) PrtTim("--- VarianceFrReal: before computation ---"); long dnx = long(R/Dx_+0.5); if(dnx<=0) dnx = 1; long dny = long(R/Dy_+0.5); if(dny<=0) dny = 1; long dnz = long(R/Dz_+0.5); if(dnz<=0) dnz = 1; cout<<"dnx="<="<)^2>="<^2/^2 if(lp) cout<<"sigmaR^2="< "<1) PrtTim("--- VarianceFrReal: after computation ---"); return nsum; } //------------------------------------------------------- int_8 GeneFluct3D::NumberOfBad(double vmin,double vmax) // number of pixels outside of ]vmin,vmax[ extremites exclues // -> vmin and vmax are considered as bad { check_array_alloc(); int_8 nbad = 0; for(long i=0;i=vmax) nbad++; } return nbad; } int_8 GeneFluct3D::MeanSigma2(double& rm,double& rs2,double vmin,double vmax) // mean,sigma^2 pour pixels avec valeurs ]vmin,vmax[ extremites exclues // -> mean and sigma^2 are NOT computed with pixels values vmin and vmax { check_array_alloc(); int_8 n = 0; rm = rs2 = 0.; for(long i=0;i=vmax) continue; rm += v; rs2 += v*v; n++; } if(n>1) { rm /= (double)n; rs2 = rs2/(double)n - rm*rm; } return n; } int_8 GeneFluct3D::SetToVal(double vmin, double vmax,double val0) // set to "val0" if out of range ]vmin,vmax[ extremites exclues // -> vmin and vmax are set to val0 { check_array_alloc(); int_8 nbad = 0; for(long i=0;i=vmax) {data_[ip] = val0; nbad++;} } return nbad; } //------------------------------------------------------- void GeneFluct3D::TurnFluct2Mass(void) // d_rho/rho -> Mass (add one!) { int lp=2; check_array_alloc(); if(lp>1) PrtTim("--- TurnFluct2Mass: before computation ---"); for(long i=0;i1) PrtTim("--- TurnFluct2Mass: after computation ---"); } double GeneFluct3D::TurnMass2MeanNumber(double n_by_mpc3) // do NOT treate negative or nul values { int lp=2; if(lp>1) PrtTim("--- TurnMass2MeanNumber: before computation ---"); double m,s2; int_8 ngood = MeanSigma2(m,s2,0.,1e+200); if(lp) cout<<"TurnMass2MeanNumber: ngood="< "<0. // On NE met PAS a zero les pixels <0 // On renormalise sur les pixels>0 pour qu'on ait n*Vol galaxies // comme on ne prend que les pixels >0, on doit normaliser // a la moyenne de <1+d_rho/rho> sur ces pixels // (rappel sur tout les pixels <1+d_rho/rho>=1) double dn = n_by_mpc3*Vol_/m /(double)ngood; // nb de gal a mettre ds 1 px if(lp) cout<<"galaxy density move from " <0.) sum += data_[ip]; // mais on ne les compte pas } if(lp) cout<1) PrtTim("--- TurnMass2MeanNumber: after computation ---"); return sum; } double GeneFluct3D::ApplyPoisson(void) // do NOT treate negative or nul mass -> let it as it is { int lp=2; check_array_alloc(); if(lp>1) PrtTim("--- ApplyPoisson: before computation ---"); double sum = 0.; for(long i=0;i0.) { unsigned long dn = PoissRandLimit(v,10.); data_[ip] = (double)dn; sum += (double)dn; } } if(lp) cout<1) PrtTim("--- ApplyPoisson: before computation ---"); return sum; } double GeneFluct3D::TurnNGal2Mass(FunRan& massdist,bool axeslog) // do NOT treate negative or nul mass -> let it as it is // INPUT: // massdist : distribution de masse (m*dn/dm) // axeslog = false : retourne la masse // = true : retourne le log10(mass) // RETURN la masse totale { int lp=2; check_array_alloc(); if(lp>1) PrtTim("--- TurnNGal2Mass: before computation ---"); double sum = 0.; for(long i=0;i0.) { long ngal = long(v+0.1); data_[ip] = 0.; for(long i=0;i1) PrtTim("--- TurnNGal2Mass: after computation ---"); return sum; } void GeneFluct3D::AddNoise2Real(double snoise) // add noise to every pixels (meme les <=0 !) { int lp=2; check_array_alloc(); if(lp>1) PrtTim("--- AddNoise2Real: before computation ---"); for(long i=0;i1) PrtTim("--- AddNoise2Real: after computation ---"); }