/* ------------------------ Projet BAORadio -------------------- Classes to compute 3D power spectrum and noise power spectrum R. Ansari - Nov 2008 ... Dec 2010 --------------------------------------------------------------- */ #include "specpk.h" #include "radutil.h" #include "randr48.h" #include "ctimer.h" //------------------------------------ // Class SpectralShape // ----------------------------------- double Pnu1(double nu) { return ( sqrt(sqrt(nu)) / ((nu+1.0)/0.2) * (1+0.2*cos(2*M_PI*(nu-2.)*0.15)*exp(-nu/50.)) ); } double Pnu2(double nu) { if (nu < 1.e-9) return 0.; return ((1.-exp(-nu/0.5))/nu*(1+0.25*cos(2*M_PI*nu*0.1)*exp(-nu/20.)) ); } double Pnu3(double nu) { return ( log(nu/100.+1)*(1+sin(2*M_PI*nu/300))*exp(-nu/4000) ); } double Pnu4(double nu) { double x = (nu-0.5)/0.05; double rc = 2*exp(-x*x); x = (nu-3.1)/0.27; rc += exp(-x*x); x = (nu-7.6)/1.4; rc += 0.5*exp(-x*x); return ( rc+2.*exp(-x*x) ); } //-------------------------------------------------- // -- SpectralShape class : test P(k) class //-------------------------------------------------- // Constructor SpectralShape::SpectralShape(int typ) { typ_=typ; SetRenormFac(); } // Return the spectral power for a given wave number wk double SpectralShape::operator() (double wk) { wk/=DeuxPI; double retv=1.; switch (typ_) { case 1: retv=Pnu1(wk); break; case 2: retv=Pnu2(wk); break; case 3: retv=Pnu3(wk); break; case 4: retv=Pnu4(wk); break; default : { // global shape double csp = pow( (2*sin(sqrt(sqrt(wk/7.)))),2.); if (csp < 0.) return 0.; // Adding some pics double picpos[5] = {75.,150.,225.,300.,375.,}; for(int k=0; k<5; k++) { double x0 = picpos[k]; if ( (wk > x0-25.) && (wk < x0+25.) ) { double x = (wk-x0); csp *= (1.+0.5*exp(-(x*x)/(2.*5*5))); break; } } retv=csp; } break; } return retv*renorm_fac; } // Return a vector representing the power spectrum (for checking) Histo SpectralShape::GetPk(int n) { if (n<16) n = 256; Histo h(0.,1024.*DeuxPI,n); for(int k=0; k > & fourcoedd, RandomGeneratorInterface& rg) : rg_(rg), fourAmp(fourcoedd) { SetPrtLevel(); SetCellSize(); hp_pk_p_=NULL; hmcnt_p_=NULL; hmcntok_p_=NULL; s2cut_=0.; } // Constructor Four3DPk::Four3DPk(RandomGeneratorInterface& rg, sa_size_t szx, sa_size_t szy, sa_size_t szz) : rg_(rg), fourAmp(szx, szy, szz) { SetPrtLevel(); SetCellSize(); hp_pk_p_=NULL; hmcnt_p_=NULL; hmcntok_p_=NULL; s2cut_=0.; } // Destructor Four3DPk::~Four3DPk() { if (hp_pk_p_) delete hp_pk_p_; if (hmcnt_p_) delete hmcnt_p_; if (hmcntok_p_) delete hmcntok_p_; } // Generate mass field Fourier Coefficient void Four3DPk::ComputeFourierAmp(SpectralShape& pk) { // We generate a random gaussian real field // fourAmp represent 3-D fourier transform of a real input array. // The second half of the array along Y and Z contain negative frequencies // double fnorm = 1./sqrt(2.*fourAmp.Size()); double fnorm = 1.; double kxx, kyy, kzz; // sa_size_t is large integer type for(sa_size_t kz=0; kzfourAmp.SizeZ()/2) ? (double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_; for(sa_size_t ky=0; kyfourAmp.SizeY()/2) ? (double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_; for(sa_size_t kx=0; kx(rg_.Gaussian(amp), rg_.Gaussian(amp)); // renormalize fourier coeff usin } } } if (prtlev_>2) cout << " Four3DPk::ComputeFourierAmp() done ..." << endl; } // Generate mass field Fourier Coefficient void Four3DPk::ComputeNoiseFourierAmp(Four2DResponse& resp, double angscale, bool crmask) // angscale is a multiplicative factor converting transverse k (wave number) values to angular wave numbers // typically = ComovRadialDistance { TMatrix mask(fourAmp.SizeY(), fourAmp.SizeX()); // fourAmp represent 3-D fourier transform of a real input array. // The second half of the array along Y and Z contain negative frequencies double kxx, kyy, kzz, rep, amp; // sa_size_t is large integer type for(sa_size_t kz=0; kzfourAmp.SizeZ()/2) ? -(double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_; for(sa_size_t ky=0; kyfourAmp.SizeY()/2) ? -(double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_; for(sa_size_t kx=0; kx(9.e9,0.); else { amp = 1./sqrt(rep)/sqrt(2.); fourAmp(kx, ky, kz) = complex(rg_.Gaussian(amp), rg_.Gaussian(amp)); } } } } if (prtlev_>2) fourAmp.Show(); if (crmask) { POutPersist po("mask.ppf"); po << mask; } if (prtlev_>0) cout << " Four3DPk::ComputeNoiseFourierAmp() done ..." << endl; } // Generate mass field Fourier Coefficient void Four3DPk::ComputeNoiseFourierAmp(Four2DResponse& resp, double f0, double df, Vector& angscales) // angscale is a multiplicative factor converting transverse k (wave number) values to angular wave numbers // typically = ComovRadialDistance { uint_8 nmodeok=0; if (angscales.Size() != fourAmp.SizeZ()) throw SzMismatchError("ComputeNoiseFourierAmp(): angscales.Size()!=fourAmp.SizeZ()"); H21Conversions conv; // fourAmp represent 3-D fourier transform of a real input array. // The second half of the array along Y and Z contain negative frequencies double kxx, kyy, kzz, rep, amp; // sa_size_t is large integer type for(sa_size_t kz=0; kz2) cout << " Four3DPk::ComputeNoiseFourierAmp(...) - freq=" << f0+kz*df << " -> AngSc=" << angsc << endl; for(sa_size_t ky=0; kyfourAmp.SizeY()/2) ? -(double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_; for(sa_size_t kx=0; kx(rg_.Gaussian(amp), rg_.Gaussian(amp)); } } } if (prtlev_>1) { cout << " Four3DPk::ComputeNoiseFourierAmp(...) Computing FFT along frequency ... \n" << " NModeOK=" << nmodeok << " / NMode=" << fourAmp.Size() << " -> " << 100.*(double)nmodeok/(double)fourAmp.Size() << "%" << endl; } TVector< complex > veczin(fourAmp.SizeZ()), veczout(fourAmp.SizeZ()); FFTWServer ffts(true); ffts.setNormalize(true); for(sa_size_t ky=0; ky2) fourAmp.Show(); if (prtlev_>0) cout << " Four3DPk::ComputeNoiseFourierAmp(Four2DResponse& resp, double f0, double df) done ..." << endl; } // Compute mass field from its Fourier Coefficient TArray Four3DPk::ComputeMassDens() { TArray massdens; // Backward fourier transform of the fourierAmp array FFTWServer ffts(true); ffts.setNormalize(true); ffts.FFTBackward(fourAmp, massdens, true); // cout << " Four3DPk::ComputeMassDens() done NbNeg=" << npbz << " / NPix=" << massDens.Size() << endl; cout << " Four3DPk::ComputeMassDens() done NPix=" << massdens.Size() << endl; return massdens; } // Compute power spectrum as a function of wave number k // cells with amp^2=re^2+im^2>s2cut are ignored // Output : power spectrum (profile histogram) HProf Four3DPk::ComputePk(double s2cut, int nbin, double kmin, double kmax, bool fgmodcnt) { // The second half of the array along Y (matrix rows) contain // negative frequencies // int nbh = sqrt(fourAmp.SizeX()*fourAmp.SizeX()+fourAmp.SizeY()*fourAmp.SizeY()/4.+fourAmp.SizeZ()*fourAmp.SizeY()/4.); // The profile histogram will contain the mean value of FFT amplitude // as a function of wave-number k = sqrt((double)(kx*kx+ky*ky)) // if (nbin < 1) nbin = nbh/2; if ((kmax<0.)||(kmaxSetErrOpt(false); if (fgmodcnt) { hmcnt_p_ = new Histo(kmin, kmax, nbin); hmcntok_p_ = new Histo(kmin, kmax, nbin); } s2cut_=s2cut; ComputePkCumul(); return *hp_pk_p_; } // Compute power spectrum as a function of wave number k // Cumul dans hp - cells with amp^2=re^2+im^2>s2cut are ignored void Four3DPk::ComputePkCumul() { uint_8 nmodeok=0; // fourAmp represent 3-D fourier transform of a real input array. // The second half of the array along Y and Z contain negative frequencies double kxx, kyy, kzz; // sa_size_t is large integer type // We ignore 0th term in all frequency directions ... for(sa_size_t kz=0; kz fourAmp.SizeZ()/2) ? (double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_; for(sa_size_t ky=0; ky fourAmp.SizeY()/2) ? (double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_; for(sa_size_t kx=0; kx za = fourAmp(kx, ky, kz); // if (za.real()>8.e19) continue; double wk = sqrt(kxx*kxx+kyy*kyy+kzz*kzz); double amp2 = za.real()*za.real()+za.imag()*za.imag(); if (hmcnt_p_) hmcnt_p_->Add(wk); if ((s2cut_>1.e-9)&&(amp2>s2cut_)) continue; if (hmcntok_p_) hmcntok_p_->Add(wk); hp_pk_p_->Add(wk, amp2); nmodeok++; } } } if ((prtlev_>1)||((prtlev_>0)&&(s2cut_>1.e-9))) { cout << " Four3DPk::ComputePkCumul/Info : NModeOK=" << nmodeok << " / NMode=" << fourAmp.Size() << " -> " << 100.*(double)nmodeok/(double)fourAmp.Size() << "%" << endl; } return; } // Compute noise power spectrum as a function of wave number k // No random generation, computes profile of noise sigma^2 // cells with amp^2=re^2+im^2>s2cut are ignored // Output : noise power spectrum (profile histogram) // angscale is a multiplicative factor converting transverse k (wave number) values to angular wave numbers // typically = ComovRadialDistance HProf Four3DPk::ComputeNoisePk(Four2DResponse& resp, double angscale, double s2cut, int nbin, double kmin, double kmax) { // The second half of the array along Y (matrix rows) contain // negative frequencies // int nbh = sqrt(fourAmp.SizeX()*fourAmp.SizeX()+fourAmp.SizeY()*fourAmp.SizeY()/4.+fourAmp.SizeZ()*fourAmp.SizeY()/4.); // The profile histogram will contain the mean value of noise sigma^2 // as a function of wave-number k = sqrt((double)(kx*kx+ky*ky)) // if (nbin < 1) nbin = nbh/2; double kmax2d=0.; if ((kmax<0.)||(kmaxSetErrOpt(false); hmcnt_p_ = new Histo(kmin, kmax, nbin); hmcntok_p_ = new Histo(kmin, kmax, nbin); s2cut_=s2cut; uint_8 nmodeok=0; // fourAmp represent 3-D fourier transform of a real input array. // The second half of the array along Y and Z contain negative frequencies double kxx, kyy, kzz; // sa_size_t is large integer type // We ignore 0th term in all frequency directions ... for(sa_size_t kz=0; kz fourAmp.SizeZ()/2) ? (double)(fourAmp.SizeZ()-kz)*dkz_ : (double)kz*dkz_; uint_8 nmodeok_kz=0; for(sa_size_t ky=0; ky fourAmp.SizeY()/2) ? (double)(fourAmp.SizeY()-ky)*dky_ : (double)ky*dky_; for(sa_size_t kx=0; kx1.e-19)?1./rep:1.e19; hmcnt_p_->Add(wk); if ((s2cut_>1.e-9)&&(amp2>s2cut_)) continue; hmcntok_p_->Add(wk); hp_pk_p_->Add(wk, amp2); nmodeok++; nmodeok_kz++; } } if (prtlev_>2) cout << " Four3DPk::ComputeNoisePk(kz="< " << 100.*(double)nmodeok/(double)fourAmp.Size() << "%" << endl; } return *hp_pk_p_; } // Fills a data table from the computed P(k) profile histogram and mode count Histo Four3DPk::FillPkDataTable(DataTable& dt) { if (hp_pk_p_==NULL) throw ParmError("Four3DPk::FillPkDataTable P(k) NOT computed"); if ((hmcnt_p_==NULL)||(hmcntok_p_==NULL)) throw ParmError("Four3DPk::FillPkDataTable Mode count histos NOT filled"); HProf& hp=(*hp_pk_p_); Histo& hmcnt=(*hmcnt_p_); Histo& hmcntok=(*hmcntok_p_); Histo fracmodok=hmcntok/hmcnt; char* nomcol[5] = {"k","pnoise","nmode","nmodok","fracmodok"}; dt.Clear(); dt.AddDoubleColumn(nomcol[0]); dt.AddDoubleColumn(nomcol[1]); dt.AddIntegerColumn(nomcol[2]); dt.AddIntegerColumn(nomcol[3]); dt.AddFloatColumn(nomcol[4]); DataTableRow dtr = dt.EmptyRow(); for(int_4 ib=0; ib0)&&(igen>0)&&(((igen-1)%prtmodulo_)==0)) cout << " PkNoiseCalculator::Compute() - done igen=" << igen << " / MaxNGen=" << NGEN << endl; } return pkn3d.GetPk() ; } //----------------------------------------------------- // -- MassDist2D class : 2D mass distribution //----------------------------------------------------- // Constructor MassDist2D::MassDist2D(GenericFunc& pk, int size, double meandens) : pkSpec(pk) , sizeA((size>16)?size:16) , massDens(sizeA, sizeA), meanRho(meandens) , fg_fourAmp(false) , fg_massDens(false) { } // To the computation job void MassDist2D::Compute() { ComputeFourierAmp(); ComputeMassDens(); } // Generate mass field Fourier Coefficient void MassDist2D::ComputeFourierAmp() { if (fg_fourAmp) return; // job already done // We generate a random gaussian real field double sigma = 1.; // The following line fills the array by gaussian random numbers //--Replaced-- massDens = RandomSequence(RandomSequence::Gaussian, 0., sigma); // Can be replaced by DR48RandGen rg; for(sa_size_t ir=0; ir white noise FFTWServer ffts(true); ffts.setNormalize(true); ffts.FFTForward(massDens, fourAmp); // fourAmp represent 2-D fourier transform of a real input array. // The second half of the array along Y (matrix rows) contain // negative frequencies // double fnorm = 1./sqrt(2.*fourAmp.Size()); // PUT smaller value for fnorm and check number of zeros double fnorm = 1.; // sa_size_t is large integer type for(sa_size_t ky=0; ky fourAmp.NRows()/2) kyy = fourAmp.NRows()-ky; // negative frequencies for(sa_size_t kx=0; kx