Skip to content

Add the Paraview parallel output format (.pvtu with one piece per rank) - #2977

Open
rois1995 wants to merge 7 commits into
developfrom
paraviewParallelOutput
Open

rois1995 wants to merge 7 commits into
developfrom
paraviewParallelOutput

Conversation

@rois1995

@rois1995 rois1995 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Proposed Changes

PARAVIEW already writes in parallel: all ranks write into one shared .vtu file with MPI-IO. But that file has only one piece, so ParaView reads it on one process, even when ParaView runs with many processes (pvserver or pvbatch with MPI). A large case may not fit in the memory of that process, and reading, filtering and rendering are serial.

This PR adds two output formats that ParaView can also read in parallel:

  • PARAVIEW_PARALLEL
  • SURFACE_PARAVIEW_PARALLEL

They write a .pvtu file plus a folder with one .vtu piece per MPI rank:

flow.pvtu
flow/flow_0.vtu
flow/flow_1.vtu
...
  • ParaView with several processes (pvserver or pvbatch with MPI) gives the pieces to its processes, so each process reads and works on only part of the mesh. It does not need the same number of processes as the SU2 run.
  • Each rank writes its own piece, with no collective call, so this is also the fastest format to write.
  • Each piece holds the cells of its own partition. Only the points on the partition boundary are written twice: +3% points on 4 ranks and +8% on 16 ranks for a 1.9M-cell mesh.
  • The precision follows VOLUME_OUTPUT_PRECISION. The connectivity uses Int64 when a piece needs it.
PARAVIEW PARAVIEW_PARALLEL
Files one .vtu one .pvtu + one .vtu per rank
SU2 writes in parallel yes (one shared file, MPI-IO) yes (one file per rank)
ParaView reads in parallel no (one piece) yes (one piece per rank)

PARAVIEW is not changed. Use it for small cases and when one file is easier to handle.

Test case

New regression test pvtu_writer / pvtu_surface_writer (parallel, 2 ranks), TestCases/output_writers/pvtu_output.cfg. It writes the flat plate solution with both new formats and compares the .pvtu files with reference files. The pieces are binary, so the test harness cannot compare them.

I checked the pieces by hand on a wing mesh (1.1M cells, 4 ranks), loaded in ParaView 5.13:

  • flow.pvtu has the same 1 086 181 cells as flow.vtu from PARAVIEW.
  • All 23 fields are identical to flow.vtu (max difference 0).
  • surface_flow.pvtu loads correctly. 2 of its 4 pieces are empty because those ranks have no surface elements.
  • Unsteady run (NACA0012, 3 time steps, 2 ranks): each saved step gets its own .pvtu file and folder (flow_00000.pvtu, flow_00000/, ...), with the same names as PARAVIEW. ParaView loads flow_*.pvtu as one time series.

Related Work

PR Checklist

  • I am submitting my contribution to the develop branch.
  • My contribution generates no new compiler warnings (try with --warnlevel=3 when using meson).
  • My contribution is commented and consistent with SU2 style (https://su2code.github.io/docs_v7/Style-Guide/).
  • I used the pre-commit hook to prevent dirty commits and used pre-commit run --all to format old commits.
  • I have added a test case that demonstrates my contribution, if necessary.
  • I have updated appropriate documentation (Tutorials, Docs Page, config_template.cpp), if necessary.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm

rois1995 and others added 4 commits October 14, 2026 07:34
The PARAVIEW writer produces a single .vtu with one piece, which ParaView
loads on one process: a large case does not fit in the memory of one
process, and reading, filtering and rendering are serial. Users work
around this by converting the output to .pvtu by hand.

Add PARAVIEW_PARALLEL and SURFACE_PARAVIEW_PARALLEL, which write a .pvtu
file listing one .vtu piece per rank, in a folder next to it. Every rank
writes its own piece with no collective call, so the writing is also the
fastest of the formats.

A piece must be self-contained, so each rank collects the points used by
its elements and asks the ranks that own them for their data (one
all-to-all exchange). The connectivity is loaded without sorting, i.e.
each rank writes the elements of its own partition, which are next to
each other, so only the points on the partition boundary are duplicated:
on a 1.9M element mesh the pieces hold 3% more points than the mesh on 4
ranks and 8% more on 16 ranks (the sorted partition would give +122% and
+225%).

The precision follows VOLUME_OUTPUT_PRECISION, and the connectivity
uses Int64 when a piece needs it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6
The flat plate solution is written with PARAVIEW_PARALLEL and
SURFACE_PARAVIEW_PARALLEL on 2 ranks, and the .pvtu files are compared
with reference files (su2code/TestCases, output_writers/).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm
…stCases

Temporary, for the reference files of the TestCases PR. To be reverted
to develop before merging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm
- The point data is passive: exchange it with the passive MPI wrapper,
  the AD wrapper treated the buffers as su2double and overran them.
- Create the folder of the pieces with the one-argument mkdir on MinGW,
  as CPhysicalGeometry does.
- Exchange the data one field at a time, so that the MPI counts are
  numbers of points and cannot overflow an int with many fields.
- Write each array to the file as soon as it is built, instead of
  building the whole piece in memory first.
- Decide Int32 or Int64 for the connectivity once for all pieces, so
  that the pieces and the .pvtu file declare the same type.
- Fix a typo and the author of the new files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm
Comment thread SU2_CFD/src/output/filewriter/CParaviewPVTUFileWriter.cpp Fixed
Comment thread SU2_CFD/src/output/filewriter/CParaviewPVTUFileWriter.cpp Fixed
Comment thread SU2_CFD/src/output/filewriter/CParaviewPVTUFileWriter.cpp Fixed
Comment thread SU2_CFD/src/output/filewriter/CParaviewPVTUFileWriter.cpp Fixed
rois1995 and others added 2 commits October 14, 2026 09:12
Create the files with owner read/write and group/others read permissions
instead of fopen (0666 before the umask), and use size_t for the field
counters, which are compared with the number of fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants