示例#1
0
文件: general.py 项目: galtay/rabacus
    def dz2dDc(self,z1,z2):
        r""" Comoving distance between `z1` and `z2`.  Two calls to :func:`Dcz`
        are made and the results subtracted.  `z1` < `z2` produces positive
        comoving distance. 

        .. math::
          D_C(z1,z2) = d_{\rm H_0} \int_{z1}^{z2} \frac{dz'}{E(z')} 
        """
        if utils.isiterable(z1) and utils.isiterable(z2):
            if not len(z1) == len(z2):
                raise utils.InputError, "len(z1) /= len(z2)"
        Dc1 = self.Dcz(z1)
        Dc2 = self.Dcz(z2)
        Dc = Dc2 - Dc1
        return Dc
示例#2
0
    def dz2dDc(self, z1, z2):
        r""" Comoving distance between `z1` and `z2`.  Two calls to :func:`Dcz`
        are made and the results subtracted.  `z1` < `z2` produces positive
        comoving distance. 

        .. math::
          D_C(z1,z2) = d_{\rm H_0} \int_{z1}^{z2} \frac{dz'}{E(z')} 
        """
        if utils.isiterable(z1) and utils.isiterable(z2):
            if not len(z1) == len(z2):
                raise utils.InputError, "len(z1) /= len(z2)"
        Dc1 = self.Dcz(z1)
        Dc2 = self.Dcz(z2)
        Dc = Dc2 - Dc1
        return Dc
示例#3
0
    def return_Eth( self, Z, N ):
        """ Returns threshold ionization energy for ions defined by `Z` and 
        `N`.

        Args:

          `Z` (int): atomic number (number of protons)        
          
          `N` (int): electron number (number of electrons)

        Returns:

          `Eth` (float): ionization energy

        """

        # Make sure input is OK
        #--------------------------------------------------------
        if utils.isiterable( Z ) or not isinstance(Z,int):
            raise utils.InputError, '\n Z must be an integer scalar'

        if utils.isiterable( N ) or not isinstance(N,int):
            raise utils.InputError, '\n N must be an integer scalar'

        if Z < 1 or Z > 26:
            raise utils.InputError, '\n We must have 1 <= Z <= 26'

        if N < 1 or N > Z:
            raise utils.InputError, '\n We must have 1 <= N <= Z'


        # calculate 
        #--------------------------------------------------------

        c1 = self.Z == Z
        c2 = self.N == N

        indx = np.where( c1 & c2 )

        indx = indx[0][0]

        Eth = self.Eth[indx]

        Eth.units = 'eV' 
        return Eth
示例#4
0
文件: general.py 项目: galtay/rabacus
 def Dcz(self,z):
     r""" Comoving distance between z=0 and z, Dc(z) 
     
     .. math::
       D_C(z) = d_{\rm H_0} \int_{0}^{z} \frac{dz'}{E(z')} 
       
     """
     if utils.isiterable( z ):
         Dc = np.array( [quad( self.iEz, 0.0, zz )[0] for zz in z] )
         Dc = Dc * self.dH0
     else:
         Dc = quad( self.iEz, 0.0, z )[0] * self.dH0
     Dc.units = self.cu.Mpc/self.cu.h
     return Dc 
示例#5
0
 def Dcz(self, z):
     r""" Comoving distance between z=0 and z, Dc(z) 
     
     .. math::
       D_C(z) = d_{\rm H_0} \int_{0}^{z} \frac{dz'}{E(z')} 
       
     """
     if utils.isiterable(z):
         Dc = np.array([quad(self.iEz, 0.0, zz)[0] for zz in z])
         Dc = Dc * self.dH0
     else:
         Dc = quad(self.iEz, 0.0, z)[0] * self.dH0
     Dc.units = self.cu.Mpc / self.cu.h
     return Dc
示例#6
0
    def D1z(self, z):
        r""" Linear growth function D1(z) 

        .. math::
          D_1(z) \propto H(z) \int_z^\infty \frac{1+z'}{H(z')^3} dz'

        The normalization is such that D1z(0) = 1

        """

        if utils.isiterable(z):
            int_u = [quad(self._D1z_integrand, zz, np.inf)[0] for zz in z]
        else:
            int_u = quad(self._D1z_integrand, z, np.inf)[0]

        D1 = self.Hz(z) / self.H0 * int_u * self._D1z_Norm
        return D1
示例#7
0
文件: general.py 项目: galtay/rabacus
    def D1a(self, a):
        r""" Linear growth function D1(a).  

        .. math::
          D_1(a) \propto H(a) \int_0^a \frac{da'}{a'^3 H(a')^3}

        The normalization is such that D1a(1) = 1

          """ 

        if utils.isiterable(a):
            integral = [quad( self._D1a_integrand, 0.0, aa )[0] for aa in a]
        else:
            integral = quad( self._D1a_integrand, 0.0, a )[0]

        D1 = self.Ha(a) / self.H0 * integral * self._D1a_Norm
        return D1 
示例#8
0
文件: general.py 项目: galtay/rabacus
    def D1z( self, z ):
        r""" Linear growth function D1(z) 

        .. math::
          D_1(z) \propto H(z) \int_z^\infty \frac{1+z'}{H(z')^3} dz'

        The normalization is such that D1z(0) = 1

        """ 

        if utils.isiterable(z):
            int_u = [quad( self._D1z_integrand, zz, np.inf )[0] for zz in z]
        else:
            int_u = quad( self._D1z_integrand, z, np.inf )[0]

        D1 = self.Hz(z) / self.H0 * int_u * self._D1z_Norm
        return D1
示例#9
0
    def D1a(self, a):
        r""" Linear growth function D1(a).  

        .. math::
          D_1(a) \propto H(a) \int_0^a \frac{da'}{a'^3 H(a')^3}

        The normalization is such that D1a(1) = 1

          """

        if utils.isiterable(a):
            integral = [quad(self._D1a_integrand, 0.0, aa)[0] for aa in a]
        else:
            integral = quad(self._D1a_integrand, 0.0, a)[0]

        D1 = self.Ha(a) / self.H0 * integral * self._D1a_Norm
        return D1
示例#10
0
    def ta(self, a):
        r""" Time since a=0 or age of the Universe, t(a). 

        .. math::
          t(a) = \int_0^a \frac{da'}{a' H(a')} 

        """

        # quad works but takes a long time.
        #-------------------------------------------------------------------
        #        if utils.isiterable( a ):
        #            t = np.array( [quad( self._dt_da, 0.0, aa )[0] for aa in a] )
        #        else:
        #            t = quad( self._dt_da, 0.0, a )[0]
        #        t = t * self.cu.s
        #        print 't = ', t.rescale("Myr/hh")

        # trap rule includes OmegaR and is fast and accurate to 6 decimals
        #-------------------------------------------------------------------
        N = 5000
        a_min = 1.0e-10
        if utils.isiterable(a):
            t = np.zeros(a.size) * self.cu.s
            for ii, aa in enumerate(a):
                xx = np.linspace(a_min, aa, N)
                yy = 1.0 / (xx * self.Ha(xx))
                t[ii] = utils.trap(xx, yy)
        else:
            xx = np.linspace(a_min, a, N)
            yy = 1.0 / (xx * self.Ha(xx))
            t = utils.trap(xx, yy)
        t.units = 'Myr/hh'

        # this is analytic but does not include OmegaR
        #-------------------------------------------------------------------
        #        pre = 2.0 / ( 3.0 * np.sqrt( self.OmegaL ) )
        #        aeq = (self.OmegaM/self.OmegaL)**(1./3.)
        #        arg = (a/aeq)**(3./2.) + np.sqrt(1 + (a/aeq)**3)
        #        t = pre * np.log(arg) * self.tH0

        return t
