a
    ߙfb                    @   sP  d dl Z d dlmZ d dlmZmZmZmZmZm	Z	m
Z
mZmZ d dlmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ dd	lmZ dd
lmZ ddl m!Z!m"Z"m#Z# ddl$m%Z%m&Z& ddl'm(Z(m)Z) erd dl*m+Z+ d dl,m-Z-m.Z. ndd Z+dd Z-dd Z.g dZ/ddgiZ0ej1ej2ej3  4dej2 Z5ej24ej6Z7dde
 ej8  j9j:Z;e
d Z<e
d Z=dej> ej?d  j9j:Z@ejA4ejBejC ZDG dd  d e!ZEG d!d" d"e"ZFG d#d$ d$eEZGG d%d& d&eFeGZHG d'd( d(eEZIG d)d* d*eFeIZJG d+d, d,eEZKG d-d. d.eFeKZLG d/d0 d0eEZMG d1d2 d2eEZNdS )3    N)abstractmethod)	acoscosexpfloorinflogpisinsqrt)Number)	HAS_SCIPY)lazyproperty)AstropyUserWarning   )scalar_inv_efuncs)units)	CosmologyFlatCosmologyMixin	Parameter)_validate_non_negative_validate_with_unit)aszarrvectorize_redshift_method)quad)	ellipkinchyp2f1c                  O   s   t dd S )Nz!No module named 'scipy.integrate'ModuleNotFoundErrorargskwargs r"   5lib/python3.9/site-packages/astropy/cosmology/flrw.pyr      s    r   c                  O   s   t dd S NzNo module named 'scipy.special'r   r   r"   r"   r#   r      s    r   c                  O   s   t dd S r$   r   r   r"   r"   r#   r   !   s    r   )
FLRW	LambdaCDMFlatLambdaCDMwCDMFlatwCDMw0waCDMFlatw0waCDMwpwaCDMw0wzCDMFlatFLRWMixin*Zscipy      ?      g    #Ag     @   c                       s  e Zd ZdZeddddZedddZed	d
dZedddddZedddZ	edde
 ddZeddZde
j dde
j dfddd fddZejdd Zedd Zed d! Zed"d# Zed$d% Zed&d' Zed(d) Zed*d+ Zed,d- Zed.d/ Zed0d1 Zed2d3 Zd4d5 Zd6d7 Z d8d9 Z!d:d; Z"d<d= Z#d>d? Z$d@dA Z%dBdC Z&dDdE Z'dFdG Z(dHdI Z)dJdK Z*dLdM Z+dNdO Z,dPdQ Z-dRdS Z.dTdU Z/dVdW Z0dXdY Z1dZd[ Z2d\d] Z3d^d_ Z4e5d`da Z6dbdc Z7ddde Z8dfdg Z9e5dhdi Z:djdk Z;dldm Z<dndo Z=e5dpdqdrds Z>dtdu Z?dvdw Z@dxdy ZAdzd{ ZBd|d} ZCd~d ZDe5dd ZEdd ZFdd ZGdd ZHdd ZIdd ZJdd ZKdd ZL  ZMS )r%   a	  
    A class describing an isotropic and homogeneous
    (Friedmann-Lemaitre-Robertson-Walker) cosmology.

    This is an abstract base class -- you cannot instantiate examples of this
    class, but must work with one of its subclasses, such as
    :class:`~astropy.cosmology.LambdaCDM` or :class:`~astropy.cosmology.wCDM`.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0.  If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0. Note that this does not include massive
        neutrinos.

    Ode0 : float
        Omega dark energy: density of dark energy in units of the critical
        density at z=0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Notes
    -----
    Class instances are immutable -- you cannot change the parameters' values.
    That is, all of the above attributes (except meta) are read only.

    For details on how to create performant custom subclasses, see the
    documentation on :ref:`astropy-cosmology-fast-integrals`.
    z7Hubble constant as an `~astropy.units.Quantity` at z=0.z
km/(s Mpc)Zscalar)docunit	fvalidatez5Omega matter; matter density/critical density at z=0.znon-negativer4   r6   ?Omega dark energy; dark energy density/critical density at z=0.floatz;Temperature of the CMB as `~astropy.units.Quantity` at z=0.ZKelvinz0.4g)r4   r5   fmtr6   z%Number of effective neutrino species.zMass of neutrino species.eV )r4   r5   Zequivalenciesr:   z>Omega baryon; baryonic matter density/critical density at z=0.)r4           RQ@Nnamemetac                   s.  t  j||	d || _|| _|| _|| _|| _|| _|| _|d u rFd n
| j	| j
 | _| jjd | _tj| j tj| _| jjt }
tt|
 tj| _t|
d  }t|tjtjd  | _t| j| _ d| _!| j dkr| j"jdkr| j| j  | _#| j$}|j%rL|jdkr"| j | _&d| _'n(d| _!d| _&| j | _'|jt()| j  | _*n|j+ dk rdt,d|j- dkr| j | _&d| _'nhd| _!t.|| j krd	}t,|t.t(/|jdkd | _&| j | j& | _'t(/|jdkd }|| | _*| j"jdkrtt0| j"jd
  | jj | _1d| j" | _2| j!r`| j*t3| j2  }|j| _4| j45 | _6| j1| 7d | _8nd| j | j1 | _8nd| _1dtj9 | _2d| _8| j dks| j2jdkrd | _$nP| j!st(:| j&}n,| j&dkr| j*}nt(;t(:| j&| j*j}|| j$j<> | _$d| j	 | j= | j1 | j8 | _>| j?| _@d| _Ad S )Nr?   g      Y@   r1   Fr   Tz,Invalid (negative) neutrino mass encounteredz$Unexpected number of neutrino massesr3   grv}+?C?r=   r0   r"   )Bsuper__init__H0Om0Ode0Tcmb0Neffm_nuOb0_Om0_Ob0_Odm0_H0value_hconstctouMpc_hubble_distanceH0units_to_invsQuantity
sec_to_GyrGyr_hubble_timecritdens_constgcm_critical_density0r   _NeffZ_nneutrinos
_massivenu_Tcmb0_neff_per_nuZ_m_nuZisscalar_nmasslessnuZ_nmassivenunponesZ_massivenu_massmin
ValueErrormaxlenZnonzeroa_B_c2_Ogamma0_Tnu0kB_evK_nu_ytolist
_nu_y_listnu_relative_density_Onu0Kzerosappendr5   _Ode0_Ok0	inv_efunc_inv_efunc_scalar_inv_efunc_scalar_args)selfrF   rG   rH   rI   rJ   rK   rL   r@   rA   ZH0_sZcd0valueZerrstrwZnu_ym	__class__r"   r#   rE      s    

