Skill Tracer
Skills › Scientific Agent Skills › fluidsim › output_analysis.md

output_analysis.md

331 lines · skills/fluidsim/references/output_analysis.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Output inventory, plotting, and budget analysis
2

Output inventory, plotting, and budget analysis

Raw lines 1 to 2
3## Analyze without overclaiming
4
5Output analysis can detect errors and quantify diagnostics. It cannot by itself
6establish:
7
8- Correct equations, units, or boundary/initial/forcing conditions.
9- Adequate resolution or dealiasing.
10- Stable/accurate time integration.
11- Conservation or budget closure.
12- Statistical stationarity.
13- Grid/time convergence.
14- Physical validity.
16Keep plotting descriptive until those checks pass.

Analyze without overclaiming

Output analysis can detect errors and quantify diagnostics. It cannot by itself establish:

  • Correct equations, units, or boundary/initial/forcing conditions.
  • Adequate resolution or dealiasing.
  • Stable/accurate time integration.
  • Conservation or budget closure.
  • Statistical stationarity.
  • Grid/time convergence.
  • Physical validity.

Keep plotting descriptive until those checks pass.

Raw lines 3 to 17
18## FluidSim 0.9 physical-state format
20Official 0.9 source selects:
22- `.nc` with `h5netcdf` when h5py lacks MPI support (normal default).
23- `.h5` with h5py when h5py is MPI-enabled.
25Filename:
27```text
28state_phys_t<TIME>[_it<ITERATION>].nc
29```
31or `.h5`, depending on the backend. The file is HDF5-backed in either current
32path. It contains:
34- `/state_phys`: solver state datasets, plus netCDF dimension-scale datasets
35 such as `x` and `y`; coordinates alone are not a valid physical state.
36- `/state_phys` attributes including `time`, `it`, variable type, and purpose.
37- `/info_simul`: solver and parameter provenance.
38- Saved state parameters when available, including restart-relevant forcing
39 state in 0.9.
40- Root attributes such as run/solver identity, axes, and save date.
42Do not infer the latest valid checkpoint solely from a filename. Verify HDF5
43readability, `/state_phys`, time/iteration attributes, expected datasets,
44parameters, state parameters, size, and checksum.

FluidSim 0.9 physical-state format

Official 0.9 source selects:

  • .nc with h5netcdf when h5py lacks MPI support (normal default).
  • .h5 with h5py when h5py is MPI-enabled.

Filename:

state_phys_t<TIME>[_it<ITERATION>].nc

or .h5, depending on the backend. The file is HDF5-backed in either current path. It contains:

  • /state_phys: solver state datasets, plus netCDF dimension-scale datasets such as x and y; coordinates alone are not a valid physical state.
  • /state_phys attributes including time, it, variable type, and purpose.
  • /info_simul: solver and parameter provenance.
  • Saved state parameters when available, including restart-relevant forcing state in 0.9.
  • Root attributes such as run/solver identity, axes, and save date.

Do not infer the latest valid checkpoint solely from a filename. Verify HDF5 readability, /state_phys, time/iteration attributes, expected datasets, parameters, state parameters, size, and checksum.

Raw lines 18 to 45
46## Other common outputs
48Exact outputs depend on the solver and enabled classes.

Other common outputs

Exact outputs depend on the solver and enabled classes.

Raw lines 46 to 49
50### Spatial means
52- Legacy/solver-specific: `spatial_means.txt`, generally repeated
53 `key = value` records.
54- Some output classes use `spatial_means.json`, JSON-lines records.
55- Typical content can include time, energy/enstrophy, forcing power,
56 dissipation, and solver-specific quantities.
58Use the solver's `load()` implementation. It can return a dictionary, pandas
59object, or another solver-specific structure; do not assume one universal
60DataFrame schema.

Spatial means

  • Legacy/solver-specific: spatial_means.txt, generally repeated key = value records.
  • Some output classes use spatial_means.json, JSON-lines records.
  • Typical content can include time, energy/enstrophy, forcing power, dissipation, and solver-specific quantities.

Use the solver's load() implementation. It can return a dictionary, pandas object, or another solver-specific structure; do not assume one universal DataFrame schema.