示例#11
0
文件: general.py 项目: galtay/rabacus
    def ta( self, a):
        r""" Time since a=0 or age of the Universe, t(a). 

        .. math::
          t(a) = \int_0^a \frac{da'}{a' H(a')} 

        """ 

        # quad works but takes a long time. 
        #-------------------------------------------------------------------
#        if utils.isiterable( a ):
#            t = np.array( [quad( self._dt_da, 0.0, aa )[0] for aa in a] )
#        else:
#            t = quad( self._dt_da, 0.0, a )[0]
#        t = t * self.cu.s
#        print 't = ', t.rescale("Myr/hh")

        # trap rule includes OmegaR and is fast and accurate to 6 decimals
        #-------------------------------------------------------------------
        N = 5000
        a_min = 1.0e-10
        if utils.isiterable( a ):
            t = np.zeros( a.size ) * self.cu.s
            for ii,aa in enumerate(a):
                xx = np.linspace( a_min, aa, N )
                yy = 1.0 / ( xx * self.Ha(xx) )
                t[ii] = utils.trap( xx, yy )
        else:
            xx = np.linspace( a_min, a, N )
            yy = 1.0 / ( xx * self.Ha(xx) )
            t = utils.trap( xx, yy )
        t.units = 'Myr/hh'

        # this is analytic but does not include OmegaR        
        #-------------------------------------------------------------------
#        pre = 2.0 / ( 3.0 * np.sqrt( self.OmegaL ) )
#        aeq = (self.OmegaM/self.OmegaL)**(1./3.)  
#        arg = (a/aeq)**(3./2.) + np.sqrt(1 + (a/aeq)**3)
#        t = pre * np.log(arg) * self.tH0

        return t 
示例#12
0
    def analytic_soltn_xH1(self, nH, y, k):
        """ Analytic equilibrium solution for the neutral fraction xH1 = nH1/nH 
        
        Args:

          `nH` (array): H number density

          `y` (array): electrons from elements heavier than hydrogen, 
          ne = nH * (xH2 + y)

          `k` (rates object): must contain the attributes ciH1, reH2, and H1i, 
          see :class:`~rabacus.atomic.chemistry.ChemistryRates`

        Returns: 

          `xH1` (array): neutral hydrogen fraction
           
        """

        RR = (k.ciH1 + k.reH2) * nH
        QQ = -(k.H1i + k.reH2 * nH + RR * (1 + y))
        PP = k.reH2 * nH * (1.0 + y)

        dd = QQ * QQ - 4.0 * RR * PP

        if utils.isiterable(dd):
            if np.any(dd < 0.0):
                indx = np.where(dd < 0.0)
                dd[indx] = dd[indx] * 0.0
        else:
            if dd < 0.0:
                dd = dd * 0.0

        # QQ is always negative in this case
        #q = -0.5 * (QQ + np.sign(QQ) * np.sqrt(QQ*QQ - 4.0*RR*PP))
        q = -0.5 * (QQ - np.sqrt(dd))
        xH1 = PP / q

        return xH1
示例#13
0
    def analytic_soltn_xH1(self, nH, y, k):
        """ Analytic equilibrium solution for the neutral fraction xH1 = nH1/nH 
        
        Args:

          `nH` (array): H number density

          `y` (array): electrons from elements heavier than hydrogen, 
          ne = nH * (xH2 + y)

          `k` (rates object): must contain the attributes ciH1, reH2, and H1i, 
          see :class:`~rabacus.atomic.chemistry.ChemistryRates`

        Returns: 

          `xH1` (array): neutral hydrogen fraction
           
        """
 
        RR = (k.ciH1 + k.reH2) * nH
        QQ = -( k.H1i + k.reH2 * nH + RR * (1+y) )
        PP = k.reH2 * nH * (1.0 + y) 
        
        dd = QQ*QQ - 4.0*RR*PP
 
        if utils.isiterable( dd ):
            if np.any( dd < 0.0 ):
                indx = np.where( dd < 0.0 )
                dd[indx] = dd[indx] * 0.0
        else:
            if dd < 0.0:
                dd = dd * 0.0 

        # QQ is always negative in this case
        #q = -0.5 * (QQ + np.sign(QQ) * np.sqrt(QQ*QQ - 4.0*RR*PP))
        q = -0.5 * ( QQ - np.sqrt(dd) )
        xH1 = PP / q
        
        return xH1
