Reference documentation for deal.II version Git 52b85b2253 2021-11-28 10:49:58 +0100
\(\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 
28 namespace 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  {
251  ExcMessage(
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(
263  ExcMessage(
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(
275  ExcMessage(
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(
287  ExcMessage(
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(
299  ExcMessage(
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  {
345  case (GroupAccessMode::open):
346  *hdf5_reference =
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  {
460  case (FileAccessMode::open):
461  *hdf5_reference = H5Fopen(name.data(), H5F_ACC_RDWR, plist);
462  Assert(*hdf5_reference >= 0, ExcMessage("Error at H5Fopen"));
463  break;
464  case (FileAccessMode::create):
465  *hdf5_reference =
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
void check_exception(const std::string &type, const std::string &name)
Definition: hdf5.cc:39
#define AssertNothrow(cond, exc)
Definition: exceptions.h:1524
DataSet open_dataset(const std::string &name) const
Definition: hdf5.cc:389
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1655
GroupAccessMode
Definition: hdf5.h:982
std::string get_name() const
Definition: hdf5.cc:82
H5D_mpio_actual_io_mode_t get_io_mode_as_hdf5_type()
Definition: hdf5.cc:248
Group(const std::string &name, const Group &parent_group, const bool mpi, const GroupAccessMode mode)
Definition: hdf5.cc:329
HDF5Object(const std::string &name, const bool mpi)
Definition: hdf5.cc:74
std::shared_ptr< hid_t > hdf5_reference
Definition: hdf5.h:415
#define AssertThrow(cond, exc)
Definition: exceptions.h:1571
FileAccessMode
Definition: hdf5.h:1079
unsigned int size
Definition: hdf5.h:940
DataSet(const std::string &name, const hid_t &parent_group_id, bool mpi)
Definition: hdf5.cc:89
bool query_io_mode
Definition: hdf5.h:951
static ::ExceptionBase & ExcMessage(std::string arg1)
Group create_group(const std::string &name) const
Definition: hdf5.cc:381
#define Assert(cond, exc)
Definition: exceptions.h:1461
void set_query_io_mode(const bool new_query_io_mode)
Definition: hdf5.cc:198
unsigned int get_rank() const
Definition: hdf5.cc:322
const std::string name
Definition: hdf5.h:406
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:401
std::string no_collective_cause_to_string(const uint32_t no_collective_cause)
Definition: hdf5.h:1527
unsigned int get_size() const
Definition: hdf5.cc:314
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 rank
Definition: hdf5.h:924
std::shared_ptr< hid_t > dataspace
Definition: hdf5.h:935
Definition: hdf5.h:345
std::string get_local_no_collective_cause()
Definition: hdf5.cc:259
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:400
uint32_t local_no_collective_cause
Definition: hdf5.h:963
std::vector< hsize_t > get_dimensions() const
Definition: hdf5.cc:206
std::string get_global_no_collective_cause()
Definition: hdf5.cc:283
uint32_t global_no_collective_cause
Definition: hdf5.h:970
std::string get_io_mode()
Definition: hdf5.cc:214
const bool mpi
Definition: hdf5.h:420
H5D_mpio_actual_io_mode_t io_mode
Definition: hdf5.h:956
File(const std::string &name, const FileAccessMode mode)
Definition: hdf5.cc:396
uint32_t get_local_no_collective_cause_as_hdf5_type()
Definition: hdf5.cc:271
bool get_query_io_mode() const
Definition: hdf5.cc:306
static ::ExceptionBase & ExcInternalError()
Group open_group(const std::string &name) const
Definition: hdf5.cc:373