|
TRUST 1.9.8
HPC thermohydraulic platform
|
This page covers the postprocessing half of a Jupyter validation form: loading the artifacts produced by run.runCases(), plotting and tabulating them, including VisIt renderings, and — most importantly — presenting the results in a way that future maintainers can actually act on.
Test-case declaration (everything that runs before run.runCases()) is covered in How to write a validation report. Running a form is covered in How to execute a validation report.
A validation form has a strict ordering:
The boundary is not just stylistic. The non-regression extraction process concatenates the Python cells of the notebook up to and including the run.runCases() call, replaces that call with a list-emitting helper, and runs the result in a headless context. Anything that lives below that line is invisible to NR; anything that lives above must be safe to execute in that headless mode. Several of the gotchas below follow from that single rule.
Every file the postprocessing code reads or writes must resolve to a path inside run.BUILD_DIRECTORY. A validation form can be redirected to a different build directory (e.g. by passing -dest through JUPYTER_RUN_OPTIONS), so hardcoded ./build paths break in those modes.
Most of the trustutils API does the right thing automatically: relative paths given to plot.loadText, Graph.addPoint, Graph.addSegment, Table.addLine-with-a-file, dumpText, visit.showField, etc. are resolved against run.BUILD_DIRECTORY. Use those entry points when possible.
For raw Python — anything that opens or writes a file directly, the most common offender being plt.savefig — join with run.BUILD_DIRECTORY explicitly:
If a path needs to be validated explicitly, run.sanitizePathToBUILD_DIRECTORY(path) returns it as an absolute path inside build/ (and raises if the input escapes it).
Run_fiche -archive packages build/ plus a used_files manifest that lists every file the report depends on (see How to execute a validation report). Files not in used_files are not in the archive, and the report cannot be rebuilt from it.
The trustutils API marks the files it touches automatically: every plot.loadText, plot.read_csv, Graph.addPoint/addSegment, plot.displayImageFile, dumpText, ... calls run.saveFileAccumulator under the hood. Custom code that writes or reads a file outside the trustutils API must do that itself:
A form is PR-ready only when Run_fiche -archive succeeds after a full build (see Archiving — required before requesting a PR).
Never import matplotlib.* and never from trustutils import plot (which transitively imports matplotlib) in a cell that runs before the run.runCases() call. NR extraction executes those cells in a headless context, and the matplotlib import there can break extraction.
Concretely: keep all from trustutils import plot, import matplotlib.* and from trustutils import visit imports in postprocessing cells only, strictly below run.runCases(). If a helper in src/python_modules/ uses matplotlib, it must also only be imported from postprocessing cells.
A validation form is read more times than it is written. The first reader is yourself. The second is your colleagues. The third — the one that matters most for this section — is a maintainer some years from now who may not share your numerical-methods or physics background.
The cost of getting this wrong differs by project. In TRUST itself, which is essentially a numerical toolbox, a thin validation form is annoying but survivable: another expert can usually recover the intent. In baltiks that implement specific physical models, correlations or numerical schemes, the validation form is often the only living explanation of those choices, so a thin form is much more expensive — the knowledge attached to it walks out the door with whoever wrote it. TrioCFD is one open-source example of such a project. The guidelines below are written with that harder case in mind; they apply to any validation form, but they matter more the further you are from a pure numerical toolbox.
The rules below are deliberately opinionated and a bit abstract. Section A practical checklist at the end of this section translates them into something a reviewer can tick off.
For every figure, table or printed result, the surrounding markdown must state two things: what claim is being made, and why the visual supports it. A figure with no commentary is decoration, not validation; if you cannot articulate why a visual is in the form, remove it.
Add a one-sentence summary at the top of the postprocessing section that names the claim being validated — e.g. "this report validates the second-order convergence of scheme X on a manufactured solution" — so that a reader who only skims the form still gets the headline. Do not assume the reader will infer intent from a graph.
The strongest form of validation is a quantitative check against an absolute reference (analytical solution, manufactured solution, conservation law, asymptotic convergence rate, ...). When you have one, materialise the comparison as a number with a stated tolerance — in a table or as an annotation on the graph — not just as overlapping curves. "The curves look the same" is not a pass criterion: a maintainer regenerating the PDF cannot tell whether a small deviation is noise or a regression.
When no absolute reference is available — a common situation in CFD — the section must instead explicitly describe the expected behaviour and the plausible failure modes:
The goal is that a maintainer regenerating the report after a change can decide on their own whether the output still passes — without contacting the original author.
A maintainer three years from now may have a different numerical methods background, a different physics background, or both. Therefore:
A form that only shows numbers matching numbers is a regression test wearing the clothes of a validation report. It will tell you when something changes; it will not tell anyone whether the change is good or bad.
A form that also explains what the numbers mean, why they should match, and what a future failure would look like, is documentation that doubles as a regression test. The latter is what carries a project across team changes — especially in baltiks where the form is often the de facto specification of a physical model or correlation.
This is not a checklist item; it is the question to ask yourself before merging: if I left the project tomorrow, would someone unfamiliar with this test be able to maintain it from the report alone? If not, the report needs more text, not more plots.
Six items to run through before opening a PR with a new or modified validation form:
A concise tour of the trustutils postprocessing entry points. All accept paths relative to run.BUILD_DIRECTORY and call run.saveFileAccumulator under the hood, so files they touch are automatically archive-friendly.
For end-to-end examples of all of the above, see Validation/Rapports_automatiques/Verification/SampleFormJupyter.