| [3115] | 1 | #include "sopnamsp.h"
 | 
|---|
 | 2 | #include "machdefs.h"
 | 
|---|
 | 3 | #include <iostream>
 | 
|---|
 | 4 | #include <stdlib.h>
 | 
|---|
 | 5 | #include <stdio.h>
 | 
|---|
 | 6 | #include <string.h>
 | 
|---|
 | 7 | #include <math.h>
 | 
|---|
 | 8 | #include <unistd.h>
 | 
|---|
 | 9 | 
 | 
|---|
 | 10 | #include "pexceptions.h"
 | 
|---|
 | 11 | 
 | 
|---|
 | 12 | #include "constcosmo.h"
 | 
|---|
 | 13 | #include "integfunc.h"
 | 
|---|
 | 14 | #include "pkspectrum.h"
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | 
 | 
|---|
 | 17 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 18 | //******************** InitialSpectrum ******************//
 | 
|---|
 | 19 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 20 | 
 | 
|---|
 | 21 | InitialSpectrum::InitialSpectrum(double n,double a)
 | 
|---|
 | 22 |   : n_(n), A_(a)
 | 
|---|
 | 23 | {
 | 
|---|
 | 24 | }
 | 
|---|
 | 25 | 
 | 
|---|
 | 26 | InitialSpectrum::InitialSpectrum(InitialSpectrum& pkinf)
 | 
|---|
 | 27 |   : n_(pkinf.n_), A_(pkinf.A_)
 | 
|---|
 | 28 | {
 | 
|---|
 | 29 | }
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | InitialSpectrum::~InitialSpectrum(void)
 | 
|---|
 | 32 | {
 | 
|---|
 | 33 | }
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | void InitialSpectrum::SetNorm(double a)
 | 
|---|
 | 36 | {
 | 
|---|
 | 37 |   A_ = a;
 | 
|---|
 | 38 | }
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | void InitialSpectrum::SetSlope(double n)
 | 
|---|
 | 41 | {
 | 
|---|
 | 42 |   n_ = n;
 | 
|---|
 | 43 | }
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | 
 | 
|---|
 | 46 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 47 | //****************** TransfertEisenstein ****************//
 | 
|---|
 | 48 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 | // From Eisenstein & Hu ApJ 496:605-614 1998 April 1
 | 
|---|
 | 51 | TransfertEisenstein::TransfertEisenstein(double h100,double OmegaCDM0,double OmegaBaryon0,double tcmb,bool nobaryon)
 | 
|---|
 | 52 |   : Oc_(OmegaCDM0) , Ob_(OmegaBaryon0) , h_(h100) , tcmb_(tcmb)
 | 
|---|
 | 53 |   , nobaryon_(nobaryon) , nooscenv_(0)
 | 
|---|
 | 54 | {
 | 
|---|
 | 55 |   if(nobaryon_ == false && Ob_>0.) Init_With_Baryons();
 | 
|---|
 | 56 |   else Init_Without_Baryon();
 | 
|---|
 | 57 | }
 | 
|---|
 | 58 | 
 | 
|---|
 | 59 | TransfertEisenstein::TransfertEisenstein(TransfertEisenstein& tf)
 | 
|---|
 | 60 |   : Oc_(tf.Oc_) , Ob_(tf.Ob_) , h_(tf.h_) , tcmb_(tf.tcmb_)
 | 
|---|
 | 61 |   , nobaryon_(tf.nobaryon_) , nooscenv_(tf.nooscenv_)
 | 
|---|
 | 62 | {
 | 
|---|
 | 63 |   if(nobaryon_ == false && Ob_>0.) Init_With_Baryons();
 | 
|---|
 | 64 |   else Init_Without_Baryon();
 | 
|---|
 | 65 | }
 | 
|---|
 | 66 | 
 | 
|---|
 | 67 | void TransfertEisenstein::Init_With_Baryons(void)
 | 
