13#include <dolfinx/common/log.h> 
   21namespace dolfinx::io::hdf5
 
   28  if constexpr (std::is_same_v<T, float>)
 
   29    return H5T_NATIVE_FLOAT;
 
   30  else if constexpr (std::is_same_v<T, double>)
 
   31    return H5T_NATIVE_DOUBLE;
 
   32  else if constexpr (std::is_same_v<T, std::int32_t>)
 
   33    return H5T_NATIVE_INT32;
 
   34  else if constexpr (std::is_same_v<T, std::uint32_t>)
 
   35    return H5T_NATIVE_UINT32;
 
   36  else if constexpr (std::is_same_v<T, std::int64_t>)
 
   37    return H5T_NATIVE_INT64;
 
   38  else if constexpr (std::is_same_v<T, std::uint64_t>)
 
   39    return H5T_NATIVE_UINT64;
 
   40  else if constexpr (std::is_same_v<T, std::size_t>)
 
   42    throw std::runtime_error(
 
   43        "Cannot determine size of std::size_t. std::size_t is not the same " 
   44        "size as long or int.");
 
   48    throw std::runtime_error(
"Cannot get HDF5 primitive data type. No " 
   49                             "specialised function for this data type.");
 
   58hid_t open_file(MPI_Comm comm, 
const std::filesystem::path& filename,
 
   59                const std::string& mode, 
bool use_mpi_io);
 
   63void close_file(hid_t handle);
 
   67void flush_file(hid_t handle);
 
   72std::filesystem::path get_filename(hid_t handle);
 
   78bool has_dataset(hid_t handle, 
const std::string& dataset_path);
 
   84hid_t open_dataset(hid_t handle, 
const std::string& path);
 
   90std::vector<std::int64_t> get_dataset_shape(hid_t handle,
 
   91                                            const std::string& dataset_path);
 
   99void set_mpi_atomicity(hid_t handle, 
bool atomic);
 
  105bool get_mpi_atomicity(hid_t handle);
 
  110void add_group(hid_t handle, 
const std::string& dataset_path);
 
  123void write_dataset(hid_t file_handle, 
const std::string& dataset_path,
 
  124                   const T* data, std::array<std::int64_t, 2> range,
 
  125                   const std::vector<int64_t>& global_size, 
bool use_mpi_io,
 
  129  const int rank = global_size.size();
 
  133    throw std::runtime_error(
"Cannot write dataset to HDF5 file" 
  134                             "Only rank 1 and rank 2 dataset are supported");
 
  138  const hid_t h5type = hdf5::hdf5_type<T>();
 
  141  std::vector<hsize_t> count(global_size.begin(), global_size.end());
 
  142  count[0] = range[1] - range[0];
 
  145  std::vector<hsize_t> offset(rank, 0);
 
  146  offset[0] = range[0];
 
  149  const std::vector<hsize_t> dimsf(global_size.begin(), global_size.end());
 
  152  const hid_t filespace0 = H5Screate_simple(rank, dimsf.data(), 
nullptr);
 
  153  if (filespace0 == H5I_INVALID_HID)
 
  154    throw std::runtime_error(
"Failed to create HDF5 data space");
 
  157  hid_t chunking_properties;
 
  161    hsize_t chunk_size = dimsf[0] / 2;
 
  162    if (chunk_size > 1048576)
 
  163      chunk_size = 1048576;
 
  164    if (chunk_size < 1024)
 
  167    hsize_t chunk_dims[2] = {chunk_size, dimsf[1]};
 
  168    chunking_properties = H5Pcreate(H5P_DATASET_CREATE);
 
  169    H5Pset_chunk(chunking_properties, rank, chunk_dims);
 
  172    chunking_properties = H5P_DEFAULT;
 
  175  const std::string group_name(dataset_path, 0, dataset_path.rfind(
'/'));
 
  176  add_group(file_handle, group_name);
 
  180      = H5Dcreate2(file_handle, dataset_path.c_str(), h5type, filespace0,
 
  181                   H5P_DEFAULT, chunking_properties, H5P_DEFAULT);
 
  182  if (dset_id == H5I_INVALID_HID)
 
  183    throw std::runtime_error(
"Failed to create HDF5 global dataset.");
 
  186  if (herr_t status = H5Sclose(filespace0); status < 0)
 
  187    throw std::runtime_error(
"Failed to close HDF5 global data space.");
 
  190  const hid_t memspace = H5Screate_simple(rank, count.data(), 
nullptr);
 
  191  if (memspace == H5I_INVALID_HID)
 
  192    throw std::runtime_error(
"Failed to create HDF5 local data space.");
 
  195  const hid_t filespace1 = H5Dget_space(dset_id);
 
  196  herr_t status = H5Sselect_hyperslab(filespace1, H5S_SELECT_SET, offset.data(),
 
  197                                      nullptr, count.data(), 
nullptr);
 
  199    throw std::runtime_error(
"Failed to create HDF5 dataspace.");
 
  202  const hid_t plist_id = H5Pcreate(H5P_DATASET_XFER);
 
  205    if (herr_t status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
 
  208      throw std::runtime_error(
 
  209          "Failed to set HDF5 data transfer property list.");
 
  214  if (H5Dwrite(dset_id, h5type, memspace, filespace1, plist_id, data) < 0)
 
  216    throw std::runtime_error(
 
  217        "Failed to write HDF5 local dataset into hyperslab.");
 
  223    if (H5Pclose(chunking_properties) < 0)
 
  224      throw std::runtime_error(
"Failed to close HDF5 chunking properties.");
 
  228  if (H5Dclose(dset_id) < 0)
 
  229    throw std::runtime_error(
"Failed to close HDF5 dataset.");
 
  232  if (H5Sclose(filespace1) < 0)
 
  233    throw std::runtime_error(
"Failed to close HDF5 hyperslab.");
 
  236  if (H5Sclose(memspace) < 0)
 
  237    throw std::runtime_error(
"Failed to close local HDF5 dataset.");
 
  240  if (H5Pclose(plist_id) < 0)
 
  241    throw std::runtime_error(
"Failed to release HDF5 file-access template.");
 
  254std::vector<T> read_dataset(hid_t dset_id, std::array<std::int64_t, 2> range,
 
  257  auto timer_start = std::chrono::system_clock::now();
 
  263    hid_t dtype = H5Dget_type(dset_id);
 
  264    if (dtype == H5I_INVALID_HID)
 
  265      throw std::runtime_error(
"Failed to get HDF5 data type.");
 
  266    if (htri_t eq = H5Tequal(dtype, hdf5::hdf5_type<T>()); eq < 0)
 
  267      throw std::runtime_error(
"HDF5 datatype equality test failed.");
 
  271      throw std::runtime_error(
"Wrong type for reading from HDF5. Use \"h5ls " 
  272                               "-v\" to inspect the types in the HDF5 file.");
 
  277  hid_t dataspace = H5Dget_space(dset_id);
 
  278  if (dataspace == H5I_INVALID_HID)
 
  279    throw std::runtime_error(
"Failed to open HDF5 data space.");
 
  282  int rank = H5Sget_simple_extent_ndims(dataspace);
 
  284    throw std::runtime_error(
"Failed to get rank of data space.");
 
  286    LOG(WARNING) << 
"io::hdf5::read_dataset untested for rank > 2.";
 
  289  std::vector<hsize_t> shape(rank);
 
  292  if (
int ndims = H5Sget_simple_extent_dims(dataspace, shape.data(), 
nullptr);
 
  295    throw std::runtime_error(
"Failed to get dimensionality of dataspace.");
 
  299  std::vector<hsize_t> offset(rank, 0);
 
  300  std::vector<hsize_t> count = shape;
 
  301  if (range[0] != -1 and range[1] != -1)
 
  303    offset[0] = range[0];
 
  304    count[0] = range[1] - range[0];
 
  312      = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset.data(), 
nullptr,
 
  313                            count.data(), 
nullptr);
 
  316    throw std::runtime_error(
"Failed to select HDF5 hyperslab.");
 
  320  hid_t memspace = H5Screate_simple(rank, count.data(), 
nullptr);
 
  321  if (memspace == H5I_INVALID_HID)
 
  322    throw std::runtime_error(
"Failed to create HDF5 dataspace.");
 
  326      std::reduce(count.begin(), count.end(), 1, std::multiplies{}));
 
  329  hid_t h5type = hdf5::hdf5_type<T>();
 
  331      = H5Dread(dset_id, h5type, memspace, dataspace, H5P_DEFAULT, data.data());
 
  334    throw std::runtime_error(
"Failed to read HDF5 data.");
 
  338  if (herr_t status = H5Sclose(dataspace); status < 0)
 
  339    throw std::runtime_error(
"Failed to close HDF5 dataspace.");
 
  342  if (herr_t status = H5Sclose(memspace); status < 0)
 
  343    throw std::runtime_error(
"Failed to close HDF5 memory space.");
 
  345  auto timer_end = std::chrono::system_clock::now();
 
  346  std::chrono::duration<double> dt = (timer_end - timer_start);
 
  347  double data_rate = data.size() * 
sizeof(T) / (1e6 * dt.count());
 
  348  LOG(INFO) << 
"HDF5 Read data rate: " << data_rate << 
"MB/s";
 
int rank(MPI_Comm comm)
Return process rank for the communicator.
Definition MPI.cpp:64