Source code for cosmofit.cosmology.models.gcg

"""
Generalized Chaplygin Gas (GCG) model.
"""

from __future__ import annotations

import numpy as np

from cosmofit.typing import Array, Redshift

from cosmofit.cosmology.numerics.powers import cube

from cosmofit.cosmology.core import Cosmology


[docs] class GCG(Cosmology): """ Generalized Chaplygin Gas (GCG). Unlike LCDM/wCDM/CPL/JBP/BA -- which all just reparametrize dark energy's equation of state on top of an independent matter component -- GCG replaces dark energy with a single exotic fluid with equation of state p = -A / rho^alpha that unifies dark matter and dark energy: it behaves like pressureless dust at early times (large rho, small ``|p/rho|``) and like a cosmological constant at late times (rho -> const), interpolating between the two as the universe expands. The ``Omega_m`` parameter here is therefore ordinary *baryonic + any additional* matter on top of the GCG fluid, not the GCG fluid's own dust-like contribution. Density evolution (closed-form solution of the GCG continuity equation):: rho_GCG(z) / rho_GCG(0) = [ A_s + (1 - A_s) (1+z)^(3(1+alpha)) ]^(1/(1+alpha)) Effective equation of state:: w(z) = -A_s / [ A_s + (1-A_s)(1+z)^(3(1+alpha)) ] * (1+z)^(3(1+alpha)) ... equivalently w(z) = -1 + (1-A_s)(1+z)^(3(1+alpha)) / [A_s + (1-A_s)(1+z)^(3(1+alpha))] so w(0) = -A_s and w(z) -> 0 (dust-like) as z -> infinity. A_s = 1 reduces GCG to flat/curved LCDM (rho_GCG(z) = rho_GCG(0) for any alpha); alpha = 1 is the original ("pure") Chaplygin gas of Kamenshchik, Moschella & Pasquier (2001). Notes ----- Uses the shared ``A_s`` and ``alpha`` fields of :class:`~cosmology.core.parameters.CosmologyParameters` (ignored by every other model, the same way LCDM ignores ``w0``/``wa``). References ---------- Kamenshchik, Moschella & Pasquier (2001), Phys. Lett. B 511, 265, arXiv:gr-qc/0103004. Bento, Bertolami & Sen (2002), Phys. Rev. D 66, 043507, arXiv:gr-qc/0202064. """ MODEL_NAME = "GCG" # --------------------------------------------------------- def _g(self, z): """ A_s + (1-A_s)(1+z)^(3(1+alpha)) -- the base of the fde(z) and dlnfde/dz expressions below, computed once and shared between them. """ z = np.asarray(z, dtype=float) return self.A_s + (1.0 - self.A_s) * (1.0 + z) ** ( 3.0 * (1.0 + self.alpha) ) # --------------------------------------------------------- def w(self, z: Redshift) -> Array: """ Effective dark-energy equation of state. """ z = np.asarray(z, dtype=float) g = self._g(z) return -1.0 + (1.0 - self.A_s) * (1.0 + z) ** ( 3.0 * (1.0 + self.alpha) ) / g # --------------------------------------------------------- def fde(self, z: Redshift) -> Array: """ GCG density evolution factor. Returns ------- ndarray ρ_GCG(z) / ρ_GCG(0) """ z = np.asarray(z, dtype=float) return self._g(z) ** (1.0 / (1.0 + self.alpha)) # --------------------------------------------------------- def E(self, z: Redshift) -> Array: """ Dimensionless Hubble parameter. Note: ``Omega_m`` here is *additional* matter on top of the GCG fluid (which supplies its own effective matter and dark-energy behavior) -- see the class docstring. """ z = np.asarray(z, dtype=float) return np.sqrt( self.Omega_m * cube(1.0 + z) + self.Omega_k * (1.0 + z) ** 2 + self.Omega_de0 * self.fde(z) ) # --------------------------------------------------------- def dEdz(self, z: Redshift) -> Array: """ Derivative of E(z). """ z = np.asarray(z, dtype=float) g = self._g(z) fde = g ** (1.0 / (1.0 + self.alpha)) # d ln(fde)/dz = 3(1-A_s)(1+z)^(3(1+alpha)-1) / g(z) # (== 3(1+w(z))/(1+z), by construction of fde above). dlnf_dz = ( 3.0 * (1.0 - self.A_s) * (1.0 + z) ** (3.0 * (1.0 + self.alpha) - 1.0) / g ) dE2_dz = ( 3.0 * self.Omega_m * (1.0 + z) ** 2 + 2.0 * self.Omega_k * (1.0 + z) + self.Omega_de0 * fde * dlnf_dz ) return dE2_dz / (2.0 * self.E(z)) # --------------------------------------------------------- def Omega_de(self, z: Redshift) -> Array: """ GCG effective density parameter. """ z = np.asarray(z, dtype=float) return self.Omega_de0 * self.fde(z)