|---|
 | 68 | {
 | 
|---|
 | 69 |   int lp = 1;
 | 
|---|
 | 70 | 
 | 
|---|
 | 71 |   nobaryon_ = false;
 | 
|---|
 | 72 |   O0_ = Oc_ + Ob_;
 | 
|---|
 | 73 |     if(lp) cout<<"Omatter="<<O0_<<" Ocdm="<<Oc_<<" Ob="<<Ob_<<endl;
 | 
|---|
 | 74 | 
 | 
|---|
 | 75 |   double H0 = 100. * h_, h2 = h_*h_;
 | 
|---|
 | 76 | 
 | 
|---|
 | 77 |   th2p7_ = tcmb_/2.7;
 | 
|---|
 | 78 |   double th2p7P4 = th2p7_*th2p7_*th2p7_*th2p7_;
 | 
|---|
 | 79 | 
 | 
|---|
 | 80 |   // Formule 2 p 606
 | 
|---|
 | 81 |   zeq_ = 2.50e4 * O0_ * h2 / th2p7P4;
 | 
|---|
 | 82 |     if(lp) cout<<"zeq = "<<zeq_<<endl;
 | 
|---|
 | 83 | 
 | 
|---|
 | 84 |   // Formule 3 p 607
 | 
|---|
 | 85 |   // (attention ici C=1 : H0 -> H0/C si on utilise la premiere formule)
 | 
|---|
 | 86 |   //  keq_ = sqrt(2.*O0_*H0*H0*zeq_) / SpeedOfLight_Cst;
 | 
|---|
 | 87 |   keq_ = 7.46e-2 * O0_ * h2 / (th2p7_*th2p7_);
 | 
|---|
 | 88 |     if(lp) cout<<"keq = "<<keq_<<" Mpc^-1"<<endl;
 | 
|---|
 | 89 | 
 | 
|---|
 | 90 |   // Formule 4 p 607
 | 
|---|
 | 91 |   double b1_eq4 = 0.313*pow(O0_*h2,-0.419)*(1. + 0.607*pow(O0_*h2,0.674));
 | 
|---|
 | 92 |   double b2_eq4 = 0.238*pow(O0_*h2,0.223);
 | 
|---|
 | 93 |   double zd_ = 1291. * pow(O0_*h2,0.251) / (1.+0.659* pow(O0_*h2,0.828))
 | 
|---|
 | 94 |              * (1. + b1_eq4*pow(Ob_*h2,b2_eq4));
 | 
|---|
 | 95 |     if(lp) cout<<"zd = "<<zd_<<endl;
 | 
|---|
 | 96 | 
 | 
|---|
 | 97 |   // Formule 5 page 607
 | 
|---|
 | 98 |   Req_ = 31.5*Ob_*h2 / th2p7P4 * (1.e3/zeq_);
 | 
|---|
 | 99 |   Rd_  = 31.5*Ob_*h2 / th2p7P4 * (1.e3/zd_);
 | 
|---|
 | 100 |     if(lp) cout<<"Req = "<<Req_<<" Rd = "<<Rd_<<endl;
 | 
|---|
 | 101 | 
 | 
|---|
 | 102 |   // Formule 6 p 607
 | 
|---|
 | 103 |   s_ = 2./(3.*keq_) * sqrt(6./Req_)
 | 
|---|
 | 104 |       * log( (sqrt(1.+Rd_) + sqrt(Rd_+Req_)) / (1.+sqrt(Req_)) );
 | 
|---|
 | 105 |     if(lp) cout<<"s = "<<s_<<" Mpc"<<endl;
 | 
|---|
 | 106 | 
 | 
|---|
 | 107 |   // Formule 7 page 607
 | 
|---|
 | 108 |   ksilk_ = 1.6*pow(Ob_*h2,0.52)*pow(O0_*h2,0.73) * (1. + pow(10.4*O0_*h2,-0.95));
 | 
|---|
 | 109 |     if(lp) cout<<"ksilk = "<<ksilk_<<" Mpc^-1"<<endl;
 | 
|---|
 | 110 | 
 | 
|---|
 | 111 |   // Formules 10 page 608
 | 
|---|
 | 112 |   double a1 = pow(46.9*O0_*h2,0.670) * (1. + pow(32.1*O0_*h2,-0.532));
 | 
|---|
 | 113 |   double a2 = pow(12.0*O0_*h2,0.424) * (1. + pow(45.0*O0_*h2,-0.582));
 | 
|---|
 | 114 |   alphac_ = pow(a1,-Ob_/O0_) * pow(a2,-pow(Ob_/O0_,3.));
 | 
|---|
 | 115 |   double b1 = 0.944 / (1. + pow(458.*O0_*h2,-0.708));
 | 
|---|
 | 116 |   double b2 = pow(0.395*O0_*h2,-0.0266);
 | 
|---|
 | 117 |   betac_ = 1 / ( 1. + b1*(pow(Oc_/O0_,b2) - 1.) );
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 |   // Formule 23 page 610
 | 
|---|
 | 120 |   bnode_ = 8.41 * pow(O0_*h2,0.435);
 | 
|---|
 | 121 |     if(lp) cout<<"bnode = "<<bnode_<<endl;
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 |   // Formule 14 page 608
 | 
|---|
 | 124 |   double y = (1.+zeq_)/(1.+zd_);
 | 
|---|
 | 125 |   double s1py = sqrt(1.+y);
 | 
|---|
 | 126 |   double Gy = y*( -6.*s1py + (2.+3.*y)*log((s1py+1.)/(s1py-1.)) );
 | 
|---|
 | 127 |   alphab_ = 2.07*keq_*s_*pow(1.+Rd_,-3./4.)*Gy;
 | 
|---|
 | 128 | 
 | 
|---|
 | 129 |   // Formule 24 page 610
 | 
|---|
 | 130 |   betab_ = 0.5 + Ob_/O0_
 | 
|---|
 | 131 |          + (3.-2.*Ob_/O0_) * sqrt(pow(17.2*O0_*h2,2.) + 1.);
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 |   // Formule 31 page 612
 | 
|---|
 | 134 |   alphag_ = 1.
 | 
|---|
 | 135 |           - 0.328*log(431.*O0_*h2)*Ob_/O0_
 | 
|---|
 | 136 |           + 0.38*log(22.3*O0_*h2)*pow(Ob_/O0_,2.);
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 |  // --- Pour la positon du premier pic acoustique
 | 
|---|
 | 139 |  // Formule 26 page 611
 | 
|---|
 | 140 |  double s_peak = 44.5*log(9.83/(O0_*h2)) / sqrt(1.+10.*pow(Ob_*h2,3./4.));  // Mpc
 | 
|---|
 | 141 |  // Formule 25 page 611
 | 
|---|
 | 142 |  kpeak_ = 5*M_PI/(2.*s_peak) * (1.+0.217*O0_*h2);  // 1/Mpc
 | 
|---|
 | 143 |    if(lp) cout<<"for 1er peak: s="<<s_peak<<" kpeak="<<kpeak_<<endl;
 | 
|---|
 | 144 | 
 | 
|---|
 | 145 |   return;
 | 
|---|
 | 146 | }
 | 