示例#14
0
    def _clean_input(self, T, fcA_H2, fcA_He2, fcA_He3, H1i, He1i, He2i):

        # check temperature
        #------------------------------------------
        if not hasattr(T, 'shape'):
            raise utils.InputError, '\n T must be an array with units. \n'

        if T.shape == ():
            self.T = np.ones(1) * T
        else:
            self.T = T.copy()

        if not hasattr(self.T, 'units'):
            raise utils.NeedUnitsError, '\n T must have units \n'
        else:
            self.T.units = 'K'

        # check fcA
        #------------------------------------------
        if utils.isiterable(fcA_H2):
            assert fcA_H2.shape == self.T.shape
            self.fcA_H2 = fcA_H2.copy()
        else:
            self.fcA_H2 = np.ones(self.T.shape) * fcA_H2

        if utils.isiterable(fcA_He2):
            assert fcA_He2.shape == self.T.shape
            self.fcA_He2 = fcA_He2.copy()
        else:
            self.fcA_He2 = np.ones(self.T.shape) * fcA_He2

        if utils.isiterable(fcA_He3):
            assert fcA_He3.shape == self.T.shape
            self.fcA_He3 = fcA_He3.copy()
        else:
            self.fcA_He3 = np.ones(self.T.shape) * fcA_He3

        # check HI photoionization rate
        #------------------------------------------
        if H1i == None:
            self.H1i = np.zeros(self.T.shape) / self.U.s
        else:
            if H1i.shape == ():
                self.H1i = np.ones(1) * H1i
            else:
                self.H1i = H1i.copy()

            if not hasattr(self.H1i, 'units'):
                raise utils.NeedUnitsError, '\n H1i must have units \n'
            else:
                self.H1i.units = '1/s'

            if self.H1i.shape != self.T.shape:
                raise utils.InputError, '\n T and H1i must have same shape \n'

        # check HeI photoionization rate
        #------------------------------------------
        if He1i == None:
            self.He1i = np.zeros(1) / self.U.s
        else:
            if He1i.shape == ():
                self.He1i = np.ones(1) * He1i
            else:
                self.He1i = He1i.copy()

            if not hasattr(self.He1i, 'units'):
                raise utils.NeedUnitsError, '\n He1i must have units \n'
            else:
                self.He1i.units = '1/s'

            if self.He1i.shape != self.T.shape:
                raise utils.InputError, '\n T and He1i must have same shape \n'

        # check HeII photoionization rate
        #------------------------------------------
        if He2i == None:
            self.He2i = np.zeros(1) / self.U.s
        else:
            if He2i.shape == ():
                self.He2i = np.ones(1) * He2i
            else:
                self.He2i = He2i.copy()

            if not hasattr(self.He2i, 'units'):
                raise utils.NeedUnitsError, '\n He2i must have units \n'
            else:
                self.He2i.units = '1/s'

            if self.He2i.shape != self.T.shape:
                raise utils.InputError, '\n T and He2i must have same shape \n'
