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.h
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 - 2026 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#ifndef dealii_hdf5_h
14#define dealii_hdf5_h
15
16#include <deal.II/base/config.h>
17
18#ifdef DEAL_II_WITH_HDF5
19
21
23
24# include <hdf5.h>
25
26# include <numeric>
27
28#endif // DEAL_II_WITH_HDF5
29
31
32#ifdef DEAL_II_WITH_HDF5
33// It is necessary to turn clang-format off in order to maintain the Doxygen
34// links because they are longer than 80 characters
35// clang-format off
343// clang-format on
344namespace HDF5
345{
350 {
351 protected:
356 HDF5Object(const std::string &name, const bool mpi);
357
358 public:
371 template <typename T>
372 T
373 get_attribute(const std::string &attr_name) const;
374
387 template <typename T>
388 void
389 set_attribute(const std::string &attr_name, const T value);
390
396 std::string
397 get_name() const;
398
399 protected:
405 const std::string name;
406
414 std::shared_ptr<hid_t> hdf5_reference;
415
419 const bool mpi;
420 };
421
425 class DataSet : public HDF5Object
426 {
427 friend class Group;
428
429 protected:
434 DataSet(const std::string &name, const hid_t &parent_group_id, bool mpi);
435
440 DataSet(const std::string &name,
441 const hid_t &parent_group_id,
442 const std::vector<hsize_t> &dimensions,
443 const std::shared_ptr<hid_t> &t_type,
444 const bool mpi);
445
446 public:
464 template <typename Container>
465 Container
466 read();
467
501 template <typename Container>
502 Container
503 read_selection(const std::vector<hsize_t> &coordinates);
504
505 // clang-format off
539 // clang-format on
540 template <typename Container>
541 Container
542 read_hyperslab(const std::vector<hsize_t> &offset,
543 const std::vector<hsize_t> &count);
544
577 template <typename Container>
578 Container
579 read_hyperslab(const std::vector<hsize_t> &data_dimensions,
580 const std::vector<hsize_t> &offset,
581 const std::vector<hsize_t> &stride,
582 const std::vector<hsize_t> &count,
583 const std::vector<hsize_t> &block);
584
596 template <typename number>
597 void
598 read_none();
599
618 template <typename Container>
619 void
620 write(const Container &data);
621
650 template <typename Container>
651 void
652 write_selection(const Container &data,
653 const std::vector<hsize_t> &coordinates);
654
655 // clang-format off
681 // clang-format on
682 template <typename Container>
683 void
684 write_hyperslab(const Container &data,
685 const std::vector<hsize_t> &offset,
686 const std::vector<hsize_t> &count);
687
720 template <typename Container>
721 void
722 write_hyperslab(const Container &data,
723 const std::vector<hsize_t> &data_dimensions,
724 const std::vector<hsize_t> &offset,
725 const std::vector<hsize_t> &stride,
726 const std::vector<hsize_t> &count,
727 const std::vector<hsize_t> &block);
728
746 template <typename number>
747 void
748 write_none();
749
766 bool
767 get_query_io_mode() const;
768
772 void
773 set_query_io_mode(const bool new_query_io_mode);
774
789 std::string
790 get_io_mode();
791
808 H5D_mpio_actual_io_mode_t
810
829 std::string
831
853 std::uint32_t
855
874 std::string
876
897 std::uint32_t
899
905 std::vector<hsize_t>
906 get_dimensions() const;
907
911 unsigned int
912 get_size() const;
913
917 unsigned int
918 get_rank() const;
919
920 private:
924 unsigned int rank;
925
930 std::vector<hsize_t> dimensions;
931
935 std::shared_ptr<hid_t> dataspace;
936
940 unsigned int size;
941
952
956 H5D_mpio_actual_io_mode_t io_mode;
957
964
971 };
972
976 class Group : public HDF5Object
977 {
978 protected:
983 {
987 open,
991 create
992 };
1001 Group(const std::string &name,
1002 const Group &parent_group,
1003 const bool mpi,
1004 const GroupAccessMode mode);
1005
1011 Group(const std::string &name, const bool mpi);
1012
1013 public:
1017 Group
1018 open_group(const std::string &name) const;
1019
1023 Group
1024 create_group(const std::string &name) const;
1025
1029 DataSet
1030 open_dataset(const std::string &name) const;
1031
1042 template <typename number>
1043 DataSet
1044 create_dataset(const std::string &name,
1045 const std::vector<hsize_t> &dimensions) const;
1046
1065 template <typename Container>
1066 void
1067 write_dataset(const std::string &name, const Container &data) const;
1068 };
1069
1073 class File : public Group
1074 {
1075 public:
1080 {
1084 open,
1088 create
1089 };
1090
1096 File(const std::string &name, const FileAccessMode mode);
1097
1105 File(const std::string &name,
1106 const FileAccessMode mode,
1107 const MPI_Comm mpi_communicator);
1108
1109 private:
1117 File(const std::string &name,
1118 const FileAccessMode mode,
1119 const bool mpi,
1120 const MPI_Comm mpi_communicator);
1121 };
1122
1123 namespace internal
1124 {
1136 template <typename number>
1137 std::shared_ptr<hid_t>
1139
1149 template <typename number>
1150 std::vector<hsize_t>
1151 get_container_dimensions(const std::vector<number> &data);
1152
1157 template <typename number>
1158 std::vector<hsize_t>
1160
1165 template <typename number>
1166 std::vector<hsize_t>
1168
1173 template <typename number>
1174 unsigned int
1175 get_container_size(const std::vector<number> &data);
1176
1181 template <typename number>
1182 unsigned int
1184
1189 template <typename number>
1190 unsigned int
1192
1211 template <typename Container>
1212 std::enable_if_t<
1213 std::is_same_v<Container, std::vector<typename Container::value_type>>,
1214 Container>
1215 initialize_container(const std::vector<hsize_t> &dimensions);
1216
1220 template <typename Container>
1221 std::enable_if_t<
1222 std::is_same_v<Container, Vector<typename Container::value_type>>,
1223 Container>
1224 initialize_container(const std::vector<hsize_t> &dimensions);
1225
1229 template <typename Container>
1230 std::enable_if_t<
1231 std::is_same_v<Container, FullMatrix<typename Container::value_type>>,
1232 Container>
1233 initialize_container(const std::vector<hsize_t> &dimensions);
1234
1241 inline void
1242 set_plist(hid_t &plist, const bool mpi);
1243
1252 inline void
1253 release_plist(hid_t &plist,
1254 H5D_mpio_actual_io_mode_t &io_mode,
1255 std::uint32_t &local_no_collective_cause,
1256 std::uint32_t &global_no_collective_cause,
1257 const bool mpi,
1258 const bool query_io_mode);
1259
1263 inline std::string
1264 no_collective_cause_to_string(const std::uint32_t no_collective_cause);
1265 } // namespace internal
1266
1267
1268
1269 // definitions
1270
1271 namespace internal
1272 {
1273 template <typename number>
1274 std::shared_ptr<hid_t>
1276 {
1277 static_assert(std::is_same_v<number, float> ||
1278 std::is_same_v<number, double> ||
1279 std::is_same_v<number, int> ||
1280 std::is_same_v<number, bool> ||
1281 std::is_same_v<number, unsigned int> ||
1282 std::is_same_v<number, std::complex<float>> ||
1283 std::is_same_v<number, std::complex<double>>,
1284 "The data type you are trying to get the HDF5 tag for "
1285 "is not supported by this function.");
1286
1287 if (std::is_same_v<number, float>)
1288 {
1289 return std::make_shared<hid_t>(H5T_NATIVE_FLOAT);
1290 }
1291 else if (std::is_same_v<number, double>)
1292 {
1293 return std::make_shared<hid_t>(H5T_NATIVE_DOUBLE);
1294 }
1295 else if (std::is_same_v<number, int>)
1296 {
1297 return std::make_shared<hid_t>(H5T_NATIVE_INT);
1298 }
1299 else if (std::is_same_v<number, unsigned int>)
1300 {
1301 return std::make_shared<hid_t>(H5T_NATIVE_UINT);
1302 }
1303 else if (std::is_same_v<number, bool>)
1304 {
1305 return std::make_shared<hid_t>(H5T_NATIVE_HBOOL);
1306 }
1307 else if (std::is_same_v<number, std::complex<float>>)
1308 {
1309 std::shared_ptr<hid_t> t_type =
1310 std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
1311 // Release the HDF5 resource
1312 const herr_t ret = H5Tclose(*pointer);
1313 AssertNothrow(ret >= 0, ExcInternalError());
1314 delete pointer;
1315 });
1316
1317 *t_type = H5Tcreate(H5T_COMPOUND, sizeof(std::complex<float>));
1318 // The C++ standards committee agreed to mandate that the storage
1319 // format used for the std::complex type be binary-compatible with
1320 // the C99 type, i.e. an array T[2] with consecutive real [0] and
1321 // imaginary [1] parts.
1322 herr_t ret = H5Tinsert(*t_type, "r", 0, H5T_NATIVE_FLOAT);
1323 Assert(ret >= 0, ExcInternalError());
1324 ret = H5Tinsert(*t_type, "i", sizeof(float), H5T_NATIVE_FLOAT);
1325 Assert(ret >= 0, ExcInternalError());
1326 (void)ret;
1327 return t_type;
1328 }
1329 else if (std::is_same_v<number, std::complex<double>>)
1330 {
1331 std::shared_ptr<hid_t> t_type =
1332 std::shared_ptr<hid_t>(new hid_t, [](hid_t *pointer) {
1333 // Release the HDF5 resource
1334 const herr_t ret = H5Tclose(*pointer);
1335 AssertNothrow(ret >= 0, ExcInternalError());
1336 delete pointer;
1337 });
1338 *t_type = H5Tcreate(H5T_COMPOUND, sizeof(std::complex<double>));
1339 // The C++ standards committee agreed to mandate that the storage
1340 // format used for the std::complex type be binary-compatible with
1341 // the C99 type, i.e. an array T[2] with consecutive real [0] and
1342 // imaginary [1] parts.
1343 herr_t ret = H5Tinsert(*t_type, "r", 0, H5T_NATIVE_DOUBLE);
1344 Assert(ret >= 0, ExcInternalError());
1345 ret = H5Tinsert(*t_type, "i", sizeof(double), H5T_NATIVE_DOUBLE);
1346 Assert(ret >= 0, ExcInternalError());
1347 (void)ret;
1348 return t_type;
1349 }
1350
1351 // The function should not reach this point
1353 return {};
1354 }
1355
1356
1357
1358 template <typename number>
1359 std::vector<hsize_t>
1360 get_container_dimensions(const std::vector<number> &data)
1361 {
1362 std::vector<hsize_t> dimensions = {data.size()};
1363 return dimensions;
1364 }
1365
1366
1367
1368 template <typename number>
1369 std::vector<hsize_t>
1371 {
1372 std::vector<hsize_t> dimensions = {data.size()};
1373 return dimensions;
1374 }
1375
1376
1377
1378 template <typename number>
1379 std::vector<hsize_t>
1381 {
1382 std::vector<hsize_t> dimensions = {data.m(), data.n()};
1383 return dimensions;
1384 }
1385
1386
1387
1388 template <typename number>
1389 unsigned int
1390 get_container_size(const std::vector<number> &data)
1391 {
1392 return static_cast<unsigned int>(data.size());
1393 }
1394
1395
1396
1397 template <typename number>
1398 unsigned int
1400 {
1401 return static_cast<unsigned int>(data.size());
1402 }
1403
1404
1405
1406 template <typename number>
1407 unsigned int
1409 {
1410 return static_cast<unsigned int>(data.m() * data.n());
1411 }
1412
1413
1414
1415 template <typename Container>
1416 std::enable_if_t<
1417 std::is_same_v<Container, std::vector<typename Container::value_type>>,
1418 Container>
1419 initialize_container(const std::vector<hsize_t> &dimensions)
1420 {
1421 return Container(std::accumulate(
1422 dimensions.begin(), dimensions.end(), 1, std::multiplies<int>()));
1423 }
1424
1425
1426
1427 template <typename Container>
1428 std::enable_if_t<
1429 std::is_same_v<Container, Vector<typename Container::value_type>>,
1430 Container>
1431 initialize_container(const std::vector<hsize_t> &dimensions)
1432 {
1433 return Container(std::accumulate(
1434 dimensions.begin(), dimensions.end(), 1, std::multiplies<int>()));
1435 }
1436
1437
1438
1439 template <typename Container>
1440 std::enable_if_t<
1441 std::is_same_v<Container, FullMatrix<typename Container::value_type>>,
1442 Container>
1443 initialize_container(const std::vector<hsize_t> &dimensions)
1444 {
1445 // If the rank is higher than 2, then remove single-dimensional entries
1446 // from the shape defined by dimensions. This is equivalent to the squeeze
1447 // function of python/numpy. For example the following code would convert
1448 // the vector {1,3,1,2} to {3,2}
1449 std::vector<hsize_t> squeezed_dimensions;
1450
1451 if (dimensions.size() > 2)
1452 {
1453 for (const auto &dimension : dimensions)
1454 {
1455 if (dimension > 1)
1456 squeezed_dimensions.push_back(dimension);
1457 }
1458 }
1459 else
1460 {
1461 squeezed_dimensions = dimensions;
1462 }
1463
1464 AssertDimension(squeezed_dimensions.size(), 2);
1465 return Container(squeezed_dimensions[0], squeezed_dimensions[1]);
1466 }
1467
1468
1469 inline void
1470 set_plist(hid_t &plist, const bool mpi)
1471 {
1472 if (mpi)
1473 {
1474# ifdef DEAL_II_WITH_MPI
1475 plist = H5Pcreate(H5P_DATASET_XFER);
1476 Assert(plist >= 0, ExcInternalError());
1477 const herr_t ret = H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE);
1478 (void)ret;
1479 Assert(ret >= 0, ExcInternalError());
1480# else
1482# endif
1483 }
1484 else
1485 {
1486 plist = H5P_DEFAULT;
1487 }
1488
1489 (void)plist;
1490 (void)mpi;
1491 }
1492
1493
1494 inline void
1495 release_plist(hid_t &plist,
1496 H5D_mpio_actual_io_mode_t &io_mode,
1497 std::uint32_t &local_no_collective_cause,
1498 std::uint32_t &global_no_collective_cause,
1499 const bool mpi,
1500 const bool query_io_mode)
1501 {
1502 if (mpi)
1503 {
1504# ifdef DEAL_II_WITH_MPI
1505 herr_t ret;
1506 (void)ret;
1507 if (query_io_mode)
1508 {
1509 ret = H5Pget_mpio_actual_io_mode(plist, &io_mode);
1510 Assert(ret >= 0, ExcInternalError());
1511 ret =
1512 H5Pget_mpio_no_collective_cause(plist,
1513 &local_no_collective_cause,
1514 &global_no_collective_cause);
1515 Assert(ret >= 0, ExcInternalError());
1516 }
1517 ret = H5Pclose(plist);
1518 Assert(ret >= 0, ExcInternalError());
1519# else
1521# endif
1522 }
1523
1524 (void)plist;
1525 (void)io_mode;
1526 (void)local_no_collective_cause;
1527 (void)global_no_collective_cause;
1528 (void)mpi;
1529 (void)query_io_mode;
1530 }
1531
1532
1533 inline std::string
1534 no_collective_cause_to_string(const std::uint32_t no_collective_cause)
1535 {
1536 std::string message;
1537
1538 auto append_to_message = [&message](const char *p) {
1539 if (message.size() > 0)
1540 message += ", ";
1541 message += p;
1542 };
1543
1544 // The first is not a bitmask comparison, the rest are bitmask
1545 // comparisons.
1546 // https://support.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-GetMpioNoCollectiveCause
1547 // See H5Ppublic.h
1548 // Hex codes are used because the HDF5 Group can deprecate some of the
1549 // enum codes. For example the enum code H5D_MPIO_FILTERS is not defined
1550 // in 1.10.2 because it is possible to use compressed datasets with the
1551 // MPI/IO driver.
1552
1553 // H5D_MPIO_COLLECTIVE
1554 if (no_collective_cause == 0x00)
1555 {
1556 append_to_message("H5D_MPIO_COLLECTIVE");
1557 }
1558 // H5D_MPIO_SET_INDEPENDENT
1559 if ((no_collective_cause & 0x01) == 0x01)
1560 {
1561 append_to_message("H5D_MPIO_SET_INDEPENDENT");
1562 }
1563 // H5D_MPIO_DATATYPE_CONVERSION
1564 if ((no_collective_cause & 0x02) == 0x02)
1565 {
1566 append_to_message("H5D_MPIO_DATATYPE_CONVERSION");
1567 }
1568 // H5D_MPIO_DATA_TRANSFORMS
1569 if ((no_collective_cause & 0x04) == 0x04)
1570 {
1571 append_to_message("H5D_MPIO_DATA_TRANSFORMS");
1572 }
1573 // H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES
1574 if ((no_collective_cause & 0x10) == 0x10)
1575 {
1576 append_to_message("H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES");
1577 }
1578 // H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET
1579 if ((no_collective_cause & 0x20) == 0x20)
1580 {
1581 append_to_message("H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET");
1582 }
1583 // H5D_MPIO_FILTERS
1584 if ((no_collective_cause & 0x40) == 0x40)
1585 {
1586 append_to_message("H5D_MPIO_FILTERS");
1587 }
1588 return message;
1589 }
1590 } // namespace internal
1591
1592
1593 template <typename T>
1594 T
1595 HDF5Object::get_attribute(const std::string &attr_name) const
1596 {
1597 const std::shared_ptr<hid_t> t_type = internal::get_hdf5_datatype<T>();
1598 T value;
1599 hid_t attr;
1600 herr_t ret;
1601
1602 attr = H5Aopen(*hdf5_reference, attr_name.data(), H5P_DEFAULT);
1603 Assert(attr >= 0, ExcMessage("Error at H5Aopen"));
1604 (void)ret;
1605 ret = H5Aread(attr, *t_type, &value);
1606 Assert(ret >= 0, ExcMessage("Error at H5Aread"));
1607 (void)ret;
1608 ret = H5Aclose(attr);
1609 Assert(ret >= 0, ExcMessage("Error at H5Aclose"));
1610
1611 return value;
1612 }
1613
1614
1615
1616 template <>
1617 inline std::string
1618 HDF5Object::get_attribute(const std::string &attr_name) const
1619 {
1620 // Reads a UTF8 variable string
1621 //
1622 // code inspired from
1623 // https://support.hdfgroup.org/ftp/HDF5/examples/misc-examples/vlstratt.c
1624 //
1625 // In the case of a variable length string the user does not have to reserve
1626 // memory for string_out. H5Aread will reserve the memory and the
1627 // user has to free the memory.
1628 //
1629 // Todo:
1630 // - Use H5Dvlen_reclaim instead of free
1631
1632 char *string_out;
1633 hid_t attr;
1634 hid_t type;
1635 herr_t ret;
1636
1637 /* Create a datatype to refer to. */
1638 type = H5Tcopy(H5T_C_S1);
1639 Assert(type >= 0, ExcInternalError());
1640
1641 // Python strings are encoded in UTF8
1642 ret = H5Tset_cset(type, H5T_CSET_UTF8);
1643 Assert(type >= 0, ExcInternalError());
1644
1645 ret = H5Tset_size(type, H5T_VARIABLE);
1646 Assert(ret >= 0, ExcInternalError());
1647
1648 attr = H5Aopen(*hdf5_reference, attr_name.data(), H5P_DEFAULT);
1649 Assert(attr >= 0, ExcInternalError());
1650
1651 ret = H5Aread(attr, type, &string_out);
1652 Assert(ret >= 0, ExcInternalError());
1653
1654 std::string string_value(string_out);
1655 // The memory of the variable length string has to be freed.
1656 // H5Dvlen_reclaim could be also used
1657 std::free(string_out);
1658 ret = H5Tclose(type);
1659 Assert(ret >= 0, ExcInternalError());
1660
1661 ret = H5Aclose(attr);
1662 Assert(ret >= 0, ExcInternalError());
1663
1664 (void)ret;
1665 return string_value;
1666 }
1667
1668
1669
1670 template <typename T>
1671 void
1672 HDF5Object::set_attribute(const std::string &attr_name, const T value)
1673 {
1674 hid_t attr;
1675 hid_t aid;
1676 herr_t ret;
1677
1678 const std::shared_ptr<hid_t> t_type = internal::get_hdf5_datatype<T>();
1679
1680
1681 /*
1682 * Create scalar attribute.
1683 */
1684 aid = H5Screate(H5S_SCALAR);
1685 Assert(aid >= 0, ExcMessage("Error at H5Screate"));
1686 attr = H5Acreate2(*hdf5_reference,
1687 attr_name.data(),
1688 *t_type,
1689 aid,
1690 H5P_DEFAULT,
1691 H5P_DEFAULT);
1692 Assert(attr >= 0, ExcMessage("Error at H5Acreate2"));
1693
1694 /*
1695 * Write scalar attribute.
1696 */
1697 ret = H5Awrite(attr, *t_type, &value);
1698 Assert(ret >= 0, ExcMessage("Error at H5Awrite"));
1699
1700 ret = H5Sclose(aid);
1701 Assert(ret >= 0, ExcMessage("Error at H5Sclose"));
1702 ret = H5Aclose(attr);
1703 Assert(ret >= 0, ExcMessage("Error at H5Aclose"));
1704
1705 (void)ret;
1706 }
1707
1708
1709
1710 template <>
1711 inline void
1712 HDF5Object::set_attribute(const std::string &attr_name,
1713 const std::string value) // NOLINT
1714 {
1715 // Writes a UTF8 variable string
1716 //
1717 // code inspired from
1718 // https://support.hdfgroup.org/ftp/HDF5/examples/misc-examples/vlstratt.c
1719
1720 hid_t attr;
1721 hid_t aid;
1722 hid_t t_type;
1723 herr_t ret;
1724
1725 /* Create a datatype to refer to. */
1726 t_type = H5Tcopy(H5T_C_S1);
1727 Assert(t_type >= 0, ExcInternalError());
1728
1729 // Python strings are encoded in UTF8
1730 ret = H5Tset_cset(t_type, H5T_CSET_UTF8);
1731 Assert(t_type >= 0, ExcInternalError());
1732
1733 ret = H5Tset_size(t_type, H5T_VARIABLE);
1734 Assert(ret >= 0, ExcInternalError());
1735
1736 /*
1737 * Create scalar attribute.
1738 */
1739 aid = H5Screate(H5S_SCALAR);
1740 Assert(aid >= 0, ExcMessage("Error at H5Screate"));
1741 attr = H5Acreate2(
1742 *hdf5_reference, attr_name.data(), t_type, aid, H5P_DEFAULT, H5P_DEFAULT);
1743 Assert(attr >= 0, ExcMessage("Error at H5Acreate2"));
1744
1745 /*
1746 * Write scalar attribute.
1747 * In most of the cases H5Awrite and H5Dwrite take a pointer to the data.
1748 * But in the particular case of a variable length string, H5Awrite takes
1749 * the address of the pointer of the string.
1750 */
1751 const char *c_string_value = value.c_str();
1752 ret = H5Awrite(attr, t_type, &c_string_value);
1753 Assert(ret >= 0, ExcInternalError());
1754
1755 ret = H5Sclose(aid);
1756 Assert(ret >= 0, ExcMessage("Error at H5Sclose"));
1757 ret = H5Aclose(attr);
1758 Assert(ret >= 0, ExcMessage("Error at H5Aclose"));
1759
1760 (void)ret;
1761 }
1762
1763
1764
1765 template <typename Container>
1766 Container
1768 {
1769 const std::shared_ptr<hid_t> t_type =
1770 internal::get_hdf5_datatype<typename Container::value_type>();
1771 hid_t plist;
1772 herr_t ret;
1773
1774 Container data = internal::initialize_container<Container>(dimensions);
1775
1776 internal::set_plist(plist, mpi);
1777
1778 ret = H5Dread(*hdf5_reference,
1779 *t_type,
1780 H5S_ALL,
1781 H5S_ALL,
1782 plist,
1784 Assert(ret >= 0, ExcInternalError());
1785
1786
1788 io_mode,
1791 mpi,
1793
1794 (void)ret;
1795 return data;
1796 }
1797
1798
1799
1800 template <typename Container>
1801 Container
1802 DataSet::read_selection(const std::vector<hsize_t> &coordinates)
1803 {
1804 Assert(coordinates.size() % rank == 0,
1805 ExcMessage(
1806 "The dimension of coordinates has to be divisible by the rank"));
1807 const std::shared_ptr<hid_t> t_type =
1808 internal::get_hdf5_datatype<typename Container::value_type>();
1809 hid_t plist;
1810 hid_t memory_dataspace;
1811 herr_t ret;
1812
1813 std::vector<hsize_t> data_dimensions{
1814 static_cast<hsize_t>(coordinates.size() / rank)};
1815
1816 Container data = internal::initialize_container<Container>(data_dimensions);
1817
1818 memory_dataspace = H5Screate_simple(1, data_dimensions.data(), nullptr);
1819 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
1820 ret = H5Sselect_elements(*dataspace,
1821 H5S_SELECT_SET,
1822 data.size(),
1823 coordinates.data());
1824 Assert(ret >= 0, ExcMessage("Error at H5Sselect_elements"));
1825
1826 internal::set_plist(plist, mpi);
1827
1828 ret = H5Dread(*hdf5_reference,
1829 *t_type,
1830 memory_dataspace,
1831 *dataspace,
1832 plist,
1834 Assert(ret >= 0, ExcMessage("Error at H5Dread"));
1835
1837 io_mode,
1840 mpi,
1842
1843 ret = H5Sclose(memory_dataspace);
1844 Assert(ret >= 0, ExcMessage("Error at H5SClose"));
1845
1846 (void)ret;
1847 return data;
1848 }
1849
1850
1851
1852 template <typename Container>
1853 Container
1854 DataSet::read_hyperslab(const std::vector<hsize_t> &offset,
1855 const std::vector<hsize_t> &count)
1856 {
1857 const std::shared_ptr<hid_t> t_type =
1858 internal::get_hdf5_datatype<typename Container::value_type>();
1859 hid_t plist;
1860 hid_t memory_dataspace;
1861 herr_t ret;
1862
1863 // In this particular overload of read_hyperslab the data_dimensions are
1864 // the same as count
1865 std::vector<hsize_t> data_dimensions = count;
1866
1867 Container data = internal::initialize_container<Container>(data_dimensions);
1868
1869 memory_dataspace =
1870 H5Screate_simple(data_dimensions.size(), data_dimensions.data(), nullptr);
1871 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
1872 ret = H5Sselect_hyperslab(*dataspace,
1873 H5S_SELECT_SET,
1874 offset.data(),
1875 nullptr,
1876 count.data(),
1877 nullptr);
1878 Assert(ret >= 0, ExcMessage("Error at H5Sselect_hyperslab"));
1879
1880 internal::set_plist(plist, mpi);
1881
1882 ret = H5Dread(*hdf5_reference,
1883 *t_type,
1884 memory_dataspace,
1885 *dataspace,
1886 plist,
1888 Assert(ret >= 0, ExcMessage("Error at H5Dread"));
1889
1891 io_mode,
1894 mpi,
1896
1897 ret = H5Sclose(memory_dataspace);
1898 Assert(ret >= 0, ExcMessage("Error at H5SClose"));
1899
1900 (void)ret;
1901 return data;
1902 }
1903
1904
1905
1906 template <typename Container>
1907 Container
1908 DataSet::read_hyperslab(const std::vector<hsize_t> &data_dimensions,
1909 const std::vector<hsize_t> &offset,
1910 const std::vector<hsize_t> &stride,
1911 const std::vector<hsize_t> &count,
1912 const std::vector<hsize_t> &block)
1913 {
1914 const std::shared_ptr<hid_t> t_type =
1915 internal::get_hdf5_datatype<typename Container::value_type>();
1916 hid_t plist;
1917 hid_t memory_dataspace;
1918 herr_t ret;
1919
1920 Container data = internal::initialize_container<Container>(data_dimensions);
1921
1922 memory_dataspace =
1923 H5Screate_simple(data_dimensions.size(), data_dimensions.data(), nullptr);
1924 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
1925 ret = H5Sselect_hyperslab(*dataspace,
1926 H5S_SELECT_SET,
1927 offset.data(),
1928 stride.data(),
1929 count.data(),
1930 block.data());
1931 Assert(ret >= 0, ExcMessage("Error at H5Sselect_hyperslab"));
1932
1933 internal::set_plist(plist, mpi);
1934
1935 ret = H5Dread(*hdf5_reference,
1936 *t_type,
1937 memory_dataspace,
1938 *dataspace,
1939 plist,
1941 Assert(ret >= 0, ExcMessage("Error at H5Dread"));
1942
1944 io_mode,
1947 mpi,
1949
1950 ret = H5Sclose(memory_dataspace);
1951 Assert(ret >= 0, ExcMessage("Error at H5SClose"));
1952
1953 (void)ret;
1954 return data;
1955 }
1956
1957
1958
1959 template <typename number>
1960 void
1962 {
1963 const std::shared_ptr<hid_t> t_type = internal::get_hdf5_datatype<number>();
1964 const std::vector<hsize_t> data_dimensions = {0};
1965
1966 hid_t memory_dataspace;
1967 hid_t plist;
1968 herr_t ret;
1969
1970 memory_dataspace = H5Screate_simple(1, data_dimensions.data(), nullptr);
1971 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
1972 ret = H5Sselect_none(*dataspace);
1973 Assert(ret >= 0, ExcMessage("H5Sselect_none"));
1974
1975 internal::set_plist(plist, mpi);
1976
1977 // The pointer of data can safely be nullptr, see the discussion at the HDF5
1978 // forum:
1979 // https://forum.hdfgroup.org/t/parallel-i-o-does-not-support-filters-yet/884/17
1980 ret = H5Dread(
1981 *hdf5_reference, *t_type, memory_dataspace, *dataspace, plist, nullptr);
1982 Assert(ret >= 0, ExcMessage("Error at H5Dread"));
1983
1985 io_mode,
1988 mpi,
1990
1991 ret = H5Sclose(memory_dataspace);
1992 Assert(ret >= 0, ExcMessage("Error at H5SClose"));
1993
1994 (void)ret;
1995 }
1996
1997
1998
1999 template <typename Container>
2000 void
2001 DataSet::write(const Container &data)
2002 {
2004 const std::shared_ptr<hid_t> t_type =
2005 internal::get_hdf5_datatype<typename Container::value_type>();
2006 hid_t plist;
2007 herr_t ret;
2008
2009 internal::set_plist(plist, mpi);
2010
2011 ret = H5Dwrite(*hdf5_reference,
2012 *t_type,
2013 H5S_ALL,
2014 H5S_ALL,
2015 plist,
2017 Assert(ret >= 0, ExcMessage("Error at H5Dwrite"));
2018
2020 io_mode,
2023 mpi,
2025
2026 (void)ret;
2027 }
2028
2029
2030
2031 template <typename Container>
2032 void
2034 const std::vector<hsize_t> &coordinates)
2035 {
2036 AssertDimension(coordinates.size(), data.size() * rank);
2037 const std::shared_ptr<hid_t> t_type =
2038 internal::get_hdf5_datatype<typename Container::value_type>();
2039 const std::vector<hsize_t> data_dimensions =
2041
2042 hid_t memory_dataspace;
2043 hid_t plist;
2044 herr_t ret;
2045
2046
2047 memory_dataspace = H5Screate_simple(1, data_dimensions.data(), nullptr);
2048 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
2049 ret = H5Sselect_elements(*dataspace,
2050 H5S_SELECT_SET,
2051 data.size(),
2052 coordinates.data());
2053 Assert(ret >= 0, ExcMessage("Error at H5Sselect_elements"));
2054
2055 internal::set_plist(plist, mpi);
2056
2057 ret = H5Dwrite(*hdf5_reference,
2058 *t_type,
2059 memory_dataspace,
2060 *dataspace,
2061 plist,
2063 Assert(ret >= 0, ExcMessage("Error at H5Dwrite"));
2064
2066 io_mode,
2069 mpi,
2071
2072 ret = H5Sclose(memory_dataspace);
2073 Assert(ret >= 0, ExcMessage("Error at H5SClose"));
2074
2075 (void)ret;
2076 }
2077
2078
2079
2080 template <typename Container>
2081 void
2083 const std::vector<hsize_t> &offset,
2084 const std::vector<hsize_t> &count)
2085 {
2086 AssertDimension(std::accumulate(count.begin(),
2087 count.end(),
2088 1,
2089 std::multiplies<unsigned int>()),
2091 const std::shared_ptr<hid_t> t_type =
2092 internal::get_hdf5_datatype<typename Container::value_type>();
2093 // In this particular overload of write_hyperslab the data_dimensions are
2094 // the same as count
2095 const std::vector<hsize_t> &data_dimensions = count;
2096
2097 hid_t memory_dataspace;
2098 hid_t plist;
2099 herr_t ret;
2100
2101 memory_dataspace =
2102 H5Screate_simple(data_dimensions.size(), data_dimensions.data(), nullptr);
2103 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
2104 ret = H5Sselect_hyperslab(*dataspace,
2105 H5S_SELECT_SET,
2106 offset.data(),
2107 nullptr,
2108 count.data(),
2109 nullptr);
2110 Assert(ret >= 0, ExcMessage("Error at H5Sselect_hyperslab"));
2111
2112 internal::set_plist(plist, mpi);
2113
2114 ret = H5Dwrite(*hdf5_reference,
2115 *t_type,
2116 memory_dataspace,
2117 *dataspace,
2118 plist,
2120 Assert(ret >= 0, ExcMessage("Error at H5Dwrite"));
2121
2123 io_mode,
2126 mpi,
2128
2129 ret = H5Sclose(memory_dataspace);
2130 Assert(ret >= 0, ExcMessage("Error at H5Sclose"));
2131
2132 (void)ret;
2133 }
2134
2135
2136
2137 template <typename Container>
2138 void
2140 const std::vector<hsize_t> &data_dimensions,
2141 const std::vector<hsize_t> &offset,
2142 const std::vector<hsize_t> &stride,
2143 const std::vector<hsize_t> &count,
2144 const std::vector<hsize_t> &block)
2145 {
2146 const std::shared_ptr<hid_t> t_type =
2147 internal::get_hdf5_datatype<typename Container::value_type>();
2148
2149 hid_t memory_dataspace;
2150 hid_t plist;
2151 herr_t ret;
2152
2153 memory_dataspace =
2154 H5Screate_simple(data_dimensions.size(), data_dimensions.data(), nullptr);
2155 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
2156 ret = H5Sselect_hyperslab(*dataspace,
2157 H5S_SELECT_SET,
2158 offset.data(),
2159 stride.data(),
2160 count.data(),
2161 block.data());
2162 Assert(ret >= 0, ExcMessage("Error at H5Sselect_hyperslab"));
2163
2164 internal::set_plist(plist, mpi);
2165
2166 ret = H5Dwrite(*hdf5_reference,
2167 *t_type,
2168 memory_dataspace,
2169 *dataspace,
2170 plist,
2172 Assert(ret >= 0, ExcMessage("Error at H5Dwrite"));
2173
2175 io_mode,
2178 mpi,
2180
2181 ret = H5Sclose(memory_dataspace);
2182 Assert(ret >= 0, ExcMessage("Error at H5Sclose"));
2183
2184 (void)ret;
2185 }
2186
2187
2188
2189 template <typename number>
2190 void
2192 {
2193 std::shared_ptr<hid_t> t_type = internal::get_hdf5_datatype<number>();
2194 std::vector<hsize_t> data_dimensions = {0};
2195
2196 hid_t memory_dataspace;
2197 hid_t plist;
2198 herr_t ret;
2199
2200 memory_dataspace = H5Screate_simple(1, data_dimensions.data(), nullptr);
2201 Assert(memory_dataspace >= 0, ExcMessage("Error at H5Screate_simple"));
2202 ret = H5Sselect_none(*dataspace);
2203 Assert(ret >= 0, ExcMessage("Error at H5PSselect_none"));
2204
2205 internal::set_plist(plist, mpi);
2206
2207 // The pointer of data can safely be nullptr, see the discussion at the HDF5
2208 // forum:
2209 // https://forum.hdfgroup.org/t/parallel-i-o-does-not-support-filters-yet/884/17
2210 ret = H5Dwrite(
2211 *hdf5_reference, *t_type, memory_dataspace, *dataspace, plist, nullptr);
2212 Assert(ret >= 0, ExcMessage("Error at H5Dwrite"));
2213
2215 io_mode,
2218 mpi,
2220
2221 ret = H5Sclose(memory_dataspace);
2222 Assert(ret >= 0, ExcMessage("Error at H5Sclose"));
2223
2224 (void)ret;
2225 }
2226
2227
2228
2229 template <typename number>
2230 DataSet
2231 Group::create_dataset(const std::string &name,
2232 const std::vector<hsize_t> &dimensions) const
2233 {
2234 std::shared_ptr<hid_t> t_type = internal::get_hdf5_datatype<number>();
2235 return {name, *hdf5_reference, dimensions, t_type, mpi};
2236 }
2237
2238
2239
2240 template <typename Container>
2241 void
2242 Group::write_dataset(const std::string &name, const Container &data) const
2243 {
2244 std::vector<hsize_t> dimensions = internal::get_container_dimensions(data);
2245 auto dataset =
2246 create_dataset<typename Container::value_type>(name, dimensions);
2247 dataset.write(data);
2248 }
2249} // namespace HDF5
2250
2251#endif // DEAL_II_WITH_HDF5
2252
2254
2255#endif // dealii_hdf5_h
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
unsigned int rank
Definition hdf5.h:924
unsigned int get_rank() const
Definition hdf5.cc:308
void write(const Container &data)
Definition hdf5.h:2001
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
void write_hyperslab(const Container &data, const std::vector< hsize_t > &offset, const std::vector< hsize_t > &count)
Definition hdf5.h:2082
unsigned int get_size() const
Definition hdf5.cc:300
void write_selection(const Container &data, const std::vector< hsize_t > &coordinates)
Definition hdf5.h:2033
void read_none()
Definition hdf5.h:1961
std::shared_ptr< hid_t > dataspace
Definition hdf5.h:935
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
void write_none()
Definition hdf5.h:2191
Container read()
Definition hdf5.h:1767
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
Container read_selection(const std::vector< hsize_t > &coordinates)
Definition hdf5.h:1802
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
Container read_hyperslab(const std::vector< hsize_t > &offset, const std::vector< hsize_t > &count)
Definition hdf5.h:1854
unsigned int size
Definition hdf5.h:940
H5D_mpio_actual_io_mode_t io_mode
Definition hdf5.h:956
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
DataSet create_dataset(const std::string &name, const std::vector< hsize_t > &dimensions) const
Definition hdf5.h:2231
Group create_group(const std::string &name) const
Definition hdf5.cc:366
GroupAccessMode
Definition hdf5.h:983
void write_dataset(const std::string &name, const Container &data) const
Definition hdf5.h:2242
std::shared_ptr< hid_t > hdf5_reference
Definition hdf5.h:414
std::string get_name() const
Definition hdf5.cc:72
T get_attribute(const std::string &attr_name) const
Definition hdf5.h:1595
const std::string name
Definition hdf5.h:405
void set_attribute(const std::string &attr_name, const T value)
Definition hdf5.h:1672
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()
static ::ExceptionBase & ExcNotImplemented()
#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::vector< index_type > data
Definition mpi.cc:734
void release_plist(hid_t &plist, H5D_mpio_actual_io_mode_t &io_mode, std::uint32_t &local_no_collective_cause, std::uint32_t &global_no_collective_cause, const bool mpi, const bool query_io_mode)
Definition hdf5.h:1495
std::string no_collective_cause_to_string(const std::uint32_t no_collective_cause)
Definition hdf5.h:1534
std::enable_if_t< std::is_same_v< Container, std::vector< typename Container::value_type > >, Container > initialize_container(const std::vector< hsize_t > &dimensions)
Definition hdf5.h:1419
unsigned int get_container_size(const std::vector< number > &data)
Definition hdf5.h:1390
void set_plist(hid_t &plist, const bool mpi)
Definition hdf5.h:1470
std::shared_ptr< hid_t > get_hdf5_datatype()
Definition hdf5.h:1275
std::vector< hsize_t > get_container_dimensions(const std::vector< number > &data)
Definition hdf5.h:1360
Definition hdf5.h:345