Data and Checkpoints

There is no use for running a simulation if it doesn’t export anything. Despite that, if everything produced is exported the amount of data would be overwhelming, probably it wouldn’t even fit into a common hard drive.

The field data describes specifications for data save and some checkings to do with these data. Some of the features available are:

  • Runtime guards (divergence and sanity checks)

  • Exports (data.exports): a single, unified concept for every field/series export. Each export picks a target (named entities grouped by kind: volumes, lines, csvs, points, bodies, planes - kinds mix freely) and one or more outputs (instantaneous snapshots and/or running statistics)

  • Monitors for global statistics over time

  • IBM nodes export

  • Body friction nodes export

Guards

Runtime guards are the single mechanism for divergence and sanity control. A guard pairs a source (what to measure), a condition (when it trips) and an action (what to do), checked on its interval. Guards are declared under data.guards.

With no guards declared, an implicit default set applies the standard divergence behaviour: the fluid density rho is checked is_nonfinite -> stop every 10 steps, each passive transported field is checked is_nonfinite -> freeze (a field that goes NaN/Inf is frozen and dropped from exports while the fluid and healthy fields keep running), and each coupled field (Boussinesq scalar or coupled DDF energy) is checked is_nonfinite -> stop. A declared guard whose source targets a given field (the fluid, or a specific transported field) replaces that field’s implicit default - this is the single customization path.

Source - exactly one of:

  • field: a macroscopic peeked cheaply from one random block (the fluid rho, or a transported field’s conserved macro such as temperature_phi). A cheap peek is only sound for the is_nonfinite condition, so a field source rejects threshold conditions.

  • monitor (with stat, and macr when the monitor watches several): a whole-region reduction over the blocks of a declared data.monitors.fields entry. Threshold conditions must use a monitor source.

Condition: is_nonfinite (NaN/Inf), gt / lt / abs_gt (need value), or outside (needs lo < hi).

Action: stop aborts the run; freeze flags a transported field as diverged so it is frozen and dropped from exports (only valid for a transported field, not the fluid); warn only logs; ignore is a no-op, used to override and disable an implicit default (for example to turn divergence checking off for a field).

simulations:
  - name: example
    data:
      guards:
        # Cheap NaN/Inf check on the fluid density every 20 steps (overrides the
        # implicit fluid default to change its cadence).
        fluid_nan:
          field: rho
          condition: is_nonfinite
          action: stop
          interval: {frequency: 20}
        # Threshold guard backed by a monitor reduction: abort if the domain-max
        # density exceeds a bound.
        rho_cap:
          monitor: rho_max # a declared data.monitors.fields entry
          macr: rho
          stat: max
          condition: gt
          value: 2.0
          action: stop

Macroscopics

The data available is mostly based on the macroscopics fields for the simulation. The list below describe the name of the fields and what they represent:

  • rho: Density

  • u: Velocity (ux, uy, uz)

  • S: Stress tensor (Sxx, Sxy, Sxz, Syy, Syz, Szz)

  • theta: Relative temperature (only for simulations with thermal model)

  • omega_LES: Value of total omega (only for simulations that use LES)

  • omega_mask: Mask value to use for omega (only for simulations that use wall model)

  • f_IBM: IBM force (only for simulations that use IBM) (f_IBMx, f_IBMy, f_IBMz)

  • sigma: Sigma value for HRRBGK (only for simulations that use HRRBGK)

All fields that require one or a list of macroscopics must use these names to refer to them. If the field doesn’t exist, it won’t be exported or used.

Beyond these built-in fields, you can define derived fields (named expressions over the macroscopics, such as ux*uy) at the data root and use them anywhere a macroscopic name is accepted.

Export rescale

Output rescale, rename and time-rescale are declared as named profiles in the registry data.export_rescales. Each export (and monitor) then selects which profile to apply through its own rescale field; an export with no rescale applies no rescaling. Per-export macroscopic selection (macrs and the statistics macrs_1st_order / macrs_2nd_order lists) stays on each export.

data:
  export_rescales:
    physical: # profile name
      # Lattice-to-physical rescale per macroscopic: result = value * mul + cte.
      # Keys are macroscopic names that exist in the config (base or derived).
      macrs_rescale:
        rho: { mul: 1e3, cte: 0 } # lattice rho -> kg/m3
        ux: { mul: 41, cte: 0 } # lattice velocity -> m/s
      # Rename macroscopic output names (keys are macroscopic names, e.g. ux not u).
      macrs_rename: { rho: pressure }
      # Multiply the time-step index by this factor for the output time axis.
      # Defaults to 1.
      time_rescale: 1
    raw: {} # an empty profile, or simply omit `rescale` on an export, for no rescaling
  exports:
    field_volume:
      macrs: ["rho", "u"]
      rescale: physical # this export uses the `physical` profile
      # ... interval / target / outputs ...
  • macrs_rescale: per-macroscopic affine rescale value * mul + cte, converting lattice values to physical units. For a derived field it is applied to each base before the expression is evaluated.

  • macrs_rename: remaps a macroscopic’s exported name (the rename applies on output only).

  • time_rescale: multiplies the time-step index for the output time axis (use the lattice-to-physical time ratio to convert to seconds).

  • An export’s / monitor’s rescale must name a declared profile; an unknown name fails to load.

Important

Rescale, rename and time-rescale are declared as profiles under data.export_rescales and selected per export via rescale. There are no per-export macrs_rescale, macrs_rename or time_rescale fields on the instantaneous, statistics, series and monitor blocks; a config that sets them fails to load.

Export coordinate system

data.export_rescales rescales macroscopic values; the coordinates an export writes (volume node positions, probe/monitor positions, geometry) are selected separately by the export’s system field, naming a coordinate system. The lattice (lbm) coordinates are mapped into that frame on export; omitting system (or lbm) writes lattice coordinates. The chosen system and its lbm-to-system transform are recorded in the export’s XDMF/HDF5 metadata. Output systems must be non-rotated (scale + translation only).

data:
  exports:
    field_volume:
      macrs: ["rho", "u"]
      rescale: physical # value rescale profile (independent of `system`)
      system: site # write node coordinates in the `site` frame (metres)
      # ... interval / target / outputs ...
  monitors:
    fields:
      near_building:
        system: site # monitor positions written in `site`
        # ... macrs / stats / interval ...

Important

Output coordinates are expressed per export with system (declaring the frame under domain.systems); there is no global output-only coordinate rescale. An export system is a similarity transform: isotropic scale only, no per-axis scaling.

Exports

Every field and time-series export is configured under one field, data.exports. Each named export carries its macroscopic selection (macrs), one interval, a target (where it samples) and an outputs block (what it produces). This single concept covers instantaneous volume snapshots, statistics, and probe time series. Output rescale, rename and time-rescale are declared as named profiles in data.export_rescales and each export selects one via its rescale field.

simulations:
  - name: example
    data:
      exports:
        # Volume snapshots with running statistics.
        field_volume:
          macrs: [rho, u, S]
          interval: { frequency: 1000, lvl: 0 }
          target:
            # Named volume entities. Each exports the macroscopic field over a
            # domain volume; any block fully outside the volume is skipped.
            volumes:
              wake:
                volume:
                  start: [32, 0, 0]
                  end: [448, 128, 64]
                  is_abs: true # defaults to true
                max_lvl: -1 # max level to export; -1 exports all levels
                max_h5_size_gb: 4.0 # HDF5 rollover threshold in GB
              full: {} # a second entity: the whole domain, defaults
          outputs:
            instantaneous: true # write the raw field every interval
            stats: # running mean (1st order) and mean-of-squares (2nd order)
              macrs_1st_order: [rho, u]
              macrs_2nd_order: [u]
              flush_interval: 0 # 0 = snapshot only at end; >=100 = also periodic + checkpoint

        # A plane probe time series, sharing one export with a volume snapshot
        # of the same region (kinds mix freely).
        inlet_plane:
          macrs: [ux, uy, uz]
          interval: { frequency: 50, lvl: 0 }
          target:
            # A series target holds any of: lines, csvs, points, bodies, planes.
            planes:
              mid:
                axis: z
                axis_pos: 32
                dist: 1
            volumes:
              inlet_box:
                volume: { start: [0, 0, 0], end: [64, 128, 64], is_abs: true }
          outputs:
            instantaneous: true

Each export saves an XDMF+HDF5 file set that can be viewed using ParaView.

Targets

