Source code for horizonground.clustering_modification

r"""
Clustering modification (:mod:`~horizonground.clustering_modification`)
===========================================================================

Compute modifications to the Newtonian power spectrum in the
distant-observer and plane-parallel limits.


Standard Kaiser RSD model
---------------------------------------------------------------------------

Redshift-space distortions induce anisotropy in the power spectrum
multipoles

.. math::

    \begin{align*}
        P_0(k, z) &=
            \left[
                b_1(z)^2 + \frac{2}{3} b_1(z) f(z) + \frac{1}{5} f(z)^2
            \right] P_\mathrm{m}(k, z) \,, \\
        P_2(k, z) &=
            \left[
                \frac{4}{3} b_1(z) f(z) + \frac{4}{7} f(z)^2
            \right] P_\mathrm{m}(k, z) \,, \\
        P_4(k, z) &= \frac{8}{35} f(z)^2 P_\mathrm{m}(k, z) \,
    \end{align*}

where :math:`P_\mathrm{m}` is the matter power spectrum, :math:`b_1(z)` is
the linear bias and :math:`f(z)` is the linear growth rate.

.. autosummary::

    standard_kaiser_factor


Non-Gaussianity scale-dependent modifications
---------------------------------------------------------------------------

Local primordial non-Gaussianty :math:`f_\mathrm{NL}` induces scale
dependence in the linear bias,

.. math::

    b_1(z) \mapsto b_1(z) + \Delta b_k(z) \,, \quad
    \Delta b(k, z) = f_\mathrm{NL} [b_1(z) - p] \frac{A(k, z)}{k^2} \,,

where the scale-dependence kernel is

.. math::

    A(k, z) = 3 \left( \frac{H_0}{c} \right)^2
        \frac{1.27 \varOmega_\mathrm{m,0} \delta_\mathrm{c}}{D(z)T(k)} \,.

Here :math:`H_0` is the Hubble parameter :math:`H(z)` (in
km s\ :sup:`-1` Mpc\ :sup:`-1`) at the current epoch :math:`z = 0`,
:math:`c` the speed of light, :math:`\varOmega_\mathrm{m,0}` the matter
density parameter at the current epoch, and :math:`\delta_\mathrm{c}` the
critical over-density in spherical gravitational collapse.  The growth
factor :math:`D(z)` is normalised to unity at the current epoch (thus the
numerical factor 1.27), the transfer function :math:`T(k)` is normalised
to unity as :math:`k \to 0`, and :math:`p` is a tracer-dependent
parameter.

Modifications to power spectrum multipoles as a result of local primordial
non-Gaussianty are

.. math::

    \begin{align*}
        \Delta P_0 &= \left[
            \left( 2 b_1 + \frac{2}{3} f \right) \Delta b
            + {\Delta b}^2
        \right] P_\mathrm{m} \,, \\
        \Delta P_2 &=
            \frac{4}{3} f \Delta b P_\mathrm{m} \,.
    \end{align*}

.. autosummary::

    scale_dependence_kernel
    non_gaussianity_correction_factor


Relativistic corrections
---------------------------------------------------------------------------

Relativistic corrections to the Newtonian clustering mode

.. math::

    \delta(\mathbf{k}, z) = \left[
        b_1 + f \mu^2
        + \mathrm{i} \frac{\mathcal{H}}{k} g_1(z) f \mu
        + \left( \frac{\mathcal{H}}{k} \right)^2 g_2(z)
    \right] \delta_\mathrm{m}(\mathbf{k}, z) \,,

are parametrised by the redshift-dependent, dimensionless quantities

.. math::

    \begin{align*}
        g_1(z) &= \left(
            3 - b_\mathrm{e} - \frac{3}{2} \varOmega_\mathrm{m}
        \right) - (2 - 5s) \left(
            1 - \frac{1}{\mathcal{H} \chi}
        \right) \,, \\
        g_2(z) &= \left(
            3 - b_\mathrm{e} - \frac{3}{2} \varOmega_\mathrm{m}
        \right) f - \frac{3}{2} \varOmega_\mathrm{m} \big[
            g_1(z) - (2 - 5s)
        \big]
    \end{align*}

with evolution bias :math:`b_\mathrm{e}(z)` and magnification bias
:math:`s(z)`, where :math:`\mathcal{H}(z)` is the conformal Hubble
parameter, :math:`\chi(z)` is the comoving distance, and the matter
density parameter evolves as

.. math::

    \varOmega_\mathrm{m}(z) = \frac{H_0^2}{H(z)^2}
        \varOmega_{\mathrm{m},0} (1 + z)^3 \,.

Modifications to power spectrum multipoles from the relativistic
corrections are

.. math::

    \begin{align*}
        \Delta P_0 &= \left[
            \left(
                2 b_1 g_2 + \frac{2}{3} f g_2 + \frac{1}{3} f^2 g_1^2
            \right) \frac{\mathcal{H}^2}{k^2}
            + g_2^2 \frac{\mathcal{H}^4}{k^4}
        \right] P_\mathrm{m} \,,\\
        \Delta P_2 &= \frac{2}{3} \left( 2 f g_2 + f^2 g_1^2 \right)
            \frac{\mathcal{H}^2}{k^2} P_\mathrm{m} \,.
    \end{align*}

.. autosummary::

    relativistic_correction_func
    relativistic_correction_value
    relativistic_correction_factor

|

"""
# pylint: disable=no-name-in-module
from astropy.constants import c
from nbodykit.cosmology import Planck15, power

