Adding Ion Fields¶
In addition to being able to create absorption spectra, Trident Trident can be used to postprocess datasets to add fields for ions not explicitly tracked in the simulation. These can later be analyzed using the standard yt analysis packages. This page provides some examples as to how these fields can be generated and analyzed.
How does it work?¶
When you installed Trident, you were forced to download an ion table, a
data table consisting of dimensions in density, temperature, and redshift.
This ion table was constructed by running many independent Cloudy instances
to approximate the ionization states of all ionic species of the first 30
elements. The ionic species were calculated assuming collisional
ionization equilibrium based on different density and
temperature values and photoionization from a metagalactic ultraviolet
background unique to each ion table. The currently preferred ion table
uses the Haardt Madau 2012 model. You can change your default
ionization model by changing your config file (see: Manually Installing your Ionization Table), or
by specifying it directly in the
ionization_table keywords of the following
By following the process below, you will add different ion fields to your dataset based on the above assumptions using the dataset’s redshift, and the values of density, temperature, and metallicity found for each gas parcel in your dataset.
Generating species fields¶
As always, we first need to import yt and Trident and then we load up a dataset:
import yt import trident fn = 'enzo_cosmology_plus/RD0009/RD0009' ds = yt.load(fn)
To add ion fields we use the
add_ion_fields function. This
will add fields for whatever ions we specify in the form of:
- Ion fraction field. e.g.
- Number density field. e.g.
- Density field. e.g.
- Mass field. e.g.
Trident follows yt’s naming convention
for atomic, molecular, and ionic species fields. In short, the ionic
prefix consists of the element and the number of times ionized it is:
e.g. H I =
H_p0, Mg II =
Mg_p1, O VI =
O_p5 (p is for plus).
Let’s add fields for O VI (five-times-ionized oxygen):
trident.add_ion_fields(ds, ions=['O VI'], ftype="gas")
Make sure you are using the appropriate value for ftype in adding your
ion fields to a dataset. To get best results, the ion interpolation
must take place on the gas fields provided by your simulation output. For
grid-based codes, these fields are typically aliased to the gas fields
(e.g., (“gas”, “density”)), so using the default ftype=”gas” is
fine. But for particle-based codes, this is not usually the case, and the
particle-based gas fields differ based on the code (e.g. PartType0,
Gas, etc.). Inspection of your dataset may be necessary
print(ds.field_list)). Set ftype correctly to make sure
ion generation takes place on the particle first, before being deposited
to the grid-based fields, or you may get incorrect results.
To show how one can use this newly generated field, we’ll make a projection of the O VI number density field to show its column density map:
proj = yt.ProjectionPlot(ds, "z", "O_p5_number_density") proj.save()
We can similarly create a phase plot to show where the O VI mass lives as a function of density and temperature:
# we need to create a data object from the dataset to make a phase plot ad = ds.all_data() phase = yt.PhasePlot(ad, "density", "temperature", ["O_p5_mass"], weight_field="O_p5_mass", fractional=True) phase.save()