A target holds named entities grouped by kind. Every kind is an entity collection, the kinds mix freely in one export, and at least one entity must be defined across them.

  • target.volumes: named volume entities, each exporting the macroscopic field over a domain volume (the regions statistics also accumulate over these). Each entity carries its volume box, max_lvl (maximum refinement level to export; -1 exports all levels) and max_h5_size_gb. The volume box accepts a system field naming the coordinate system its corners are given in (default domain.default_system); is_abs, non-rotated systems only, mapped to lbm at load. This is the box’s input frame and is independent of the export’s own system (which sets the output coordinate frame). See Coordinate systems.

  • target.{lines,csvs,points,bodies,planes}: a collection of point-like entities sampled by interpolation. See Series targets below for each entity kind. Lines, points, planes and CSVs accept a system field naming the coordinate system their coordinates are given in (default domain.default_system); the points are mapped to lbm before sampling. See Coordinate systems.

Outputs

The outputs block selects what an export produces. The two outputs are independent, so all combinations are valid (instantaneous only, stats only, or both); at least one must be enabled.

  • instantaneous (bool): write the raw field/series value at each interval step.

  • stats ({macrs_1st_order, macrs_2nd_order, flush_interval} or null): accumulate runtime statistics over the export’s interval. First order is the running mean; second order is the running mean of the squared value (the basis for the standard deviation). The accumulators roll in place. By default (flush_interval: 0) they are written once, as a single snapshot at the end of the run, so statistics add negligible disk footprint. Set flush_interval to a positive number of level-0 steps (at least 100) to also snapshot the partial averages periodically and on checkpoint - useful for inspecting convergence on long runs. The order lists may name built-in macroscopics or derived fields; a derived name accumulates the statistics of its per-step value (so uxuy in macrs_1st_order gives <ux*uy>, never <ux><uy>). Stats macroscopics must be a subset of the export’s macrs, except derived names, whose bases are pulled in automatically.

Note

There is no dedicated spectrum output kind: a series export with outputs.instantaneous: true and interval: {frequency: 1, lvl: max} samples at the maximum rate. See Spectrum analysis.

Note

The selected profile’s macrs_rescale is applied to the instantaneous value before statistics accumulation, so a rescaled second-order field stays correct. Renaming (macrs_rename) is applied on output only.

Note

Some arrays, such as f_IBM, are not present in all blocks. For the blocks where they do not exist, the exported values are filled with NaN (not a number).

Derived fields

Derived fields are named SymPy expressions over base macroscopic instance names, declared once at the data root in data.derived_macrs:

data:
  derived_macrs:
    uxuy: "ux*uy"
    uxuz: "ux*uz"
    uyuz: "uy*uz"
  exports:
    ...

A derived name can then be used like any built-in macroscopic in any export: in an export’s macrs list (instantaneous volume, series) and in the stats order lists. When an export references a derived name, its base instances are pulled into that output’s read/sample/ interpolation set automatically, the expression is evaluated per node (or per sample) on the materialized base values, and the result is emitted under the derived name. Bases pulled in only to support a derived field are not written unless the export also requests them. The selected profile’s macrs_rescale is applied to each base before the expression is evaluated, and macrs_rename applies to the derived output name like any field.

Rules:

  • An expression may reference only base instance names (rho, ux, uy, uz, Sxy, …) plus the whitelisted math functions; it may not reference another derived field (no derived-on-derived).

  • A derived name must not collide with a built-in macroscopic name.

A common use is the full Reynolds stress tensor: combine the second-order means of the velocity components with the first-order means of their derived products.

data:
  derived_macrs:
    uxuy: "ux*uy"
    uxuz: "ux*uz"
    uyuz: "uy*uz"
  exports:
    reynolds:
      macrs: [u]
      interval: { frequency: 1000, lvl: 0 }
      target:
        volumes:
          reynolds:
            volume: { start: [0, 0, 0], end: [128, 128, 64], is_abs: true }
      outputs:
        stats:
          macrs_1st_order: [u, uxuy, uxuz, uyuz] # <ui> and <ui uj>
          macrs_2nd_order: [u] # <ui^2>

The Reynolds stresses then follow offline as <ui^2> - <ui>^2 (diagonal) and <ui uj> - <ui><uj> (off-diagonal).

Interval

interval controls when an export’s instantaneous and statistics outputs run.