zFLRW.__init__c                 C   s.   |du r|S t | ||}|| jkr*td|S )zCValidate baryon density to None or positive float > matter density.Nz=baryonic density can not be larger than total matter density.)r   rG   rj   )r~   ZparamrQ   r"   r"   r#   rL     s    
zFLRW.Ob0c                 C   s   | j S )z?Omega dark matter; dark matter density/critical density at z=0.)rO   r~   r"   r"   r#   Odm0  s    z	FLRW.Odm0c                 C   s   | j S )zIOmega curvature; the effective curvature density/critical density at z=0.)rz   r   r"   r"   r#   Ok0$  s    zFLRW.Ok0c                 C   s   | j S )zKTemperature of the neutrino background as `~astropy.units.Quantity` at z=0.)ro   r   r"   r"   r#   Tnu0)  s    z	FLRW.Tnu0c                 C   s   | j jdkrdS | jS )z?Does this cosmology have at least one massive neutrino species?r   F)ro   rQ   rc   r   r"   r"   r#   has_massive_nu.  s    zFLRW.has_massive_nuc                 C   s   | j S )z:Dimensionless Hubble constant: h = H_0 / 100 [km/sec/Mpc].)rR   r   r"   r"   r#   h5  s    zFLRW.hc                 C   s   | j S )z)Hubble time as `~astropy.units.Quantity`.)r]   r   r"   r"   r#   hubble_time:  s    zFLRW.hubble_timec                 C   s   | j S )z-Hubble distance as `~astropy.units.Quantity`.)rX   r   r"   r"   r#   hubble_distance?  s    zFLRW.hubble_distancec                 C   s   | j S )z5Critical density as `~astropy.units.Quantity` at z=0.)ra   r   r"   r"   r#   critical_density0D  s    zFLRW.critical_density0c                 C   s   | j S )z<Omega gamma; the density/critical density of photons at z=0.)rn   r   r"   r"   r#   Ogamma0I  s    zFLRW.Ogamma0c                 C   s   | j S )z;Omega nu; the density/critical density of neutrinos at z=0.)ru   r   r"   r"   r#   Onu0N  s    z	FLRW.Onu0c                 C   s   t ddS )a  The dark energy equation of state.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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.
        zw(z) is not implementedN)NotImplementedErrorr~   zr"   r"   r#   r   U  s    zFLRW.wc                 C   s(   t |}| j|d d  | |d  S )ae  
        Return the density parameter for non-relativistic matter
        at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Om : ndarray or float
            The density of non-relativistic matter relative to the critical
            density at each redshift.
            Returns `float` if the input is scalar.

        Notes
        -----
        This does not include neutrinos, even if non-relativistic at the
        redshift of interest; see `Onu`.
        r0   r1   rB   )r   rM   r{   r   r"   r"   r#   Omo  s    zFLRW.Omc                 C   s:   | j du rtdt|}| j |d d  | |d  S )a	  Return the density parameter for baryonic matter at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Ob : ndarray or float
            The density of baryonic matter relative to the critical density at
            each redshift.
            Returns `float` if the input is scalar.

        Raises
        ------
        ValueError
            If ``Ob0`` is `None`.
        Nz)Baryon density not set for this cosmologyr0   r1   rB   )rN   rj   r   r{   r   r"   r"   r#   Ob  s    
zFLRW.Obc                 C   s:   | j du rtdt|}| j |d d  | |d  S )a  Return the density parameter for dark matter at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Odm : ndarray or float
            The density of non-relativistic dark matter relative to the
            critical density at each redshift.
            Returns `float` if the input is scalar.

        Raises
        ------
        ValueError
            If ``Ob0`` is `None`.

        Notes
        -----
        This does not include neutrinos, even if non-relativistic at the
        redshift of interest.
        NzSBaryonic density not set for this cosmology, unclear meaning of dark matter densityr0   r1   rB   )rO   rj   r   r{   r   r"   r"   r#   Odm  s    
zFLRW.Odmc                 C   sL   t |}| jdkr,t|dr(t|jS dS | j|d d  | |d  S )a  
        Return the equivalent density parameter for curvature at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Ok : ndarray or float
            The equivalent density parameter for curvature at each redshift.
            Returns `float` if the input is scalar.
        r   shaper=   r0   rB   )r   rz   hasattrrg   rw   r   r{   r   r"   r"   r#   Ok  s    
zFLRW.Okc                 C   sJ   t |}| jdkr,t|dr(t|jS dS | j| | | |d  S )a  Return the density parameter for dark energy at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Ode : ndarray or float
            The density of non-relativistic matter relative to the critical
            density at each redshift.
            Returns `float` if the input is scalar.
        r   r   r=   rB   )r   ry   r   rg   rw   r   de_density_scaler{   r   r"   r"   r#   Ode  s    
zFLRW.Odec                 C   s(   t |}| j|d d  | |d  S )a  Return the density parameter for photons at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Ogamma : ndarray or float
            The energy density of photons relative to the critical density at
            each redshift.
            Returns `float` if the input is scalar.
        r0   r3   rB   )r   rn   r{   r   r"   r"   r#   Ogamma  s    zFLRW.Ogammac                 C   s@   t |}| jdkr,t|dr(t|jS dS | || | S )a  Return the density parameter for neutrinos at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Onu : ndarray or float
            The energy density of neutrinos relative to the critical density at
            each redshift. Note that this includes their kinetic energy (if
            they have mass), so it is not equal to the commonly used
            :math:`\sum \frac{m_{\nu}}{94 eV}`, which does not include
            kinetic energy.
            Returns `float` if the input is scalar.
        r   r   r=   )r   ru   r   rg   rw   r   r   rt   r   r"   r"   r#   Onu  s    
zFLRW.Onuc                 C   s   | j t|d  S )aI  Return the CMB temperature at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Tcmb : `~astropy.units.Quantity` ['temperature']
            The temperature of the CMB in K.
        r0   )rd   r   r   r"   r"   r#   Tcmb  s    z	FLRW.Tcmbc                 C   s   | j t|d  S )ad  Return the neutrino temperature at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        Tnu : `~astropy.units.Quantity` ['temperature']
            The temperature of the cosmic neutrino background in K.
        r0   )ro   r   r   r"   r"   r#   Tnu   s    zFLRW.Tnuc           	      C   s   d}t |}| js6|| j t|dr0t|jnd S d}d}d}| jdtj|dd  }d|| |  | }|	d| j
 }|| j | S )	a  Neutrino density function relative to the energy density in photons.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        f : ndarray or float
            The neutrino density scaling factor relative to the density in
            photons at each redshift.
            Only returns `float` if z is scalar.

        Notes
        -----
        The density in neutrinos is given by

        .. math::

           \rho_{\nu} \left(a\right) = 0.2271 \, N_{eff} \,
           f\left(m_{\nu} a / T_{\nu 0} \right) \,
           \rho_{\gamma} \left( a \right)

        where

        .. math::

           f \left(y\right) = \frac{120}{7 \pi^4}
           \int_0^{\infty} \, dx \frac{x^2 \sqrt{x^2 + y^2}}
           {e^x + 1}

        assuming that all neutrino species have the same mass.
        If they have different masses, a similar term is calculated for each
        one. Note that ``f`` has the asymptotic behavior :math:`f(0) = 1`. This
        method returns :math:`0.2271 f` using an analytical fitting formula
        given in Komatsu et al. 2011, ApJS 192, 18.
        rC   r   r0   gHzG?g'|?gTN?)Zaxis)r   rc   rb   r   rg   rh   r   rq   Zexpand_dimssumrf   re   )	r~   r   ZprefacpZinvpkZ	curr_nu_yZrel_mass_perZrel_massr"   r"   r#   rt   /  s    /$zFLRW.nu_relative_densityc                 C   s   d|  t|d  S )a  Internal convenience function for w(z) integral (eq. 5 of [1]_).

        Parameters
        ----------
        ln1pz : `~numbers.Number` or scalar ndarray
            Assumes scalar input, since this should only be called inside an
            integral.

        References
        ----------
        .. [1] Linder, E. (2003). Exploring the Expansion History of the
               Universe. Phys. Rev. Lett., 90, 091301.
        r0   )r   r   )r~   Zln1pzr"   r"   r#   _w_integrandq  s    zFLRW._w_integrandc                    sh   t |}t|ttjfs>t fdd|D }td| S t jdt	|d d }td| S dS )a{  Evaluates the redshift dependence of the dark energy density.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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.
        c                    s&   g | ]}t  jd td| d  qS )r   r   )r   r   r   ).0redshiftr   r"   r#   
<listcomp>  s   z)FLRW.de_density_scale.<locals>.<listcomp>r1   r   r0   N)
r   
isinstancer   rg   ZgenericZarrayr   r   r   r   )r~   r   Zivalr"   r   r#   r     s    )zFLRW.de_density_scalec                 C   sj   | j r| jd| |  }n| j| j }t|d }t|d || | j | | j  | j	| 
|  S )a\  Function used to calculate H(z), the Hubble parameter.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        E : ndarray or float
            The redshift scaling of the Hubble constant.
            Returns `float` if the input is scalar.
            Defined such that :math:`H(z) = H_0 E(z)`.

        Notes
        -----
        It is not necessary to override this method, but if de_density_scale
        takes a particularly simple form, it may be advantageous to.
        r   r0   rB   )rc   rn   rt   ru   r   rg   r   rM   rz   ry   r   r~   r   ZOrzp1r"   r"   r#   efunc  s    "z