|---|
 | 147 | 
 | 
|---|
 | 148 | void TransfertEisenstein::Init_Without_Baryon(void)
 | 
|---|
 | 149 | {
 | 
|---|
 | 150 |   int lp = 1;
 | 
|---|
 | 151 | 
 | 
|---|
 | 152 |   nobaryon_ = true;
 | 
|---|
 | 153 |   O0_ = Oc_;
 | 
|---|
 | 154 |   if(lp) cout<<"Omatter="<<O0_<<" Ocdm="<<Oc_<<endl;
 | 
|---|
 | 155 |   th2p7_ = tcmb_/2.7;
 | 
|---|
 | 156 | }
 | 
|---|
 | 157 | 
 | 
|---|
 | 158 | TransfertEisenstein::~TransfertEisenstein(void)
 | 
|---|
 | 159 | {
 | 
|---|
 | 160 | }
 | 
|---|
 | 161 | 
 | 
|---|
 | 162 | void TransfertEisenstein::SetNoOscEnv(unsigned short nooscenv)
 | 
|---|
 | 163 | // To obtain the non-oscillatory part of the spectrum
 | 
|---|
 | 164 | // nooscenv = 0 : use the baryon oscillatory part of transfert function
 | 
|---|
 | 165 | // nooscenv = 1 : use approx. paragraph 3.3 p610 (middle of right column)
 | 
|---|
 | 166 | // nooscenv = 2 : use formulae 29+30+31 page 612
 | 
|---|
 | 167 | {
 | 
|---|
 | 168 |   if(nooscenv>2) {
 | 
|---|
 | 169 |     cout<<"TransfertEisenstein::SetNoOscEnv: Error bad nooscenv value: "<<nooscenv<<endl;
 | 
|---|
 | 170 |     throw ParmError("TransfertEisenstein::SetNoOscEnv: Error bad nooscenv value");
 | 
|---|
 | 171 |   }
 | 
|---|
 | 172 |   nooscenv_ = nooscenv;
 | 
|---|
 | 173 | }
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 | double TransfertEisenstein::T0tild(double k,double alphac,double betac)
 | 
|---|
 | 176 | {
 | 
|---|
 | 177 |   // Formule 10 p 608
 | 
|---|
 | 178 |   //double q = k*th2p7_*th2p7_/(O0_*h_*h_);
 | 
|---|
 | 179 |   double q = k/(13.41*keq_);
 | 
|---|
 | 180 |   // Formule 20 p 610
 | 
|---|
 | 181 |   double C = (14.2/alphac) + 386./(1.+69.9*pow(q,1.08));
 | 
|---|
 | 182 |   // Formule 19 p 610
 | 
|---|
 | 183 |   double x = log(M_E+1.8*betac*q);
 | 
|---|
 | 184 |   return x / (x + C*q*q);
 | 
|---|
 | 185 | }
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 | double TransfertEisenstein::operator() (double k)
 | 
|---|
 | 188 | {
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 |   // --- Pour zero baryon
 | 
|---|
 | 191 |   //  OU Pour function lissee sans oscillation baryon
 | 
|---|
 | 192 |   if(nobaryon_  || nooscenv_ == 2) {
 | 
|---|
 | 193 |     double gamma = O0_*h_;
 | 
|---|
 | 194 |     // Formule 30 page 612 (pour fct lissee)
 | 
|---|
 | 195 |     if( nobaryon_==false && nooscenv_ == 2 )
 | 
|---|
 | 196 |       gamma = O0_*h_*(alphag_ + (1.-alphag_)/(1.+pow(0.43*k*s_,4.)));
 | 
|---|
 | 197 |     // Formule 28 page 612
 | 
|---|
 | 198 |     double q = k / h_ * th2p7_*th2p7_/gamma;  // Mpc^-1
 | 
|---|
 | 199 |     // Formules 29 page 612
 | 
|---|
 | 200 |     double l0 = log(2.*M_E + 1.8*q);
 | 
|---|
 | 201 |     double c0 = 14.2 + 731./(1.+62.5*q);
 | 
|---|
 | 202 |     return l0 / (l0 + c0*q*q);
 | 
|---|
 | 203 |   }
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 |   // --- CDM
 | 
|---|
 | 206 |   double f = 1. / (1. + pow(k*s_/5.4,4.));
 | 
|---|
 | 207 |   double Tc = f*T0tild(k,1.,betac_) + (1.-f)*T0tild(k,alphac_,betac_);
 | 
|---|
 | 208 | 
 | 
|---|
 | 209 |   // --- Baryons
 | 
|---|
 | 210 |   // Formule 22 page 610
 | 
|---|
 | 211 |   double stk, ksbnode = k*s_/bnode_;
 | 
|---|
 | 212 |   if(ksbnode<0.001) stk =s_ * ksbnode;
 | 
|---|
 | 213 |      else   stk = s_ / pow(1. + pow(1./ksbnode,3.), 1/.3);
 | 
|---|
 | 214 |   // Formule 21 page 610
 | 
|---|
 | 215 |   double j0kst = 0.;
 | 
|---|
 | 216 |   if(nooscenv_ == 1) j0kst = pow(1.+pow(k*stk,4.) , -1./4.); //lissee sans oscillation baryon
 | 
|---|
 | 217 |   else {
 | 
|---|
 | 218 |     double x = k*stk;
 | 
|---|
 | 219 |     if(x<0.01) j0kst = 1. - x*x/6.*(1.-x*x/20.);
 | 
|---|
 | 220 |       else j0kst = sin(x)/x;
 | 
|---|
 | 221 |     ////if(k>0.038&&k<0.07) cout<<"k="<<k<<" stk="<<stk<<" x="<<x<<endl;
 | 
|---|
 | 222 |   }
 | 
|---|
 | 223 |   double Tb = T0tild(k,1.,1.) / (1. + pow(k*s_/5.2,2.));
 | 
|---|
 | 224 |   Tb += alphab_/(1.+pow(betab_/(k*s_),3.)) * exp(-pow(k/ksilk_,1/4.));
 | 
|---|
 | 225 |   Tb *= j0kst;
 | 
|---|
 | 226 | 
 | 
|---|
 | 227 |   // --- Total
 | 
|---|
 | 228 |   double T = (Ob_/O0_)*Tb + (Oc_/O0_)*Tc;
 | 
|---|
 | 229 | 
 | 
|---|
 | 230 |   return T;
 | 
|---|
 | 231 | }
 | 
