Mallard 0.8.0
Unstructured, GPU accelerated, high-order finite volume CFD solver
Mallard website
Loading...
Searching...
No Matches
hdf5_util.h
Go to the documentation of this file.
1
13#ifndef HDF5_UTIL_H
14#define HDF5_UTIL_H
15
16#ifdef Mallard_HAS_HDF5
17
18#include <algorithm>
19#include <cstdint>
20#include <stdexcept>
21#include <string>
22#include <type_traits>
23#include <vector>
24
25#include <hdf5.h>
26
27#include "comm.h"
28
29namespace h5 {
30
31#if defined(Mallard_HAS_MPI) && defined(H5_HAVE_PARALLEL)
32inline constexpr bool PARALLEL = true;
33#else
34inline constexpr bool PARALLEL = false;
35#endif
36
38class Handle {
39 public:
40 Handle(hid_t id_in, herr_t (*close_in)(hid_t), const std::string & what) : id(id_in), close(close_in) {
41 if (id < 0) throw std::runtime_error("HDF5: " + what + " failed.");
42 }
43 ~Handle() { close(id); }
44 Handle(const Handle &) = delete;
45 Handle & operator=(const Handle &) = delete;
46 operator hid_t() const { return id; }
47
48 private:
49 hid_t id;
50 herr_t (*close)(hid_t);
51};
52
53inline void check(herr_t status, const std::string & what) {
54 if (status < 0) throw std::runtime_error("HDF5: " + what + " failed.");
55}
56
57template <typename T>
59 if constexpr (std::is_same_v<T, double>) return H5T_NATIVE_DOUBLE;
60 else if constexpr (std::is_same_v<T, float>) return H5T_NATIVE_FLOAT;
61 else if constexpr (std::is_same_v<T, int64_t>) return H5T_NATIVE_INT64;
62 else if constexpr (std::is_same_v<T, uint64_t>) return H5T_NATIVE_UINT64;
63 else if constexpr (std::is_same_v<T, uint32_t>) return H5T_NATIVE_UINT32;
64 else static_assert(sizeof(T) == 0, "HDF5: unsupported type");
65}
66
67template <typename T>
69 if constexpr (std::is_same_v<T, double>) return H5T_IEEE_F64LE;
70 else if constexpr (std::is_same_v<T, float>) return H5T_IEEE_F32LE;
71 else if constexpr (std::is_same_v<T, int64_t>) return H5T_STD_I64LE;
72 else if constexpr (std::is_same_v<T, uint64_t>) return H5T_STD_U64LE;
73 else return H5T_STD_U32LE;
74}
75
77inline hid_t file_access(bool collective = true) {
79#if defined(Mallard_HAS_MPI) && defined(H5_HAVE_PARALLEL)
80 if (collective) {
81 check(H5Pset_fapl_mpio(fapl, comm::world(), MPI_INFO_NULL), "H5Pset_fapl_mpio");
82 check(H5Pset_all_coll_metadata_ops(fapl, true), "H5Pset_all_coll_metadata_ops");
83 check(H5Pset_coll_metadata_write(fapl, true), "H5Pset_coll_metadata_write");
84 }
85#else
87#endif
88 return fapl;
89}
90
92inline hid_t transfer(bool collective = true) {
94#if defined(Mallard_HAS_MPI) && defined(H5_HAVE_PARALLEL)
95 if (collective) check(H5Pset_dxpl_mpio(dxpl, H5FD_MPIO_COLLECTIVE), "H5Pset_dxpl_mpio");
96#else
98#endif
99 return dxpl;
100}
101
103inline void select_rows(hid_t space, uint64_t first, uint64_t n) {
104 hsize_t dims[2] = {0, 1};
107 if (n == 0) {
108 check(H5Sselect_none(space), "H5Sselect_none");
109 return;
110 }
111 const hsize_t start[2] = {first, 0}, count[2] = {n, rank == 2 ? dims[1] : 1};
112 check(H5Sselect_hyperslab(space, H5S_SELECT_SET, start, nullptr, count, nullptr), "H5Sselect_hyperslab");
113}
114
119template <typename T>
120void write_rows(hid_t parent, const char * name, uint64_t n_rows, int cols, uint64_t first, uint64_t n,
121 const T * data, hid_t dxpl) {
122 const int rank = cols > 1 ? 2 : 1;
123 const hsize_t dims[2] = {n_rows, hsize_t(cols)}, local[2] = {n, hsize_t(cols)};
124 Handle space(H5Screate_simple(rank, dims, nullptr), H5Sclose, "H5Screate_simple");
126 std::string("creating ") + name);
127 Handle memory(H5Screate_simple(rank, local, nullptr), H5Sclose, "H5Screate_simple");
128 select_rows(space, first, n);
129 select_rows(memory, 0, n);
130 // HDF5 rejects null buffers even for empty selections
131 const T dummy{};
132 check(H5Dwrite(dset, memory_type<T>(), memory, space, dxpl, n ? data : &dummy), std::string("writing ") + name);
133}
134
136inline uint64_t n_rows(hid_t parent, const char * name) {
137 Handle dset(H5Dopen2(parent, name, H5P_DEFAULT), H5Dclose, std::string("opening ") + name);
138 Handle space(H5Dget_space(dset), H5Sclose, "H5Dget_space");
139 hsize_t dims[2] = {0, 0};
141 return dims[0];
142}
143
145template <typename T>
146std::vector<T> read_rows(hid_t parent, const char * name, uint64_t first, uint64_t n, uint32_t cols, hid_t dxpl) {
147 Handle dset(H5Dopen2(parent, name, H5P_DEFAULT), H5Dclose, std::string("opening ") + name);
148 Handle space(H5Dget_space(dset), H5Sclose, "H5Dget_space");
149 const int rank = cols > 1 ? 2 : 1;
150 const hsize_t local[2] = {n, hsize_t(cols)};
151 Handle memory(H5Screate_simple(rank, local, nullptr), H5Sclose, "H5Screate_simple");
152 select_rows(space, first, n);
153 select_rows(memory, 0, n);
154 std::vector<T> data(std::max<uint64_t>(n * cols, 1));
155 check(H5Dread(dset, memory_type<T>(), memory, space, dxpl, data.data()), std::string("reading ") + name);
156 data.resize(n * cols);
157 return data;
158}
159
161template <typename T>
162void write_attribute(hid_t object, const char * name, T value) {
163 Handle space(H5Screate(H5S_SCALAR), H5Sclose, "H5Screate");
165 check(H5Awrite(attr, memory_type<T>(), &value), name);
166}
167
168inline void write_int_attribute(hid_t object, const char * name, int value) {
169 Handle space(H5Screate(H5S_SCALAR), H5Sclose, "H5Screate");
171 check(H5Awrite(attr, H5T_NATIVE_INT, &value), name);
172}
173
174inline int read_int_attribute(hid_t object, const char * name) {
175 if (H5Aexists(object, name) <= 0) throw std::runtime_error(std::string("HDF5 file: missing attribute ") + name);
176 Handle attr(H5Aopen(object, name, H5P_DEFAULT), H5Aclose, name);
177 int value = 0;
178 check(H5Aread(attr, H5T_NATIVE_INT, &value), name);
179 return value;
180}
181
183inline void write_strings_attribute(hid_t object, const char * name, const std::vector<std::string> & strings) {
184 size_t width = 1;
185 for (const auto & s : strings) width = std::max(width, s.size());
186 std::vector<char> buffer(std::max<size_t>(strings.size(), 1) * width, '\0');
187 for (size_t i = 0; i < strings.size(); i++) std::copy(strings[i].begin(), strings[i].end(), &buffer[i * width]);
188 Handle type(H5Tcopy(H5T_C_S1), H5Tclose, "H5Tcopy");
189 check(H5Tset_size(type, width), "H5Tset_size");
190 check(H5Tset_strpad(type, H5T_STR_NULLPAD), "H5Tset_strpad");
191 const hsize_t n = strings.size();
192 Handle space(H5Screate_simple(1, &n, nullptr), H5Sclose, "H5Screate_simple");
193 Handle attr(H5Acreate2(object, name, type, space, H5P_DEFAULT, H5P_DEFAULT), H5Aclose, name);
194 check(H5Awrite(attr, type, buffer.data()), name);
195}
196
197inline std::vector<std::string> read_strings_attribute(hid_t object, const char * name) {
198 Handle attr(H5Aopen(object, name, H5P_DEFAULT), H5Aclose, name);
199 Handle type(H5Aget_type(attr), H5Tclose, "H5Aget_type");
200 Handle space(H5Aget_space(attr), H5Sclose, "H5Aget_space");
201 const size_t width = H5Tget_size(type);
204 check(H5Tset_size(memory_type, width), "H5Tset_size");
206 std::vector<char> buffer(static_cast<size_t>(std::max<hssize_t>(n, 1)) * width, '\0');
207 check(H5Aread(attr, memory_type, buffer.data()), name);
208 std::vector<std::string> strings;
209 for (hssize_t i = 0; i < n; i++) {
210 const char * s = &buffer[static_cast<size_t>(i) * width];
211 strings.emplace_back(s, std::find(s, s + width, '\0'));
212 }
213 return strings;
214}
215
216} // namespace h5
217
218#endif // Mallard_HAS_HDF5
219
220#endif // HDF5_UTIL_H
Process-level communication: MPI when built with Mallard_ENABLE_MPI, otherwise a single-rank stub wit...
KOKKOS_INLINE_FUNCTION rtype dot(const rtype *a, const rtype *b)
Compute the dot product of two arrays.
Definition common_math.h:32
int rank()
Rank of this process in the world communicator.
Definition comm.cpp:181
int size()
Number of processes in the world communicator.
Definition comm.cpp:182
std::string count(uint64_t n)
1234567 -> "1,234,567".
Definition log.cpp:167
BaseDims dims
Definition units.cpp:32