FLRW.efuncc                 C   sh   | j r| jd| |  }n| j| j }t|d }|d || | j | | j  | j| |  d S )a]  Inverse of ``efunc``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        E : ndarray or float
            The redshift scaling of the inverse Hubble constant.
            Returns `float` if the input is scalar.
        r   r0   rB         )	rc   rn   rt   ru   r   rM   rz   ry   r   r   r"   r"   r#   r{     s    zFLRW.inv_efuncc                 C   s   | j |g| jR  |d  S )a  Integrand of the lookback time (equation 30 of [1]_).

        Parameters
        ----------
        z : float
            Input redshift.

        Returns
        -------
        I : float
            The integrand for the lookback time.

        References
        ----------
        .. [1] Hogg, D. (1999). Distance measures in cosmology, section 11.
               arXiv e-prints, astro-ph/9905116.
        r0   )r|   r}   r   r"   r"   r#   _lookback_time_integrand_scalar  s    z$FLRW._lookback_time_integrand_scalarc                 C   s   t |}| ||d  S )a  Integrand of the lookback time (equation 30 of [1]_).

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        I : float or array
            The integrand for the lookback time.

        References
        ----------
        .. [1] Hogg, D. (1999). Distance measures in cosmology, section 11.
               arXiv e-prints, astro-ph/9905116.
        r0   r   r{   r   r"   r"   r#   lookback_time_integrand  s    zFLRW.lookback_time_integrandc                 C   s$   | j }|d d | j|g|R   S )a  Integrand of the absorption distance [1]_.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        X : float
            The integrand for the absorption distance.

        References
        ----------
        .. [1] Hogg, D. (1999). Distance measures in cosmology, section 11.
               arXiv e-prints, astro-ph/9905116.
        r0   rB   )r}   r|   )r~   r   r    r"   r"   r#   _abs_distance_integrand_scalar  s    z#FLRW._abs_distance_integrand_scalarc                 C   s   t |}|d d | | S )a  Integrand of the absorption distance [1]_.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        X : float or array
            The integrand for the absorption distance.

        References
        ----------
        .. [1] Hogg, D. (1999). Distance measures in cosmology, section 11.
               arXiv e-prints, astro-ph/9905116.
        r0   rB   r   r   r"   r"   r#   abs_distance_integrand&  s    zFLRW.abs_distance_integrandc                 C   s   | j | | S )aM  Hubble parameter (km/s/Mpc) at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        H : `~astropy.units.Quantity` ['frequency']
            Hubble parameter at each input redshift.
        )rP   r   r   r"   r"   r#   H;  s    zFLRW.Hc                 C   s   dt |d  S )a  Scale factor at redshift ``z``.

        The scale factor is defined as :math:`a = 1 / (1 + z)`.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        a : ndarray or float
            Scale factor at each input redshift.
            Returns `float` if the input is scalar.
        r0   )r   r   r"   r"   r#   scale_factorJ  s    zFLRW.scale_factorc                 C   s
   |  |S )a)  Lookback time in Gyr to redshift ``z``.

        The lookback time is the difference between the age of the Universe now
        and the age at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            Lookback time in Gyr to each input redshift.

        See Also
        --------
        z_at_value : Find the redshift corresponding to a lookback time.
        )_lookback_timer   r"   r"   r#   lookback_time\  s    zFLRW.lookback_timec                 C   s   | j | | S )a  Lookback time in Gyr to redshift ``z``.

        The lookback time is the difference between the age of the Universe now
        and the age at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            Lookback time in Gyr to each input redshift.
        )r]   _integral_lookback_timer   r"   r"   r#   r   r  s    zFLRW._lookback_timec                C   s   t | jd|d S )a  Lookback time to redshift ``z``. Value in units of Hubble time.

        The lookback time is the difference between the age of the Universe now
        and the age at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : float or ndarray
            Lookback time to each input redshift in Hubble time units.
            Returns `float` if input scalar, `~numpy.ndarray` otherwise.
        r   )r   r   r   r"   r"   r#   r     s    zFLRW._integral_lookback_timec                 C   s   |  |tj tjS )a  
        The lookback distance is the light travel time distance to a given
        redshift. It is simply c * lookback_time. It may be used to calculate
        the proper distance between two redshifts, e.g. for the mean free path
        to ionizing radiation.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Lookback distance in Mpc
        )r   rS   rT   rU   rV   rW   r   r"   r"   r#   lookback_distance  s    zFLRW.lookback_distancec                 C   s
   |  |S )a  Age of the universe in Gyr at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            The age of the universe in Gyr at each input redshift.

        See Also
        --------
        z_at_value : Find the redshift corresponding to an age.
        )_ager   r"   r"   r#   age  s    zFLRW.agec                 C   s   | j | | S )a  Age of the universe in Gyr at redshift ``z``.

        This internal function exists to be re-defined for optimizations.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            The age of the universe in Gyr at each input redshift.
        )r]   _integral_ager   r"   r"   r#   r     s    z	FLRW._agec                C   s   t | j|tjd S )aE  Age of the universe at redshift ``z``. Value in units of Hubble time.

        Calculated using explicit integration.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : float or ndarray
            The age of the universe at each input redshift in Hubble time units.
            Returns `float` if input scalar, `~numpy.ndarray` otherwise.

        See Also
        --------
        z_at_value : Find the redshift corresponding to an age.
        r   )r   r   rg   r   r   r"   r"   r#   r     s    zFLRW._integral_agec                 C   s   | j | |d  S )aV  Critical density in grams per cubic cm at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        rho : `~astropy.units.Quantity`
            Critical density in g/cm^3 at each input redshift.
        rB   )ra   r   r   r"   r"   r#   critical_density  s    zFLRW.critical_densityc                 C   s   |  d|S )a  Comoving line-of-sight distance in Mpc at a given redshift.

        The comoving distance along the line-of-sight between two objects
        remains constant with time for objects in the Hubble flow.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc to each input redshift.
        r   )_comoving_distance_z1z2r   r"   r"   r#   comoving_distance  s    zFLRW.comoving_distancec                 C   s   |  ||S )a$  
        Comoving line-of-sight distance in Mpc between objects at redshifts
        ``z1`` and ``z2``.

        The comoving distance along the line-of-sight between two objects
        remains constant with time for objects in the Hubble flow.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc between each input redshift.
        ) _integral_comoving_distance_z1z2r~   z1z2r"   r"   r#   r     s    zFLRW._comoving_distance_z1z2rB   )Zninc                C   s   t | j||| jdd S )a`  
        Comoving line-of-sight distance between objects at redshifts ``z1`` and
        ``z2``. Value in Mpc.

        The comoving distance along the line-of-sight between two objects
        remains constant with time for objects in the Hubble flow.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts.

        Returns
        -------
        d : float or ndarray
            Comoving distance in Mpc between each input redshift.
            Returns `float` if input scalar, `~numpy.ndarray` otherwise.
        )r    r   )r   r|   r}   r   r"   r"   r#   '_integral_comoving_distance_z1z2_scalar  s    z,FLRW._integral_comoving_distance_z1z2_scalarc                 C   s   | j | || S )a  
        Comoving line-of-sight distance in Mpc between objects at redshifts
        ``z1`` and ``z2``. The comoving distance along the line-of-sight
        between two objects remains constant with time for objects in the
        Hubble flow.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'] or array-like
            Input redshifts.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc between each input redshift.
        )rX   r   r   r"   r"   r#   r   2  s    z%FLRW._integral_comoving_distance_z1z2c                 C   s   |  d|S )a  Comoving transverse distance in Mpc at a given redshift.

        This value is the transverse comoving distance at redshift ``z``
        corresponding to an angular separation of 1 radian. This is the same as
        the comoving distance if :math:`\Omega_k` is zero (as in the current
        concordance Lambda-CDM model).

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving transverse distance in Mpc at each input redshift.

        Notes
        -----
        This quantity is also called the 'proper motion distance' in some texts.
        r   )"_comoving_transverse_distance_z1z2r   r"   r"   r#   comoving_transverse_distanceE  s    z!FLRW.comoving_transverse_distancec                 C   sx   | j }| ||}|dkr|S tt|}| j}|dkrV|| t||j |j  S || t||j |j  S dS )a	  Comoving transverse distance in Mpc between two redshifts.

        This value is the transverse comoving distance at redshift ``z2`` as
        seen from redshift ``z1`` corresponding to an angular separation of
        1 radian. This is the same as the comoving distance if :math:`\Omega_k`
        is zero (as in the current concordance Lambda-CDM model).

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving transverse distance in Mpc between input redshift.

        Notes
        -----
        This quantity is also called the 'proper motion distance' in some texts.
        r   N)	rz   r   r   absrX   rg   ZsinhrQ   r
   )r~   r   r   r   ZdcZsqrtOk0dhr"   r"   r#   r   ]  s    z'FLRW._comoving_transverse_distance_z1z2c                 C   s   t |}| ||d  S )a  Angular diameter distance in Mpc at a given redshift.

        This gives the proper (sometimes called 'physical') transverse
        distance corresponding to an angle of 1 radian for an object
        at redshift ``z`` ([1]_, [2]_, [3]_).

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Angular diameter distance in Mpc at each input redshift.

        References
        ----------
        .. [1] Weinberg, 1972, pp 420-424; Weedman, 1986, pp 421-424.
        .. [2] Weedman, D. (1986). Quasar astronomy, pp 65-67.
        .. [3] Peebles, P. (1993). Principles of Physical Cosmology, pp 325-327.
        r0   r   r   r   r"   r"   r#   angular_diameter_distance~  s    zFLRW.angular_diameter_distancec                 C   s   t |}|d | | S )a  Luminosity distance in Mpc at redshift ``z``.

        This is the distance to use when converting between the bolometric flux
        from an object at redshift ``z`` and its bolometric luminosity [1]_.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Luminosity distance in Mpc at each input redshift.

        See Also
        --------
        z_at_value : Find the redshift corresponding to a luminosity distance.

        References
        ----------
        .. [1] Weinberg, 1972, pp 420-424; Weedman, 1986, pp 60-62.
        r0   r   r   r"   r"   r#   luminosity_distance  s    zFLRW.luminosity_distancec                 C   sN   t |t | }}t||k r:td| d| dt | |||d  S )a  Angular diameter distance between objects at 2 redshifts.

        Useful for gravitational lensing, for example computing the angular
        diameter distance between a lensed galaxy and the foreground lens.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts. For most practical applications such as
            gravitational lensing, ``z2`` should be larger than ``z1``. The
            method will work for ``z2 < z1``; however, this will return
            negative distances.

        Returns
        -------
        d : `~astropy.units.Quantity`
            The angular diameter distance between each input redshift pair.
            Returns scalar if input is scalar, array else-wise.
        zSecond redshift(s) z2 (z%) is less than first redshift(s) z1 (z).r0   )r   rg   anywarningswarnr   r   r   r"   r"   r#   angular_diameter_distance_z1z2  s    z#FLRW.angular_diameter_distance_z1z2c                C   s   t | jd|d S )a6  Absorption distance at redshift ``z``.

        This is used to calculate the number of objects with some cross section
        of absorption and number density intersecting a sightline per unit
        redshift path ([1]_, [2]_).

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : float or ndarray
            Absorption distance (dimensionless) at each input redshift.
            Returns `float` if input scalar, `~numpy.ndarray` otherwise.

        References
        ----------
        .. [1] Hogg, D. (1999). Distance measures in cosmology, section 11.
               arXiv e-prints, astro-ph/9905116.
        .. [2] Bahcall, John N. and Peebles, P.J.E. 1969, ApJ, 156L, 7B
        r   )r   r   r   r"   r"   r#   absorption_distance  s    zFLRW.absorption_distancec                 C   s,   dt t| |j d }t|tjS )aF  Distance modulus at redshift ``z``.

        The distance modulus is defined as the (apparent magnitude - absolute
        magnitude) for an object at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        distmod : `~astropy.units.Quantity` ['length']
            Distance modulus at each input redshift, in magnitudes.

        See Also
        --------
        z_at_value : Find the redshift corresponding to a distance modulus.
        g      @g      9@)rg   Zlog10r   r   rQ   rV   rZ   Zmag)r~   r   valr"   r"   r#   distmod  s    zFLRW.distmodc                 C   s   | j }|dkr$dt | |d  S | jj}| |j}dt |d  d|  tjd  }|| t	d||| d    }t	t
|| | }|dkr||dt	t
| t|   S ||dt	t
| t|   S d	S )
a=  Comoving volume in cubic Mpc at redshift ``z``.

        This is the volume of the universe encompassed by redshifts less than
        ``z``. For the case of :math:`\Omega_k = 0` it is a sphere of radius
        `comoving_distance` but it is less intuitive if :math:`\Omega_k` is not.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        V : `~astropy.units.Quantity`
            Comoving volume in :math:`Mpc^3` at each input redshift.
        r   gUUUUUU?r1   g      @       @r   rB   r0   N)rz   r	   r   rX   rQ   r   rV   rW   rg   r   r   arcsinharcsin)r~   r   r   r   dmZterm1Zterm2Zterm3r"   r"   r#   comoving_volume  s    """zFLRW.comoving_volumec                 C   s(   |  |}| j|d  | |tj>  S )a  Differential comoving volume at redshift z.

        Useful for calculating the effective comoving volume.
        For example, allows for integration over a comoving volume that has a
        sensitivity function that changes with redshift. The total comoving
        volume is given by integrating ``differential_comoving_volume`` to
        redshift ``z`` and multiplying by a solid angle.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        dV : `~astropy.units.Quantity`
            Differential comoving volume per redshift per steradian at each
            input redshift.
        r   )r   rX   r   rV   Z	steradian)r~   r   r   r"   r"   r#   differential_comoving_volume#  s    
z!FLRW.differential_comoving_volumec                 C   s   |  |tjt tj S )a  
        Separation in transverse comoving kpc corresponding to an arcminute at
        redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            The distance in comoving kpc corresponding to an arcmin at each
            input redshift.
        )r   rU   rV   kpcarcmin_in_radiansarcminr   r"   r"   r#   kpc_comoving_per_arcmin:  s
    zFLRW.kpc_comoving_per_arcminc                 C   s   |  |tjt tj S )a  
        Separation in transverse proper kpc corresponding to an arcminute at
        redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            The distance in proper kpc corresponding to an arcmin at each input
            redshift.
        )r   rU   rV   r   r   r   r   r"   r"   r#   kpc_proper_per_arcminM  s
    zFLRW.kpc_proper_per_arcminc                 C   s   t j| |t jt  S )a  
        Angular separation in arcsec corresponding to a comoving kpc at
        redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        theta : `~astropy.units.Quantity` ['angle']
            The angular separation in arcsec corresponding to a comoving kpc at
            each input redshift.
        )rV   arcsecr   rU   r   arcsec_in_radiansr   r"   r"   r#   arcsec_per_kpc_comoving`  s    zFLRW.arcsec_per_kpc_comovingc                 C   s   t j| |t jt  S )a  
        Angular separation in arcsec corresponding to a proper kpc at redshift
        ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        theta : `~astropy.units.Quantity` ['angle']
            The angular separation in arcsec corresponding to a proper kpc at
            each input redshift.
        )rV   r   r   rU   r   r   r   r"   r"   r#   arcsec_per_kpc_propers  s    zFLRW.arcsec_per_kpc_proper)N__name__
__module____qualname____doc__r   rF   rG   rH   rI   rJ   rV   Zmass_energyrK   rL   rv   r;   rE   Z	validatorpropertyr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rt   r   r   r   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r"   r"   r   r#   r%   9   s   ;

 











B2


!
 r%   c                       sD   e Zd ZdZedddZ fddZ fddZ fd	d
Z  Z	S )r.   a  
    Mixin class for flat FLRW cosmologies. Do NOT instantiate directly.
    Must precede the base class in the multiple-inheritance so that this
    mixin's ``__init__`` proceeds the base class'.
    Note that all instances of ``FlatFLRWMixin`` are flat, but not all
    flat cosmologies are instances of ``FlatFLRWMixin``. As example,
    ``LambdaCDM`` **may** be flat (for the a specific set of parameter values),
    but ``FlatLambdaCDM`` **will** be flat.
    r8   T)r4   Zderivedc                    s"   t    d| jjv rtdd S )NrH   z>subclasses of `FlatFLRWMixin` cannot have `Ode0` in `__init__`)rD   __init_subclass__Z_init_signature
parameters	TypeError)clsr   r"   r#   r     s    
zFlatFLRWMixin.__init_subclass__c                    s4   t  j|i | d| j | j | j | _d| _d S )Nr0   r=   )rD   rE   rM   rn   ru   ry   rz   )r~   r    kwr   r"   r#   rE     s    zFlatFLRWMixin.__init__c                    s|   t  trt  S dd j dd D } j|vr@tS tjt jkovt	 fddjD ov j
dk}|S )a>  flat-FLRW equivalence. Use ``.is_equivalent()`` for actual check!

        Parameters
        ----------
        other : `~astropy.cosmology.FLRW` subclass instance
            The object in which to compare.

        Returns
        -------
        bool or `NotImplemented`
            `True` if 'other' is of the same class / non-flat class (e.g.
            ``FlatLambdaCDM`` and ``LambdaCDM``) has matching parameters
            and parameter values. `False` if 'other' is of the same class but
            has different parameters. `NotImplemented` otherwise.
        c                 S   s"   g | ]}t |tr|tur|qS r"   )
