def test_class_setup(): cosmology = astropy.cosmology.Planck13 assert cosmology.Om0 == cosmology.Odm0 + cosmology.Ob0 assert 1 == (cosmology.Om0 + cosmology.Ode0 + cosmology.Ok0 + cosmology.Ogamma0 + cosmology.Onu0) class_parameters = get_class_parameters(cosmology) try: from classy import Class cosmo = Class() cosmo.set(class_parameters) cosmo.compute() assert cosmo.h() == cosmology.h assert cosmo.T_cmb() == cosmology.Tcmb0.value assert cosmo.Omega_b() == cosmology.Ob0 # Calculate Omega(CDM)_0 two ways: assert abs((cosmo.Omega_m() - cosmo.Omega_b()) - (cosmology.Odm0 - cosmology.Onu0)) < 1e-8 assert abs(cosmo.Omega_m() - (cosmology.Om0 - cosmology.Onu0)) < 1e-8 # CLASS calculates Omega_Lambda itself so this is a non-trivial test. calculated_Ode0 = cosmo.get_current_derived_parameters( ['Omega_Lambda'])['Omega_Lambda'] assert abs(calculated_Ode0 - (cosmology.Ode0 + cosmology.Onu0)) < 1e-5 cosmo.struct_cleanup() cosmo.empty() except ImportError: pass
b4ar = [ 256.82199304134315, 78.62142674299282, 374.08451421691973, -146.54664459312085 ] norm = 1. # b1 = 1.909433 # b2 = -2.357092 # bG2 = 3.818261e-01 # css0 = -2.911944e+01 # css2 = -1.235181e+01 # Pshot = 2.032084e+03 # bGamma3 = 0. # b4 = 1.924983e+02 print('S8=', cosmo.sigma8() * (cosmo.Omega_m() / 0.3)**0.5) kmsMpc = 3.33564095198145e-6 rd = cosmo.rs_drag() print('rd=', rd) for j in range(len(chunk)): z = zs[j] b1 = b1ar[j] b2 = b2ar[j] bG2 = bG2ar[j] css0 = css0ar[j] css2 = css2ar[j] Pshot = Pshotar[j] bGamma3 = bGamma3ar[j] b4 = b4ar[j]
'P_k_max_h/Mpc': '100.', 'output': 'mPk,tCl', 'z_pk': z, 'non linear': ' SPT ', 'IR resummation': ' Yes ', 'Bias tracers': ' Yes ', 'RSD': ' Yes ', 'RSD only': 'No', 'AP': 'No' }) #cosmo.set({'k_pivot':'0.05','ln10^{10}A_s':'3.11655','n_s':'0.9649','alpha_s':'0.','Omega_k':'0.','Omega_fld':'0','YHe':0.25,'z_reio':'10.','T_cmb':'2.726','h':'0.6511406','omega_b':'0.0218022','N_ncdm':'0','N_eff':'3.045','omega_cdm':'0.116977','P_k_max_h/Mpc': '100.','output':'mPk,tCl','z_pk':'0.61','non linear':' SPT ','IR resummation':' Yes ','Bias tracers':' Yes ','RSD':' Yes ','RSD only':'No', 'Alcock-Paczynski effect':'Yes'}) t1 = time() cosmo.compute() h = cosmo.h() omb = cosmo.Omega_m() print(omb) #k1 = 0.7*1.028185622909e-5 #k1 = 1.e-6 #z = 0.0 #k1 = 0.1 #print(cosmo.pk(k1,z)) #print(cosmo.pk_lin(k1,z)) k = np.linspace(log(0.0001), log(50), 400) k = np.exp(k) testout = [[0 for x in range(42)] for y in range(len(k))] for i in range(len(k)): testout[i][0] = k[i]
def fitEE(self): # function to cimpute the band powers cosmo = Class() cosmo.set(self.cosmoParams) if self.settings.include_neutrino: cosmo.set(self.other_settings) cosmo.set(self.neutrino_settings) cosmo.set(self.class_argumets) try: cosmo.compute() except CosmoComputationError as failure_message: print(failure_message) self.sigma_8 = np.nan cosmo.struct_cleanup() cosmo.empty() return np.array([np.nan] * self.nzcorrs * self.bo_EE), np.array( [np.nan] * self.nzcorrs * self.bo_EE), np.array( [np.nan] * self.nzcorrs * self.bo_EE) except CosmoSevereError as critical_message: print(critical_message) self.sigma_8 = np.nan cosmo.struct_cleanup() cosmo.empty() return np.array([np.nan] * self.nzcorrs * self.bo_EE), np.array( [np.nan] * self.nzcorrs * self.bo_EE), np.array( [np.nan] * self.nzcorrs * self.bo_EE) # retrieve Omega_m and h from cosmo (CLASS) self.Omega_m = cosmo.Omega_m() self.small_h = cosmo.h() self.rho_crit = self.get_critical_density() # derive the linear growth factor D(z) linear_growth_rate = np.zeros_like(self.redshifts) # print self.redshifts for index_z, z in enumerate(self.redshifts): try: # for CLASS ver >= 2.6: linear_growth_rate[ index_z] = cosmo.scale_independent_growth_factor(z) except BaseException: # my own function from private CLASS modification: linear_growth_rate[index_z] = cosmo.growth_factor_at_z(z) # normalize to unity at z=0: try: # for CLASS ver >= 2.6: linear_growth_rate /= cosmo.scale_independent_growth_factor(0.) except BaseException: # my own function from private CLASS modification: linear_growth_rate /= cosmo.growth_factor_at_z(0.) # get distances from cosmo-module: r, dzdr = cosmo.z_of_r(self.redshifts) self.sigma_8 = cosmo.sigma8() # Get power spectrum P(k=l/r,z(r)) from cosmological module # this doesn't really have to go into the loop over fields! pk = np.zeros((self.settings.nellsmax, self.settings.nzmax), 'float64') k_max_in_inv_Mpc = self.settings.k_max_h_by_Mpc * self.small_h # note that this is being computed at only nellsmax # followed by an interplation record = np.zeros((self.settings.nellsmax, self.settings.nzmax)) record_k = np.zeros((self.settings.nellsmax, self.settings.nzmax)) for index_ells in range(self.settings.nellsmax): for index_z in range(1, self.settings.nzmax): k_in_inv_Mpc = (self.ells[index_ells] + 0.5) / r[index_z] z = self.redshifts[index_z] record[index_ells, index_z] = self.baryon_feedback_bias_sqr( k_in_inv_Mpc / self.small_h, self.redshifts[index_z], A_bary=self.systematics['A_bary']) record_k[index_ells, index_z] = k_in_inv_Mpc self.record_bf = record[:, 1:].flatten() self.record_k = record_k[:, 1:].flatten() self.k_max_in_inv_Mpc = k_max_in_inv_Mpc for index_ells in range(self.settings.nellsmax): for index_z in range(1, self.settings.nzmax): # standard Limber approximation: # k = ells[index_ells] / r[index_z] # extended Limber approximation (cf. LoVerde & Afshordi 2008): k_in_inv_Mpc = (self.ells[index_ells] + 0.5) / r[index_z] if k_in_inv_Mpc > k_max_in_inv_Mpc: pk_dm = 0. else: pk_dm = cosmo.pk(k_in_inv_Mpc, self.redshifts[index_z]) # pk[index_ells,index_z] = cosmo.pk(ells[index_ells]/r[index_z], self.redshifts[index_z]) if self.settings.baryon_feedback: pk[index_ells, index_z] = pk_dm * self.baryon_feedback_bias_sqr( k_in_inv_Mpc / self.small_h, self.redshifts[index_z], A_bary=self.systematics['A_bary']) else: pk[index_ells, index_z] = pk_dm # for KiDS-450 constant biases in photo-z are not sufficient: if self.settings.bootstrap_photoz_errors: # draw a random bootstrap n(z); borders are inclusive! random_index_bootstrap = np.random.randint( int(self.settings.index_bootstrap_low), int(self.settings.index_bootstrap_high) + 1) # print 'Bootstrap index:', random_index_bootstrap pz = np.zeros((self.settings.nzmax, self.nzbins), 'float64') pz_norm = np.zeros(self.nzbins, 'float64') for zbin in range(self.nzbins): redshift_bin = self.redshift_bins[zbin] # ATTENTION: hard-coded subfolder! # index can be recycled since bootstraps for tomographic bins # are independent! fname = os.path.join( self.settings.data_directory, '{:}/bootstraps/{:}/n_z_avg_bootstrap{:}.hist'.format( self.settings.photoz_method, redshift_bin, random_index_bootstrap)) z_hist, n_z_hist = np.loadtxt(fname, unpack=True) shift_to_midpoint = np.diff(z_hist)[0] / 2. spline_pz = itp.splrep(z_hist + shift_to_midpoint, n_z_hist) mask_min = self.redshifts >= z_hist.min() + shift_to_midpoint mask_max = self.redshifts <= z_hist.max() + shift_to_midpoint mask = mask_min & mask_max # points outside the z-range of the histograms are set to 0! pz[mask, zbin] = itp.splev(self.redshifts[mask], spline_pz) dz = self.redshifts[1:] - self.redshifts[:-1] pz_norm[zbin] = np.sum(0.5 * (pz[1:, zbin] + pz[:-1, zbin]) * dz) pr = pz * (dzdr[:, np.newaxis] / pz_norm) else: pr = self.pz * (dzdr[:, np.newaxis] / self.pz_norm) # pr[pr < 0] = 0 g = np.zeros((self.settings.nzmax, self.nzbins), 'float64') for zbin in range(self.nzbins): # assumes that z[0] = 0 for nr in range(1, self.settings.nzmax - 1): # for nr in range(self.nzmax - 1): fun = pr[nr:, zbin] * (r[nr:] - r[nr]) / r[nr:] g[nr, zbin] = np.sum(0.5 * (fun[1:] + fun[:-1]) * (r[nr + 1:] - r[nr:-1])) g[nr, zbin] *= 2. * r[nr] * (1. + self.redshifts[nr]) # Start loop over l for computation of C_l^shear Cl_GG_integrand = np.zeros( (self.settings.nzmax, self.nzbins, self.nzbins), 'float64') Cl_GG = np.zeros((self.settings.nellsmax, self.nzbins, self.nzbins), 'float64') Cl_II_integrand = np.zeros_like(Cl_GG_integrand) Cl_II = np.zeros_like(Cl_GG) Cl_GI_integrand = np.zeros_like(Cl_GG_integrand) Cl_GI = np.zeros_like(Cl_GG) dr = r[1:] - r[:-1] for index_ell in range(self.settings.nellsmax): # find Cl_integrand = (g(r) / r)**2 * P(l/r,z(r)) for zbin1 in range(self.nzbins): for zbin2 in range(zbin1 + 1): # self.nzbins): Cl_GG_integrand[1:, zbin1, zbin2] = g[1:, zbin1] * \ g[1:, zbin2] / r[1:]**2 * pk[index_ell, 1:] factor_IA = self.get_factor_IA( self.redshifts[1:], linear_growth_rate[1:], self.systematics['A_IA']) # / self.dzdr[1:] # print F_of_x # print self.eta_r[1:, zbin1].shape Cl_II_integrand[1:, zbin1, zbin2] = pr[1:, zbin1] * \ pr[1:, zbin2] * factor_IA**2 / r[1:]**2 * pk[index_ell, 1:] pref = g[1:, zbin1] * pr[1:, zbin2] + g[1:, zbin2] * pr[ 1:, zbin1] Cl_GI_integrand[1:, zbin1, zbin2] = pref * factor_IA / r[1:]**2 * pk[ index_ell, 1:] # Integrate over r to get C_l^shear_ij = P_ij(l) # C_l^shear_ii = 9/4 Omega0_m^2 H_0^4 \sum_0^rmax dr (g_i(r) g_j(r) # /r**2) P(k=l/r,z(r)) for zbin1 in range(self.nzbins): for zbin2 in range(zbin1 + 1): # self.nzbins): Cl_GG[index_ell, zbin1, zbin2] = np.sum( 0.5 * (Cl_GG_integrand[1:, zbin1, zbin2] + Cl_GG_integrand[:-1, zbin1, zbin2]) * dr) # here we divide by 16, because we get a 2^2 from g(z)! Cl_GG[index_ell, zbin1, zbin2] *= 9. / 16. * \ self.Omega_m**2 # in units of Mpc**4 # dimensionless Cl_GG[index_ell, zbin1, zbin2] *= (self.small_h / 2997.9)**4 Cl_II[index_ell, zbin1, zbin2] = np.sum( 0.5 * (Cl_II_integrand[1:, zbin1, zbin2] + Cl_II_integrand[:-1, zbin1, zbin2]) * dr) Cl_GI[index_ell, zbin1, zbin2] = np.sum( 0.5 * (Cl_GI_integrand[1:, zbin1, zbin2] + Cl_GI_integrand[:-1, zbin1, zbin2]) * dr) # here we divide by 4, because we get a 2 from g(r)! Cl_GI[index_ell, zbin1, zbin2] *= 3. / 4. * self.Omega_m Cl_GI[index_ell, zbin1, zbin2] *= (self.small_h / 2997.9)**2 # ordering of redshift bins is correct in definition of theory below! theory_EE_GG = np.zeros((self.nzcorrs, self.bo_EE), 'float64') theory_EE_II = np.zeros((self.nzcorrs, self.bo_EE), 'float64') theory_EE_GI = np.zeros((self.nzcorrs, self.bo_EE), 'float64') index_corr = 0 # A_noise_corr = np.zeros(self.nzcorrs) for zbin1 in range(self.nzbins): for zbin2 in range(zbin1 + 1): # self.nzbins): # correlation = 'z{:}z{:}'.format(zbin1 + 1, zbin2 + 1) # print(zbin1, zbin2) Cl_sample_GG = Cl_GG[:, zbin1, zbin2] spline_Cl_GG = itp.splrep(self.ells, Cl_sample_GG) D_l_EE_GG = self.ell_norm * \ itp.splev(self.ells_sum, spline_Cl_GG) theory_EE_GG[index_corr, :] = self.get_theory( self.ells_sum, D_l_EE_GG, self.band_window_matrix, index_corr, band_type_is_EE=True) Cl_sample_GI = Cl_GI[:, zbin1, zbin2] spline_Cl_GI = itp.splrep(self.ells, Cl_sample_GI) D_l_EE_GI = self.ell_norm * \ itp.splev(self.ells_sum, spline_Cl_GI) theory_EE_GI[index_corr, :] = self.get_theory( self.ells_sum, D_l_EE_GI, self.band_window_matrix, index_corr, band_type_is_EE=True) Cl_sample_II = Cl_II[:, zbin1, zbin2] spline_Cl_II = itp.splrep(self.ells, Cl_sample_II) D_l_EE_II = self.ell_norm * \ itp.splev(self.ells_sum, spline_Cl_II) theory_EE_II[index_corr, :] = self.get_theory( self.ells_sum, D_l_EE_II, self.band_window_matrix, index_corr, band_type_is_EE=True) index_corr += 1 cosmo.struct_cleanup() cosmo.empty() return theory_EE_GG.flatten(), theory_EE_GI.flatten( ), theory_EE_II.flatten()
matplotlib.mathtext.rcParams['legend.fontsize']='medium' plt.rcParams["figure.figsize"] = [8.0,6.0] M = Class() # Table I of 1908.06995, third column, best-fit values # Note: f and m found by trial-and-error to give the best-fit fEDE=.12, zc=10^3.562=3647. M.set({'f_scf': 3.98e+26, 'm_scf': 5.31e-28, 'thetai_scf': 2.83, 'A_s': 2.215e-09, 'n_s': 0.9889, '100*theta_s': 1.04152, 'omega_b': 0.02253, 'omega_cdm': 0.1306, 'm_ncdm': 0.06, 'tau_reio': 0.072}) #'non linear':can choose 'halofit' or 'HMCODE' M.set({'non linear':'HMCODE','N_ncdm':1, 'N_ur':2.0328, 'Omega_Lambda':0.0, 'Omega_fld':0, 'Omega_scf':-1, 'n_scf':3, 'CC_scf':1, 'scf_parameters':'1, 1, 1, 1, 1, 0.0', 'scf_tuning_index':3, 'attractor_ic_scf':'no', 'output':'tCl pCl lCl mPk', 'lensing':'yes', 'l_max_scalars':2508, 'P_k_max_h/Mpc':20,'z_max_pk':4.}) M.compute() print(M.Omega_m()) baM = M.get_background() fEDE = M.fEDE() z_c = M.z_c() baH = baM['H [1/Mpc]'] baT = baM['conf. time [Mpc]'] baa = 1/(1 + baM['z']) bV = baM['V_e_scf'] bpp = baM["phi'_scf"] baCrit = baM['(.)rho_crit'] rho_scf = (bpp*bpp/(2*baa*baa) + bV)/3.
class Cosmology(object): """ Class to hold the basic cosmology and CLASS attributes. This can be initialized by a set of cosmological parameters or a pre-defined cosmology. Loaded cosmological models: - **Planck18**: Bestfit cosmology from Planck 2018, using the baseline TT,TE,EE+lowE+lensing likelihood. - **Quijote**: Fiducial cosmology from the Quijote simulations of Francisco Villaescusa-Navarro et al. - **Abacus**: Fiducial cosmology from the Abacus simulations of Lehman Garrison et al. Args: redshift (float): Desired redshift :math:`z` name (str): Load cosmology from a list of predetermined cosmologies (see above). params (kwargs): Any other CLASS parameters. (Note that sigma8 does not seem to be supported by CLASS in Python 3). Keyword Args: verb (bool): If true output useful messages througout run-time, default: False. npoints (int): Number of points to use in the interpolators for sigma^2, default: 100000 """ loaded_models = {'Quijote':{"h":0.6711,"omega_cdm":(0.3175 - 0.049)*0.6711**2, "Omega_b":0.049, "n_s":0.9624, "N_eff":3.046, "A_s":2.134724e-09}, #"sigma8":0.834, 'Abacus':{"h":0.6726,"omega_cdm":0.1199, "omega_b":0.02222,"n_s":0.9652,"A_s":2.135472e-09,#"sigma8":0.830, "N_eff":3.046}, 'Planck18':{"h":0.6732,"omega_cdm":0.12011,"omega_b":0.022383, "n_s":0.96605,"A_s":2.042644e-09}}#,"sigma8":0.8120}} def __init__(self,redshift,name="",verb=False,npoints=int(1e5),**params): """ Initialize the cosmology class with cosmological parameters or a defined model. """ ## Load parameters into a dictionary to pass to CLASS class_params = dict(**params) if len(name)>0: if len(params.items())>0: raise Exception('Must either choose a preset cosmology or specify parameters!') if name in self.loaded_models.keys(): if verb: print('Loading the %s cosmology at z = %.2f'%(name,redshift)) loaded_model = self.loaded_models[name] for key in loaded_model.keys(): class_params[key] = loaded_model[key] else: raise Exception("This cosmology isn't yet implemented") else: if len(params.items())==0: if verb: print('Using default CLASS cosmology') for name, param in params.items(): class_params[name] = param ## # Check we have the correct parameters if 'sigma8' in class_params.keys() and 'A_s' in class_params.keys(): raise NameError('Cannot specify both A_s and sigma8!') ## Define other parameters self.z = redshift self.a = 1./(1.+redshift) if 'output' not in class_params.keys(): class_params['output']='mPk' if 'P_k_max_h/Mpc' not in class_params.keys() and 'P_k_max_1/Mpc' not in class_params.keys(): class_params['P_k_max_h/Mpc']=300. if 'z_pk' in class_params.keys(): assert class_params['z_pk']==redshift, "Can't pass multiple redshifts!" else: class_params['z_pk']=redshift ## Load CLASS and set parameters if verb: print('Loading CLASS') self.cosmo = Class() self.cosmo.set(class_params) self.cosmo.compute() self.h = self.cosmo.h() self.name = name self.npoints = npoints self.verb = verb ## Check if we're using neutrinos here if self.cosmo.Omega_nu>0.: if self.verb: print("Using a neutrino fraction of Omega_nu = %.3e"%self.cosmo.Omega_nu) self.use_neutrinos = True # Define neutrino mass fraction self.f_nu = self.cosmo.Omega_nu/self.cosmo.Omega_m() if self.cosmo.Neff()>3.5: print("N_eff > 3.5, which seems large (standard value: 3.046). This may indicate that N_ur has not been set.") else: if self.verb: print("Assuming massless neturinos.") self.use_neutrinos = False ## Create a vectorized sigma(R) function from CLASS if self.use_neutrinos: self.vector_sigma_R = np.vectorize(lambda r: self.cosmo.sigma_cb(r/self.h,self.z)) else: self.vector_sigma_R = np.vectorize(lambda r: self.cosmo.sigma(r/self.h,self.z)) # get density in physical units at z = 0 # rho_critical is in Msun/h / (Mpc/h)^3 units # rhoM is in **physical** units of Msun/Mpc^3 self.rho_critical = ((3.*100.*100.)/(8.*np.pi*6.67408e-11)) * (1000.*1000.*3.085677581491367399198952281E+22/1.9884754153381438E+30) self.rhoM = self.rho_critical*self.cosmo.Omega0_m() def compute_linear_power(self,kh,kh_min=0.,with_neutrinos=False): """Compute the linear power spectrum from CLASS for a vector of input k. If set, we remove any modes below some minimum k. Args: kh (float, np.ndarray): Wavenumber or vector of wavenumbers (in h/Mpc units) to compute linear power with. Keyword Args: kh_min (float): Value of k (in h/Mpc units) below which to set :math:`P(k) = 0`, default: 0. with_neutrinos (bool): If True, return the full matter power spectrum, else return the CDM+baryon power spectrum (which is generally used in the halo model). Default: False. Returns: np.ndarray: Linear power spectrum in :math:`(h^{-1}\mathrm{Mpc})^3` units """ if type(kh)==np.ndarray: # Define output vector and filter modes with too-small k output = np.zeros_like(kh) filt = np.where(kh>kh_min) N_k = len(filt[0]) # Compute Pk using CLASS (vectorized) if not hasattr(self,'vector_linear_power'): ## NB: This works in physical 1/Mpc units so we convert here if self.use_neutrinos: # Here we need both the CDM+baryon (cb) power spectra and the full matter power spectra # The CDM+baryon spectrum is used for the halo model parts, and the residual (matter-cb) added at the end self.vector_linear_power = np.vectorize(lambda k: self.cosmo.pk_cb_lin(k*self.h,self.z)*self.h**3.) self.vector_linear_power_total = np.vectorize(lambda k: self.cosmo.pk_lin(k*self.h,self.z)*self.h**3.) else: self.vector_linear_power = np.vectorize(lambda k: self.cosmo.pk_lin(k*self.h,self.z)*self.h**3.) if self.use_neutrinos and with_neutrinos: output[filt] = self.vector_linear_power_total(kh[filt]) else: output[filt] = self.vector_linear_power(kh[filt]) return output else: if kh<kh_min: return 0. else: if self.use_neutrinos and with_neutrinos: return self.vector_linear_power_total(kh) else: return self.vector_linear_power(kh) def sigma_logM_int(self,logM_h): """Return the value of :math:`\sigma(M,z)` using the prebuilt interpolators, which are constructed if not present. Args: logM (np.ndarray): Input :math:`\log_{10}(M/h^{-1}M_\mathrm{sun})` Returns: np.ndarray: :math:`\sigma(M,z)` """ if not hasattr(self,'sigma_logM_int_func'): self._interpolate_sigma_and_deriv(npoints=self.npoints) return self._sigma_logM_int_func(logM_h) def dlns_dlogM_int(self,logM_h): """Return the value of :math:`d\ln\sigma/d\log M` using the prebuilt interpolators, which are constructed if not present. Args: logM (np.ndarray): Input :math:`\log_{10}(M/h^{-1}M_\mathrm{sun})` Returns: np.ndarray: :math:`d\ln\sigma/d\log M` """ if not hasattr(self,'dlns_dlogM_int_func'): self._interpolate_sigma_and_deriv(npoints=self.npoints) return self._dlns_dlogM_int_func(logM_h) def _sigmaM(self,M_h): """Compute :math:`\sigma(M,z)` from CLASS as a vector function. Args: M_h (np.ndarray): Mass in :math:`h^{-1}M_\mathrm{sun}` units. z (float): Redshift. Returns: np.ndarray: :math:`\sigma(M,z)` """ # convert to Lagrangian radius r_h = np.power((3.*M_h)/(4.*np.pi*self.rhoM),1./3.) sigma_func = self.vector_sigma_R(r_h) return sigma_func def _interpolate_sigma_and_deriv(self,logM_h_min=6,logM_h_max=17,npoints=int(1e5)): """Create an interpolator function for :math:`d\ln\sigma/d\log M` and :math:`sigma(M)`. NB: This has no effect if the interpolator has already been computed. Keyword Args: logM_min (float): Minimum mass in :math:`\log_{10}(M/h^{-1}M_\mathrm{sun})`, default: 6 logM_max (float): Maximum mass in :math:`\log_{10}(M/h^{-1}M_\mathrm{sun})`, default 17 npoints (int): Number of sampling points, default 100000 """ if not hasattr(self,'_sigma_logM_int_func'): if self.verb: print("Creating an interpolator for sigma(M) and its derivative.") ## Compute log derivative by interpolation and numerical differentiation # First compute the grid of M and sigma M_h_grid = np.logspace(logM_h_min,logM_h_max,10000) all_sigM = self._sigmaM(M_h_grid) logM_h_grid = np.log10(M_h_grid) # Define ln(sigma) and numerical derivatives all_lns = np.log(all_sigM) all_diff = -np.diff(all_lns)/np.diff(logM_h_grid) mid_logM_h = 0.5*(logM_h_grid[:-1]+logM_h_grid[1:]) self._sigma_logM_int_func = interp1d(logM_h_grid,all_sigM) self._dlns_dlogM_int_func = interp1d(mid_logM_h,all_diff) def _h_over_h0(self): """Return the value of :math:`H(z)/H(0)` at the class redshift Returns: float: :math:`H(z)/H(0)` """ Omega0_k = 1.-self.cosmo.Omega0_m()-self.cosmo.Omega_Lambda() Ea = np.sqrt((self.cosmo.Omega0_m()+self.cosmo.Omega_Lambda()*pow(self.a,-3)+Omega0_k*self.a)/pow(self.a,3)) return Ea def _Omega_m(self): """Return the value of :math:`\Omega_m(z)` at the class redshift