|---|
 | 232 | 
 | 
|---|
 | 233 | double TransfertEisenstein::KPeak(void)
 | 
|---|
 | 234 | // Position du premier pic acoustic
 | 
|---|
 | 235 | {
 | 
|---|
 | 236 |  if(nobaryon_) return -1.;
 | 
|---|
 | 237 |  return kpeak_;
 | 
|---|
 | 238 | }
 | 
|---|
 | 239 | 
 | 
|---|
 | 240 | 
 | 
|---|
 | 241 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 242 | //********************* GrowthFactor ********************//
 | 
|---|
 | 243 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 244 | 
 | 
|---|
 | 245 | // From Eisenstein & Hu ApJ 496:605-614 1998 April 1
 | 
|---|
 | 246 | GrowthFactor::GrowthFactor(double OmegaMatter0,double OmegaLambda0)
 | 
|---|
 | 247 |   : O0_(OmegaMatter0) , Ol_(OmegaLambda0) , Ok_(1.-OmegaMatter0-OmegaLambda0)
 | 
|---|
 | 248 | {
 | 
|---|
 | 249 |   if(OmegaMatter0==0.) {
 | 
|---|
 | 250 |     cout<<"GrowthFactor::GrowthFactor: Error bad OmegaMatter0  value : "<<OmegaMatter0<<endl;
 | 
|---|
 | 251 |     throw ParmError("GrowthFactor::GrowthFactor: Error badOmegaMatter0  value");
 | 
|---|
 | 252 |   }
 | 
|---|
 | 253 |   norm_ = 1.; // puisque (*this)(0.) a besoin de norm_
 | 
|---|
 | 254 |   norm_ = (*this)(0.);
 | 
|---|
 | 255 |   cout<<"GrowthFactor::GrowthFactor : norm="<<norm_<<endl;
 | 
|---|
 | 256 | }
 | 
|---|
 | 257 | 
 | 
|---|
 | 258 | GrowthFactor::GrowthFactor(GrowthFactor& d1)
 | 
|---|
 | 259 |   : O0_(d1.O0_) , Ol_(d1.Ol_) , Ok_(d1.Ok_) , norm_(d1.norm_)
 | 
|---|
 | 260 | {
 | 
|---|
 | 261 | }
 | 
|---|
 | 262 | 
 | 
|---|
 | 263 | GrowthFactor::~GrowthFactor(void)
 | 
|---|
 | 264 | {
 | 
|---|
 | 265 | }
 | 
|---|
 | 266 | 
 | 
|---|
 | 267 | double GrowthFactor::operator() (double z)
 | 
|---|
 | 268 | // see Formulae A4 + A5 + A6 page 614
 | 
|---|
 | 269 | {
 | 
|---|
 | 270 |  z += 1.;
 | 
|---|
 | 271 |  double z2 = z*z, z3 = z2*z;
 | 
|---|
 | 272 |  double den = Ol_ + Ok_*z2 + O0_*z3;
 | 
|---|
 | 273 |  double o0z = O0_ *z3 / den;
 | 
|---|
 | 274 |  double olz = Ol_ / den;
 | 
|---|
 | 275 | 
 | 
|---|
 | 276 |  // 4./7. = 0.571429
 | 
|---|
 | 277 |  double D1z = pow(o0z,0.571429) - olz + (1.+o0z/2.)*(1.+olz/70.);
 | 
|---|
 | 278 |  D1z = 2.5*o0z / z / D1z;
 | 
|---|
 | 279 | 
 | 
|---|
 | 280 |  return D1z / norm_;
 | 
|---|
 | 281 | }
 | 
|---|
 | 282 | 
 | 
|---|
 | 283 | 
 | 
|---|
 | 284 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 285 | //************** PkSpectrum0 et PkSpectrumZ *************//
 | 
|---|
 | 286 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 287 | 
 | 
|---|
 | 288 | PkSpectrum0::PkSpectrum0(InitialSpectrum& pkinf,TransfertEisenstein& tf)
 | 
|---|
 | 289 |   : pkinf_(pkinf) , tf_(tf)
 | 
|---|
 | 290 | {
 | 
|---|
 | 291 | }
 | 
|---|
 | 292 | 
 | 
|---|
 | 293 | PkSpectrum0::PkSpectrum0(PkSpectrum0& pk0)
 | 