issubclassr%   )r   rT   r"   r"   r#   r     s   z+FlatFLRWMixin.__equiv__.<locals>.<listcomp>r   Nc                 3   s(   | ] }t t|t |kV  qd S )N)rg   allgetattr)r   r   otherr~   r"   r#   	<genexpr>  s   z*FlatFLRWMixin.__equiv__.<locals>.<genexpr>r=   )r   r.   rD   	__equiv__r   mroNotImplementedsetZ__all_parameters__r   r   )r~   r   Zcomparable_classesZ	params_eqr   r   r#   r     s    

zFlatFLRWMixin.__equiv__)
r   r   r   r   r   rH   r   rE   r   r   r"   r"   r   r#   r.     s   
r.   c                       s   e Zd ZdZdej ddej dfddd fddZdd	 Zd
d Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Z  ZS )(r&   aK  FLRW cosmology with a cosmological constant and curvature.

    This has no additional attributes beyond those of FLRW.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0.  If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    Ode0 : float
        Omega dark energy: density of the cosmological constant in units of
        the critical density at z=0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import LambdaCDM
    >>> cosmo = LambdaCDM(H0=70, Om0=0.3, Ode0=0.7)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)
    r=   r>   Nr?   c          
         s   t  j|||||||||	d	 | jjdkrbtj| _| j| j| j	f| _
| j	dkrX|   q| j| _nV| jstj| _| j| j| j	| j| j f| _
n*tj| _| j| j| j	| j| j| j| jf| _
d S N	rF   rG   rH   rI   rJ   rK   rL   r@   rA   r   )rD   rE   rd   rQ   r   Zlcdm_inv_efunc_norelr|   rM   ry   rz   r}   _optimize_flat_norad _elliptic_comoving_distance_z1z2r   rc   Zlcdm_inv_efunc_nomnurn   ru   Zlcdm_inv_efuncre   rf   rs   )
r~   rF   rG   rH   rI   rJ   rK   rL   r@   rA   r   r"   r#   rE     s(    



zLambdaCDM.__init__c                 C   sd   | j dkr$| j| _| j| _| j| _n<| j dkrH| j| _| j| _| j	| _n| j
| _| j| _| j| _dS )z>Set optimizations for flat LCDM cosmologies with no radiation.r   r   N)rM   _dS_comoving_distance_z1z2r   _dS_ager   _dS_lookback_timer   _EdS_comoving_distance_z1z2_EdS_age_EdS_lookback_time&_hypergeometric_comoving_distance_z1z2	_flat_age_flat_lookback_timer   r"   r"   r#   r     s    



zLambdaCDM._optimize_flat_noradc                 C   s&   t |}dt|dr t|jnd S )a  Returns dark energy equation of state at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        w : ndarray or float
            The dark energy equation of state.
            Returns `float` if the input is scalar.

        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. Here this is :math:`w(z) = -1`.
              r   r0   r   r   rg   rh   r   r   r"   r"   r#   r   /  s    zLambdaCDM.wc                 C   s"   t |}t|drt|jS dS )a*  Evaluates the redshift dependence of the dark energy density.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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 in this case is given by :math:`I = 1`.
        r   r0   r   r   r"   r"   r#   r   G  s    zLambdaCDM.de_density_scalec              
   C   sj  zt ||\}}W n. tyB } ztd|W Y d}~n
d}~0 0 | jdksb| jdksb| jdkrn| ||S d| jd  | j | jd  }|t| }|dk sd|k rZdd }t||d	  t	||d   d
}d||d	|    d }t	|d| d  }	d	t	|	 }
d|	 |d	d|    d|	  }|| j| j|||	|}|| j| j|||	|}nd|k r.|dk r.| j| jkr.dd }t
td	| d }t	dttd	| d  }d
d| |  }d
dd|   }d
d| |  }dt	||  }
|| ||  }|| j| j|||}|| j| j|||}n| ||S | jt	t| j }||
 t||t||  S )a  Comoving transverse distance in Mpc between two redshifts.

        This value is the transverse comoving distance at redshift ``z``
        corresponding to an angular separation of 1 radian. This is the same as
        the comoving distance if :math:`\Omega_k` is zero.

        For :math:`\Omega_{rad} = 0` the comoving distance can be directly
        calculated as an elliptic integral [1]_.

        Not valid or appropriate for flat cosmologies (Ok0=0).

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc between each input redshift.

        References
        ----------
        .. [1] Kantowski, R., Kao, J., & Thomas, R. (2000). Distance-Redshift
               in Inhomogeneous FLRW. arXiv e-prints, astro-ph/0002334.
        z1 and z2 have different shapesNr   g      +rB   r1   c                 S   sF   t |d |  t| ||  | |d |  t| ||  |  S Nr0   )rg   Zarccosr   )rG   r   kappay1Ar   r"   r"   r#   phi_z  s    "z9LambdaCDM._elliptic_comoving_distance_z1z2.<locals>.phi_zr   UUUUUU?r   r3   c                 S   s,   t t || |d |  t| |  S r  )rg   r   r   r   )rG   r   r  y2r   r"   r"   r#   r    s    )rg   broadcast_arraysrj   rM   ry   rz   r   r   powr   r   r   r
   rX   r   )r~   r   r   ebr  r  Zv_kr  r  r_   Zk2Zphi_z1Zphi_z2ZybZycr  Zy3	prefactorr"   r"   r#   r   ]  s>     " "z*LambdaCDM._elliptic_comoving_distance_z1z2c              
   C   sR   zt ||\}}W n. tyB } ztd|W Y d}~n
d}~0 0 | j||  S )a  
        Comoving line-of-sight distance in Mpc between objects at redshifts
        ``z1`` and ``z2`` in a flat, :math:`\Omega_{\Lambda}=1` cosmology
        (de Sitter).

        The comoving distance along the line-of-sight between two objects
        remains constant with time for objects in the Hubble flow.

        The de Sitter case has an analytic solution.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts. Must be 1D or scalar.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc between each input redshift.
        r  Nrg   r	  rj   rX   )r~   r   r   r  r"   r"   r#   r     s
     z$LambdaCDM._dS_comoving_distance_z1z2c              
   C   sj   zt ||\}}W n. tyB } ztd|W Y d}~n
d}~0 0 d| j }||d d |d d   S )a  
        Comoving line-of-sight distance in Mpc between objects at redshifts
        ``z1`` and ``z2`` in a flat, :math:`\Omega_M=1` cosmology
        (Einstein - de Sitter).

        The comoving distance along the line-of-sight between two objects
        remains constant with time for objects in the Hubble flow.

        For :math:`\Omega_M=1`, :math:`\Omega_{rad}=0` the comoving distance
        has an analytic solution.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts. Must be 1D or scalar.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc between each input redshift.
        r  NrB   r0   r   r  )r~   r   r   r  r  r"   r"   r#   r     s     
z%LambdaCDM._EdS_comoving_distance_z1z2c              
   C   s   zt ||\}}W n. tyB } ztd|W Y d}~n
