CosmoBolognaLib
Free Software C++/Python libraries for cosmological calculations
BAO.cpp
Go to the documentation of this file.
1 /********************************************************************
2  * Copyright (C) 2010 by Federico Marulli and Alfonso Veropalumbo *
3  * federico.marulli3@unibo.it *
4  * *
5  * This program is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU General Public License as *
7  * published by the Free Software Foundation; either version 2 of *
8  * the License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public *
16  * License along with this program; if not, write to the Free *
17  * Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ********************************************************************/
20 
34 #include "Cosmology.h"
35 #include "recombination.Recfast.h"
36 #include "cosmology.Recfast.h"
37 
38 using namespace std;
39 
40 using namespace cbl;
41 
42 
43 // =====================================================================================
44 
45 
46 //redshift at wich occurs baryon photon decoupling, see Hu & Sugiyama (1996).
48 {
49  double ombh2 = m_Omega_baryon*m_hh*m_hh;
50  double omdmh2 = m_Omega_CDM*m_hh*m_hh;
51  double g1 = 0.0783*pow(ombh2,-0.238)/(1.+39.5*pow(ombh2,0.763));
52  double g2 = 0.560/(1+21.1*pow(ombh2,1.81));
53  double zdec = 1048*(1.+0.00124*pow(ombh2,-0.738))*(1.+g1*pow(ombh2+omdmh2,g2));
54  return zdec;
55 
56 }
57 
58 
59 // =====================================================================================
60 
61 
63 {
64  double wb = m_Omega_baryon*m_hh*m_hh;
65  double wb2 = wb*wb;
66  double dNeff = m_massless_neutrinos+m_massive_neutrinos-3.046;
67  double dNeff2 = dNeff*dNeff;
68 
69  double Yp = 0.2311+0.9520*wb-11.27*wb2+dNeff*(0.01356+0.008581*wb-0.1810*wb2)+dNeff2*(-0.0009795-0.001370*wb+0.01746*wb2);
70 
71  vector<double> params(14);
72  int npz=10000;
73  double zstart=1.0e+4, zend=0.001;
74 
75  params[0]=npz;
76  params[1]=zstart;
77  params[2]=zend;
78  params[3] = Yp; // Yp
79  params[4] = par::TCMB; // Temperature of CMB at z=0
80  params[5] = m_Omega_matter; // Omega matter
81  params[6] = m_Omega_baryon; // Omega Baryons
82  params[7] = m_Omega_DE; // Omega Lambda
83  params[8] = m_Omega_k; // Omega Curvature
84  params[9] = m_hh; // h100
85  params[10] = m_massless_neutrinos+m_massive_neutrinos; // effective number of neutrinos
86  params[11] = 1.14; // fudge-factor; normally F=1.14
87 
88  params[12] = 0.; // fDM [eV/s] which gives annihilation efficiency;
89  // typical value fDM=2.0e-24 eV/s (see Chluba 2010 for definitions)
90  params[13] = 0; // switch on/off recombination corrections (Chluba & Thomas 2010)
91 
92  vector<double> zarr(npz), Xe_H(npz), Xe_He(npz), Xe(npz), TM(npz);
93 
94  Xe_frac(&params[0], &zarr[0], &Xe_H[0], &Xe_He[0], &Xe[0], &TM[0], 0);
95 
96  double HHc = m_hh*100*pow(cbl::par::kilo*cbl::par::pc, -1);
97  double cc_m = par::cc*1000.;
98 
99  double rho_cr = 3.*pow(HHc, 2)/(8.*par::pi*par::GN);
100 
101  double rho_b = m_Omega_baryon*rho_cr;
102  double rho_rad = 4.*par::sSB*pow(par::TCMB, 4)*pow(cc_m, -3);
103  double R = 3./4*rho_b/rho_rad;
104 
105  double Np = rho_b*(1.-Yp)/par::mp;
106  double kthom = 6.6524616e-29;
107 
108  vector<double> zz(npz), dtau(npz), tau(npz);
109  for(int i=0; i<npz; i++){
110  zz[i] = zarr[npz-1-i];
111  double a = 1./(1+zz[i]);
112  dtau[i] = Xe[npz-1-i]*Np*kthom/R*a/(HHc*EE(zz[i]));
113  }
114 
115  glob::FuncGrid interp_dtau(zz, dtau, "Spline");
116 
117  auto integrand = [&] (double redshift) {return interp_dtau(redshift);};
118 
119  auto func = [&] (double redshift)
120  {
121  return wrapper::gsl::GSL_integrate_qag(integrand, 0., redshift);
122  };
123 
124  return wrapper::gsl::GSL_root_brent (func, 1., 500, 2000);
125  /*
126  double wb = m_Omega_baryon*m_hh*m_hh;
127  double wm = m_Omega_matter*m_hh*m_hh;
128 
129  double b1 = 0.313*pow(wm,-0.419)*(1+0.607*pow(wm,0.674));
130  double b2 = 0.238*pow(wm,0.223);
131  double zd = 1291.*pow(wm,0.251)*(1+b1*pow(wb,b2))/(1+0.659*pow(wm,0.828));
132  return zd;
133 */
134 }
135 
136 
137 // =====================================================================================
138 
139 // Sound horizon at drag epoch
140 
141 double cbl::cosmology::Cosmology::rs (const std::string method_Pk, const double T_CMB) const
142 {
143  if (method_Pk=="EisensteinHu")
144  return rs_EH(T_CMB);
145 
146  else if (method_Pk=="CAMB")
147  return rs_CAMB();
148 
149  else
150  return ErrorCBL(" the input parameter method_Pk is not allowed!", "rs", "BAO.cpp");
151 }
152 
153 
154 // =====================================================================================
155 
156 // Sound horizon at drag epoch (Eisentein & Hu 1998, Section 2.1)
157 
158 double cbl::cosmology::Cosmology::rs_EH (const double T_CMB) const
159 {
160  double Om0h2 = m_Omega_matter*pow(m_hh,2);
161  double Ombh2 = m_Omega_baryon*pow(m_hh,2);
162  double Tratio = T_CMB/2.7;
163 
164  double zeq = 2.5*pow(10.,4)*Om0h2*pow(Tratio,-4); // Matter radiation Equivalence (explicit function?)
165  double keq = 7.46*pow(10.,-2)*Om0h2*pow(Tratio,-2); // Particle Horizon at zeq
166 
167  double b1 = 0.313 * pow(Om0h2,-0.419) * (1.+0.607*pow(Om0h2,0.674));
168  double b2 = 0.238 * pow(Om0h2,0.223);
169 
170  double zdrag = 1291.*(pow(Om0h2,0.251)/(1.+0.659*pow(Om0h2,0.828)))*(1.+b1*pow(Ombh2,b2));
171 
172  double Rd = 31.5*Ombh2*pow(Tratio,-4)*pow(10.,3)/zdrag;
173  double Req = 31.5*Ombh2*pow(Tratio,-4)*pow(10.,3)/zeq;
174 
175  double rs = 2.*pow(3.*keq,-1)*pow(6./Req,0.5)*log((pow(1.+Rd,0.5)+pow(Rd+Req,0.5))/(1.+pow(Req,0.5)));
176  return ((m_unit) ? rs*m_hh : rs);
177 }
178 
179 
180 // =====================================================================================
181 
182 
184 {
185  double wcb= m_Omega_matter*pow(m_hh,2);
186  double wb= m_Omega_baryon*pow(m_hh,2);
187  double wnu = m_Omega_neutrinos*pow(m_hh,2);
188 
189  double rd = 55.154*exp(-72.3*pow(wnu+0.0006,2))/(pow(wcb,0.25351)*pow(wb,0.12807));
190  return ((m_unit) ? rd*m_hh : rd);
191 }
192 
193 
194 // =====================================================================================
195 
196 
197 double cbl::cosmology::Cosmology::ys (const double redshift, const std::string method_Pk, const double T_CMB) const
198 {
199  return rs(method_Pk, T_CMB)/((m_unit) ? D_V(redshift)/m_hh : D_V(redshift));
200 }
201 
202 
203 // =====================================================================================
204 
205 
206 double cbl::cosmology::Cosmology::Az (const double redshift) const
207 {
208  return ((m_unit) ? D_V(redshift)/m_hh : D_V(redshift))*1.e2*sqrt(m_Omega_matter*m_hh*m_hh)/(par::cc*redshift);
209 }
210 
211 
212 // =====================================================================================
213 
214 
215 double cbl::cosmology::Cosmology::sound_speed(const double redshift, const double T_CMB) const
216 {
217  double rho_b = 3.*pow(100.*m_hh/par::cc, 2)*m_Omega_baryon; // Mpc^-2
218 
219  double cc_m = par::cc*1000.;
220  double Mpc = par::pc*1.e6;
221  double rho_rad = 8.*par::pi*par::GN*pow(cc_m, -2)*4.*par::sSB*pow(T_CMB, 4)*pow(cc_m, -3)*pow(Mpc, 2); // Mpc^-2
222 
223  double R = 3./4*rho_b/rho_rad/(1+redshift);
224  double cs = 1./sqrt(3.*(1.+R));
225  return par::cc*cs;
226 }
227 
228 
229 // =====================================================================================
230 
231 
232 double cbl::cosmology::Cosmology::rs_integrand (const double a, const double T_CMB) const
233 {
234  double redshift=1./a-1;
235 
236  double zeq = 2.5e4*m_Omega_matter*m_hh*m_hh*pow(T_CMB/2.7,-4);
237  double a_eq = 1./(1+zeq);
238 
239  double factor;
240  if(m_Omega_radiation ==0)
241  factor = sqrt(m_Omega_matter*(a+a_eq)+m_Omega_k*a*a+m_Omega_DE*f_DE(redshift)*pow(a,4));
242  else
243  factor = a*a*EE(redshift);
244 
245  return sound_speed(redshift, T_CMB)/factor;
246 }
247 
248 
249 // =====================================================================================
250 
251 
252 double cbl::cosmology::Cosmology::rs (const double redshift, const double T_CMB) const
253 {
254  function<double(double)> integrand = bind(&Cosmology::rs_integrand, this, std::placeholders::_1, T_CMB);
255  double a = 1./(1+redshift);
256  return wrapper::gsl::GSL_integrate_qag(integrand, 0, a)/m_H0;
257 }
258 
259 
260 // =====================================================================================
261 
262 
263 vector<double> cbl::cosmology::Cosmology::linear_point (const double redshift, const double rmin, const double rmax, const int nbinr, const std::string interpType)
264 {
265  vector<double> rr = linear_bin_vector(nbinr, rmin, rmax);
266 
267  vector<double> kk, Pk;
268  run_CAMB(kk, Pk, false, redshift);
269  for(size_t i=0; i<kk.size(); i++){
270  kk[i] = pow(10., kk[i]);
271  Pk[i] = pow(10., Pk[i]);
272  }
273 
274  vector<double> xi = cbl::wrapper::fftlog::transform_FFTlog(rr, 1, kk, Pk);
275 
276  cbl::glob::FuncGrid xi_interp(rr, xi, interpType);
277 
278  double rsCAMB = rs_CAMB();
279  vector<double> boundaries = {rsCAMB-5, rsCAMB+5};
280 
281 
282  // procedure to find the peak
283 
284  bool end = false;
285  double rpeak, rdip;
286 
287  while (!end) {
288  rpeak = xi_interp.root_D1v(boundaries[0], boundaries[1], 0, 1.e-10);
289 
290  if ((rpeak<boundaries[1]) && (rpeak > boundaries[0]))
291  end = true;
292  else if (rpeak==boundaries[1])
293  boundaries[1]+=2;
294  else
295  boundaries[0]-=2;
296  }
297 
298 
299  // procedure to find the dip
300 
301  end = false;
302  boundaries[1] = boundaries[0];
303  boundaries[0] = boundaries[1]-10;
304 
305  while (!end) {
306  rdip = xi_interp.root_D1v(boundaries[0], boundaries[1], 0, 1.e-10);
307 
308  if ((rdip<boundaries[1]) &&(rdip > boundaries[0]))
309  end = true;
310  else if (rdip==boundaries[1])
311  boundaries[1] += 2;
312  else
313  boundaries[0] -= 2;
314  }
315 
316  return {0.5*(rdip+rpeak), rdip, rpeak};
317 }
The class Cosmology.
std::vector< double > linear_point(const double redshift, const double rmin=60., const double rmax=150., const int nbinr=100, const std::string interpType="Spline")
the linear point
Definition: BAO.cpp:263
double rs_EH(const double T_CMB=par::TCMB) const
the sound horizon at the drag epoch predicted by Eisentein & Hu 1998
Definition: BAO.cpp:158
double z_drag() const
redshift of drag epoch
Definition: BAO.cpp:62
double rs_integrand(const double redshift, const double T_CMB=2.7255) const
the sound horizon integrand
Definition: BAO.cpp:232
double rs_CAMB() const
the sound horizon at the drag epoch estimated with CAMB [http://camb.info/], analytical formula by Au...
Definition: BAO.cpp:183
double sound_speed(const double redshift, const double T_CMB=2.7255) const
the sound speed
Definition: BAO.cpp:215
double ys(const double redshift, const std::string method_Pk, const double T_CMB=par::TCMB) const
the fiducial cosmology independent ratio rs/DV, valid choices for method_Pk are: EisensteinHu [http:/...
Definition: BAO.cpp:197
double rs() const
get the sound horizon at recombination
Definition: Cosmology.h:1289
double Az(const double redshift) const
the acoustic parameter
Definition: BAO.cpp:206
double z_decoupling() const
redshift at wich occurs baryon photon decoupling
Definition: BAO.cpp:47
The class FuncGrid.
Definition: FuncGrid.h:55
double root_D1v(const double x_low, const double x_up, const double fx0=0, const double rel_err=1.e-2, const double abs_err=1.e-6)
find roots with GSL brent method for the first derivative
Definition: FuncGrid.cpp:231
static const double kilo
conversion factor
Definition: Constants.h:81
static const double pi
: the ratio of a circle's circumference to its diameter
Definition: Constants.h:199
static const double sSB
: the Stefan-Boltzmann constant, the factor relating the emissive power of a black body to the fourth...
Definition: Constants.h:227
static const double pc
: the parsec, defined as 1au/1arc sec [m]
Definition: Constants.h:272
static const double GN
: the Newtonian constant of gravitation [m3 Kg-1 s-2]
Definition: Constants.h:245
static const double cc
: the speed of light in vacuum (the value is exact) [km/sec]
Definition: Constants.h:221
static const double TCMB
: the present day CMB temperature [K]
Definition: Constants.h:275
static const double mp
: the mass of the proton [kg]
Definition: Constants.h:266
std::vector< double > transform_FFTlog(const std::vector< double > yy, const int dir, const std::vector< double > xx, const std::vector< double > fx, const double mu=0, const double q=0, const double kr=1, const int kropt=0)
wrapper of the FFTlog to compute the discrete Fourier sine or cosine transform of a logarithmically...
Definition: FFTlog.cpp:43
double GSL_root_brent(gsl_function Func, const double low_guess, const double up_guess, const double rel_err=1.e-3, const double abs_err=0)
function to find roots using GSL qag method
Definition: GSLwrapper.cpp:430
double GSL_integrate_qag(gsl_function Func, const double a, const double b, const double rel_err=1.e-3, const double abs_err=0, const int limit_size=1000, const int rule=6)
integral, computed using the GSL qag method
Definition: GSLwrapper.cpp:180
The global namespace of the CosmoBolognaLib
Definition: CAMB.h:38
std::vector< T > linear_bin_vector(const size_t nn, const T min, const T max)
fill a std::vector with linearly spaced values
Definition: Kernel.h:1604
int ErrorCBL(const std::string msg, const std::string functionCBL, const std::string fileCBL, const cbl::glob::ExitCode exitCode=cbl::glob::ExitCode::_error_)
throw an exception: it is used for handling exceptions inside the CosmoBolognaLib
Definition: Kernel.h:780