h5

出典:h5fortran/docs/USAGE-visualization.md

可視化用HDF5出力

t_hdf5_writer はローカルのmeshとfieldを逐次出力します。 t_phdf5_writer は全MPI rankのデータを一つのHDF5ファイルへ集合的に書きます。 Parallel APIを有効にしたビルドでは、用途に応じて二つのwriterを使い分けられます。 どちらも同じscheme_version=1のレイアウトを生成します。Fortran側ではXDMF/XMLを生成しません。HDF5時系列を出力した後、 独立ツールh5xdmfでXDMF3を生成します。

snapshot HDF5を正本とし、metadata.h5 はPythonが作る再生成可能な索引とする。 ソルバーは metadata.h5 へ追記しない。

想定する完成形:

result/
├── seq000000.h5
├── seq000001.h5
├── ...
├── metadata.h5
├── fluid.xdmf
└── soil_particles.xdmf

HDF5出力

use hdf5, only: h5open_f, h5close_f
use h5fort
use mpi
use iso_fortran_env, only: int64, real64

type(t_phdf5_writer) :: writer
integer :: ierr, hdferr
real(real64) :: nodes(3, num_points)
integer(int64) :: connectivity(8, num_cells)
real(real64) :: pressure(num_points)
real(real64) :: velocity(3, num_points)

call MPI_Init(ierr)
call h5open_f(hdferr)
if (hdferr /= 0) call MPI_Abort(MPI_COMM_WORLD, 1, ierr)

writer%h5_filepath = 'result/seq000000.h5'
writer%output_type = 'UnstructuredGrid'
writer%num_points = num_points
writer%num_cells = num_cells
writer%time = 0.0_real64

call writer%init()
call writer%write_geometry_ugrid(nodes, connectivity)
call writer%write_point_data(pressure, 'Pressure')
call writer%write_point_data(velocity, 'Velocity')
call writer%close()

call h5close_f(hdferr)
if (hdferr /= 0) call MPI_Abort(MPI_COMM_WORLD, 1, ierr)
call MPI_Finalize(ierr)

逐次出力には型を type(t_hdf5_writer) に変更し、use mpi とMPIの初期化・終了を 省略します。HDF5のエラー判定は if (hdferr /= 0) error stop とします。 writerの設定とwrite呼び出しは共通です。逐次writerはMPI有効ビルドでも利用できます。 複数rankから逐次出力する場合、rankごとに異なるファイル名を指定してください。

h5fort は常に t_hdf5_writer を公開し、 H5FORTRAN_ENABLE_PARALLEL=ON で t_phdf5_writer を公開します。 逐次writerだけを使うconsumerでは h5fortran_serial のみをリンクし、 use h5fort_serial_visualization, only: t_hdf5_writer とします。 インストール後のtarget名は h5fortran::h5fortran_serial です。 並列consumerは h5fortran_parallel、全APIを使う場合は h5fortran をリンクします。

H5FORTRAN_HDF5_ROOT(または HDF5_ROOT)に使用するHDF5のprefixを指定します。 一つのビルドでは全targetが同じHDF5を使います。parallel構成にはparallel HDF5が必要です。 この構成では h5fortran_serial だけをリンクしても、parallel HDF5由来のMPI依存が残ります。 MPI依存のない構成には、H5FORTRAN_ENABLE_PARALLEL=OFF とserial HDF5を指定して 別途ビルドしてください。serial構成でparallel HDF5を使用することもできますが、 その場合もHDF5由来のMPI依存は残ります。

以下のrankに関する説明はparallel writerに適用します。

num_cells は各rankが出力するowned cell数で、ghost cellは含めません。 num_points はowned cellが参照する全local node数です。rank境界の共有・halo nodeは rankごとに別nodeとして重複して構いません。

connectivityは nodes(:, :) を参照するrank-local 0-origin node IDで渡します。 writerがrankごとのnode offsetを加え、HDF5全体のIDへ変換します。呼び出し側で global node IDを計算するための通信は不要です。init、write、close は全rankが 同じ順序で呼びます。

両writerともHDF5ライブラリ自体の開始・終了を行いません。parallelでは全rankがプログラム全体で MPI_Init → h5open_f → writer処理 → h5close_f → MPI_Finalize の順に 呼びます。複数stepや複数meshを書いても、h5open_f / h5close_f はそれぞれ 1回だけです。

