Пример #1
0
    def hmp(self, z=0):
        """Generating halo mass profiles

        Parameters
        ----------
        z : float
            Redshift of the snapshot
        """

        rhocrit = Planck15.critical_density(z).to(units.Msun / units.kpc**3) \
                  / (Planck15.H(z) / 100)

        for i in range(len(self.params)):
            _input = self.params[i]
            halos = _input['rockstar'].binnedhalos[_input['bin']]

            _input['hmp'] = MyHMP(
                halos,
                _input['gadget'].data,
                float(_input['rockstar'].header['Particle_mass'][0]))


            rmin = _input['rockstar'].header['Softening_length'] / 2.0
            rmax = 2 * np.max(halos['rvir'])
            _input['rockstar'].binnedhalos['mean_rvir'] = sum(halos['rvir']) \
                                                          / len(halos['rvir'])
            rbins = np.logspace(np.log10(rmin), np.log10(rmax), num=50, base=10)

            _input['hmp'].hmp(rbins, rhocrit.value)
Пример #2
0
    def hmp(self, z=0):
        """Generating halo mass profiles

        Parameters
        ----------
        z : float
            Redshift of the snapshot
        """

        rhocrit = Planck15.critical_density(z).to(units.Msun / units.kpc**3) \
                  / (Planck15.H(z) / 100)

        for i in range(len(self.params)):
            _input = self.params[i]
            halos = _input['rockstar'].binnedhalos[_input['bin']]

            _input['hmp'] = MyHMP(
                halos, _input['gadget'].data,
                float(_input['rockstar'].header['Particle_mass'][0]))

            rmin = _input['rockstar'].header['Softening_length'] / 2.0
            rmax = 2 * np.max(halos['rvir'])
            _input['rockstar'].binnedhalos['mean_rvir'] = sum(halos['rvir']) \
                                                          / len(halos['rvir'])
            rbins = np.logspace(np.log10(rmin),
                                np.log10(rmax),
                                num=50,
                                base=10)

            _input['hmp'].hmp(rbins, rhocrit.value)
def rvir(profile, overdensity=180, z=0.5):
    rho_crit = Planck15.critical_density(z).value
    mtot = profile['total_mass'].value  #g/cm^3
    r = profile['radius'].value  #cm
    V = 4 * np.pi * (r**3) / 3.
    cum_rho = mtot / V
    rvir = r[np.argmin(abs(cum_rho - (overdensity * rho_crit)))]
    return rvir
Пример #4
0
def frac_in_halos(zvals, Mlow, Mhigh, rmax=1.):
    """
    Calculate the fraction of dark matter in collapsed halos
     over a mass range and at a given redshift

    Note that the fraction of DM associated with these halos
    will be scaled down by an additional factor of f_diffuse

    Requires Aemulus HMF to be installed

    Args:
        zvals: ndarray
        Mlow: float
          In h^-1 units already so this will be applied for the halo mass function
        Mhigh: float
          In h^-1 units already
        rmax: float
          Extent of the halo in units of rvir

    Returns:
        ratios: ndarray
          rho_halo / rho_m
    """
    hmfe = init_hmf()

    M = np.logspace(np.log10(Mlow * cosmo.h),
                    np.log10(Mhigh * cosmo.h),
                    num=1000)
    lM = np.log(M)

    ratios = []
    for z in zvals:
        a = 1. / (1.0 + z)  # scale factor

        # Setup
        #dndlM = np.array([hmfe.dndlnM(Mi, a)[0] for Mi in M])
        dndlM = hmfe.dndlnM(M, z)
        M_spl = IUS(lM, M * dndlM)

        # Integrate
        rho_tot = M_spl.integral(np.log(Mlow * cosmo.h), np.log(
            Mhigh * cosmo.h)) * units.M_sun / units.Mpc**3
        # Cosmology
        rho_M = cosmo.critical_density(z) * cosmo.Om(z) / (
            1 + z)**3  # Tinker calculations are all mass
        ratio = (rho_tot * cosmo.h**2 / rho_M).decompose()
        #
        ratios.append(ratio)
    ratios = np.array(ratios)
    # Boost halos if extend beyond rvir (homologous in mass, but constant concentration is an approx)
    if rmax != 1.:
        #from pyigm.cgm.models import ModifiedNFW
        c = 7.7
        nfw = ModifiedNFW(c=c)
        M_ratio = nfw.fy_dm(rmax * nfw.c) / nfw.fy_dm(nfw.c)
        ratios *= M_ratio
    # Return
    return np.array(ratios)