d}~0 0 d| j | j d }| jt || j  }|| ||d  | ||d    S )a  
        Comoving line-of-sight distance in Mpc between objects at redshifts
        ``z1`` and ``z2``.

        The comoving distance along the line-of-sight between two objects
        remains constant with time for objects in the Hubble flow.

        For :math:`\Omega_{rad} = 0` the comoving distance can be directly
        calculated as a hypergeometric function [1]_.

        Parameters
        ----------
        z1, z2 : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshifts.

        Returns
        -------
        d : `~astropy.units.Quantity` ['length']
            Comoving distance in Mpc between each input redshift.

        References
        ----------
        .. [1] Baes, M., Camps, P., & Van De Putte, D. (2017). Analytical
               expressions and numerical evaluation of the luminosity distance
               in a flat cosmology. MNRAS, 468(1), 927-930.
        r  Nr   r  r0   )rg   r	  rj   rM   rX   r   _T_hypergeometric)r~   r   r   r  sr  r"   r"   r#   r     s     z0LambdaCDM._hypergeometric_comoving_distance_z1z2c                 C   s"   dt | tddd|d   S )a  Compute value using Gauss Hypergeometric function 2F1.

        .. math::

           T(x) = 2 \sqrt(x) _{2}F_{1}\left(\frac{1}{6}, \frac{1}{2};
                                            \frac{7}{6}; -x^3 \right)

        Notes
        -----
        The :func:`scipy.special.hyp2f1` code already implements the
        hypergeometric transformation suggested by Baes et al. [1]_ for use in
        actual numerical evaulations.

        References
        ----------
        .. [1] Baes, M., Camps, P., & Van De Putte, D. (2017). Analytical
           expressions and numerical evaluation of the luminosity distance
           in a flat cosmology. MNRAS, 468(1), 927-930.
        rB   gUUUUUU?g      ?g?r1   )rg   r   r   )r~   xr"   r"   r#   r    s    zLambdaCDM._T_hypergeometricc                 C   s(   t |trtntj|ttd}| j| S )a  Age of the universe in Gyr at redshift ``z``.

        The age of a de Sitter Universe is infinite.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            The age of the universe in Gyr at each input redshift.
        )Zdtype)r   r   r   rg   Z	full_liker9   r]   )r~   r   tr"   r"   r#   r     s    zLambdaCDM._dS_agec                 C   s   d| j  t|d d  S )  Age of the universe in Gyr at redshift ``z``.

        For :math:`\Omega_{rad} = 0` (:math:`T_{CMB} = 0`; massless neutrinos)
        the age can be directly calculated as an elliptic integral [1]_.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            The age of the universe in Gyr at each input redshift.

        References
        ----------
        .. [1] Thomas, R., & Kantowski, R. (2000). Age-redshift relation for
               standard cosmology. PRD, 62(10), 103507.
        UUUUUU?r0   g      )r]   r   r   r"   r"   r#   r   /  s    zLambdaCDM._EdS_agec                 C   sV   d| j  tjd| j  }ttjd| j d d t|d d  }|| jS )r  r  r   y                r0   r1   )r]   rg   Zemathr   rM   r   r   real)r~   r   r  argr"   r"   r#   r   F  s    0zLambdaCDM._flat_agec                 C   s   |  d|  | S )a  Lookback time in Gyr to redshift ``z``.

        The lookback time is the difference between the age of the Universe now
        and the age at redshift ``z``.

        For :math:`\Omega_{rad} = 0` (:math:`T_{CMB} = 0`; massless neutrinos)
        the age can be directly calculated as an elliptic integral.
        The lookback time is here calculated based on the ``age(0) - age(z)``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            Lookback time in Gyr to each input redshift.
        r   )r   r   r"   r"   r#   r   a  s    zLambdaCDM._EdS_lookback_timec                 C   s   | j tt|d  S )a  Lookback time in Gyr to redshift ``z``.

        The lookback time is the difference between the age of the Universe now
        and the age at redshift ``z``.

        For :math:`\Omega_{rad} = 0` (:math:`T_{CMB} = 0`; massless neutrinos)
        the age can be directly calculated.

        .. math::

           a = exp(H * t) \  \text{where t=0 at z=0}

           t = (1/H) (ln 1 - ln a) = (1/H) (0 - ln (1/(1+z))) = (1/H) ln(1+z)

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            Lookback time in Gyr to each input redshift.
        r0   )r]   rg   r   r   r   r"   r"   r#   r   w  s    zLambdaCDM._dS_lookback_timec                 C   s   |  d|  | S )a  Lookback time in Gyr to redshift ``z``.

        The lookback time is the difference between the age of the Universe now
        and the age at redshift ``z``.

        For :math:`\Omega_{rad} = 0` (:math:`T_{CMB} = 0`; massless neutrinos)
        the age can be directly calculated.
        The lookback time is here calculated based on the ``age(0) - age(z)``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        t : `~astropy.units.Quantity` ['time']
            Lookback time in Gyr to each input redshift.
        r   )r   r   r"   r"   r#   r     s    zLambdaCDM._flat_lookback_timec                 C   s`   | j r| jd| |  }n| j| j }t|d }t|d || | j | | j  | j	 S )  Function used to calculate H(z), the Hubble parameter.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        E : ndarray or float
            The redshift scaling of the Hubble constant.
            Returns `float` if the input is scalar.
            Defined such that :math:`H(z) = H_0 E(z)`.
        r0   rB   )
rc   rn   rt   ru   r   rg   r   rM   rz   ry   r   r"   r"   r#   r     s
    zLambdaCDM.efuncc                 C   s^   | j r| jd| |  }n| j| j }t|d }|d || | j | | j  | j d S )  Function used to calculate :math:`\frac{1}{H_z}`.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        E : ndarray or float
            The inverse redshift scaling of the Hubble constant.
            Returns `float` if the input is scalar.
            Defined such that :math:`H_z = H_0 / E`.
        r   r0   rB   r   )rc   rn   rt   ru   r   rM   rz   ry   r   r"   r"   r#   r{     s
    zLambdaCDM.inv_efunc)r   r   r   r   rV   rv   r;   rE   r   r   r   r   r   r   r   r  r   r   r   r   r   r   r   r{   r   r"   r"   r   r#   r&     s,   8J&r&   c                       sN   e Zd ZdZdej ddej dfddd fddZdd	 Zd
d Z	  Z
S )r'   a  FLRW cosmology with a cosmological constant and no curvature.

    This has no additional attributes beyond those of FLRW.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import FlatLambdaCDM
    >>> cosmo = FlatLambdaCDM(H0=70, Om0=0.3)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)
    r=   r>   Nr?   c          	         s   t  j||d||||||d	 | jjdkrJtj| _| j| jf| _	| 
  nN| jsrtj| _| j| j| j| j f| _	n&tj| _| j| j| j| j| j| jf| _	d S )Nr=   r   r   )rD   rE   rd   rQ   r   Zflcdm_inv_efunc_norelr|   rM   ry   r}   r   rc   Zflcdm_inv_efunc_nomnurn   ru   Zflcdm_inv_efuncre   rf   rs   )	r~   rF   rG   rI   rJ   rK   rL   r@   rA   r   r"   r#   rE     s$    

zFlatLambdaCDM.__init__c                 C   sV   | j r| jd| |  }n| j| j }t|d }t|d || | j  | j S )r  r   r0   r1   )	rc   rn   rt   ru   r   rg   r   rM   ry   r   r"   r"   r#   r   '  s
    zFlatLambdaCDM.efuncc                 C   sT   | j r| jd| |  }n| j| j }t|d }|d || | j  | j d S )r  r0   r1   r   )rc   rn   rt   ru   r   rM   ry   r   r"   r"   r#   r{   @  s
    zFlatLambdaCDM.inv_efuncr   r   r   r   rV   rv   r;   rE   r   r{   r   r"   r"   r   r#   r'     s   4r'   c                       sl   e Zd ZdZedddZddej ddej dfddd	 fd
dZ	dd Z
dd Zdd Zdd Z  ZS )r(   a	  
    FLRW cosmology with a constant dark energy equation of state and curvature.

    This has one additional attribute beyond those of FLRW.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    Ode0 : float
        Omega dark energy: density of dark energy in units of the critical
        density at z=0.

    w0 : float, optional
        Dark energy equation of state at all redshifts. This is
        pressure/density for dark energy in units where c=1. A cosmological
        constant has w0=-1.0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import wCDM
    >>> cosmo = wCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)
    zDark energy equation of state.r9   r7   r   r=   r>   Nr?   c	                   s   t  j||||||||	|
d	 || _| jjdkrPtj| _| j| j	| j
| jf| _n^| jstj| _| j| j	| j
| j| j | jf| _n.tj| _| j| j	| j
| j| j| j| j| jf| _d S r   )rD   rE   w0rd   rQ   r   Zwcdm_inv_efunc_norelr|   rM   ry   rz   _w0r}   rc   Zwcdm_inv_efunc_nomnurn   ru   Zwcdm_inv_efuncre   rf   rs   )r~   rF   rG   rH   r  rI   rJ   rK   rL   r@   rA   r   r"   r#   rE     s*    
zwCDM.__init__c                 C   s(   t |}| jt|dr"t|jnd S )a  Returns dark energy equation of state at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        w : ndarray or float
            The dark energy equation of state
            Returns `float` if the input is scalar.

        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. Here this is :math:`w(z) = w_0`.
        r   r0   )r   r  r   rg   rh   r   r   r"   r"   r#   r     s    zwCDM.wc                 C   s   t |d dd| j   S )aZ  Evaluates the redshift dependence of the dark energy density.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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 in this case is given by
        :math:`I = \left(1 + z\right)^{3\left(1 + w_0\right)}`
        r0         @)r   r  r   r"   r"   r#   r     s    zwCDM.de_density_scalec                 C   sr   | j r| jd| |  }n| j| j }t|d }t|d || | j | | j  | j	|dd| j
     S )r  r0   rB   r  )rc   rn   rt   ru   r   rg   r   rM   rz   ry   r  r   r"   r"   r#   r     s    "z
