CosmoBolognaLib
Free Software C++/Python libraries for cosmological calculations
ModelFunction_PowerSpectrum_Angular.cpp
Go to the documentation of this file.
1 /********************************************************************
2  * Copyright (C) 2016 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 
37 
38 using namespace std;
39 using namespace cbl;
40 
41 
42 // ===============================================================================================
43 
44 
45 std::vector<double> cbl::modelling::angularpk::Cl_mixed(std::vector<double> l_mixing, std::vector<std::vector<double>> mixing_matrix, std::vector<double> l, std::vector<double> Cl, double fsky){
46 
47  if(l_mixing[0]!=0) cbl::ErrorCBL("the mixing matrix should start from l=0", "Cl_mixed", "ModelFunction_PowerSpectrum_Angular.cpp",cbl::glob::ExitCode::_error_);
48 
49  double _fsky=1./fsky;
50  std::vector<double> Cl_mixed(l.size(), 0);
51 
52  for (size_t j=0; j<l.size(); ++j)
53  for (size_t i=0; i<l.size(); ++i)
54  Cl_mixed[j]+=mixing_matrix[j+l[0]][i+l[0]]*Cl[i]*_fsky;
55 
56  return Cl_mixed;
57 
58 }
59 
60 
61 // ============================================================================================
62 
63 
64 double cbl::modelling::angularpk::integral_limber_interp (const double l, std::vector<double> z_vector, std::vector<double> kk, cbl::glob::FuncGrid2D pk_interp, std::vector<double> par, std::shared_ptr<void> inputs){
65 
66  shared_ptr<STR_data_model> pp = static_pointer_cast<STR_data_model>(inputs);
67  // redefine the cosmology
68  cbl::cosmology::Cosmology cosmo = *pp->cosmology;
69 
70  //set the cosmological parameters
71  for (size_t i=0; i<pp->Cpar.size(); ++i)
72  cosmo.set_parameter(pp->Cpar[i], par[i]);
73 
74  double lower_limit;
75  double upper_limit;
76  if(pp->z_min_bin2>0 && pp->z_max_bin2>0){
77  lower_limit = min(pp->z_min, pp->z_min_bin2);
78  upper_limit = max(pp->z_max, pp->z_max_bin2);
79  }
80  else{
81  lower_limit = pp->z_min;
82  upper_limit = pp->z_max;
83  }
84 
85  // relative measurement precision (it raises a warning message if not satisfied)
86  const double prec = 1.e-5;
87 
88  // default values (refer to the GSL documentation for different choiches)
89  const int limit_size = 1000;
90  const int rule = 6;
91 
92  std::function<double(double)> integrand_limber = [&l, &par, &pk_interp, &cosmo, &inputs, &z_vector, &kk] (double redshift)
93  {
94  shared_ptr<STR_data_model> pp = static_pointer_cast<STR_data_model>(inputs);
95 
96  double offset=0;
97  double slope=0;
98  if(par.size()>pp->Cpar.size()+4 && pp->dN_par_bin2.size()==0){ //Cpar.size()+2 because the first element is l
99  offset = par[pp->Cpar.size()+1];
100  slope = par[pp->Cpar.size()+2];
101  }
102 
103  double distribution=0;
104  double distribution_bin2=0;
105  for (size_t i=0; i<pp->dN_par.size(); ++i){ //if dN_par.size=0 it does not enter into this cycle (offset and slope are defined outside)
106  if(redshift<pp->z_max && redshift>pp->z_min)
107  distribution += pp->dN_par[i]*pow(redshift, i);
108  else distribution=0;
109  }
110  distribution+=par[pp->Cpar.size()]+par[pp->Cpar.size()+1]*redshift;
111  if(pp->dN_par_bin2.size()>0){
112  for (size_t i=0; i<pp->dN_par_bin2.size(); ++i)
113  if(redshift<pp->z_max_bin2 && redshift>pp->z_min_bin2)
114  distribution_bin2 += pp->dN_par_bin2[i]*pow(redshift, i);
115  else distribution_bin2=0;
116  distribution_bin2+=offset+slope*redshift;
117  }
118 
119  std::vector<double> pk_interpolated;
120  std::vector<std::vector<double>> Pk_interp;
121  double kk_exact=double(l+0.5)/cosmo.D_C(redshift);
122  size_t index_k=10000;
123  double kk_diff=10000;
124  for(size_t i=0; i<kk.size(); ++i)
125  if(abs(kk[i]-kk_exact)<kk_diff){
126  kk_diff=abs(kk[i]-kk_exact);
127  index_k=i;
128  }
129  if(index_k!=0) kk[index_k]=kk_exact;
130 
131  std::vector<std::vector<double>> interp_matrix={{redshift}, {kk[index_k]}};
132  interp_matrix=cbl::transpose(interp_matrix);
133  pk_interpolated=pk_interp.eval_func(interp_matrix);
134 
135  double _cc=1/cbl::par::cc;
136  double inv_d2= 1/(cosmo.D_C(redshift)*cosmo.D_C(redshift));
137  if(pp->dN_par_bin2.size()>0) return distribution*distribution_bin2*pk_interpolated[0]*inv_d2*cosmo.HH(redshift)*_cc;
138  return distribution*distribution*pk_interpolated[0]*inv_d2*cosmo.HH(redshift)*_cc;
139 
140  };
141 
142  std::vector<double> parameter_integrand;
143  parameter_integrand.emplace_back(l);
144  for (size_t i=0; i<par.size(); ++i) parameter_integrand.emplace_back(par[i]);
145  return cbl::wrapper::gsl::GSL_integrate_qag(integrand_limber, lower_limit, upper_limit, prec, limit_size, rule);
146 
147 }
148 
149 
150 // ============================================================================================
151 
152 
153 double cbl::modelling::angularpk::integrand_limber_exact(double redshift, std::shared_ptr<void> inputs, std::vector<double> par){
154 
155  // structure contaning the required input data
156 
157  shared_ptr<STR_data_model> pp = static_pointer_cast<STR_data_model>(inputs);
158 
159  // redefine the cosmology
160  cbl::cosmology::Cosmology cosmo = *pp->cosmology;
161 
162  // set the cosmological parameters
163  for (size_t i=0; i<pp->Cpar.size(); ++i)
164  cosmo.set_parameter(pp->Cpar[i], par[i+1]); //i+1 because i=0 is l
165  double offset=0;
166  double slope=0;
167  if(par.size()>pp->Cpar.size()+4 && pp->dN_par_bin2.size()==0){ //Cpar.size()+2 because the first element is l
168  offset = par[pp->Cpar.size()+2];
169  slope = par[pp->Cpar.size()+3];
170  }
171 
172  // redefine the cosmology
173  double distribution=0;
174  double distribution_bin2=0;
175  for (size_t i=0; i<pp->dN_par.size(); ++i){ //if dN_par.size=0 it does not enter into this cycle (offset and slope are definet outside)
176  if(redshift<pp->z_max && redshift>pp->z_min){
177  distribution += pp->dN_par[i]*pow(redshift, i);
178  }
179  else distribution=0;
180  }
181  distribution+=par[pp->Cpar.size()+1]+par[pp->Cpar.size()+2]*redshift;
182  if(pp->dN_par_bin2.size()>0){
183  for (size_t i=0; i<pp->dN_par_bin2.size(); ++i)
184  if(redshift<pp->z_max_bin2 && redshift>pp->z_min_bin2){
185  distribution_bin2 += pp->dN_par_bin2[i]*pow(redshift, i);
186  }
187  else distribution_bin2=0;
188  distribution_bin2+=offset+slope*redshift;
189  }
190 
191  double l=par[0];
192  double _cc=1/cbl::par::cc;
193  double Pk=cosmo.Pk_matter({double((l+0.5)/cosmo.D_C(redshift))}, pp->method_Pk, pp->NL, redshift, false, "test", pp->norm, pp->k_min, pp->k_max)[0];
194 
195  double inv_d2= 1/(cosmo.D_C(redshift)*cosmo.D_C(redshift));
196  if(pp->dN_par_bin2.size()>0) return distribution*distribution_bin2*Pk*inv_d2*cosmo.HH(redshift)*_cc;
197 
198  return distribution*distribution*Pk*inv_d2*cosmo.HH(redshift)*_cc;
199 
200 }
201 
202 
203 // =====================================================================
204 
205 
206 double cbl::modelling::angularpk::integral_limber_exact (const double l, std::vector<double> parameter, std::shared_ptr<void> inputs){
207 
208  shared_ptr<STR_data_model> pp = static_pointer_cast<STR_data_model>(inputs);
209 
210  double lower_limit;
211  double upper_limit;
212  if(pp->z_min_bin2>0 && pp->z_max_bin2>0){
213  lower_limit = min(pp->z_min, pp->z_min_bin2);
214  upper_limit = max(pp->z_max, pp->z_max_bin2);
215  }
216  else{
217  lower_limit = pp->z_min;
218  upper_limit = pp->z_max;
219  }
220 
221  // relative measurement precision (it raises a warning message if not satisfied)
222  const double prec = 1.e-5;
223 
224  // default values (refer to the GSL documentation for different choiches)
225  const int limit_size = 1000;
226  const int rule = 6;
227 
228  std::vector<double> parameter_integrand;
229  parameter_integrand.emplace_back(l);
230  for (size_t i=0; i<parameter.size(); ++i) parameter_integrand.emplace_back(parameter[i]);
231  return cbl::wrapper::gsl::GSL_integrate_qag(&integrand_limber_exact, inputs, parameter_integrand, lower_limit, upper_limit, prec, limit_size, rule);
232 
233 }
234 
235 
236 // ===========================================================================================
237 
238 
239 std::vector<double> cbl::modelling::angularpk::Cl_limber(const std::vector<double> l, const std::shared_ptr<void> inputs, std::vector<double> &parameter)
240 {
241 
242  // structure contaning the required input data
243  shared_ptr<STR_data_model> pp = static_pointer_cast<STR_data_model>(inputs);
244  // redefine the cosmology
245  cbl::cosmology::Cosmology cosmo = *pp->cosmology;
246 
247  // set the cosmological parameters
248  for (size_t i=0; i<pp->Cpar.size(); ++i)
249  cosmo.set_parameter(pp->Cpar[i], parameter[i]);
250 
251  vector<double> Cl(l.size(), 0);
252 
253  // input parameters
254  double bias = parameter[pp->Cpar.size()];
255 
256  if(pp->interpolate_power_spectrum==false)
257  for (size_t i=0; i<l.size(); i++) Cl[i] = cbl::modelling::angularpk::integral_limber_exact(l[i], parameter, inputs);
258 
259  else{
260  std::vector<double> kk, z_vector;
261  double kk_step=0.0002, z_step=0.03;
262  double kk_min=double((*std::min_element(std::begin(l), std::end(l))+0.5)/cosmo.D_C(pp->z_max)), kk_max=double((*max_element(std::begin(l), std::end(l))+0.5)/cosmo.D_C(pp->z_min));
263  for(size_t i=0; i<(pp->z_max-pp->z_min)/z_step +1; ++i) z_vector.emplace_back(pp->z_min+i*z_step);
264  for(size_t i=0; i<(kk_max-kk_min)/kk_step+1; ++i) kk.emplace_back(kk_min+i*kk_step);
265 
266  std::vector<std::vector<double>> Pk=cosmo.Pk_matter(kk, pp->method_Pk, pp->NL, z_vector, false, "test", pp->norm, pp->k_min, pp->k_max);
267  cbl::glob::FuncGrid2D pk_interp({z_vector},{kk}, Pk, "Linear");
268 
269  for (size_t i=0; i<l.size(); i++)
270  Cl[i] = cbl::modelling::angularpk::integral_limber_interp(l[i], z_vector, kk, pk_interp, parameter, inputs);
271  }
272 
273  if(pp->mixing_matrix.size()!=0) Cl=Cl_mixed(pp->ll, pp->mixing_matrix, l, Cl, pp->fsky);
274 
275  if(pp->dN_par_bin2.size()>0){
276  double bias_bin2 = parameter[pp->Cpar.size()+1];
277  for (size_t i =0; i<Cl.size(); i++) Cl[i] *= bias*bias_bin2;
278  parameter[pp->Cpar.size()+2] = cosmo.sigma8()*sqrt(cosmo.Omega_matter()/0.3); //S8
279  parameter[pp->Cpar.size()+3] = cosmo.Omega_baryon()/cosmo.Omega_matter(); //baryonic fraction
280  }
281  else {
282  for (size_t i =0; i<Cl.size(); i++) Cl[i] *= bias*bias;
283  parameter[pp->Cpar.size()+1] = cosmo.sigma8()*sqrt(cosmo.Omega_matter()/0.3); //S8
284  parameter[pp->Cpar.size()+2] = cosmo.Omega_baryon()/cosmo.Omega_matter(); //baryonic fraction
285  }
286  return Cl;
287 
288 }
289 
290 
291 // ============================================================================================
292 
Global functions to model the angular power spectrum.
std::vector< double > Cl_mixed(std::vector< double > l_mixing, std::vector< std::vector< double >> mixing_matrix, std::vector< double > l, std::vector< double > Cl, double fsky)
the angular power spectrum convolved with the mixing matrix
double integral_limber_exact(double l, std::vector< double > parameter, std::shared_ptr< void > input)
the integrand function in the Limber approximation for the calculus of angular power spectrum
double integral_limber_interp(double l, std::vector< double > z_vector, std::vector< double > kk, cbl::glob::FuncGrid2D pk_interp, std::vector< double > parameter, std::shared_ptr< void > input)
the integrand function in the Limber approximation for the calculus of angular power spectrum
std::vector< double > Cl_limber(const std::vector< double > l, const std::shared_ptr< void > inputs, std::vector< double > &parameter)
the model for the angular power spectrum
double integrand_limber_exact(double redshift, std::shared_ptr< void > pp, std::vector< double > par)
the integrand function in the Limber approximation for the calculus of angular power spectrum
The class Cosmology.
Definition: Cosmology.h:277
double Omega_baryon() const
get the private member Cosmology::m_Omega_baryon
Definition: Cosmology.h:1126
void set_parameter(const CosmologicalParameter parameter, const double value)
set the value of one cosmological paramter
Definition: Cosmology.cpp:424
double sigma8() const
get the private member Cosmology::m_sigma8
Definition: Cosmology.h:1212
double HH(const double redshift=0.) const
the Hubble function
Definition: Cosmology.cpp:570
std::vector< double > Pk_matter(const std::vector< double > kk, const std::string method_Pk, const bool NL, const double redshift, const bool store_output=true, const std::string output_root="test", const int norm=-1, const double k_min=0.001, const double k_max=100., const double prec=1.e-2, const std::string file_par=par::defaultString, const bool unit1=false)
the dark matter power spectrum
Definition: PkXi.cpp:1331
double Omega_matter() const
get the private member Cosmology::m_Omega_matter
Definition: Cosmology.h:1119
double D_C(const double redshift) const
the comoving line-of-sight distance at a given redshift
Definition: Cosmology.cpp:741
The class FuncGrid2D.
Definition: FuncGrid.h:302
std::vector< double > eval_func(const std::vector< std::vector< double >> xx) const
evaluate the function at the xx points
Definition: FuncGrid.cpp:341
static const double cc
: the speed of light in vacuum (the value is exact) [km/sec]
Definition: Constants.h:221
@ _error_
generic error
double bias(const double Mmin, const double sigmalgM, const double M0, const double M1, const double alpha, const std::shared_ptr< void > inputs)
the mean galaxy bias
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
void distribution(std::vector< double > &xx, std::vector< double > &fx, std::vector< double > &err, const std::vector< double > FF, const std::vector< double > WW, const int nbin, const bool linear=true, const std::string file_out=par::defaultString, const double fact=1., const double V1=par::defaultDouble, const double V2=par::defaultDouble, const std::string bin_type="Linear", const bool conv=false, const double sigma=0.)
derive and store the number distribution of a given std::vector
Definition: Func.cpp:1654
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
std::vector< std::vector< T > > transpose(std::vector< std::vector< T >> matrix)
transpose a matrix
Definition: Kernel.h:1729