Raw lines 50 to 61
62### Spectra
64Current 2D base spectra initialize:
66```text
67spectra1D.h5
68spectra2D.h5
69```
71Common datasets include:
73- `times`
74- `kxE`, `kyE`, or `khE`
75- solver-specific `spectrum1D*` or `spectrum2D*` arrays
77NS2D/NS3D and stratified variants define different keys and dimensions.
78`load1d_mean()`/`load2d_mean()` return dictionaries in the base implementation;
79inspect keys before use.

Spectra

Current 2D base spectra initialize:

spectra1D.h5
spectra2D.h5

Common datasets include:

  • times
  • kxE, kyE, or khE
  • solver-specific spectrum1D* or spectrum2D* arrays

NS2D/NS3D and stratified variants define different keys and dimensions. load1d_mean()/load2d_mean() return dictionaries in the base implementation; inspect keys before use.

Raw lines 62 to 80
81### Spectral energy budget
83The current base filename is:
85```text
86spect_energy_budg.h5
87```
89For NS2D, current source computes `transfer2D_E` and `transfer2D_Z` and derives
90fluxes with a reverse cumulative sum multiplied by wave-number spacing. Other
91solvers define different transfer/budget terms.
93Do not interpret a transfer sign, flux plateau, or cascade without verifying:
95- Fourier/spectrum normalization.
96- Wave-number coordinate and shell/bin measure.
97- Sign convention.
98- Time averaging interval and stationarity.
99- Forcing/dissipation ranges.
100- Finite-domain and dealiased cutoff effects.
101- Closure against the corresponding global budget.

Spectral energy budget

The current base filename is:

spect_energy_budg.h5

For NS2D, current source computes transfer2D_E and transfer2D_Z and derives fluxes with a reverse cumulative sum multiplied by wave-number spacing. Other solvers define different transfer/budget terms.

Do not interpret a transfer sign, flux plateau, or cascade without verifying:

  • Fourier/spectrum normalization.
  • Wave-number coordinate and shell/bin measure.
  • Sign convention.
  • Time averaging interval and stationarity.
  • Forcing/dissipation ranges.
  • Finite-domain and dealiased cutoff effects.
  • Closure against the corresponding global budget.
Raw lines 81 to 102
103### Logs and parameter files
105A normal run may include:
107- `params_simul.xml`
108- `info_solver.xml`
109- `stdout.txt`
110- a run lock while advancing
111- solver/output-specific HDF5, netCDF4, text, or JSON files
113Inventory actual contents instead of assuming all files exist.

Logs and parameter files

A normal run may include:

  • params_simul.xml
  • info_solver.xml
  • stdout.txt
  • a run lock while advancing
  • solver/output-specific HDF5, netCDF4, text, or JSON files

Inventory actual contents instead of assuming all files exist.

Raw lines 103 to 114
115## Bounded metadata inventory
117```bash
118python3 scripts/output_inventory.py \
119 --path run-directory \
120 --max-files 256 \
121 --max-hdf5-files 32 \
122 --max-datasets 2000 \
123 --max-attributes 5000
124```
126The helper:
128- Accepts only local paths inside `--root`.
129- Rejects URLs, parent traversal, symlinks, hard links, special files, and
130 unbounded counts.
131- Lazily imports h5py only for HDF5/netCDF4 candidates.
132- Reports dataset shape, dtype, chunks, compression, and allocated storage.
133- Reads only a short allowlist of scalar provenance attributes.
134- Does not index datasets.
135- Does not follow soft or external HDF5 links.
136- Emits strict JSON and no raw field values.
138The byte/count limits and hyperslabs bound requested data, not native HDF5
139metadata allocation or decompression buffers; they are not an OS memory quota.
141If a `.nc` file is classic netCDF rather than HDF5, it reports it unreadable
142rather than trying another unbounded parser.

Bounded metadata inventory

python3 scripts/output_inventory.py \
  --path run-directory \
  --max-files 256 \
  --max-hdf5-files 32 \
  --max-datasets 2000 \
  --max-attributes 5000

The helper:

  • Accepts only local paths inside --root.
  • Rejects URLs, parent traversal, symlinks, hard links, special files, and unbounded counts.
  • Lazily imports h5py only for HDF5/netCDF4 candidates.
  • Reports dataset shape, dtype, chunks, compression, and allocated storage.
  • Reads only a short allowlist of scalar provenance attributes.
  • Does not index datasets.
  • Does not follow soft or external HDF5 links.
  • Emits strict JSON and no raw field values.