|---|
 | 294 |   : pkinf_(pk0.pkinf_) , tf_(pk0.tf_)
 | 
|---|
 | 295 | {
 | 
|---|
 | 296 | }
 | 
|---|
 | 297 | 
 | 
|---|
 | 298 | PkSpectrum0::~PkSpectrum0(void)
 | 
|---|
 | 299 | {
 | 
|---|
 | 300 | }
 | 
|---|
 | 301 | 
 | 
|---|
 | 302 | double PkSpectrum0::operator() (double k)
 | 
|---|
 | 303 | {
 | 
|---|
 | 304 |   double tf = tf_(k);
 | 
|---|
 | 305 |   double pkinf = pkinf_(k);
 | 
|---|
 | 306 |   return pkinf *tf*tf;
 | 
|---|
 | 307 | }
 | 
|---|
 | 308 | 
 | 
|---|
 | 309 | //------------------------------------
 | 
|---|
 | 310 | PkSpectrumZ::PkSpectrumZ(PkSpectrum0& pk0,GrowthFactor& d1,double zref)
 | 
|---|
 | 311 |   : pk0_(pk0) , d1_(d1) , zref_(zref) , scale_(1.) , typspec_(0)
 | 
|---|
 | 312 |   , zold_(-1.) , d1old_(1.)
 | 
|---|
 | 313 | {
 | 
|---|
 | 314 | }
 | 
|---|
 | 315 | 
 | 
|---|
 | 316 | PkSpectrumZ::PkSpectrumZ(PkSpectrumZ& pkz)
 | 
|---|
 | 317 |   : pk0_(pkz.pk0_) , d1_(pkz.d1_) , zref_(pkz.zref_) , scale_(pkz.scale_) , typspec_(0)
 | 
|---|
 | 318 |   , zold_(pkz.zold_) , d1old_(pkz.d1old_)
 | 
|---|
 | 319 | {
 | 
|---|
 | 320 | }
 | 
|---|
 | 321 | 
 | 
|---|
 | 322 | PkSpectrumZ::~PkSpectrumZ(void) 
 | 
|---|
 | 323 | {
 | 
|---|
 | 324 | }
 | 
|---|
 | 325 | 
 | 
|---|
 | 326 | void PkSpectrumZ::SetTypSpec(unsigned short typspec)
 | 
|---|
 | 327 |   // typsec = 0 : compute Pk(k)
 | 
|---|
 | 328 |   //        = 1 : compute Delta^2(k) = k^3*Pk(k)/2Pi^2
 | 
|---|
 | 329 | {
 | 
|---|
 | 330 |   if(typspec>1) {
 | 
|---|
 | 331 |     cout<<"PkSpectrumZ::SetTypSpec: Error bad typspec value: "<<typspec<<endl;
 | 
|---|
 | 332 |     throw ParmError("PkSpectrumZ::SetTypSpec: Error bad typspec value");
 | 
|---|
 | 333 |   }
 | 
|---|
 | 334 |   typspec_ = typspec;
 | 
|---|
 | 335 | }
 | 
|---|
 | 336 | 
 | 
|---|
 | 337 | double PkSpectrumZ::operator() (double k)
 | 
|---|
 | 338 | {
 | 
|---|
 | 339 |   return (*this)(k,zref_);
 | 
|---|
 | 340 | }
 | 
|---|
 | 341 | 
 | 
|---|
 | 342 | double PkSpectrumZ::operator() (double k,double z)
 | 
|---|
 | 343 | {
 | 
|---|
 | 344 |   double d1;
 | 
|---|
 | 345 |   if(z == zold_) d1 = d1old_;
 | 
|---|
 | 346 |     else {d1 = d1old_ = d1_(z); zold_ = z;}
 | 
|---|
 | 347 | 
 | 
|---|
 | 348 |   double v = pk0_(k) * d1*d1;
 | 
|---|
 | 349 |   if(typspec_) v *= k*k*k/(2.*M_PI*M_PI);
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 |   return scale_ * v;
 | 
|---|
 | 352 | }
 | 
|---|
 | 353 | 
 | 
|---|
 | 354 | 
 | 
|---|
 | 355 | 
 | 
|---|
 | 356 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 357 | //******************* VarianceSpectrum ******************//
 | 
|---|
 | 358 | ///////////////////////////////////////////////////////////
 | 
|---|
 | 359 | 
 | 
|---|
 | 360 | VarianceSpectrum::VarianceSpectrum(GenericFunc& pk,unsigned short typfilter=0)
 | 
|---|
 | 361 |   : pk_(pk) , R_(0.)
 | 
|---|
 | 362 | {
 | 
|---|
 | 363 |   SetFilter(typfilter);
 | 
|---|
 | 364 | }
 | 
|---|
 | 365 | 
 | 
|---|
 | 366 | VarianceSpectrum::VarianceSpectrum(VarianceSpectrum& vpk)
 | 
|---|
 | 367 |   : pk_(vpk.pk_) , R_(vpk.R_)
 | 
|---|
 | 368 | {
 | 
|---|
 | 369 |   SetFilter(vpk.typfilter_);
 | 
|---|
 | 370 | }
 | 
|---|
 | 371 | 
 | 
|---|
 | 372 | VarianceSpectrum::~VarianceSpectrum(void)
 | 
|---|
 | 373 | {
 | 
|---|
 | 374 | }
 | 
|---|
 | 375 | 
 | 
|---|
 | 376 | //------------------------------------
 | 
