Prerequisites
This tutorial is meant to be read with a Jupyter notebook open next to it. Every code cell you see in the chapters is a cell you paste into your notebook and run. There is nothing to install beyond standard scientific Python — no boltzmann.py, no helper modules. By the time you finish chapter 7, your notebook will contain a complete CMB Boltzmann code, written by you, that produces TT, EE, TE, , lensed BB, and tensor BB spectra. We will compare against CAMB exactly once at the end, as a validation step.
Software
You need Python 3.10 or newer with:
pip install numpy scipy matplotlib jupyter
pip install camb # used only for the final validation
numpy and scipy do the numerics, matplotlib the plots, jupyter the interactive environment, and camb is the reference code we will compare our final result against.
Start Jupyter from a clean working directory and create a notebook (for example cmb_tutorial.ipynb). The cells you build up across the chapters are the codebase.
Cell 1: imports and Planck-2018 parameters
This is the first cell of your notebook. It imports the libraries we will use throughout, and defines a parameter dictionary that every later function will consume.
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate, interpolate, optimize, special
# Optional: numba speeds up the inner Boltzmann RHS by ~10x.
# Falls back gracefully if not installed.
try:
from numba import njit
_jit = njit(cache=False)
except ImportError:
_jit = lambda f: f
# Default: Planck 2018 best-fit LCDM
params = {
'omega_b_h2': 0.02237, # physical baryon density
'omega_c_h2': 0.1200, # physical cold dark matter density
'h': 0.6736, # H_0 / (100 km/s/Mpc)
'n_s': 0.9649, # scalar spectral index
'A_s': 2.1e-9, # scalar amplitude at k_pivot = 0.05 Mpc^-1
'tau_reion': 0.0544, # reionisation optical depth
'N_eff': 3.044, # effective number of relativistic species
'T_cmb': 2.7255, # CMB temperature today (K)
'Y_He': 0.245, # primordial helium mass fraction
'k_pivot': 0.05, # pivot scale (1/Mpc)
'ell_max': 2500, # maximum multipole we will compute
}
plt.rcParams.update({'figure.figsize': (7, 4.5), 'font.size': 11})
A tour of the parameters:
and are the physical baryon and cold-dark-matter densities, in units of . The CMB and BBN measure these directly (they fix the amount of matter per unit volume at a given temperature, independent of ).
is the dimensionless Hubble parameter: . Planck 2018 gives .
and describe the primordial scalar curvature power spectrum, , at the pivot scale .
is the optical depth to reionisation. Photons that reach us today have a chance of having rescattered after the universe was reionised.
, slightly above because of partial heating of neutrinos during annihilation.
sets the absolute photon temperature today; combined with it fixes via the Stefan-Boltzmann law.
is the primordial helium mass fraction; relevant for recombination because each helium atom contributes two electrons.
Units
We use natural units with . The remaining dimensional scale is length, in megaparsecs:
Comoving wavenumbers are in . The Hubble parameter has units of as well (since ). Two “Hubble” parameters will appear:
The combination , which appears throughout the perturbation equations, is dimensionless.
What we will build
Here is the architecture we will assemble, chapter by chapter:
- Chapter 1 – Background
Physical constants.
init_background,total_density_a4,hubble,conformal_time,sound_horizon,build_background. The expanding-universe layer that every later chapter relies on.- Chapter 2 – Recombination
solve_recombination(Peebles ODEs), reionisation,build_thermodynamics(visibility function).- Chapter 3 – Perturbations
init_perturbation_grid,adiabatic_ics,boltzmann_derivs,evolve_k. The Boltzmann hierarchy in synchronous gauge with tight coupling.- Chapter 4 – Line of sight
build_sources: the Seljak-Zaldarriaga trick that turns the hierarchy into a one-dimensional integral.- Chapter 5 – Power spectra
make_k_grid,make_tau_grid,compute_spectra. Projection to , , . First validation against CAMB.- Chapter 6 – Lensing
lensing_potential, Wigner- recursion,lens_spectra. Lensed TT/EE/BB.- Chapter 7 – Tensors
tensor_spectra. Tensor BB from primordial gravitational waves. Final validation against CAMB.
By the end your notebook will have on the order of lines of code, divided into about thirty cells. Each cell is a function (or a small group) tied to a specific equation in the text. If you ever lose track of why a particular line exists, the section that introduced it explains it. The code does not depend on anything not shown in the chapters.
Mathematical tools you will meet later
A few mathematical objects are needed only in specific chapters; we introduce each where it first appears so that you build intuition together with the physics:
Christoffel symbols, Ricci tensor, Einstein equations – chapter 1, when we derive the Friedmann equation from general relativity.
Conformal time and the comoving horizon – chapter 1, end.
Spherical Bessel functions – chapter 4, where they appear in the line-of-sight integration.
Spherical harmonics and the addition theorem – chapter 4, when we move from Fourier modes to multipoles.
Wigner -functions – chapter 6, when we lens polarisation. They generalise Legendre polynomials to spin-2 fields.
Once Cell 1 has run without error, you are ready for chapter 1.