Observable quantities

This page shows observable quantities that can be derived from solutions of the Einstein-Boltzmann system, such as power spectra and distances.

Primordial power spectra

SymBoltz.spectrum_primordial — Function
spectrum_primordial(k, h, As, ns=1.0; kp = 0.05*(L100/h))

Compute the primordial power spectrum

\[P₀(k) = 2π² Aₛ (k/kₚ)^{nₛ-1} / k³\]

with spectral amplitude As, spectral index ns and pivot scale wavenumber kp at the wavenumber(s) k. All wavenumbers are in units of $H₀/c$, and the default pivot scale is 0.05/Mpc.

source

Example

using SymBoltz, Plots
M = ΛCDM()
pars = Dict(M.g.h => 0.7, M.I.As => 2e-9, M.I.ns => 0.95)
ks = 10 .^ range(-2, +4, length=100)
Ps = spectrum_primordial(ks, M, pars)
plot(log10.(ks), log10.(Ps); xlabel = "log10(k / (H₀/c))", ylabel = "log10(P / (c/H₀)³)")
Example block output

Matter power spectra

SymBoltz.spectrum_matter — Function
spectrum_matter([modes,] prob::CosmologyProblem, k[, τ]; kwargs...)

Compute the matter power spectrum

\[P(k,τ) = P₀(k) |Δ(k,τ)|²\]

of the total gauge-invariant overdensity

\[Δ = (∑ₛρₛΔₛ) / (∑ₛρₛ)\]

for one or more modes at wavenumbers k and conformal time(s) τ from the problem prob. The problem is solved for the given $k$, and the matter power spectrum is saved at the given $τ$.

  • modes must be :c (CDM), :b (baryons), :h (massive neutrinos), :m (matter; equivalent to $c+b+h$), a vector thereof, or unspecified to use :m.
  • k must be a vector of wavenumbers in units of $H₀/c$.
  • τ must be a single or a vector of conformal times, or unspecified to use $τ = τ₀$ today.
  • kwargs... are keyword arguments that are forwarded to solve(prob, k; kwargs...).
source
spectrum_matter([modes,] sol::CosmologySolution, k[, τ]; kwargs...)

Compute the matter power spectrum in the same way, but interpolate between wavenumbers and times already stored in the solution sol.

source
SymBoltz.spectrum_matter_nonlinear — Function
spectrum_matter_nonlinear(sol::CosmologySolution, k)

Compute the nonlinear matter power spectrum from the cosmology solution sol at wavenumber(s) k using halofit implemented in MatterPower.jl.

source

Example

With explicitly chosen wavenumbers:

using SymBoltz, Plots
M = ΛCDM()
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)
ks = 10 .^ range(-2, +5, length=100)
sol = solve(prob, ks)

# Linear power spectrum
modes = [:m, :cb, :h]
Ps = spectrum_matter(modes, sol, ks)
plot(
    log10.(ks), transpose(log10.(Ps));
    xlabel = "log10(k / (H₀/c))", ylabel = "log10(P / (c/H₀)³)",
    label = permutedims("linear (SymBoltz), " .* string.(modes)), ylims = (-15, -6),
    linestyle = [:solid :dash :dot :dashdot :dashdotdot], legend_position = :bottomleft
)

# Nonlinear power spectrum (from halofit)
Ps = spectrum_matter_nonlinear(sol, ks)
plot!(
    log10.(ks), log10.(Ps);
    label = "non-linear (halofit), matter", legend_position = :bottomleft
)
Example block output

As a function of conformal time and redshift:

τs = range(sol[M.τ][end], 0.5, length=10)
Ps = spectrum_matter(sol, ks, τs)
zs = sol(M.g.z, τs) # corresponding redshifts
plot(
    log10.(ks), transpose(log10.(Ps));
    xlabel = "log10(k / (H₀/c))", ylabel = "log10(P / (c/H₀)³)",
    label = permutedims("z=".*string.(round.(zs;digits=1))),
    legend_position = :bottomleft
)
Example block output

CMB power spectra

SymBoltz.spectrum_cmb — Function
spectrum_cmb(ΘlAs::AbstractMatrix, ΘlBs::AbstractMatrix, P0s::AbstractVector, ls::AbstractVector, ks::AbstractVector; normalization = :Cl, thread = true)

Compute the angular power spectrum

\[Cₗᴬᴮ = (2/π) ∫\mathrm{d}k \, k² P₀(k) Θₗᴬ(k,τ₀) Θₗᴮ(k,τ₀)\]

for the given ls. If normalization == :Dl, compute $Dₗ = Cₗ l (l+1) / 2π$ instead.