示例#15
0
    def _clean_input( self, T, fcA_H2, fcA_He2, fcA_He3, H1i, He1i, He2i ):

        # check temperature 
        #------------------------------------------
        if not hasattr( T, 'shape' ):
            raise utils.InputError, '\n T must be an array with units. \n'

        if T.shape == ():
            self.T = np.ones(1) * T
        else:
            self.T = T.copy()

        if not hasattr(self.T,'units'): 
            raise utils.NeedUnitsError, '\n T must have units \n'
        else:
            self.T.units = 'K'

        # check fcA
        #------------------------------------------
        if utils.isiterable( fcA_H2 ):
            assert fcA_H2.shape == self.T.shape
            self.fcA_H2 = fcA_H2.copy()
        else:
            self.fcA_H2 = np.ones(self.T.shape) * fcA_H2

        if utils.isiterable( fcA_He2 ):
            assert fcA_He2.shape == self.T.shape
            self.fcA_He2 = fcA_He2.copy()
        else:
            self.fcA_He2 = np.ones(self.T.shape) * fcA_He2

        if utils.isiterable( fcA_He3 ):
            assert fcA_He3.shape == self.T.shape
            self.fcA_He3 = fcA_He3.copy()
        else:
            self.fcA_He3 = np.ones(self.T.shape) * fcA_He3

        # check HI photoionization rate
        #------------------------------------------
        if H1i == None:
            self.H1i = np.zeros(self.T.shape) / self.U.s
        else:
            if H1i.shape == ():
                self.H1i = np.ones(1) * H1i
            else:
                self.H1i = H1i.copy()

            if not hasattr(self.H1i,'units'): 
                raise utils.NeedUnitsError, '\n H1i must have units \n'
            else:
                self.H1i.units = '1/s'

            if self.H1i.shape != self.T.shape:
                raise utils.InputError, '\n T and H1i must have same shape \n'


        # check HeI photoionization rate
        #------------------------------------------
        if He1i == None:
            self.He1i = np.zeros(1) / self.U.s
        else:
            if He1i.shape == ():
                self.He1i = np.ones(1) * He1i
            else:
                self.He1i = He1i.copy()

            if not hasattr(self.He1i,'units'): 
                raise utils.NeedUnitsError, '\n He1i must have units \n'
            else:
                self.He1i.units = '1/s'

            if self.He1i.shape != self.T.shape:
                raise utils.InputError, '\n T and He1i must have same shape \n'


        # check HeII photoionization rate
        #------------------------------------------
        if He2i == None:
            self.He2i = np.zeros(1) / self.U.s
        else:
            if He2i.shape == ():
                self.He2i = np.ones(1) * He2i
            else:
                self.He2i = He2i.copy()

            if not hasattr(self.He2i,'units'): 
                raise utils.NeedUnitsError, '\n He2i must have units \n'
            else:
                self.He2i.units = '1/s'

            if self.He2i.shape != self.T.shape:
                raise utils.InputError, '\n T and He2i must have same shape \n'
示例#16
0
    def return_fit( self, Z, N, E ):
        """ Returns a photo-ionization cross-section for an ion defined by 
        `Z` and `N` at energies `E`.

        Args:

          `Z` (int): atomic number (number of protons)        
          
          `N` (int): electron number (number of electrons)

          `E` (array): calculate cross-section at these energies

        Returns:

          `sigma` (array): photoionization cross-sections


        """


        # Make sure input is OK
        #--------------------------------------------------------

        if hasattr(E,'units'): 
            E.units = 'eV'
        else:
            raise utils.NeedUnitsError, '\n Input variable E must have units \n'

        if utils.isiterable( Z ) or not isinstance(Z,int):
            raise utils.InputError, '\n Z must be an integer scalar'

        if utils.isiterable( N ) or not isinstance(N,int):
            raise utils.InputError, '\n N must be an integer scalar'

        if Z < 1 or Z > 26:
            raise utils.InputError, '\n We must have 1 <= Z <= 26'

        if N < 1 or N > Z:
            raise utils.InputError, '\n We must have 1 <= N <= Z'


        # calculate fit
        #--------------------------------------------------------

        c1 = self.Z == Z
        c2 = self.N == N

        indx = np.where( c1 & c2 )

        indx = indx[0][0]

        Z = self.Z[indx]
        N = self.N[indx]
        Eth = self.Eth[indx]
        Emax = self.Emax[indx]
        E0 = self.E0[indx]
        sigma0 = self.sigma0[indx]
        ya = self.ya[indx]
        P = self.P[indx]
        yw = self.yw[indx]
        y0 = self.y0[indx]
        y1 = self.y1[indx]

        x = E / E0 - y0
        y = np.sqrt( x*x + y1*y1 )

        t1 = (x-1)*(x-1) + yw*yw
        t2 = y**(0.5*P - 5.5)
        t3 = (1+np.sqrt(y/ya))**(-P)
        
        F = t1 * t2 * t3

        sigma = sigma0 * F 
      
        # zero cross-section below threshold
        #--------------------------------------------------------
        if utils.isiterable( E ):
            indx = np.where( E < Eth )
            if indx[0].size > 0:
                sigma[indx] = 0.0 * self.U.cm**2
        else:
            if E < Eth:
                sigma = 0.0 * self.U.cm**2

        return sigma
