deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
hdf5.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2019 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#include <deal.II/base/config.h>
14
15#include <deal.II/base/hdf5.h>
16
17#include <hdf5.h>
18
19#include <iostream>
20
22
23namespace HDF5
24{
25 namespace internal
26 {
27 namespace HDF5ObjectImplementation
28 {
33 void
34 check_exception(const std::string &type, const std::string &name)
35 {
36#ifdef DEAL_II_WITH_MPI
37 if (std::uncaught_exceptions() > 0)
38 {
39 std::cerr
40 << "---------------------------------------------------------\n"
41 << "HDF5 " + type + " objects call " + name +
42 " to end access to\n"
43 << "them and release any resources they acquired. This call\n"
44 << "requires MPI synchronization. Since an exception is\n"
45 << "currently uncaught, this synchronization would likely\n"
46 << "deadlock because only the current process is trying to\n"
47 << "destroy the object. As a consequence, the program will be\n"
48 << "aborted and the HDF5 might be corrupted.\n"
49 << "---------------------------------------------------------"
50 << std::endl;
51
52 MPI_Abort(MPI_COMM_WORLD, 1);
53 }
54#else
55 (void)type;
56 (void)name;
57#endif
58 }
59 } // namespace HDF5ObjectImplementation
60 } // namespace internal
61
62
63
64 HDF5Object::HDF5Object(const std::string &name, const bool mpi)
65 : name(name)
66 , mpi(mpi)
67 {}
68
69
70
71 std::string
73 {
74 return name;
75 }
76
77
78
79 DataSet::DataSet(const std::string &name,
80 const hid_t &parent_group_id,
81 const bool mpi)
82 : HDF5Object(name, mpi)
83 , query_io_mode(false)
84 , io_mode(H5D_MPIO_NO_COLLECTIVE)
85 , local_no_collective_cause(H5D_MPIO_SET_INDEPENDENT)
86 , global_no_collective_cause(H5D_MPIO_SET_INDEPENDENT)
87 {
88 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
90 "H5Dclose");
91 // Release the HDF5 resource
92 const herr_t ret = H5Dclose(*pointer);
94 delete pointer;
95 });
96 dataspace = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
98 "H5Sclose");
99 // Release the HDF5 resource
100 const herr_t ret = H5Sclose(*pointer);
101 AssertNothrow(ret >= 0, ExcInternalError());
102 delete pointer;
103 });
104
105 // rank_ret can take a negative value if the functions
106 // H5Sget_simple_extent_ndims and H5Sget_simple_extent_dims fail. rank is
107 // unsigned int therefore it can not be used to store the return value of
108 // H5Sget_simple_extent_ndims and H5Sget_simple_extent_dims
109 int rank_ret;
110
111 *hdf5_reference = H5Dopen2(parent_group_id, name.data(), H5P_DEFAULT);
112 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Dopen2"));
113 *dataspace = H5Dget_space(*hdf5_reference);
114 Assert(*dataspace >= 0, ExcMessage("Error at H5Dget_space"));
115 rank_ret = H5Sget_simple_extent_ndims(*dataspace);
116 Assert(rank_ret >= 0, ExcInternalError());
117 rank = rank_ret;
118 dimensions.resize(rank);
119 rank_ret =
120 H5Sget_simple_extent_dims(*dataspace, dimensions.data(), nullptr);
121 AssertDimension(rank_ret, static_cast<int>(rank));
122
123 size = 1;
124 for (const auto &dimension : dimensions)
125 {
126 size *= dimension;
127 }
128 }
129
130
131
132 DataSet::DataSet(const std::string &name,
133 const hid_t &parent_group_id,
134 const std::vector<hsize_t> &dimensions,
135 const std::shared_ptr<hid_t> &t_type,
136 const bool mpi)
137 : HDF5Object(name, mpi)
138 , rank(dimensions.size())
139 , dimensions(dimensions)
140 , query_io_mode(false)
141 , io_mode(H5D_MPIO_NO_COLLECTIVE)
142 , local_no_collective_cause(H5D_MPIO_SET_INDEPENDENT)
143 , global_no_collective_cause(H5D_MPIO_SET_INDEPENDENT)
144 {
145 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
147 "H5Dclose");
148 // Release the HDF5 resource
149 const herr_t ret = H5Dclose(*pointer);
150 AssertNothrow(ret >= 0, ExcInternalError());
151 delete pointer;
152 });
153 dataspace = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
155 "H5Sclose");
156 // Release the HDF5 resource
157 const herr_t ret = H5Sclose(*pointer);
158 AssertNothrow(ret >= 0, ExcInternalError());
159 delete pointer;
160 });
161
162 *dataspace = H5Screate_simple(rank, dimensions.data(), nullptr);
163 Assert(*dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
164
165 *hdf5_reference = H5Dcreate2(parent_group_id,
166 name.data(),
167 *t_type,
168 *dataspace,
169 H5P_DEFAULT,
170 H5P_DEFAULT,
171 H5P_DEFAULT);
172 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Dcreate2"));
173
174 size = 1;
175 for (const auto &dimension : dimensions)
176 {
177 size *= dimension;
178 }
179 }
180
181
182
183 void
184 DataSet::set_query_io_mode(const bool new_query_io_mode)
185 {
186 query_io_mode = new_query_io_mode;
187 }
188
189
190
191 std::vector<hsize_t>
193 {
194 return dimensions;
195 }
196
197
198
199 std::string
201 {
203 ExcMessage("query_io_mode should be true in order to use io_mode"));
204 switch (io_mode)
205 {
206 case (H5D_MPIO_NO_COLLECTIVE):
207 return "H5D_MPIO_NO_COLLECTIVE";
208 break;
209 case (H5D_MPIO_CHUNK_INDEPENDENT):
210 return "H5D_MPIO_CHUNK_INDEPENDENT";
211 break;
212 case (H5D_MPIO_CHUNK_COLLECTIVE):
213 return "H5D_MPIO_CHUNK_COLLECTIVE";
214 break;
215 case (H5D_MPIO_CHUNK_MIXED):
216 return "H5D_MPIO_CHUNK_MIXED";
217 break;
218 case (H5D_MPIO_CONTIGUOUS_COLLECTIVE):
219 return "H5D_MPIO_CONTIGUOUS_COLLECTIVE";
220 break;
221 default:
223 return "Internal error";
224 break;
225 }
226 // The function should not reach this line.
228 return "Internal error";
229 }
230
231
232
233 H5D_mpio_actual_io_mode_t
235 {
238 "query_io_mode should be true in order to use get_io_mode"));
239 return io_mode;
240 }
241
242
243
244 std::string
246 {
247 Assert(
250 "query_io_mode should be true in order to use get_local_no_collective_cause()"));
252 }
253
254
255
256 std::uint32_t
258 {
259 Assert(
262 "query_io_mode should be true in order to use get_local_no_collective_cause()"));
264 }
265
266
267
268 std::string
270 {
271 Assert(
274 "query_io_mode should be true in order to use get_global_no_collective_cause()"));
276 }
277
278
279
280 std::uint32_t
282 {
283 Assert(
286 "query_io_mode should be true in order to use get_global_no_collective_cause()"));
288 }
289
290
291 bool
293 {
294 return query_io_mode;
295 }
296
297
298
299 unsigned int
301 {
302 return size;
303 }
304
305
306
307 unsigned int
309 {
310 return rank;
311 }
312
313
314
315 Group::Group(const std::string &name,
316 const Group &parentGroup,
317 const bool mpi,
318 const GroupAccessMode mode)
319 : HDF5Object(name, mpi)
320 {
321 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
323 // Release the HDF5 resource
324 const herr_t ret = H5Gclose(*pointer);
325 AssertNothrow(ret >= 0, ExcInternalError());
326 delete pointer;
327 });
328 switch (mode)
329 {
332 H5Gopen2(*(parentGroup.hdf5_reference), name.data(), H5P_DEFAULT);
333 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Gopen2"));
334 break;
336 *hdf5_reference = H5Gcreate2(*(parentGroup.hdf5_reference),
337 name.data(),
338 H5P_DEFAULT,
339 H5P_DEFAULT,
340 H5P_DEFAULT);
341 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Gcreate2"));
342 break;
343 default:
345 break;
346 }
347 }
348
349
350
351 Group::Group(const std::string &name, const bool mpi)
352 : HDF5Object(name, mpi)
353 {}
354
355
356
357 Group
358 Group::open_group(const std::string &name) const
359 {
360 return {name, *this, mpi, GroupAccessMode::open};
361 }
362
363
364
365 Group
366 Group::create_group(const std::string &name) const
367 {
368 return {name, *this, mpi, GroupAccessMode::create};
369 }
370
371
372
373 DataSet
374 Group::open_dataset(const std::string &name) const
375 {
376 return {name, *hdf5_reference, mpi};
377 }
378
379
380
381 File::File(const std::string &name, const FileAccessMode mode)
382 : File(name,
383 mode,
384 false,
385#ifdef DEAL_II_WITH_MPI
386 MPI_COMM_NULL
387#else
388 0
389#endif
390 )
391 {}
392
393
394
395 File::File(const std::string &name,
396 const FileAccessMode mode,
397 const MPI_Comm mpi_communicator)
398 : File(name, mode, true, mpi_communicator)
399 {}
400
401
402
403 File::File(const std::string &name,
404 const FileAccessMode mode,
405 const bool mpi,
406 const MPI_Comm mpi_communicator)
407 : Group(name, mpi)
408 {
409 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
411 // Release the HDF5 resource
412 const herr_t err = H5Fclose(*pointer);
413 AssertNothrow(err >= 0, ExcInternalError());
414 delete pointer;
415 });
416
417 hid_t plist;
418 herr_t ret;
419
420 if (mpi)
421 {
422#ifdef DEAL_II_WITH_MPI
423# ifdef H5_HAVE_PARALLEL
424 const MPI_Info info = MPI_INFO_NULL;
425
426 plist = H5Pcreate(H5P_FILE_ACCESS);
427 Assert(plist >= 0, ExcMessage("Error at H5Pcreate"));
428 ret = H5Pset_fapl_mpio(plist, mpi_communicator, info);
429 Assert(ret >= 0, ExcMessage("Error at H5Pset_fapl_mpio"));
430# else
431 AssertThrow(false, ExcMessage("HDF5 parallel support is disabled."));
432# endif // H5_HAVE_PARALLEL
433#else
434 AssertThrow(false, ExcMessage("MPI support is disabled."));
435#endif // DEAL_II_WITH_MPI
436 }
437 else
438 {
439 plist = H5P_DEFAULT;
440 }
441
442 switch (mode)
443 {
445 *hdf5_reference = H5Fopen(name.data(), H5F_ACC_RDWR, plist);
446 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Fopen"));
447 break;
450 H5Fcreate(name.data(), H5F_ACC_TRUNC, H5P_DEFAULT, plist);
451 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Fcreate"));
452 break;
453 default:
455 break;
456 }
457
458 if (mpi)
459 {
460 // Release the HDF5 resource
461 ret = H5Pclose(plist);
462 Assert(ret >= 0, ExcMessage("Error at H5Pclose"));
463 }
464
465 (void)ret;
466 (void)mpi_communicator;
467 }
468} // namespace HDF5
469
unsigned int rank
Definition hdf5.h:924
unsigned int get_rank() const
Definition hdf5.cc:308
bool query_io_mode
Definition hdf5.h:951
std::vector< hsize_t > get_dimensions() const
Definition hdf5.cc:192
std::vector< hsize_t > dimensions
Definition hdf5.h:930
std::uint32_t get_local_no_collective_cause_as_hdf5_type()
Definition hdf5.cc:257
unsigned int get_size() const
Definition hdf5.cc:300
std::shared_ptr< hid_t > dataspace
Definition hdf5.h:935
DataSet(const std::string &name, const hid_t &parent_group_id, bool mpi)
Definition hdf5.cc:79
std::string get_local_no_collective_cause()
Definition hdf5.cc:245
std::string get_io_mode()
Definition hdf5.cc:200
std::uint32_t local_no_collective_cause
Definition hdf5.h:963
std::string get_global_no_collective_cause()
Definition hdf5.cc:269
bool get_query_io_mode() const
Definition hdf5.cc:292
std::uint32_t global_no_collective_cause
Definition hdf5.h:970
std::uint32_t get_global_no_collective_cause_as_hdf5_type()
Definition hdf5.cc:281
H5D_mpio_actual_io_mode_t get_io_mode_as_hdf5_type()
Definition hdf5.cc:234
void set_query_io_mode(const bool new_query_io_mode)
Definition hdf5.cc:184
unsigned int size
Definition hdf5.h:940
H5D_mpio_actual_io_mode_t io_mode
Definition hdf5.h:956
File(const std::string &name, const FileAccessMode mode)
Definition hdf5.cc:381
FileAccessMode
Definition hdf5.h:1080
DataSet open_dataset(const std::string &name) const
Definition hdf5.cc:374
Group open_group(const std::string &name) const
Definition hdf5.cc:358
Group(const std::string &name, const Group &parent_group, const bool mpi, const GroupAccessMode mode)
Definition hdf5.cc:315
Group create_group(const std::string &name) const
Definition hdf5.cc:366
GroupAccessMode
Definition hdf5.h:983
std::shared_ptr< hid_t > hdf5_reference
Definition hdf5.h:414
std::string get_name() const
Definition hdf5.cc:72
const std::string name
Definition hdf5.h:405
HDF5Object(const std::string &name, const bool mpi)
Definition hdf5.cc:64
const bool mpi
Definition hdf5.h:419
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertNothrow(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::size_t size
Definition mpi.cc:733
void check_exception(const std::string &type, const std::string &name)
Definition hdf5.cc:34
std::string no_collective_cause_to_string(const std::uint32_t no_collective_cause)
Definition hdf5.h:1534
Definition hdf5.h:345