source
spectrum_cmb(modes::AbstractVector{<:Symbol}, prob::CosmologyProblem, jl::SphericalBesselCache; normalization = :Cl, kinterp = nothing, Δkτ0 = 2π/4, xs = cosgrid(0.0, 1.0; length=1200), l_limber = 11, bgalg = default_bgalg(prob), bgreltol = 1e-7, bgabstol = 1e-7, bgopts = (), ptalg = default_ptalg(prob), ptreltol = 1e-5, ptabstol = 1e-5, ptopts = (), thread = true, verbose = false, kwargs...)

Compute angular CMB power spectra $Cₗᴬᴮ$ at angular wavenumbers ls from the cosmological problem prob. The requested modes are specified as a vector of symbols in the form :AB, where A and B are T (temperature), E (E-mode polarization) or ψ (lensing). The spectra are of dimensionless temperature fluctuations relative to the present photon temperature $T_{γ0}$; multiply by $T_{γ0}^2$ to get dimensionful spectra. Returns a matrix of $Cₗ$ if normalization is :Cl, or $Dₗ = l(l+1)/2π$ if normalization is :Dl.

Precision parameters

  • xs: Grid of $(τ-τᵢ)/(τ₀-τᵢ)$ specifying the $τ$-points that will be sampled in line-of-sight integration (also if the independent variable is not $τ$), or an integer number of points interpolated from the background time steps.
  • kinterp: Interpolator that decides which $k$-modes the perturbation ODEs will be solved explicitly for, and then interpolated in-between to a finer grid set by Δkτ0.
  • Δkτ0: Grid spacing to use when integrating over $k$ to project to $ℓ$-space.
  • l_limber: Use Limber approximation for lensing line-of-sight integrals with equal or greater $ℓ$.
  • bgalg/ptalg, bgreltol/ptreltol, bgabstol/ptabstol: ODE algorithms and tolerances for the background/perturbation stages.
  • bgopts/ptopts: extra options for the background/perturbation ODE solves.

Examples

using SymBoltz
M = ΛCDM()
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)

ls = 10:10:1000
jl = SphericalBesselCache(ls)
modes = [:TT, :TE, :ψψ, :ψT]
Dls = spectrum_cmb(modes, prob, jl; normalization = :Dl)
source
spectrum_cmb(modes::AbstractVector, prob::CosmologyProblem, jl::SphericalBesselCache, ls::AbstractVector; kwargs...)

Same, but compute the spectrum properly only for jl.l and then interpolate the results to all ls.

source

Example

using SymBoltz, Plots
M = ΛCDM()
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)

ls = 25:25:3000 # 25, 50, ..., 3000
jl = SphericalBesselCache(ls)
modes = [:TT, :EE, :TE, :ψψ, :ψT, :ψE]
Dls = spectrum_cmb(modes, prob, jl; normalization = :Dl)

plot(ls, log10.(abs.(Dls)); xlabel = "l", ylabel = "lg(Dₗ)", label = permutedims(String.(modes)))
Example block output

Two-point correlation function

SymBoltz.correlation_function — Function
correlation_function(sol::CosmologySolution; N = 2048, spline = true)

Compute the two-point correlation function in real space by Fourier transforming the matter power spectrum of sol with N points the FFTLog algorithm implemented in TwoFAST. Returns N radii and correlation function values (e.g. r, ξ).

source

Example

using SymBoltz, Plots
M = ΛCDM()
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)
ks = 10 .^ range(-2, +6, length=300)
sol = solve(prob, ks)
rs, ξs = correlation_function(sol)
rs = rs * L100 # convert from c/H₀ to Mpc/h
plot(rs, @. ξs * rs^2; xlims = (0, 200), xlabel = "r / (Mpc/h)", ylabel = "r² ξ / (Mpc/h)²")
Example block output

Matter density fluctuations

SymBoltz.variance_matter — Function
variance_matter(sol::CosmologySolution, R)

Compute the variance $⟨δ²⟩$ of the linear matter density field with a top-hat filter with radius R in units of $c/H₀$. Wraps the implementation in MatterPower.jl.

source
SymBoltz.stddev_matter — Function
stddev_matter(sol::CosmologySolution, R)

Compute the standard deviation $√(⟨δ²⟩)$ of the linear matter density field with a top-hat filter with radius R in units of $c/H₀$.

source
using SymBoltz, Plots
M = ΛCDM()
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)
ks = 10 .^ range(-2, +6, length=300)
sol = solve(prob, ks)

Rs = 10 .^ range(0.5, 2.5, length=100) # Mpc/h
σs = stddev_matter.(sol, Rs / L100) # Mpc/h to c/H₀
plot(log10.(Rs), log10.(σs); xlabel = "lg(R / (Mpc/h))", ylabel = "lg(σ)", label = nothing)

σ8 = stddev_matter(sol, 8 / L100) # 8 Mpc/h to c/H₀
scatter!((log10(8), log10(σ8)), series_annotation = text("  σ₈ = $(round(σ8; digits=3))", :left), label = nothing)
Example block output

Distance measures

SymBoltz.distance_luminosity — Function
distance_luminosity(χ, a, h, Ωk0 = 0)

