class mean_pairwise_velocity: TOP_HAT = 0 GAUSSIAN = 1 SHARP_K = 2 NO_FILTER = 3 def __init__(self, power_spectrum, mode_evolution, kmin=1.0e-3, kmax=1.0e4, mMin=1e12, mMax=1e15, physics=None, AXIONS=True, jenkins_mass=False, window_function=GAUSSIAN): """ :type power_spectrum: function(float)->float :type mode_evolution: GrowthInterpolation :type kmin: float :type kmax: float :type mMin: float :type mMax: float :type physics: Physics :type AXIONS: bool :type jenkins_mass: bool """ if physics is None: self.__phys = Physics(True, True) else: self.__phys = physics self.__mMin = mMin self.__mMax = mMax self.__kmin = kmin self.__kmax = kmax self.__jenkins_mass = jenkins_mass self.__AXIONS = AXIONS self.__power_spectrum = power_spectrum if window_function == mean_pairwise_velocity.TOP_HAT: self.__window_function = mean_pairwise_velocity.top_hat_window self.__radius_of_mass = self.radius_of_mass_top_hat elif window_function == mean_pairwise_velocity.GAUSSIAN: self.__window_function = mean_pairwise_velocity.gaussian_window self.__radius_of_mass = self.radius_of_mass_gaussian elif window_function == mean_pairwise_velocity.SHARP_K: self.__window_function = mean_pairwise_velocity.sharp_k_window self.__radius_of_mass = self.radius_of_mass_sharp_k elif window_function == mean_pairwise_velocity.NO_FILTER: self.__window_function = mean_pairwise_velocity.no_window self.__radius_of_mass = self.radius_of_mass_top_hat else: print("This doesn't work!") print(window_function) raise Exception("Function Comparision fails!") if AXIONS: axion_G, axion_dlogG_dlogA = mode_evolution.get_growth( ), mode_evolution.get_dlogG_dlogA() self.__growth, self.__G0, self.__dlogG_dlogA = lambda K, A: axion_G( A, K), lambda K: axion_G(1, K), lambda K, A: axion_dlogG_dlogA( A, K) else: dz_interp = self.__phys.get_D_interpolation(recompute=True, save=False) D0 = self.__phys.D(0) cdm_growth = lambda k, a: dz_interp((1 - a) / a) cdm_dlogG_dlogA = lambda K, A: differentiate( lambda log_a: cdm_growth(K, np.exp(log_a)), h=0.01)(np.log( A)) / cdm_growth(K, A) cdm_G0 = lambda k: D0 self.__growth, self.__G0, self.__dlogG_dlogA = cdm_growth, cdm_G0, cdm_dlogG_dlogA def compute(self, z, do_unbiased=False, high_res=False, high_res_multi=2, diagnostic=False): """ :type z: float :type do_unbiased: bool :type high_res: bool :type high_res_multi: int """ # do_unbiased: whether to compute unbiased spectra as well # high_res : compute correlations functions with hiher resolution # high_res_multi:multiplier by which to increase the number of intenrgation points for the computation of correlations functions a = 1 / (1 + z) masses = np.logspace( np.log10(self.__mMin) - 0.5, np.log10(self.__mMax) + 0.5, 300) print("Computing variance of the mass distribution...") sigma_sq = np.vectorize( lambda r: mean_pairwise_velocity.sigma_mass_distribution_sq( r, a, self.__power_spectrum, self.__growth, self.__G0, kmin_log=np.log(self.__kmin), kmax_log=np.log(self.__kmax), window_function=self.__window_function))( self.__radius_of_mass(masses)) sigma_sq_0 = np.vectorize( lambda r: mean_pairwise_velocity.sigma_mass_distribution_sq( r, 1.0, self.__power_spectrum, self.__growth, self.__G0, kmin_log=np.log(self.__kmin), kmax_log=np.log(self.__kmax), window_function=self.__window_function))( self.__radius_of_mass(masses)) sigma8 = np.sqrt( mean_pairwise_velocity.sigma_mass_distribution_sq( 8 / self.__phys.h, 1, self.__power_spectrum, self.__growth, self.__G0, kmin_log=np.log(self.__kmin), kmax_log=np.log(self.__kmax), window_function=self.__window_function)) print(sigma8) sigma_sq_log_interp = interpolate(np.log(masses), np.log(sigma_sq)) sigma_sq_interp = lambda m: np.exp(sigma_sq_log_interp(np.log(m))) sigma_sq_0_log_interp = interpolate(np.log(masses), np.log(sigma_sq_0)) sigma_sq_0_interp = lambda m: np.exp(sigma_sq_0_log_interp(np.log(m))) if self.__jenkins_mass: mass_function = self.jenkins_mass_function else: mass_function = self.press_schechter_mass_function k_vals = np.logspace(np.log10(self.__kmin), np.log10(self.__kmax), 300) print("Computing halo bias moments...") halo_bias_moments = [np.zeros(len(k_vals)), np.zeros(len(k_vals))] halo_bias_moments[0][:] = np.array( list( map( lambda k: self.mass_averaged_halo_bias( k, 1, lambda m: self.halo_bias(m, sigma_sq_interp, sigma_sq_0_interp), lambda m: mass_function(m, sigma_sq_interp), mMin=self.__mMin, mMax=self.__mMax), k_vals))) halo_bias_moments[1][:] = np.array( list( map( lambda k: self.mass_averaged_halo_bias( k, 2, lambda m: self.halo_bias(m, sigma_sq_interp, sigma_sq_0_interp), lambda m: mass_function(m, sigma_sq_interp), mMin=self.__mMin, mMax=self.__mMax), k_vals))) # computation may fail when numerator is nuermcially zero; use last successful value as limit halo_bias_moments[0][np.isnan(halo_bias_moments[0])] = np.nanmin( halo_bias_moments[0]) halo_bias_moments[1][np.isnan(halo_bias_moments[1])] = np.nanmin( halo_bias_moments[1]) halo_bias_1_interp = interp1d(k_vals, halo_bias_moments[0], fill_value=(halo_bias_moments[0][0], halo_bias_moments[0][-1]), bounds_error=False) halo_bias_2_interp = interp1d(k_vals, halo_bias_moments[1], fill_value=(halo_bias_moments[1][0], halo_bias_moments[1][-1]), bounds_error=False) print("Computing two-point correlation functions...") r_vals = np.linspace(1e-3, 300, 550) correlation_func_q2_vals = [] correlation_func_q1_vals = [] if do_unbiased: correlation_func_q1_vals_unbiased = [] correlation_func_q2_vals_unbiased = [] if high_res: res_multiplier = high_res_multi else: res_multiplier = 1.0 if self.__AXIONS: # axion growth function f = lambda k: self.__dlogG_dlogA(k, a) correlation_func_vals = np.array( list( map( lambda r: mean_pairwise_velocity.correlation_func( r, a, self.__power_spectrum, self.__growth, self.__G0, halo_bias_1_interp, halo_bias_2_interp, self.__kmin, self.__kmax, f, N=1000 * res_multiplier), r_vals))) correlation_func_q1_vals, correlation_func_q2_vals = correlation_func_vals[:, 0], correlation_func_vals[:, 1] if do_unbiased: correlation_func_vals_unbiased = np.array( list( map( lambda r: mean_pairwise_velocity.correlation_func( r, a, self.__power_spectrum, self.__growth, self.__G0, lambda k: 1, lambda k: 1, self.__kmin, self.__kmax, f, N=1000 * res_multiplier), r_vals))) correlation_func_q1_vals_unbiased, correlation_func_q2_vals_unbiased = correlation_func_vals_unbiased[:, 0], correlation_func_vals_unbiased[:, 1] else: correlation_func_vals = np.array( list( map( lambda r: mean_pairwise_velocity.correlation_func( r, a, self.__power_spectrum, self.__growth, self.__G0, halo_bias_1_interp, halo_bias_2_interp, self.__kmin, self.__kmax, N=1000 * res_multiplier), r_vals))) correlation_func_q1_vals, correlation_func_q2_vals = correlation_func_vals[:, 0], correlation_func_vals[:, 1] if do_unbiased: correlation_func_vals_unbiased = np.array( list( map( lambda r: mean_pairwise_velocity.correlation_func( r, a, self.__power_spectrum, self.__growth, self.__G0, lambda k: 1, lambda k: 1, self.__kmin, self.__kmax, N=1000 * res_multiplier), r_vals))) correlation_func_q1_vals_unbiased, correlation_func_q2_vals_unbiased = correlation_func_vals_unbiased[:, 0], correlation_func_vals_unbiased[:, 1] print("Computing volume averaged correlation function ...") correlation_func_q1_interp = interp1d(r_vals, correlation_func_q1_vals) correlation_func_bar_vals = [] if do_unbiased: correlation_func_q1_interp_unbiased = interp1d( r_vals, correlation_func_q1_vals_unbiased) correlation_func_bar_vals_unbiased = [] correlation_func_bar_vals = np.vectorize( lambda r: mean_pairwise_velocity.correlation_func_bar( r, correlation_func_q1_interp, rmin=min(r_vals)))(r_vals) if do_unbiased: correlation_func_bar_vals_unbiased = np.vectorize( lambda r: mean_pairwise_velocity.correlation_func_bar( r, correlation_func_q1_interp_unbiased, rmin=min(r_vals)))( r_vals) if self.__AXIONS: v_vals = 2 / 3 * 100 * self.__phys.h * self.__phys.E( z) * a * r_vals * np.array(correlation_func_bar_vals) / ( 1 + np.array(correlation_func_q2_vals)) if do_unbiased: v_vals_unbiased = 2 / 3 * 100 * self.__phys.h * self.__phys.E( z) * a * r_vals * np.array( correlation_func_bar_vals_unbiased) / ( 1 + np.array(correlation_func_q2_vals_unbiased)) else: v_vals = 2 / 3 * self.__dlogG_dlogA( 0.0, a) * 100 * self.__phys.h * self.__phys.E( z) * a * r_vals * np.array(correlation_func_bar_vals) / ( 1 + np.array(correlation_func_q2_vals)) if do_unbiased: v_vals_unbiased = 2 / 3 * self.__dlogG_dlogA( 0.0, a) * 100 * self.__phys.h * self.__phys.E( z) * a * r_vals * np.array( correlation_func_bar_vals_unbiased ) / (1 + np.array(correlation_func_q2_vals_unbiased)) if diagnostic: return r_vals, v_vals, correlation_func_q1_vals, correlation_func_q2_vals, correlation_func_bar_vals, k_vals, halo_bias_moments, masses, sigma_sq, sigma_sq_0, mass_function( masses, sigma_sq_interp) if do_unbiased: return r_vals, v_vals, v_vals_unbiased else: return r_vals, v_vals @staticmethod def correlation_func(r, a, P, D, D0, bias_1, bias_2, kmin, kmax, f=lambda k: 1, N=500): step_N = N # simpsons rule log width = (np.log(kmax) - np.log(kmin)) / step_N # compute width of the intervals eval_points_1 = np.log(kmin) + np.arange(1, step_N, 2) * width eval_points_2 = np.log(kmin) + np.arange(2, step_N, 2) * width eval_points_real_1 = np.exp(eval_points_1) eval_points_real_2 = np.exp(eval_points_2) integrand_log_gen = lambda k: k**2 * np.sin(k * r) * P(k) * D( k, a)**2 / D0(k)**2 xi_1_multiplier = lambda k: f(k) * bias_1(k) xi_1 = (integrand_log_gen(kmin) * xi_1_multiplier(kmin) + integrand_log_gen(kmax) * xi_1_multiplier(kmax) + 4 * sum( integrand_log_gen(eval_points_real_1) * xi_1_multiplier(eval_points_real_1)) + 2 * sum( integrand_log_gen(eval_points_real_2) * xi_1_multiplier(eval_points_real_2))) * width / 3 xi_2 = (integrand_log_gen(kmin) * bias_2(kmin) + integrand_log_gen(kmax) * bias_2(kmax) + 4 * sum( integrand_log_gen(eval_points_real_1) * bias_2(eval_points_real_1)) + 2 * sum( integrand_log_gen(eval_points_real_2) * bias_2(eval_points_real_2))) * width / 3 return 1 / (2 * np.pi**2 * r) * np.array([xi_1, xi_2]) @staticmethod def correlation_func_bar(r, correlation_func_f, rmin=1e-3, N=2000): return 3 / r**3 * num.integrateS( lambda r: r**2 * correlation_func_f(r), rmin, r, N) @staticmethod def top_hat_window(x): return np.piecewise( x, [np.fabs(x) < 1e-4, np.fabs(x) >= 1e-4], [1, lambda x: 3 * (np.sin(x) - x * np.cos(x)) / x**3]) @staticmethod def gaussian_window(x): return np.exp(-x**2 / 2) @staticmethod def sharp_k_window(x): return np.piecewise(x, [np.fabs(x) <= 1, np.fabs(x) > 1], [1, 0]) @staticmethod def no_window(x): return 1 @staticmethod def sigma_mass_distribution_sq(R, a, P, G, G0, N=2000, kmin_log=np.log(1e-4), kmax_log=np.log(1e4), window_function=None): if window_function is None: window_function = mean_pairwise_velocity.gaussian_window elif window_function == mean_pairwise_velocity.sharp_k_window: kmax_log = min([kmax_log, np.log(1 / R)]) if kmin_log >= kmax_log: return 0.0 elif window_function == mean_pairwise_velocity.gaussian_window or window_function == mean_pairwise_velocity.top_hat_window: pass elif window_function == mean_pairwise_velocity.no_window: window_function = mean_pairwise_velocity.top_hat_window else: raise Exception("There is a problem with the window function!") integrand_log = lambda log_k: np.exp(log_k)**3 * P(np.exp(log_k)) * G( np.exp(log_k), a)**2 / G0(np.exp(log_k))**2 * window_function( np.exp(log_k) * R)**2 return 1 / (2 * np.pi**2) * num.integrateS(integrand_log, kmin_log, kmax_log, N) def radius_of_mass_top_hat(self, M): return (3 * M / (4 * np.pi * self.__phys.rho0))**(1 / 3) def radius_of_mass_gaussian(self, M): return (2 * np.pi)**(-1 / 2) * (M / self.__phys.rho0)**(1 / 3) def radius_of_mass_sharp_k(self, M): return (9 * np.pi / 2)**(-1 / 3) * self.radius_of_mass_top_hat(M) def mass_of_radius_top_hat(self, R): return 4 / 3 * np.pi * R**3 * self.__phys.rho0 def mass_of_radius_gaussian(self, R): return np.sqrt(2 * np.pi) * (4 * np.pi / 3)**( -1 / 3) * self.mass_of_radius_top_hat(R) def mass_of_radius_sharp_k(self, R): return (9 * np.pi / 2) * self.mass_of_radius_top_hat(R) def halo_bias(self, M, sigma_sq, sigma_sq_0): return 1 + (self.__phys.delta_crit**2 - sigma_sq_0(M)) / (np.sqrt( sigma_sq(M)) * np.sqrt(sigma_sq_0(M)) * self.__phys.delta_crit) def jenkins_mass_function(self, M, sigma_sq): sigma = lambda m: np.sqrt(sigma_sq(m)) dlogSigma_dlogM = differentiate( lambda log_m: np.log(sigma(np.exp(log_m))), h=0.01)(np.log(M)) f = 0.315 * np.exp(-np.fabs(np.log(1 / sigma(M)) + 0.61)**3.8) return self.__phys.rho0 / M**2 * f * np.fabs(dlogSigma_dlogM) def press_schechter_mass_function(self, M, sigma_sq): sigma = lambda m: np.sqrt(sigma_sq(m)) dlogSigma_dlogM = differentiate( lambda log_m: np.log(sigma(np.exp(log_m))), h=0.01)(np.log(M)) return np.sqrt( 2 / np.pi) * (self.__phys.rho0 * self.__phys.delta_crit / sigma(M) / M**2) * np.fabs(dlogSigma_dlogM) * np.exp( -self.__phys.delta_crit**2 / (2 * sigma(M)**2)) def mass_averaged_halo_bias(self, k, q, halo_bias_function, mass_function, mMin=1e10, mMax=1e15, N=2000): integrand_mass = lambda log_m: np.exp(log_m)**2 * mass_function( np.exp(log_m)) * self.__window_function(k * self.__radius_of_mass( np.exp(log_m)))**2 integrand_bias = lambda log_m: np.exp(log_m)**2 * mass_function( np.exp(log_m)) * halo_bias_function(np.exp( log_m))**q * self.__window_function(k * self.__radius_of_mass( np.exp(log_m)))**2 if self.__window_function == mean_pairwise_velocity.sharp_k_window: mMax = min([mMax, self.mass_of_radius_sharp_k(1 / k)]) if mMax <= mMin: return 0.0 elif self.__window_function == mean_pairwise_velocity.gaussian_window or self.__window_function == mean_pairwise_velocity.top_hat_window or self.__window_function == mean_pairwise_velocity.no_window: pass else: raise Exception("There is a problem with the window function!") average_mass = num.integrateS(integrand_mass, np.log(mMin), np.log(mMax), N) average_halo_bias = num.integrateS(integrand_bias, np.log(mMin), np.log(mMax), N) try: return average_halo_bias / average_mass except ZeroDivisionError: return np.nan
class covariance_matrix: def __init__(self, power_spectrum, mode_evolution, zmin, zmax, Nz, r_vals, deltaR, f_sky, sigma_v_vals, kmin=1.0e-3, kmax=1.0e4, mMin=1e12, mMax=1e15, physics=None, jenkins_mass=False, window_function=mean_pairwise_velocity.GAUSSIAN): if physics is None: self.__phys = Physics(True, True) else: self.__phys = physics self.__zmin = zmin self.__zmax = zmax self.__mMin = mMin self.__mMax = mMax self.__kmin = kmin self.__kmax = kmax self.__f_sky = f_sky self.__sigma_v_vals = sigma_v_vals self.__deltaR = deltaR self.vs = [] self.correlation_f = [] self.__r_vals = r_vals self.__z_vals = np.linspace(zmin, zmax, Nz + 1) self.__window_function = None self.__radius_of_mass = None if jenkins_mass: self.__mass_function = self.jenkins_mass_function else: self.__mass_function = self.press_schechter_mass_function self.__AXIONS = False self.__power_spectrum = power_spectrum if self.__AXIONS: axion_G, axion_dlogG_dlogA = mode_evolution.get_growth( ), mode_evolution.get_dlogG_dlogA() self.__growth, self.__G0, self.__dlogG_dlogA = lambda K, A: axion_G( A, K), lambda K: axion_G(1, K), lambda K, A: axion_dlogG_dlogA( A, K) else: dz_interp = self.__phys.get_D_interpolation(recompute=True, save=False) D0 = self.__phys.D(0) cdm_growth = lambda k, a: dz_interp((1 - a) / a) cdm_dlogG_dlogA = lambda K, A: differentiate( lambda log_a: cdm_growth(K, np.exp(log_a)), h=0.01)(np.log( A)) / cdm_growth(K, A) cdm_G0 = lambda k: D0 self.__growth, self.__G0, self.__dlogG_dlogA = cdm_growth, cdm_G0, cdm_dlogG_dlogA self.__f = lambda a: self.__dlogG_dlogA(0, a) R1, R2 = np.meshgrid(self.__r_vals, self.__r_vals) self.__r_pairs = [(R1.flatten()[i], R2.flatten()[i]) for i in range(0, len(self.__r_vals)**2)] output = [] with MyProcessPool(min([6, Nz])) as pool: output = list( pool.imap( lambda i: self.evaluate_covariance(i, window_function), np.arange(0, Nz, 1))) self.__covariance = np.empty((Nz, len(r_vals), len(r_vals))) self.__inv_covariance_interpolations = np.empty((Nz), dtype='object') for i in range(Nz): self.__covariance[i, :, :] = np.reshape(output[i][0], (len(r_vals), len(r_vals))) self.__inv_covariance_interpolations[i] = RectBivariateSpline( r_vals, r_vals, np.linalg.inv(self.__covariance[i]), bbox=[min(r_vals), max(r_vals), min(r_vals), max(r_vals)]) self.vs.append(output[i][1]) self.correlation_f.append(output[i][2]) def save_covariance(self, path): with open(path, "wb") as f: dill.dump(self, f) @staticmethod def load_covariance(path): cov = None with open(path, "rb") as f: cov = dill.load(f) return cov def evaluate_covariance(self, z_bin, window_function): if window_function == mean_pairwise_velocity.TOP_HAT: self.__window_function = covariance_matrix.top_hat_window self.__radius_of_mass = self.radius_of_mass_top_hat elif window_function == mean_pairwise_velocity.GAUSSIAN: self.__window_function = covariance_matrix.gaussian_window self.__radius_of_mass = self.radius_of_mass_gaussian elif window_function == mean_pairwise_velocity.SHARP_K: self.__window_function = covariance_matrix.sharp_k_window self.__radius_of_mass = self.radius_of_mass_sharp_k elif window_function == mean_pairwise_velocity.NO_FILTER: self.__window_function = covariance_matrix.no_window self.__radius_of_mass = self.radius_of_mass_top_hat else: print("This doesn't work!") print(window_function) raise Exception("Function Comparision fails!") zmin, zmax = self.__z_vals[z_bin], self.__z_vals[z_bin + 1] print(zmin, zmax) z_central = (zmax - zmin) / 2 a_central = 1 / (1 + z_central) sigma_sq_interp, sigma_sq_0_interp, halo_bias_1_interp, halo_bias_2_interp, correlation_func_q1_interp, correlation_func_q2_interp, v_interp = self.pre_compute( z_central) volume = self.survey_volume(zmin, zmax) number_density = self.number_density(sigma_sq_interp) covariances = [] for r in self.__r_pairs: covariances.append( self.compute(z_bin, r[0], r[1], self.__deltaR, correlation_func_q2_interp, halo_bias_1_interp, number_density, volume)) #self.vs = v_interp return covariances, v_interp, correlation_func_q2_interp def pre_compute(self, z, high_res=False, high_res_multi=2): a = 1 / (1 + z) masses = np.logspace(1, 19, 300) print("Computing variance of the mass distribution...") sigma_sq = np.vectorize(lambda r: self.sigma_mass_distribution_sq( r, a, self.__power_spectrum, self.__growth, self.__G0, kmin_log=np.log(self.__kmin), kmax_log=np.log(self.__kmax), window_function=self.__window_function))( self.__radius_of_mass(masses)) sigma_sq_0 = np.vectorize(lambda r: self.sigma_mass_distribution_sq( r, 1.0, self.__power_spectrum, self.__growth, self.__G0, kmin_log=np.log(self.__kmin), kmax_log=np.log(self.__kmax), window_function=self.__window_function))( self.__radius_of_mass(masses)) sigma8 = np.sqrt( self.sigma_mass_distribution_sq( 8 / self.__phys.h, 1, self.__power_spectrum, self.__growth, self.__G0, kmin_log=np.log(self.__kmin), kmax_log=np.log(self.__kmax), window_function=self.__window_function)) print(sigma8) sigma_sq_log_interp = interpolate(np.log(masses), np.log(sigma_sq)) sigma_sq_interp = lambda m: np.exp(sigma_sq_log_interp(np.log(m))) sigma_sq_0_log_interp = interpolate(np.log(masses), np.log(sigma_sq_0)) sigma_sq_0_interp = lambda m: np.exp(sigma_sq_0_log_interp(np.log(m))) k_vals = np.logspace(np.log10(self.__kmin), np.log10(self.__kmax), 200) """ plt.figure() m_vals=np.logspace(12, 15, 100) plt.loglog(m_vals, np.array(list(map(lambda m: self.__mass_function(m, sigma_sq_interp), m_vals))*m_vals)) plt.loglog(m_vals, np.array(list(map(lambda m: self.jenkins_mass_function(m, sigma_sq_interp), m_vals))*m_vals)) plt.show() exit()""" print("Computing halo bias moments...") halo_bias_moments = [np.zeros(len(k_vals)), np.zeros(len(k_vals))] halo_bias_moments[0] = np.array( list( map( lambda k: self.mass_averaged_halo_bias( k, 1, lambda m: self.halo_bias(m, sigma_sq_interp, sigma_sq_0_interp), lambda m: self.__mass_function(m, sigma_sq_interp), mMin=self.__mMin, mMax=self.__mMax), k_vals))) halo_bias_moments[1] = np.array( list( map( lambda k: self.mass_averaged_halo_bias( k, 2, lambda m: self.halo_bias(m, sigma_sq_interp, sigma_sq_0_interp), lambda m: self.__mass_function(m, sigma_sq_interp), mMin=self.__mMin, mMax=self.__mMax), k_vals))) # computation may fail when numerator is numercially zero; use last successful value as limit halo_bias_moments[0][np.isnan(halo_bias_moments[0])] = np.nanmin( halo_bias_moments[0]) halo_bias_moments[1][np.isnan(halo_bias_moments[1])] = np.nanmin( halo_bias_moments[1]) halo_bias_1_interp = interp1d(k_vals, halo_bias_moments[0], fill_value=(halo_bias_moments[0][0], halo_bias_moments[0][-1]), bounds_error=False) halo_bias_2_interp = interp1d(k_vals, halo_bias_moments[1], fill_value=(halo_bias_moments[1][0], halo_bias_moments[1][-1]), bounds_error=False) print(halo_bias_1_interp(self.__kmax), halo_bias_1_interp(self.__kmin)) print("Computing two-point correlation functions...") r_vals = np.linspace(1e-3, 300, 400) correlation_func_q2_vals = [] correlation_func_q1_vals = [] if high_res: res_multiplier = high_res_multi else: res_multiplier = 1.0 if self.__AXIONS: correlation_func_vals = np.array( list( map( lambda r: self.correlation_func(r, a, self.__power_spectrum, self.__growth, self.__G0, halo_bias_1_interp, halo_bias_2_interp, min(k_vals), max(k_vals), self.__f, N=500 * res_multiplier ), r_vals))) correlation_func_q1_vals, correlation_func_q2_vals = correlation_func_vals[:, 0], correlation_func_vals[:, 1] else: correlation_func_vals = np.array( list( map( lambda r: self.correlation_func(r, a, self.__power_spectrum, self.__growth, self.__G0, halo_bias_1_interp, halo_bias_2_interp, min(k_vals), max(k_vals), N=500 * res_multiplier ), r_vals))) correlation_func_q1_vals, correlation_func_q2_vals = correlation_func_vals[:, 0], correlation_func_vals[:, 1] print("Computing volume averaged correlation function ...") correlation_func_q1_interp = interp1d(r_vals, correlation_func_q1_vals) correlation_func_q2_interp = interp1d(r_vals, correlation_func_q2_vals) correlation_func_bar_vals = [] correlation_func_bar_vals = np.vectorize( lambda r: self.correlation_func_bar( r, correlation_func_q1_interp, rmin=min(r_vals)))(r_vals) if self.__AXIONS: v_vals = 2 / 3 * 100 * self.__phys.h * self.__phys.E( z) * a * r_vals * np.array(correlation_func_bar_vals) / ( 1 + np.array(correlation_func_q2_vals)) else: v_vals = 2 / 3 * self.__f(a) * 100 * self.__phys.h * self.__phys.E( z) * a * r_vals * np.array(correlation_func_bar_vals) / ( 1 + np.array(correlation_func_q2_vals)) v_interp = interp1d(r_vals, v_vals) return sigma_sq_interp, sigma_sq_0_interp, halo_bias_1_interp, halo_bias_2_interp, correlation_func_q1_interp, correlation_func_q2_interp, v_interp def compute(self, z_bin, r1, r2, deltaR, correlation_func_q2_interp, halo_bias_1_interp, number_density, volume, N=2000): if self.__AXIONS: raise Exception("Not implemented!") else: zmin, zmax = self.__z_vals[z_bin], self.__z_vals[z_bin + 1] z_central = (zmax - zmin) / 2 a_central = 1 / (1 + z_central) integrand_log = lambda log_k: np.exp(log_k) * ( self.__growth(0, a_central)**2 / self.__G0( 0)**2 * self.__power_spectrum(np.exp( log_k)) * halo_bias_1_interp(np.exp(log_k)) + 1 / number_density)**2 * covariance_matrix.binned_window_function( np.exp(log_k), r1, r1 + deltaR ) * covariance_matrix.binned_window_function( np.exp(log_k), r2, r2 + deltaR) #integrand_log = lambda log_k: np.exp(log_k) * (1/number_density)**2 * covariance_matrix.binned_window_function(np.exp(log_k), r1, r1+deltaR)*covariance_matrix.binned_window_function(np.exp(log_k), r2, r2+deltaR) integral = num.integrateS(integrand_log, np.log(self.__kmin), np.log(self.__kmax), N) if r1 == r2: n_pairs = self.number_of_pairs(r1, deltaR, number_density, volume, correlation_func_q2_interp(r1)) return 4 / (np.pi**2 * volume) * ( 100 * self.__phys.h * self.__phys.E(1 / a_central - 1) * a_central)**2 / (1 + correlation_func_q2_interp(r1)) / ( 1 + correlation_func_q2_interp(r2)) * self.__f( a_central)**2 * integral + 2 * self.__sigma_v_vals[ z_bin]**2 / n_pairs else: return 4 / (np.pi**2 * volume) * ( 100 * self.__phys.h * self.__phys.E(1 / a_central - 1) * a_central)**2 / (1 + correlation_func_q2_interp(r1)) / ( 1 + correlation_func_q2_interp(r2) ) * self.__f(a_central)**2 * integral def get_inverted_covariance_interpolation(self, z_bin, r1, r2): return np.squeeze(self.__inv_covariance_interpolations[z_bin].ev( r1, r2)) def get_covariance(self, z_bin): return self.__covariance[z_bin] def get_inverted_covariance(self, z_bin): return np.linalg.inv(self.__covariance[z_bin]) def survey_volume(self, z_1, z_2): w = lambda z0: 3000.0 / self.__phys.h * num.integrate( lambda z: 1 / (self.__phys.E(z)), 0, z0) return 4 / 3 * np.pi * self.__f_sky * (w(z_2)**3 - w(z_1)**3) def number_density(self, sigma_sq): mass_f = lambda m: self.__mass_function(m, sigma_sq) return num.integrate(mass_f, self.__mMin, self.__mMax) @staticmethod def number_of_pairs(r, deltaR, number_density, survey_volume, correlation): bin_volume = 4 / 3 * np.pi * ((r + deltaR)**3 - r**3) return number_density**2 * survey_volume * bin_volume * ( 1 + correlation) / 2 @staticmethod def binned_window_function(k, rmin, rmax): w_tilde = lambda x: (2 * np.cos(x) + x * np.sin(x)) / x**3 return 3 * (rmin**3 * w_tilde(k * rmin) - rmax**3 * w_tilde(k * rmax)) / (rmax**3 - rmin**3) @staticmethod def correlation_func(r, a, P, D, D0, bias_1, bias_2, kmin, kmax, f=lambda k: 1, N=500): step_N = int(np.clip((r / 50) + 1, 1, 7)**2 * N) # simpsons rule log width = (np.log(kmax) - np.log(kmin)) / step_N # compute width of the intervals eval_points_1 = np.log(kmin) + np.arange(1, step_N, 2) * width eval_points_2 = np.log(kmin) + np.arange(2, step_N, 2) * width eval_points_real_1 = np.exp(eval_points_1) eval_points_real_2 = np.exp(eval_points_2) integrand_log_gen = lambda k: k**2 * np.sin(k * r) * P(k) * D( k, a)**2 / D0(k)**2 # print(type(f), type(bias_1)) xi_1_multiplier = lambda k: f(k) * bias_1(k) xi_1 = (integrand_log_gen(kmin) * xi_1_multiplier(kmin) + integrand_log_gen(kmax) * xi_1_multiplier(kmax) + 4 * sum( integrand_log_gen(eval_points_real_1) * xi_1_multiplier(eval_points_real_1)) + 2 * sum( integrand_log_gen(eval_points_real_2) * xi_1_multiplier(eval_points_real_2))) * width / 3 xi_2 = (integrand_log_gen(kmin) * bias_2(kmin) + integrand_log_gen(kmax) * bias_2(kmax) + 4 * sum( integrand_log_gen(eval_points_real_1) * bias_2(eval_points_real_1)) + 2 * sum( integrand_log_gen(eval_points_real_2) * bias_2(eval_points_real_2))) * width / 3 return 1 / (2 * np.pi**2 * r) * np.array([xi_1, xi_2]) @staticmethod def correlation_func_bar(r, correlation_func_f, rmin=1e-3): return 3 / r**3 * num.integrate(lambda R: R**2 * correlation_func_f(R), rmin, r) @staticmethod def top_hat_window(x): return np.piecewise( x, [np.fabs(x) < 1e-4, np.fabs(x) >= 1e-4], [1, lambda x: 3 * (np.sin(x) - x * np.cos(x)) / x**3]) @staticmethod def gaussian_window(x): return np.exp(-x**2 / 2) @staticmethod def sharp_k_window(x): return np.piecewise(x, [np.fabs(x) <= 1, np.fabs(x) > 1], [1, 0]) @staticmethod def no_window(x): return 1 def radius_of_mass_top_hat(self, M): return (3 * M / (4 * np.pi * self.__phys.rho0))**(1 / 3) def radius_of_mass_gaussian(self, M): return (2 * np.pi)**(-1 / 2) * (M / self.__phys.rho0)**(1 / 3) def radius_of_mass_sharp_k(self, M): return (9 * np.pi / 2)**(-1 / 3) * self.radius_of_mass_top_hat(M) def mass_of_radius_top_hat(self, R): return 4 / 3 * np.pi * R**3 * self.__phys.rho0 def mass_of_radius_gaussian(self, R): return np.sqrt(2 * np.pi) * (4 * np.pi / 3)**( -1 / 3) * self.mass_of_radius_top_hat(R) def mass_of_radius_sharp_k(self, R): return (9 * np.pi / 2) * self.mass_of_radius_top_hat(R) @staticmethod def sigma_mass_distribution_sq(R, a, P, G, G0, N=2000, kmin_log=np.log(1e-4), kmax_log=np.log(1e4), window_function=None): if window_function is None: window_function = covariance_matrix.gaussian_window elif window_function == covariance_matrix.sharp_k_window: kmax_log = min([kmax_log, np.log(1 / R)]) if kmin_log >= kmax_log: return 0.0 elif window_function == covariance_matrix.gaussian_window or window_function == covariance_matrix.top_hat_window: pass elif window_function == covariance_matrix.no_window: window_function = covariance_matrix.top_hat_window else: raise Exception("There is a problem with the window function!") integrand_log = lambda log_k: np.exp(log_k)**3 * P(np.exp(log_k)) * G( np.exp(log_k), a)**2 / G0(np.exp(log_k))**2 * window_function( np.exp(log_k) * R)**2 return 1 / (2 * np.pi**2) * num.integrateS(integrand_log, kmin_log, kmax_log, N) def halo_bias(self, M, sigma_sq, sigma_sq_0): return 1 + (self.__phys.delta_crit**2 - sigma_sq_0(M)) / (np.sqrt( sigma_sq(M)) * np.sqrt(sigma_sq_0(M)) * self.__phys.delta_crit) def jenkins_mass_function(self, M, sigma_sq): sigma = lambda m: np.sqrt(sigma_sq(m)) dlogSigma_dlogM = differentiate( lambda log_m: np.log(sigma(np.exp(log_m))), h=0.01)(np.log(M)) f = 0.315 * np.exp(-np.fabs(np.log(1 / sigma(M)) + 0.61)**3.8) return self.__phys.rho0 / M**2 * f * np.fabs(dlogSigma_dlogM) def press_schechter_mass_function(self, M, sigma_sq): sigma = lambda m: np.sqrt(sigma_sq(m)) dlogSigma_dlogM = differentiate( lambda log_m: np.log(sigma(np.exp(log_m))), h=0.01)(np.log(M)) return np.sqrt( 2 / np.pi) * (self.__phys.rho0 * self.__phys.delta_crit / sigma(M) / M**2) * np.fabs(dlogSigma_dlogM) * np.exp( -self.__phys.delta_crit**2 / (2 * sigma(M)**2)) def mass_averaged_halo_bias(self, k, q, halo_bias_function, mass_function, mMin=1e10, mMax=1e15): integrand_mass = lambda log_m: np.exp(log_m)**2 * mass_function( np.exp(log_m)) * self.__window_function(k * self.__radius_of_mass( np.exp(log_m)))**2 integrand_bias = lambda log_m: np.exp(log_m)**2 * mass_function( np.exp(log_m)) * halo_bias_function(np.exp( log_m))**q * self.__window_function(k * self.__radius_of_mass( np.exp(log_m)))**2 if self.__window_function == covariance_matrix.sharp_k_window: mMax = min([mMax, self.mass_of_radius_sharp_k(1 / k)]) if mMax <= mMin: return 0.0 elif self.__window_function == covariance_matrix.gaussian_window or self.__window_function == covariance_matrix.top_hat_window or self.__window_function == covariance_matrix.no_window: pass else: raise Exception("There is a problem with the window function!") average_mass = num.integrate(integrand_mass, np.log(mMin), np.log(mMax)) average_halo_bias = num.integrate(integrand_bias, np.log(mMin), np.log(mMax)) try: return average_halo_bias / average_mass except Exception as ex: return np.nan