Ejemplo n.º 1
0
    def xir(self, rvals, hankelN=6000, hankelh=0.0005, ft_hankel=None):
        """
        Function that performs a Hankel transform to obtain the 2-point
        correlation function corresponding to the power spectrum.
        """

        if ft_hankel is None:
            ft_hankel = hankel.SymmetricFourierTransform(ndim=3,
                                                         N=hankelN,
                                                         h=hankelh)
        xivals = ft_hankel.transform(f=self.pkinterp,
                                     k=rvals,
                                     ret_err=False,
                                     ret_cumsum=False,
                                     inverse=True)

        return xivals
Ejemplo n.º 2
0
def create_profile_grid_fourier(log_kvals_rvir_dict,
                                log_conc_dict,
                                gamma_dict,
                                output_file="default.npz",
                                hankelN=12000,
                                hankelh=1e-6,
                                verbose=True):
    """
    Function to create and save to memory a grid of Fourier-space density
    profiles, so that we can later use them to speed-up calculations
    using interpolations.
    The resulting grid will depend on three coordinates:
        - log10(k * rvir)
        - log10(concentration)
        - gamma
    The input dictionaries define the min/max/number of steps for each of the
    coordinates.
    The profile will be computed for mass=1, and with the appropriate value
    of rho_s to be properly normalized (i.e., u(k) --> 1 as k --> 0).
    We also save an array containing the computed rho_s (for mass=1,
    rvir=1) as function of log10(concentration) and gamma for later use.
    As this should be called only once before the runs, I use the
    slower (but more precise) function 'alt_rhos_modNFW' to compute rho_s.
    """

    k_rvir = np.logspace(log_kvals_rvir_dict['min'],
                         log_kvals_rvir_dict['max'], log_kvals_rvir_dict['N'])
    log_k_rvir = np.log10(k_rvir)

    concentration = np.logspace(log_conc_dict['min'], log_conc_dict['max'],
                                log_conc_dict['N'])
    log_conc = np.log10(concentration)

    gamma_exp = np.linspace(gamma_dict['min'], gamma_dict['max'],
                            gamma_dict['N'])

    ft_hankel = hankel.SymmetricFourierTransform(ndim=3, N=hankelN, h=hankelh)

    profile_grid = np.empty(
        (log_kvals_rvir_dict['N'], log_conc_dict['N'], gamma_dict['N']))

    rho_s_grid = np.empty((log_conc_dict['N'], gamma_dict['N']))

    for i, conc in enumerate(concentration):
        if verbose:
            print(f"Concentration = {conc} ({i} of {log_conc_dict['N']})")
        for j, g_exp in enumerate(gamma_exp):

            rho_s = alt_rhos_modNFW(mass=1, rvir=1, conc=conc, gamma=g_exp)
            norm_prof_func = \
                lambda x: profile_ModNFW_config_scalar(rvals=x, rho_s=1,
                                                       conc=conc, rvir=1,
                                                       gamma_exp=g_exp)
            profile_grid[:, i, j] = \
                rho_s*ft_hankel.transform(f=norm_prof_func, k=k_rvir,
                                          ret_err=False, ret_cumsum=False)
            rho_s_grid[i, j] = rho_s

    np.savez(output_file,
             log10_k_rvir=log_k_rvir,
             log10_concentration=log_conc,
             gamma=gamma_exp,
             profile_grid=profile_grid,
             rho_s_unit=rho_s_grid)

    log_file = output_file + ".log"
    with open(log_file, 'a') as flog:
        flog.write(
            "Arrays in " + output_file + " created by function "
            "densprofile.create_profile_grid_fourier(), with options:\n")
        flog.write("Limits for log(k * rvir) array: " +
                   str(log_kvals_rvir_dict) + "\n")
        flog.write("Limits for log(concentration) array: " +
                   str(log_conc_dict) + "\n")
        flog.write("Limits for gamma array: " + str(gamma_dict) + "\n")
        flog.write("Hankel parameters: N = %d, h = %f\n" % (hankelN, hankelh))

    return 0