Compute luminosity distances (in meters)

\[d_L = \frac{c}{H_0} \frac{r}{a}, \quad \mathrm{where} \quad r = \chi \, \frac{\sin\left(\sqrt{-Ω_{k0}} \, \chi\right)}{\sqrt{-Ω_{k0}} \, \chi},\]

from conformal lookback times χ, scale factors a, Hubble parameter h and curvature density Ωk0.

source
using SymBoltz, Plots
M = RMΛ(K = SymBoltz.curvature(SymBoltz.metric()))
pars = Dict(
    M.r.Ω₀ => 5e-5,
    M.m.Ω₀ => 0.3,
    M.K.Ω₀ => 0.1,
    M.r.T₀ => NaN,
    M.g.h => 0.7
)
prob = CosmologyProblem(M, pars)
sol = solve(prob)

zs = 0.0:1.0:10.0
τs = SymBoltz.timeseries(sol, M.g.z, zs) # times at given redshifts
dLs = distance_luminosity(sol(M.χ, τs), sol(M.g.a, τs), sol[M.g.h], sol[M.K.Ω₀]) / SymBoltz.Gpc
plot(zs, dLs; marker=:dot, xlabel="z", ylabel="dL / Gpc", label=nothing)
Example block output

Sound horizon (BAO scale)

SymBoltz.sound_horizon — Function
sound_horizon(sol::CosmologySolution)

Cumulatively integrate the sound horizon

\[ rₛ(τ) = ∫_0^τ dτ cₛ = ∫_0^τ \frac{dτ}{√(3(1+3ρ_b/4ρ_γ))}\]

to the time steps of the solution sol.

source
using SymBoltz, Plots
M = ΛCDM()
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)
sol = solve(prob)
τs = sol[M.τ]
rs = sound_horizon(sol)
plot(τs, rs; xlabel = "τ / H₀⁻¹", ylabel = "rₛ / (c/H₀)")
Example block output

Source functions

SymBoltz.source_grid — Function
source_grid(
    prob::CosmologyProblem, Ss, τs, ks[, bgsols];
    bgalg = default_bgalg(prob), bgreltol = 1e-7, bgabstol = 1e-7, bgopts = (),
    ptalg = default_ptalg(prob), ptreltol = 1e-5, ptabstol = 1e-5, ptopts = (),
    thread = true, verbose = false
)

Compute and evaluate source functions $S(τ,k)$ with symbolic expressions Ss on a grid with conformal times τs and wavenumbers ks from the problem prob. Returns a matrix of size (Nτ, Nk), where each element is a vector of length NS = length(Ss) holding all source values at that (τ, k) point.

The algorithms bgalg/ptalg, tolerances bgreltol/ptreltol and bgabstol/ptabstol and extra options bgopts/ptopts are passed to the background/perturbation ODE solves. If the background solutions bgsols are passed, they are used directly and the background options are not accepted.

source
using SymBoltz, Plots, DataInterpolations
M = ΛCDM(h = nothing, ν = nothing)
pars = parameters_Planck18(M)
prob = CosmologyProblem(M, pars)
sol = solve(prob)

τs = sol[M.τ] # conformal times in background solution
ks = exp.(range(log(1.0), log(2000.0), length = 50)) # logarithmic k-grid
Ss = source_grid(prob, M.ST, τs, ks)
iτ = argmax(sol[M.b.v]) # index of decoupling time
iτs = iτ-75:iτ+75 # indices around decoupling
p1 = surface(ks, τs[iτs], Ss[iτs, :]; camera = (45, 25), xlabel = "k", ylabel = "τ", zlabel = "S", colorbar = false)

lgas = -6.0:0.2:0.0
τs = LinearInterpolation(sol[M.τ], sol[log10(M.g.a)])(lgas) # τ at given lg(a)
ks = 5.0:5.0:100.0
Ss = source_grid(prob, M.g.Ψ, τs, ks)
p2 = wireframe(ks, lgas, Ss; camera = (75, 20), xlabel = "k", ylabel = "lg(a)", zlabel = "Φ")

plot(p1, p2)
Example block output

Line-of-sight integration

SymBoltz.los_integrate — Function
los_integrate(Ss::AbstractMatrix{T}, ls::AbstractVector, τs::AbstractVector, ks::AbstractVector, jl::SphericalBesselCache; l_limber = typemax(Int), thread = true, verbose = false) where {T}

For the given ls and ks, compute the line-of-sight integrals

\[Iₗ(k) = ∫dτ S(k,τ) jₗ(k(τ₀-τ))\]

over the source function values Ss against the spherical Bessel functions $jₗ(x)$ cached in jl. The element Ss[i,j] holds the source function value $S(τᵢ, kⱼ)$. The Limber approximation

\[Iₗ ≈ √(π/(2l+1)) S(τ₀-(l+1/2)/k, k)\]

is used for l ≥ l_limber.

source