wCDM.efuncc                 C   sp   | j r| jd| |  }n| j| j }t|d }|d || | j | | j  | j|dd| j     d S )r  r0   rB   r  r   )	rc   rn   rt   ru   r   rM   rz   ry   r  r   r"   r"   r#   r{     s    zwCDM.inv_efunc)r   r   r   r   r   r  rV   rv   r;   rE   r   r   r   r{   r   r"   r"   r   r#   r(   W  s   >
r(   c                       sP   e Zd ZdZddej ddej dfddd fddZd	d
 Zdd Z	  Z
S )r)   a  
    FLRW cosmology with a constant dark energy equation of state and no spatial
    curvature.

    This has one additional attribute beyond those of FLRW.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    w0 : float, optional
        Dark energy equation of state at all redshifts. This is
        pressure/density for dark energy in units where c=1. A cosmological
        constant has w0=-1.0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import FlatwCDM
    >>> cosmo = FlatwCDM(H0=70, Om0=0.3, w0=-0.9)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)
    r   r=   r>   Nr?   c          
         s   t  j||d|||||||	d
 | jjdkrHtj| _| j| j| j	f| _
nV| jsttj| _| j| j| j| j | j	f| _
n*tj| _| j| j| j| j| j| j| j	f| _
d S )Nr=   )
rF   rG   rH   r  rI   rJ   rK   rL   r@   rA   r   )rD   rE   rd   rQ   r   Zfwcdm_inv_efunc_norelr|   rM   ry   r  r}   rc   Zfwcdm_inv_efunc_nomnurn   ru   Zfwcdm_inv_efuncre   rf   rs   )
r~   rF   rG   r  rI   rJ   rK   rL   r@   rA   r   r"   r#   rE   K	  s(    

zFlatwCDM.__init__c                 C   sh   | j r| jd| |  }n| j| j }t|d }t|d || | j  | j|dd| j	     S )r  r0   r1   r  r   )
rc   rn   rt   ru   r   rg   r   rM   ry   r  r   r"   r"   r#   r   b	  s    zFlatwCDM.efuncc                 C   sf   | j r| jd| |  }n| j| j }t|d }|d || | j  | j|dd| j     d S )a  Function used to calculate :math:`\frac{1}{H_z}`.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        E : ndarray or float
            The inverse redshift scaling of the Hubble constant.
            Returns `float` if the input is scalar.
            Defined such that :math:`H(z) = H_0 E(z)`.
        r0   r1   r  r   )rc   rn   rt   ru   r   rM   ry   r  r   r"   r"   r#   r{   z	  s    zFlatwCDM.inv_efuncr  r"   r"   r   r#   r)   	  s   ;r)   c                       sj   e Zd ZdZedddZedddZdddej ddej	 d	fd	d	d
 fddZ
dd Zdd Z  ZS )r*   ao  FLRW cosmology with a CPL dark energy equation of state and curvature.

    The equation for the dark energy equation of state uses the
    CPL form as described in Chevallier & Polarski [1]_ and Linder [2]_:
    :math:`w(z) = w_0 + w_a (1-a) = w_0 + w_a z / (1+z)`.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    Ode0 : float
        Omega dark energy: density of dark energy in units of the critical
        density at z=0.

    w0 : float, optional
        Dark energy equation of state at z=0 (a=1). This is pressure/density
        for dark energy in units where c=1.

    wa : float, optional
        Negative derivative of the dark energy equation of state with respect
        to the scale factor. A cosmological constant has w0=-1.0 and wa=0.0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import w0waCDM
    >>> cosmo = w0waCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9, wa=0.2)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)

    References
    ----------
    .. [1] Chevallier, M., & Polarski, D. (2001). Accelerating Universes with
           Scaling Dark Matter. International Journal of Modern Physics D,
           10(2), 213-223.
    .. [2] Linder, E. (2003). Exploring the Expansion History of the
           Universe. Phys. Rev. Lett., 90, 091301.
    %Dark energy equation of state at z=0.r9   r7   >Negative derivative of dark energy equation of state w.r.t. a.r   r=   r>   Nr?   c
                   s   t  j|||||||	|
|d	 || _|| _| jjdkrZtj| _| j	| j
| j| j| jf| _nf| jstj| _| j	| j
| j| j| j | j| jf| _n2tj| _| j	| j
| j| j| j| j| j| j| jf	| _d S r   )rD   rE   r  ward   rQ   r   Zw0wacdm_inv_efunc_norelr|   rM   ry   rz   r  _war}   rc   Zw0wacdm_inv_efunc_nomnurn   ru   Zw0wacdm_inv_efuncre   rf   rs   )r~   rF   rG   rH   r  r  rI   rJ   rK   rL   r@   rA   r   r"   r#   rE   	  s.    
zw0waCDM.__init__c                 C   s    t |}| j| j| |d   S )a  Returns dark energy equation of state at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        w : ndarray or float
            The dark energy equation of state
            Returns `float` if the input is scalar.

        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. Here this is
        :math:`w(z) = w_0 + w_a (1 - a) = w_0 + w_a \frac{z}{1+z}`.
        r0   )r   r  r   r   r"   r"   r#   r   	  s    z	w0waCDM.wc                 C   s@   t |}|d }|dd| j | j   td| j | |  S )a  Evaluates the redshift dependence of the dark energy density.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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 in this case is given by

        .. math::

           I = \left(1 + z\right)^{3 \left(1 + w_0 + w_a\right)}
                     \exp \left(-3 w_a \frac{z}{1+z}\right)
        r0   r1   r   )r   r  r   rg   r   r~   r   r   r"   r"   r#   r   
  s    zw0waCDM.de_density_scale)r   r   r   r   r   r  r  rV   rv   r;   rE   r   r   r   r"   r"   r   r#   r*   	  s   J
r*   c                       sB   e Zd ZdZdddej ddej dfddd fddZ  ZS )	r+   a
  FLRW cosmology with a CPL dark energy equation of state and no
    curvature.

    The equation for the dark energy equation of state uses the CPL form as
    described in Chevallier & Polarski [1]_ and Linder [2]_:
    :math:`w(z) = w_0 + w_a (1-a) = w_0 + w_a z / (1+z)`.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    w0 : float, optional
        Dark energy equation of state at z=0 (a=1). This is pressure/density
        for dark energy in units where c=1.

    wa : float, optional
        Negative derivative of the dark energy equation of state with respect
        to the scale factor. A cosmological constant has w0=-1.0 and wa=0.0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import Flatw0waCDM
    >>> cosmo = Flatw0waCDM(H0=70, Om0=0.3, w0=-0.9, wa=0.2)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)

    References
    ----------
    .. [1] Chevallier, M., & Polarski, D. (2001). Accelerating Universes with
           Scaling Dark Matter. International Journal of Modern Physics D,
           10(2), 213-223.
    .. [2] Linder, E. (2003). Exploring the Expansion History of the
           Universe. Phys. Rev. Lett., 90, 091301.
    r   r=   r>   Nr?   c	                   s   t  j||d|||||||	|
d | jjdkrNtj| _| j| j| j	| j
f| _n^| js~tj| _| j| j| j| j | j	| j
f| _n.tj| _| j| j| j| j| j| j| j	| j
f| _d S )Nr=   )rF   rG   rH   r  r  rI   rJ   rK   rL   r@   rA   r   )rD   rE   rd   rQ   r   Zfw0wacdm_inv_efunc_norelr|   rM   ry   r  r   r}   rc   Zfw0wacdm_inv_efunc_nomnurn   ru   Zfw0wacdm_inv_efuncre   rf   rs   )r~   rF   rG   r  r  rI   rJ   rK   rL   r@   rA   r   r"   r#   rE   z
  s*    

zFlatw0waCDM.__init__)	r   r   r   r   rV   rv   r;   rE   r   r"   r"   r   r#   r+   2
  s   G