|---|
 | 377 | void VarianceSpectrum::SetFilter(unsigned short typfilter)
 | 
|---|
 | 378 | // typfilter = 0 : spherical 3D top-hat
 | 
|---|
 | 379 | //           = 1 : spherical 3D gaussian
 | 
|---|
 | 380 | //           = 2 : no filter juste integrate spectrum)
 | 
|---|
 | 381 | {
 | 
|---|
 | 382 |   if(typfilter>2) {
 | 
|---|
 | 383 |     cout<<"VarianceSpectrum::SetFilter: Error bad value for type of filter"<<endl;
 | 
|---|
 | 384 |     throw ParmError("VarianceSpectrum::SetFilter: Error bad value for type of filter");
 | 
|---|
 | 385 |   }
 | 
|---|
 | 386 |   typfilter_ = typfilter;
 | 
|---|
 | 387 | }
 | 
|---|
 | 388 | 
 | 
|---|
 | 389 | void VarianceSpectrum::SetInteg(double dperc,double dlogkinc,double dlogkmax,unsigned short glorder)
 | 
|---|
 | 390 | // ATTENTION: on n'integre pas f(k)*dk mais k*f(k)*d(log10(k))
 | 
|---|
 | 391 | // see argument details in function IntegrateFuncLog (integfunc.cc)
 | 
|---|
 | 392 | {
 | 
|---|
 | 393 |   dperc_ = dperc;  if(dperc_<=0.) dperc_ = 0.1;
 | 
|---|
 | 394 |   dlogkinc_ = dlogkinc;
 | 
|---|
 | 395 |   dlogkmax_ = dlogkmax;
 | 
|---|
 | 396 |   glorder_ = glorder;
 | 
|---|
 | 397 | }
 | 
|---|
 | 398 | 
 | 
|---|
 | 399 | 
 | 
|---|
 | 400 | //------------------------------------
 | 
|---|
 | 401 | double VarianceSpectrum::Filter2(double x)
 | 
|---|
 | 402 | // ATTENTION: c'est le filtre au carre qui est renvoye
 | 
|---|
 | 403 | {
 | 
|---|
 | 404 |   // Just integrate the spectrum without filtering
 | 
|---|
 | 405 |   if(typfilter_ == 2) return 1.;
 | 
|---|
 | 406 | 
 | 
|---|
 | 407 |   double x2 = x*x;
 | 
|---|
 | 408 |   // Filtre gaussien G(x) = exp(-x^2/2)
 | 
|---|
 | 409 |   //        remarque G(x)^2 = exp(-x^2)
 | 
|---|
 | 410 |   // on prend le DL de G(x)^2 pour x->0 a l'ordre O(x^6)
 | 
|---|
 | 411 |   //             DL(x) = 1-x^2*(1-x^2/2)
 | 
|---|
 | 412 |   //             pour x<0.01  |DL(x)-G(X)^2|<2.0e-13
 | 
|---|
 | 413 |   if(typfilter_ == 1)
 | 
|---|
 | 414 |     if(x<0.01) return 1.-x2*(1.-x2/2.); else return exp(-x2);
 | 
|---|
 | 415 | 
 | 
|---|
 | 416 |   // Filtre top-hat T(x) = 3*(sin(x)-x*cos(x))/x^3
 | 
|---|
 | 417 |   // --- Gestion de la pseudo-divergence pour x->0
 | 
|---|
 | 418 |   // on prend le DL de T(x)^2 pour x->0 a l'ordre O(x^7)
 | 
|---|
 | 419 |   //             DL(x) = 1-x^2/5*(1-3*x^2/35*(1-4*x^2/81))
 | 
|---|
 | 420 |   //             pour x<0.1  |DL(x)-T(X)^2|<2.5e-13
 | 
|---|
 | 421 |   double f2=0.;
 | 
|---|
 | 422 |   if(x<0.1) {
 | 
|---|
 | 423 |     f2 = 1.-x2/5.*(1.-3.*x2/35.*(1.-4.*x2/81.));
 | 
|---|
 | 424 |   } else {
 | 
|---|
 | 425 |     f2 = 3.*(sin(x)-x*cos(x))/(x2*x);
 | 
|---|
 | 426 |     f2 *= f2;
 | 
|---|
 | 427 |   }
 | 
|---|
 | 428 |   return f2;
 | 
|---|
 | 429 |   
 | 
|---|
 | 430 | }
 | 
|---|
 | 431 | 
 | 
|---|
 | 432 | double VarianceSpectrum::Variance(double R,double kmin,double kmax)
 | 
|---|
 | 433 | // Compute variance of spectrum pk_ by integration
 | 
|---|
 | 434 | // Input:
 | 
|---|
 | 435 | //     R = taille du filter top-hat ou gaussien
 | 
|---|
 | 436 | //     kmin,kmax = bornes en k de l'integrale pour calculer la variance
 | 
|---|
 | 437 | // Return:
 | 
|---|
 | 438 | //     valeur de la variance (sigma^2)
 | 
|---|
 | 439 | // Remarque:
 | 
|---|
 | 440 | //   la meilleure approximation du filtre top-hat (R) est un filtre gaussien avec (Rg=R/sqrt(5))
 | 
|---|
 | 441 | //   la variance renvoyee est la variance de la masse
 | 