interval:
  start_step: 0 # first step (in `lvl` units); defaults to 0
  end_step: 0 # last step (0 = run to the end)
  frequency: 0.3 # may be fractional
  lvl: 0 # reference level, or the literal "max"
  constant_dt: true # default: uniform (floored) interval; false = closest-snap
  • frequency may be fractional, and lvl may be the literal "max" (always the grid’s finest refinement level, so a config never hard-codes the grid depth).

  • Because every level advances with a constant dt, exports can only land on an integer multiple of the finest level’s dt (the internal iterations). How the requested interval maps onto those iterations is set by constant_dt:

    • constant_dt: true (default, uniform): the requested interval is rounded down to a whole number of finest-level steps, floor(frequency * 2**(max_lvl - lvl)) (clamped to at least one), and exports fire at every multiple of that fixed period, so consecutive snapshots are equally spaced in time. For example, frequency: 0.1 on a grid with max_lvl: 4 (finest step 0.0625) exports exactly every 0.0625 (floor(0.1 / 0.0625) = 1 finest step); the realised interval is at or below the requested one. This is what evenly-sampled series, animations, and spectral post-processing want.

    • constant_dt: false (closest-snap): the ideal export times n * frequency are snapped to the closest achievable finest-level iteration. For example, with frequency: 0.3 on a grid whose finest step is 0.25, exports land at 0.25, 0.5, 1.0, 1.25, 1.5, ... - the spacing alternates but the long-run average interval stays 0.3.

Volume transformations

A volume entity is an axis-aligned box, referenced for transformation by the qualified name volume.<export>.<entity> (or volume.<export> to match every volume entity of the export) in domain.global_transformations.probes_apply. Only translation and scaling are supported; rotation and inversion are ignored with a warning, since an axis-aligned box cannot be rotated. The transformed box is re-validated to stay legal (start < end).

Monitors

Sometimes keeping track of global statistics over time is important, to know wheter the simulation is stabilizing or diverging, if mass is being gained, velocity is out of control or other multiple use cases. For this Nassu implements monitors to keep track of macroscopics statistics during simulation.

simulations:
  - name: example
    data:
      monitors:
        fields:
          # Monitor name
          rho_max:
            # Macroscopics to monitor
            macrs: [rho, ux]
            # Optionally select a `data.export_rescales` profile (omit for none).
            rescale: physical
            # Statistics to check, available ones are: min, max, mean, pos
            # pos exports the position of maximun and minimun value (if they are selected)
            stats: [max, pos]
            # Interval in which to monitor statistics
            interval: {start_step: 500, end_step: 10000, frequency: 50}
            # Steps between successive writes of the CSV and plot.
            # Defaults to 250
            interval_flush: 250
          # Another example of macroscopics statistics
          macrs_stats:
            macrs: [rho, uy, Sxy, Sxz]
            stats: [min, max, mean]
            interval: {start_step: 0, end_step: 0, frequency: 500}
            # It's possible to define a series of volumes to monitor only blocks in it.
            # If none is specified, it checks the full domain.
            # The checking is done based on blocks, so the volume may be a bit larger than specified
            volumes_monitor:
              - start: [10, 20, 0]
                end: [100, 100, 100]
                is_abs: true
              # A monitor volume may name a coordinate system its corners are given in
              # (default domain.default_system). Only absolute, non-rotated systems are
              # supported; see domain.md#coordinate-systems.
              - start: [0, 0, 0]
                end: [40, 40, 20]
                is_abs: true
                system: site
              - start: [0.1, 0.1, 0.1]
                end: [0.9, 0.9, 0.9]
                is_abs: false
            # In case any volume should be ignored, it can be specified here. All blocks that are 
            # fully inside a volume to ignore are not used for monitoring.
            volumes_ignore:
              - start: [50, 60, 5]
                end: [70, 120, 10]
                is_abs: true

Each monitor exports a .csv file and plots the statistics over time for each macroscopic. Monitor rows are buffered in memory and committed (CSV append and plot re-render) in batches every interval_flush steps, mirroring a series export’s interval_flush. Lower values keep the on-disk files more up to date and reduce peak memory at the cost of more frequent disk I/O; the buffer is also force-flushed at end of run and on checkpoint.

IBM Nodes

IBM Lagrangian nodes carry per-node values (interpolated velocity, spread force, friction velocity, the filtered streamwise pressure gradient, …). The field data.export_IBM_nodes configures the export.

