13#include <dolfinx/common/log.h> 
   21namespace dolfinx::io::hdf5
 
   27  if constexpr (std::is_same_v<T, float>)
 
   28    return H5T_NATIVE_FLOAT;
 
   29  else if constexpr (std::is_same_v<T, double>)
 
   30    return H5T_NATIVE_DOUBLE;
 
   31  else if constexpr (std::is_same_v<T, std::int32_t>)
 
   32    return H5T_NATIVE_INT32;
 
   33  else if constexpr (std::is_same_v<T, std::uint32_t>)
 
   34    return H5T_NATIVE_UINT32;
 
   35  else if constexpr (std::is_same_v<T, std::int64_t>)
 
   36    return H5T_NATIVE_INT64;
 
   37  else if constexpr (std::is_same_v<T, std::uint64_t>)
 
   38    return H5T_NATIVE_UINT64;
 
   39  else if constexpr (std::is_same_v<T, std::uint8_t>)
 
   40    return H5T_NATIVE_UINT8;
 
   41  else if constexpr (std::is_same_v<T, std::size_t>)
 
   43    throw std::runtime_error(
 
   44        "Cannot determine size of std::size_t. std::size_t is not the same " 
   45        "size as long or int.");
 
   49    throw std::runtime_error(
"Cannot get HDF5 primitive data type. No " 
   50                             "specialised function for this data type.");
 
   59hid_t open_file(MPI_Comm comm, 
const std::filesystem::path& filename,
 
   60                const std::string& mode, 
bool use_mpi_io);
 
   64void close_file(hid_t handle);
 
   68void flush_file(hid_t handle);
 
   73std::filesystem::path get_filename(hid_t handle);
 
   79bool has_dataset(hid_t handle, 
const std::string& dataset_path);
 
   86void set_attribute(hid_t handle, 
const std::string& attr_name,
 
   87                   const std::string& value);
 
   88void set_attribute(hid_t handle, 
const std::string& attr_name,
 
   89                   const std::vector<std::int32_t>& value);
 
   90void set_attribute(hid_t handle, 
const std::string& attr_name,
 
   97hid_t open_dataset(hid_t handle, 
const std::string& path);
 
  103std::vector<std::int64_t> get_dataset_shape(hid_t handle,
 
  104                                            const std::string& dataset_path);
 
  115void set_mpi_atomicity(hid_t handle, 
bool atomic);
 
  121bool get_mpi_atomicity(hid_t handle);
 
  126void add_group(hid_t handle, 
const std::string& dataset_path);
 
  143void write_dataset(hid_t file_handle, 
const std::string& dataset_path,
 
  144                   const T* data, std::array<std::int64_t, 2> range,
 
  145                   const std::vector<int64_t>& global_size, 
bool use_mpi_io,
 
  149  const std::string group_name(dataset_path, 0, dataset_path.rfind(
'/'));
 
  150  add_group(file_handle, group_name);
 
  153  const int rank = global_size.size();
 
  157    throw std::runtime_error(
"Cannot write dataset to HDF5 file" 
  158                             "Only rank 1 and rank 2 dataset are supported");
 
  162  const hid_t h5type = hdf5::hdf5_type<T>();
 
  165  std::vector<hsize_t> count(global_size.begin(), global_size.end());
 
  166  count[0] = range[1] - range[0];
 
  169  std::vector<hsize_t> offset(rank, 0);
 
  170  offset[0] = range[0];
 
  173  const std::vector<hsize_t> dimsf(global_size.begin(), global_size.end());
 
  176  if (has_dataset(file_handle, dataset_path))
 
  179    hid_t dset_id = hdf5::open_dataset(file_handle, dataset_path.c_str());
 
  180    H5Dset_extent(dset_id, dimsf.data());
 
  185    std::vector<hsize_t> maxdims(dimsf.begin(), dimsf.end());
 
  188    hid_t chunking_properties;
 
  192      std::fill(maxdims.begin(), maxdims.end(), H5S_UNLIMITED);
 
  195      hsize_t chunk_size = dimsf[0] / 2;
 
  196      if (chunk_size > 1048576)
 
  197        chunk_size = 1048576;
 
  198      if (chunk_size < 1024)
 
  201      hsize_t chunk_dims[2] = {chunk_size, dimsf[1]};
 
  202      chunking_properties = H5Pcreate(H5P_DATASET_CREATE);
 
  203      H5Pset_chunk(chunking_properties, rank, chunk_dims);
 
  206      chunking_properties = H5P_DEFAULT;
 
  209    const hid_t filespace0
 
  210        = H5Screate_simple(rank, dimsf.data(), maxdims.data());
 
  211    if (filespace0 == H5I_INVALID_HID)
 
  212      throw std::runtime_error(
"Failed to create HDF5 data space");
 
  216        = H5Dcreate2(file_handle, dataset_path.c_str(), h5type, filespace0,
 
  217                     H5P_DEFAULT, chunking_properties, H5P_DEFAULT);
 
  218    if (dset_id == H5I_INVALID_HID)
 
  219      throw std::runtime_error(
"Failed to create HDF5 global dataset.");
 
  222    if (H5Sclose(filespace0) < 0)
 
  223      throw std::runtime_error(
"Failed to close HDF5 global data space.");
 
  228      if (H5Pclose(chunking_properties) < 0)
 
  229        throw std::runtime_error(
"Failed to close HDF5 chunking properties.");
 
  233    if (H5Dclose(dset_id) < 0)
 
  234      throw std::runtime_error(
"Failed to close HDF5 dataset.");
 
  238  hid_t dset_id = hdf5::open_dataset(file_handle, dataset_path.c_str());
 
  239  assert(dset_id != H5I_INVALID_HID);
 
  241  hid_t dataspace = H5Dget_space(dset_id);
 
  242  if (dataspace == H5I_INVALID_HID)
 
  243    throw std::runtime_error(
"Failed to open HDF5 data space.");
 
  245  herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset.data(),
 
  246                                      nullptr, count.data(), 
nullptr);
 
  248    throw std::runtime_error(
"Failed to create HDF5 dataspace.");
 
  251  const hid_t plist_id = H5Pcreate(H5P_DATASET_XFER);
 
  254    if (herr_t status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
 
  257      throw std::runtime_error(
 
  258          "Failed to set HDF5 data transfer property list.");
 
  263  const hid_t memspace = H5Screate_simple(rank, count.data(), 
nullptr);
 
  264  if (memspace == H5I_INVALID_HID)
 
  265    throw std::runtime_error(
"Failed to create HDF5 local data space.");
 
  268  if (H5Dwrite(dset_id, h5type, memspace, dataspace, plist_id, data) < 0)
 
  270    throw std::runtime_error(
"Failed to write HDF5 local dataset.");
 
  278  if (H5Pclose(plist_id) < 0)
 
  279    throw std::runtime_error(
"Failed to release HDF5 file-access template.");
 
  292std::vector<T> read_dataset(hid_t dset_id, std::array<std::int64_t, 2> range,
 
  295  auto timer_start = std::chrono::system_clock::now();
 
  301    hid_t dtype = H5Dget_type(dset_id);
 
  302    if (dtype == H5I_INVALID_HID)
 
  303      throw std::runtime_error(
"Failed to get HDF5 data type.");
 
  304    if (htri_t eq = H5Tequal(dtype, hdf5::hdf5_type<T>()); eq < 0)
 
  305      throw std::runtime_error(
"HDF5 datatype equality test failed.");
 
  309      throw std::runtime_error(
"Wrong type for reading from HDF5. Use \"h5ls " 
  310                               "-v\" to inspect the types in the HDF5 file.");
 
  315  hid_t dataspace = H5Dget_space(dset_id);
 
  316  if (dataspace == H5I_INVALID_HID)
 
  317    throw std::runtime_error(
"Failed to open HDF5 data space.");
 
  320  int rank = H5Sget_simple_extent_ndims(dataspace);
 
  322    throw std::runtime_error(
"Failed to get rank of data space.");
 
  324    spdlog::warn(
"io::hdf5::read_dataset untested for rank > 2.");
 
  327  std::vector<hsize_t> shape(rank);
 
  330  if (
int ndims = H5Sget_simple_extent_dims(dataspace, shape.data(), 
nullptr);
 
  333    throw std::runtime_error(
"Failed to get dimensionality of dataspace.");
 
  337  std::vector<hsize_t> offset(rank, 0);
 
  338  std::vector<hsize_t> count = shape;
 
  339  if (range[0] != -1 and range[1] != -1)
 
  341    offset[0] = range[0];
 
  342    count[0] = range[1] - range[0];
 
  350      = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset.data(), 
nullptr,
 
  351                            count.data(), 
nullptr);
 
  354    throw std::runtime_error(
"Failed to select HDF5 hyperslab.");
 
  358  hid_t memspace = H5Screate_simple(rank, count.data(), 
nullptr);
 
  359  if (memspace == H5I_INVALID_HID)
 
  360    throw std::runtime_error(
"Failed to create HDF5 dataspace.");
 
  364      std::reduce(count.begin(), count.end(), 1, std::multiplies{}));
 
  367  hid_t h5type = hdf5::hdf5_type<T>();
 
  369      = H5Dread(dset_id, h5type, memspace, dataspace, H5P_DEFAULT, data.data());
 
  372    throw std::runtime_error(
"Failed to read HDF5 data.");
 
  376  if (herr_t status = H5Sclose(dataspace); status < 0)
 
  377    throw std::runtime_error(
"Failed to close HDF5 dataspace.");
 
  380  if (herr_t status = H5Sclose(memspace); status < 0)
 
  381    throw std::runtime_error(
"Failed to close HDF5 memory space.");
 
  383  auto timer_end = std::chrono::system_clock::now();
 
  384  std::chrono::duration<double> dt = (timer_end - timer_start);
 
  385  double data_rate = data.size() * 
sizeof(T) / (1e6 * dt.count());
 
  386  spdlog::info(
"HDF5 Read data rate: {} MB/s", data_rate);
 
int rank(MPI_Comm comm)
Return process rank for the communicator.
Definition MPI.cpp:64