|---|
 | 442 | {
 | 
|---|
 | 443 |   if(R<=0. || kmin<=0 || kmax<=0. || kmin>=kmax) {
 | 
|---|
 | 444 |     cout<<"VarianceSpectrum::Variance: Error R<=0 or kmin<=0 or kmax<=0 or kmin>=kmax"<<endl;
 | 
|---|
 | 445 |     throw ParmError("VarianceSpectrum::Variance: Error R<=0 or kmin<=0 or kmax<=0 or kmin>=kmax");
 | 
|---|
 | 446 |   }
 | 
|---|
 | 447 | 
 | 
|---|
 | 448 |   R_ = R;
 | 
|---|
 | 449 |   double lkmin = log10(kmin), lkmax = log10(kmax);
 | 
|---|
 | 450 | 
 | 
|---|
 | 451 |   double var = IntegrateFuncLog(*this,lkmin,lkmax,dperc_,dlogkinc_,dlogkmax_,glorder_);
 | 
|---|
 | 452 | 
 | 
|---|
 | 453 |   return var;
 | 
|---|
 | 454 | }
 | 
|---|
 | 455 | 
 | 
|---|
 | 456 | //------------------------------------
 | 
|---|
 | 457 | double VarianceSpectrum::FindMaximum(double R,double kmin,double kmax,double eps)
 | 
|---|
 | 458 | // Retourne le maximum de la fonction a integrer
 | 
|---|
 | 459 | // La recherche a lieu entre [kmin,kmax] par pas logarithmiques
 | 
|---|
 | 460 | // Input:
 | 
|---|
 | 461 | //     R : taille du filter top-hat ou gaussien
 | 
|---|
 | 462 | //     kmin,kmax : intervalle de recherche
 | 
|---|
 | 463 | //     eps : precision requise sur les valeurs
 | 
|---|
 | 464 | // Return:
 | 
|---|
 | 465 | //     position (en k) du maximum
 | 
|---|
 | 466 | {
 | 
|---|
 | 467 |   if(R<=0. || kmin<=0 || kmax<=0. || kmin>=kmax) {
 | 
|---|
 | 468 |     cout<<"VarianceSpectrum::FindMaximum: Error R<=0 or kmin<=0 or kmax<=0 or kmin>=kmax || eps<=0"<<endl;
 | 
|---|
 | 469 |     throw ParmError("VarianceSpectrum::FindMaximum: Error R<=0 or kmin<=0 or kmax<=0 or kmin>=kmax || eps<=0");
 | 
|---|
 | 470 |   }
 | 
|---|
 | 471 | 
 | 
|---|
 | 472 |   R_ = R;
 | 
|---|
 | 473 | 
 | 
|---|
 | 474 |   int n = 10; // toujours >2
 | 
|---|
 | 475 |   double lkmin = log10(kmin), lkmax = log10(kmax), dlk = (lkmax-lkmin)/n;
 | 
|---|
 | 476 | 
 | 
|---|
 | 477 |   double lkfind=lkmin, pkfind=-1.;
 | 
|---|
 | 478 |   while(1) {
 | 
|---|
 | 479 |     for(int i=0; i<=n; i++) {
 | 
|---|
 | 480 |       double lk = lkmin  + i*dlk;
 | 
|---|
 | 481 |       double v = (*this)(pow(10.,lk));
 | 
|---|
 | 482 |       if(v<pkfind) continue;
 | 
|---|
 | 483 |       pkfind = v; lkfind = lk;
 | 
|---|
 | 484 |     }
 | 
|---|
 | 485 |     //cout<<"VarianceSpectrum::FindMaximum: lkfind="<<lkfind<<" pkfind="<<pkfind
 | 
|---|
 | 486 |     //    <<" lkmin,max="<<lkmin<<","<<lkmax<<" dlk="<<dlk<<endl;
 | 
|---|
 | 487 |     // --- Convergence si l'encadrement de "kfind" est tel que "dk/kfind<eps"
 | 
|---|
 | 488 |     // On a dk = 10^(lkfind+dlk) - 10^(lkfind-dlk) = kfind * (10^(dlk) - 10^(-dlk))
 | 
|---|
 | 489 |     if( pow(10.,dlk)-pow(10.,-dlk) < eps ) break;
 | 
|---|
 | 490 |     if(lkfind-dlk>lkmin) lkmin = lkfind-dlk;
 | 
|---|
 | 491 |     if(lkfind+dlk<lkmax) lkmax = lkfind+dlk;
 | 
|---|
 | 492 |     dlk = (lkmax-lkmin)/n;
 | 
|---|
 | 493 |   }
 | 
|---|
 | 494 | 
 | 
|---|
 | 495 |   return pow(10.,lkfind);
 | 
|---|
 | 496 | }
 | 
|---|
 | 497 | 
 | 
|---|
 | 498 | int VarianceSpectrum::FindLimits(double R,double high,double &kmin,double &kmax,double eps)
 | 
|---|
 | 499 | // Retourne "[kmin,kmax]" tel que la fonction a integrer soit "f(k) <= high"
 | 
|---|
 | 500 | //   La recherche a lieu entre [kmin,kmax] par pas logarithmiques
 | 
|---|
 | 501 | // Input:
 | 
|---|
 | 502 | //     R : taille du filter top-hat ou gaussien
 | 
|---|
 | 503 | //     kmin,kmax : intervalle de recherche
 | 
|---|
 | 504 | //     eps : precision requise sur les valeurs kmin et kmax
 | 
|---|
 | 505 | // Output:
 | 
|---|
 | 506 | //     kmin,kmax telles que "f(k) <= high"
 | 
|---|
 | 507 | // Return:
 | 