simulations:
  - name: example
    data:
      export_IBM_nodes:
        export_main:
          body_name: my_body
          start_step: 500
          end_step: 10000
          frequency: 100
          # Export mode: `triangle` (default) or `point_cloud`. See below.
          mode: triangle
          # `stride` / `target_num_nodes` apply to `point_cloud` mode only.
          # Export every Nth Lagrangian node. 1 keeps all nodes; 2 keeps
          # nodes 0, 2, 4, ...; etc. Defaults to 1.
          stride: 1
          # Desired approximate number of exported nodes. When set, overrides
          # `stride` by deriving an effective stride from the body's total
          # node count. Leave unset (null) to use `stride`. Defaults to null.
          target_num_nodes: null
          # H5 rollover threshold in gigabytes. A new chunk is started as
          # soon as the current chunk exceeds this size. Defaults to 4.0.
          max_h5_size_gigabytes: 4.0
          # Number of (lvl-0) simulation steps between successive HDF5
          # writes. Per-step snapshots are accumulated in memory and
          # committed to disk in batches; lower values trade memory for
          # more frequent I/O. Defaults to 250.
          interval_flush: 250

Per-step snapshots are accumulated in memory and committed to disk in batches every interval_flush (lvl-0) simulation steps, mirroring a series export’s interval_flush. The buffer is also force-flushed at end of run and on every checkpoint, so the on-disk stream is always consistent with the checkpointed state.

The exporter writes a single XDMF temporal collection per body at <sim_output>/geometry/body.<body>.nodes.xdmf, backed by rolling HDF5 chunks <sim_output>/geometry/body.<body>.nodes.NNN.hdf. The static geometry is written once into the first chunk and reused by every timestep grid; per-step fields are appended as new datasets.

ParaView (and any XDMF-aware reader) opens the .xdmf directly and exposes a working time slider plus all fields as attribute arrays. For programmatic access, SimulationOutput.bodies[name].read_ibm_xdmf() returns a vtkXdmfReader wired to the file.

Export modes

The mode field selects how the nodes are written.

triangle (the default) writes a triangle-conformed mesh: the topology is the source geometry’s own faces (vertices + triangle connectivity), and each triangle carries one representative value as a Cell-centered attribute. The runtime IBM node set does not map one-to-one to the geometry’s triangles (the solver subdivides and redistributes them by area and refinement level), so the nodes are aggregated back onto their source triangle: forces and area are summed over a triangle’s nodes (the area sum recovers the source face area), normal comes from the geometry, and the remaining fields (velocities, pressure gradient, …) are area-weighted means. An extra n_nodes attribute reports how many runtime nodes mapped to each face; faces with no node get zero forces and NaN means. This view conforms exactly to the input geometry, which makes it the natural choice for inspection and validation. It is only valid for body geometries; point-cloud bodies have no source triangulation and must use point_cloud.

point_cloud writes the raw Lagrangian nodes as a Polyvertex topology, with each node’s fields (force, u_interp, pres_grad, …) as Node-centered point attributes. This mode exposes the exact node set the solver uses and supports sub-sampling for very large bodies:

For very large bodies (tens of thousands of Lagrangian nodes), the stride knob sub-samples every Nth node at export time, keeping the output proportionally smaller without changing how the solver itself runs. The stride is applied to both the positions in the XDMF geometry (written once) and every subsequent timestep’s attribute arrays.

If you would rather target a node count directly than guess a stride, set target_num_nodes. When present it overrides stride: on the first export the effective stride is derived from the body’s total node count as max(1, round(total_nodes / target_num_nodes)), so the exported count is close to (but not exactly) the target. A target at least as large as the body’s node count keeps every node. The resolved stride is logged and frozen for the run; leave target_num_nodes unset to use stride as-is.

stride and target_num_nodes apply to point_cloud mode only; setting either with mode: triangle is a configuration error.

Body nodes

The field data.body_nodes configures a lean, probe-style export of BC-independent wall friction and pressure for an IBM body, separate from the heavy data.export_IBM_nodes mesh export above. At its frequency a read-only friction-sampling (“post-proc”) pass measures the near-wall fluid state at each body node and writes a dedicated per-node post-processing struct - it never touches the IBM solver / wall-model state and spreads no force, so it never perturbs the flow. The result is written as a flat CSV/HDF time series rather than an XDMF mesh.

