deal.II version GIT relicensing-2206-gaa53ff9447 2024-12-02 09: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 (void)ret;
99 delete pointer;
100 });
101 dataspace = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
103 "H5Sclose");
104 // Release the HDF5 resource
105 const herr_t ret = H5Sclose(*pointer);
106 AssertNothrow(ret >= 0, ExcInternalError());
107 (void)ret;
108 delete pointer;
109 });
110
111 // rank_ret can take a negative value if the functions
112 // H5Sget_simple_extent_ndims and H5Sget_simple_extent_dims fail. rank is
113 // unsigned int therefore it can not be used to store the return value of
114 // H5Sget_simple_extent_ndims and H5Sget_simple_extent_dims
115 int rank_ret;
116
117 *hdf5_reference = H5Dopen2(parent_group_id, name.data(), H5P_DEFAULT);
118 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Dopen2"));
119 *dataspace = H5Dget_space(*hdf5_reference);
120 Assert(*dataspace >= 0, ExcMessage("Error at H5Dget_space"));
121 rank_ret = H5Sget_simple_extent_ndims(*dataspace);
122 Assert(rank_ret >= 0, ExcInternalError());
123 rank = rank_ret;
124 dimensions.resize(rank);
125 rank_ret =
126 H5Sget_simple_extent_dims(*dataspace, dimensions.data(), nullptr);
127 AssertDimension(rank_ret, static_cast<int>(rank));
128
129 size = 1;
130 for (const auto &dimension : dimensions)
131 {
132 size *= dimension;
133 }
134 }
135
136
137
138 DataSet::DataSet(const std::string &name,
139 const hid_t &parent_group_id,
140 const std::vector<hsize_t> &dimensions,
141 const std::shared_ptr<hid_t> &t_type,
142 const bool mpi)
143 : HDF5Object(name, mpi)
144 , rank(dimensions.size())
145 , dimensions(dimensions)
146 , query_io_mode(false)
147 , io_mode(H5D_MPIO_NO_COLLECTIVE)
148 , local_no_collective_cause(H5D_MPIO_SET_INDEPENDENT)
149 , global_no_collective_cause(H5D_MPIO_SET_INDEPENDENT)
150 {
151 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
153 "H5Dclose");
154 // Release the HDF5 resource
155 const herr_t ret = H5Dclose(*pointer);
156 AssertNothrow(ret >= 0, ExcInternalError());
157 (void)ret;
158 delete pointer;
159 });
160 dataspace = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
162 "H5Sclose");
163 // Release the HDF5 resource
164 const herr_t ret = H5Sclose(*pointer);
165 AssertNothrow(ret >= 0, ExcInternalError());
166 (void)ret;
167 delete pointer;
168 });
169
170 *dataspace = H5Screate_simple(rank, dimensions.data(), nullptr);
171 Assert(*dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
172
173 *hdf5_reference = H5Dcreate2(parent_group_id,
174 name.data(),
175 *t_type,
176 *dataspace,
177 H5P_DEFAULT,
178 H5P_DEFAULT,
179 H5P_DEFAULT);
180 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Dcreate2"));
181
182 size = 1;
183 for (const auto &dimension : dimensions)
184 {
185 size *= dimension;
186 }
187 }
188
189
190
191 void
192 DataSet::set_query_io_mode(const bool new_query_io_mode)
193 {
194 query_io_mode = new_query_io_mode;
195 }
196
197
198
199 std::vector<hsize_t>
201 {
202 return dimensions;
203 }
204
205
206
207 std::string
209 {
211 ExcMessage("query_io_mode should be true in order to use io_mode"));
212 switch (io_mode)
213 {
214 case (H5D_MPIO_NO_COLLECTIVE):
215 return "H5D_MPIO_NO_COLLECTIVE";
216 break;
217 case (H5D_MPIO_CHUNK_INDEPENDENT):
218 return "H5D_MPIO_CHUNK_INDEPENDENT";
219 break;
220 case (H5D_MPIO_CHUNK_COLLECTIVE):
221 return "H5D_MPIO_CHUNK_COLLECTIVE";
222 break;
223 case (H5D_MPIO_CHUNK_MIXED):
224 return "H5D_MPIO_CHUNK_MIXED";
225 break;
226 case (H5D_MPIO_CONTIGUOUS_COLLECTIVE):
227 return "H5D_MPIO_CONTIGUOUS_COLLECTIVE";
228 break;
229 default:
231 return "Internal error";
232 break;
233 }
234 // The function should not reach this line.
236 return "Internal error";
237 }
238
239
240
241 H5D_mpio_actual_io_mode_t
243 {
246 "query_io_mode should be true in order to use get_io_mode"));
247 return io_mode;
248 }
249
250
251
252 std::string
254 {
255 Assert(
258 "query_io_mode should be true in order to use get_local_no_collective_cause()"));
260 }
261
262
263
264 std::uint32_t
266 {
267 Assert(
270 "query_io_mode should be true in order to use get_local_no_collective_cause()"));
272 }
273
274
275
276 std::string
278 {
279 Assert(
282 "query_io_mode should be true in order to use get_global_no_collective_cause()"));
284 }
285
286
287
288 std::uint32_t
290 {
291 Assert(
294 "query_io_mode should be true in order to use get_global_no_collective_cause()"));
296 }
297
298
299 bool
301 {
302 return query_io_mode;
303 }
304
305
306
307 unsigned int
309 {
310 return size;
311 }
312
313
314
315 unsigned int
317 {
318 return rank;
319 }
320
321
322
323 Group::Group(const std::string &name,
324 const Group &parentGroup,
325 const bool mpi,
326 const GroupAccessMode mode)
327 : HDF5Object(name, mpi)
328 {
329 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
331 // Release the HDF5 resource
332 const herr_t ret = H5Gclose(*pointer);
333 AssertNothrow(ret >= 0, ExcInternalError());
334 (void)ret;
335 delete pointer;
336 });
337 switch (mode)
338 {
341 H5Gopen2(*(parentGroup.hdf5_reference), name.data(), H5P_DEFAULT);
342 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Gopen2"));
343 break;
345 *hdf5_reference = H5Gcreate2(*(parentGroup.hdf5_reference),
346 name.data(),
347 H5P_DEFAULT,
348 H5P_DEFAULT,
349 H5P_DEFAULT);
350 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Gcreate2"));
351 break;
352 default:
354 break;
355 }
356 }
357
358
359
360 Group::Group(const std::string &name, const bool mpi)
361 : HDF5Object(name, mpi)
362 {}
363
364
365
366 Group
367 Group::open_group(const std::string &name) const
368 {
369 return {name, *this, mpi, GroupAccessMode::open};
370 }
371
372
373
374 Group
375 Group::create_group(const std::string &name) const
376 {
377 return {name, *this, mpi, GroupAccessMode::create};
378 }
379
380
381
382 DataSet
383 Group::open_dataset(const std::string &name) const
384 {
385 return {name, *hdf5_reference, mpi};
386 }
387
388
389
390 File::File(const std::string &name, const FileAccessMode mode)
391 : File(name,
392 mode,
393 false,
394# ifdef DEAL_II_WITH_MPI
395 MPI_COMM_NULL
396# else
397 0
398# endif
399 )
400 {}
401
402
403
404 File::File(const std::string &name,
405 const FileAccessMode mode,
406 const MPI_Comm mpi_communicator)
407 : File(name, mode, true, mpi_communicator)
408 {}
409
410
411
412 File::File(const std::string &name,
413 const FileAccessMode mode,
414 const bool mpi,
415 const MPI_Comm mpi_communicator)
416 : Group(name, mpi)
417 {
418 hdf5_reference = std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
420 // Release the HDF5 resource
421 const herr_t err = H5Fclose(*pointer);
422 AssertNothrow(err >= 0, ExcInternalError());
423 (void)err;
424 delete pointer;
425 });
426
427 hid_t plist;
428 herr_t ret;
429
430 if (mpi)
431 {
432# ifdef DEAL_II_WITH_MPI
433# ifdef H5_HAVE_PARALLEL
434 const MPI_Info info = MPI_INFO_NULL;
435
436 plist = H5Pcreate(H5P_FILE_ACCESS);
437 Assert(plist >= 0, ExcMessage("Error at H5Pcreate"));
438 ret = H5Pset_fapl_mpio(plist, mpi_communicator, info);
439 Assert(ret >= 0, ExcMessage("Error at H5Pset_fapl_mpio"));
440# else
441 AssertThrow(false, ExcMessage("HDF5 parallel support is disabled."));
442# endif // H5_HAVE_PARALLEL
443# else
444 AssertThrow(false, ExcMessage("MPI support is disabled."));
445# endif // DEAL_II_WITH_MPI
446 }
447 else
448 {
449 plist = H5P_DEFAULT;
450 }
451
452 switch (mode)
453 {
455 *hdf5_reference = H5Fopen(name.data(), H5F_ACC_RDWR, plist);
456 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Fopen"));
457 break;
460 H5Fcreate(name.data(), H5F_ACC_TRUNC, H5P_DEFAULT, plist);
461 Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Fcreate"));
462 break;
463 default:
465 break;
466 }
467
468 if (mpi)
469 {
470 // Release the HDF5 resource
471 ret = H5Pclose(plist);
472 Assert(ret >= 0, ExcMessage("Error at H5Pclose"));
473 }
474
475 (void)ret;
476 (void)mpi_communicator;
477 }
478} // namespace HDF5
479
481
482#endif // DEAL_II_WITH_HDF5
unsigned int rank
Definition hdf5.h:924
unsigned int get_rank() const
Definition hdf5.cc:316
bool query_io_mode
Definition hdf5.h:951
std::vector< hsize_t > get_dimensions() const
Definition hdf5.cc:200
std::vector< hsize_t > dimensions
Definition hdf5.h:930
std::uint32_t get_local_no_collective_cause_as_hdf5_type()
Definition hdf5.cc:265
unsigned int get_size() const
Definition hdf5.cc:308
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:83
std::string get_local_no_collective_cause()
Definition hdf5.cc:253
std::string get_io_mode()
Definition hdf5.cc:208
std::uint32_t local_no_collective_cause
Definition hdf5.h:963
std::string get_global_no_collective_cause()
Definition hdf5.cc:277
bool get_query_io_mode() const
Definition hdf5.cc:300
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:289
H5D_mpio_actual_io_mode_t get_io_mode_as_hdf5_type()
Definition hdf5.cc:242
void set_query_io_mode(const bool new_query_io_mode)
Definition hdf5.cc:192
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:390
FileAccessMode
Definition hdf5.h:1080
DataSet open_dataset(const std::string &name) const
Definition hdf5.cc:383
Group open_group(const std::string &name) const
Definition hdf5.cc:367
Group(const std::string &name, const Group &parent_group, const bool mpi, const GroupAccessMode mode)
Definition hdf5.cc:323
Group create_group(const std::string &name) const
Definition hdf5.cc:375
GroupAccessMode
Definition hdf5.h:983
std::shared_ptr< hid_t > hdf5_reference
Definition hdf5.h:414
std::string get_name() const
Definition hdf5.cc:76
const std::string name
Definition hdf5.h:405
HDF5Object(const std::string &name, const bool mpi)
Definition hdf5.cc:68
const bool mpi
Definition hdf5.h:419
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
#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)
#define DEAL_II_ASSERT_UNREACHABLE()
std::size_t size
Definition mpi.cc:734
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:1536
Definition hdf5.h:345