diff options
| author | Aaron LI <aaronly.me@outlook.com> | 2017-01-08 13:39:28 +0800 | 
|---|---|---|
| committer | Aaron LI <aly@aaronly.me> | 2017-06-01 16:33:38 +0800 | 
| commit | e312e39c9821a89aaf6dc74e36022ffa4ad16fab (patch) | |
| tree | 5d1befc1f70b0a206ae98a17a16573321a02f501 | |
| parent | 659ef86e04124f1aa7fd4dc30f1612bf608d66a1 (diff) | |
| download | fg21sim-e312e39c9821a89aaf6dc74e36022ffa4ad16fab.tar.bz2 | |
cosmology.py: Greatly optimize the speed!
| -rw-r--r-- | fg21sim/extragalactic/clusters/cosmology.py | 83 | 
1 files changed, 57 insertions, 26 deletions
| diff --git a/fg21sim/extragalactic/clusters/cosmology.py b/fg21sim/extragalactic/clusters/cosmology.py index 5f7b283..4d65cdc 100644 --- a/fg21sim/extragalactic/clusters/cosmology.py +++ b/fg21sim/extragalactic/clusters/cosmology.py @@ -5,15 +5,10 @@  Flat ΛCDM cosmological model.  """ -import logging -  import numpy as np  from scipy import integrate  import astropy.units as au -from astropy.cosmology import LambdaCDM, z_at_value - - -logger = logging.getLogger(__name__) +from astropy.cosmology import FlatLambdaCDM  class Cosmology: @@ -41,16 +36,13 @@ class Cosmology:          http://adsabs.harvard.edu/abs/2002ApJ...577..579R          Sec.(2)      """ -    def __init__(self, H0=71.0, Om0=0.27, Ob0=0.046, Ode0=None, sigma8=0.834): -        Ode0 = 1.0 - Om0 if Ode0 is None else Ode0 -        if (Ode0 > 0) and abs(Om0 + Ode0 - 1) > 1e-5: -            raise ValueError("non-flat LambdaCDM model not supported!") +    def __init__(self, H0=71.0, Om0=0.27, Ob0=0.046, sigma8=0.834):          self.H0 = H0  # [km/s/Mpc]          self.Om0 = Om0          self.Ob0 = Ob0 -        self.Ode0 = Ode0 +        self.Ode0 = 1.0 - Om0          self.sigma8 = sigma8 -        self.cosmo = LambdaCDM(H0=H0, Om0=Om0, Ob0=Ob0, Ode0=Ode0) +        self._cosmo = FlatLambdaCDM(H0=H0, Om0=Om0, Ob0=Ob0)      @property      def h(self): @@ -69,9 +61,32 @@ class Cosmology:          M8 = (4*np.pi/3) * r**3 * self.rho_crit(0)          return (M8 * au.g.to(au.solMass)) +    def E(self, z): +        """ +        Redshift evolution factor. +        """ +        return np.sqrt(self.Om0 * (1+z)**3 + self.Ode0) + +    def H(self, z): +        """ +        Hubble parameter at redshift z. +        """ +        return self.H0 * self.E(z) + +    @property +    def hubble_time(self): +        """ +        Hubble time. +        Unit: [Gyr] +        """ +        # uconv = au.Mpc.to(au.km) * au.s.to(au.Gyr) +        uconv = 977.7922216731284 +        t_H = (1.0/self.H0) * uconv  # [Gyr] +        return t_H +      def age(self, z):          """ -        Cosmic time at redshift z. +        Cosmic time (age) at redshift z.          Parameters          ---------- @@ -83,22 +98,29 @@ class Cosmology:          age : float              Age of the universe (cosmic time) at the given redshift.              Unit: [Gyr] + +        References +        ---------- +        [1] Thomas & Kantowski 2000, Physical Review D, 62, 103507 +            http://adsabs.harvard.edu/abs/2000PhRvD..62j3507T +            Eq.(18)          """ -        return self.cosmo.age(z).value +        t_H = self.hubble_time +        t = (t_H * (2/3/np.sqrt(1-self.Om0)) * +             np.arcsinh(np.sqrt((1/self.Om0 - 1) / (1+z)**3))) +        return t      @property      def age0(self):          """          Present age of the universe.          """ -        if not hasattr(self, "_age0"): -            self._age0 = self.age(0) -        return self._age0 +        return self.age(0)      def redshift(self, age):          """ -        Invert the above age calculation, to return the redshift -        corresponding to the given cosmic time. +        Invert the above ``self.age(z)`` formula analytically, to calculate +        the redshift corresponding to the given cosmic time (age).          Parameters          ---------- @@ -108,22 +130,31 @@ class Cosmology:          Returns          -------          z : float -            Redshift corresponding to the input age. +            Redshift corresponding to the specified age.          """ -        return z_at_value(self.age, age) +        t_H = self.hubble_time +        term1 = (1/self.Om0) - 1 +        term2 = np.sinh(3*age*np.sqrt(1-self.Om0) / (2*t_H)) ** 2 +        z = (term1 / term2) ** (1/3) - 1 +        return z      def rho_crit(self, z):          """          Critical density at redshift z.          Unit: [g/cm^3]          """ -        return self.cosmo.critical_density(0).value +        G = 6.67384e-08  # [cm^3/g/s^2] +        rho = 3 * self.H(z)**2 / (8*np.pi * G) +        # uconv = au.km.to(au.Mpc)**2 +        uconv = 1.0502650403056094e-39 +        rho *= uconv +        return rho -    def OmegaM(self, z): +    def Om(self, z):          """          Density parameter of matter at redshift z.          """ -        return self.Om0 * (1+z)**3 / self.cosmo.efunc(z)**2 +        return self.Om0 * (1+z)**3 / self.E(z)**2      def overdensity_virial(self, z):          """ @@ -136,7 +167,7 @@ class Cosmology:              http://adsabs.harvard.edu/abs/2005MNRAS.357.1313C              Eqs.(10,A4)          """ -        omega_z = (1 / self.OmegaM(z)) - 1 +        omega_z = (1 / self.Om(z)) - 1          Delta_c = 18*np.pi**2 * (1 + 0.4093 * omega_z**0.9052)          return Delta_c @@ -154,7 +185,7 @@ class Cosmology:          coef = 3 * (12*np.pi) ** (2/3) / 20          D0 = self.growth_factor(0)          D_z = self.growth_factor(z) -        Om_z = self.OmegaM(z) +        Om_z = self.Om(z)          delta_c = coef * (D0 / D_z) * (1 + 0.0123*np.log10(Om_z))          return delta_c | 