r+   c                       s   e Zd ZdZedddZedddZedejdZ	dd	d	ej d	e
j d
d	e
j dfddd fddZdd Zdd Z  ZS )r,   a  
    FLRW cosmology with a CPL dark energy equation of state, a pivot redshift,
    and curvature.

    The equation for the dark energy equation of state uses the CPL form as
    described in Chevallier & Polarski [1]_ and Linder [2]_, but modified to
    have a pivot redshift as in the findings of the Dark Energy Task Force
    [3]_: :math:`w(a) = w_p + w_a (a_p - a) = w_p + w_a( 1/(1+zp) - 1/(1+z) )`.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    Ode0 : float
        Omega dark energy: density of dark energy in units of the critical
        density at z=0.

    wp : float, optional
        Dark energy equation of state at the pivot redshift zp. This is
        pressure/density for dark energy in units where c=1.

    wa : float, optional
        Negative derivative of the dark energy equation of state with respect
        to the scale factor. A cosmological constant has wp=-1.0 and wa=0.0.

    zp : float or quantity-like ['redshift'], optional
        Pivot redshift -- the redshift where w(z) = wp

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import wpwaCDM
    >>> cosmo = wpwaCDM(H0=70, Om0=0.3, Ode0=0.7, wp=-0.9, wa=0.2, zp=0.4)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)

    References
    ----------
    .. [1] Chevallier, M., & Polarski, D. (2001). Accelerating Universes with
           Scaling Dark Matter. International Journal of Modern Physics D,
           10(2), 213-223.
    .. [2] Linder, E. (2003). Exploring the Expansion History of the
           Universe. Phys. Rev. Lett., 90, 091301.
    .. [3] Albrecht, A., Amendola, L., Bernstein, G., Clowe, D., Eisenstein,
           D., Guzzo, L., Hirata, C., Huterer, D., Kirshner, R., Kolb, E., &
           Nichol, R. (2009). Findings of the Joint Dark Energy Mission Figure
           of Merit Science Working Group. arXiv e-prints, arXiv:0901.0721.
    z7Dark energy equation of state at the pivot redshift zp.r9   r7   r  z$The pivot redshift, where w(z) = wp.)r4   r5   r   r=   r>   Nr?   c                   s   t  j||||||	|
||d	 || _|| _|| _dd| jj  }| jjdkrrtj	| _
| j| j| j| j|| jf| _nj| jstj| _
| j| j| j| j| j | j|| jf| _n4tj| _
| j| j| j| j| j| j| j| j|| jf
| _d S )Nr   r0   r   )rD   rE   wpr  zp_zprQ   rd   r   Zwpwacdm_inv_efunc_norelr|   rM   ry   rz   _wpr   r}   rc   Zwpwacdm_inv_efunc_nomnurn   ru   Zwpwacdm_inv_efuncre   rf   rs   )r~   rF   rG   rH   r#  r  r$  rI   rJ   rK   rL   r@   rA   apivr   r"   r#   rE   
  s2    


zwpwaCDM.__init__c                 C   s0   dd| j j  }| j| j|dt|d     S )a  Returns dark energy equation of state at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        w : ndarray or float
            The dark energy equation of state
            Returns `float` if the input is scalar.

        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. Here this is :math:`w(z) = w_p + w_a (a_p - a)` where
        :math:`a = 1/1+z` and :math:`a_p = 1 / 1 + z_p`.
        r0   )r%  rQ   r&  r   r   )r~   r   r'  r"   r"   r#   r   
  s    z	wpwaCDM.wc                 C   sT   t |}|d }dd| jj  }|dd| j || j    td| j | |  S )a  Evaluates the redshift dependence of the dark energy density.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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 in this case is given by

        .. math::

           a_p = \frac{1}{1 + z_p}

           I = \left(1 + z\right)^{3 \left(1 + w_p + a_p w_a\right)}
                     \exp \left(-3 w_a \frac{z}{1+z}\right)
        r0   r        )r   r%  rQ   r&  r   rg   r   )r~   r   r   r'  r"   r"   r#   r   #  s    zwpwaCDM.de_density_scale)r   r   r   r   r   r#  r  cur   r$  rV   rv   r;   rE   r   r   r   r"   r"   r   r#   r,   
  s   Tr,   c                       sj   e Zd ZdZedddZedddZdddej ddej	 d	fd	d	d
 fddZ
dd Zdd Z  ZS )r-   a	  
    FLRW cosmology with a variable dark energy equation of state and curvature.

    The equation for the dark energy equation of state uses the simple form:
    :math:`w(z) = w_0 + w_z z`.

    This form is not recommended for z > 1.

    Parameters
    ----------
    H0 : float or scalar quantity-like ['frequency']
        Hubble constant at z = 0. If a float, must be in [km/sec/Mpc].

    Om0 : float
        Omega matter: density of non-relativistic matter in units of the
        critical density at z=0.

    Ode0 : float
        Omega dark energy: density of dark energy in units of the critical
        density at z=0.

    w0 : float, optional
        Dark energy equation of state at z=0. This is pressure/density for
        dark energy in units where c=1.

    wz : float, optional
        Derivative of the dark energy equation of state with respect to z.
        A cosmological constant has w0=-1.0 and wz=0.0.

    Tcmb0 : float or scalar quantity-like ['temperature'], optional
        Temperature of the CMB z=0. If a float, must be in [K]. Default: 0 [K].
        Setting this to zero will turn off both photons and neutrinos
        (even massive ones).

    Neff : float, optional
        Effective number of Neutrino species. Default 3.04.

    m_nu : quantity-like ['energy', 'mass'] or array-like, optional
        Mass of each neutrino species in [eV] (mass-energy equivalency enabled).
        If this is a scalar Quantity, then all neutrino species are assumed to
        have that mass. Otherwise, the mass of each species. The actual number
        of neutrino species (and hence the number of elements of m_nu if it is
        not scalar) must be the floor of Neff. Typically this means you should
        provide three neutrino masses unless you are considering something like
        a sterile neutrino.

    Ob0 : float or None, optional
        Omega baryons: density of baryonic matter in units of the critical
        density at z=0.  If this is set to None (the default), any computation
        that requires its value will raise an exception.

    name : str or None (optional, keyword-only)
        Name for this cosmological object.

    meta : mapping or None (optional, keyword-only)
        Metadata for the cosmology, e.g., a reference.

    Examples
    --------
    >>> from astropy.cosmology import w0wzCDM
    >>> cosmo = w0wzCDM(H0=70, Om0=0.3, Ode0=0.7, w0=-0.9, wz=0.2)

    The comoving distance in Mpc at redshift z:

    >>> z = 0.5
    >>> dc = cosmo.comoving_distance(z)
    r  r9   r7   z9Derivative of the dark energy equation of state w.r.t. z.r   r=   r>   Nr?   c
                   s   t  j|||||||	|
|d	 || _|| _| jjdkrZtj| _| j	| j
| j| j| jf| _nf| jstj| _| j	| j
| j| j| j | j| jf| _n2tj| _| j	| j
| j| j| j| j| j| j| jf	| _d S r   )rD   rE   r  wzrd   rQ   r   Zw0wzcdm_inv_efunc_norelr|   rM   ry   rz   r  _wzr}   rc   Zw0wzcdm_inv_efunc_nomnurn   ru   Zw0wzcdm_inv_efuncre   rf   rs   )r~   rF   rG   rH   r  r*  rI   rJ   rK   rL   r@   rA   r   r"   r#   rE     s.    
zw0wzCDM.__init__c                 C   s   | j | jt|  S )a  Returns dark energy equation of state at redshift ``z``.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        Returns
        -------
        w : ndarray or float
            The dark energy equation of state.
            Returns `float` if the input is scalar.

        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. Here this is given by :math:`w(z) = w_0 + w_z z`.
        )r  r+  r   r   r"   r"   r#   r     s    z	w0wzCDM.wc                 C   s<   t |}|d }|dd| j | j   td| j |  S )a  Evaluates the redshift dependence of the dark energy density.

        Parameters
        ----------
        z : Quantity-like ['redshift'], array-like, or `~numbers.Number`
            Input redshift.

        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 in this case is given by

        .. math::

           I = \left(1 + z\right)^{3 \left(1 + w_0 - w_z\right)}
                     \exp \left(-3 w_z z\right)
        r0   r  r(  )r   r  r+  rg   r   r"  r"   r"   r#   r     s    zw0wzCDM.de_density_scale)r   r   r   r   r   r  r*  rV   rv   r;   rE   r   r   r   r"   r"   r   r#   r-   D  s   D
r-   )Or   abcr   Zmathr   r   r   r   r   r   r	   r
   r   Znumbersr   Znumpyrg   Zastropy.constantsZ	constantsrS   Zastropy.unitsr   rV   Z"astropy.utils.compat.optional_depsr   Zastropy.utils.decoratorsr   Zastropy.utils.exceptionsr   r<   r   r)  corer   r   r   Z	parameterr   r   Zutilsr   r   Zscipy.integrater   Zscipy.specialr   r   __all__Z__doctest_requires__Zkmr  rW   rU   rY   r\   r[   GZcgsrQ   r^   r   r   Zsigma_sbrT   rm   Zk_Br;   rv   rp   r%   r.   r&   r'   r(   r)   r*   r+   r,   r-   r"   r"   r"   r#   <module>   sr   ,
          XC    ~ 9   a 2