The byte/count limits and hyperslabs bound requested data, not native HDF5 metadata allocation or decompression buffers; they are not an OS memory quota.

If a .nc file is classic netCDF rather than HDF5, it reports it unreadable rather than trying another unbounded parser.

Raw lines 115 to 143
Runs code python3 scripts/output_inventory.py :118
144## Read-only FluidSim object
146```python
147from fluidsim import load_sim_for_plot
149sim = load_sim_for_plot(
150 "run-directory",
151 merge_missing_params=False,
152 hide_stdout=True,
154```
156Official 0.9 source uses a coarse operator and disables saving/online plots.
157This is appropriate for output-class analysis, not full-resolution arbitrary
158field operations.
160Examples:
162```python
163sim.output.phys_fields.plot(time=1.0)
164sim.output.spatial_means.plot()
165sim.output.spectra.plot1d(tmin=0.5, tmax=1.0, coef_compensate=0)
166sim.output.spect_energy_budg.plot(tmin=0.5, tmax=1.0)
167```
169For NS2D, `plot1d` and `plot2d` default to `coef_compensate=3`, multiplying
170the plotted spectrum by a power of wave number. Use `coef_compensate=0` for
171an uncompensated spectrum and record the choice before interpreting slopes.
173Methods and accepted arguments vary by solver/output class. Check the selected
174class API. A successful plot says nothing about correctness.

Read-only FluidSim object

from fluidsim import load_sim_for_plot

sim = load_sim_for_plot(
    "run-directory",
    merge_missing_params=False,
    hide_stdout=True,
)

Official 0.9 source uses a coarse operator and disables saving/online plots. This is appropriate for output-class analysis, not full-resolution arbitrary field operations.

Examples:

sim.output.phys_fields.plot(time=1.0)
sim.output.spatial_means.plot()
sim.output.spectra.plot1d(tmin=0.5, tmax=1.0, coef_compensate=0)
sim.output.spect_energy_budg.plot(tmin=0.5, tmax=1.0)

For NS2D, plot1d and plot2d default to coef_compensate=3, multiplying the plotted spectrum by a power of wave number. Use coef_compensate=0 for an uncompensated spectrum and record the choice before interpreting slopes.

Methods and accepted arguments vary by solver/output class. Check the selected class API. A successful plot says nothing about correctness.

Raw lines 144 to 175
176## Full state loading
178```python
179from fluidsim import load_state_phys_file
181sim = load_state_phys_file(
182 "run-directory",
183 t_approx="last",
184 modif_save_params=True,
185 merge_missing_params=False,
186 init_with_initialized_state=True,
187 hide_stdout=True,
189```
191This can allocate full-resolution state/operators. Run the memory estimator
192first and do not use it merely to inspect metadata.
194`modif_save_params=True` disables saving/online plotting. To continue a run,
195use the reviewed restart workflow rather than toggling saving casually.

Full state loading

from fluidsim import load_state_phys_file

sim = load_state_phys_file(
    "run-directory",
    t_approx="last",
    modif_save_params=True,
    merge_missing_params=False,
    init_with_initialized_state=True,
    hide_stdout=True,
)

This can allocate full-resolution state/operators. Run the memory estimator first and do not use it merely to inspect metadata.

modif_save_params=True disables saving/online plotting. To continue a run, use the reviewed restart workflow rather than toggling saving casually.

Raw lines 176 to 196
197## Scalar and spectral summary helper
199```bash
200python3 scripts/budget_summary.py \
201 --path run-directory \
202 --max-files 128 \
203 --max-records 200000 \
204 --max-datasets 256 \
205 --max-values-per-dataset 4096
206```
208It:
210- Aggregates finite spatial-mean values in constant memory.
211- Supports every semicolon-separated term in FluidSim key/value text and
212 strict JSON-lines, including enstrophy and total injection/dissipation.
213- Counts nonfinite values rather than silently reporting a finite-only success;
214 its mean remains an unweighted mean of finite saved samples.
215- Summarizes only bounded spectral/budget hyperslabs.
216- Uses the latest first-axis record for multidimensional datasets.
217- Emits a sum only when the entire latest record fits the value bound.
218- Does not follow soft/external links, and rejects virtual/external dataset
219 storage before reading values; it does not load full large arrays.
220- Explicitly reports that convergence/physical validity are not established.
222This is a triage summary, not a solver-aware closure calculation or a
223time-weighted average. Check `nonfinite_count` alongside the finite statistics.

