Fast Methods for Cosmological Simulations
FastSim serves as a tool for quick N-body simulations in modified gravity.
ccl_halomod.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <string.h>
5 
6 #include <gsl/gsl_errno.h>
7 #include <gsl/gsl_integration.h>
8 #include <gsl/gsl_sf_expint.h>
9 #include <gsl/gsl_roots.h>
10 
11 #include "ccl.h"
12 #include "ccl_params.h"
13 #include "ccl_halomod.h"
14 
15 // Analytic FT of NFW profile, from Cooray & Sheth (2002; Section 3 of https://arxiv.org/abs/astro-ph/0206508)
16 // Normalised such that U(k=0)=1
17 static double u_nfw_c(ccl_cosmology *cosmo, double rv, double c, double k, int *status){
18 
19  double rs, ks;
20  double f1, f2, f3, fc;
21 
22  // Special case to prevent numerical problems if k=0,
23  // the result should be unity here because of the normalisation
24  if (k==0.) {
25  return 1.;
26  }
27 
28  // The general k case
29  else{
30 
31  // Scale radius for NFW (rs=rv/c)
32  rs = rv/c;
33 
34  // Dimensionless wave-number variable
35  ks = k*rs;
36 
37  // Various bits for summing together to get final result
38  f1 = sin(ks)*(gsl_sf_Si(ks*(1.+c))-gsl_sf_Si(ks));
39  f2 = cos(ks)*(gsl_sf_Ci(ks*(1.+c))-gsl_sf_Ci(ks));
40  f3 = sin(c*ks)/(ks*(1.+c));
41  fc = log(1.+c)-c/(1.+c);
42 
43  return (f1+f2-f3)/fc;
44 
45  }
46 }
47 
48 /*----- ROUTINE: ccl_halo_concentration -----
49 INPUT: cosmology, a halo mass [Msun], scale factor, halo definition, concentration model label
50 TASK: Computes halo concentration; the ratio of virial raidus to scale radius for an NFW halo.
51 */
52 double ccl_halo_concentration(ccl_cosmology *cosmo, double halomass, double a, double odelta, int *status){
53 
54  double gz, g0, nu, delta_c, a_form;
55  double Mpiv, A, B, C;
56 
57  switch(cosmo->config.halo_concentration_method){
58 
59  // Bhattacharya et al. (2011; 1005.2239; Delta = 200rho_m; Table 2)
61 
62  if (odelta != 200.) {
63  *status = CCL_ERROR_CONC_DV;
64  ccl_cosmology_set_status_message(cosmo, "ccl_halomod.c: halo_concentration(): Bhattacharya (2011) concentration relation only valid for Delta_v = 200 \n");
65  return NAN;
66  }
67 
68  gz = ccl_growth_factor(cosmo,a,status);
69  g0 = ccl_growth_factor(cosmo,1.0,status);
70  delta_c = 1.686;
71  nu = delta_c/ccl_sigmaM(cosmo, halomass, a, status);
72  return 9.*pow(nu,-0.29)*pow(gz/g0,1.15);
73 
74  // Duffy et al. (2008; 0804.2486; Table 1)
75  case ccl_duffy2008:
76 
77  Mpiv = 2e12/cosmo->params.h; // Pivot mass in Msun (note in the paper units are Msun/h)
78 
79  if (odelta == Dv_BryanNorman(cosmo, a, status)) {
80 
81  // Duffy et al. (2008) for virial density haloes (second section in Table 1)
82  A = 7.85;
83  B = -0.081;
84  C = -0.71;
85  return A*pow(halomass/Mpiv,B)*pow(a,-C);
86 
87  } else if (odelta == 200.) {
88 
89  // Duffy et al. (2008) for x200 mean-matter-density haloes (third section in Table 1)
90  A = 10.14;
91  B = -0.081;
92  C = -1.01;
93  return A*pow(halomass/Mpiv,B)*pow(a,-C);
94 
95  } else {
96 
97  *status = CCL_ERROR_CONC_DV;
98  ccl_cosmology_set_status_message(cosmo, "ccl_halomod.c: halo_concentration(): Duffy (2008) virial concentration only valid for virial Delta_v or 200\n");
99  return NAN;
100 
101  }
102 
103  // Constant concentration (good for tests)
105 
106  return 4.;
107 
108  // Something went wrong
109  default:
110 
111  *status = CCL_ERROR_HALOCONC;
112  ccl_raise_exception(*status, "ccl_halomod.c: concentration-mass relation specified incorrectly");
113  return NAN;
114 
115  }
116 }
117 
118 // Fourier Transforms of halo profiles
119 static double window_function(ccl_cosmology *cosmo, double m, double k, double a, double odelta, ccl_win_label label, int *status){
120 
121  double rho_matter, c, rv;
122 
123  switch(label){
124 
125  case ccl_nfw:
126 
127  // The mean background matter density in Msun/Mpc^3
128  rho_matter = ccl_rho_x(cosmo, 1., ccl_species_m_label, 1, status);
129 
130  // The halo virial radius
131  rv = r_delta(cosmo, m, a, odelta, status);
132 
133  // The halo concentration for this halo mass and at this scale factor
134  c = ccl_halo_concentration(cosmo, m, a, odelta, status);
135 
136  // The function U is normalised to 1 for k<<1 so multiplying by M/rho turns units to overdensity
137  return m*u_nfw_c(cosmo, rv, c, k, status)/rho_matter;
138 
139  // Something went wrong
140  default:
141 
142  *status = CCL_ERROR_HALOWIN;
143  ccl_raise_exception(*status, "ccl_halomod.c: Window function specified incorrectly");
144  return NAN;
145 
146  }
147 
148 }
149 
150 // Parameters structure for the one-halo integrand
151 typedef struct{
153  double k, a;
154  int *status;
156 
157 // Integrand for the one-halo integral
158 static double one_halo_integrand(double log10mass, void *params){
159 
160  Int_one_halo_Par *p = (Int_one_halo_Par *)params;;
161  double halomass = pow(10,log10mass);
162  double odelta = Dv_BryanNorman(p->cosmo, p->a, p->status); // Virial density for haloes
163 
164  // The normalised Fourier Transform of a halo density profile
165  double wk = window_function(p->cosmo,halomass, p->k, p->a, odelta, ccl_nfw, p->status);
166 
167  // Fairly sure that there should be no ln(10) factor should be here since the integration is being specified in log10 range
168  double dn_dlogM = ccl_massfunc(p->cosmo, halomass, p->a, odelta, p->status);
169 
170  return dn_dlogM*pow(wk,2);
171 }
172 
173 // The one-halo term integral using gsl
174 static double one_halo_integral(ccl_cosmology *cosmo, double k, double a, int *status){
175 
176  int one_halo_integral_status = 0, qagstatus;
177  double result = 0, eresult;
178  double log10mmin = log10(HM_MMIN);
179  double log10mmax = log10(HM_MMAX);
180  Int_one_halo_Par ipar;
181  gsl_function F;
182  gsl_integration_workspace *w = gsl_integration_workspace_alloc(1000);
183 
184  // Structure required for the gsl integration
185  ipar.cosmo = cosmo;
186  ipar.k = k;
187  ipar.a = a;
188  ipar.status = &one_halo_integral_status;
189  F.function = &one_halo_integrand;
190  F.params = &ipar;
191 
192  // Actually does the integration
193  qagstatus = gsl_integration_qag(&F, log10mmin, log10mmax, HM_EPSABS, HM_EPSREL, HM_LIMIT, HM_INT_METHOD, w, &result, &eresult);
194 
195  // Clean up
196  gsl_integration_workspace_free(w);
197 
198  // Check for errors
199  if (qagstatus != GSL_SUCCESS) {
200  ccl_raise_gsl_warning(qagstatus, "ccl_halomod.c: one_halo_integral():");
201  *status = CCL_ERROR_ONE_HALO_INT;
202  ccl_cosmology_set_status_message(cosmo, "ccl_halomod.c: one_halo_integral(): Integration failure\n");
203  return NAN;
204  } else {
205  return result;
206  }
207 
208 }
209 
210 // Parameters structure for the two-halo integrand
211 typedef struct{
213  double k, a;
214  int *status;
216 
217 // Integrand for the two-halo integral
218 static double two_halo_integrand(double log10mass, void *params){
219 
220  Int_two_halo_Par *p = (Int_two_halo_Par *)params;
221  double halomass = pow(10,log10mass);
222  double odelta = Dv_BryanNorman(p->cosmo, p->a, p->status); // Virial density for haloes
223 
224  // The normalised Fourier Transform of a halo density profile
225  double wk = window_function(p->cosmo,halomass, p->k, p->a, odelta, ccl_nfw, p->status);
226 
227  // Fairly sure that there should be no ln(10) factor should be here since the integration is being specified in log10 range
228  double dn_dlogM = ccl_massfunc(p->cosmo, halomass, p->a, odelta, p->status);
229 
230  // Halo bias
231  double b = ccl_halo_bias(p->cosmo, halomass, p->a, odelta, p->status);
232 
233  return b*dn_dlogM*wk;
234 }
235 
236 // The two-halo term integral using gsl
237 static double two_halo_integral(ccl_cosmology *cosmo, double k, double a, int *status){
238 
239  int two_halo_integral_status = 0, qagstatus;
240  double result = 0, eresult;
241  double log10mmin = log10(HM_MMIN);
242  double log10mmax = log10(HM_MMAX);
243  Int_two_halo_Par ipar;
244  gsl_function F;
245  gsl_integration_workspace *w = gsl_integration_workspace_alloc(1000);
246 
247  // Structure required for the gsl integration
248  ipar.cosmo = cosmo;
249  ipar.k = k;
250  ipar.a = a;
251  ipar.status = &two_halo_integral_status;
252  F.function = &two_halo_integrand;
253  F.params = &ipar;
254 
255  // Actually does the integration
256  qagstatus = gsl_integration_qag(&F, log10mmin, log10mmax, HM_EPSABS, HM_EPSREL, HM_LIMIT, HM_INT_METHOD, w, &result, &eresult);
257 
258  // Clean up
259  gsl_integration_workspace_free(w);
260 
261  // Check for errors
262  if (qagstatus != GSL_SUCCESS) {
263  ccl_raise_gsl_warning(qagstatus, "ccl_halomod.c: two_halo_integral():");
264  *status = CCL_ERROR_TWO_HALO_INT;
265  ccl_cosmology_set_status_message(cosmo, "ccl_halomod.c: two_halo_integral(): Integration failure\n");
266  return NAN;
267  } else {
268  return result;
269  }
270 
271 }
272 
273 /*----- ROUTINE: ccl_twohalo_matter_power -----
274 INPUT: cosmology, wavenumber [Mpc^-1], scale factor
275 TASK: Computes the two-halo power spectrum term in the halo model assuming NFW haloes
276 */
277 double ccl_twohalo_matter_power(ccl_cosmology *cosmo, double k, double a, int *status){
278 
279  // Get the integral
280  double I2h = two_halo_integral(cosmo, k, a, status);
281 
282  // The addative correction is the missing part of the integral below the lower-mass limit
283  double A = 1.-two_halo_integral(cosmo, 0., a, status);
284 
285  // Virial overdensity for haloes
286  double odelta = Dv_BryanNorman(cosmo, a, status);
287 
288  // ...multiplied by the ratio of window functions
289  double W1 = window_function(cosmo, HM_MMIN, k, a, odelta, ccl_nfw, status);
290  double W2 = window_function(cosmo, HM_MMIN, 0., a, odelta, ccl_nfw, status);
291  A = A*W1/W2;
292 
293  // Add the additive correction to the calculated integral
294  I2h = I2h+A;
295 
296  return ccl_linear_matter_power(cosmo, k, a, status)*I2h*I2h;
297 
298 }
299 
300 /*----- ROUTINE: ccl_onehalo_matter_power -----
301 INPUT: cosmology, wavenumber [Mpc^-1], scale factor
302 TASK: Computes the one-halo power spectrum term in the halo model assuming NFW haloes
303 */
304 double ccl_onehalo_matter_power(ccl_cosmology *cosmo, double k, double a, int *status){
305 
306  return one_halo_integral(cosmo, k, a, status);
307 
308 }
309 
310 /*----- ROUTINE: ccl_onehalo_matter_power -----
311 INPUT: cosmology, wavenumber [Mpc^-1], scale factor
312 TASK: Computes the halo model power spectrum by summing the two- and one-halo terms
313 */
314 double ccl_halomodel_matter_power(ccl_cosmology *cosmo, double k, double a, int *status){
315 
316  // Standard sum of two- and one-halo terms
317  return ccl_twohalo_matter_power(cosmo, k, a, status)+ccl_onehalo_matter_power(cosmo, k, a, status);
318 
319 }
static int rs
Definition: ccl_emu17.c:25
static double u_nfw_c(ccl_cosmology *cosmo, double rv, double c, double k, int *status)
Definition: ccl_halomod.c:17
double r_delta(ccl_cosmology *cosmo, double halomass, double a, double odelta, int *status)
Definition: ccl_massfunc.c:52
#define CCL_ERROR_HALOWIN
Definition: ccl_error.h:30
ccl_cosmology * cosmo
Definition: ccl_halomod.c:212
#define HM_MMIN
Definition: ccl_halomod.h:6
void ccl_raise_gsl_warning(int gslstatus, const char *msg,...)
Definition: ccl_error.c:75
#define CCL_ERROR_HALOCONC
Definition: ccl_error.h:29
#define HM_INT_METHOD
Definition: ccl_halomod.h:11
halo_concentration_t halo_concentration_method
Definition: ccl_config.h:115
ccl_parameters params
Definition: ccl_core.h:124
double ccl_growth_factor(ccl_cosmology *cosmo, double a, int *status)
double ccl_massfunc(ccl_cosmology *cosmo, double smooth_mass, double a, double odelta, int *status)
Definition: ccl_massfunc.c:562
double h
Definition: ccl_core.h:33
static double two_halo_integral(ccl_cosmology *cosmo, double k, double a, int *status)
Definition: ccl_halomod.c:237
double ccl_sigmaM(ccl_cosmology *cosmo, double smooth_mass, double a, int *status)
Definition: ccl_massfunc.c:624
double ccl_onehalo_matter_power(ccl_cosmology *cosmo, double k, double a, int *status)
Definition: ccl_halomod.c:304
#define CCL_ERROR_TWO_HALO_INT
Definition: ccl_error.h:34
ccl_win_label
Definition: ccl_halomod.h:16
void ccl_cosmology_set_status_message(ccl_cosmology *cosmo, const char *status_message,...)
Definition: ccl_core.c:792
#define HM_MMAX
Definition: ccl_halomod.h:7
double ccl_linear_matter_power(ccl_cosmology *cosmo, double k, double a, int *status)
Definition: ccl_power.c:1506
ccl_cosmology * cosmo
Definition: ccl_halomod.c:152
#define CCL_ERROR_CONC_DV
Definition: ccl_error.h:32
#define HM_EPSREL
Definition: ccl_halomod.h:9
#define HM_LIMIT
Definition: ccl_halomod.h:10
static double window_function(ccl_cosmology *cosmo, double m, double k, double a, double odelta, ccl_win_label label, int *status)
Definition: ccl_halomod.c:119
dictionary params
Definition: halomod_bm.py:27
double ccl_rho_x(ccl_cosmology *cosmo, double a, ccl_species_x_label label, int is_comoving, int *status)
#define HM_EPSABS
Definition: ccl_halomod.h:8
double ccl_halo_concentration(ccl_cosmology *cosmo, double halomass, double a, double odelta, int *status)
Definition: ccl_halomod.c:52
static int p
Definition: ccl_emu17.c:25
double ccl_halomodel_matter_power(ccl_cosmology *cosmo, double k, double a, int *status)
Definition: ccl_halomod.c:314
double ccl_halo_bias(ccl_cosmology *cosmo, double smooth_mass, double a, double odelta, int *status)
Definition: ccl_massfunc.c:582
float pow(float base, unsigned long int exp)
Definition: precision.hpp:39
static int m[2]
Definition: ccl_emu17.c:25
#define CCL_ERROR_ONE_HALO_INT
Definition: ccl_error.h:33
double ccl_twohalo_matter_power(ccl_cosmology *cosmo, double k, double a, int *status)
Definition: ccl_halomod.c:277
ccl_configuration config
Definition: ccl_core.h:125
double Dv_BryanNorman(ccl_cosmology *cosmo, double a, int *status)
Definition: ccl_massfunc.c:37
void ccl_raise_exception(int err, const char *msg,...)
Definition: ccl_error.c:35
static double one_halo_integral(ccl_cosmology *cosmo, double k, double a, int *status)
Definition: ccl_halomod.c:174
static double w[2][28][111]
Definition: ccl_emu17.c:33
static double one_halo_integrand(double log10mass, void *params)
Definition: ccl_halomod.c:158
static double two_halo_integrand(double log10mass, void *params)
Definition: ccl_halomod.c:218