Setup the N-body model¶
We describe here the quantities that must be stored in the N-body model in order
to compute a surface brightness image.
We assume here a swift
hdf5 format, while other formats can be used.
The N-body model must contain the following fields:
positions for each stellar particle, in \(\rm{kpc}\) (
nb.pos
)velocities for each stellar particle, in \(\rm{km/s}\) (
nb.vel
)mass for each stellar particle, in \(10^{10}\,\rm{M_\odot}\) (
nb.mass
). The mast must corresponds to the initial SSP mass.age for each stellar particle, in \(\rm{Gyr}\) (
nb.age
) An old stellar particle will have a typical age of \(12\,\rm{Gyr}\) and a recently formed particles of \(2\,\rm{Gyr}\)metallicity for each stellar particle ([M/H]) (
nb.mh
)\[[M/H] = \log_{10} \frac{M_{\rm{M}}/M_{\rm{H}}}{ \left( M_{\rm{M}}/M_{\rm{H}}\right)_{\odot} }\]where \(M_{\rm{M}}/M_{\rm{H}}\) is the mass fraction of metals and usually denoted by \(Z\) and \(\left( M_{\rm{M}}/M_{\rm{H}}\right)_{\odot}\) is the solar metal fraction and is set to 0.02.
an estimation of the size for each stellar particle, in \(\rm{kpc}\) (
nb.rsp
).
Warning
All quantities that must be provided must be in proper coorinates (not in comoving ones) and must be free of Hubble parameter (\(h\))!
The following lines show how to get a snapshot of the appropriate format using pNbody:
import numpy as np
from pNbody import *
from astropy import units as u
# define units
u_Length = 1* u.kpc
u_Mass = 10**10 * u.M_sun
u_Velocity = 1* u.km/u.s
u_Time = u_Length/u_Velocity
toMsol = u_Mass.to(u.M_sun).value
n = 10
outputfile = "snapshot.hdf5"
x = np.random.random(n) # <<< x in kpc
y = np.random.random(n) # <<< y in kpc
z = np.random.random(n) # <<< z in kpc
pos = np.transpose(np.array([x, y, z]))
vx = np.random.random(n) # <<< vx in km/s
vy = np.random.random(n) # <<< vy in km/s
vz = np.random.random(n) # <<< vz in km/s
vel = np.transpose(np.array([vx, vy, vz]))
mass = np.ones(n) # <<< mass in 10^10 solar mass
# create the pNbody object
nb = Nbody(status='new',pos=pos,vel=vel,mass=mass,ftype='swift')
# set all particles to stellar particles
nb.set_tpe(4)
nb.age = np.random.random(n) # <<< age of the stellar particles in Gyr
nb.mh = np.random.random(n) # <<< metallicity [M/H]
# add units
nb.UnitLength_in_cm = u_Length.to(u.cm).value
nb.UnitMass_in_g = u_Mass.to(u.g).value
nb.UnitVelocity_in_cm_per_s = u_Velocity.to(u.cm/u.s).value
nb.Unit_time_in_cgs = u_Time.to(u.s).value
nb.hubblefactorcorrection = False
nb.comovingtoproperconversion = False
nb.atime = 1
nb.rename(outputfile)
nb.write()
If not provided, an estimation for the size of stellar particles can be obtained using the following command (see Scripts for mode details):
mockimgs_sb_addfields --do_not_compute_ages --do_not_compute_magnitudes snapshot.hdf5 -o snapshot.hdf5
Note that the input can be also the output (here snapshot.hdf5
).
The size may be retrieved via the variable nb.rsp
once snapshot.hdf5
is opened with pNbody
.
Warning
The following command may sometimes fail if two stellar particles are too close to each other, which should normally not happen. However, if this is the case, the workaround is to “shake” very slightly the particles before saving the hdf5 file. For example, in the previous script, add:
x = x + np.random.uniform(-0.5,0.5,nb.nbody)*eps
y = y + np.random.uniform(-0.5,0.5,nb.nbody)*eps
z = z + np.random.uniform(-0.5,0.5,nb.nbody)*eps
where eps must take a value much smaller than the typical spacial resolution of the system.
Check the model¶
To check that the created model contains all the necessary fields, you can print the content of the fields
related to the stellar particles using the sw_getDescriptionFields
command:
sw_getDescriptionFields snapshot.hdf5
which should return:
PartType4
Coordinates
Masses
ParticleIDs
SmoothingLengths
StellarAge
StellarMetallicity
Velocities
Another way of checking is to run:
gpy snapshot.hdf5
and successively ask for the existence of different arrays:
nb.has_array("pos")
nb.has_array("vel")
nb.has_array("mass")
nb.has_array("num")
nb.has_array("rsp")
nb.has_array("age")
nb.has_array("mh")
the output should be:
In [1]: nb.has_array("pos")
Out[1]: True
In [2]: nb.has_array("vel")
Out[2]: True
In [3]: nb.has_array("mass")
Out[3]: True
In [4]: nb.has_array("num")
Out[4]: True
In [5]: nb.has_array("rsp")
Out[5]: True
In [6]: nb.has_array("age")
Out[6]: True
In [7]: nb.has_array("mh")
Out[7]: True
mockimgs_sb_addfields
¶
usage: mockimgs_sb_addfields [-h] [-o OUTPUTFILENAME] [--nngb NNGB]
[--do_not_compute_ages] [--do_not_compute_rsp]
[--do_not_compute_magnitudes] [--ftype FTYPE]
[FILE ...]
positional arguments:
FILE a file name
options:
-h, --help show this help message and exit
-o OUTPUTFILENAME Name of the output file
--nngb NNGB Number of neighbouring particles to consider to
compute RSP(==HSML)
--do_not_compute_ages
do not compute ages
--do_not_compute_rsp do not compute rsp
--do_not_compute_magnitudes
do not compute compute_magnitudes
--ftype FTYPE type of file