Program Listing for File hdf_utils.h

Return to documentation for file (framework/utils/hdf_utils.h)

// SPDX-FileCopyrightText: 2024 The OpenSn Authors <https://open-sn.github.io/opensn/>
// SPDX-License-Identifier: MIT

#pragma once

#include "hdf5.h"
#include <vector>
#include <string>

namespace opensn
{
template <typename T>
hid_t get_datatype();

template <>
inline hid_t
get_datatype<char>()
{
  return H5T_NATIVE_CHAR;
}

template <>
inline hid_t
get_datatype<signed char>()
{
  return H5T_NATIVE_SCHAR;
}

template <>
inline hid_t
get_datatype<unsigned char>()
{
  return H5T_NATIVE_UCHAR;
}

template <>
inline hid_t
get_datatype<short>()
{
  return H5T_NATIVE_SHORT;
}

template <>
inline hid_t
get_datatype<unsigned short>()
{
  return H5T_NATIVE_USHORT;
}

template <>
inline hid_t
get_datatype<int>()
{
  return H5T_NATIVE_INT;
}

template <>
inline hid_t
get_datatype<unsigned int>()
{
  return H5T_NATIVE_UINT;
}

template <>
inline hid_t
get_datatype<long>()
{
  return H5T_NATIVE_LONG;
}

template <>
inline hid_t
get_datatype<unsigned long>()
{
  return H5T_NATIVE_ULONG;
}

template <>
inline hid_t
get_datatype<long long>()
{
  return H5T_NATIVE_LLONG;
}

template <>
inline hid_t
get_datatype<unsigned long long>()
{
  return H5T_NATIVE_ULLONG;
}

template <>
inline hid_t
get_datatype<float>()
{
  return H5T_NATIVE_FLOAT;
}

template <>
inline hid_t
get_datatype<double>()
{
  return H5T_NATIVE_DOUBLE;
}

inline bool
H5Has(hid_t id, const std::string& name)
{
  return (H5Lexists(id, name.c_str(), H5P_DEFAULT) > 0);
}

inline bool
H5CreateGroup(hid_t id, const std::string& name)
{
  return (H5Gcreate2(id, name.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) >= 0);
}

template <typename T>
bool
H5WriteDataset1D(hid_t id, const std::string& name, std::vector<T> data)
{
  bool success = false;

  hsize_t dim[1], maxdims[1];
  dim[0] = data.size();
  maxdims[0] = data.size();
  auto dataspace = H5Screate_simple(1, dim, maxdims);
  if (dataspace != H5I_INVALID_HID)
  {
    auto dataset = H5Dcreate2(
      id, name.c_str(), get_datatype<T>(), dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    if (dataset != H5I_INVALID_HID)
    {
      if (H5Dwrite(dataset, get_datatype<T>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data()) >= 0)
        success = true;
      H5Dclose(dataset);
    }
    H5Sclose(dataspace);
  }

  return success;
}

template <typename T>
bool
H5CreateAttribute(hid_t id, const std::string& name, T& data)
{
  bool success = false;

  auto dataspace = H5Screate(H5S_SCALAR);
  if (dataspace != H5I_INVALID_HID)
  {
    auto attribute =
      H5Acreate2(id, name.c_str(), get_datatype<T>(), dataspace, H5P_DEFAULT, H5P_DEFAULT);
    if (attribute != H5I_INVALID_HID)
    {
      if (H5Awrite(attribute, get_datatype<T>(), &data) >= 0)
        success = true;
      H5Aclose(attribute);
    }
    H5Sclose(dataspace);
  }

  return success;
}

template <typename T>
bool
H5ReadDataset1D(hid_t id, const std::string& name, std::vector<T>& data)
{
  bool success = true;

  auto dataset = H5Dopen2(id, name.c_str(), H5P_DEFAULT);
  if (dataset != H5I_INVALID_HID)
  {
    auto dataspace = H5Dget_space(dataset);
    if (dataspace != H5I_INVALID_HID)
    {
      hsize_t dims[1];
      if (H5Sget_simple_extent_dims(dataspace, dims, NULL) == 1)
      {
        data.resize(dims[0]);
        if (H5Dread(dataset, get_datatype<T>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data()) < 0)
        {
          data.clear();
          data.shrink_to_fit();
          success = false;
        }
      }
      H5Sclose(dataspace);
    }
    H5Dclose(dataset);
  }
  else
  {
    if (H5Aexists(id, name.c_str()))
    {
      auto attribute = H5Aopen(id, name.c_str(), H5P_DEFAULT);
      if (attribute != H5I_INVALID_HID)
      {
        auto size = static_cast<size_t>(H5Aget_storage_size(attribute));
        if (size > 0)
        {
          size_t num_elements = size / sizeof(T);
          data.resize(num_elements);
          if (H5Aread(attribute, get_datatype<T>(), data.data()) < 0)
          {
            data.clear();
            data.shrink_to_fit();
            success = false;
          }
        }
        H5Aclose(attribute);
      }
    }
  }

  return success;
}

template <typename T>
bool
H5ReadAttribute(hid_t id, const std::string& name, T& value)
{
  bool success = false;

  if (H5Aexists(id, name.c_str()))
  {
    auto attribute = H5Aopen(id, name.c_str(), H5P_DEFAULT);
    if (attribute != H5I_INVALID_HID)
    {
      if (H5Aread(attribute, get_datatype<T>(), &value) >= 0)
        success = true;
      H5Aclose(attribute);
    }
  }

  return success;
}

template <>
inline bool
H5ReadAttribute<std::string>(hid_t id, const std::string& name, std::string& value)
{
  bool success = false;

  if (H5Aexists(id, name.c_str()))
  {
    auto attribute = H5Aopen(id, name.c_str(), H5P_DEFAULT);
    if (attribute != H5I_INVALID_HID)
    {
      auto size = static_cast<size_t>(H5Aget_storage_size(attribute));
      if (size > 0)
      {
        hid_t string_type = H5Tcopy(H5T_C_S1);
        H5Tset_size(string_type, size + 1);
        std::vector<char> buffer(size + 1);
        if (H5Aread(attribute, string_type, buffer.data()) >= 0)
        {
          value = buffer.data();
          success = true;
        }
      }
      H5Aclose(attribute);
    }
  }

  return success;
}

template <>
inline bool
H5ReadAttribute<bool>(hid_t id, const std::string& name, bool& value)
{
  bool success = false;

  if (H5Aexists(id, name.c_str()))
  {
    auto attribute = H5Aopen(id, name.c_str(), H5P_DEFAULT);
    if (attribute != H5I_INVALID_HID)
    {
      if (H5Aread(attribute, H5T_NATIVE_INT, &value) >= 0)
        success = true;
      H5Aclose(attribute);
    }
  }

  return success;
}

template <typename T>
bool
H5ReadGroupAttribute(hid_t id, const std::string& group_id, const std::string& name, T& value)
{
  bool success = false;

  auto group = H5Gopen2(id, group_id.c_str(), H5P_DEFAULT);
  if (group != H5I_INVALID_HID)
  {
    success = H5ReadAttribute<T>(group, name, value);
    H5Gclose(group);
  }

  return success;
}

template <>
inline bool
H5ReadGroupAttribute<std::string>(hid_t id,
                                  const std::string& group_id,
                                  const std::string& name,
                                  std::string& value)
{
  bool success = false;

  auto group = H5Gopen2(id, group_id.c_str(), H5P_DEFAULT);
  if (group != H5I_INVALID_HID)
  {
    success = H5ReadAttribute<std::string>(group, name, value);
    H5Gclose(group);
  }

  return success;
}

template <>
inline bool
H5ReadGroupAttribute<bool>(hid_t id,
                           const std::string& group_id,
                           const std::string& name,
                           bool& value)
{
  bool success = false;

  auto group = H5Gopen2(id, group_id.c_str(), H5P_DEFAULT);
  if (group != H5I_INVALID_HID)
  {
    success = H5ReadAttribute<bool>(group, name, value);
    H5Gclose(group);
  }

  return success;
}

} // namespace opensn