simulations:
  - name: example
    data:
      body_nodes:
        cube_friction:
          body_name: my_body
          start_step: 0
          end_step: 0
          frequency: 100
          # `triangle` (default) aggregates the runtime nodes onto the body's
          # source triangles; `point_cloud` writes the raw per-node rows.
          mode: triangle
          # Steps between successive HDF5 writes; force-flushed at end of run
          # and on checkpoint. Defaults to 250.
          interval_flush: 250

In the default triangle mode the runtime Lagrangian nodes (which the solver subdivides and redistributes, so they do not map one-to-one to the geometry’s faces) are aggregated back onto the source triangles: the intensive diagnostics (friction_u_tau, friction_y_plus, traction_x/y/z, pressure) become area-weighted means, area sums, and the normal comes from the source triangle. This collapses the millions of runtime nodes down to the geometry’s ~10k faces. point_cloud mode writes one row per Lagrangian node instead; triangle is only valid for body geometries.

There is no column selection: the export always writes the whole post-processing set - the viscous traction_x/y/z, the friction velocity friction_u_tau and its friction_y_plus, and the wall surface pressure (p = rho*(1+theta)*c_s^2, sampled at the reference point co-located with the reference velocity; the theta term folds in temperature and is 0 for isothermal flow), plus the summed area and, in triangle mode, the n_nodes aggregation count. The geometry columns (the centroid pos_* and the source-triangle normal_*) go to the static topology sidecar. Only these primitives are stored; the nonlinear scalars (wall shear tau_w, the skin-friction coefficient Cf, the tangential direction, and the form/friction drag split) are derived later at read time in nassu.viz.friction.

The export writes a static topology sidecar <sim_output>/outputs/body_nodes.<body>.friction.csv (entity index, centroid, normal) once, plus the per-timestep friction series in <sim_output>/outputs/body_nodes.<body>.friction.h5. Per-step rows are buffered in memory and committed to disk in batches every interval_flush (lvl-0) steps, force-flushed at end of run and on every checkpoint. SimulationOutput.body_nodes[name].read_full_data() returns the full series as a pandas DataFrame.

Series targets

A series-target export samples a time series over a set of points. These points may be a line, a single point, the values on a body, a CSV list or an axis-aligned plane. The entity collections live under the export’s target; the shared knobs (macrs, interval, …) and outputs are exactly as described under Exports. Series targets additionally accept interval_group (steps per HDF table, default 1000) and interval_flush (steps between disk flushes, default 250).

simulations:
  - name: example
    data:
      exports:
        series1:
          macrs: [rho, u]
          # rescale / rename / time_rescale come from the selected data.export_rescales profile
          interval: { start_step: 78, end_step: 0, frequency: 10, lvl: 4 }
          interval_group: 1000 # steps per HDF table; defaults to 1000
          interval_flush: 250 # steps between disk flushes; defaults to 250
          target:
            # Lines to sample
            lines:
              line1:
                # Start, end and distance between points.
                start_pos: [200.46875, 79.4285, 2.905]
                end_pos: [200.46875, 80.5715, 2.905]
                dist: 0.28575
            # Single points
            points:
              point1:
                pos: [200.46875, 79.4285, 2.905]
            # Bodies
            bodies:
              my_CAARC:
                body_name: "CAARC"
                normal_offset: 0.03125
                # cell uses triangle centres; vertex uses triangle vertices
                element_type: "cell" # or "vertex"
              my_surface:
                # A single surface of a body
                body_name: "CAARC.surface_name"
                normal_offset: -0.03125
                element_type: "cell"
            # CSV point lists (header x, y, z, separated by ,)
            csvs:
              my_csv:
                filename: "my_filename.csv"
            # Planes (3D only)
            planes:
              plane1:
                axis: z # plane normal direction (x, y or z)
                axis_pos: 2.905 # coordinate along `axis`
                # In-plane bounds, ordered by global axis index excluding `axis`
                # (axis=z -> (x, y)). Omit both to span the full domain.
                min: [200.0, 79.0]
                max: [201.0, 81.0]
                # Grid spacing: scalar (uniform) or a pair (one per in-plane axis).
                dist: 0.28575
          outputs:
            instantaneous: true
            # stats is also valid on series targets:
            # stats: { macrs_1st_order: [u], macrs_2nd_order: [u] }

