MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
cosmology.c
Go to the documentation of this file.
1 #include <math.h>
2 #include <gsl/gsl_integration.h>
3 #include <gsl/gsl_errno.h>
4 #include <gsl/gsl_odeiv2.h>
5 
6 #include "cosmology.h"
7 #include "physconst.h"
8 #include "utils.h"
9 
10 /*Stefan-Boltzmann constant in cgs units*/
11 #define STEFAN_BOLTZMANN 5.670373e-5
12 
13 static inline double OmegaFLD(const Cosmology * CP, const double a);
14 
15 void init_cosmology(Cosmology * CP, const double TimeBegin, const struct UnitSystem units)
16 {
17  CP->Hubble = HUBBLE * units.UnitTime_in_s;
19  CP->GravInternal = GRAVITY / pow(units.UnitLength_in_cm, 3) * units.UnitMass_in_g * pow(units.UnitTime_in_s, 2);
20 
21  /*With slightly relativistic massive neutrinos, for consistency we need to include radiation.
22  * A note on normalisation (as of 08/02/2012):
23  * CAMB appears to set Omega_Lambda + Omega_Matter+Omega_K = 1,
24  * calculating Omega_K in the code and specifying Omega_Lambda and Omega_Matter in the paramfile.
25  * This means that Omega_tot = 1+ Omega_r + Omega_g, effectively
26  * making h0 (very) slightly larger than specified, and the Universe is no longer flat!
27  */
29  CP->OmegaK = 1.0 - CP->Omega0 - CP->OmegaLambda;
30 
31  /* Omega_g = 4 \sigma_B T_{CMB}^4 8 \pi G / (3 c^3 H^2) */
32 
34  * pow(CP->CMBTemperature, 4)
35  * (8 * M_PI * GRAVITY)
36  / (3*pow(LIGHTCGS, 3)*HUBBLE*HUBBLE)
38 
39  init_omega_nu(&CP->ONu, CP->MNu, TimeBegin, CP->HubbleParam, CP->CMBTemperature);
40  /*Initialise the hybrid neutrinos, after Omega_nu*/
43 
44  /* Neutrinos will be included in Omega0, if massive.
45  * This ensures that OmegaCDM contains only non-relativistic species.*/
46  if(CP->MNu[0] + CP->MNu[1] + CP->MNu[2] > 0) {
47  CP->OmegaCDM -= get_omega_nu(&CP->ONu, 1);
48  }
49 }
50 
51 /* Returns 1 if the neutrino particles are 'tracers', not actively gravitating,
52  * and 0 if they are actively gravitating particles.*/
53 int hybrid_nu_tracer(const Cosmology * CP, double atime)
54 {
55  return CP->HybridNeutrinosOn && (atime <= CP->HybridNuPartTime);
56 }
57 /*Hubble function at scale factor a, in dimensions of CP.Hubble*/
58 double hubble_function(const Cosmology * CP, double a)
59 {
60 
61  double hubble_a;
62 
63  /* first do the terms in SQRT */
64  hubble_a = CP->OmegaLambda;
65 
66  hubble_a += OmegaFLD(CP, a);
67  hubble_a += CP->OmegaK / (a * a);
68  hubble_a += (CP->OmegaCDM + CP->OmegaBaryon) / (a * a * a);
69 
70  if(CP->RadiationOn) {
71  hubble_a += CP->OmegaG / (a * a * a * a);
72  hubble_a += get_omega_nu(&CP->ONu, a);
73  }
74  hubble_a += CP->Omega_ur/(a*a*a*a);
75  /* Now finish it up. */
76  hubble_a = CP->Hubble * sqrt(hubble_a);
77  return (hubble_a);
78 }
79 
80 static double growth(Cosmology * CP, double a, double *dDda);
81 
82 double GrowthFactor(Cosmology * CP, double astart, double aend)
83 {
84  return growth(CP, astart, NULL) / growth(CP, aend, NULL);
85 }
86 
87 int growth_ode(double a, const double yy[], double dyda[], void * params)
88 {
89  Cosmology * CP = (Cosmology *) params;
90  const double hub = hubble_function(CP, a)/CP->Hubble;
91  dyda[0] = yy[1]/pow(a,3)/hub;
92  /*Only use gravitating part*/
93  /* Note: we do not include neutrinos
94  * here as they are free-streaming at the initial time.
95  * This is not right if our box is very large and thus overlaps
96  * with their free-streaming scale. In that case the growth factor will be scale-dependent
97  * and we need to numerically differentiate. In practice the box will either be larger
98  * than the horizon, and so need radiation perturbations, or the neutrino
99  * mass will be larger than current constraints allow, so we just warn for now.*/
100  dyda[1] = yy[0] * 1.5 * a * (CP->OmegaCDM + CP->OmegaBaryon)/(a*a*a) / hub;
101  return GSL_SUCCESS;
102 }
103 
111 double growth(Cosmology * CP, double a, double * dDda)
112 {
113  gsl_odeiv2_system FF;
114  FF.function = &growth_ode;
115  FF.jacobian = NULL;
116  FF.params = CP;
117  FF.dimension = 2;
118  gsl_odeiv2_driver * drive = gsl_odeiv2_driver_alloc_standard_new(&FF,gsl_odeiv2_step_rkf45, 1e-5, 1e-8,1e-8,1,1);
119  /* We start early to avoid lambda.*/
120  double curtime = 1e-5;
121  /* Handle even earlier times*/
122  if(a < curtime)
123  curtime = a / 10;
124  /* Initial velocity chosen so that D = Omegar + 3/2 Omega_m a,
125  * the solution for a matter/radiation universe.*
126  * Note the normalisation of D is arbitrary
127  * and never seen outside this function.*/
128  double yinit[2] = {1.5 * (CP->OmegaCDM + CP->OmegaBaryon)/(curtime*curtime), pow(curtime,3)*hubble_function(CP, curtime)/CP->Hubble * 1.5 * (CP->OmegaCDM + CP->OmegaBaryon)/(curtime*curtime*curtime)};
129  if(CP->RadiationOn)
130  yinit[0] += CP->OmegaG/pow(curtime, 4)+get_omega_nu(&CP->ONu, curtime);
131 
132  int stat = gsl_odeiv2_driver_apply(drive, &curtime,a, yinit);
133  if (stat != GSL_SUCCESS) {
134  endrun(1,"gsl_odeiv in growth: %d. Result at %g is %g %g\n",stat, curtime, yinit[0], yinit[1]);
135  }
136  gsl_odeiv2_driver_free(drive);
137  /*Store derivative of D if needed.*/
138  if(dDda) {
139  *dDda = yinit[1]/pow(a,3)/(hubble_function(CP, a)/CP->Hubble);
140  }
141  return yinit[0];
142 }
143 
144 /*
145  * This is the Zeldovich approximation prefactor,
146  * f1 = d ln D1 / dlna = a / D (dD/da)
147  */
148 double F_Omega(Cosmology * CP, double a)
149 {
150  double dD1da=0;
151  double D1 = growth(CP, a, &dD1da);
152  return a / D1 * dD1da;
153 }
154 
155 /*Dark energy density as a function of time:
156  * OmegaFLD(a) ~ exp(-3 int((1+w(a))/a da)_a^1
157  * and w(a) = w0 + (1-a) wa*/
158 static inline double OmegaFLD(const Cosmology * CP, const double a)
159 {
160  if(CP->Omega_fld == 0.)
161  return 0;
162  return CP->Omega_fld * pow(a, 3 * (1 + CP->w0_fld + CP->wa_fld))*exp(3*CP->wa_fld*(1-a));
163 }
164 
166 {
168  double R;
169 };
170 
171 static double sigma2_int(double k, void * p)
172 {
173  struct sigma2_params * params = (struct sigma2_params *) p;
174  FunctionOfK * fk = params->fk;
175  const double R = params->R;
176  double kr, kr3, kr2, w, x;
177 
178  kr = R * k;
179  kr2 = kr * kr;
180  kr3 = kr2 * kr;
181 
182  if(kr < 1e-8)
183  return 0;
184 
185  w = 3 * (sin(kr) / kr3 - cos(kr) / kr2);
186  x = 4 * M_PI * k * k * w * w * function_of_k_eval(fk, k);
187 
188  return x;
189 }
190 
191 double function_of_k_eval(FunctionOfK * fk, double k)
192 {
193  /* ignore the 0 mode */
194 
195  if(k == 0) return 1;
196 
197  int l = 0;
198  int r = fk->size - 1;
199 
200  while(r - l > 1) {
201  int m = (r + l) / 2;
202  if(k < fk->table[m].k)
203  r = m;
204  else
205  l = m;
206  }
207  double k2 = fk->table[r].k,
208  k1 = fk->table[l].k;
209  double p2 = fk->table[r].Pk,
210  p1 = fk->table[l].Pk;
211 
212  if(l == r) {
213  return fk->table[l].Pk;
214  }
215 
216  if(p1 == 0 || p2 == 0 || k1 == 0 || k2 == 0) {
217  /* if any of the p is zero, use linear interpolation */
218  double p = (k - k1) * p2 + (k2 - k) * p1;
219  p /= (k2 - k1);
220  return p;
221  } else {
222  k = log(k);
223  p1 = log(p1);
224  p2 = log(p2);
225  k1 = log(k1);
226  k2 = log(k2);
227  double p = (k - k1) * p2 + (k2 - k) * p1;
228  p /= (k2 - k1);
229  return exp(p);
230  }
231 }
232 
234 {
235  gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
236  struct sigma2_params params = {fk, R};
237  double result,abserr;
238  gsl_function F;
239  F.function = &sigma2_int;
240  F.params = &params;
241 
242  /* note: 500/R is here chosen as integration boundary (infinity) */
243  gsl_integration_qags (&F, 0, 500. / R, 0, 1e-4,1000,w,&result, &abserr);
244  // printf("gsl_integration_qng in TopHatSigma2. Result %g, error: %g, intervals: %lu\n",result, abserr,w->size);
245  gsl_integration_workspace_free (w);
246  return sqrt(result);
247 }
248 
250  double old = function_of_k_tophat_sigma(fk, R);
251  size_t i;
252  for(i = 0; i < fk->size; i ++) {
253  fk->table[i].Pk *= sigma / old;
254  };
255 }
256 
259 void
260 check_units(const Cosmology * CP, const struct UnitSystem units)
261 {
262  /* Detect cosmologies that are likely to be typos in the parameter files*/
263  if(CP->HubbleParam < 0.1 || CP->HubbleParam > 10 ||
264  CP->OmegaLambda < 0 || CP->OmegaBaryon < 0 || CP->OmegaG < 0 || CP->OmegaCDM < 0)
265  endrun(5, "Bad cosmology: H0 = %g OL = %g Ob = %g Og = %g Ocdm = %g\n",
267 
268  message(0, "Hubble (internal units) = %g\n", CP->Hubble);
269  message(0, "G (internal units) = %g\n", CP->GravInternal);
270  message(0, "UnitLength_in_cm = %g \n", units.UnitLength_in_cm);
271  message(0, "UnitMass_in_g = %g \n", units.UnitMass_in_g);
272  message(0, "UnitTime_in_s = %g \n", units.UnitTime_in_s);
273  message(0, "UnitVelocity_in_cm_per_s = %g \n", units.UnitVelocity_in_cm_per_s);
274  message(0, "UnitDensity_in_cgs = %g \n", units.UnitDensity_in_cgs);
275  message(0, "UnitEnergy_in_cgs = %g \n", units.UnitEnergy_in_cgs);
276  message(0, "Dark energy model: OmegaL = %g OmegaFLD = %g\n",CP->OmegaLambda, CP->Omega_fld);
277  message(0, "Photon density OmegaG = %g\n",CP->OmegaG);
278  if(!CP->MassiveNuLinRespOn)
279  message(0, "Massless Neutrino density OmegaNu0 = %g\n",get_omega_nu(&CP->ONu, 1));
280  message(0, "Curvature density OmegaK = %g\n",CP->OmegaK);
281  if(CP->RadiationOn) {
282  /* note that this value is inaccurate if there is a massive neutrino. */
283  double OmegaTot = CP->OmegaG + CP->OmegaK + CP->Omega0 + CP->OmegaLambda;
284  if(!CP->MassiveNuLinRespOn)
285  OmegaTot += get_omega_nu(&CP->ONu, 1);
286  message(0, "Radiation is enabled in Hubble(a). "
287  "Following CAMB convention: Omega_Tot - 1 = %g\n", OmegaTot - 1);
288  }
289  message(0, "\n");
290 }
static double OmegaFLD(const Cosmology *CP, const double a)
Definition: cosmology.c:158
static double sigma2_int(double k, void *p)
Definition: cosmology.c:171
double function_of_k_eval(FunctionOfK *fk, double k)
Definition: cosmology.c:191
void check_units(const Cosmology *CP, const struct UnitSystem units)
Definition: cosmology.c:260
void function_of_k_normalize_sigma(FunctionOfK *fk, double R, double sigma)
Definition: cosmology.c:249
double GrowthFactor(Cosmology *CP, double astart, double aend)
Definition: cosmology.c:82
static double growth(Cosmology *CP, double a, double *dDda)
Definition: cosmology.c:111
int hybrid_nu_tracer(const Cosmology *CP, double atime)
Definition: cosmology.c:53
double hubble_function(const Cosmology *CP, double a)
Definition: cosmology.c:58
double function_of_k_tophat_sigma(FunctionOfK *fk, double R)
Definition: cosmology.c:233
#define STEFAN_BOLTZMANN
Definition: cosmology.c:11
void init_cosmology(Cosmology *CP, const double TimeBegin, const struct UnitSystem units)
Definition: cosmology.c:15
double F_Omega(Cosmology *CP, double a)
Definition: cosmology.c:148
int growth_ode(double a, const double yy[], double dyda[], void *params)
Definition: cosmology.c:87
double sigma[3]
Definition: densitykernel.c:97
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
void init_hybrid_nu(_hybrid_nu *const hybnu, const double mnu[], const double vcrit, const double light, const double nu_crit_time, const double kBtnu)
void init_omega_nu(_omega_nu *omnu, const double MNu[], const double a0, const double HubbleParam, const double tcmb0)
double get_omega_nu(const _omega_nu *const omnu, const double a)
#define HUBBLE
Definition: physconst.h:25
#define GRAVITY
Definition: physconst.h:5
#define LIGHTCGS
Definition: physconst.h:18
static Cosmology * CP
Definition: power.c:27
double GravInternal
Definition: cosmology.h:32
double wa_fld
Definition: cosmology.h:17
double Omega_ur
Definition: cosmology.h:18
int HybridNeutrinosOn
Definition: cosmology.h:28
double Omega_fld
Definition: cosmology.h:15
double Omega0
Definition: cosmology.h:10
int RadiationOn
Definition: cosmology.h:23
double HubbleParam
Definition: cosmology.h:20
double HybridVcrit
Definition: cosmology.h:29
double CMBTemperature
Definition: cosmology.h:9
double OmegaK
Definition: cosmology.h:13
double OmegaCDM
Definition: cosmology.h:11
double UnitTime_in_s
Definition: cosmology.h:22
double OmegaLambda
Definition: cosmology.h:14
double OmegaBaryon
Definition: cosmology.h:19
double HybridNuPartTime
Definition: cosmology.h:31
int MassiveNuLinRespOn
Definition: cosmology.h:26
double OmegaG
Definition: cosmology.h:12
double MNu[3]
Definition: cosmology.h:25
_omega_nu ONu
Definition: cosmology.h:24
double Hubble
Definition: cosmology.h:21
double w0_fld
Definition: cosmology.h:16
size_t size
Definition: cosmology.h:38
double k
Definition: cosmology.h:40
double Pk
Definition: cosmology.h:41
struct FunctionOfK::@2 table[]
double UnitEnergy_in_cgs
Definition: unitsystem.h:13
double UnitMass_in_g
Definition: unitsystem.h:8
double UnitTime_in_s
Definition: unitsystem.h:11
double UnitLength_in_cm
Definition: unitsystem.h:10
double UnitDensity_in_cgs
Definition: unitsystem.h:12
double UnitVelocity_in_cm_per_s
Definition: unitsystem.h:9
_hybrid_nu hybnu
FunctionOfK * fk
Definition: cosmology.c:167
Definition: power.c:35