CLASS MANUAL
background.c File Reference
#include "background.h"
+ Include dependency graph for background.c:

Functions

int background_at_tau (struct background *pba, double tau, short return_format, short intermode, int *last_index, double *pvecback)
 
int background_tau_of_z (struct background *pba, double z, double *tau)
 
int background_functions (struct background *pba, double *pvecback_B, short return_format, double *pvecback)
 
int background_init (struct precision *ppr, struct background *pba)
 
int background_free (struct background *pba)
 
int background_free_input (struct background *pba)
 
int background_indices (struct background *pba)
 
int background_ncdm_distribution (void *pbadist, double q, double *f0)
 
int background_ncdm_test_function (void *pbadist, double q, double *test)
 
int background_ncdm_init (struct precision *ppr, struct background *pba)
 
int background_ncdm_momenta (double *qvec, double *wvec, int qsize, double M, double factor, double z, double *n, double *rho, double *p, double *drho_dM, double *pseudo_p)
 
int background_ncdm_M_from_Omega (struct precision *ppr, struct background *pba, int n_ncdm)
 
int background_solve (struct precision *ppr, struct background *pba)
 
int background_initial_conditions (struct precision *ppr, struct background *pba, double *pvecback, double *pvecback_integration)
 
int background_output_titles (struct background *pba, char titles[_MAXTITLESTRINGLENGTH_])
 
int background_output_data (struct background *pba, int number_of_titles, double *data)
 
int background_derivs (double tau, double *y, double *dy, void *parameters_and_workspace, ErrorMsg error_message)
 
double V_e_scf (struct background *pba, double phi)
 
double V_p_scf (struct background *pba, double phi)
 
double V_scf (struct background *pba, double phi)
 

Detailed Description

Documented background module

  • Julien Lesgourgues, 17.04.2011
  • routines related to ncdm written by T. Tram in 2011

Deals with the cosmological background evolution. This module has two purposes:

  • at the beginning, to initialize the background, i.e. to integrate the background equations, and store all background quantities as a function of conformal time inside an interpolation table.
  • to provide routines which allow other modules to evaluate any background quantity for a given value of the conformal time (by interpolating within the interpolation table), or to find the correspondence between redshift and conformal time.

The overall logic in this module is the following:

  1. most background parameters that we will call {A} (e.g. rho_gamma, ..) can be expressed as simple analytical functions of a few variables that we will call {B} (in simplest models, of the scale factor 'a'; in extended cosmologies, of 'a' plus e.g. (phi, phidot) for quintessence, or some temperature for exotic particles, etc...).
  2. in turn, quantities {B} can be found as a function of conformal time by integrating the background equations.
  3. some other quantities that we will call {C} (like e.g. the sound horizon or proper time) also require an integration with respect to time, that cannot be inferred analytically from parameters {B}.

So, we define the following routines:

  • background_functions() returns all background quantities {A} as a function of quantities {B}.
  • background_solve() integrates the quantities {B} and {C} with respect to conformal time; this integration requires many calls to background_functions().
  • the result is stored in the form of a big table in the background structure. There is one column for conformal time 'tau'; one or more for quantities {B}; then several columns for quantities {A} and {C}.

Later in the code, if we know the variables {B} and need some quantity {A}, the quickest and most precise way is to call directly background_functions() (for instance, in simple models, if we want H at a given value of the scale factor). If we know 'tau' and want any other quantity, we can call background_at_tau(), which interpolates in the table and returns all values. Finally it can be useful to get 'tau' for a given redshift 'z': this can be done with background_tau_of_z(). So if we are somewhere in the code, knowing z and willing to get background quantities, we should call first background_tau_of_z() and then background_at_tau().

In order to save time, background_at_tau() can be called in three modes: short_info, normal_info, long_info (returning only essential quantities, or useful quantities, or rarely useful quantities). Each line in the interpolation table is a vector whose first few elements correspond to the short_info format; a larger fraction contribute to the normal format; and the full vector corresponds to the long format. The guideline is that short_info returns only geometric quantities like a, H, H'; normal format returns quantities strictly needed at each step in the integration of perturbations; long_info returns quantities needed only occasionally.

In summary, the following functions can be called from other modules:

  1. background_init() at the beginning
  2. background_at_tau(), background_tau_of_z() at any later time
  3. background_free() at the end, when no more calls to the previous functions are needed

Function Documentation

int background_at_tau ( struct background pba,
double  tau,
short  return_format,
short  intermode,
int *  last_index,
double *  pvecback 
)

Background quantities at given conformal time tau.

Evaluates all background quantities at a given value of conformal time by reading the pre-computed table and interpolating.

