Programmatic usage (API)
The core class of nonos is GasDataSet that you need to import from nonos.api. GasDataSet takes the form:
Mandatory argument:
on: output number (ex: for idefix, the VTK filef"data.{on:04d}.vtk")
Optional arguments:
directory: working directory where the output file is (default: current working directory).geometry: if the geometry is not recognized.codeandinifile: if the parameter file is not recognized (i.e. different from idefix.ini for idefix, variables.par for fargo3d and pluto.ini for pluto).codecan be"idefix","fargo3d","fargo-adsg"or"pluto".
GasDataSet is a field container, and you can access the fields in the form of a dictionary. You can check what fields are included in ds by running ds.keys(). For example, the density field could be accessed with ds["RHO"].
Examples
-
General case for the output number 0:
-
For a simulation with fargo-adsg and a parameter file "template.par" and for the output number 0, you need to do:
-
For a simulation performed with idefix in the directory "path/to/output", a parameter file "idefix-rkl.ini" and for the output number 10, you need to do:
Full examples
Example 1 (idefix, 2D, polar \(R\)-\(\phi\))
After going to the nonos directory, and opening ipython, we import GasDataSet.
We use the class GasDataSet which takes as argument the output number of the output file given by idefix/pluto/fargo.
As mentioned earlier, ds contains in particular a dictionary with the different fields. Let's say you want to perform a vertical slice of the density in the midplane, plot the result in the xy plane and rotate the grid given the planet number 0 (which orbit is described in the planet0.dat file):
dsop is now a Plotable object. We can e.g. represent its log10, with a given colormap, and display the colorbar by adding the argument title.
fig, ax = plt.subplots()
dsvm.plot(fig, ax, cmap="inferno", title=r"$\rho_{\rm mid}$")
ax.set_aspect("equal")
plt.show()
Example 2 (idefix, 3D, polar \(R\)-\(\phi\)-\(z\))
import matplotlib.pyplot as plt
from nonos.api import GasDataSet
ds = GasDataSet(43, geometry="polar", directory="tests/data/idefix_planet3d")
If now, with the same dataset, we perform a latitudinal projection of the field RHO, i.e. the integral of the density between \(-\theta\) and \(\theta\), and then an azimuthal average, before mapping it in the radial ("R") direction:
Finally, we display the y-label by adding the argument title
Example 3 (idefix, 2D, polar \(R\)-\(\phi\))
As a summary, we show here a simple 2D example.
import matplotlib.pyplot as plt
from nonos.api import GasDataSet
ds = GasDataSet(23, directory="tests/data/idefix_newvtk_planet2d")
fig, ax = plt.subplots()
ds["VX1"].map("R", "phi").plot(fig, ax, cmap="RdBu_r", title=r"$v_{\rm R}$")
fig.tight_layout()
plt.show()
Compute a new field
In order to compute a new field from preexisting ones, you can use the compute function, which takes 3 mandatory arguments (field the name of the new field, data the corresponding array and ref a known field with similar structure as the new field).
Example
Let us assume we have a VTK file named data.0000.vtk in cartesian geometry.
import numpy as np
from nonos.api import GasDataSet, compute
ds = GasDataSet(0)
Vnorm = compute(
field="V",
data=np.sqrt(ds["VX1"].data**2 + ds["VX2"].data**2 + ds["VX3"].data**2),
ref=ds["VX1"],
)
Coordinates
If ds is a dataset, the coordinates ds.coords at the cell edges and cell centers can be accessed with the following attributes:
| geometry | cartesian | polar | spherical |
|---|---|---|---|
| edges | (x, y, z) |
(R, phi, z) |
(r, theta, phi) |
| centers | (xmed, ymed, zmed) |
(Rmed, phimed, zmed) |
(rmed, thetamed, phimed) |
Attributes of fields
If ds is a dataset containing the three-dimensional density field ds["RHO"], you can access important quantities, such as:
data: the 3D array.coords: the coordinates that you can access depending on the geometry.on: the output number associated with the VTK file.
Operations on fields
If ds is a dataset containing the three-dimensional density field ds["RHO"], several operations on the field are possible.
1. General operations
| API function | operation | geometry |
|---|---|---|
latitudinal_projection(theta) |
Integral between \(-\theta\) and \(\theta\) | polar,spherical |
vertical_projection(z) |
Integral between \(-z\) and \(z\) | cartesian,polar |
vertical_at_midplane() |
Slice in the midplane | cartesian,polar,spherical |
latitudinal_at_theta(theta) |
Slice at latitude \(\theta\) | polar,spherical |
vertical_at_z(z) |
Slice at altitude \(z\) | cartesian,polar,spherical |
azimuthal_at_phi(phi) |
Slice at azimuth \(\phi\) | polar,spherical |
azimuthal_average() |
Azimuthal average | polar,spherical |
radial_at_r(distance) |
Slice at distance |
polar,spherical |
radial_average_interval(vmin,vmax) |
Radial average (vmin to vmax) |
polar,spherical |
Chain the operations
Some of these operations can be combined, e.g. first a slice in the midplane and then an azimuthal average with ds["RHO"].vertical_at_midplane().azimuthal_average().
It is also possible to access some other quantities in the arrays:
| API function | operation | geometry |
|---|---|---|
find_ir(distance) |
index in the radial direction at distance |
polar,spherical |
find_imid(altitude) |
index in the \(z\)/\(\theta\) direction at altitude |
cartesian,polar,spherical |
find_iphi(phi) |
index in the azimuthal direction at phi |
polar,spherical |
2. Other important operations
map("XDIR","YDIR"): before plotting the field, we have to map it in the("XDIR","YDIR")plane + optionalrotate_by(rotation angle, float) orrotate_with(planet log file, str) to rotate the grid. Mapping the field means here that we start with a native geometry for the outputs, e.g., a 2D polar geometry (\(R\), \(\phi\)), and we want to visualize it in a cartesian plane (\(x\), \(y\)).("XDIR","YDIR")can be for example("R","phi"),("x","y"),("x","z"),("r","theta"),... depending on the native geometry you have and the target geometry you want.diff(on): compute the relative difference of the same field for a different VTK file.save(directory): create a .npy file which saves indirectorythe array you just computed.
3. Additional operations for planet / disk simulations
| API function | operation | geometry |
|---|---|---|
azimuthal_at_planet(planet_number) |
Slice at planet azimuth \(\phi_p\) | polar,spherical |
remove_planet_hill(planet_number) |
Remove the Hill sphere | polar,spherical |
find_rp(planet_number) |
radial location of the planet | - |
find_rhill(planet_number) |
Hill radius of the planet | - |
find_phip(planet_number) |
azimuthal location of the planet | - |
Remove the Hill sphere
remove_planet_hill(planet_number) masks the region \(\phi_p \in \left[\phi_p - 2 R_{\rm hill}/R_p , \phi_p + 2 R_{\rm hill}/R_p \right]\) with \((R_p, \phi_p)\) the planet's coordinates and \(R_{\rm hill}\) its Hill radius.
4. Save fields and read dataset from reduced files
It is possible to save reduced arrays in NPY files, which are standard binary file format for numpy arrays. It it then possible to get a dataset from these reduced files. It could be a good strategy to pre-process large VTK files on a cluster and transfer afterwards the reduced files locally for post-processing.
Save reduced fields (idefix, 3D, spherical \(r\)-\(\theta\)-\(\phi\))
Access reduced fields in a dataset (idefix, 3D, spherical \(r\)-\(\theta\)-\(\phi\))
Plotting the fields
Once the field has been mapped in a plane of visualization (ex: dsmap = ds["RHO"].radial_at_r(1).map("phi","z")), we can plot it using the plot method. Note that you first need to create your figure and subplots, and you can afterwards add some complexity by using the power of matplotlib.
Mandatory arguments:
figandax: matplotlib figure and subplot (ex:fig, ax = plt.subplots())
Optional arguments:
log: plot the log10 of the field (default:False)vminandvmax: set respectively the minimum value and maximum value of the datacmap: choice of colormap (default:inferno)title: name of the field in the colorbar (default:None, i.e. no colorbar)filename,fmtanddpi: in order to directly save the plot, corresponds respectively the name of the file, the extension (default:png) and the resolution (default:500) of the saved figure. It is equivalent to By default, the figure is not saved in case you want to personalize the final plot with other matplotlib operations.
Plotting a file (idefix, 3D, polar \(R\)-\(\phi\)-\(z\))
import matplotlib.pyplot as plt
from nonos.api import GasDataSet
ds = GasDataSet(23)
dsmap = ds["RHO"].radial_at_r(1).map("phi","z")
fig, ax = plt.subplots()
dsmap.plot(
fig,
ax,
log=True,
title=r"$\rho(R=1)$",
filename="rho_R1",
fmt="png",
dpi=200,
)