Scalar and spectral summary helper

python3 scripts/budget_summary.py \
  --path run-directory \
  --max-files 128 \
  --max-records 200000 \
  --max-datasets 256 \
  --max-values-per-dataset 4096

It:

  • Aggregates finite spatial-mean values in constant memory.
  • Supports every semicolon-separated term in FluidSim key/value text and strict JSON-lines, including enstrophy and total injection/dissipation.
  • Counts nonfinite values rather than silently reporting a finite-only success; its mean remains an unweighted mean of finite saved samples.
  • Summarizes only bounded spectral/budget hyperslabs.
  • Uses the latest first-axis record for multidimensional datasets.
  • Emits a sum only when the entire latest record fits the value bound.
  • Does not follow soft/external links, and rejects virtual/external dataset storage before reading values; it does not load full large arrays.
  • Explicitly reports that convergence/physical validity are not established.

This is a triage summary, not a solver-aware closure calculation or a time-weighted average. Check nonfinite_count alongside the finite statistics.

Raw lines 197 to 224
Runs code python3 scripts/budget_summary.py :200
225## Budget checks
227Construct a table or plot for each governing budget:
2291. Stored quantity change over the same interval.
2302. Measured forcing/input.
2313. Physical and numerical dissipation.
2324. Transfer terms with consistent sign/normalization.
2335. Boundary terms (zero only if justified by periodicity/model).
2346. Residual after all terms.
236Report absolute and normalized residuals, time interval, differencing method,
237save cadence, and uncertainty. A small instantaneous residual can be accidental;
238inspect trends and refinement.
240For forced turbulence, compare requested `forcing_rate` to measured forcing
241power. They are not interchangeable without checking the implementation's
242normalization and time discretization.

Budget checks

Construct a table or plot for each governing budget:

  1. Stored quantity change over the same interval.
  2. Measured forcing/input.
  3. Physical and numerical dissipation.
  4. Transfer terms with consistent sign/normalization.
  5. Boundary terms (zero only if justified by periodicity/model).
  6. Residual after all terms.

Report absolute and normalized residuals, time interval, differencing method, save cadence, and uncertainty. A small instantaneous residual can be accidental; inspect trends and refinement.

For forced turbulence, compare requested forcing_rate to measured forcing power. They are not interchangeable without checking the implementation's normalization and time discretization.

Raw lines 225 to 243
244## Resolution and dealiasing diagnostics
246At minimum:
248- Plot/inspect spectra up to the dealiased cutoff.
249- Quantify energy/variance in a documented high-wave-number tail band.
250- Check pile-up, aliasing signatures, anisotropy, and directional spectra where
251 relevant.
252- Check physical-space extrema/gradients and solver constraints.
253- Repeat at finer resolution with the same physical/nondimensional problem.
254- Avoid choosing an “inertial range” after seeing the desired slope without
255 reporting selection criteria and sensitivity.
257Power-law fitting alone does not verify a cascade or resolved simulation.

Resolution and dealiasing diagnostics

At minimum:

  • Plot/inspect spectra up to the dealiased cutoff.
  • Quantify energy/variance in a documented high-wave-number tail band.
  • Check pile-up, aliasing signatures, anisotropy, and directional spectra where relevant.
  • Check physical-space extrema/gradients and solver constraints.
  • Repeat at finer resolution with the same physical/nondimensional problem.
  • Avoid choosing an “inertial range” after seeing the desired slope without reporting selection criteria and sensitivity.

Power-law fitting alone does not verify a cascade or resolved simulation.

Raw lines 244 to 258
259## Time-step diagnostics
261Use stdout/output time-step history to inspect:
263- Initial and maximum `deltat`.
264- CFL-driven changes.
265- Fast-wave or buoyancy/rotation scales.
266- Diffusive/hyperdiffusive limits.
267- Discontinuities around restart.
268- Sensitivity to lower `deltat_max`/`cfl_coef`.
270Do not infer stability from the absence of NaNs.

Time-step diagnostics