Пример #5
0
class CosmoParams:
    hubble_constant: float = Planck15.H0.value
    omega_bary_hsqr: float = Planck15.Ob0 * Planck15.h**2
    omega_cdm_hsqr: float = Planck15.Odm0 * Planck15.h**2
    spectral_index: float = 0.9667
    scalar_amp: float = 2.2e-9
    sigma_8: float = 0.830
    tau_reion: float = 0.06
    omega_bary: float = Planck15.Ob0
    omega_cdm: float = Planck15.Odm0
    omega_matter: float = Planck15.Om0
    omega_lambda: float = Planck15.Ode0
    rho_crit: float = Planck15.critical_density(0).to(u.Msun / u.Mpc**3).value

    h: float = Planck15.h
    cmb_temp: float = Planck15.Tcmb0.value

    w0: float = -1.0
    wa: float = 0.0
    neutrino_mass_sum: float = 0.06

    use_ppf: bool = True
    flat: bool = True

    def _check_flatness(self):
        if not np.allclose(self.omega_matter + self.omega_lambda, 1,
                           rtol=1e-2):
            raise NonFlatUniverseError(
                'omega_matter and omega_lambda must sum to 1')

    def _check_matter_consistency(self):
        if not np.allclose(self.omega_matter,
                           self.omega_cdm + self.omega_bary):
            raise MatterInconsistencyError(
                'omega_cdm and omega_bary must sum to omega_matter')

    def _check_hsqr_params(self):
        if not np.allclose(self.omega_bary, self.omega_bary_hsqr / self.h**2):
            raise MatterInconsistencyError(
                'omega_bary_hsqr must equal omega_bary * h**2')
        if not np.allclose(self.omega_cdm, self.omega_cdm_hsqr / self.h**2):
            raise MatterInconsistencyError(
                'omega_cdm_hsqr must equal omega_cdm * h**2')

    def _check_hubble_consistency(self):
        if not np.allclose(self.hubble_constant / 100, self.h):
            raise HubbleConstantError('hubble_constant must equal h*100')

    def __post_init__(self):
        if self.flat:
            self._check_flatness()
        self._check_matter_consistency()
        self._check_hsqr_params()
        self._check_hubble_consistency()
def plot(file, ax, label=None, linestyle='solid', rnorm=None, znorm=None):
    f = h5py.File(file)['fields']
    t = f['temperature'].value * kB
    r = f['radius'].value * du
    d = f['density'].value
    k = entropy(f)
    if rnorm:
        r500 = rvir(f, overdensity=500)
        r /= r500
    if znorm:
        rho_crit = Planck15.critical_density(znorm).value
        d /= rho_crit
    ax1, ax2, ax3 = ax.flatten()
    ax1.plot(r, t, color=m.to_rgba(i), label=label, linestyle=linestyle)
    ax2.loglog(r, d, color=m.to_rgba(i), linestyle=linestyle)
    ax3.loglog(r, k, color=m.to_rgba(i), linestyle=linestyle)