_SPEED_OF_LIGHT_IN_KM_PER_S = c.to('km/s').value
_SPHERICAL_COLLAPSE_CRITICAL_OVERDENSITY = 1.686
_GROWTH_FACTOR_NORMALISATION = 1.27

FIDUCIAL_COSMOLOGY = Planck15
r""":class:`nbodykit.cosmology.Cosmology`: Default Planck15 cosmology.

"""


[docs]def standard_kaiser_factor(order, bias, redshift, cosmo=FIDUCIAL_COSMOLOGY): r"""Compute the standard Kaiser power spectrum multipoles as multiples of the matter power spectrum, i.e. :math:`P_\ell/P_\mathrm{m}`. Parameters ---------- order : int Order of the multipole, ``order >= 0``. bias : callable or float Scale-independent linear bias (at `redshift`). redshift : float Redshift. cosmo : :class:`nbodykit.cosmology.Cosmology`, optional Cosmological model (default is ``FIDUCIAL_COSMOLOGY``). Returns ------- factor : float Power spectrum multipole as a multiple of the matter power spectrum. """ b_1 = bias(redshift) if callable(bias) else bias f = cosmo.scale_independent_growth_rate(redshift) if order == 0: factor = b_1 ** 2 + 2./3. * f * b_1 + 1./5. * f**2 elif order == 2: factor = 4./3. * f * b_1 + 4./7. * f**2 elif order == 4: factor = 8./35. * f**2 else: factor = 0. return factor
[docs]def scale_dependence_kernel(redshift, cosmo=FIDUCIAL_COSMOLOGY): r"""Return the scale-dependence kernel :math:`A(k, z)` in the presence of local primordial non-Gaussianity. Parameters ---------- redshift : float Redshift. cosmo : :class:`nbodykit.cosmology.Cosmology`, optional Cosmological model (default is ``FIDUCIAL_COSMOLOGY``). Returns ------- callable Scale-dependence kernel as a function of wavenumber (in :math:`h/\mathrm{Mpc}`). """ numerical_constants = 3 * _SPHERICAL_COLLAPSE_CRITICAL_OVERDENSITY \ * cosmo.Om0 * _GROWTH_FACTOR_NORMALISATION \ * (FIDUCIAL_COSMOLOGY.H0 / _SPEED_OF_LIGHT_IN_KM_PER_S)**2 transfer_function = power.transfers.CLASS(cosmo, redshift) return lambda k: numerical_constants / transfer_function(k)
[docs]def non_gaussianity_correction_factor(wavenumber, order, local_png, bias, redshift, cosmo=FIDUCIAL_COSMOLOGY, tracer_p=1.): r"""Compute modifications to the power spectrum multipoles by local primordial non-Gaussianity as multiples of the matter power spectrum, i.e. :math:`\Delta P_\ell/P_\mathrm{m}`. Parameters ---------- wavenumber : float, array_like Wavenumber (in :math:`h/\mathrm{Mpc}`). order : int Order of the multipole, ``order >= 0``. local_png : float Local primordial non-Gaussianity. bias : callable or float Scale-independent linear bias (at `redshift`). redshift : float Redshift. cosmo : :class:`nbodykit.cosmology.Cosmology`, optional Base cosmological model (default is ``FIDUCIAL_COSMOLOGY``). tracer_p : float, optional Tracer parameter (default is 1.). Returns ------- factor : float :class:`numpy.ndarray` Power spectrum multipole modifications as multiples of the matter power spectrum. """ f_nl, p = local_png, tracer_p b_1 = bias(redshift) if callable(bias) else bias f = cosmo.scale_independent_growth_rate(redshift) delta_b = f_nl * (b_1 - p) \ * scale_dependence_kernel(redshift, cosmo=cosmo)(wavenumber) \ / wavenumber ** 2 if order == 0: factor = (2 * b_1 + 2./3. * f) * delta_b + delta_b ** 2 elif order == 2: factor = 4./3. * f * delta_b else: factor = 0. return factor
[docs]def relativistic_correction_func(corr_order, cosmo=FIDUCIAL_COSMOLOGY, evolution_bias=None, magnification_bias=None): r"""Return the relativistic correction function :math:`g_1(z)` or :math:`g_2(z)`. Parameters ---------- corr_order : {1, 2}, int Order of the correction parameter :math:`\mathcal{H}/k`. cosmo : :class:`nbodykit.cosmology.Cosmology`, optional Cosmological model (default is ``FIDUCIAL_COSMOLOGY``). evolution_bias, magnification_bias : callable or None, optional Evolution bias or magnification bias as a function of redshift (default is `None`). Returns ------- callable Relativistic correction function as a function of redshift (in :math:`h`/Mpc). """ astropy_cosmo = cosmo.to_astropy() b_e = evolution_bias or (lambda z: 0.) s = magnification_bias or (lambda z: 0.) omega_m = lambda z: astropy_cosmo.Om0 \ * (astropy_cosmo.H0 / astropy_cosmo.H(z)) ** 2 * (1 + z) ** 3 aH_chi = lambda z: astropy_cosmo.scale_factor(z) \ * (astropy_cosmo.H(z).value / _SPEED_OF_LIGHT_IN_KM_PER_S) \ * astropy_cosmo.comoving_distance(z).value f = cosmo.scale_independent_growth_rate def g1_of_z(z): return 3 - b_e(z) - 3./2. * omega_m(z) \ - (2 - 5 * s(z)) * (1 - 1 / aH_chi(z)) def g2_of_z(z): return (3 - b_e(z) - 3./2. * omega_m(z)) * f(z) \ - 3./2. * omega_m(z) * (g1_of_z(z) - (2 - 5 * s(z))) if corr_order == 1: return g1_of_z if corr_order == 2: return g2_of_z raise ValueError("Accepted correction order is 1 or 2.")
[docs]def relativistic_correction_value(redshift, corr_order, cosmo=FIDUCIAL_COSMOLOGY, evolution_bias=None, magnification_bias=None): r"""Evaluate the redshift-dependent relativistic correction value :math:`g_1(z)` or :math:`g_2(z)`. Parameters ---------- redshift : float Redshift. corr_order : {1, 2}, int Correction order of the parameter :math:`\mathcal{H}/k`. cosmo : :class:`nbodykit.cosmology.Cosmology`, optional Base cosmological model (default is ``FIDUCIAL_COSMOLOGY``). evolution_bias, magnification_bias : float or None, optional Evolution bias or magnification bias evaluated at input `redshift` (default is `None`). Returns ------- correction_value : float Relativistic correction function value (in :math:`h`/Mpc) at `redshift`. """ astropy_cosmo = cosmo.to_astropy() b_e = evolution_bias or 0. s = magnification_bias or 0. omega_m = astropy_cosmo.Om0 \ * (astropy_cosmo.H0 / astropy_cosmo.H(redshift)) ** 2 \ * (1 + redshift) ** 3 aH_chi = astropy_cosmo.scale_factor(redshift) \ * (astropy_cosmo.H(redshift).value / _SPEED_OF_LIGHT_IN_KM_PER_S) \ * astropy_cosmo.comoving_distance(redshift).value f = cosmo.scale_independent_growth_rate(redshift) g_1 = 3 - b_e - 3./2. * omega_m - (2 - 5 * s) * (1 - 1 / aH_chi) if corr_order == 1: return g_1 if corr_order == 2: return (3 - b_e - 3./2. * omega_m) * f \ - 3./2. * omega_m * (g_1 - (2 - 5 * s)) raise ValueError("Accepted correction order is 1 or 2.")
[docs]def relativistic_correction_factor(wavenumber, order, redshift, bias, correction_value_1=None, correction_value_2=None, cosmo=FIDUCIAL_COSMOLOGY, evolution_bias=None, magnification_bias=None): r"""Compute modifications to the power spectrum multipoles by relativistic corrections as multiples of the matter power spectrum, i.e. :math:`\Delta P_\ell/P_\mathrm{m}`. Parameters ---------- wavenumber : float, array_like Wavenumber (in :math:`h/\mathrm{Mpc}`). order : int Order of the multipole, ``order >= 0``. redshift : float Redshift. bias : callable or float Scale-independent linear bias (at `redshift`). correction_value_1, correction_value_2 : float or None, optional If not `None` (default), this is directly used as :math:`g_1(z)` or :math:`g_2(z)` at `redshift` in calculations, and `evolution_bias`, `magnification_bias` are ignored. cosmo : :class:`nbodykit.cosmology.Cosmology`, optional Cosmological model (default is ``FIDUCIAL_COSMOLOGY``). evolution_bias : float or callable or None, optional Evolution bias as a function of redshift, or evaluated at input `redshift` (default is `None`). If callable/float, `magnification_bias` must also be callable/float. magnification_bias : float or callable or None, optional Magnification bias as a function of redshift, or evaluated at input `redshift` (default is `None`). If callable/float, `evolution_bias` must also be callable/float. Returns ------- factor : float :class:`numpy.ndarray` Power spectrum multipole modifications as multiples of the matter power spectrum. """ astropy_cosmo = cosmo.to_astropy() aH_over_k = astropy_cosmo.scale_factor(redshift) \ * (astropy_cosmo.H(redshift).value / _SPEED_OF_LIGHT_IN_KM_PER_S) \ / wavenumber b_1 = bias(redshift) if callable(bias) else bias f = cosmo.scale_independent_growth_rate(redshift) g_1 = correction_value_1 or relativistic_correction_func( 1, cosmo=cosmo, evolution_bias=evolution_bias, magnification_bias=magnification_bias )(redshift) g_2 = correction_value_2 or relativistic_correction_func( 2, cosmo=cosmo, evolution_bias=evolution_bias, magnification_bias=magnification_bias )(redshift) if order == 0: factor = (2 * b_1 * g_2 + 2./3. * f * g_2 + 1./3. * f**2 * g_1 ** 2) \ * aH_over_k ** 2 + g_2 ** 2 * aH_over_k ** 4 elif order == 2: factor = 2./3. * (2 * f * g_2 + f**2 * g_1 ** 2) * aH_over_k ** 2 else: factor = 0. return factor