Post Processingยถ
After running a simulation, multiple artifacts are generated from it.
These include macroscopics fields exported during simulation, .stl files representing the geometries in the domain, log messages, runtime information, among many other files.
This section explains the output folder structure and files, and how to interact with them.
Output structureยถ
Each simulation is saved in the folder <save_path>/<simulation_name>/<sim_id>/.
This folder is structured as
๐ save_path/simulation_name/sim_id
โ๏ธ config.yaml # Full configuration for the simulation (not the original file that generated the simulations)
โ๏ธ info.yaml # Runtime information for the simulation
๐ simulation.log # Log file
๐ outputs # Everything the exports write, flat (open these in ParaView)
๐ {export}.volume.{entity}.{kind}.xdmf # Volume export XDMF index, accumulates all time steps
๐พ {export}.volume.{entity}.{kind}.{chunk}.h5 # Rolling HDF5 data backing the volume index
๐ {export}.{type}.{probe}.{kind}.xdmf # Probe series index, {type} in line/point/plane/body/csv
๐พ {export}.{type}.{probe}.{kind}.h5 # Time series data for the probe series
๐ {export}.{type}.{probe}.{kind}.points.csv # Series points, positions after all transformations
๐ง {export}.body.{probe}.{kind}.geometry.stl # Surface mesh of a body probe series
๐ monitors # Field monitors exported
๐ {monitor name}.{macr_name}.csv # Monitor time series
๐ผ๏ธ {monitor name}.{macr_name}.plot.png # Monitor plot
๐ geometry # Geometry: IBM bodies and point clouds
๐ {system} # Output system folder, one per coordinate system with `output_geometries` (lbm included)
๐ง {body name}.stl # Body STL written in this output system
๐ pcloud.{cloud name}.pos.csv # Point cloud positions written in this output system
๐ body.{body name}.nodes.xdmf # IBM node positions and exported values (point cloud per body)
๐พ body.{body name}.nodes.{chunk}.hdf # Rolling HDF5 data backing the IBM node point cloud
๐ pcloud.{cloud name}.nodes.csv # Point cloud IBM node positions (debug.output_IBM_nodes)
๐ pcloud.{cloud name}.nodes.xdmf # Point cloud node values
๐พ pcloud.{cloud name}.nodes.{chunk}.hdf # Rolling HDF5 data backing the point cloud
๐ mesh # Computational grid artifacts (user-inspectable)
๐งฑ blocks.lbm.obj # Domain refinement blocks in the base lattice frame, for visualization
๐งฑ blocks.{system}.obj # Refinement blocks rescaled into each output coordinate system
๐ wall_normals.xdmf # Continuous wall-normal map (when a predicate BC region wrote it)
๐ checkpoint # Checkpoints saved during simulation, can be used to restart at a given step
๐ {time_step}
๐ macrs.xdmf # Macroscopics required to restart (rho, u, S, omega_LES)
๐พ macrs.000.h5 # HDF5 data backing the checkpoint macroscopics
๐๏ธ state.json # Probes plus solver state to restart
๐ simulation.log # Copy of the log to restart
โ๏ธ config.yaml # Copy of the config to restart
๐ _setup # Solver machinery, never opened interactively
๐ code_generated # Each program generated for runtime and its compile log
๐ง {program name}.cu # Generated CUDA source
๐ {program name}.cu.compile.log # Compile log for the generated source
๐ SEM # Synthetic eddy method state
๐ profile.{name}.stats # Profiling data
Note
The output layout is flat, which makes results easy to open and manage in
ParaView. Under outputs/, {kind} is inst (instantaneous) or stats
(statistics), and an entityโs
output_name replaces the derived
{export}.{type}.{entity} part of the stem for its whole file family.
Run report (info.yaml)ยถ
info.yaml is the runโs own record: the resolved configuration, the block and
memory breakdown, the kernel and stream topology, and how the run went. It is
rewritten as the simulation progresses, so it is readable while the run is still
going and final once it stops.
Three sections describe the runโs lifecycle:
sim_status- how the run ended:finished,diverged,runtime_error,build_errororinterrupted(the user stopped it with Ctrl-C). A report read mid-run saysrunning. This is the same outcome thenassu runprocess reports as its exit code:0,4,3,2and5respectively.sim_timestamps- UTC wall-clock instants bounding each phase, as<phase>_start/<phase>_endpairs over the phasesfull,build,initializationandruntime. Every start has its end, whatever ended the run: a run cut short by a divergence or an error closes its phases at the point of failure, so the report always says when the run stopped.sim_timedeltas- elapsed seconds of each phase, measured on a monotonic clock.
A run whose build failed before the solver was assembled still writes an
info.yaml, marked partial: true: it carries the configuration, the lifecycle
sections above and the status, while the sections describing a built simulation
are empty.
Embedded export metadataยถ
Every export Nassu writes as an XDMF index plus companion HDF5 files carries a
provenance record inside the files themselves, so an export stays self-describing
after it is moved, archived, or shared apart from its info.yaml.
The record is written twice: as <Information Name=... Value=...> elements under
the XDMF <Domain>, and as root-group attributes on each HDF5 chunk. The complete
record is additionally stored as a single JSON string under the nassu_metadata
attribute, so one read recovers everything:
import json
import h5py
with h5py.File("outputs/fields.volume.domain.inst.000.h5") as f:
metadata = json.loads(f.attrs["nassu_metadata"])
print(metadata["nassu_version"], metadata["coordinate_system"])
The record identifies the run (nassu_version, nassu_commit, nassu_dirty,
simulation_name, sim_id, n_steps), the export (export_name, export_kind, fields,
frequency, interval_lvl, and stats_start_step for a statistics export), the
reported time axis (time_initial, time_step_size, time_rescale), the applied
renames and rescales (macrs_rename, macrs_rescale), and the write window
(datetime_export_start, datetime_export_end). The end time is refreshed on each
timestep write, so it tracks the real window even for an interrupted run.
Coordinate framesยถ
Two keys describe the frame the written coordinates live in:
coordinate_systemandcoordinate_matrixThe name of the exportโs output coordinate system, and the 4x4 matrix mapping lattice (
lbm) coordinates into it. Volume and probe-series exports report the system selected by theirsystemfield. IBM node exports (the per-body point clouds and thebody_nodesfriction series) always reportlbm: their positions are the Lagrangian node positions verbatim, with no output-system rescale applied. Note that the static geometry undergeometry/{system}/- a bodyโs surface STL and a point cloudโs positions CSV - is written once per output system, so a case declaringdomain.systemsgets it in every declared frame (unless the frame setsoutput_geometries: false) while its IBM nodes stay inlbm. In a point cloudโs positions CSV the columns follow what they measure:x, y, zcarry the systemโs affine, the normalsnx, ny, nzare directions and are identical in every frame, andareacarries the square of the scale, so a force integrated from the file comes out in that frameโs units.volume_transformation_matrixThe 4x4 rigid transform of an oriented export volume. An oriented volume is written as a structured mesh whose node coordinates already carry the rotation, and this key is what lets a reader recover which rotation that is. It is absent for a plain axis-aligned volume.
Source provenanceยถ
nassu_commit is the git commit the running Nassu was built from, and nassu_dirty
records whether that build carried uncommitted changes. Together with
nassu_version they identify the exact source that produced the data: a version
alone is shared by many commits, and a dirty build corresponds to no commit at all.
The commit is resolved from the buildโs own baked record, or - in a development
checkout - from the repository the installed package lives in. It never depends on
the directory the case was launched from. When neither can answer (an install with
no baked record and no repository), nassu_commit is absent from the HDF5
attributes and null in the JSON record; it is never filled in with the version
string, so a reader can always tell a hash from a version.
nassu version prints the same identity for the installed solver, and
nassu version --json prints the full record.
The metadata is documentation, never load-bearing: readers that ignore it are unaffected.
Series indexingยถ
There are some specific rules to the historic series indexing that itโs very important to understand to operate with it.
The points are generated using the specification of the generator, then the points outside the domain are filtered out.
The idx field of the points are generated using as reference the initial points (the ones not filtered out).
So, for example, if the first two points of a line are out of the domain, the first index of the points.csv will be 2.
This is important for when youโre combining the idx of this with other sources of information, such as the LNAS vertices or triangles.
Domain overviewยถ
To have an overview of the domain setup, we recommend using ParaView. It supports all our file extensions and have extensive funcionalities for visualization, process and many other resources.
Below is an example of domain visualization using the mesh/blocks.obj and the geometry files of the bodies.
Visualization of domain refinement and positioned bodiesยถ
Itโs also possible to view the points of series in the domain, converting the csv table to points in space
Visualization of points position from historic seriesยถ
Macroscopics Fieldsยถ
Check the state of the macroscopics fields, such as density or velocity, is a must step to check the quality of a simulation.
We also recommend ParaView for this.
The macroscopic field can be either exported for instantaneous and statistical values of the macroscopic variables rho, u, S, omega_LES.
The resulting .xdmf can be further post processed with Paraview using the calculator tool, as demonstrated below for a statistics field:
Post processing of macroscopic fields with Paraviewยถ
In the example above, the calculator filter from ParaView is used for the calculation of turbulent intensity \(I_{u}\) from averaged fields of velocity and squared velocity sqrt(ux_2nd-(ux^2))/ux.
Another frequently performed calculation is to transform the velocity components into a vector, which can be done with iHat*ux + jHat*uy + kHat*uz.
Being Python-based software, ParaView allows the user to apply any of its filters through scripts.
This allows the user to write post processing routines that can be performed in any .xdmf files that contain the same variable names.
API interactionยถ
All these files and paths can be accessed through an internal API as well. In this way a program can access the full path of files such as the historic series data or points, macroscopics instataneous path, the .obj file with blocks visualization, and other information.
Below is a code snippet demonstrating how to use it.
import pathlib
from nassu.cfg.model import ConfigScheme
from nassu.cfg.schemes.simul import SimulationConfigs, SimulationOutput
filename = "validation/wind_engineering/02_flow_over_wall_mounted_cube/02_flow_over_mounted_cube.nassu.yaml"
sim_cfgs = ConfigScheme.from_file(pathlib.Path(filename)).load_sim_cfgs()
sim_cfg = sim_cfgs[0]
sim_output: SimulationOutput = sim_cfg.output
cube_stl_path = sim_output.bodies["cube"].stl # Path for stl output file of cube
full_info = sim_output.read_info() # reads info.yaml
To know more about this interface and how to interact with it, check the class nassu.cfg.schemes.simul.SimulationOutput.