def test_cosmo_methods(): """ Check that all pyccl functions that take cosmo as their first argument are methods of the Cosmology object. """ from inspect import getmembers, isfunction, signature from pyccl import background, bcm, boltzmann, \ cls, correlations, covariances, neutrinos, \ pk2d, power, tk3d, tracers, halos, nl_pt from pyccl.core import CosmologyVanillaLCDM cosmo = CosmologyVanillaLCDM() subs = [ background, boltzmann, bcm, cls, correlations, covariances, neutrinos, pk2d, power, tk3d, tracers, halos, nl_pt ] funcs = [getmembers(sub, isfunction) for sub in subs] funcs = [func for sub in funcs for func in sub] for name, func in funcs: pars = signature(func).parameters if list(pars)[0] == "cosmo": _ = getattr(cosmo, name) # quantitative assert ccl.sigma8(cosmo) == cosmo.sigma8() assert ccl.rho_x(cosmo, 1., "matter", is_comoving=False) == \ cosmo.rho_x(1., "matter", is_comoving=False) assert ccl.get_camb_pk_lin(cosmo).eval(1., 1., cosmo) == \ cosmo.get_camb_pk_lin().eval(1., 1., cosmo) prof = ccl.halos.HaloProfilePressureGNFW() hmd = ccl.halos.MassDef200m() hmf = ccl.halos.MassFuncTinker08(cosmo) hbf = ccl.halos.HaloBiasTinker10(cosmo) hmc = ccl.halos.HMCalculator(cosmo, massfunc=hmf, hbias=hbf, mass_def=hmd) assert ccl.halos.halomod_power_spectrum(cosmo, hmc, 1., 1., prof) == \ cosmo.halomod_power_spectrum(hmc, 1., 1., prof)
def pk(self, k, a, lmmin=6., lmmax=17., nlm=256, return_decomposed=False): """ Returns power spectrum at redshift `z` sampled at all values of k in `k`. k : array of wavenumbers in CCL units a : scale factor lmmin, lmmax, nlm : mass edges and sampling rate for mass integral. return_decomposed : if True, returns 1-halo, 2-halo, bias, shot noise and total (see below for order). """ z = 1. / a - 1. marr = np.logspace(lmmin, lmmax, nlm) dlm = np.log10(marr[1] / marr[0]) u_s = self.u_sat(z, marr, k) hmf = ccl.massfunc(self.cosmo, marr, a) hbf = ccl.halo_bias(self.cosmo, marr, a) rhoM = ccl.rho_x(self.cosmo, a, "matter", is_comoving=True) n0_1h = (rhoM - np.sum(hmf * marr) * dlm) / marr[0] n0_2h = (rhoM - np.sum(hmf * hbf * marr) * dlm) / marr[0] #Number of galaxies fc = self.fc_f(z) ngm = self.n_tot(z, marr) ncm = self.n_cent(z, marr) nsm = self.n_sat(z, marr) #Number density ng = np.sum(hmf * ngm) * dlm + n0_1h * ngm[0] if ng <= 1E-16: #Make sure we won't divide by 0 return None #Bias b_hod = np.sum( (hmf * hbf * ncm)[None, :] * (fc + nsm[None, :] * u_s[:, :]), axis=1) * dlm + n0_2h * ncm[0] * (fc + nsm[0] * u_s[:, 0]) b_hod /= ng #1-halo #p1h=np.sum((hmf*ncm**2)[None,:]*(fc+nsm[None,:]*u_s[:,:])**2,axis=1)*dlm+n0_1h*(ncm[0]*(fc+nsm[0]*u_s[:,0]))**2 p1h = np.sum( (hmf * ncm)[None, :] * (2 * fc * nsm[None, :] * u_s[:, :] + (nsm[None, :] * u_s[:, :])**2), axis=1) * dlm + n0_1h * ncm[0] * (2 * fc * nsm[0] * u_s[:, 0] + (nsm[0] * u_s[:, 0])**2) p1h /= ng**2 #2-halo p2h = b_hod**2 * ccl.linear_matter_power(self.cosmo, k, a) if return_decomposed: return p1h + p2h, p1h, p2h, np.ones_like(k) / ng, b_hod else: return p1h + p2h
def _norm(self, cosmo, mass_def, M, a): """ Battaglia profile normalization (P200, above Eq. (9) in Battaglia et al., 2012) N = G M200c 200 rho_crit,phys(a) f_b/(2 R200c,phys) f_b = Omega_b/Omega_m Units are Msun/(Mpc s^2) :param cosmo: :param mass_def: :param M: :param a: :return: """ # Since the Battaglia profile is defined in physical units the norm needs to be in physical units as well R_Delta = mass_def.get_radius(cosmo, M, a) f_b = cosmo['Omega_b'] / cosmo['Omega_m'] P_Delta = G_MPC_MSUN * M * mass_def.get_Delta(cosmo, a) * ccl.rho_x( cosmo, a, 'critical') * f_b / (2. * R_Delta) return P_Delta
def check_background(cosmo): """ Check that background and growth functions can be run. """ # Types of scale factor input (scalar, list, array) a_scl = 0.5 is_comoving = 0 a_lst = [0.2, 0.4, 0.6, 0.8, 1.] a_arr = np.linspace(0.2, 1., 5) # growth_factor assert_(all_finite(ccl.growth_factor(cosmo, a_scl))) assert_(all_finite(ccl.growth_factor(cosmo, a_lst))) assert_(all_finite(ccl.growth_factor(cosmo, a_arr))) # growth_factor_unnorm assert_(all_finite(ccl.growth_factor_unnorm(cosmo, a_scl))) assert_(all_finite(ccl.growth_factor_unnorm(cosmo, a_lst))) assert_(all_finite(ccl.growth_factor_unnorm(cosmo, a_arr))) # growth_rate assert_(all_finite(ccl.growth_rate(cosmo, a_scl))) assert_(all_finite(ccl.growth_rate(cosmo, a_lst))) assert_(all_finite(ccl.growth_rate(cosmo, a_arr))) # comoving_radial_distance assert_(all_finite(ccl.comoving_radial_distance(cosmo, a_scl))) assert_(all_finite(ccl.comoving_radial_distance(cosmo, a_lst))) assert_(all_finite(ccl.comoving_radial_distance(cosmo, a_arr))) # comoving_angular_distance assert_(all_finite(ccl.comoving_angular_distance(cosmo, a_scl))) assert_(all_finite(ccl.comoving_angular_distance(cosmo, a_lst))) assert_(all_finite(ccl.comoving_angular_distance(cosmo, a_arr))) # h_over_h0 assert_(all_finite(ccl.h_over_h0(cosmo, a_scl))) assert_(all_finite(ccl.h_over_h0(cosmo, a_lst))) assert_(all_finite(ccl.h_over_h0(cosmo, a_arr))) # luminosity_distance assert_(all_finite(ccl.luminosity_distance(cosmo, a_scl))) assert_(all_finite(ccl.luminosity_distance(cosmo, a_lst))) assert_(all_finite(ccl.luminosity_distance(cosmo, a_arr))) # scale_factor_of_chi assert_(all_finite(ccl.scale_factor_of_chi(cosmo, a_scl))) assert_(all_finite(ccl.scale_factor_of_chi(cosmo, a_lst))) assert_(all_finite(ccl.scale_factor_of_chi(cosmo, a_arr))) # omega_m_a assert_(all_finite(ccl.omega_x(cosmo, a_scl, 'matter'))) assert_(all_finite(ccl.omega_x(cosmo, a_lst, 'matter'))) assert_(all_finite(ccl.omega_x(cosmo, a_arr, 'matter'))) # Fractional density of different types of fluid assert_(all_finite(ccl.omega_x(cosmo, a_arr, 'dark_energy'))) assert_(all_finite(ccl.omega_x(cosmo, a_arr, 'radiation'))) assert_(all_finite(ccl.omega_x(cosmo, a_arr, 'curvature'))) assert_(all_finite(ccl.omega_x(cosmo, a_arr, 'neutrinos_rel'))) assert_(all_finite(ccl.omega_x(cosmo, a_arr, 'neutrinos_massive'))) # Check that omega_x fails if invalid component type is passed assert_raises(ValueError, ccl.omega_x, cosmo, a_scl, 'xyz') # rho_crit_a assert_(all_finite(ccl.rho_x(cosmo, a_scl, 'critical', is_comoving))) assert_(all_finite(ccl.rho_x(cosmo, a_lst, 'critical', is_comoving))) assert_(all_finite(ccl.rho_x(cosmo, a_arr, 'critical', is_comoving))) # rho_m_a assert_(all_finite(ccl.rho_x(cosmo, a_scl, 'matter', is_comoving))) assert_(all_finite(ccl.rho_x(cosmo, a_lst, 'matter', is_comoving))) assert_(all_finite(ccl.rho_x(cosmo, a_arr, 'matter', is_comoving)))
def test_background_rho_x(a, kind, is_comoving): val = ccl.rho_x(COSMO_NU, a, kind, is_comoving) assert np.all(np.isfinite(val)) assert np.shape(val) == np.shape(a)
def test_background_rho_x_raises(): with pytest.raises(ValueError): ccl.rho_x(COSMO, 1, 'blah', False)
def hm_bias(cosmo, a, profile, logMrange=(6, 17), mpoints=128, selection=None, **kwargs): """Computes the halo model prediction for the bias of a given tracer. Args: cosmo (:obj:`ccl.Cosmology`): cosmology. a (array): array of scale factor values profile (`Profile`): a profile. Only Arnaud and HOD are implemented. logMrange (tuple): limits of integration in log10(M/Msun) mpoints (int): number of mass samples selection (function): selection function in (M,z) to include in the calculation. Pass None if you don't want to select a subset of the M-z plane. **kwargs: parameter used internally by the profiles. """ # Input handling a = np.atleast_1d(a) # Profile normalisations Unorm = profile.profnorm(cosmo, a, squeeze=False, **kwargs) Unorm = Unorm[..., None] # Set up integration boundaries logMmin, logMmax = logMrange # log of min and max halo mass [Msun] mpoints = int(mpoints) # number of integration points M = np.logspace(logMmin, logMmax, mpoints) # masses sampled # Out-of-loop optimisations Dm = profile.Delta / ccl.omega_x(cosmo, a, "matter") # CCL uses Delta_m with warnings.catch_warnings(): warnings.simplefilter("ignore") mfunc = np.array( [ccl.massfunc(cosmo, M, A1, A2) for A1, A2 in zip(a, Dm)]) bh = np.array( [ccl.halo_bias(cosmo, M, A1, A2) for A1, A2 in zip(a, Dm)]) # shape transformations mfunc, bh = mfunc.T[..., None], bh.T[..., None] if selection is not None: select = np.array([selection(M, 1. / aa - 1) for aa in a]) select = select.T[..., None] else: select = 1 U, _ = profile.fourier_profiles(cosmo, np.array([0.001]), M, a, squeeze=False, **kwargs) # Tinker mass function is given in dn/dlog10M, so integrate over d(log10M) b2h = simps(bh * mfunc * select * U, x=np.log10(M), axis=0).squeeze() # Contribution from small masses (added in the beginning) rhoM = ccl.rho_x(cosmo, a, "matter", is_comoving=True) dlM = (logMmax - logMmin) / (mpoints - 1) mfunc, bh = mfunc.squeeze(), bh.squeeze() # squeeze extra dimensions n0_2h = np.array((rhoM - np.dot(M, mfunc * bh) * dlM) / M[0])[None, ..., None] b2h += (n0_2h * U[0]).squeeze() b2h /= Unorm.squeeze() return b2h.squeeze()
def hm_power_spectrum(cosmo, k, a, profiles, logMrange=(6, 17), mpoints=128, include_1h=True, include_2h=True, squeeze=True, hm_correction=None, selection=None, **kwargs): """Computes the halo model prediction for the 3D cross-power spectrum of two quantities. Args: cosmo (:obj:`ccl.Cosmology`): cosmology. k (array): array of wavenumbers in units of Mpc^-1 a (array): array of scale factor values profiles (tuple): tuple of two profile objects (currently only Arnaud and HOD are implemented) corresponding to the two quantities being correlated. logMrange (tuple): limits of integration in log10(M/Msun) mpoints (int): number of mass samples include_1h (bool): whether to include the 1-halo term. include_2h (bool): whether to include the 2-halo term. hm_correction (:obj:`HalomodCorrection` or None): Correction to the halo model in the transition regime. If `None`, no correction is applied. selection (function): selection function in (M,z) to include in the calculation. Pass None if you don't want to select a subset of the M-z plane. **kwargs: parameter used internally by the profiles. """ # Input handling a, k = np.atleast_1d(a), np.atleast_2d(k) # Profile normalisations p1, p2 = profiles Unorm = p1.profnorm(cosmo, a, squeeze=False, **kwargs) if p1.name == p2.name: Vnorm = Unorm else: Vnorm = p2.profnorm(cosmo, a, squeeze=False, **kwargs) if (Vnorm < 1e-16).any() or (Unorm < 1e-16).any(): return None # zero division Unorm, Vnorm = Unorm[..., None], Vnorm[..., None] # transform axes # Set up integration boundaries logMmin, logMmax = logMrange # log of min and max halo mass [Msun] mpoints = int(mpoints) # number of integration points M = np.logspace(logMmin, logMmax, mpoints) # masses sampled # Out-of-loop optimisations Pl = np.array( [ccl.linear_matter_power(cosmo, k[i], a) for i, a in enumerate(a)]) Dm = p1.Delta / ccl.omega_x(cosmo, a, "matter") # CCL uses Delta_m with warnings.catch_warnings(): warnings.simplefilter("ignore") mfunc = np.array( [ccl.massfunc(cosmo, M, A1, A2) for A1, A2 in zip(a, Dm)]) if selection is not None: select = np.array([selection(M, 1. / aa - 1) for aa in a]) mfunc *= select # tinker10 halo bias csm = ccl.Cosmology(Omega_c=cosmo["Omega_c"], Omega_b=cosmo["Omega_b"], h=cosmo["h"], sigma8=cosmo["sigma8"], n_s=cosmo["n_s"], mass_function="tinker10") with warnings.catch_warnings(): warnings.simplefilter("ignore") bh = np.array([ccl.halo_bias(csm, M, A1, A2) for A1, A2 in zip(a, Dm)]) # shape transformations mfunc, bh = mfunc.T[..., None], bh.T[..., None] if selection is not None: select = np.array([selection(M, 1. / aa - 1) for aa in a]) select = select.T[..., None] else: select = 1 U, UU = p1.fourier_profiles(cosmo, k, M, a, squeeze=False, **kwargs) # optimise for autocorrelation (no need to recompute) if p1.name == p2.name: V = U UV = UU else: V, VV = p2.fourier_profiles(cosmo, k, M, a, squeeze=False, **kwargs) r = kwargs["r_corr"] if "r_corr" in kwargs else 0 UV = U * V * (1 + r) # Tinker mass function is given in dn/dlog10M, so integrate over d(log10M) P1h = simps(mfunc * select * UV, x=np.log10(M), axis=0) b2h_1 = simps(bh * mfunc * select * U, x=np.log10(M), axis=0) b2h_2 = simps(bh * mfunc * select * V, x=np.log10(M), axis=0) # Contribution from small masses (added in the beginning) rhoM = ccl.rho_x(cosmo, a, "matter", is_comoving=True) dlM = (logMmax - logMmin) / (mpoints - 1) mfunc, bh = mfunc.squeeze(), bh.squeeze() # squeeze extra dimensions n0_1h = np.array((rhoM - np.dot(M, mfunc) * dlM) / M[0])[None, ..., None] n0_2h = np.array((rhoM - np.dot(M, mfunc * bh) * dlM) / M[0])[None, ..., None] P1h += (n0_1h * U[0] * V[0]).squeeze() b2h_1 += (n0_2h * U[0]).squeeze() b2h_2 += (n0_2h * V[0]).squeeze() F = (include_1h * P1h + include_2h * (Pl * b2h_1 * b2h_2)) / (Unorm * Vnorm) if hm_correction is not None: for ia, (aa, kk) in enumerate(zip(a, k)): R = hm_correction.rk_interp(kk, aa) F[ia, :] *= R return F.squeeze() if squeeze else F
def get_halomod_pk(cp,karr,z,integrate=True,fname_out=None) : cosmo=ccl.Cosmology(Omega_c=cp['Om_m']-cp['Om_b'],Omega_b=cp['Om_b'],h=cp['h'], sigma8=cp['sig8'],n_s=cp['n'], transfer_function='eisenstein_hu',matter_power_spectrum='linear') lmarr=LMMIN+(LMMAX-LMMIN)*(np.arange(NM)+0.5)/NM #log(M*h/M_sum) dlm=(LMMAX-LMMIN)/NM lmarrb=np.zeros(NM+2); lmarrb[0]=lmarr[0]-dlm; lmarrb[1:-1]=lmarr; lmarrb[-1]=lmarr[-1]+dlm marr=10.**lmarr #M (in Msun/h) M_h Ms/h = M Ms marrb=10.**lmarrb #M (in Msun/h) M_h Ms/h = M Ms sigmarrb=ccl.sigmaM(cosmo,marrb/cp['h'],1./(1+z)) sigmarr=sigmarrb[1:-1] dlsMdl10M=np.fabs((sigmarrb[2:]-sigmarrb[:-2])/(2*dlm))/sigmarr omega_z=cp['Om_m']*(1+z)**3/(cp['Om_m']*(1+z)**3+1-cp['Om_m']) delta_c=params['DELTA_C']*(1+0.012299*np.log10(omega_z)) Delta_v=(18*np.pi**2+82*(omega_z-1)-39*(omega_z-1)**2)/omega_z fM=st_gs(sigmarr,delta_c)*dlsMdl10M bM=st_b1(sigmarr,delta_c) cM=duffy_c(marr,z) cMf=interp1d(lmarr,cM,kind='linear',bounds_error=False,fill_value=cM[0]) rhoM=ccl.rho_x(cosmo,1.,'matter')/cp['h']**2 #Compute mass function normalization fM0=1-np.sum(fM)*dlm fbM0=1-np.sum(fM*bM)*dlm rvM=(3*marr/(4*np.pi*rhoM*Delta_v))**0.333333333333 rsM=rvM/cM rsM0=(3*10.**LM0/(4*np.pi*rhoM*Delta_v))**0.333333333/duffy_c(10.**LM0,z) rsMf=interp1d(lmarr,rsM,kind='linear',bounds_error=False,fill_value=rsM0) f1hf=interp1d(lmarr,marr*fM/rhoM,kind='linear',bounds_error=False,fill_value=0) f1h0=fM0*10.**LM0/rhoM f2hf=interp1d(lmarr,fM*bM,kind='linear',bounds_error=False,fill_value=0) f2h0=fbM0 #NFW profile def u_nfw(lm,k) : x=k*rsMf(lm) #k*r_s c=cMf(lm) sic,cic=sici(x*(1+c)) six,cix=sici(x) fsin=np.sin(x)*(sic-six) fcos=np.cos(x)*(cic-cix) fsic=np.sin(c*x)/(x*(1+c)) fcon=np.log(1.+c)-c/(1+c) return (fsin+fcos-fsic)/fcon def p1h(k) : def integ(lm) : u=u_nfw(lm,k) f1h=f1hf(lm) return u*u*f1h if integrate : return quad(integ,lmarr[0],lmarr[-1])[0]+f1h0*(u_nfw(LM0,k))**2 else : return np.sum(integ(lmarr))*dlm+f1h0*(u_nfw(LM0,k))**2 def b2h(k) : def integ(lm) : u=u_nfw(lm,k) f2h=f2hf(lm) return u*f2h if integrate : return quad(integ,lmarr[0],lmarr[-1])[0]+f2h0*u_nfw(LM0,k) else : return np.sum(integ(lmarr))*dlm+f2h0*u_nfw(LM0,k) p1harr=np.array([p1h(kk) for kk in karr]) b2harr=np.array([b2h(kk) for kk in karr]) pklin=ccl.linear_matter_power(cosmo,karr*cp['h'],1./(1+z))*cp['h']**3 p2harr=pklin*b2harr**2 ptarr=p1harr+p2harr np.savetxt(fname_out,np.transpose([karr,pklin,p2harr,p1harr,ptarr])) return pklin,pklin*b2harr**2,p1harr,pklin*b2harr**2+p1harr
def pk_gm(self, k, a, lmmin=6., lmmax=17., nlm=256, return_decomposed=False): """ Returns galaxy-matter power spectrum at a single scale-factor a for array of wave vectors k. :param k: wave vector array :param a: single scale factor value :param lmmin: Mmin for HOD integrals :param lmmax: Mmax for HOD integrals :param nlm: sampling rate for mass integral :param return_decomposed: boolean tag, if True return 1h, 2h power spectrum separately :return: """ z = 1. / a - 1. marr = np.logspace(lmmin, lmmax, nlm) dlm = np.log10(marr[1] / marr[0]) u_nfw = self.u_sat(z, marr, k) hmf = ccl.massfunc(self.cosmo, marr, a) hbf = ccl.halo_bias(self.cosmo, marr, a) rhoM = ccl.rho_x(self.cosmo, a, "matter", is_comoving=True) n0_1h = (rhoM - np.sum(hmf * marr) * dlm) / marr[0] n0_2h = (rhoM - np.sum(hmf * hbf * marr) * dlm) / marr[0] # n0_2h = (rhoM - np.sum(hmf*hbf*marr)*dlm) #Number of galaxies fc = self.fc_f(z) ngm = self.n_tot(z, marr) ncm = self.n_cent(z, marr) nsm = self.n_sat(z, marr) #Number density ng = np.sum(hmf * ngm) * dlm + n0_1h * ngm[0] if ng <= 1E-16: #Make sure we won't divide by 0 return None #Bias b_hod=np.sum((hmf*hbf*ncm)[None,:]*(fc+nsm[None,:]*u_nfw[:,:]),axis=1)*dlm \ + n0_2h*ncm[0]*(fc+nsm[0]*u_nfw[:,0]) b_m = np.sum((hmf * hbf)[None, :] * marr[None, :] * u_nfw[:, :], axis=1) * dlm + n0_2h * u_nfw[:, 0] b_hod /= ng b_m /= rhoM #1-halo #p1h=np.sum((hmf*ncm**2)[None,:]*(fc+nsm[None,:]*u_s[:,:])**2,axis=1)*dlm+n0_1h*(ncm[0]*(fc+nsm[0]*u_s[:,0]))**2 p1h=np.sum((hmf*ncm)[None,:]*(fc+nsm[None,:]*u_nfw[:,:])*marr*u_nfw[:,:],axis=1)*dlm \ + n0_1h*ncm[0]*(fc + nsm[0]*u_nfw[:,0])*u_nfw[:,0] p1h /= ng * rhoM #2-halo p2h = b_hod * b_m * ccl.linear_matter_power(self.cosmo, k, a) if return_decomposed: return p1h + p2h, p1h, p2h, np.ones_like(k) / ng, b_hod else: return p1h + p2h
def hm_1h_trispectrum(cosmo, k, a, profiles, logMrange=(8, 16), mpoints=128, selection=None, **kwargs): """Computes the halo model prediction for the 1-halo 3D trispectrum of four quantities. Args: cosmo (:obj:`ccl.Cosmology`): cosmology. k (array): array of wavenumbers in units of Mpc^-1 a (array): array of scale factor values profiles (tuple): tuple of four profile objects (currently only Arnaud and HOD are implemented) corresponding to the four quantities being correlated. logMrange (tuple): limits of integration in log10(M/Msun) mpoints (int): number of mass samples selection (function): selection function in (M,z) to include in the calculation. Pass None if you don't want to select a subset of the M-z plane. **kwargs: parameter used internally by the profiles. """ k = np.atleast_1d(k) a = np.atleast_1d(a) pau, pav, pbu, pbv = profiles aUnorm = pau.profnorm(cosmo, a, squeeze=False, **kwargs) aVnorm = pav.profnorm(cosmo, a, squeeze=False, **kwargs) bUnorm = pbu.profnorm(cosmo, a, squeeze=False, **kwargs) bVnorm = pbv.profnorm(cosmo, a, squeeze=False, **kwargs) logMmin, logMmax = logMrange mpoints = int(mpoints) M = np.logspace(logMmin, logMmax, mpoints) Dm = pau.Delta / ccl.omega_x(cosmo, a, 'matter') mfunc = np.array( [ccl.massfunc(cosmo, M, aa, Dmm) for aa, Dmm in zip(a, Dm)]).T if selection is not None: select = np.array([selection(M, 1. / aa - 1) for aa in a]).T else: select = 1 aU, aUU = pau.fourier_profiles(cosmo, k, M, a, squeeze=False, **kwargs) if pau.name == pav.name: aUV = aUU else: aV, aVV = pav.fourier_profiles(cosmo, k, M, a, squeeze=False, **kwargs) if 'r_corr' in kwargs: r = kwargs['r_corr'] else: r = 0 # aUV = np.sqrt(aUU*aVV)*(1+r) aUV = aU * aV * (1 + r) bU, bUU = pbu.fourier_profiles(cosmo, k, M, a, squeeze=False, **kwargs) if pbu.name == pbv.name: bUV = bUU else: bV, bVV = pbv.fourier_profiles(cosmo, k, M, a, squeeze=False, **kwargs) if 'r_corr' in kwargs: r = kwargs['r_corr'] else: r = 0 # bUV = np.sqrt(bUU*bVV)*(1+r) bUV = bU * bV * (1 + r) t1h = simps((select * mfunc)[:, :, None, None] * aUV[:, :, :, None] * bUV[:, :, None, :], x=np.log10(M), axis=0) rhoM = ccl.rho_x(cosmo, a, "matter", is_comoving=True) dlM = (logMmax - logMmin) / (mpoints - 1) n0_1h = (rhoM - np.dot(M, mfunc) * dlM) / M[0] t1h += (n0_1h[:, None, None] * aUV[0, :, :, None] * bUV[0, :, None, :]) t1h /= (aUnorm * aVnorm * bUnorm * bVnorm)[:, None, None] return t1h