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_error or interrupted (the user stopped it with Ctrl-C). A report read mid-run says running. This is the same outcome the nassu run process reports as its exit code: 0, 4, 3, 2 and 5 respectively.

  • sim_timestamps - UTC wall-clock instants bounding each phase, as <phase>_start / <phase>_end pairs over the phases full, build, initialization and runtime. 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_system and coordinate_matrix

The 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 their system field. IBM node exports (the per-body point clouds and the body_nodes friction series) always report lbm: their positions are the Lagrangian node positions verbatim, with no output-system rescale applied. Note that the static geometry under geometry/{system}/ - a bodyโ€™s surface STL and a point cloudโ€™s positions CSV - is written once per output system, so a case declaring domain.systems gets it in every declared frame (unless the frame sets output_geometries: false) while its IBM nodes stay in lbm. In a point cloudโ€™s positions CSV the columns follow what they measure: x, y, z carry the systemโ€™s affine, the normals nx, ny, nz are directions and are identical in every frame, and area carries the square of the scale, so a force integrated from the file comes out in that frameโ€™s units.

volume_transformation_matrix

The 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.

Bodies geometry

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

Points historic series

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:

Macroscopics 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.