示例#17
0
    def _clean_input( self, T, fcA_H2, fcA_He2, fcA_He3, H1h, He1h, He2h ):

        # check temperature 
        #------------------------------------------
        if not hasattr( T, 'shape' ):
            raise utils.InputError, '\n T must be an array with units. \n'

        if T.shape == ():
            self.T = np.ones(1) * T
        else:
            self.T = T.copy()

        if not hasattr(self.T,'units'): 
            raise utils.NeedUnitsError, '\n T must have units \n'
        else:
            self.T.units = 'K'

        # check fcA
        #------------------------------------------
        if utils.isiterable( fcA_H2 ):
            assert fcA_H2.shape == self.T.shape
            self.fcA_H2 = fcA_H2.copy()
        else:
            self.fcA_H2 = np.ones(self.T.shape) * fcA_H2

        if utils.isiterable( fcA_He2 ):
            assert fcA_He2.shape == self.T.shape
            self.fcA_He2 = fcA_He2.copy()
        else:
            self.fcA_He2 = np.ones(self.T.shape) * fcA_He2

        if utils.isiterable( fcA_He3 ):
            assert fcA_He3.shape == self.T.shape
            self.fcA_He3 = fcA_He3.copy()
        else:
            self.fcA_He3 = np.ones(self.T.shape) * fcA_He3


        # check HI photo-heating rate
        #------------------------------------------
        if H1h == None:
            self.H1h = np.zeros(1) * self.u.erg / self.u.s
        else:
            if H1h.shape == ():
                self.H1h = np.ones(1) * H1h
            else:
                self.H1h = H1h.copy()

            if not hasattr(self.H1h,'units'): 
                raise utils.NeedUnitsError, '\n H1h must have units \n'
            else:
                self.H1h.units = 'erg/s'

            if self.H1h.shape != self.T.shape:
                raise utils.InputError, '\n T and H1h must have same shape \n'

        # check HeI photo-heating rate
        #------------------------------------------
        if He1h == None:
            self.He1h = np.zeros(1) * self.u.erg / self.u.s
        else:
            if He1h.shape == ():
                self.He1h = np.ones(1) * He1h
            else:
                self.He1h = He1h.copy()

            if not hasattr(self.He1h,'units'): 
                raise utils.NeedUnitsError, '\n He1h must have units \n'
            else:
                self.He1h.units = 'erg/s'

            if self.He1h.shape != self.T.shape:
                raise utils.InputError, '\n T and He1h must have same shape \n'

        # check HeII photo-heating rate
        #------------------------------------------
        if He2h == None:
            self.He2h = np.zeros(1) * self.u.erg / self.u.s
        else:
            if He2h.shape == ():
                self.He2h = np.ones(1) * He2h
            else:
                self.He2h = He2h.copy()

            if not hasattr(self.He2h,'units'): 
                raise utils.NeedUnitsError, '\n He2h must have units \n'
            else:
                self.He2h.units = 'erg/s'

            if self.He2h.shape != self.T.shape:
                raise utils.InputError, '\n T and He2h must have same shape \n'