Source code for profiles.temperature

"""Temperature profiles for use in Pisces models.

The :mod:`~profiles.temperature` module provides a number of built-in profiles to model density and surface density
profiles in various contexts, including for galaxies, clusters of galaxies, stars, etc.
"""

from abc import ABC
from typing import Any

import unyt

from .base import BaseSphericalRadialProfile


[docs] class BaseSphericalTemperatureProfile(BaseSphericalRadialProfile, ABC): """Base class for spherical temperature profiles. This class provides a foundation for implementing various temperature profiles in spherical coordinates. It inherits from `BaseSphericalRadialProfile` and defines the basic structure and methods for temperature profiles. """ # @@ CLASS ATTRIBUTES (INVARIANT) @@ # _IS_ABC = True # @@ CLASS ATTRIBUTES @@ # AXES: list[str] = ["r"] DEFAULT_PARAMETERS: dict[str, Any] = {}
[docs] class IsothermalTemperatureProfile(BaseSphericalTemperatureProfile): r"""Isothermal Temperature Profile. A constant-temperature profile often used as a first approximation in galaxy and cluster modeling. .. math:: T(r) = T_0 where :math:`T_0` is a uniform temperature. .. dropdown:: Parameters .. list-table:: :widths: 25 25 50 :header-rows: 1 * - **Name** - **Symbol** - **Description** * - ``T_0`` - :math:`T_0` - Constant temperature Example ------- .. plot:: >>> from pisces.profiles.temperature import ( ... IsothermalTemperatureProfile, ... ) >>> import matplotlib.pyplot as plt >>> r = np.linspace(0, 10, 100) >>> profile = IsothermalTemperatureProfile( ... T_0=1e7 * unyt.Unit("K") ... ) >>> T = profile(r) >>> plt.plot(r, T) >>> plt.xlabel("r [kpc]") >>> plt.ylabel("Temperature [K]") >>> plt.grid() >>> plt.show() """ __IS_ABSTRACT__ = False __VARIABLES__ = ["r"] __VARIABLES_LATEX__ = [r"r"] __PARAMETERS__ = { "T_0": unyt.unyt_quantity(1e7, "K"), } @classmethod def __function__(cls, r, T_0=1e7): return T_0 @classmethod def __function_units__(cls, r, T_0=unyt.unyt_quantity(1, "K"), **kwargs): return T_0.units
[docs] class BetaModelTemperatureProfile(BaseSphericalTemperatureProfile): r"""Beta Model Temperature Profile. This profile models the temperature decline using a single β-model, widely used in galaxy clusters and X-ray gas distributions. .. math:: T(r) = T_0 \left(1 + \left(\frac{r}{r_c}\right)^2\right)^{-\beta} .. dropdown:: Parameters .. list-table:: :widths: 25 25 50 :header-rows: 1 * - **Name** - **Symbol** - **Description** * - ``T_0`` - :math:`T_0` - Central temperature * - ``r_c`` - :math:`r_c` - Core radius * - ``beta`` - :math:`\beta` - Slope parameter """ __IS_ABSTRACT__ = False __VARIABLES__ = ["r"] __VARIABLES_LATEX__ = [r"r"] __PARAMETERS__ = { "T_0": unyt.unyt_quantity(5.0, "keV"), "r_c": unyt.unyt_quantity(500.0, "kpc"), "beta": unyt.unyt_quantity(0.7, ""), } @classmethod def __function__(cls, r, T_0, r_c, beta): return T_0 * (1 + (r / r_c) ** 2) ** (-beta) @classmethod def __function_units__(cls, r, T_0, **kwargs): return T_0.units
[docs] class DoubleBetaTemperatureProfile(BaseSphericalTemperatureProfile): r"""Double Beta Temperature Profile. This model combines two β-components to describe systems with two distinct thermal structures. .. math:: T(r) = T_0 \left(1 + \left(\frac{r}{r_c}\right)^2\right)^{-\beta_1} + T_1 \left(1 + \left(\frac{r}{r_c}\right)^2\right)^{-\beta_2} .. dropdown:: Parameters .. list-table:: :widths: 25 25 50 :header-rows: 1 * - **Name** - **Symbol** - **Description** * - ``T_0`` - :math:`T_0` - Temperature of first component * - ``T_1`` - :math:`T_1` - Temperature of second component * - ``r_c`` - :math:`r_c` - Core radius (shared) * - ``beta_1`` - :math:`\beta_1` - Slope of first component * - ``beta_2`` - :math:`\beta_2` - Slope of second component """ __IS_ABSTRACT__ = False __VARIABLES__ = ["r"] __VARIABLES_LATEX__ = [r"r"] __PARAMETERS__ = { "T_0": unyt.unyt_quantity(5.0, "keV"), "T_1": unyt.unyt_quantity(3.0, "keV"), "r_c": unyt.unyt_quantity(500.0, "kpc"), "beta_1": unyt.unyt_quantity(0.7, ""), "beta_2": unyt.unyt_quantity(1.0, ""), } @classmethod def __function__(cls, r, T_0, T_1, r_c, beta_1, beta_2): return T_0 * (1 + (r / r_c) ** 2) ** (-beta_1) + T_1 * (1 + (r / r_c) ** 2) ** (-beta_2) @classmethod def __function_units__(cls, r, T_0, **kwargs): return T_0.units
[docs] class CoolingFlowTemperatureProfile(BaseSphericalTemperatureProfile): r"""Cooling Flow Temperature Profile. A power-law model for cooling flows in cluster cores. .. math:: T(r) = T_0 \left( \frac{r}{r_c} \right)^{-a} .. dropdown:: Parameters .. list-table:: :widths: 25 25 50 :header-rows: 1 * - **Name** - **Symbol** - **Description** * - ``T_0`` - :math:`T_0` - Central temperature * - ``r_c`` - :math:`r_c` - Core radius * - ``a`` - :math:`a` - Power-law slope """ __IS_ABSTRACT__ = False __VARIABLES__ = ["r"] __VARIABLES_LATEX__ = [r"r"] __PARAMETERS__ = { "T_0": unyt.unyt_quantity(5.0, "keV"), "r_c": unyt.unyt_quantity(100.0, "kpc"), "a": unyt.unyt_quantity(0.8, ""), } @classmethod def __function__(cls, r, T_0, r_c, a): return T_0 * (r / r_c) ** (-a) @classmethod def __function_units__(cls, r, T_0, **kwargs): return T_0.units
[docs] class AM06TemperatureProfile(BaseSphericalTemperatureProfile): r"""Ascasibar & Markevitch (2006) Temperature Profile. Flexible 3-parameter model for cool-core clusters. .. math:: T(r) = \frac{T_0}{1 + \frac{r}{a}} \cdot \frac{c + \frac{r}{a_c}}{1 + \frac{r}{a_c}} .. dropdown:: Parameters .. list-table:: :widths: 25 25 50 :header-rows: 1 * - ``T_0`` - :math:`T_0` - Central temperature * - ``a`` - :math:`a` - Transition scale radius * - ``a_c`` - :math:`a_c` - Core radius * - ``c`` - :math:`c` - Inner slope factor """ __IS_ABSTRACT__ = False __VARIABLES__ = ["r"] __VARIABLES_LATEX__ = [r"r"] __PARAMETERS__ = { "T_0": unyt.unyt_quantity(4.0, "keV"), "a": unyt.unyt_quantity(300.0, "kpc"), "a_c": unyt.unyt_quantity(50.0, "kpc"), "c": unyt.unyt_quantity(0.2, ""), } @classmethod def __function__(cls, r, T_0, a, a_c, c): return T_0 / (1 + r / a) * (c + r / a_c) / (1 + r / a_c) @classmethod def __function_units__(cls, r, T_0, **kwargs): return T_0.units
[docs] class VikhlininTemperatureProfile(BaseSphericalTemperatureProfile): r"""Vikhlinin Temperature Profile. Empirical model that captures a peaked core, a power-law decline, and a central cooling component. .. math:: T(r) = T_0 \left( \frac{r}{r_t} \right)^{-a} \left[1 + \left( \frac{r}{r_t} \right)^b \right]^{-c/b} \cdot \frac{\left(\left(\frac{r}{r_{\text{cool}}}\right)^{a_{\text{cool}}} + \frac{T_{\text{min}}}{T_0}\right)} {\left(\left(\frac{r}{r_{\text{cool}}}\right)^{a_{\text{cool}}} + 1\right)} .. dropdown:: Parameters .. list-table:: :widths: 25 25 50 :header-rows: 1 * - **Name** - **Symbol** - **Description** * - ``T_0`` - :math:`T_0` - Central peak temperature * - ``r_t`` - :math:`r_t` - Truncation radius * - ``a`` - :math:`a` - Power-law inner slope * - ``b`` - :math:`b` - Sharpness of transition * - ``c`` - :math:`c` - Outer slope * - ``T_min`` - :math:`T_{\text{min}}` - Minimum temperature in cooling region * - ``r_cool`` - :math:`r_{\text{cool}}` - Radius of cooling region * - ``a_cool`` - :math:`a_{\text{cool}}` - Slope of cooling core """ __IS_ABSTRACT__ = False __VARIABLES__ = ["r"] __VARIABLES_LATEX__ = [r"r"] __PARAMETERS__ = { "T_0": unyt.unyt_quantity(5.0, "keV"), "r_t": unyt.unyt_quantity(100.0, "kpc"), "a": unyt.unyt_quantity(0.1, ""), "b": unyt.unyt_quantity(2.0, ""), "c": unyt.unyt_quantity(1.2, ""), "T_min": unyt.unyt_quantity(2.0, "keV"), "r_cool": unyt.unyt_quantity(10.0, "kpc"), "a_cool": unyt.unyt_quantity(0.2, ""), } @classmethod def __function__(cls, r, T_0, r_t, a, b, c, T_min, r_cool, a_cool): x = (r / r_cool) ** a_cool t1 = (r / r_t) ** (-a) t2 = (1 + (r / r_t) ** b) ** (-c / b) t3 = (x + T_min / T_0) / (x + 1) return T_0 * t1 * t2 * t3 @classmethod def __function_units__(cls, r, T_0, **kwargs): return T_0.units