Source code for astropy.cosmology._src.traits.darkenergy
from abc import abstractmethod
from math import exp, log
import numpy as np
from numpy.typing import ArrayLike
from astropy.cosmology._src.scipy_compat import quad
from astropy.cosmology._src.typing import FArray
from astropy.cosmology._src.utils import aszarr, deprecated_keywords
from astropy.units import Quantity
[docs]
class DarkEnergyComponent:
# Subclasses should use `Parameter` to make this a parameter of the cosmology.
Ode0: float
"""Omega dark energy; dark energy density/critical density at z=0."""
[docs]
@abstractmethod
@deprecated_keywords("z", since="7.0")
def w(self, z: Quantity | ArrayLike) -> FArray:
r"""The dark energy equation of state.
Parameters
----------
z : Quantity-like ['redshift'], array-like
Input redshift.
.. versionchanged:: 7.0
Passing z as a keyword argument is deprecated.
Returns
-------
w : ndarray or float
The dark energy equation of state.
`float` if scalar input.
Notes
-----
The dark energy equation of state is defined as
:math:`w(z) = P(z)/\rho(z)`, where :math:`P(z)` is the pressure at
redshift z and :math:`\rho(z)` is the density at redshift z, both in
units where c=1.
This must be overridden by subclasses.
"""
raise NotImplementedError("w(z) is not implemented")
def _w_integrand(self, ln1pz: float | FArray, /) -> FArray:
"""Internal convenience function for w(z) integral (eq. 5 of [1]_).
Parameters
----------
ln1pz : `~numbers.Number` or scalar ndarray, positional-only
Assumes scalar input, since this should only be called inside an
integral.
.. versionchanged:: 7.0
The argument is positional-only.
References
----------
.. [1] Linder, E. (2003). Exploring the Expansion History of the
Universe. Phys. Rev. Lett., 90, 091301.
"""
return 1.0 + self.w(exp(ln1pz) - 1.0)
[docs]
@deprecated_keywords("z", since="7.0")
def de_density_scale(self, z: Quantity | ArrayLike) -> FArray:
r"""Evaluates the redshift dependence of the dark energy density.
Parameters
----------
z : Quantity-like ['redshift'], array-like
Input redshift.
.. versionchanged:: 7.0
Passing z as a keyword argument is deprecated.
Returns
-------
I : ndarray or float
The scaling of the energy density of dark energy with redshift.
Returns `float` if the input is scalar.
Notes
-----
The scaling factor, I, is defined by :math:`\rho(z) = \rho_0 I`,
and is given by
.. math::
I = \exp \left( 3 \int_{a}^1 \frac{ da^{\prime} }{ a^{\prime} }
\left[ 1 + w\left( a^{\prime} \right) \right] \right)
The actual integral used is rewritten from [1]_ to be in terms of z.
It will generally helpful for subclasses to overload this method if
the integral can be done analytically for the particular dark
energy equation of state that they implement.
References
----------
.. [1] Linder, E. (2003). Exploring the Expansion History of the
Universe. Phys. Rev. Lett., 90, 091301.
"""
# This allows for an arbitrary w(z) following eq (5) of
# Linder 2003, PRL 90, 91301. The code here evaluates
# the integral numerically. However, most popular
# forms of w(z) are designed to make this integral analytic,
# so it is probably a good idea for subclasses to overload this
# method if an analytic form is available.
z = aszarr(z)
ival = (
quad(self._w_integrand, 0, log(z + 1.0))[0] # scalar
if z.ndim == 0
else np.asarray([quad(self._w_integrand, 0, log(1 + _z))[0] for _z in z])
)
return np.exp(3 * ival)
[docs]
@deprecated_keywords("z", since="7.0")
def Ode(self, z: Quantity | ArrayLike) -> FArray:
"""Return the density parameter for dark energy at redshift ``z``.
Parameters
----------
z : Quantity-like ['redshift'], array-like
Input redshift.
.. versionchanged:: 7.0
Passing z as a keyword argument is deprecated.
Returns
-------
Ode : ndarray
The density of dark energy relative to the critical density at each
redshift.
"""
z = aszarr(z)
if self.Ode0 == 0: # Common enough to be worth checking explicitly
return np.zeros_like(z)
# Ensure self.inv_efunc is implemented by the main class
if not hasattr(self, "inv_efunc") or not callable(self.inv_efunc):
msg = "The main class must implement an 'inv_efunc(z)' method."
raise NotImplementedError(msg)
return self.Ode0 * self.de_density_scale(z) * self.inv_efunc(z) ** 2