Parameters
pbaInput: pointer to background structure (containing pre-computed table)
tauInput: value of conformal time
return_formatInput: format of output vector (short, normal, long)
intermodeInput: interpolation mode (normal or closeby)
last_indexInput/Output: index of the previous/current point in the interpolation array (input only for closeby mode, output for both)
pvecbackOutput: vector (assumed to be already allocated)
Returns
the error status

Summary:

  • define local variables
  • check that tau is in the pre-computed range
  • deduce length of returned vector from format mode
  • interpolate from pre-computed table with array_interpolate() or array_interpolate_growing_closeby() (depending on interpolation mode)

+ Here is the caller graph for this function:

int background_tau_of_z ( struct background pba,
double  z,
double *  tau 
)

Conformal time at given redshift.

Returns tau(z) by interpolation from pre-computed table.

Parameters
pbaInput: pointer to background structure
zInput: redshift
tauOutput: conformal time
Returns
the error status

Summary:

  • define local variables
  • check that $ z $ is in the pre-computed range
  • interpolate from pre-computed table with array_interpolate()

+ Here is the caller graph for this function:

int background_functions ( struct background pba,
double *  pvecback_B,
short  return_format,
double *  pvecback 
)

Background quantities at given $ a $.

Function evaluating all background quantities which can be computed analytically as a function of {B} parameters such as the scale factor 'a' (see discussion at the beginning of this file). In extended cosmological models, the pvecback_B vector contains other input parameters than just 'a', e.g. (phi, phidot) for quintessence, some temperature of exotic relics, etc...

Parameters
pbaInput: pointer to background structure
pvecback_BInput: vector containing all {B} type quantities (scale factor, ...)
return_formatInput: format of output vector
pvecbackOutput: vector of background quantities (assumed to be already allocated)
Returns
the error status

Summary:

  • define local variables
  • initialize local variables
  • pass value of $ a$ to output
  • compute each component's density and pressure
  • compute expansion rate H from Friedmann equation: this is the only place where the Friedmann equation is assumed. Remember that densities are all expressed in units of $ [3c^2/8\pi G] $, ie $ \rho_{class} = [8 \pi G \rho_{physical} / 3 c^2]$
  • compute derivative of H with respect to conformal time
  • compute relativistic density to total density ratio
  • compute other quantities in the exhaustive, redundant format
  • compute critical density
  • compute Omega_m

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_init ( struct precision ppr,
struct background pba 
)

Initialize the background structure, and in particular the background interpolation table.

Parameters
pprInput: pointer to precision structure
pbaInput/Output: pointer to initialized background structure
Returns
the error status

Summary:

  • define local variables
  • in verbose mode, provide some information
  • if shooting failed during input, catch the error here
  • assign values to all indices in vectors of background quantities with background_indices()
  • control that cosmological parameter values make sense
  • this function integrates the background over time, allocates and fills the background table

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_free ( struct background pba)

Free all memory space allocated by background_init().

Parameters
pbaInput: pointer to background structure (to be freed)
Returns
the error status

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_free_input ( struct background pba)

Free pointers inside background structure which were allocated in input_read_parameters()

Parameters
pbaInput: pointer to background structure
Returns
the error status

+ Here is the caller graph for this function:

int background_indices ( struct background pba)

Assign value to each relevant index in vectors of background quantities.

Parameters
pbaInput: pointer to background structure
Returns
the error status

Summary:

  • define local variables
  • initialize all flags: which species are present?
  • initialize all indices

+ Here is the caller graph for this function:

int background_ncdm_distribution ( void *  pbadist,
double  q,
double *  f0 
)

This is the routine where the distribution function f0(q) of each ncdm species is specified (it is the only place to modify if you need a partlar f0(q))

Parameters
pbadistInput: structure containing all parameters defining f0(q)
qInput: momentum
f0Output: phase-space distribution
  • extract from the input structure pbadist all the relevant information
  • shall we interpolate in file, or shall we use analytical formula below?
  • a) deal first with the case of interpolating in files
  • b) deal now with case of reading analytical function

Next enter your analytic expression(s) for the p.s.d.'s. If you need different p.s.d.'s for different species, put each p.s.d inside a condition, like for instance: if (n_ncdm==2) {*f0=...}. Remember that n_ncdm = 0 refers to the first species.

This form is only appropriate for approximate studies, since in reality the chemical potentials are associated with flavor eigenstates, not mass eigenstates. It is easy to take this into account by introducing the mixing angles. In the later part (not read by the code) we illustrate how to do this.

+ Here is the caller graph for this function:

int background_ncdm_test_function ( void *  pbadist,
double  q,
double *  test 
)

This function is only used for the purpose of finding optimal quadrature weights. The logic is: if we can accurately convolve f0(q) with this function, then we can convolve it accurately with any other relevant function.

Parameters
pbadistInput: structure containing all background parameters
qInput: momentum
testOutput: value of the test function test(q)

Using a + bq creates problems for otherwise acceptable distributions which diverges as $ 1/r $ or $ 1/r^2 $ for $ r\to 0 $

+ Here is the caller graph for this function:

int background_ncdm_init ( struct precision ppr,
struct background pba 
)

This function finds optimal quadrature weights for each ncdm species

Parameters
pprInput: precision structure
pbaInput/Output: background structure
  • in verbose mode, inform user of number of sampled momenta for background quantities

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_ncdm_momenta ( double *  qvec,
double *  wvec,
int  qsize,
double  M,
double  factor,
double  z,
double *  n,
double *  rho,
double *  p,
double *  drho_dM,
double *  pseudo_p 
)

For a given ncdm species: given the quadrature weights, the mass and the redshift, find background quantities by a quick weighted sum over. Input parameters passed as NULL pointers are not evaluated for speed-up

Parameters
qvecInput: sampled momenta
wvecInput: quadrature weights
qsizeInput: number of momenta/weights
MInput: mass
factorInput: normalization factor for the p.s.d.
zInput: redshift
nOutput: number density
rhoOutput: energy density
pOutput: pressure
drho_dMOutput: derivative used in next function
pseudo_pOutput: pseudo-pressure used in perturbation module for fluid approx

Summary:

  • rescale normalization at given redshift
  • initialize quantities
  • loop over momenta
  • adjust normalization

+ Here is the caller graph for this function:

int background_ncdm_M_from_Omega ( struct precision ppr,
struct background pba,
int  n_ncdm 
)

When the user passed the density fraction Omega_ncdm or omega_ncdm in input but not the mass, infer the mass with Newton iteration method.

Parameters
pprInput: precision structure
pbaInput/Output: background structure
n_ncdmInput: index of ncdm species

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_solve ( struct precision ppr,
struct background pba 
)

This function integrates the background over time, allocates and fills the background table

Parameters
pprInput: precision structure
pbaInput/Output: background structure

Summary:

  • define local variables
  • allocate vector of quantities to be integrated
  • initialize generic integrator with initialize_generic_integrator()
  • impose initial conditions with background_initial_conditions()
  • create a growTable with gt_init()
  • loop over integration steps: call background_functions(), find step size, save data in growTable with gt_add(), perform one step with generic_integrator(), store new value of tau
  • save last data in growTable with gt_add()
  • clean up generic integrator with cleanup_generic_integrator()
  • retrieve data stored in the growTable with gt_getPtr()
  • interpolate to get quantities precisely today with array_interpolate()
  • deduce age of the Universe
  • allocate background tables
  • In a loop over lines, fill background table using the result of the integration plus background_functions()
  • free the growTable with gt_free()
  • fill tables of second derivatives (in view of spline interpolation)
  • compute remaining "related parameters"
    • so-called "effective neutrino number", computed at earliest time in interpolation table. This should be seen as a definition: Neff is the equivalent number of instantaneously-decoupled neutrinos accounting for the radiation density, beyond photons
  • done

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_initial_conditions ( struct precision ppr,
struct background pba,
double *  pvecback,
double *  pvecback_integration 
)

Assign initial values to background integrated variables.

Parameters
pprInput: pointer to precision structure
pbaInput: pointer to background structure
pvecbackInput: vector of background quantities used as workspace
pvecback_integrationOutput: vector of background quantities to be integrated, returned with proper initial values
Returns
the error status

Summary:

  • define local variables
  • fix initial value of $ a $

    If we have ncdm species, perhaps we need to start earlier than the standard value for the species to be relativistic. This could happen for some WDM models.

  • We must add the relativistic contribution from NCDM species
    • f is the critical density fraction of DR. The exact solution is:

f = -Omega_rad+pow(pow(Omega_rad,3./2.)+0.5*pow(a/pba->a_today,6)*pvecback_integration[pba->index_bi_rho_dcdm]*pba->Gamma_dcdm/pow(pba->H0,3),2./3.);

but it is not numerically stable for very small f which is always the case. Instead we use the Taylor expansion of this equation, which is equivalent to ignoring f(a) in the Hubble rate.

There is also a space reserved for a future case where dr is not sourced by dcdm

  • Fix initial value of $ \phi, \phi' $ set directly in the radiation attractor => fixes the units in terms of rho_ur

