Research Blog
Welcome to my Research Blog.
This is mostly meant to document what I am working on for myself, and to communicate with my colleagues. It is likely filled with errors!
This project is maintained by ndrakos
Altering the MUSIC code was honestly way more annoying than just writing things myself. Therefore, I’m going to write some basic IC code in python. I think this will be more useful in the long-run, since we want to implement our own code into Cholla.
For this post, I’ll just focus on the dark matter component, and note where I need to add in neutrinos.
Cosmology - I will define: Omega_m, Omega_L, Omega_b, H0, sigma_8, nspec (and optionally w0 and wa) Simulation details - box size, number of particles, redshift
When adding neutrinos, there will need to be additional parameters set (see this post).
I need to:
That will output a density field (in Fourier space)
For this need power spectrum. I’ll use CAMB (see previous post).
import camb
params = camb.CAMBparams()
params.set_cosmology(H0=H0, ombh2=Omega_b, omch2=Omega_m) #check these all in the right units
params.InitPower.set_params(ns=nspec)
params.set_matter_power(redshifts=[z_start])
PK = camb.get_matter_power_interpolator(params,var1='delta_tot',var2='delta_tot')
The power spectrum will be different for neutrinos, but camb includes this as well
Question: will I want to use delta_tot, delta_cdm or delta_nonu for the CDM particles?
Here is the code to make the density field (in Fourier space):
#Make gaussian field
seed(seed1)
density = random.randn(N,N,N) #gaussian field
#Fourier Transform
density = np.fft.fftn(density) #fourier space
ka = 2*np.pi*fft.fftfreq(N, d=boxlength/(N-1))
kx,ky,kz =np.meshgrid(ka,ka,ka)
k = np.sqrt(kx**2 + ky**2 + kz**2)
#scale with powerspectrum in fourier space
P = PK.P(z_start,k)
density = np.sqrt(P)*density
The displacement field can be calculated from the density field (in Fourier space)
\(s = -i \dfrac{1}{D_+} \dfrac{k_{lmn}}{k^2{lmn}} \delta_{lmn}\),
where \(D_+\) is the growth factor. This can be calculated directly from an integral, but I am currently using the fitting function from Carroll, Press & Turner (note this assumes a csomological constant). This will be easy to integrate numerically later if I chose to update it. For now I have:
H2 = Omega_m*(1+z_start)**3 + Omega_L
w_m = Omega_m * (1+z_start)**3 / H2
w_l = Omega_L / H2
Dp = 5*w_m /(w_m **(4/7) - w_l + (1+w_m/2)*(1 + w_l/70) ) / (2*(1+z_start))
The inverse Fourier Transform of \(s\) will give the displacement field:
k[k==0]=np.inf #This mode can be ignored, because it corresponds to a simple change of a reference frame.
d_x = -1j /Dp * kx/k**2 * density
d_y = -1j /Dp * ky/k**2 * density
d_z = -1j /Dp * kz/k**2 * density
d_x = np.real(np.fft.ifftn(d_x))
d_y = np.real(np.fft.ifftn(d_y))
d_z = np.real(np.fft.ifftn(d_z))
This returns the displacement vector at each coordinate.
Question: Is it okay to just take the real part and ignore the imaginary part?
The positions are initially on the grid vertices, and then offset using the displacement field.
a = np.linspace(0,boxlength,N)
x,y,z =np.meshgrid(a,a,a)
x += Dp*d_x; y += Dp*d_y; z+=Dp*d_z
x = x.flatten(); y =y.flatten(); z = z.flatten()
This exact same procedure can be used to get neutrino points except (1) I will use a coarser grid (2) the power spectrum will be different and (3) there will be multiple neutrinos per grid point.
Bulk velocity is straightforward to calculate from the displacement field. I will need to calculate \(dD_+/da\) first
Dp_dot = -3*Omega_m*(1+z_start)**4/2/H2*Dp + 5/2*Omega_m*(1+z_start)**3/H2
and then the velocities are
vx = Dp_dot*d_x/(1+z_start);
vy = Dp_dot*d_y/(1+z_start);
vz = Dp_dot*d_z/(1+z_start);
vx = vx.flatten(); vy =vy.flatten(); vz = vz.flatten()
Neutrinos will also have an extra velocity, which I have calculated previously here
I am only considering equal mass dark matter particles, and equal mass neutrinos (note that we might change this later). Given the mass density parameter, the box size, and the cosmological parameters, I can calculate the mass per particle.
The mass of each particle should be
\[m = \Omega_m \times \rho_c \times \rm{boxlength}^3 \times N^{-3}\]and the critical density at redshift \(z\) is \(3 H(z)^2 / 8 \pi G\)