Each entity of points (such as line, body and its names) exports a .points.csv with the actual points being exported and an XDMF+HDF5 file set with the macroscopics time series indexed by the points.

Line probes additionally export their .xdmf with an XDMF Polyline topology (TopologyType="Polyline", NodesPerElement=N), so ParaView renders the segment as a connected line instead of a scatter of dots. Point and CSV probes still use Polyvertex, which is the correct topology for them. The companion .points.csv is still written for every probe kind.

Plane probes (planes, 3D only) sample an axis-aligned rectangular grid of points at the grid vertices, spaced by dist on the two in-plane axes (endpoint-inclusive, same convention as lines). dist is either a scalar (uniform spacing on both axes) or a pair giving one spacing per in-plane axis, ordered by global axis index excluding axis - the same ordering as min/max. They are built internally as a tessellated rectangle, so they export their .xdmf with a Triangle topology and node-centered scalars: ParaView renders the plane as a surface instead of a point cloud. min/max are optional: provide both to bound the plane, or omit both to span the full domain on the in-plane axes. The plane is axis-aligned by construction; for an arbitrarily oriented plane apply a rotation (and/or translation) through the probe transformation mechanism, exactly as for other probes. Unlike body probes, transformations on a plane are intended and do not emit a warning.

Important

The time series values are indexed in reference to the original points.

For example, if the original list of points is [(1, -1, 1), (1, 1, 1), (2, 2, 2), (2, -4, 2)] only the points at index 1 and 2 are inside the domain. So the export time series will have only point_idx values of 1 and 2, referecing to the index in the original list of points.

This is particularly useful when exporting from a body, to relate the index with the .lnas list of vertices or triangles

Spectrum analysis

Spectral (Fourier) analysis of a time series needs the values at the full numerical time resolution - every internal iteration. This is an ordinary instantaneous series export at the maximum sampling rate: interval: {frequency: 1, lvl: max} fires at every finest-level internal iteration.

simulations:
  - name: example
    data:
      exports:
        spectrum_probe:
          macrs: [rho, u]
          # rescale / rename / time_rescale come from the selected data.export_rescales profile
          interval: { frequency: 1, lvl: max } # every finest-level internal iteration
          target:
            points:
              upstream:
                pos: [200.46875, 80.0, 4.81]
              downstream:
                pos: [201.48375, 80.0, 4.81]
          outputs:
            instantaneous: true

Each point exports a .points.csv with the actual position used and an XDMF+HDF5 file set with the time series data.

Note

A series export samples via the GPU interpolation kernel at the exact probe position, the better default for spectral analysis. It carries a single interval: with lvl: max, a probe in a coarse block records repeated (zero-order-hold) values between its block’s updates - set the export’s lvl to the probe’s block level, or split exports per region, to avoid the repeats. The spectrum data lands in the export’s regular series files.

Checkpoint

One key feature is the capability of restarting a simulation, maintaining the fields and state from a previous time step. This is provided through the checkpoint field, which tries to best fit this goal, providing the capacity to restart a simulation or to run a new one using the state of another simulation.

simulations:
  - name: example
    checkpoint:
      export:
        # Interval to export checkpoint. It defaults to no export.
        interval: {end_step: 30000, frequency: 5000, start_step: 10000}
        # True to save checkpoint after simulation is finished or not.
        # Defaults to false.
        finish_save: false
        # Keep only the last checkpoint on disk, removing other saved ones in the `checkpoint` folder
        # Defaults to false
        keep_only_last_checkpoint: true
      load:
        # Start simulation from checkpoint. Defaults to False
        checkpoint_start: true
        # Reset simulation time step, start at 0 instead of checkpoint time step.
        # Defaults to false.
        reset_time_step: false
        # Path to folder to load checkpoint from. If not specified, tries to load
        # from the simulation output folder the last checkpoint saved
        # Defaults to null
        folderpath: null

There are some known limitations to the checkpoint capabilities. Some notable ones are:

  • The multiblock communication that requires temporal interpolation lost their previous state, starting with a constant time field.

  • The stats accumulators of an export (the running k and averages) are backed up and restored, so accumulation resumes consistently across a checkpoint. When stats.flush_interval is set, the partial averages are also snapshotted to disk on each checkpoint.

  • For series exports the simulation overwrites the files.

    • Despite this, the original ones are saved in the checkpoint as well, so it’s possible to join them afterwards.