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