Use stdout/output time-step history to inspect:

  • Initial and maximum deltat.
  • CFL-driven changes.
  • Fast-wave or buoyancy/rotation scales.
  • Diffusive/hyperdiffusive limits.
  • Discontinuities around restart.
  • Sensitivity to lower deltat_max/cfl_coef.

Do not infer stability from the absence of NaNs.

Raw lines 259 to 271
272## Stationarity and averaging
274Before time averaging:
276- Define stationarity metrics and burn-in independently of the desired result.
277- Plot energy, dissipation, forcing, and key observables.
278- Check drift and autocorrelation/integral times.
279- Report effective sample duration/count.
280- Repeat across seeds or independent intervals where stochastic uncertainty
281 matters.
283Do not label “statistically steady” from a short visual plateau.

Stationarity and averaging

Before time averaging:

  • Define stationarity metrics and burn-in independently of the desired result.
  • Plot energy, dissipation, forcing, and key observables.
  • Check drift and autocorrelation/integral times.
  • Report effective sample duration/count.
  • Repeat across seeds or independent intervals where stochastic uncertainty matters.

Do not label “statistically steady” from a short visual plateau.

Raw lines 272 to 284
285## Custom HDF5 reading
287If built-in loaders are insufficient, keep access bounded:
289```python
290import h5py
292with h5py.File("spectra2D.h5", "r") as handle:
293 dataset = handle["spectrum2D_E"]
294 latest = dataset[-1, :4096]
295```
297Before indexing, inspect shape, dtype, chunks, and expected bytes. Never use
298`dataset[...]` or `[:]` on an unknown large field. Check HDF5 links before
299traversal; an external link can open another file.

Custom HDF5 reading

If built-in loaders are insufficient, keep access bounded:

import h5py

with h5py.File("spectra2D.h5", "r") as handle:
    dataset = handle["spectrum2D_E"]
    latest = dataset[-1, :4096]

Before indexing, inspect shape, dtype, chunks, and expected bytes. Never use dataset[...] or [:] on an unknown large field. Check HDF5 links before traversal; an external link can open another file.

Raw lines 285 to 300
301## Plot/report provenance
303Every exported result should carry:
305- Parent run/config/script/lock hashes.
306- Solver and package/backend versions.
307- Grid/domain/dealiasing/time scheme/CFL.
308- Initial/forcing/dissipation definitions.
309- State/output file hashes or immutable manifest.
310- Exact dataset keys and time window.
311- Averaging/binning/normalization and plotting code revision.
312- Refinement and budget-check results.
314Avoid manual GUI-only transformations that cannot be reconstructed.

Plot/report provenance

Every exported result should carry:

  • Parent run/config/script/lock hashes.
  • Solver and package/backend versions.
  • Grid/domain/dealiasing/time scheme/CFL.
  • Initial/forcing/dissipation definitions.
  • State/output file hashes or immutable manifest.
  • Exact dataset keys and time window.
  • Averaging/binning/normalization and plotting code revision.
  • Refinement and budget-check results.

Avoid manual GUI-only transformations that cannot be reconstructed.

Raw lines 301 to 315
Runs code script/lock :305
316## Sources (verified 2026-10-01)
318- [Physical-field save source](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/util/phys_fields.py)
319 — `.nc`/`.h5` selection, groups, attributes, state parameters, filename.
320- [Physical-fields output source](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/base/output/phys_fields.py).
321- [NS2D spatial-means source](https://fluidsim.readthedocs.io/en/latest/_modules/fluidsim/solvers/ns2d/output/spatial_means.html)
322 — semicolon-separated energy, enstrophy, and total budget terms.
323- [h5py link access](https://docs.h5py.org/en/stable/high/group.html) and
324 [dataset storage](https://docs.h5py.org/en/stable/high/dataset.html).
325- [Spatial-means source](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/base/output/spatial_means.py).
326- [Spectra source](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/base/output/spectra.py).
327- [Spectral-budget base source](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/base/output/spect_energy_budget.py).
328- [NS2D spectral-budget source](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/solvers/ns2d/output/spect_energy_budget.py).
329- [Load utilities](https://github.com/fluiddyn/fluidsim/blob/0.9.0/fluidsim/util/util.py).
330- Mohanan et al., [FluidSim primary paper](https://doi.org/10.5334/jors.239),
331 published 2019-04-26 — architecture and output-class method claims.

Sources (verified 2026-10-01)

Raw lines 316 to 331