|---|
 | 508 | //     rc  = 0 si OK
 | 
|---|
 | 509 | //     rc |= 1 "f(kmin) >= high"   (bit0 =1)
 | 
|---|
 | 510 | //     rc |= 2 "f(kmax) >= high"   (bit1 =1)
 | 
|---|
 | 511 | //     rc |= 4 "f(k) < high pour tout k"   (bit2 =1)
 | 
|---|
 | 512 | {
 | 
|---|
 | 513 |   if(R<=0. || kmin<=0 || kmax<=0. || kmin>=kmax  || eps<=0.) {
 | 
|---|
 | 514 |     cout<<"VarianceSpectrum::FindLimits: Error R<=0 or kmin<=0 or kmax<=0 or kmin>=kmax or eps<=0"<<endl;
 | 
|---|
 | 515 |     throw ParmError("VarianceSpectrum::FindLimits: Error R<=0 or kmin<=0 or kmax<=0 or kmin>=kmax || eps<=0");
 | 
|---|
 | 516 |   }
 | 
|---|
 | 517 | 
 | 
|---|
 | 518 |   R_ = R;
 | 
|---|
 | 519 |   int n = 10; // toujours >2
 | 
|---|
 | 520 | 
 | 
|---|
 | 521 |   int rc = 0;
 | 
|---|
 | 522 |   double lkmin,lkmax,dlk,lkfind;
 | 
|---|
 | 523 | 
 | 
|---|
 | 524 |   // --- Find kmin
 | 
|---|
 | 525 |   lkmin=log10(kmin); lkmax=log10(kmax); dlk=(lkmax-lkmin)/n;
 | 
|---|
 | 526 |   while(1) {
 | 
|---|
 | 527 |     lkfind = lkmin;
 | 
|---|
 | 528 |     for(int i=0;i<=n;i++) {
 | 
|---|
 | 529 |       if( (*this)(pow(10,lkfind)) >= high ) break;   //cmvbug
 | 
|---|
 | 530 |       lkfind = lkmin + i*dlk;
 | 
|---|
 | 531 |     }
 | 
|---|
 | 532 |     //cout<<"VarianceSpectrum::FindLimits[kmin]: lkfind="<<lkfind
 | 
|---|
 | 533 |     //    <<" lkmin,max="<<lkmin<<","<<lkmax<<" dlk="<<dlk<<endl;
 | 
|---|
 | 534 |     if(fabs(lkfind-lkmax)<dlk/2.) {rc |= 4; return rc;} // protect against f(k)<high for all k
 | 
|---|
 | 535 |     if( pow(10.,dlk)-pow(10.,-dlk) < eps ) break;
 | 
|---|
 | 536 |     if(lkfind-dlk>lkmin) lkmin = lkfind-dlk;
 | 
|---|
 | 537 |     if(lkfind+dlk<lkmax) lkmax = lkfind+dlk;
 | 
|---|
 | 538 |     dlk = (lkmax-lkmin)/n;
 | 
|---|
 | 539 |   }
 | 
|---|
 | 540 |   if(lkfind-lkmin<dlk/2.) rc |= 1;  // f(kmin) >= high
 | 
|---|
 | 541 |   else kmin = pow(10.,lkmin);
 | 
|---|
 | 542 |   //cout<<"rc="<<rc<<" lkmin="<<lkmin<<"  pk="<<(*this)(pow(10.,lkmin))<<endl;
 | 
|---|
 | 543 | 
 | 
|---|
 | 544 |   // --- Find kmax
 | 
|---|
 | 545 |   lkmin=log10(kmin); lkmax=log10(kmax); dlk=(lkmax-lkmin)/n;
 | 
|---|
 | 546 |   while(1) {
 | 
|---|
 | 547 |     lkfind=lkmax;
 | 
|---|
 | 548 |     for(int i=0;i<=n;i++) {
 | 
|---|
 | 549 |       if( (*this)(pow(10,lkfind)) >= high ) break;   //cmvbug
 | 
|---|
 | 550 |       lkfind -= dlk;
 | 
|---|
 | 551 |       lkfind = lkmax - i*dlk;
 | 
|---|
 | 552 |     }
 | 
|---|
 | 553 |     //cout<<"VarianceSpectrum::FindLimits[kmax]: lkfind="<<lkfind
 | 
|---|
 | 554 |     //    <<" lkmin,max="<<lkmin<<","<<lkmax<<" dlk="<<dlk<<endl;
 | 
|---|
 | 555 |     if( pow(10.,dlk)-pow(10.,-dlk) < eps ) break;
 | 
|---|
 | 556 |     if(lkfind-dlk>lkmin) lkmin = lkfind-dlk;
 | 
|---|
 | 557 |     if(lkfind+dlk<lkmax) lkmax = lkfind+dlk;
 | 
|---|
 | 558 |     dlk = (lkmax-lkmin)/n;
 | 
|---|
 | 559 |   }
 | 
|---|
 | 560 |   if(lkmax-lkfind<dlk/2.) rc |= 2;  // f(kmax) >= high
 | 
|---|
 | 561 |   else kmax = pow(10.,lkmax);
 | 
|---|
 | 562 |   //cout<<"rc="<<rc<<" lkmax="<<lkmax<<"  pk="<<(*this)(pow(10.,lkmax))<<endl;
 | 
|---|
 | 563 | 
 | 
|---|
 | 564 |   return rc;
 | 
|---|
 | 565 | }
 | 
|---|