\documentclass[fleqn, usenatbib, useAMS, a4paper]{mnras} \usepackage{graphicx} \usepackage{amsmath,paralist,xcolor,xspace,amssymb} \usepackage{times} \usepackage{comment} \usepackage[super]{nth} \newcommand{\todo}[1]{{\textcolor{red}{TODO: #1}\\}} \newcommand{\swift}{{\sc Swift}\xspace} \newcommand{\D}[2]{\frac{d#1}{d#2}} \newcommand{\LL}{\left(} \newcommand{\RR}{\right)} \title{Integration scheme for cooling} \author{Alexei Borissov, Matthieu Schaller} \begin{document} \maketitle %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Basic principles} \subsection{Isochoric cooling} \todo{MATTHIEU: Discuss the fact that we want to do cooling at constant density.} \subsection{Time integration} We want to compute the change in internal energy of a given particle due to the interaction of the gas with the background radiation. More specifically we want to integrate the following equation: \begin{equation} u_{\rm final} \equiv u(t+\Delta t) = u(t) + \left(\frac{\partial u}{\partial t}\bigg|_{\rm hydro} + \frac{\partial u}{\partial t}\bigg|_{\rm cooling}\right) \times \Delta t. \end{equation} The first derivative is given by the SPH scheme, the second one is what we are after here. We start by computing the internal energy the particle would have in the absence of cooling: \begin{equation} u_0 \equiv u(t) + \frac{\partial u}{\partial t}\bigg|_{\rm hydro} \times \Delta t. \end{equation} We then proceed to solve the implicit equation \begin{equation}\label{implicit-eq} u_{\rm final} = u_0 + \lambda(u_{\rm final}) \Delta t, \end{equation} where $\lambda$ is the cooling rate\footnote{Note this is not the physical cooling rate $\Lambda/n_{\rm H}^2$ that is commonly used. This is the change in energy over time $\frac{\partial u}{\partial t}\big|_{\rm cool}$ from all the channels including all the multiplicative factors coming in front of the physical $\Lambda$.}, which for a given particle varies only with respect to $u$ throughout the duration of the timestep. The other dependencies of $\lambda$ (density, metallicity and redshift) are kept constant over the course of $\Delta t$. Crucially, we want to evaluate $\lambda$ at the end of the time-step. Once a solution to this implicit problem has been found, we get the total cooling rate: \begin{equation} \frac{\partial u}{\partial t}\bigg|_{\rm total} \equiv \frac{u_{\rm final} - u(t)}{\Delta t}, \end{equation} leading to the following total equation of motion for internal energy: \begin{equation} u(t+\Delta t) = u(t) + \frac{\partial u}{\partial t}\bigg|_{\rm total} \times \Delta t. \end{equation} The time integration is then performed in the regular time integration section of the code. Note that, as expected, if $\lambda=0$ the whole processes reduces to a normal hydro-dynamics only time integration of the internal energy. Finally, for schemes evolving entropy $A$ instead of internal energy $u$ (or for that matter any other thermodynamic quantity), we convert the entropy derivative coming from the hydro scheme to an internal energy derivative, solve the implicit cooling problem using internal energies and convert the total time derivative back to an entropy derivative. Since we already assume that cooling is performed at constant density, there is no loss in accuracy happening via this conversion procedure. \subsubsection{Energy floor and prediction step} In most applications, the cooling is not allowed to bring the internal energy below a certain value $u_{\rm min}$, usually expressed in the form of a minimal temperature. Additionally, and even in the absence of such a temperature floor, we must ensure that the energy does not become negative. Since the time-step size is not chosen in a way to fulfil these criteria, we have to limit the total rate of change of energy such that the limits are not reached. In practice this means modifying $\frac{\partial u}{\partial t}\big|_{\rm total}$ such that \begin{equation} u(t) + \frac{\partial u}{\partial t}\bigg|_{\rm total} \times \Delta t \geq u_{\rm min} \end{equation} is true. In the vast majority of cases, there is no need to modify the energy derivative but this may be necessary for some rapidly cooling particles. The time integration uses a leapfrog algorithm in its ``Kick-Drift-Kick'' form. In the cases, where the time-step is constant, the condition as written above would be sufficient, however with variable $\Delta t$ this needs modifying. If the next time-step of a particle decreases in size, then the condition above will remain true. However, if the time-step size increases then we may violate the condition and integrate the energy to a value below $u_{\rm min}$. The time-step size is chosen in-between the application of the two kick operators\footnote{Effectively creating the chain ``Kick-Drift-Kick-Timestep'', where the last operation fixes the time-step size for the next kick-drift-kick cycle.}. We hence have to ensure that the integration of one half of the current step (the second kick) and one half of the next step (the first kick) does not lead to a value below the allowed minimum. In \swift, we do not allow the time-step to increase by more than a factor of $2$. This implies that we will at most integrate the internal energy forward in time for $1.5\Delta t$, where $\Delta t$ is the current value of the time-step size we used in all the equations thus far. An additional subtlety does, however, enter the scheme. The internal energy is not just used in the Kick operator. Because of the needs of the SPH scheme, the particles have to carry an estimate of the entropy at various points in time inside the step of this particle. This is especially important for inactive particles that act as sources for neighbouring active particles. We must hence not only protect for the next half-kick, we must also ensure that the value we estimated will be valid over the next drift step as well. This means completing the current half-kick and the next full drift, which could in principle double in size; this implies checking the limits over the next $2.5\Delta t$. However, for that variable, since it is an extrapolation and not the actual variable we integrate forward in time, we do not need to enforce the $u_{\rm min}$ limit. We must only ensure that the energy remains positive. Combining those two conditions, we conclude that we must enforce two limits: \begin{equation} \left\lbrace \begin{array}{ll} \displaystyle\frac{\partial u}{\partial t}\bigg|_{\rm total} \geq -\displaystyle\frac{u(t) - u_{\rm min} }{1.5 \Delta t}, \Bigg. \\ \displaystyle\frac{\partial u}{\partial t}\bigg|_{\rm total} \geq -\displaystyle\frac{u(t) - u_{\rm min} }{(2.5 + \epsilon) \Delta t}, \end{array} \right. \end{equation} where in the second equation we added a small value $\epsilon$ to ensure that we will not get negative values because of rounding errors. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Solution to the implicit cooling problem} In this section we describe the integration scheme used to compute the cooling rate. It consists of an explicit solver for cases where the cooling rate is small, a solver based on the Newton-Raphson method, and one based on the bisection method. \subsection{Explicit solver} For many particles the cooling occuring over a timestep will be small (for example, if a particle is at the equilibrium temperature and was not heated by other means such as shock heating). In these cases $\lambda(u_0) \simeq \lambda(u_{final})$, so an explicit solution to compute $u_{final}$ may be used as a faster alternative to a more complicated implicit scheme. More specifically, if $\lambda(u_0) dt < \varepsilon u_0$ we set \begin{equation} u_{final} = u_0 + \lambda(u_0) dt, \end{equation} where $\varepsilon$ is a small constant, set to $0.05$ to be consistent with the EAGLE simulations. In cases where $\lambda(u_0) dt > \varepsilon u_0$ one of two implicit methods are used, either the Newton-Raphson method, which benefits from faster convergence, however is not guaranteed to converge, or the bisection method, which is slower but always converges. \subsection{Newton-Raphson method} Equation \ref{implicit-eq} may be rearranged so that we are trying to find the root of \begin{equation}\label{fu-eq} f(u_{final}) = u_{final} - u_0 - \lambda(u_{final}) dt = 0. \end{equation} This may be done iteratively using the Newton-Raphson method obtaining consecutive approximations to $u_{final}$ by \begin{equation} u_{n+1} = u_n - \frac{f(u_n)}{df(u_n)/du}. \end{equation} In some cases a negative value of $u_{n+1}$ may be calculated. To prevent the occurance of negative internal energies during the calculation we introduce $x = \log (u_{final})$, so that we solve \begin{equation}\label{fx-eq} f(x) = e^x - u_0 - \lambda(e^x) dt = 0 \end{equation} instead of \ref{fu-eq}. Thus we obtain consecutive approximations of the root of $f$ by the formula $x_{n+1} = x_n - f(x_n)/f'(x_n)$. This leads to \begin{equation} x_{n+1} = x_n - \frac{1 - u_0 e^{-x_n} -\lambda(e^{x_n})e^{-x_n}dt}{1 - \frac{d\lambda}{du}(e^{x_n}) dt}. \end{equation} The tables used for EAGLE cooling in fact depend on temperature rather than internal energy and include a separate table to convert from internal energy to temperature. Hence, to obtain the gradient we use \begin{align*} \D \lambda u &= \D \lambda T \D T u \\ &= \frac{\lambda(T_{high,n}) - \lambda(T_{low,n})}{T_{high,n} - T_{low,n}} \frac{T(u_{high,n}) - T(u_{low,n})}{u_{high,n} - u_{low,n}}, \end{align*} where $T_{\rm high,n}, u_{\rm high,n}$ and $T_{\rm low,n}, u_{\rm low,n}$ are values of the temperature and internal energy grid bracketing the current temperature and internal energy for the iteration in Newton's method (e.g. $u_{high,n} \ge u_n \ge u_{low,n}$). The initial guess for the Newton-Raphson method is taken to be $x_0 = \log(u_0)$. If in the first iteration the sign of the $\lambda$ changes the next guess to correspond to the equilibrium temperature (i.e. $10^4$K). A particle is considered to have converged if the relative error in the internal energy is sufficiently small. This can be formulated as \begin{align*} \frac{u_{n+1} - u_n}{u_{n+1}} &< C \\ u_{n+1} - u_n &< Cu_{n+1} \\ \LL 1-C\RR u_{n+1} &< u_n \\ \frac{u_{n+1}}{u_n} &< \frac{1}{1-C} \\ x_{n+1} - x_n = \log\frac{u_{n+1}}{u_n} &< -\log\LL 1-C \RR \simeq C. \end{align*} Since the grid spacing in the internal energy of the Eagle tables is 0.045 in $\log_{10}u$ we take $C = 10^{-2}$. In cases when the Newton-Raphson method doesn't converge within a specified number of iterations we revert to the bisection method. In order to use the Newton-Raphson method a parameter (EagleCooling:newton\_integration) in the yaml file needs to be set to 1. \subsection{Bisection method} In order to guarantee convergence the bisection method is used to solve equation \ref{fu-eq} The implementation is the same as in the EAGLE simulations, but is described here for convenience. First a small interval is used to bracket the solution. The interval bounds are defined as $u_{upper} = \kappa u_0$ and $u_{lower} = \kappa^{-1} u_0$, with $\kappa = \sqrt{1.1}$ as specified in EAGLE. If the particle is cooling ($\lambda(u_0) < 0$) $u_{upper}$ and $u_{lower}$ are iteratively decreased by factors of $\kappa$ until $f(u_{lower}) < 0$. Alternatively, if the particle is initially heating ($\lambda(u_0) > 0$) the bounds are iteratively increased by factors of $\kappa$ until $f(u_{upper}) > 0$. Once the bounds are obtained, the bisection scheme is performed as normal. \section{EAGLE cooling tables} We use the same cooling tables as used in EAGLE, specifically those found in \cite{Wiersma2009} and may be found at http://www.strw.leidenuniv.nl/WSS08/. These tables contain pre-computed values of the cooling rate for a given redshift, metallicity, hydrogen number density and temperature produced using the package CLOUDY. When calculating the cooling rate for particles at redshifts higher than the redshift of reionisation the tables used do not depend on redshift, but only on metallicity, hydrogen number density and temperature. These tables are linearly interpolated based on the particle based on the particle properties. Since these tables specify the cooling rate in terms of temperature, the internal energy of a particle needs to be converted to a temperature in a way which takes into account the ionisation state of the gas. This is done by interpolating a pre-computed table of values of temperature depending on redshift, hydrogen number density, helium fraction and internal energy (again, for redshifts higher than the redshift of reionisation this table does not depend on redshift). Inverse Compton cooling is not accounted for in the high redshift tables, so prior to reionisation it is taken care of by an analytical formula, \begin{equation} \frac{\Lambda_{compton}}{n_h^2} = -\Lambda_{0,compton} \left( T - T_{CMB}(1+z) \right) (1+z)^4 \frac{n_e}{n_h}, \end{equation} which is added to the cooling rate interpolated from the tables. Here $n_h$ is the hydrogen number density, $T$ the temperature of the particle, $T_{CMB} = 2.7255$K the temperature of the CMB, $z$ the redshift, $n_e$ the hydrogen and helium electron number density, and $\Lambda_{0,compton} = 1.0178085 \times 10^{-37} g \cdot cm^2 \cdot s^{-3} \cdot K^{-5}$. \section{Co-moving time integration} In the case of cosmological simulations, the equations need to be slightly modified to take into account the expansion of the Universe. The code uses the comoving internal energy $u' = a(t)^{3(\gamma-1)}u$ or comoving entropy $A'=A$ as thermodynamic variable. The equation of motion for the variable are then modified and take the following form: \begin{equation} \frac{\partial u'_i}{\partial t} = \frac{\partial u'_i}{\partial t}\bigg|_{\rm hydro} = \frac{1}{a(t)^2} Y'_i(t)\big|_{\rm hydro}, \end{equation} where $Y_i$ is computed from the particle itself and its neighbours and corresponds to the change in internal energy due to hydrodynamic forces. We then integrate the internal energy forward in time using \begin{equation} u'_i(t+\Delta t) = u'_i(t) + Y'_i(t)\big|_{\rm hydro} \times \underbrace{\int_t^{t+\Delta t} \frac{1}{a(t)^2} dt}_{\Delta t_{\rm therm}}. \end{equation} The exact same equations apply in the case of a hydrodynamics scheme evolving entropy (see cosmology document). We note that this is different from the choice made in Gadget where there is no $a^{-2}$ term as it is absorbed in the definition in $Y'_i$ itself. As a consequence $\Delta t_{\rm therm}$ is just $\Delta t$. In order to compute the cooling rate of a particle, we convert quantities to physcial coordinates. Given the appearence of scale-factors in some of these equations, we have to be careful to remain consistent throughout. We start by constructing the co-moving internal energy at the end of the time-step in the absence of cooling: \begin{equation} u'_0 \equiv u'(t) + Y'_i(t)\big|_{\rm hydro} \times \Delta t_{\rm therm}, \end{equation} which we then convert into a physical internal energy alongside the thermal energy at the current time: \begin{align} u(t) &= a^{3(1-\gamma)}u'(t),\\ u_0 &= a^{3(1-\gamma)}u'_0. \end{align} We can then solve the implicit cooling problem in the same way as in the non-comoving case and obtain \begin{equation} u_{\rm final} = u_0 + \lambda(u_{\rm final}) \Delta t. \end{equation} We note that the $\Delta t$ here is the actual time between the start and end of the step; unlike $\Delta t_{\rm therm}$ there are no scale-factors entering that term. The solution to the implicit problem in physical coordinates yields the definition of the total time derivative of internal energy: \begin{equation} \frac{\partial u}{\partial t}\bigg|_{\rm total} \equiv \frac{u_{\rm final} - u(t)}{\Delta t}. \end{equation} This allows us to construct the total eveolution of co-moving energy: \begin{equation} Y'_i(t)\big|_{\rm total} = a^{3(\gamma-1)} \times \frac{\Delta t}{\Delta t_{\rm therm}} \times \frac{\partial u}{\partial t}\bigg|_{\rm total}, \end{equation} where the first term is is the conversion from physical to co-moving internal energy and the second term is required by our definition of our time integration opertator. The time integration routine then performs the same calculation as in the non-cooling case: \begin{equation} u'_i(t+\Delta t) = u'_i(t) + Y'_i(t)\big|_{\rm total} \times {\Delta t_{\rm therm}}. \end{equation} \bibliographystyle{mnras} \bibliography{./bibliography.bib} \end{document}