{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example 8: Ionization and Thermal History"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this part of the notebook, we will show several different examples of how to evaluate the temperature and ionization histories using many of the different options available to `DarkHistory`. The function that solves the differential equations is [*history.tla.get_history()*](https://darkhistory.readthedocs.io/en/latest/_autosummary/darkhistory/history/tla/darkhistory.history.tla.get_history.html), and the set of equations that is solved can be compactly written as follows:\n",
    "\n",
    "$$ \\dot{T}_m = \\dot{T}_m^{(0)} + \\dot{T}_m^{\\text{inj}} + \\dot{T}_m^\\text{re} $$\n",
    "\n",
    "$$ \\dot{x}_\\text{HII} = \\dot{x}_\\text{HII}^{(0)} + \\dot{x}_\\text{HII}^{\\text{inj}} + \\dot{x}_\\text{HII}^\\text{re} $$\n",
    "\n",
    "$$ \\dot{x}_\\text{HeII} = \\dot{x}_\\text{HeII}^{(0)} + \\dot{x}_\\text{HeII}^{\\text{inj}} + \\dot{x}_\\text{HeII}^\\text{re} $$\n",
    "\n",
    "with each of the terms defined in Eqs. (2), (5), (51), and (52) of paper I."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Notebook Initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "import sys\n",
    "sys.path.append(\"..\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%autoreload\n",
    "\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "matplotlib.rc_file('matplotlibrc')\n",
    "\n",
    "\n",
    "import numpy as np\n",
    "from scipy.interpolate import interp1d\n",
    "\n",
    "import darkhistory.physics as phys\n",
    "import darkhistory.history.tla as tla"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Standard Ionization and Temperature Histories with Helium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The most basic use of `get_history` is to obtain the standard ionization and temperature histories with no exotic energy injection sources or reionization. In the simplest approximation, we can neglect helium and simply evaluate the following equations:\n",
    "\n",
    "$$ \\dot{T}_m = \\dot{T}_m^{(0)}, \\qquad \\dot{x}_\\text{HII} = \\dot{x}_\\text{HII}^{(0)}. $$\n",
    "\n",
    "First, we initialize the redshift abscissa. This must be defined in decreasing redshift. Note that the transfer functions used in calculating $f_c(z)$ only span a redshift range of $4 \\leq 1+z \\leq 3000$. In this example, we solve the TLA from $1+z = 3000$ to $1+z = 1$. \n",
    "\n",
    "First, we define a redshift vector at which we would like to find the solution. The vector must be stored in *decreasing* redshift order, and should always be defined as $1+z$. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rs_vec = np.flipud(np.arange(1., 3000., 0.1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we call the solver. If we simply pass the redshift abscissa to the function with no further options, the solution will not have any source of reionization, and helium is ignored. The initial conditions can be manually passed to the solver through the keyword argument `init_cond`, but not initializing it will result in the solver starting at the standard ionization and temperature values at `rs_vec[0]`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "soln_no_He = tla.get_history(rs_vec)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we would like to also solve for the helium ionization fraction, i.e. solve the system\n",
    "\n",
    "$$ \\dot{T}_m = \\dot{T}_m^{(0)}, \\qquad \\dot{x}_\\text{HII} = \\dot{x}_\\text{HII}^{(0)}, \\qquad \\dot{x}_\\text{HeII} = \\dot{x}_\\text{HeII}^{(0)}, $$\n",
    "\n",
    "we will need to set the `helium_TLA` flag to `True`. Here is how we call the function:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "soln_with_He = tla.get_history(rs_vec, helium_TLA=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The solution is returned as an array with dimensions `(rs_vec.size, 4)`. Each column corresponds to the solution for ($T_m$ in eV, $x_\\mathrm{HII}$, $x_\\mathrm{HeII}$, $x_\\mathrm{HeIII}$). Let's plot temperature in K, and the ionization fraction $x_e = x_\\mathrm{HII} + x_\\mathrm{HeII}$ as a function of redshift $1+z$. We will plot both solutions for comparison."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "Tm = soln_no_He[:,0]/phys.kB\n",
    "\n",
    "xe_no_He   = soln_no_He[:,1]\n",
    "# The other columns with xHeII and xHeIII are negligible.\n",
    "xe_with_He = soln_with_He[:,1] + soln_with_He[:,2]\n",
    "#The last column with xHeIII is negligible\n",
    "\n",
    "\n",
    "fig_He = plt.figure(figsize=(15,6.5))\n",
    "\n",
    "ax = plt.subplot(1,2,1)\n",
    "\n",
    "plt_T_IGM, = plt.plot(rs_vec, Tm, label='IGM Temperature')\n",
    "# Plot the CMB temperature for comparison, using the function phys.TCMB\n",
    "plt_T_CMB, = plt.plot(rs_vec, phys.TCMB(rs_vec)/phys.kB, 'k--', label='CMB Temperature')\n",
    "\n",
    "ax.set_xscale('log')\n",
    "ax.set_yscale('log')\n",
    "\n",
    "plt.legend(handles=[plt_T_IGM, plt_T_CMB], loc=4)\n",
    "\n",
    "\n",
    "plt.title(r'\\bf{Temperature History}')\n",
    "plt.xlabel(r'Redshift $(1+z)$')\n",
    "plt.ylabel('Temperature [K]')\n",
    "plt.axis([1, 2e3, 1e-2, 1e4])\n",
    "\n",
    "ax = plt.subplot(1,2,2)\n",
    "\n",
    "plt_He,    = plt.plot(rs_vec, xe_with_He, label=r'$x_e$, with He')\n",
    "plt_no_He, = plt.plot(rs_vec, xe_no_He,   label=r'$x_e$, no He')\n",
    "\n",
    "plt.legend(handles=[plt_He, plt_no_He], loc=2)\n",
    "\n",
    "# ax.set_xscale('log')\n",
    "ax.set_yscale('log')\n",
    "\n",
    "plt.title(r'\\bf{Ionization History}')\n",
    "plt.xlabel(r'Redshift $(1+z)$')\n",
    "plt.ylabel(r'Free Electron Fraction $x_e$')\n",
    "plt.axis([1, 3e3, 1e-4, 2.7])\n",
    "\n",
    "from matplotlib.transforms import blended_transform_factory\n",
    "from mpl_toolkits.axes_grid1.inset_locator import inset_axes\n",
    "from mpl_toolkits.axes_grid1.inset_locator import mark_inset\n",
    "\n",
    "transform = blended_transform_factory(fig_He.transFigure, ax.transAxes)\n",
    "axins = inset_axes(ax,  width=\"22%\", height=\"50%\",\n",
    "                    bbox_to_anchor=(0, 0.1, 0.885, 0.885),\n",
    "                    bbox_transform=transform, loc=4, borderpad=0)\n",
    "\n",
    "mark_inset(ax, axins, loc1=2, loc2=4, fc=\"none\", ec=\"0.5\")\n",
    "\n",
    "plt.plot(rs_vec, xe_with_He)\n",
    "plt.plot(rs_vec, xe_no_He)\n",
    "plt.title(r'\\bf{Helium Recombination}', fontsize=18, y = 0.95)\n",
    "plt.yticks([0.96, 1., 1.04, 1.08, 1.12])\n",
    "plt.xticks([1600, 2000, 2400, 2800])\n",
    "plt.axis([1.4e3, 3e3, 0.95, 1.13])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A few technical details to note.  Ionization levels are solved numerically using the variable \n",
    "\n",
    "$$\\zeta_i \\equiv \\text{arctanh} \\left[\\frac{2}{\\chi_i}\\left(x_i - \\frac{\\chi_i}{2} \\right) \\right]$$\n",
    "\n",
    "for $i = $ HII, HeII and HeIII, with $\\chi_i=1$ for HII and $\\chi_i = \\mathcal{F}_\\text{He}$ for HeII and HeIII. This guarantees that the ionization fraction $x_e$ is bounded between 0 and 1. As a result, it is common to find that $x_i$ values may not be completely zero when they are expected to be, but instead have some small, non-zero value. This is simply a negligible numerical error that can be ignored. Ionization levels below $10^{-12}$ should not be regarded as accurate. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reionization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Default Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The solver can also accept a reionization model. A default reionization model is included with `DarkHistory`. This model combines the fiducial photoionization and photoheating rates provided in [[1]](#cite_rates1) with rates for collisional ionization, collisional excitation, recombination cooling and bremsstrahlung cooling given in [[2]](#cite_rates2), in order to obtain the ionization/temperature change during reionization (for more details, refer to the paper). The photoionization and photoheating data for the model are stored in [*history.reionization*](https://darkhistory.readthedocs.io/en/latest/_autosummary/darkhistory/history/darkhistory.history.reionization.html).\n",
    "\n",
    "Reionization models must come with a redshift at which they turn on, $1+z_\\text{re}$ (the default model has $1+z_\\text{re} = 16.1$, and is set automatically by the code). Prior to reionization, the solver will integrate the usual set of equations without reionization:\n",
    "\n",
    "$$ \\dot{T}_m = \\dot{T}_m^{(0)}, \\qquad \\dot{x}_\\text{HII} = \\dot{x}_\\text{HII}^{(0)}, \\qquad \\dot{x}_\\text{HeII} = \\dot{x}_\\text{HeII}^{(0)}, $$\n",
    "\n",
    "Once reionization starts, it will instead integrate\n",
    "\n",
    "$$ \\dot{T}_m = \\dot{T}_m^{(0)} + \\dot{T}_m^\\text{re}, \\qquad \\dot{x}_\\text{HII} = \\dot{x}_\\text{HII}^\\text{re}, \\qquad \\dot{x}_\\text{HeII} = \\dot{x}_\\text{HeII}^\\text{re}, $$\n",
    "\n",
    "To obtain the temperature/ionization history with the default reionization model, simply specify `reion_switch = True`. In the default case, the solver knows when to switch to the reionization equations. For other models, the user must also specify the `reion_rs` flag. In this example, we will also solve for helium as well, which is the self-consistent thing to do here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "soln_default_reion = tla.get_history(rs_vec, helium_TLA=True, reion_switch=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And now plot the results. These results should be compared to Fig. 6 of [[1]](#cite_rates1) and are in good agreement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "fig_reion=plt.figure(figsize=(15,6.5))\n",
    "\n",
    "ax = plt.subplot(1,2,1)\n",
    "\n",
    "plt_Tm_reion, = plt.plot(rs_vec, soln_default_reion[:,0]/phys.kB, label=r'Matter Temperature $T_m$')\n",
    "\n",
    "# Text\n",
    "plt.text(0.06, 0.88, 'Reionization (Puchwein+)', fontsize=20, transform=ax.transAxes) \n",
    "\n",
    "leg = plt.legend(handles=[plt_Tm_reion], loc=3)\n",
    "\n",
    "plt.title(r'\\bf{Temperature History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel(r'Temperature [K]')\n",
    "plt.axis([1, 17.5, 0, 20000])\n",
    "\n",
    "ax = plt.subplot(1,2,2)\n",
    "\n",
    "plt_xHII, = plt.plot(rs_vec, soln_default_reion[:,1], linewidth=2, label=r'$n_\\mathrm{HII}/n_\\mathrm{H}$')\n",
    "plt_xHeII, = plt.plot(rs_vec, soln_default_reion[:,2]/phys.chi, linewidth=2, label=r'$n_\\mathrm{HeII}/n_\\mathrm{He}$')\n",
    "# The solution is stored as nHeII/nH, so it needs to be converted to nHeII/nHe. \n",
    "plt_xHeIII, = plt.plot(rs_vec, soln_default_reion[:,3]/phys.chi, linewidth=2, label=r'$n_\\mathrm{HeIII}/n_\\mathrm{He}$')\n",
    "# Same for HeIII. \n",
    "\n",
    "# Text\n",
    "plt.text(0.06, 0.88, 'Reionization (Puchwein+)', fontsize=20, transform=ax.transAxes) \n",
    "\n",
    "leg = plt.legend(handles=[plt_xHII, plt_xHeII, plt_xHeIII], loc=5)\n",
    "\n",
    "plt.title(r'\\bf{Ionization History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel('Ionization Fraction')\n",
    "plt.axis([1, 17.5, 0, 1.2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### User-Defined Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The user may enter their own photoionization and photoheating rates into the TLA solver. This is done by defining two tuples of functions, each containing the photoionization and photoheating rates respectively of HI, HeI and HeII. Here, we define functions `photoion_rate` and `photoheat_rate` to return these tuples, given some new photoionization and photoheating rates. In this example, we use the rates from [[3]](#cite_rates3)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def photoion_rate():\n",
    "    \n",
    "    rs_vec = 1. + np.array([\n",
    "        0.00, 0.05, 0.10, 0.16, 0.21, 0.27, 0.33, 0.40, 0.47,\n",
    "        0.54, 0.62, 0.69, 0.78, 0.87, 0.96, 1.05, 1.15, 1.26, \n",
    "        1.37, 1.49, 1.61, 1.74, 1.87, 2.01, 2.16, 2.32, 2.48,\n",
    "        2.65, 2.83, 3.02, 3.21, 3.42, 3.64, 3.87, 4.11, 4.36,\n",
    "        4.62, 4.89, 5.18, 5.49, 5.81, 6.14, 6.49, 6.86, 7.25,\n",
    "        7.65, 8.07, 8.52, 8.99, 9.48, 9.99, 10.50, 11.10, 11.70,\n",
    "        12.30, 13.00, 13.70, 14.40, 15.10\n",
    "    ])\n",
    "    \n",
    "    rate_vec_HI = np.array([\n",
    "        22.8, 28.4, 35.4, 44.0, 54.6, 67.4, 83.1, 102, 125,\n",
    "        152, 185, 223, 267, 318, 376, 440, 510, 585, 660, 732, \n",
    "        799, 859, 909, 944, 963, 965, 950, 919, 875, 822, 765, \n",
    "        705, 647, 594, 546, 504, 469, 441, 412, 360, 293, 230,\n",
    "        175, 129, 92.8, 65.5, 45.6, 31.2, 21.2, 14.3, 9.59, \n",
    "        6.40, 4.27, 2.92, 1.73, 1.02, 0.592, 0.341, 0.194\n",
    "    ]) * 1e-15\n",
    "    \n",
    "    rate_vec_HeI = np.array([\n",
    "        12.4, 15.7, 19.6, 24.6, 30.7, 38.3, 47.5, 58.7, 72.2,\n",
    "        88.4, 108, 130, 157, 187, 222, 261, 302, 346, 391, \n",
    "        434, 474, 509, 538, 557, 567, 566, 555, 535, 508,\n",
    "        476, 441, 406, 372, 341, 314, 291, 271, 253, 237, 214,\n",
    "        184, 154, 125, 99.2, 76.1, 56.8, 41.4, 29.6, 20.7, \n",
    "        14.4, 9.82, 6.67, 4.53, 3.24, 2.02, 1.23, 0.746, 0.446,\n",
    "        0.262\n",
    "    ]) * 1e-15\n",
    "    \n",
    "    rate_vec_HeII = np.array([\n",
    "        0.555, 0.676, 0.823, 1.00, 1.22, 1.48, 1.80, 2.18,\n",
    "        2.63, 3.17, 3.80, 4.54, 5.38, 6.33, 7.38, 8.52, \n",
    "        9.70, 10.9, 11.9, 12.7, 13.2, 13.4, 13.3, 12.8, \n",
    "        11.9, 10.6, 9.04, 7.22, 5.30, 3.51, 2.08, 1.14,\n",
    "        0.591, 0.302, 0.152, 0.0760, 0.0375, 0.0182,\n",
    "        0.00857, 0.00323, 0.00117, 4.42e-4, 1.73e-4, \n",
    "        7.01e-5, 2.92e-5, 1.25e-5, 5.67e-6, 2.74e-6, 1.44e-6,\n",
    "        8.19e-7, 4.99e-7, 3.25e-7, 2.12e-7, 1.43e-7, 9.84e-8,\n",
    "        6.81e-8, 4.73e-8, 3.30e-8, 1.92e-8\n",
    "    ]) * 1e-15\n",
    "\n",
    "    def ion_rate_HI(rs):\n",
    "        log10_rate = np.interp(rs, rs_vec, np.log10(rate_vec_HI))\n",
    "        return 10**log10_rate\n",
    "    \n",
    "    def ion_rate_HeI(rs):\n",
    "        log10_rate = np.interp(rs, rs_vec, np.log10(rate_vec_HeI))\n",
    "        return 10**log10_rate\n",
    "    \n",
    "    def ion_rate_HeII(rs):\n",
    "        log10_rate = np.interp(rs, rs_vec, np.log10(rate_vec_HeII))\n",
    "        return 10**log10_rate\n",
    "\n",
    "    return (ion_rate_HI, ion_rate_HeI, ion_rate_HeII)\n",
    "\n",
    "def photoheat_rate():\n",
    "    \n",
    "    rs_vec = 1. + np.array([\n",
    "        0.00, 0.05, 0.10, 0.16, 0.21, 0.27, 0.33, 0.40, 0.47,\n",
    "        0.54, 0.62, 0.69, 0.78, 0.87, 0.96, 1.05, 1.15, 1.26, \n",
    "        1.37, 1.49, 1.61, 1.74, 1.87, 2.01, 2.16, 2.32, 2.48,\n",
    "        2.65, 2.83, 3.02, 3.21, 3.42, 3.64, 3.87, 4.11, 4.36,\n",
    "        4.62, 4.89, 5.18, 5.49, 5.81, 6.14, 6.49, 6.86, 7.25,\n",
    "        7.65, 8.07, 8.52, 8.99, 9.48, 9.99, 10.50, 11.10, 11.70,\n",
    "        12.30, 13.00, 13.70, 14.40, 15.10\n",
    "    ])\n",
    "    \n",
    "    rate_vec_HI = np.array([\n",
    "        8.89, 11.1, 13.9, 17.3, 21.5, 26.6, 32.9, 40.5, 49.6, \n",
    "        60.5, 73.4, 88.5, 106, 126, 149, 175, 203, 232, 262,\n",
    "        290, 317, 341, 360, 374, 381, 382, 375, 363, 346, 325,\n",
    "        302, 279, 257, 236, 218, 202, 189, 178, 167, 148, 123,\n",
    "        98.9, 77.1, 58.3, 43.0, 31.0, 21.9, 15.3, 10.5, 7.13, \n",
    "        4.81, 3.23, 2.17, 1.51, 0.915, 0.546, 0.323, 0.189, 0.110\n",
    "    ]) * 1e-14\n",
    "    \n",
    "    rate_vec_HeI = np.array([\n",
    "        11.2, 14.0, 17.4, 21.6, 26.7, 33.1, 40.8, 50.2, 61.5,\n",
    "        75.1, 91.1, 110, 132, 157, 186, 217, 251, 287, 323, \n",
    "        357, 387, 413, 432, 444, 446, 438, 422, 398, 368, 336,\n",
    "        304, 274, 249, 227, 209, 194, 181, 170, 160, 146, 130, \n",
    "        112, 95.2, 78.3, 62.5, 48.3, 36.3, 26.6, 19.1, 13.4, \n",
    "        9.27, 6.36, 4.35, 3.14, 1.98, 1.22, 0.749, 0.455, 0.270\n",
    "    ])* 1e-14\n",
    "\n",
    "    rate_vec_HeII = np.array([\n",
    "        1.14, 1.38, 1.68, 2.03, 2.45, 2.96, 3.57, 4.29, 5.14,\n",
    "        6.15, 7.32, 8.67, 10.2, 11.9, 13.9, 15.9, 18.1, 20.2,\n",
    "        22.1, 23.7, 24.7, 25.3, 25.2, 24.4, 22.9, 20.7, 17.8,\n",
    "        14.5, 11.1, 7.75, 4.97, 2.96, 1.68, 0.925, 0.501, 0.267,\n",
    "        0.141, 0.0727, 0.0365, 0.0156, 0.00624, 0.00269, 0.00128,\n",
    "        6.74e-4, 3.88e-4, 2.40e-4, 1.55e-4, 1.03e-4, 6.98e-5, \n",
    "        4.76e-5, 3.26e-5, 2.24e-5, 1.53e-5, 1.06e-5, 7.52e-6,\n",
    "        5.31e-6, 3.73e-6, 2.57e-6, 1.54e-6\n",
    "    ]) * 1e-14\n",
    "\n",
    "    def heat_rate_HI(rs):\n",
    "        log10_rate = np.interp(rs, rs_vec, np.log10(rate_vec_HI))\n",
    "        return 10**log10_rate\n",
    "    \n",
    "    def heat_rate_HeI(rs):\n",
    "        log10_rate = np.interp(rs, rs_vec, np.log10(rate_vec_HeI))\n",
    "        return 10**log10_rate\n",
    "    \n",
    "    def heat_rate_HeII(rs):\n",
    "        log10_rate = np.interp(rs, rs_vec, np.log10(rate_vec_HeII))\n",
    "        return 10**log10_rate\n",
    "\n",
    "    return (heat_rate_HI, heat_rate_HeI, heat_rate_HeII)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we call the solver. In addition to setting `reion_switch=True`, we must also specify the redshift `reion_rs` at which reionization effects start, as well as the two tuples for `photoion_rate_func` and `photoheat_rate_func` respectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "soln_user_reion = tla.get_history(\n",
    "    rs_vec, helium_TLA=True, reion_switch=True, \n",
    "    reion_rs = 16.1, photoion_rate_func=photoion_rate(), photoheat_rate_func=photoheat_rate()\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Plot the results, and compare them to the our default model. Again, this shows good agreement with Fig. 6 of [[1]](#cite_rates1)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "plt.figure(figsize=(15,6.5))\n",
    "\n",
    "ax = plt.subplot(1,2,1)\n",
    "plt.rc('text', usetex=True)\n",
    "\n",
    "plt_Tm_Puchwein, = plt.plot(rs_vec, soln_default_reion[:,0]/phys.kB, ':', label='Matter Temperature, Puchwein+')\n",
    "plt_Tm_Haardt, = plt.plot(rs_vec, soln_user_reion[:,0]/phys.kB, label='Matter Temperature, Haardt+')\n",
    "\n",
    "plt.legend(handles=[plt_Tm_Puchwein, plt_Tm_Haardt])\n",
    "\n",
    "\n",
    "plt.title(r'\\bf{Temperature History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel('Temperature [K]')\n",
    "plt.axis([1, 17.5, 0, 20000])\n",
    "\n",
    "ax = plt.subplot(1,2,2)\n",
    "\n",
    "plt_xHII_Puchwein, = plt.plot(\n",
    "    rs_vec, soln_default_reion[:,1], ':',\n",
    "    label=r'$n_\\mathrm{HII}/n_\\mathrm{H}$, Puchwein+'\n",
    ")\n",
    "plt_xHII_Haardt, = plt.plot(\n",
    "    rs_vec, soln_user_reion[:,1],\n",
    "    label=r'$n_\\mathrm{HII}/n_\\mathrm{H}$, Haardt+'\n",
    ")\n",
    "plt_xHeIII_Puchwein, = plt.plot(\n",
    "    rs_vec, soln_default_reion[:,3]/phys.chi, ':',\n",
    "    label=r'$n_\\mathrm{HeIII}/n_\\mathrm{He}$, Puchwein+'\n",
    ")\n",
    "plt_xHeIII_Haardt, = plt.plot(\n",
    "    rs_vec, soln_user_reion[:,3]/phys.chi, \n",
    "    label=r'$n_\\mathrm{HeIII}/n_\\mathrm{He}$, Haardt+'\n",
    ")\n",
    "\n",
    "plt.legend(handles=[plt_xHII_Puchwein, plt_xHII_Haardt, plt_xHeIII_Puchwein, plt_xHeIII_Haardt], loc=1)\n",
    "\n",
    "plt.title(r'\\bf{Ionization History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel('Ionization Fraction')\n",
    "plt.axis([1, 17.5, 0, 1.55])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fixed Ionization History"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A less self-consistent way to model reionization is to fix the ionization history once reionization begins. When combined with exotic sources of energy injection, this treatment will not account for additional ionization from the energy injection, while the energy deposition into heating will be calculated based only on the fixed ionization history that has been specified. However, if we expect the additional ionization from energy injection to only be a small perturbation on top of reionization, this may be a good approximation.\n",
    "\n",
    "We will now take the standard $\\text{tanh}$ model that is used in [[4]](#cite_tanh), with\n",
    "\n",
    "$$ x_e = \\frac{1+\\mathcal{F}_\\text{He}}{2} \\left[1 + \\tanh \\left( \\frac{ \\eta - \\eta_\\text{re}}{\\delta \\eta} \\right) \\right] . $$\n",
    "\n",
    "$\\eta \\equiv (1+z)^{3/2}$, and we take $\\delta \\eta = 0.75 (1+z)^{1/2}$. We choose $z_\\text{re} = 8.8$ and $\\delta \\eta = 1.5(1+z)^{1/2} \\times 0.7$.\n",
    "\n",
    "For simplicity, `DarkHistory` always assumes $n_\\text{HII} = n_\\text{HeII}$, a standard assumption in many reionization models. Changing this assumption would only require a relatively straightforward but messy modification to [*history.tla.get_history()*](https://darkhistory.readthedocs.io/en/latest/_autosummary/darkhistory/history/tla/darkhistory.history.tla.get_history.html). We do not implement the full reionization of HeII to HeIII.\n",
    "\n",
    "We first define the model as a function that takes in redshift $1+z$ and returns the $x_e$ value:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the standard ionization history as an interpolation function for convenience. \n",
    "\n",
    "def xe_reion_func(rs):\n",
    "    # Parameters of the model.\n",
    "    \n",
    "    f = 1. + phys.chi\n",
    "    delta_z = 0.7\n",
    "    delta_eta = 1.5*rs**0.5*delta_z\n",
    "    z_re = 8.8\n",
    "    eta = rs**(3/2)\n",
    "    eta_re = (1 + z_re)**(3/2)\n",
    "    \n",
    "    reion_model_xe = (f/2)*(1 + np.tanh((eta_re - eta)/delta_eta))\n",
    "    \n",
    "    return reion_model_xe"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we pass it to the solver through the flag `xe_reion_func`. Remember to also specify `reion_rs`, which we take to be $1+z_\\text{re} = 10$ here. In order to try to give smooth solutions, the switchover point into the reionization model is *not* given strictly by `reion_rs`, but by the largest redshift where `xe_reion_func` first returns a value of $x_e$ that exceeds the solution without reionization."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "soln_fixed_reion = tla.get_history(\n",
    "    rs_vec, reion_switch=True, helium_TLA=True,\n",
    "    reion_rs = 13., xe_reion_func = xe_reion_func\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the plot! Note that this treatment completely neglects the photoheating contribution to the IGM temperature, leading to a very cold IGM compared to the earlier, more complete reionization models. This may however still be useful for setting lower bounds. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(15,6.5))\n",
    "\n",
    "ax = plt.subplot(1,2,1)\n",
    "\n",
    "plt_TIGM, = plt.plot(rs_vec, soln_fixed_reion[:,0]/phys.kB, label=r'Matter Temperature $T_m$')\n",
    "\n",
    "# Text\n",
    "plt.text(0.06, 0.88, 'Reionization (tanh)', fontsize=20, transform=ax.transAxes) \n",
    "\n",
    "plt.axis([1, 18.5, 1, 12.5])\n",
    "plt.title(r'\\bf{Temperature History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel('Temperature [K]')\n",
    "\n",
    "leg=plt.legend(handles=[plt_TIGM], loc=4)\n",
    "\n",
    "ax = plt.subplot(1,2,2)\n",
    "\n",
    "plt_xHII,  = plt.plot(rs_vec, soln_fixed_reion[:,1], label=r'$n_\\mathrm{HII}/n_\\mathrm{H}$')\n",
    "plt_xHeII, = plt.plot(rs_vec, soln_fixed_reion[:,2], label=r'$n_\\mathrm{HeII}/n_\\mathrm{H}$')\n",
    "plt_xe,    = plt.plot(rs_vec, soln_fixed_reion[:,1] + soln_fixed_reion[:,2], label=r'$n_e/n_\\mathrm{H}$')\n",
    "\n",
    "# Text\n",
    "plt.text(0.06, 0.88, 'Reionization (tanh)', fontsize=20, transform=ax.transAxes) \n",
    "\n",
    "leg=plt.legend(handles=[plt_xHII, plt_xHeII, plt_xe], loc=5)\n",
    "\n",
    "plt.axis([1, 18.5, -0.1, 1.4])\n",
    "\n",
    "plt.title(r'\\bf{Ionization History}')\n",
    "plt.xlabel(r'Redshift $(1+z)$')\n",
    "plt.ylabel(r'Ionization Fraction')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reionization + Dark Matter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Dark Matter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we will introduce dark matter into the TLA equations. We introduce a dark matter species with mass $m_\\chi = $ 100 MeV that decays with some (long) lifetime into an $e^+e^-$ pair. The energy injection rate is:\n",
    "\n",
    "$$ \\left( \\frac{dE}{dV \\, dt} \\right)_{\\text{inj.}} = \\frac{\\rho_{\\text{DM},0}}{\\tau} (1 + z)^3  $$\n",
    "\n",
    "where $\\tau$ is the lifetime, and $\\rho_{\\text{DM},0}$ is the dark matter density today. \n",
    "\n",
    "In this example, we will simply use the $f_c(z)$ computed in DarkHistory without backreaction.  We call these $f_c(z)$ values the \"baseline $f_c(z)$\" values. *If the user only intends to use these baseline $f_c(z)$ values, then `get_history()` alone is sufficient for all purposes*. The rest of `DarkHistory` is focused on correctly computing $f_c(z,\\mathbf{x})$ to ensure that backreaction is taken into account.\n",
    "\n",
    "There are two ways to solve the TLA with DM injection using the baseline $f_c(z)$, i.e. without backreaction. The user can call `main.evolve()` with `backreaction = False` or, if the only information they require is the matter temperature and ionization levels, they can directly call `get_history()` with `baseline_f=True`. These $f_c(z)$ values were calculated by Darkhistory and are provided in the downloaded data folder. `get_history()` is also much faster, since it does not calculate spectra."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once we specify the DM parameters, we can now call the solver in the manner shown below (we turn off helium for this example).  We set $m_\\chi = 100 $ MeV and $\\tau = 3 \\times 10^{25}$s.  With dark matter, the redshift cannot go below $1+z = 4$, where the `DarkHistory` calculation of $f_c(z)$ stops."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "%autoreload\n",
    "rs_vec_DM = np.flipud(np.arange(4, 3000., 0.1))\n",
    "\n",
    "soln_DM = tla.get_history(\n",
    "    rs_vec_DM, baseline_f = True,\n",
    "    inj_particle = 'elec', DM_process = 'decay',\n",
    "    mDM=1e8, lifetime = 3e25,\n",
    "    reion_switch=False,\n",
    "    helium_TLA=False\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And this is the outcome of the computation. We will compare these results with the standard solution with no dark matter energy injection or reionization, which is accessible through `physics.xH_std` and `physics.Tm_std`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "Tm_DM = soln_DM[:,0]/phys.kB\n",
    "xHII_DM = soln_DM[:,1]\n",
    "\n",
    "fig_DM = plt.figure(figsize=(15,6.5))\n",
    "\n",
    "ax = plt.subplot(1,2,1)\n",
    "\n",
    "plt_T_DM,  = plt.plot(rs_vec_DM, Tm_DM, label=r'Matter Temperature $T_m$, with DM')\n",
    "plt_T_std, = plt.plot(rs_vec_DM, phys.Tm_std(rs_vec_DM)/phys.kB, label=r'Matter Temperature $T_m$, no DM') \n",
    "# Plot the CMB temperature for comparison, using the function phys.TCMB\n",
    "plt_T_CMB, = plt.plot(rs_vec_DM, phys.TCMB(rs_vec_DM)/phys.kB, 'k--', label=r'CMB Temperature $T_\\mathrm{CMB}$')\n",
    "\n",
    "# Text\n",
    "plt.text(0.06, 0.88, r'$\\chi \\to e^+e^-$, $m_\\chi$ = 100 MeV', fontsize=20, transform=ax.transAxes) \n",
    "plt.text(0.06, 0.82, r'$\\tau = 3 \\times 10^{25}$ s', fontsize=20, transform=ax.transAxes)\n",
    "\n",
    "ax.set_xscale('log')\n",
    "ax.set_yscale('log')\n",
    "\n",
    "leg = plt.legend(handles=[plt_T_DM, plt_T_std, plt_T_CMB], loc=4)\n",
    "\n",
    "\n",
    "plt.title(r'\\bf{Temperature History}')\n",
    "plt.xlabel(r'Redshift $(1+z)$')\n",
    "plt.ylabel('Temperature [K]')\n",
    "plt.axis([4, 3e3, 1e-1, 3e4])\n",
    "\n",
    "ax = plt.subplot(1,2,2)\n",
    "\n",
    "plt_xHII_DM,    = plt.plot(rs_vec_DM, xHII_DM, label=r'$n_\\mathrm{HII}/n_\\mathrm{H}$, with DM')\n",
    "plt_xHII_std,   = plt.plot(rs_vec_DM, phys.xHII_std(rs_vec_DM), label=r'$n_\\mathrm{HII}/n_\\mathrm{H}$, no DM')\n",
    "\n",
    "# Text\n",
    "plt.text(0.06, 0.88, r'$\\chi \\to e^+e^-$, $m_\\chi$ = 100 MeV', fontsize=20, transform=ax.transAxes) \n",
    "plt.text(0.06, 0.82, r'$\\tau = 3 \\times 10^{25}$ s', fontsize=20, transform=ax.transAxes)\n",
    "\n",
    "leg = plt.legend(handles=[plt_xHII_DM, plt_xHII_std], loc=4)\n",
    "\n",
    "\n",
    "ax.set_xscale('log')\n",
    "ax.set_yscale('log')\n",
    "\n",
    "plt.title(r'\\bf{Ionization History}')\n",
    "plt.xlabel(r'Redshift $(1+z)$')\n",
    "plt.ylabel(r'Ionization Fraction $x_\\mathrm{HII}$')\n",
    "plt.axis([4, 3e3, 1e-5, 3])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Dark Matter and Reionization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now it's time to combine dark matter energy injection with reionization! This is easily done by turning `reion_switch` to `True` to use the default reionization model. Again, for comparison, we provide the solution without and with backreaction turned on.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "soln_DM_reion = tla.get_history(\n",
    "    rs_vec_DM, baseline_f = True,\n",
    "    inj_particle = 'elec', DM_process = 'decay',\n",
    "    mDM=1e8, lifetime = 3e25,\n",
    "    reion_switch=True,\n",
    "    helium_TLA=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To calculate the result with backreaction, [*main.evolve()*](https://darkhistory.readthedocs.io/en/latest/_autosummary/main/main.evolve.html) must be used, with `backreaction = True`. For the case of $\\chi \\to e^+e^-$ without any electroweak corrections, `primary` must be set to `elec_delta`. Since we are importing `main` for the first time, the transfer functions will be loaded. We'll compute both the results without reionization `soln_DM_BR` and `soln_DM_reion_BR`. Reionization is turned on by setting `reion_switch = True`, and uses the default reionization model. `helium_TLA` should be set to `True` as well for consistency.\n",
    "\n",
    "Without reionization, `coarsen_factor = 32` is a reasonable choice, since the temperature changes slowly with redshift. Coarsening with reionization should be used with caution, due to rapid changes in temperature that should be integrated over small step sizes. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%autoreload 2\n",
    "\n",
    "import darkhistory.main as main\n",
    "import darkhistory.main as main\n",
    "\n",
    "soln_DM_BR = main.evolve(\n",
    "    DM_process='decay', mDM=1e8, lifetime=3e25, primary='elec_delta',\n",
    "    start_rs = 3000,\n",
    "    coarsen_factor=32, backreaction=True\n",
    ")\n",
    "\n",
    "soln_DM_reion_BR = main.evolve(\n",
    "    DM_process='decay', mDM=1e8, lifetime=3e25, primary='elec_delta',\n",
    "    start_rs = 3000,\n",
    "    coarsen_factor=12, backreaction=True, helium_TLA=True, reion_switch=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's compare the various solutions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "# DM, no reionization, no backreaction.\n",
    "Tm_DM   = soln_DM[:,0]/phys.kB\n",
    "xHII_DM = soln_DM[:,1]\n",
    "\n",
    "# DM, no reionization, with backreaction.\n",
    "rs_vec_BR  = soln_DM_BR['rs']\n",
    "Tm_DM_BR   = soln_DM_BR['Tm']/phys.kB\n",
    "xHII_DM_BR = soln_DM_BR['x'][:,0]\n",
    "\n",
    "# DM, reionization, no backreaction.\n",
    "Tm_DM_reion = soln_DM_reion[:,0]/phys.kB\n",
    "xHII_DM_reion = soln_DM_reion[:,1]\n",
    "\n",
    "# DM, reionization, with backreaction.\n",
    "rs_vec_DM_reion_BR = soln_DM_reion_BR['rs']\n",
    "Tm_DM_reion_BR     = soln_DM_reion_BR['Tm']/phys.kB\n",
    "xHII_DM_reion_BR   = soln_DM_reion_BR['x'][:,0]\n",
    "\n",
    "fig_reion=plt.figure(figsize=(15,6.5))\n",
    "\n",
    "ax = plt.subplot(1,2,1)\n",
    "\n",
    "plt_Tm_DM,          = plt.plot(rs_vec_DM, Tm_DM, ':', linewidth=4, label='Dark Matter')\n",
    "plt_Tm_DM_BR,       = plt.plot(rs_vec_BR, Tm_DM_BR, ':', linewidth=4, label='DM+Backreaction')\n",
    "plt_Tm_reion,       = plt.plot(rs_vec, soln_default_reion[:,0]/phys.kB, 'k--', label='Reionization')\n",
    "plt_Tm_DM_reion,    = plt.plot(rs_vec_DM, Tm_DM_reion, label='Reion.+DM')\n",
    "plt_Tm_DM_reion_BR, = plt.plot(rs_vec_DM_reion_BR, Tm_DM_reion_BR, label='Reion.+DM+Backreaction')\n",
    "\n",
    "# Text\n",
    "plt.text(0.37, 0.88, r'$\\chi \\to e^+e^-$, $m_\\chi$ = 100 MeV', fontsize=20, transform=ax.transAxes) \n",
    "plt.text(0.63, 0.82, r'$\\tau = 3 \\times 10^{25}$ s', fontsize=20, transform=ax.transAxes)\n",
    "\n",
    "leg = plt.legend(handles=[plt_Tm_DM, plt_Tm_DM_BR, plt_Tm_reion, plt_Tm_DM_reion, plt_Tm_DM_reion_BR], loc=(0.33, 0.43))\n",
    "\n",
    "\n",
    "plt.title(r'\\bf{Temperature History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel('Matter Temperature $T_m$ [K]')\n",
    "plt.axis([4, 22, 0, 25000])\n",
    "\n",
    "ax = plt.subplot(1,2,2)\n",
    "\n",
    "plt_xHII_DM,          = plt.plot(rs_vec_DM, xHII_DM, ':', linewidth=4, label='Dark Matter')\n",
    "plt_xHII_DM_BR,       = plt.plot(rs_vec_BR, xHII_DM_BR, ':', linewidth=4, label='DM+Backreaction')\n",
    "plt_xHII_reion,       = plt.plot(rs_vec, soln_default_reion[:,1], 'k--', label='Reionization')\n",
    "plt_xHII_DM_reion,    = plt.plot(rs_vec_DM, xHII_DM_reion, label=r'Reion.+DM')\n",
    "plt_xHII_DM_reion_BR, = plt.plot(rs_vec_DM_reion_BR, xHII_DM_reion_BR, label='Reion.+DM+Backreaction')\n",
    "\n",
    "# Text\n",
    "plt.text(0.37, 0.88, r'$\\chi \\to e^+e^-$, $m_\\chi$ = 100 MeV', fontsize=20, transform=ax.transAxes) \n",
    "plt.text(0.63, 0.82, r'$\\tau = 3 \\times 10^{25}$ s', fontsize=20, transform=ax.transAxes)\n",
    "\n",
    "leg = plt.legend(handles=[plt_xHII_DM, plt_xHII_DM_BR, plt_xHII_reion, plt_xHII_DM_reion, plt_xHII_DM_reion_BR], loc=(0.33, 0.43))\n",
    "\n",
    "plt.title(r'\\bf{Ionization History}')\n",
    "plt.xlabel('Redshift (1+z)')\n",
    "plt.ylabel(r'Ionization Fraction $x_\\mathrm{HII}$')\n",
    "plt.axis([4, 22, 0, 1.5])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bibliography"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[1]<a id='cite_rates1'></a> Ewald Puchwein, Francesco Haardt, Martin G. Haehnelt, and Piero Madau, “Consistent modelling of the meta-galactic UV background and the thermal/ionization history of the intergalactic medium,” (2018), arXiv:1801.04931 [astro-ph.GA]\n",
    "\n",
    "[2]<a id='cite_rates2'></a> James S. Bolton and Martin G. Haehnelt, “The nature and evolution of the highly ionized near-zones in the absorption spectra of z =6 quasars,” Mon. Not. Roy. Astron. Soc. 374, 493–514 (2007), arXiv:astro-ph/0607331 [astro-ph].\n",
    "\n",
    "[3]<a id='cite_rates3'></a> James S. Bolton and Martin G. Haehnelt, “The nature and evolution of the highly ionized near-zones in the absorption spectra of z =6 quasars,” Mon. Not. Roy. Astron. Soc. 374, 493–514 (2007), arXiv:astro-ph/0607331 [astro-ph].\n",
    "\n",
    "[4]<a id='cite_tanh'></a> Antony Lewis, “Cosmological parameters from WMAP 5-year temperature maps,” Phys. Rev. D78, 023002 (2008), arXiv:0804.3865 [astro-ph]."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "cite2c": {
   "citations": {
    "6232408/3KKTSI4D": {
     "DOI": "10.1103/PhysRevD.94.063507",
     "abstract": "Dark matter annihilation or decay could have a significant impact on the ionization and thermal history of the universe. In this paper, we study the potential contribution of dark matter annihilation (s-wave- or p-wave-dominated) or decay to cosmic reionization, via the production of electrons, positrons and photons. We map out the possible perturbations to the ionization and thermal histories of the universe due to dark matter processes, over a broad range of velocity-averaged annihilation cross sections/decay lifetimes and dark matter masses. We have employed recent numerical studies of the efficiency with which annihilation/decay products induce heating and ionization in the intergalactic medium, and in this work extended them down to a redshift of 1+z=4 for two different reionization scenarios. We also improve on earlier studies by using the results of detailed structure formation models of dark matter haloes and subhaloes that are consistent with up-to-date N-body simulations, with estimates on the uncertainties that originate from the smallest scales. We find that for dark matter models that are consistent with experimental constraints, a contribution of more than 10% to the ionization fraction at reionization is disallowed for all annihilation scenarios. Such a contribution is possible only for decays into electron/positron pairs, for light dark matter with mass mχ≲100  MeV, and a decay lifetime τχ∼1024–1025  s.",
     "author": [
      {
       "family": "Liu",
       "given": "Hongwan"
      },
      {
       "family": "Slatyer",
       "given": "Tracy R."
      },
      {
       "family": "Zavala",
       "given": "Jesús"
      }
     ],
     "container-title": "Phys.Rev.",
     "id": "6232408/3KKTSI4D",
     "issue": "6",
     "issued": {
      "day": 8,
      "month": 9,
      "year": 2016
     },
     "page": "063507",
     "page-first": "063507",
     "title": "Contributions to cosmic reionization from dark matter annihilation and decay",
     "type": "article-journal",
     "volume": "D94"
    },
    "6232408/4FF4XZAM": {
     "DOI": "10.1111/j.1365-2966.2006.11176.x",
     "abstract": "We use state-of-the-art hydrodynamical simulations combined with a 1D radiative transfer code to assess the extent to which the highly ionized regions observed close to z~6 quasars, which we refer to as near-zones, can constrain the ionization state of the surrounding IGM. We find the appearance in Lya absorption of a quasar HII ionization front expanding into a neutral IGM can be very similar to a classical proximity zone, produced by the enhancement in ionizing flux close to a quasar embedded in a highly ionized IGM. The observed sizes of these highly ionized near-zones and their redshift evolution can be reproduced for a wide range of IGM neutral hydrogen fractions for plausible values of the luminosity and lifetime of the quasars. The observed near-zone sizes at the highest observed redshifts are equally consistent with a significantly neutral and a highly ionized surrounding IGM. Stronger constraints on the IGM neutral hydrogen fraction can be obtained by considering the relative size of the near-zones in the Lya and Lyb regions of a quasar spectrum. A large sample of high quality quasar absorption spectra with accurate determinations of near-zone sizes and their redshift evolution in both the Lya and Lyb regions should confirm or exclude the possibility that the Universe is predominantly neutral at the highest observed redshifts. The width of the discrete absorption features in these near-zones will contain important additional information on the ionization state and the previous thermal history of the IGM at these redshifts.",
     "author": [
      {
       "family": "Bolton",
       "given": "James S."
      },
      {
       "family": "Haehnelt",
       "given": "Martin G."
      }
     ],
     "container-title": "Mon.Not.Roy.Astron.Soc.",
     "id": "6232408/4FF4XZAM",
     "issued": {
      "year": 2007
     },
     "page": "493-514",
     "page-first": "493",
     "title": "The nature and evolution of the highly ionized near-zones in the absorption spectra of z~=6 quasars",
     "type": "article-journal",
     "volume": "374"
    },
    "6232408/CEI8B32P": {
     "DOI": "10.1051/0004-6361/201628897",
     "URL": "https://www.aanda.org/articles/aa/abs/2016/12/aa28897-16/aa28897-16.html",
     "abstract": "We investigate constraints on cosmic reionization extracted from the <i>Planck<i/> cosmic microwave background (CMB) data. We combine the <i>Planck<i/> CMB anisotropy data in temperature with the low-multipole polarization data to fit ΛCDM models with various parameterizations of the reionization history. We obtain a Thomson optical depth <i>τ<i/> = 0.058 ± 0.012 for the commonly adopted instantaneous reionization model. This confirms, with data solely from CMB anisotropies, the low value suggested by combining <i>Planck<i/> 2015 results with other data sets, and also reduces the uncertainties. We reconstruct the history of the ionization fraction using either a symmetric or an asymmetric model for the transition between the neutral and ionized phases. To determine better constraints on the duration of the reionization process, we also make use of measurements of the amplitude of the kinetic Sunyaev-Zeldovich (kSZ) effect using additional information from the high-resolution Atacama Cosmology Telescope and South Pole Telescope experiments. The average redshift at which reionization occurs is found to lie between <i>z<i/> = 7.8 and 8.8, depending on the model of reionization adopted. Using kSZ constraints and a redshift-symmetric reionization model, we find an upper limit to the width of the reionization period of Δ<i>z<i/> < 2.8. In all cases, we find that the Universe is ionized at less than the 10% level at redshifts above <i>z<i/> ≃ 10. This suggests that an early onset of reionization is strongly disfavoured by the <i>Planck<i/> data. We show that this result also reduces the tension between CMB-based analyses and constraints from other astrophysical sources.",
     "accessed": {
      "day": 6,
      "month": 3,
      "year": 2019
     },
     "author": [
      {
       "family": "Adam",
       "given": "R."
      },
      {
       "family": "Aghanim",
       "given": "N."
      },
      {
       "family": "Ashdown",
       "given": "M."
      },
      {
       "family": "Aumont",
       "given": "J."
      },
      {
       "family": "Baccigalupi",
       "given": "C."
      },
      {
       "family": "Ballardini",
       "given": "M."
      },
      {
       "family": "Banday",
       "given": "A. J."
      },
      {
       "family": "Barreiro",
       "given": "R. B."
      },
      {
       "family": "Bartolo",
       "given": "N."
      },
      {
       "family": "Basak",
       "given": "S."
      },
      {
       "family": "Battye",
       "given": "R."
      },
      {
       "family": "Benabed",
       "given": "K."
      },
      {
       "family": "Bernard",
       "given": "J.-P."
      },
      {
       "family": "Bersanelli",
       "given": "M."
      },
      {
       "family": "Bielewicz",
       "given": "P."
      },
      {
       "family": "Bock",
       "given": "J. J."
      },
      {
       "family": "Bonaldi",
       "given": "A."
      },
      {
       "family": "Bonavera",
       "given": "L."
      },
      {
       "family": "Bond",
       "given": "J. R."
      },
      {
       "family": "Borrill",
       "given": "J."
      },
      {
       "family": "Bouchet",
       "given": "F. R."
      },
      {
       "family": "Boulanger",
       "given": "F."
      },
      {
       "family": "Bucher",
       "given": "M."
      },
      {
       "family": "Burigana",
       "given": "C."
      },
      {
       "family": "Calabrese",
       "given": "E."
      },
      {
       "family": "Cardoso",
       "given": "J.-F."
      },
      {
       "family": "Carron",
       "given": "J."
      },
      {
       "family": "Chiang",
       "given": "H. C."
      },
      {
       "family": "Colombo",
       "given": "L. P. L."
      },
      {
       "family": "Combet",
       "given": "C."
      },
      {
       "family": "Comis",
       "given": "B."
      },
      {
       "family": "Couchot",
       "given": "F."
      },
      {
       "family": "Coulais",
       "given": "A."
      },
      {
       "family": "Crill",
       "given": "B. P."
      },
      {
       "family": "Curto",
       "given": "A."
      },
      {
       "family": "Cuttaia",
       "given": "F."
      },
      {
       "family": "Davis",
       "given": "R. J."
      },
      {
       "family": "Bernardis",
       "given": "P. de"
      },
      {
       "family": "Rosa",
       "given": "A. de"
      },
      {
       "family": "Zotti",
       "given": "G. de"
      },
      {
       "family": "Delabrouille",
       "given": "J."
      },
      {
       "family": "Valentino",
       "given": "E. Di"
      },
      {
       "family": "Dickinson",
       "given": "C."
      },
      {
       "family": "Diego",
       "given": "J. M."
      },
      {
       "family": "Doré",
       "given": "O."
      },
      {
       "family": "Douspis",
       "given": "M."
      },
      {
       "family": "Ducout",
       "given": "A."
      },
      {
       "family": "Dupac",
       "given": "X."
      },
      {
       "family": "Elsner",
       "given": "F."
      },
      {
       "family": "Enßlin",
       "given": "T. A."
      },
      {
       "family": "Eriksen",
       "given": "H. K."
      },
      {
       "family": "Falgarone",
       "given": "E."
      },
      {
       "family": "Fantaye",
       "given": "Y."
      },
      {
       "family": "Finelli",
       "given": "F."
      },
      {
       "family": "Forastieri",
       "given": "F."
      },
      {
       "family": "Frailis",
       "given": "M."
      },
      {
       "family": "Fraisse",
       "given": "A. A."
      },
      {
       "family": "Franceschi",
       "given": "E."
      },
      {
       "family": "Frolov",
       "given": "A."
      },
      {
       "family": "Galeotta",
       "given": "S."
      },
      {
       "family": "Galli",
       "given": "S."
      },
      {
       "family": "Ganga",
       "given": "K."
      },
      {
       "family": "Génova-Santos",
       "given": "R. T."
      },
      {
       "family": "Gerbino",
       "given": "M."
      },
      {
       "family": "Ghosh",
       "given": "T."
      },
      {
       "family": "González-Nuevo",
       "given": "J."
      },
      {
       "family": "Górski",
       "given": "K. M."
      },
      {
       "family": "Gruppuso",
       "given": "A."
      },
      {
       "family": "Gudmundsson",
       "given": "J. E."
      },
      {
       "family": "Hansen",
       "given": "F. K."
      },
      {
       "family": "Helou",
       "given": "G."
      },
      {
       "family": "Henrot-Versillé",
       "given": "S."
      },
      {
       "family": "Herranz",
       "given": "D."
      },
      {
       "family": "Hivon",
       "given": "E."
      },
      {
       "family": "Huang",
       "given": "Z."
      },
      {
       "family": "Ilić",
       "given": "S."
      },
      {
       "family": "Jaffe",
       "given": "A. H."
      },
      {
       "family": "Jones",
       "given": "W. C."
      },
      {
       "family": "Keihänen",
       "given": "E."
      },
      {
       "family": "Keskitalo",
       "given": "R."
      },
      {
       "family": "Kisner",
       "given": "T. S."
      },
      {
       "family": "Knox",
       "given": "L."
      },
      {
       "family": "Krachmalnicoff",
       "given": "N."
      },
      {
       "family": "Kunz",
       "given": "M."
      },
      {
       "family": "Kurki-Suonio",
       "given": "H."
      },
      {
       "family": "Lagache",
       "given": "G."
      },
      {
       "family": "Lähteenmäki",
       "given": "A."
      },
      {
       "family": "Lamarre",
       "given": "J.-M."
      },
      {
       "family": "Langer",
       "given": "M."
      },
      {
       "family": "Lasenby",
       "given": "A."
      },
      {
       "family": "Lattanzi",
       "given": "M."
      },
      {
       "family": "Lawrence",
       "given": "C. R."
      },
      {
       "family": "Jeune",
       "given": "M. Le"
      },
      {
       "family": "Levrier",
       "given": "F."
      },
      {
       "family": "Lewis",
       "given": "A."
      },
      {
       "family": "Liguori",
       "given": "M."
      },
      {
       "family": "Lilje",
       "given": "P. B."
      },
      {
       "family": "López-Caniego",
       "given": "M."
      },
      {
       "family": "Ma",
       "given": "Y.-Z."
      },
      {
       "family": "Macías-Pérez",
       "given": "J. F."
      },
      {
       "family": "Maggio",
       "given": "G."
      },
      {
       "family": "Mangilli",
       "given": "A."
      },
      {
       "family": "Maris",
       "given": "M."
      },
      {
       "family": "Martin",
       "given": "P. G."
      },
      {
       "family": "Martínez-González",
       "given": "E."
      },
      {
       "family": "Matarrese",
       "given": "S."
      },
      {
       "family": "Mauri",
       "given": "N."
      },
      {
       "family": "McEwen",
       "given": "J. D."
      },
      {
       "family": "Meinhold",
       "given": "P. R."
      },
      {
       "family": "Melchiorri",
       "given": "A."
      },
      {
       "family": "Mennella",
       "given": "A."
      },
      {
       "family": "Migliaccio",
       "given": "M."
      },
      {
       "family": "Miville-Deschênes",
       "given": "M.-A."
      },
      {
       "family": "Molinari",
       "given": "D."
      },
      {
       "family": "Moneti",
       "given": "A."
      },
      {
       "family": "Montier",
       "given": "L."
      },
      {
       "family": "Morgante",
       "given": "G."
      },
      {
       "family": "Moss",
       "given": "A."
      },
      {
       "family": "Naselsky",
       "given": "P."
      },
      {
       "family": "Natoli",
       "given": "P."
      },
      {
       "family": "Oxborrow",
       "given": "C. A."
      },
      {
       "family": "Pagano",
       "given": "L."
      },
      {
       "family": "Paoletti",
       "given": "D."
      },
      {
       "family": "Partridge",
       "given": "B."
      },
      {
       "family": "Patanchon",
       "given": "G."
      },
      {
       "family": "Patrizii",
       "given": "L."
      },
      {
       "family": "Perdereau",
       "given": "O."
      },
      {
       "family": "Perotto",
       "given": "L."
      },
      {
       "family": "Pettorino",
       "given": "V."
      },
      {
       "family": "Piacentini",
       "given": "F."
      },
      {
       "family": "Plaszczynski",
       "given": "S."
      },
      {
       "family": "Polastri",
       "given": "L."
      },
      {
       "family": "Polenta",
       "given": "G."
      },
      {
       "family": "Puget",
       "given": "J.-L."
      },
      {
       "family": "Rachen",
       "given": "J. P."
      },
      {
       "family": "Racine",
       "given": "B."
      },
      {
       "family": "Reinecke",
       "given": "M."
      },
      {
       "family": "Remazeilles",
       "given": "M."
      },
      {
       "family": "Renzi",
       "given": "A."
      },
      {
       "family": "Rocha",
       "given": "G."
      },
      {
       "family": "Rossetti",
       "given": "M."
      },
      {
       "family": "Roudier",
       "given": "G."
      },
      {
       "family": "Rubiño-Martín",
       "given": "J. A."
      },
      {
       "family": "Ruiz-Granados",
       "given": "B."
      },
      {
       "family": "Salvati",
       "given": "L."
      },
      {
       "family": "Sandri",
       "given": "M."
      },
      {
       "family": "Savelainen",
       "given": "M."
      },
      {
       "family": "Scott",
       "given": "D."
      },
      {
       "family": "Sirri",
       "given": "G."
      },
      {
       "family": "Sunyaev",
       "given": "R."
      },
      {
       "family": "Suur-Uski",
       "given": "A.-S."
      },
      {
       "family": "Tauber",
       "given": "J. A."
      },
      {
       "family": "Tenti",
       "given": "M."
      },
      {
       "family": "Toffolatti",
       "given": "L."
      },
      {
       "family": "Tomasi",
       "given": "M."
      },
      {
       "family": "Tristram",
       "given": "M."
      },
      {
       "family": "Trombetti",
       "given": "T."
      },
      {
       "family": "Valiviita",
       "given": "J."
      },
      {
       "family": "Tent",
       "given": "F. Van"
      },
      {
       "family": "Vielva",
       "given": "P."
      },
      {
       "family": "Villa",
       "given": "F."
      },
      {
       "family": "Vittorio",
       "given": "N."
      },
      {
       "family": "Wandelt",
       "given": "B. D."
      },
      {
       "family": "Wehus",
       "given": "I. K."
      },
      {
       "family": "White",
       "given": "M."
      },
      {
       "family": "Zacchei",
       "given": "A."
      },
      {
       "family": "Zonca",
       "given": "A."
      }
     ],
     "container-title": "Astronomy & Astrophysics",
     "container-title-short": "A&A",
     "id": "6232408/CEI8B32P",
     "issued": {
      "day": 1,
      "month": 12,
      "year": 2016
     },
     "journalAbbreviation": "A&A",
     "language": "en",
     "page": "A108",
     "page-first": "A108",
     "title": "Planck intermediate results - XLVII. Planck constraints on reionization history",
     "type": "article-journal",
     "volume": "596"
    },
    "6232408/DVUAUQGP": {
     "DOI": "10.1086/149628",
     "author": [
      {
       "family": "Peebles",
       "given": "P. J. E."
      }
     ],
     "container-title": "Astrophys.J.",
     "id": "6232408/DVUAUQGP",
     "issued": {
      "year": 1968
     },
     "page": "1",
     "page-first": "1",
     "title": "Recombination of the Primeval Plasma",
     "type": "article-journal",
     "volume": "153"
    },
    "6232408/HNJVBBSZ": {
     "DOI": "10.1103/PhysRevD.83.043513",
     "abstract": "We present a state-of-the-art primordial recombination code, HyRec, including all the physical effects that have been shown to significantly affect recombination. The computation of helium recombination includes simple analytic treatments of hydrogen continuum opacity in the He I 2 1P - 1 1S line, the He I] 2 3P - 1 1S line, and treats feedback between these lines within the on-the-spot approximation. Hydrogen recombination is computed using the effective multilevel atom method, virtually accounting for an infinite number of excited states. We account for two-photon transitions from 2s and higher levels as well as frequency diffusion in Lyman-alpha with a full radiative transfer calculation. We present a new method to evolve the radiation field simultaneously with the level populations and the free electron fraction. These computations are sped up by taking advantage of the particular sparseness pattern of the equations describing the radiative transfer. The computation time for a full recombination history is ~2 seconds. This makes our code well suited for inclusion in Monte Carlo Markov chains for cosmological parameter estimation from upcoming high-precision cosmic microwave background anisotropy measurements.",
     "author": [
      {
       "family": "Ali-Haimoud",
       "given": "Yacine"
      },
      {
       "family": "Hirata",
       "given": "Christopher M."
      }
     ],
     "container-title": "Phys.Rev.",
     "id": "6232408/HNJVBBSZ",
     "issued": {
      "year": 2011
     },
     "page": "043513",
     "page-first": "043513",
     "shortTitle": "HyRec",
     "title": "HyRec: A fast and highly accurate primordial hydrogen and helium recombination code",
     "title-short": "HyRec",
     "type": "article-journal",
     "volume": "D83"
    },
    "6232408/MJ7LY7BF": {
     "abstract": "Recent observations suggest that hydrogen reionization ends late ($z \\simeq 6$) and proceeds quickly. We present here a new model of the meta-galactic UV/X-ray background (UVB) that is consistent with this. It adopts the most recent determinations of the ionizing emissivity due to stars and AGN, as well as of the HI absorber column density distribution. Another major improvement is a new treatment of the intergalactic medium (IGM) opacity for ionizing photons that is able to consistently capture the transition from a neutral to an ionized IGM. Previous synthesis models of the UVB, when used in simulations, yield reionization and thermal histories that are inconsistent with the assumed ionizing emissivities. With our new treatment, this discrepancy is fully resolved. In our fiducial model, galaxies leaking $\\lesssim 18\\%$ of their Lyman continuum emission drive HI reionization, while AGN drive HeII reionization (completing at $z \\simeq 6.2$ and $2.8$ respectively). Due to the limited time available for cooling between HI and HeII reionization, higher IGM temperatures are predicted for late reionization scenarios. In our fiducial model, the predicted temperatures agree well with observational constraints at $z \\lesssim 4$, while being slightly high compared to (somewhat uncertain) data above that. Models with a larger contribution of AGN are instead disfavoured by the temperature data, as well as by measurements of the HI and HeII Lyman-$\\alpha$ forest opacities. We also present \"equivalent-equilibrium\" ionization/heating rates that mimic our fiducial UVB model for use in simulation codes that assume ionization equilibrium.",
     "author": [
      {
       "family": "Puchwein",
       "given": "Ewald"
      },
      {
       "family": "Haardt",
       "given": "Francesco"
      },
      {
       "family": "Haehnelt",
       "given": "Martin G."
      },
      {
       "family": "Madau",
       "given": "Piero"
      }
     ],
     "id": "6232408/MJ7LY7BF",
     "issued": {
      "year": 2018
     },
     "title": "Consistent modelling of the meta-galactic UV background and the thermal/ionization history of the intergalactic medium",
     "type": "article-journal"
    },
    "6232408/QRY4E9Y7": {
     "DOI": "10.1088/0004-637X/746/2/125",
     "abstract": "We present improved synthesis models of the evolving spectrum of the UV/X-ray diffuse background, updating and extending our previous results. Five new main components are added to our radiative transfer code CUBA: (1) the sawtooth modulation of the background intensity from resonant line absorption in the Lyman series of cosmic hydrogen and helium; (2) the X-ray emission from obscured and unobscured quasars; (3) a piecewise parameterization of the distribution in redshift and column density of intergalactic absorbers that fits recent measurements of the mean free path of 1 ryd photons; (4) an accurate treatment of the photoionization structure of absorbers; and (5) the UV emission from star-forming galaxies at all redshifts. We provide tables of the predicted HI and HeII photoionization and photoheating rates for use, e.g., in cosmological hydrodynamics simulations of the Lya forest, and a new metallicity-dependent calibration to the UV luminosity density-star formation rate density relation. A \"minimal cosmic reionization model\" is also presented in which the galaxy UV emissivity traces recent determinations of the cosmic history of star formation, the luminosity-weighted escape fraction of hydrogen-ionizing radiation increases rapidly with lookback time, the clumping factor of the high-redshift intergalactic medium evolves following the results of recent hydrodynamic simulations, and Population III stars and miniquasars make a negligible contribution to the metagalactic flux. The model provides a good fit to the hydrogen-ionization rates inferred from flux decrement and proximity effect measurements, predicts that cosmological HII (HeIII) regions overlap at redshift 6.7 (2.8), and yields an optical depth to Thomson scattering that is in agreement with WMAP results. (Abridged)",
     "author": [
      {
       "family": "Haardt",
       "given": "Francesco"
      },
      {
       "family": "Madau",
       "given": "Piero"
      }
     ],
     "container-title": "Astrophys.J.",
     "id": "6232408/QRY4E9Y7",
     "issued": {
      "year": 2012
     },
     "page": "125",
     "page-first": "125",
     "shortTitle": "Radiative transfer in a clumpy universe",
     "title": "Radiative transfer in a clumpy universe: IV. New synthesis models of the cosmic UV/X-ray background",
     "title-short": "Radiative transfer in a clumpy universe",
     "type": "article-journal",
     "volume": "746"
    },
    "6232408/S55R7ACJ": {
     "DOI": "10.1103/PhysRevD.93.023521",
     "abstract": "Any injection of electromagnetically interacting particles during the cosmic dark ages will lead to increased ionization, heating, production of Lyman-α photons and distortions to the energy spectrum of the cosmic microwave background, with potentially observable consequences. In this paper we describe numerical results for the low-energy electrons and photons produced by the cooling of particles injected at energies from keV to multi-TeV scales, at arbitrary injection redshifts (but focusing on the post-recombination epoch). We use these data, combined with existing calculations modeling the cooling of these low-energy particles, to estimate the resulting contributions to ionization, excitation and heating of the gas, and production of low-energy photons below the threshold for excitation and ionization. We compute corrected deposition-efficiency curves for annihilating dark matter, and demonstrate how to compute equivalent curves for arbitrary energy-injection histories. These calculations provide the necessary inputs for the limits on dark matter annihilation presented in the accompanying paper I, but also have potential applications in the context of dark matter decay or deexcitation, decay of other metastable species, or similar energy injections from new physics. We make our full results publicly available at http://nebel.rc.fas.harvard.edu/epsilon, to facilitate further independent studies. In particular, we provide the full low-energy electron and photon spectra, to allow matching onto more detailed codes that describe the cooling of such particles at low energies.",
     "author": [
      {
       "family": "Slatyer",
       "given": "Tracy R."
      }
     ],
     "container-title": "Phys.Rev.",
     "id": "6232408/S55R7ACJ",
     "issue": "2",
     "issued": {
      "day": 25,
      "month": 1,
      "year": 2016
     },
     "page": "023521",
     "page-first": "023521",
     "title": "Indirect Dark Matter Signatures in the Cosmic Dark Ages II. Ionization, Heating and Photon Production from Arbitrary Energy Injections",
     "type": "article-journal",
     "volume": "D93"
    },
    "6232408/SPGPKD33": {
     "DOI": "10.1103/PhysRevD.88.063502",
     "abstract": "Anisotropies of the cosmic microwave background (CMB) have proven to be a very powerful tool to constrain dark matter annihilation at the epoch of recombination. However, CMB constraints are currently derived using a number of reasonable but yet untested assumptions that could potentially lead to a misestimation of the true bounds (or any reconstructed signal). In this paper we examine the potential impact of these systematic effects. In particular, we separately study the propagation of the secondary particles produced by annihilation in two energy regimes: first following the shower from the initial particle energy to the keV scale, and then tracking the resulting secondary particles from this scale to the absorption of their energy as heat, ionization, or excitation of the medium. We improve both the high- and low-energy parts of the calculation, in particular finding that our more accurate treatment of losses to sub-10.2 eV photons produced by scattering of high-energy electrons weakens the constraints on particular dark matter annihilation models by up to a factor of 2. On the other hand, we find that the uncertainties we examine for the low-energy propagation do not significantly affect the results for current and upcoming CMB data. We include the evaluation of the precise amount of excitation energy, in the form of Lyman-α photons, produced by the propagation of the shower, and examine the effects of varying the helium fraction and helium ionization fraction. In the recent literature, simple approximations for the fraction of energy absorbed in different channels have often been used to derive CMB constraints: we assess the impact of using accurate vs approximate energy fractions. Finally we check that the choice of recombination code (between RECFAST v1.5 and COSMOREC), to calculate the evolution of the free electron fraction in the presence of dark matter annihilation, introduces negligible differences.",
     "author": [
      {
       "family": "Galli",
       "given": "Silvia"
      },
      {
       "family": "Slatyer",
       "given": "Tracy R."
      },
      {
       "family": "Valdes",
       "given": "Marcos"
      },
      {
       "family": "Iocco",
       "given": "Fabio"
      }
     ],
     "container-title": "Phys.Rev.",
     "id": "6232408/SPGPKD33",
     "issued": {
      "year": 2013
     },
     "page": "063502",
     "page-first": "063502",
     "title": "Systematic Uncertainties In Constraining Dark Matter Annihilation From The Cosmic Microwave Background",
     "type": "article-journal",
     "volume": "D88"
    },
    "6232408/VKMX8MFJ": {
     "DOI": "10.1103/PhysRevD.95.023010",
     "abstract": "Precise measurements of the temperature and polarization anisotropies of the cosmic microwave background can be used to constrain the annihilation and decay of dark matter. In this work, we demonstrate via principal component analysis that the imprint of dark matter decay on the cosmic microwave background can be approximately parametrized by a single number for any given dark matter model. We develop a simple prescription for computing this model-dependent detectability factor, and demonstrate how this approach can be used to set model-independent bounds on a large class of decaying dark matter scenarios. We repeat our analysis for decay lifetimes shorter than the age of the Universe, allowing us to set constraints on metastable species other than the dark matter decaying at early times, and decays that only liberate a tiny fraction of the dark matter mass energy. We set precise bounds and validate our principal component analysis using a Markov chain Monte Carlo approach and Planck 2015 data.",
     "author": [
      {
       "family": "Slatyer",
       "given": "Tracy R."
      },
      {
       "family": "Wu",
       "given": "Chih-Liang"
      }
     ],
     "container-title": "Phys.Rev.",
     "id": "6232408/VKMX8MFJ",
     "issue": "2",
     "issued": {
      "day": 30,
      "month": 1,
      "year": 2017
     },
     "page": "023010",
     "page-first": "023010",
     "title": "General Constraints on Dark Matter Decay from the Cosmic Microwave Background",
     "type": "article-journal",
     "volume": "D95"
    },
    "6232408/VV5Y8E88": {
     "author": [
      {
       "family": "Zeldovich",
       "given": "Ya B."
      },
      {
       "family": "Kurt",
       "given": "V. G."
      },
      {
       "family": "Sunyaev",
       "given": "R. A."
      }
     ],
     "container-title": "Sov.Phys.JETP",
     "id": "6232408/VV5Y8E88",
     "issued": {
      "year": 1969
     },
     "page": "146",
     "page-first": "146",
     "title": "Recombination of hydrogen in the hot model of the universe",
     "type": "article-journal",
     "volume": "28"
    },
    "6232408/XNS48NT3": {
     "DOI": "10.1103/PhysRevD.78.023002",
     "URL": "https://link.aps.org/doi/10.1103/PhysRevD.78.023002",
     "abstract": "I calculate a hybrid cross-power spectrum estimator from the WMAP 5-year CMB temperature maps, discuss the goodness of fit, and then constrain cosmological parameters. The spectrum and results are generally consistent with previous results, though the power spectrum error bars are slightly smaller and there are small shifts at high l. The small improvement in error bars is obtained at very low numerical cost but does not significantly improve parameter constraints. I discuss the accuracy of the likelihood model and how constraints on the optical depth translate into constraints on the reionization history allowing for helium reionization. In the appendices I propose a simple reionization parametrization that determines the history in terms of a midpoint reionization redshift, and suggest a new likelihood approximation for chi-squared-like distributions with varying skewness.",
     "accessed": {
      "day": 6,
      "month": 3,
      "year": 2019
     },
     "author": [
      {
       "family": "Lewis",
       "given": "Antony"
      }
     ],
     "container-title": "Physical Review D",
     "container-title-short": "Phys. Rev. D",
     "id": "6232408/XNS48NT3",
     "issue": "2",
     "issued": {
      "day": 2,
      "month": 7,
      "year": 2008
     },
     "journalAbbreviation": "Phys. Rev. D",
     "page": "023002",
     "page-first": "023002",
     "title": "Cosmological parameters from WMAP 5-year temperature maps",
     "type": "article-journal",
     "volume": "78"
    }
   }
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