! nodes(:, 1:4) を参照するrank-local connectivity
connectivity(:, 1) = [0_int64, 1_int64, 2_int64, 3_int64]
call writer%write_geometry(nodes, connectivity)

共有nodeのfield値を一致させて可視化したい場合、必要に応じて出力前に通常のhalo exchangeを行います。これはnode番号を統合する通信ではなく、field値を同期するための 通信です。

重複nodeを結合したい場合はParaViewの Clean to Grid filterを利用できます。 ghost cellまで出力するとcellが重複するため、出力対象はowned cellだけにします。

PolyDataは output_type='PolyData'、num_cells=0 として write_geometry_polydata(nodes) を呼びます。同じ h5_filepath に UnstructuredGrid、PolyDataの順で書くと、/ugrid と /polydata に保存されます。

Connectivity meshの一般形

connectivityを持つmeshは、同じwriterで任意のXDMF topologyを扱えます。 mesh_name はHDF5のroot直下group名です。

writer%h5_filepath = 'result/seq000000.h5'
writer%output_type = 'UnstructuredGrid'
writer%mesh_name = 'tetra'
writer%topology_type = 'Tetrahedron'
writer%nodes_per_element = 4
writer%num_points = num_points
writer%num_cells = num_cells
writer%time = time

call writer%init()
call writer%write_geometry(nodes, connectivity)
call writer%write_point_data(pressure, 'Pressure')
call writer%close()

代表的な指定は次のとおりです。

要素 topology_type nodes_per_element
六面体 Hexahedron 8
四面体 Tetrahedron 4
2D四角形 Quadrilateral 4
三角形 Triangle 3

topology_type と nodes_per_element は同時に指定します。省略した場合だけ Hexahedron、8が既定値になります。同じHDF5へ異なる mesh_name で順番に 書き込むことで、複数種類のmeshを一つのtime stepに保存できます。

scheme_version=1

保存先と属性は共有仕様の可視化レイアウトを参照してください。

Fortran配列はcolumn-majorで、第1次元が最も速く変化します。HDF5 Fortran APIは 次元を反転して保存するため、C/C++・h5pyのrow-major表記とは次の対応になります。

Fortranで渡す形状 ファイル上の形状
nodes(3, num_points) (num_points, 3)
connectivity(nodes_per_element, num_cells) (num_cells, nodes_per_element)
field(ncomp, nlocal) (nlocal, ncomp)
field(nlocal) (nlocal)

並列出力ではFortranの最終次元(ファイル上の第0次元)に沿ってrankのデータを連結します。 呼び出し側で転置する必要はありません。一般の配列も a(nx, ny) がファイルでは (ny, nx) になります。次元順序も参照してください。

Tensor6 は field(6, nlocal) の第1次元を XX, YY, ZZ, XY, YZ, XZ の順にします。 テンソル成分の順序に従ってください。

geometryは real(real32/real64/real128)、connectivityは integer(int8/int16/int32/int64)、point/cell dataはこれら7 kindの1D/2Dに 対応します。

XDMFの生成

Python 3.10以上とuvを用意し、h5xdmfをインストールして実行します。

uv tool install ../h5xdmf
h5xdmf "result/seq*.h5" --metadata result/metadata.h5 --outdir result

更新・再構築、空stepの扱いと運用上の注意は POSTPROCESS.md を参照してください。

完成形のexample

逐次・並列のどちらも、5 stepの流体・土粒子snapshot出力からポストプロセスまで 一括実行できます。流体は四面体mesh上の圧力波と渦速度、土粒子は沈降・拡散と応力を持つ。

example writer 実行ファイル データ規模
serial-viz t_hdf5_writer example_serial_viz 1プロセスで全meshを作成
parallel-viz t_phdf5_writer example_parallel_viz 既定2 rankのlocal meshを結合

1プロセスで出力する場合は逐次例を使います。

example/serial-viz/generate.sh build

複数rankから集合的に出力する場合は example/parallel-viz/generate.sh build を 使います。 両例は同じmesh・field名で result/seq000000.h5 〜 seq000004.h5 を生成します。 生成されるファイルと使い方は各exampleのREADMEを参照してください。 ParaViewでの色付け、Glyph、粒子表示の手順もexample READMEに記載している。

必要な実行時ツールはPython 3.10以上、h5py、numpyです。依存関係と固定版は h5xdmfの pyproject.toml と uv.lock で管理されています。生成XDMFの確認にはParaView、 HDF5構造の手動確認には h5dump または h5ls が便利ですが、どちらも生成処理の 必須依存ではありません。