Пример #7
0
 def setup_param(self, cosmo=None):
     """ Setup key parameters of the model
     """
     # Cosmology
     if cosmo is None:
         self.rhoc = 9.2e-30 * units.g / units.cm**3
         self.fb = 0.16  # Baryon fraction
         self.H0 = 70. * units.km / units.s / units.Mpc
     else:
         self.rhoc = cosmo.critical_density(self.z)
         self.fb = cosmo.Ob0 / cosmo.Om0
         self.H0 = cosmo.H0
     # Dark Matter
     self.r200 = (((3 * self.M_halo) /
                   (4 * np.pi * 200 * self.rhoc))**(1 / 3)).to('kpc')
     self.rho0 = 200 * self.rhoc / 3 * self.c**3 / self.fy_dm(
         self.c)  # Central density
     # Baryons
     self.M_b = self.M_halo * self.fb
     self.rho0_b = (self.M_b / (4 * np.pi) * (self.c / self.r200)**3 /
                    self.fy_b(self.c)).cgs
     # Misc
     self.mu = 1.33  # Reduced mass correction for Helium
Пример #8
0
def build_grid(z_FRB=1., ntrial=10, seed=12345, Mlow=1e10, r_max=2., outfile=None, dz_box=0.1,
    dz_grid=0.01, f_hot=0.75, verbose=True):
    """
    Generate a universe of dark matter halos with DM measurements
    Mainly an internal function for generating useful output grids.

    Requires the Aemulus Halo Mass function

    Args:
        z_FRB: float, optional
        ntrial: int, optional
        seed: int, optional
        Mlow: float, optional
          h^-1 mass
        r_max: float, optional
          Extent of the halo in units of rvir
        outfile: str, optional
          Write
        dz_box: float, optional
          Size of the slice of the universe for each sub-calculation
        dz_grid: float, optional
          redshift spacing in the DM grid
        f_hot: float
          Fraction of the cosmic fraction of matter in diffuse gas (for DM)

    Returns:
        DM_grid: ndarray (ntrial, nz)
        halo_tbl: Table
          Table of all the halos intersected

    """
    Mhigh = 1e16  # Msun
    # mNFW
    y0 = 2.
    alpha = 2.

    warnings.warn("Ought to do concentration properly someday!")
    cgm = ModifiedNFW(alpha=alpha, y0=y0, f_hot=f_hot)
    icm = ICM()

    # Random numbers
    rstate = np.random.RandomState(seed)

    # Init HMF
    hmfe = init_hmf()

    # Boxes
    nbox = int(z_FRB / dz_box)
    nz = int(z_FRB / dz_grid)
    dX = int(np.sqrt(ntrial))+1
    #
    npad = 6 # Mpc
    base_l = 2*dX + npad
    print('L_base = {} cMpc'.format(base_l))
    warnings.warn("Worry about being big enough given cMpc vs pMpc")

    DM_grid = np.zeros((ntrial,nz))

    # Spline distance to z
    D_max = cosmo.comoving_distance(z_FRB)
    D_val = np.linspace(1e-3,D_max.value,200) # IS THIS FINE ENOUGH?
    z_val = np.array([z_at_value(cosmo.comoving_distance, iz) for iz in D_val*units.Mpc])
    D_to_z = IUS(D_val, z_val)

    # Save halo info
    #halos = [[] for i in range(ntrial)]
    halo_i, M_i, R_i, DM_i, z_i = [], [], [], [], []

    # Loop me
    prev_zbox = 0.
    #for ss in range(nbox):
    #for ss in [0]:
    for ss in [5]:
        zbox = ss*dz_box + dz_box/2.
        print('zbox = {}'.format(zbox))
        a = 1./(1.0 + zbox) # Scale factor
        # Mass function
        M = np.logspace(np.log10(Mlow*cosmo.h), np.log10(Mhigh*cosmo.h), num=1000)
        lM = np.log(M)
        dndlM = np.array([hmf.dndlM(Mi, a) for Mi in M])
        n_spl = IUS(lM, dndlM)
        cum_n = np.array([n_spl.integral(np.log(Mlow*cosmo.h), ilM) for ilM in lM])
        ncum_n = cum_n/cum_n[-1]
        # As z increases, we have numerical issues at the high mass end (they are too rare)
        try:
            mhalo_spl = IUS(ncum_n, lM)
        except ValueError:
            # Kludge me
            print("REDUCING Mhigh by 2x")
            Mhigh /= 2.
            M = np.logspace(np.log10(Mlow*cosmo.h), np.log10(Mhigh*cosmo.h), num=1000)
            lM = np.log(M)
            dndlM = np.array([hmf.dndlM(Mi, a) for Mi in M])
            n_spl = IUS(lM, dndlM)
            cum_n = np.array([n_spl.integral(np.log(Mlow*cosmo.h), ilM) for ilM in lM])
            ncum_n = cum_n/cum_n[-1]
            #
            mhalo_spl = IUS(ncum_n, lM)

        # Volume -- Box with base l = 2Mpc
        D_zn = cosmo.comoving_distance(zbox + dz_box/2.) # Full box
        D_zp = cosmo.comoving_distance(ss*dz_box) # Previous
        D_z = D_zn - D_zp
        V = D_z * (base_l*units.Mpc)**2

        # Average N_halo
        avg_n = hmf.n_bin(Mlow*cosmo.h, Mhigh*cosmo.h, a) * cosmo.h**3 * units.Mpc**-3
        avg_N = (V * avg_n).value

        # Assume Gaussian stats for number of halos
        N_halo = int(np.round(avg_N + np.sqrt(avg_N)*rstate.randn(1)))

        # Random masses
        randM = rstate.random_sample(N_halo)
        rM = np.exp(mhalo_spl(randM)) / cosmo.h

        # r200
        r200 = (((3*rM*units.M_sun.cgs) / (4*np.pi*200*cosmo.critical_density(zbox)))**(1/3)).to('kpc')

        # Random locations (X,Y,Z)
        X_c = rstate.random_sample(N_halo)*base_l # Mpc
        Y_c = rstate.random_sample(N_halo)*base_l # Mpc
        Z_c = (rstate.random_sample(N_halo)*D_z.to('Mpc') + D_zp).value

        # Check mass fraction
        if verbose:
            Mtot = np.log10(np.sum(rM))
            M_m = (cosmo.critical_density(zbox)*cosmo.Om(zbox) * V/(1+zbox)**3).to('M_sun')
            #print("N_halo: {}  avg_N: {}".format(N_halo, avg_N))
            print("z: {}  Mhalo/M_m = {}".format(zbox, 10**Mtot/M_m.value))
            print(frac_in_halos([zbox], Mlow, Mhigh))

        # Redshifts
        z_ran = D_to_z(Z_c)

        # Loop on trials
        all_DMs = []
        all_nhalo = []
        all_r200 = []
        for itrial in range(ntrial):
            # X,Y trial
            X_trial = npad//2 + (2*itrial%dX)  # Step by 2Mpc
            Y_trial = npad//2 + 2*itrial // dX
            # Impact parameters
            try:
                R_com = np.sqrt((X_c-X_trial)**2 + (Y_c-Y_trial)**2)  # Mpc
            except:
                pdb.set_trace()
            R_phys = R_com * 1000. / (1+z_ran) * units.kpc
            # Cut
            intersect = R_phys < r_max*r200
            print("We hit {} halos".format(np.sum(intersect)))
            all_nhalo.append(np.sum(intersect))
            if not np.any(intersect):
                all_DMs.append(0.)
                continue
            # Loop -- FIND A WAY TO SPEED THIS UP!
            DMs = []
            for iobj in np.where(intersect)[0]:
                # Init
                if rM[iobj] > 1e14: # Use ICM model
                    model = icm
                else:
                    model = cgm
                model.log_Mhalo=np.log10(rM[iobj])
                model.M_halo = 10.**model.log_Mhalo * constants.M_sun.cgs
                model.z = zbox # To be consistent with above;  should be close enough
                model.setup_param(cosmo=cosmo)
                # DM
                DM = model.Ne_Rperp(R_phys[iobj], rmax=r_max, add_units=False)/(1+model.z)
                DMs.append(DM)
                # Save halo info
                halo_i.append(itrial)
                M_i.append(model.M_halo.value)
                R_i.append(R_phys[iobj].value)
                DM_i.append(DM)
                z_i.append(z_ran[iobj])
                all_r200.append(cgm.r200.value)
            # Save em
            iz = (z_ran[intersect]/dz_grid).astype(int)
            DM_grid[itrial,iz] += DMs
            all_DMs.append(np.sum(DMs))
            #print(DMs, np.log10(rM[intersect]), R_phys[intersect])
            if (itrial % 100) == 0:
                pdb.set_trace()

    # Table the halos
    halo_tbl = Table()
    halo_tbl['trial'] = halo_i
    halo_tbl['M'] = M_i
    halo_tbl['R'] = R_i
    halo_tbl['DM'] = DM_i
    halo_tbl['z'] = z_i

    # Write
    if outfile is not None:
        print("Writing to {}".format(outfile))
        np.save(outfile, DM_grid, allow_pickle=False)
        halo_tbl.write(outfile+'.fits', overwrite=True)

    return DM_grid, halo_tbl
Пример #9
0
def halo_incidence(Mlow, zFRB, radius=None, hmfe=None, Mhigh=1e16, nsample=20,
                   cumul=False):
    """
    Calculate the (approximate) average number of intersections to halos of a
    given minimum mass to a given zFRB.

    Requires Aemulus HMF to be installed

    Args:
        Mlow: float
          Mass of minimum halo in Solar masses
          The code deals with h^-1 factors so that you do not
          The minimum value is 2e10
        zFRB: float
          Redshift of the FRB
        radius: Quantity, optional
          The calculation will specify this radius as rvir derived from
           Mlow unless this is specified. And this rvir *will* vary with redshift
        hmfe (hmf.hmf_emulator, optional): Halo mass function emulator from Aeumulus
        Mhigh: float, optional
          Mass of maximum halo in Solar masses
        nsammple: int, optional
          Number of samplings in redshift
          20 should be enough
        cumul: bool, optional
          Return the cumulative quantities instead

    Returns:
        If cumul is False
        Navg: float
          Number of average intersections
        elif cumul is True
        zeval: ndarray
        Ncumul: ndarray
    """
    # Mlow limit
    if Mlow < 2e10:
        warnings.warn("Calculations are limited to Mlow > 2e10")
        return
    # HMF
    if hmfe is None:
        hmfe = init_hmf()
    #
    zs = np.linspace(0., zFRB, nsample)
    # Mean density
    ns = []
    for iz in zs:
        ns.append(hmfe.n_in_bins((Mlow * cosmo.h, Mhigh * cosmo.h), iz) * cosmo.h**3)  # * units.Mpc**-3
    # Interpolate
    ns = units.Quantity(ns*units.Mpc**-3)
    # Radii
    if radius is None:
        rhoc = cosmo.critical_density(zs)
        #https://arxiv.org/pdf/1312.4629.pdf eq5
        q = cosmo.Ode0/(cosmo.Ode0+cosmo.Om0*(1+zs)**3)
        rhovir = (18*np.pi**2-82*q-39*q**2)*rhoc
        r200 = (((3*Mlow*constants.M_sun.cgs) / (4*np.pi*rhovir))**(1/3)).to('kpc')
    else:
        r200 = np.ones_like(zs) * radius
    # Ap
    Ap = np.pi * r200**2

    # l(X)
    loX = ((constants.c/cosmo.H0) * ns * Ap).decompose().value

    # dX
    X = cosmo.absorption_distance(zs)
    dX = X - np.roll(X,1)
    dX[0] = 0.

    # Finish
    if cumul:
        Navg = np.cumsum(loX * dX)
        return zs, Navg
    else:
        import pdb; pdb.set_trace()
        Navg = np.sum(loX * dX)
        return Navg