TODO:

  • There seems to be some small oscillation when it starts.
  • Check equations and signs. Sign of phi_prime?
  • is rho_ur all there is early on?
  • –> If there is no attractor solution for scf_lambda, assign some value. Otherwise would give a nan.
  • –> If no attractor initial conditions are assigned, gets the provided ones.
  • compute initial proper time, assuming radiation-dominated universe since Big Bang and therefore $ t=1/(2H) $ (good approximation for most purposes)
  • compute initial conformal time, assuming radiation-dominated universe since Big Bang and therefore $ \tau=1/(aH) $ (good approximation for most purposes)
  • compute initial sound horizon, assuming $ c_s=1/\sqrt{3} $ initially
  • compute initial value of the integral over $ d\tau /(aH^2) $, assumed to be proportional to $ a^4 $ during RD, but with arbitrary normalization

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int background_output_titles ( struct background pba,
char  titles[_MAXTITLESTRINGLENGTH_] 
)

Subroutine for formatting background output

  • Length of the column title should be less than OUTPUTPRECISION+6 to be indented correctly, but it can be as long as .
int background_output_data ( struct background pba,
int  number_of_titles,
double *  data 
)

Stores quantities

int background_derivs ( double  tau,
double *  y,
double *  dy,
void *  parameters_and_workspace,
ErrorMsg  error_message 
)

Subroutine evaluating the derivative with respect to conformal time of quantities which are integrated (a, t, etc).

This is one of the few functions in the code which is passed to the generic_integrator() routine. Since generic_integrator() should work with functions passed from various modules, the format of the arguments is a bit special:

  • fixed input parameters and workspaces are passed through a generic pointer. Here, this is just a pointer to the background structure and to a background vector, but generic_integrator() doesn't know its fine structure.
  • the error management is a bit special: errors are not written as usual to pba->error_message, but to a generic error_message passed in the list of arguments.
Parameters
tauInput: conformal time
yInput: vector of variable
dyOutput: its derivative (already allocated)
parameters_and_workspaceInput: pointer to fixed parameters (e.g. indices)
error_messageOutput: error message

Summary:

  • define local variables
  • calculate functions of $ a $ with background_functions()
  • calculate $ a'=a^2 H $
  • calculate $ t' = a $
  • calculate $ rs' = c_s $
  • calculate growth' $ = 1/(aH^2) $
  • compute dcdm density $ \rho' = -3aH \rho - a \Gamma \rho $
  • Compute dr density $ \rho' = -4aH \rho - a \Gamma \rho $
  • Scalar field equation: $ \phi'' + 2 a H \phi' + a^2 dV = 0 $ (note H is wrt cosmic time)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

double V_e_scf ( struct background pba,
double  phi 
)

Scalar field potential and its derivatives with respect to the field _scf For Albrecht & Skordis model: 9908085

  • $ V = V_{p_{scf}}*V_{e_{scf}} $
  • $ V_e = \exp(-\lambda \phi) $ (exponential)
  • $ V_p = (\phi - B)^\alpha + A $ (polynomial bump)

TODO:

  • Add some functionality to include different models/potentials (tuning would be difficult, though)
  • Generalize to Kessence/Horndeski/PPF and/or couplings
  • A default module to numerically compute the derivatives when no analytic functions are given should be added.
  • Numerical derivatives may further serve as a consistency check.

The units of phi, tau in the derivatives and the potential V are the following:

  • phi is given in units of the reduced Planck mass $ m_{pl} = (8 \pi G)^{(-1/2)}$
  • tau in the derivative is given in units of Mpc.
  • the potential $ V(\phi) $ is given in units of $ m_{pl}^2/Mpc^2 $. With this convention, we have $ \rho^{class} = (8 \pi G)/3 \rho^{physical} = 1/(3 m_{pl}^2) \rho^{physical} = 1/3 * [ 1/(2a^2) (\phi')^2 + V(\phi) ] $ and $ \rho^{class} $ has the proper dimension $ Mpc^-2 $.

+ Here is the caller graph for this function:

double V_p_scf ( struct background pba,
double  phi 
)

parameters and functions for the polynomial coefficient $ V_p = (\phi - B)^\alpha + A $(polynomial bump)

double scf_alpha = 2;

double scf_B = 34.8;

double scf_A = 0.01; (values for their Figure 2)

+ Here is the caller graph for this function:

double V_scf ( struct background pba,
double  phi 
)

Fianlly we can obtain the overall potential $ V = V_p*V_e $

+ Here is the call graph for this function:

+ Here is the caller graph for this function: