A small C++ library that calculates the optical depth to resonant line scattering in a cosmological background. This was implemented for Ly$\alpha$ forest calculations, but can easily be extended to other atomic species.
The build system is just a Makefile
that creates the static library
libispec.a
. Please modify the make variables CXX
, CPPFLAGS
,
CXXFLAGS
, and LDFLAGS
as needed.
We want to compute the optical depth to resonant line scattering
\tau_\nu = \int n_X \sigma_\nu dr
where
The cross section for resonant line scattering is
\sigma_\nu = \frac{\pi e^2}{m_e c} \frac{f_{lu}}{\Delta \nu_D} \phi_\nu \ = \frac{\pi e^2}{m_e c} \lambda_{lu} f_{lu} \frac{\phi_\nu}{b}
where
We can evaluate the path integral in many coordinates systems, but for most
problems, it is simplest to use velocity coordinates. At fixed redshift, we
have
In general, the line profile is a Voigt profile
Altogether the optical depth is
\tau_v = \frac{\pi e^2}{m_e c} \frac{\lambda_{lu} f_{lu}}{H(z)} \int \frac{n_X}{b} \pi^{-1/2} \exp[-\frac{(v - v' - v_\parallel)^2}{b^2}] dv'
The terms outside the integral are a constant for all optical depths
The library provides three methods for evaluating the integral above. In all
cases, the user provides regularly spaced arrays of n, v, and T, and the
functions compute the optical depth with a regular spacing on the same domain.
All functions assume that the path data is cell-centered,
The midpoint function is the simplest scheme, evaluating the integrand for each input element and summing. This is fastest, but will underestimate the contribution from thin lines for instance.
The midpoint linear subsample scheme is an improvement. This function assumes that we can linearly interpolate between the element points and evaluate the midpoint approximation to the integral with finer spacing. However, linear interpolation might not be appropriate.
The piecewise constant scheme assumes the element data is constant between points. In this case, the integral is analytic and the result does not depend on sampling. This is the most robust method, although it has the disadvantage of assuming PWC data.
We include a test suite in the test
directory. We use the Catch
library for
testing. Each cc
file contains test problems marked with the TEST_CASE
macro. The test suite includes a few unit tests and two toy problems.
Integrating over a path where n, v, and T are constant. In this case,
\tau_v = A n \int b^{-1} \pi^{-1/2} \exp[-(v - v' - v_\parallel)^2 / b^2] dv' = A n / 2 [ erf( (v - v_a) / b ) - erf( (v - v_b) / b ) ]
where v_a and v_b are the path bounds.
Integrating over a path where v and T are constant and n(v) = n_0 exp[-(v - v_0)^2 / a^2]. The solution is analytic, but ugly.
\tau_v = A n_0 \int b^{-1} \pi^{-1/2} \exp[-(v - v_0)^2 / a^2] \exp[-(v - v' - v_\parallel)^2 / b^2] dv' = A n_0 a / (2 c) exp[-(v - v_0 - v_\parallel)^2 / c^2] [ erf( (a^2 (v_b + v_\parallel - v) + b^2 (v_b - v_0)) / (a b c) ) - erf( (a^2 (v_a + v_\parallel - v) + b^2 (v_a - v_0)) / (a b c) ) ]
where