Ejemplo n.º 3
0
def profile_ModNFW_fourier_hankel(kvals,
                                  mass,
                                  rho_s,
                                  rvir,
                                  conc,
                                  gamma=1.0,
                                  hankelN=6000,
                                  hankelh=1e-5,
                                  ft_hankel=None):
    """
    Try to do the same as the function profile_ModNFW_fourier_parameters,
    but using the Hankel transforms in the 'hankel' library.
    We use the fact that the transform we need to do is the same as to
    convert from xi(r) to P(k), assuming that the rho(r) function provides
    already a truncated profile.

    For now, using N=6000, h=1e-5, and our cut at k=1/(10 rvir),
    I get a difference typically below 1.5% comparing to the u(k) calculated
    analytically for gamma=1.

    Could in principle use the multidimensional version of hankel to speed
    up the transformation (avoiding explicit loop over Nm).
    However, for useful values of Nm this rockets up the memory usage, so this
    approach is not viable in practice.
    """

    kvals = np.atleast_1d(kvals)
    assert kvals.ndim == 1
    Nk = len(kvals)

    mass = np.atleast_1d(mass)
    rho_s = np.atleast_1d(rho_s)
    rvir = np.atleast_1d(rvir)
    conc = np.atleast_1d(conc)
    assert mass.ndim == 1
    assert rho_s.ndim == 1
    assert rvir.ndim == 1
    assert conc.ndim == 1
    Nm = len(mass)
    assert Nm == len(rho_s) == len(rvir) == len(conc)

    if ft_hankel is None:
        ft_hankel = hankel.SymmetricFourierTransform(ndim=3,
                                                     N=hankelN,
                                                     h=hankelh)
    uprof_out = np.ones((Nk, Nm), float)
    for i in range(Nm):
        idx_calc = (kvals > 1. / (10 * rvir[i]))
        norm_prof_func = lambda x: \
            profile_ModNFW_config_scalar(rvals=x, rho_s=rho_s[i],
                                         conc=conc[i], rvir=rvir[i],
                                         gamma_exp=gamma)/mass[i]
        uprof_out[idx_calc, i] = ft_hankel.transform(f=norm_prof_func,
                                                     k=kvals[idx_calc],
                                                     ret_err=False,
                                                     ret_cumsum=False)
    # I add a condition, so that I make u(k)=1 for
    # all k < 1/(10 rvir).
    # This is a bit arbitrary, what works to avoid the oscillations
    # that appear at small k
    # rvir_grid, kvals_grid = np.meshgrid(rvir, kvals)
    # uprof_out[kvals_grid < 1./(10*rvir_grid)] = 1.0

    return uprof_out
