def test_mgrowth(): """ Compare the modified growth function computed by CCL against the exact result for a particular modification of the growth rate. """ # Define differential growth rate arrays nz_mg = 128 z_mg = np.zeros(nz_mg) df_mg = np.zeros(nz_mg) for i in range(0, nz_mg): z_mg[i] = 4. * (i + 0.0) / (nz_mg - 1.) df_mg[i] = 0.1 / (1. + z_mg[i]) # Define two test cosmologies, without and with modified growth respectively p1 = ccl.Parameters(Omega_c=0.25, Omega_b=0.05, Omega_k=0., N_nu_rel=0., N_nu_mass=0., m_nu=0., w0=-1., wa=0., h=0.7, A_s=2.1e-9, n_s=0.96) p2 = ccl.Parameters(Omega_c=0.25, Omega_b=0.05, Omega_k=0., N_nu_rel=0., N_nu_mass=0., m_nu=0., w0=-1., wa=0., h=0.7, A_s=2.1e-9, n_s=0.96, z_mg=z_mg, df_mg=df_mg) cosmo1 = ccl.Cosmology(p1) cosmo2 = ccl.Cosmology(p2) # We have included a growth modification \delta f = K*a, with K==0.1 # (arbitrarily). This case has an analytic solution, given by # D(a) = D_0(a)*exp(K*(a-1)). Here we compare the growth computed by CCL # with the analytic solution. a = 1. / (1. + z_mg) d1 = ccl.growth_factor(cosmo1, a) d2 = ccl.growth_factor(cosmo2, a) f1 = ccl.growth_rate(cosmo1, a) f2 = ccl.growth_rate(cosmo2, a) f2r = f1 + 0.1 * a d2r = d1 * np.exp(0.1 * (a - 1.)) # Check that ratio of calculated and analytic results is within tolerance assert_allclose(d2r / d2, np.ones(d2.size), rtol=GROWTH_TOLERANCE) assert_allclose(f2r / f2, np.ones(f2.size), rtol=GROWTH_TOLERANCE)
def plot_model(ax, CBase, C, fmt, name): zar = np.linspace(0, 2.5, 100) aar = 1 / (1 + zar) f = ccl.growth_rate(C, aar) s8 = ccl.sigma8(C) * ccl.growth_factor(C, aar) f0 = ccl.growth_rate(CBase, aar) s80 = ccl.sigma8(CBase) * ccl.growth_factor(CBase, aar) ax.plot(zar, (f * s8) / (f0 * s80), fmt, label=name) return interp1d(zar, (s80 * f0))
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 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)) ) # 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')) )
def signal_power(zc, k, mu, cosmo, params): """ Return the signal auto- and cross-power spectra. """ # Scale factor at central redshift a = 1. / (1. + zc) # Get matter power spectrum pk = ccl.linear_matter_power(cosmo, k, a) # Get redshift-dep. functions b = bias(zc, params) rg = corrfac(zc, params) f = params['x_f'] * ccl.growth_rate(cosmo, a) beta = f / b H = params['x_H'] * ccl.h_over_h0(cosmo, a) * 100. * cosmo['h'] # km/s/Mpc # Redshift-space suppression factors D_g = 1. / np.sqrt(1. + 0.5 * (k * mu * sigma_g(zc, params))**2.) D_u = np.sinc(k * sigma_u(zc, params)) # galaxy-galaxy (dimensionless) pk_gg = b**2. * (1. + 2. * rg * beta * mu**2. + beta**2. * mu**4.) * D_g**2. * pk # galaxy-velocity (units: km/s) pk_gv = 1.j * a * H * f * b * mu * (rg + beta * mu**2.) * D_g * D_u / k * pk #pk_vg = -1. * pk_gv # Complex conjugate # velocity-velocity (units: [km/s]^2) pk_vv = (a * H * f * mu)**2. * (D_u / k)**2. * pk # Multiply all elements by P(k) and return return pk_gg, pk_gv, pk_vv
def test_growth_rate_gamma(): # We test consistency of both effective growth # parametrisation for LCDM cosmo_ccl = ccl.Cosmology( Omega_c=0.3, Omega_b=0.05, h=0.7, sigma8=0.8, n_s=0.96, Neff=0, transfer_function="eisenstein_hu", matter_power_spectrum="linear", ) cosmo_jax = Cosmology( Omega_c=0.3, Omega_b=0.05, h=0.7, sigma8=0.8, n_s=0.96, Omega_k=0.0, w0=-1.0, wa=0.0, gamma=0.55, ) # Test array of scale factors a = np.linspace(0.01, 1.0) fccl = ccl.growth_rate(cosmo_ccl, a) fjax = bkgrd.growth_rate(cosmo_jax, a) assert_allclose(fccl, fjax, rtol=1e-2)
def test_growth_rate(): # We first define equivalent CCL and jax_cosmo cosmologies cosmo_ccl = ccl.Cosmology( Omega_c=0.3, Omega_b=0.05, h=0.7, sigma8=0.8, n_s=0.96, Neff=0, transfer_function="eisenstein_hu", matter_power_spectrum="linear", ) cosmo_jax = Cosmology( Omega_c=0.3, Omega_b=0.05, h=0.7, sigma8=0.8, n_s=0.96, Omega_k=0.0, w0=-1.0, wa=0.0, ) # Test array of scale factors a = np.linspace(0.01, 1.0) fccl = ccl.growth_rate(cosmo_ccl, a) fjax = bkgrd.growth_rate(cosmo_jax, a) assert_allclose(fccl, fjax, rtol=1e-2)
def compute_covmat_cv(cosmo, zm, dndz): # Area COSMOS area_deg2 = 1.7 area_rad2 = area_deg2 * (np.pi / 180)**2 theta_rad = np.sqrt(area_rad2 / np.pi) # TODO: Where do we get the area # Bin widths dz = np.mean(zm[1:] - zm[:-1]) # Number of galaxies in each bin dn = dndz * dz # z bin edges zb = np.append((zm - dz / 2.), zm[-1] + dz / 2.) # Comoving distance to bin edges chis = ccl.comoving_radial_distance(cosmo, 1. / (1 + zb)) # Mean comoving distance in each bin chi_m = 0.5 * (chis[1:] + chis[:-1]) # Comoving distance width dchi = chis[1:] - chis[:-1] # Disc radii R_m = theta_rad * chi_m # Galaxy bias b_m = 0.95 / ccl.growth_factor(cosmo, 1. / (1 + zm)) # Growth rate (for RSDs) f_m = ccl.growth_rate(cosmo, 1. / (1 + zm)) # Transverse k bins n_kt = 512 # Parallel k bins n_kp = 512 plt.plot(zm, dn, 'b-') plt.savefig('N_z.png') plt.close() # Transverse modes kt_arr = np.geomspace(0.00005, 10., n_kt) # Parallel modes kp_arr = np.geomspace(0.00005, 10., n_kp) # Total wavenumber k_arr = np.sqrt(kt_arr[None, :]**2 + kp_arr[:, None]**2) # B.H. changed a to float(a) pk_arr = np.array([(b+f*kp_arr[:,None]**2/k_arr**2)**2* ccl.nonlin_matter_power(cosmo,k_arr.flatten(),float(a)).reshape([n_kp,n_kt])\ for a,b,f in zip(1./(1+zm),b_m,f_m)]) window = np.array([2*jv(1,kt_arr[None,:]*R)/(kt_arr[None,:]*R)*np.sin(0.5*kp_arr[:,None]*dc)/\ (0.5*kp_arr[:,None]*dc) for R,dc in zip(R_m,dchi)]) # Estimating covariance matrix # avoiding getting 0s in covariance eps = 0.0 # Changed from dn to dndz B.H. and A.S. TODO: Check print("covmat_cv...") covmat_cv = np.array([[(ni+eps)*(nj+eps)*covar(i,j,window,pk_arr,chi_m,kp_arr,kt_arr) \ for i,ni in enumerate(dndz)] \ for j,nj in enumerate(dndz)]) return covmat_cv
def __init__(self, cosmo, z_max=6., n_chi=1024): self.chi_max = ccl.comoving_radial_distance(cosmo, 1. / (1 + z_max)) chi = np.linspace(0, self.chi_max, n_chi) a_arr = ccl.scale_factor_of_chi(cosmo, chi) H0 = cosmo['h'] / ccl.physical_constants.CLIGHT_HMPC OM = cosmo['Omega_c'] + cosmo['Omega_b'] Ez = ccl.h_over_h0(cosmo, a_arr) fz = ccl.growth_rate(cosmo, a_arr) w_arr = 3 * cosmo['T_CMB'] * H0**3 * OM * Ez * chi**2 * (1 - fz) self._trc = [] self.add_tracer(cosmo, kernel=(chi, w_arr), der_bessel=-1)
def signal_covariance(zc, cosmo, params): """ Signal power spectrum matrix, containing (cross-)spectra for gg, gv, vv. These are simply the galaxy auto-, galaxy-velocity cross-, and velocity auto-spectra. """ # Scale factor at central redshift a = 1. / (1. + zc) # Grid of Fourier wavenumbers k = np.logspace(KMIN, KMAX, NK) mu = np.linspace(-1., 1., NMU) K, MU = np.meshgrid(k, mu) # Get matter power spectrum pk = ccl.linear_matter_power(cosmo, k, a=1.) # Get redshift-dep. functions b = bias(zc, params) rg = corrfac(zc, params) f = params['x_f'] * ccl.growth_rate(cosmo, a) beta = f / b H = params['x_H'] * ccl.h_over_h0(cosmo, a) * 100. * cosmo['h'] # km/s/Mpc # Redshift-space suppression factors D_g = 1. / np.sqrt(1. + 0.5 * (K * MU * sigma_g(zc, params))**2.) D_u = np.sinc(K * sigma_u(zc, params)) # Build 2x2 matrix of mu- and k-dependent pre-factors of P(k) fac = np.zeros((2, 2, mu.size, k.size)).astype(complex) # galaxy-galaxy (dimensionless) fac[0, 0] = b**2. * (1. + 2. * rg * beta * MU**2. + beta**2. * MU**4.) * D_g**2. # galaxy-velocity (units: km/s) fac[0, 1] = 1.j * a * H * f * b * MU * (rg + beta * MU**2.) * D_g * D_u / K fac[1, 0] = -1. * fac[0, 1] # Complex conjugate # velocity-velocity (units: [km/s]^2) fac[1, 1] = (a * H * f * MU)**2. * (D_u / K)**2. # Multiply all elements by P(k) and return return fac * pk[np.newaxis, np.newaxis, np.newaxis, :]
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)))
lum_dist = ccl.luminosity_distance(cosmo, a) dist_mod = ccl.distance_modulus(cosmo, a) # Plot the comoving radial distance as a function of redshift, as an example. plt.figure() plt.plot(z, chi_rad, 'k', linewidth=2) plt.xlabel('$z$', fontsize=20) plt.ylabel('Comoving distance, Mpc', fontsize=15) plt.tick_params(labelsize=13) # plt.show() plt.close() # Compute growth quantities : D = ccl.growth_factor(cosmo, a) f = ccl.growth_rate(cosmo, a) plt.figure() plt.plot(z, D, 'k', linewidth=2, label='Growth factor') plt.plot(z, f, 'g', linewidth=2, label='Growth rate') plt.xlabel('$z$', fontsize=20) plt.tick_params(labelsize=13) plt.legend(loc='lower left') # plt.show() plt.close() # The ratio of the Hubble parameter at scale factor a to H0: H_over_H0 = ccl.h_over_h0(cosmo, a) plt.figure() plt.plot(z, H_over_H0, 'k', linewidth=2) plt.xlabel('$z$', fontsize=20)
#Call function to evalute growth index for PPNC model z, H, Omega_M, Omega_DE, f, D, gam = PPNC2(z_final, H0, Omega_M0, k, alpha_0, p, gamma_0, gamma_cm0, q, gamma_cDE0, r) # ignore: PPNC(2.0, H0, 0.3, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, -lam/2.0, 1.0) ################################################################################ import pyccl as ccl cosmo = ccl.Cosmology(Omega_c=0.25, Omega_b=0.05, h=0.7324, A_s=2.1e-9, n_s=0.96) ccl_D = ccl.growth_factor(cosmo, 1. / (1. + z)) ccl_f = ccl.growth_rate(cosmo, 1. / (1. + z)) ################################################################################ #Time code in secs #print("Time taken", time.clock() - start, "secs") print('D') #print('H', H) #P.subplot(111) P.figure(1) aa = 1. / (1. + z) #Plot growth factor P.plot(1. / (1. + z), D[:, 0], 'r-', lw=1.8)
def fs8(self, C): fs8 = ccl.growth_rate(C, self.aar) * ccl.sigma8(C) fs80 = ccl.growth_rate(self.CBase, self.aar) * ccl.sigma8(self.CBase) return fs8 / fs80
return 0.3 * (OmegaH / 1e-3) * np.sqrt( (1 + z) / (2.5) * 0.29 / (OmegaM + (1. - OmegaM) / (1 + z)**3)) # first let's compute background values at our zs for name, zs in [("zlow", zlow)]: #,("zhigh",zhigh)]: f = open("background_%s.dat" % (name), 'w') f.write( "# z distance(z)[Mpc] growth(z)[normalised at z=0] f(z)=dlng/dlna Tspin(z) [mK] b(z) N(z) [Mpc^3] \n" ) for z in zs: print z afact = 1. / (1 + z) dist = ccl.luminosity_distance(cosmo, afact) # this is what class has gf = ccl.growth_factor(cosmo, afact) gr = ccl.growth_rate(cosmo, afact) print z, gr if z < 10: Ts = Tspin(z, OmegaH, OmegaC) bias = castorinaBias(z) Pn = castorinaPn(z) / h**3 # converting from Mpc/h^3 to Mpc^3 else: Ts = pritchardTSpin(z) bias = 1.0 Pn = 0.0 f.write("%3.2f %g %g %g %g %g %g \n" % (z, dist, gf, gr, Ts, bias, Pn)) f.close() # next write power spectrum f = open("pk0.dat", "w") f.write("# k [1/Mpc] Pk [Mpc^3] \n")
def plotRusty(C, bfunc, nbarfunc, zmin, zmax, Ptfunc=None, toplot='Pn', kweight=1, kmin=5e-3, kmax=1.0, Nk=90, Nz=100, vmin=None, vmax=None, mu=0.5, plotlog=True): """ Evertying should be self-explanatory, except that *** WE WORK IN CCL UNITS, so nbar is in 1/Mpc^3 *** toplot can be Pn or SNR (Pn/(1+Pn)) or SNR2 Ptfucn returns thermal noise, set to none for gals, takes (C,z,k) however kmin and kmax are in Mpc/h. """ h = C['h'] k_edges = np.logspace(np.log10(kmin * h), np.log10(kmax * h), Nk + 1) z_edges = np.linspace(zmin, zmax, Nz + 1) ks = np.sqrt(k_edges[:-1] * k_edges[1:]) ## log spacing zs = 0.5 * (z_edges[:-1] + z_edges[1:]) hmap = np.zeros((Nk, Nz)) kw = ks**kweight for zi, z in enumerate(zs): Pk = ccl.nonlin_matter_power(C, ks, 1 / (1 + z)) f = ccl.growth_rate(C, 1 / (1 + z)) bias = bfunc(z) nbar = nbarfunc(z) PkUse = (bias + f * mu**2)**2 * Pk Pnoise = 1 / nbar if Ptfunc is not None: Pnoise += np.array([Ptfunc(C, z, kx) for kx in ks]) Pn = PkUse / Pnoise SNR = Pn / (1 + Pn) if (toplot == 'Pn'): hmap[:, zi] = Pn if plotlog else Pn * kw elif (toplot == 'SNR'): hmap[:, zi] = SNR elif (toplot == 'SNR2'): hmap[:, zi] = SNR**2 else: print("Bad toplot!") stop() #plt.imshow (hmap, origin='lower', extent=(kmin,kmax, zmin,zmax),vmin=vmin,vmax=vmax) K, Z = np.meshgrid(ks, zs) if plotlog: plt.pcolor(K / h, Z, hmap.T, norm=LogNorm(), vmin=vmin, vmax=vmax) else: plt.pcolor(K / h, Z, hmap.T, vmin=vmin, vmax=vmax) plt.xscale('log') plt.colorbar()
# Calculate PPNC growth rate and growth factor z = np.linspace(0., 1.99, 100) a = 1. / (1. + z) ppn_D = ppncosmo.growth_factor(a) ppn_f = ppncosmo.growth_rate(a) # Initialise CCL cosmology cclcosmo = ccl.Cosmology(Omega_c=Omega_c, Omega_b=Omega_b, h=H0 / 100., A_s=2.1e-9, n_s=0.96) # Calculate CCL growth rate and growth factor ccl_D = ccl.growth_factor(cclcosmo, a) ccl_f = ccl.growth_rate(cclcosmo, a) # Plot comparison plt.subplot(111) plt.plot(z, ccl_D, 'k-', lw=1.8) plt.plot(z, ppn_D, 'r--', lw=1.8) plt.plot(z, ccl_f, 'k-', lw=1.8) plt.plot(z, ppn_f, 'y--', lw=1.8) plt.xlabel("z") plt.tight_layout() plt.show()
def realise_velocity(self, delta_x=None, delta_k=None, redshift=None, inplace=True): """ Realise the (unscaled) velocity field in Fourier space (e.g. see Dodelson Eq. 9.18): v(k) = i [f(a) H(a) a] delta_k vec{k} / k^2 The DFT prefactor has not been applied; to get the real-space velocity, simply do ifftn(velocity_k[i]), where i=0..2 for the x,y,z Cartesian directions. Parameters: delta_x (array_like, optional): Density fluctuation field. If this and `delta_k` are None, will use `self.delta_k` as the field. Default: None. delta_k (array_like, optional): Fourier-space density fluctuation field. If this and `delta_x` are None, will use `self.delta_k` as the field. Default: None. redshift (float, optional): If specified, use this redshift to calculate the matter power spectrum for the Gaussian random realisation. Otherwise, the value of `self.redshift` is used. Default: None. inplace (bool, optional): If True, store the Fourier transform, `velocity_k`, of the resulting velocity field and its Fourier transform into the `self.velocity_k` variable. Default: True. Returns: velocity_k (tuple of array_like): 3-tuple of the x,y,z velocity field components in Fourier space, v_x(k), v_y(k), v_z(k). Apply ifftn() directly to any of the components to get the real-space velocity component with the correct normalisation. """ # Get redshift if redshift is None: redshift = self.redshift scale_factor = 1. / (1. + redshift) # Check inputs if delta_x is not None and delta_k is not None: raise ValueError( "delta_x and delta_k specified; can only specify one") # Do FFT of delta_x if specified; otherwise use delta_k or self.delta_k if delta_x is not None: delta_k = fft.fftn(delta_x) if delta_k is None: delta_k = self.delta_k # Get squared k-vector in k-space (and factor in scaling from kx, ky, kz) k2 = self.k**2. # Calculate components of A (the unscaled velocity) Ax = 1.j * delta_k * self.Kx * (2. * np.pi / self.Lx) / k2 Ay = 1.j * delta_k * self.Ky * (2. * np.pi / self.Ly) / k2 Az = 1.j * delta_k * self.Kz * (2. * np.pi / self.Lz) / k2 Ax = np.nan_to_num(Ax) Ay = np.nan_to_num(Ay) Az = np.nan_to_num(Az) # If the FFT has an even number of samples, the most negative frequency # mode must have the same value as the most positive frequency mode. # However, when multiplying by 'i', allowing this mode to have a # non-zero real part makes it impossible to satisfy the reality # conditions. As such, we can set the whole mode to be zero, make sure # that it's pure imaginary, or use an odd number of samples. Different # ways of dealing with this could change the answer! if self.N % 2 == 0: # Even no. samples # Set highest (negative) freq. to zero mx = np.where(self.Kx == np.min(self.Kx)) my = np.where(self.Ky == np.min(self.Ky)) mz = np.where(self.Kz == np.min(self.Kz)) # self.Kx[mx] = 0.0; self.Ky[my] = 0.0; self.Kz[mz] = 0.0 Ax[mx] = Ay[my] = Az[mz] = 0. # Apply prefactor, v(k) = i [f(a) H(a) a] delta_k vec{k} / k^2 # N.B. velocity_k is missing a prefactor of 1/sqrt(self.box_factor). # If you do ifftn(velocity_k), you will get the real-space velocity # field back with the correct scaling however fac = 100.*self.cosmo['h'] * ccl.h_over_h0(self.cosmo, a=scale_factor) \ * ccl.growth_rate(self.cosmo, a=scale_factor) * scale_factor Ax *= fac Ay *= fac Az *= fac velocity_k = (Ax, Ay, Az) # Store result in object if requested if inplace: self.velocity_k = velocity_k return velocity_k