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