Ejemplo n.º 4
0
def hod_from_parameters(redshift=0,
                        OmegaM0=0.27,
                        OmegaL0=0.73,
                        OmegaB0=0.046,
                        H0=70.0,
                        use_camb=True,
                        init_power_amplitude=2.2e-9,
                        init_power_spect_index=0.96,
                        camb_halofit_version=None,
                        camb_kmax=200.0,
                        camb_k_per_logint=30,
                        powesp_matter_file=None,
                        powesp_linz0_file=None,
                        hod_type=1,
                        hod_mass_min=1e11,
                        hod_mass_1=1e12,
                        hod_alpha=1.0,
                        hod_siglogM=0.5,
                        hod_mass_0=1e11,
                        f_gal=1.0,
                        gamma=1.0,
                        logM_min=8.0,
                        logM_max=16.0,
                        logM_step=0.005,
                        scale_dep_bias=True,
                        use_mvir_limit=True,
                        halo_exclusion_model=2,
                        use_tinker_bias_params=True,
                        hankelN=6000,
                        hankelh=0.0005,
                        rmin=0.01,
                        rmax=100.0,
                        nr=100,
                        rlog=True,
                        fprof_grid_log_krvir=None,
                        fprof_grid_log_conc=None,
                        fprof_grid_gamma=None,
                        fprof_grid_profile=None,
                        fprof_grid_rhos=None,
                        fprof_hankelN=12000,
                        fprof_hankelh=1e-6,
                        fprof_Nk_interp=100,
                        fprof_Nm_interp=100):
    """
    Construct an HODClustering object defining all the needed parameters.
    """

    assert redshift >= 0

    if redshift > 10:
        raise UserWarning("You entered a quite high value of redshift (>10). \
I am not sure these models are valid there, proceed at your own risk.")

    # First, build the Cosmology object
    # As we work always using distances in Mpc/h, we should be
    # fine setting H0=100
    assert OmegaM0 >= 0
    if (OmegaM0 + OmegaL0) != 1:
        raise UserWarning("You are using a non-flat cosmology. \
Are you sure that is what you really want?")
    cosmo_object = ac.LambdaCDM(H0=100, Om0=OmegaM0, Ode0=OmegaL0)

    # Calculate or read in the needed PowerSpectrum objects
    if use_camb:
        pk_matter_object = get_camb_pk(redshift=redshift,
                                       OmegaM0=OmegaM0,
                                       OmegaL0=OmegaL0,
                                       OmegaB0=OmegaB0,
                                       H0=H0,
                                       Pinit_As=init_power_amplitude,
                                       Pinit_n=init_power_spect_index,
                                       nonlinear=True,
                                       halofit_model=camb_halofit_version,
                                       kmax=camb_kmax,
                                       k_per_logint=camb_k_per_logint)

        pk_linz0_object = get_camb_pk(redshift=0,
                                      OmegaM0=OmegaM0,
                                      OmegaL0=OmegaL0,
                                      OmegaB0=OmegaB0,
                                      H0=H0,
                                      Pinit_As=init_power_amplitude,
                                      Pinit_n=init_power_spect_index,
                                      nonlinear=False,
                                      kmax=camb_kmax,
                                      k_per_logint=camb_k_per_logint)

    else:
        pk_matter_object = PowerSpectrum.fromfile(powesp_matter_file)
        pk_linz0_object = PowerSpectrum.fromfile(powesp_linz0_file)

    # Build the HOD object
    hod_object = hodmodel.HODModel(hod_type=hod_type,
                                   mass_min=hod_mass_min,
                                   mass_1=hod_mass_1,
                                   alpha=hod_alpha,
                                   siglogM=hod_siglogM,
                                   mass_0=hod_mass_0)

    # Build the halo model object.
    # We have two options for the parameters defining the bias:
    # - Use the original bias parameters from Sheth (2001), MoWhite2002
    # - Use the modified parameters following Tinker (2005)
    if use_tinker_bias_params:
        bpar = 0.35
        cpar = 0.8
    else:
        bpar = 0.5
        cpar = 0.6

    halo_object = halomodel.HaloModelMW02(cosmo=cosmo_object,
                                          powesp_lin_0=pk_linz0_object,
                                          redshift=redshift,
                                          par_b=bpar,
                                          par_c=cpar)

    # Now, create the Hankel FourierTransform object needed for the conversions
    # P(k) --> xi(r)
    ft_hankel = hankel.SymmetricFourierTransform(ndim=3, N=hankelN, h=hankelh)

    # Define the array of r-values for the HODClustering object
    assert rmax > rmin
    assert rmin >= 0
    assert nr > 0

    if rlog:
        rvals_array = np.logspace(np.log10(rmin), np.log10(rmax), nr)
    else:
        rvals_array = np.linspace(rmin, rmax, nr)

    # Create the Hankel FourierTransform object corresponding to the conversion
    # of the halo radial profiles from config. to Fourier space
    fprof_ft_hankel = hankel.SymmetricFourierTransform(ndim=3,
                                                       N=fprof_hankelN,
                                                       h=fprof_hankelh)

    # And finally, define the clustering object
    model_clustering_object = \
        HODClustering(redshift=redshift, cosmo=cosmo_object,
                      powesp_matter=pk_matter_object, hod_instance=hod_object,
                      halo_instance=halo_object, powesp_lin_0=pk_linz0_object,
                      f_gal=f_gal, gamma=gamma,
                      logM_min=logM_min, logM_max=logM_max,
                      logM_step=logM_step, scale_dep_bias=scale_dep_bias,
                      use_mvir_limit=use_mvir_limit,
                      halo_exclusion_model=halo_exclusion_model,
                      ft_hankel=ft_hankel, rvalues=rvals_array,
                      fprof_grid_log_krvir=fprof_grid_log_krvir,
                      fprof_grid_log_conc=fprof_grid_log_conc,
                      fprof_grid_gamma=fprof_grid_gamma,
                      fprof_grid_profile=fprof_grid_profile,
                      fprof_grid_rhos=fprof_grid_rhos,
                      fprof_ft_hankel=fprof_ft_hankel,
                      fprof_Nk_interp=fprof_Nk_interp,
                      fprof_Nm_interp=fprof_Nm_interp)

    print("New HODClustering object created, "
          f"galaxy density = {model_clustering_object.gal_dens:.4} (h/Mpc)^3")

    return model_clustering_object