Wildmeshing Toolkit
HDF5Reader.cpp
Go to the documentation of this file.
1 // gcc-13 complains about how we use an empty vector as a key.
2 // Vector should do empty key deref for us - we hope
3 #if defined(__GNUG__) && !defined(__clang__)
4 #pragma GCC diagnostic push
5 #pragma GCC diagnostic ignored "-Wnull-dereference"
6 #endif
7 #include <map>
8 #if defined(__GNUG__) && !defined(__clang__)
9 #pragma GCC diagnostic pop
10 #endif
11 
12 #if defined(__GNUG__) && !defined(__clang__)
13 #pragma GCC diagnostic push
14 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
15 #endif
16 #include <string>
17 #if defined(__GNUG__) && !defined(__clang__)
18 #pragma GCC diagnostic pop
19 #endif
20 
21 #include "HDF5Reader.hpp"
22 
23 #include <wmtk/Mesh.hpp>
24 
25 #include <wmtk/EdgeMesh.hpp>
26 #include <wmtk/PointMesh.hpp>
27 #include <wmtk/TetMesh.hpp>
28 #include <wmtk/TriMesh.hpp>
29 
30 #include <wmtk/utils/Logger.hpp>
31 #include <wmtk/utils/Rational.hpp>
32 
34 
35 #include <h5pp/h5pp.h>
36 
37 #include <regex>
38 
39 
40 namespace wmtk {
42 
43 
44 std::shared_ptr<Mesh> HDF5Reader::read(const std::filesystem::path& filename)
45 {
46  constexpr static int64_t TWO_TUPLE_SIZE = wmtk::multimesh::utils::TWO_TUPLE_SIZE;
47  constexpr static int64_t DEFAULT_TUPLES_VALUES = wmtk::multimesh::utils::DEFAULT_TUPLES_VALUES;
48 
49  h5pp::File hdf5_file(filename, h5pp::FileAccess::READONLY);
50 
51  auto root = read_mesh(hdf5_file, "WMTK");
52 
53  if (hdf5_file.linkExists("WMTK/multimesh")) {
54  std::map<std::vector<int64_t>, std::shared_ptr<Mesh>> meshes;
55  meshes[{}] = root;
56 
57  const auto dsets = hdf5_file.findGroups("mesh_", "WMTK/multimesh", -1, 1);
58  for (auto& s : dsets) {
59  const std::string dataset = "WMTK/multimesh/" + s;
60 
61  auto absolute_id =
62  hdf5_file.readAttribute<std::vector<int64_t>>(dataset, "absolute_id");
63  meshes[absolute_id] = read_mesh(hdf5_file, dataset);
64  }
65 
66 
67  for (auto& p : meshes) {
68  if (p.first.empty()) continue;
69 
70  const std::vector<int64_t>& child_id = p.first;
71  const auto child_index = child_id.back();
72 
73  std::vector<int64_t> parent_id = child_id;
74  parent_id.pop_back();
75 
76  auto parent_mesh = meshes.at(parent_id);
77  auto child_mesh = p.second;
78 
79  const PrimitiveType child_primitive_type = child_mesh->top_simplex_type();
80 
81 
82  assert(parent_mesh->m_multi_mesh_manager.m_children.size() == child_index);
83 
84  auto child_to_parent_handle =
85  child_mesh
86  ->get_attribute_handle<int64_t>(
88  child_primitive_type)
89  .as<int64_t>();
90 
91  auto parent_to_child_handle =
92  parent_mesh
93  ->get_attribute_handle<int64_t>(
95  child_index),
96  child_primitive_type)
97  .as<int64_t>();
98 
99  child_mesh->m_multi_mesh_manager.m_parent = parent_mesh.get();
100  child_mesh->m_multi_mesh_manager.m_child_id = child_index;
101  child_mesh->m_multi_mesh_manager.map_to_parent_handle = child_to_parent_handle;
102 
103  parent_mesh->m_multi_mesh_manager.m_children.emplace_back();
104  parent_mesh->m_multi_mesh_manager.m_children.back().mesh = child_mesh;
105  parent_mesh->m_multi_mesh_manager.m_children.back().map_handle = parent_to_child_handle;
106  parent_mesh->m_multi_mesh_manager
107  .m_has_child_mesh_in_dimension[child_mesh->top_cell_dimension()] = true;
108  parent_mesh->assert_capacity_valid();
109  child_mesh->assert_capacity_valid();
110  }
111 
112 #if !defined(NDEBUG)
113  for (auto& p : meshes) {
114  assert(p.first == p.second->m_multi_mesh_manager.absolute_id());
115  }
116 #endif
117  }
118 
119 
120  return root;
121 }
122 
123 std::shared_ptr<Mesh> HDF5Reader::read_mesh(h5pp::File& hdf5_file, const std::string& root_dataset)
124 {
125  PrimitiveType top_simplex_type =
126  hdf5_file.readAttribute<PrimitiveType>(root_dataset, "top_simplex_type");
127 
128  std::shared_ptr<Mesh> mesh;
129 
130  switch (top_simplex_type) {
131  case PrimitiveType::Vertex: mesh = std::make_shared<PointMesh>(); break;
132  case PrimitiveType::Edge: mesh = std::make_shared<EdgeMesh>(); break;
133  case PrimitiveType::Triangle: mesh = std::make_shared<TriMesh>(); break;
134  case PrimitiveType::Tetrahedron: mesh = std::make_shared<TetMesh>(); break;
135  default: break;
136  }
137 
138  std::vector<int64_t> capacities =
139  hdf5_file.readAttribute<std::vector<int64_t>>(root_dataset, "capacities");
140 
141 
142  mesh->set_capacities(capacities);
143 
144 
145  const auto dsets = hdf5_file.findDatasets("", root_dataset, -1, 1);
146  for (auto& s : dsets) {
147  const std::string dataset = root_dataset + "/" + s;
148 
149 
150  const int64_t stride = hdf5_file.readAttribute<int64_t>(dataset, "stride");
151  const int64_t dimension = hdf5_file.readAttribute<int64_t>(dataset, "dimension");
152  const std::string type = hdf5_file.readAttribute<std::string>(dataset, "type");
153  const std::string name =
154  std::regex_replace(s, std::regex(std::to_string(dimension) + "/"), "");
155 
156  auto pt = PrimitiveType(dimension);
157 
158  if (type == "int64_t") {
159  auto v = hdf5_file.readDataset<std::vector<int64_t>>(dataset);
160  const auto default_val = hdf5_file.readAttribute<int64_t>(dataset, "default_value");
161 
162  set_attribute<int64_t>(default_val, name, pt, stride, v, *mesh);
163  } else if (type == "char") {
164  auto tmp = hdf5_file.readDataset<std::vector<short>>(dataset);
165  const auto default_val = char(hdf5_file.readAttribute<short>(dataset, "default_value"));
166 
167  std::vector<char> v;
168  v.reserve(tmp.size());
169  for (auto val : tmp) v.push_back(char(val));
170 
171 
172  set_attribute<char>(default_val, name, pt, stride, v, *mesh);
173  } else if (type == "double") {
174  auto v = hdf5_file.readDataset<std::vector<double>>(dataset);
175  const auto default_val = hdf5_file.readAttribute<double>(dataset, "default_value");
176 
177 
178  set_attribute<double>(default_val, name, pt, stride, v, *mesh);
179  } else if (type == "rational") {
180  const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> tmp =
181  hdf5_file.readDataset<
182  Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(dataset);
183  const Eigen::Matrix<char, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> tmp_char =
184  tmp.cast<char>();
185 
186  const std::string data = hdf5_file.readAttribute<std::string>(dataset, "default_value");
187  Rational default_val;
188  default_val.init_from_binary(data);
189 
190  std::vector<Rational> v;
191  v.reserve(tmp.rows());
192  for (size_t i = 0; i < tmp.rows(); ++i) {
193  v.emplace_back(tmp_char.row(i));
194  }
195 
196  set_attribute<Rational>(default_val, name, pt, stride, v, *mesh);
197 
198  } else {
199  logger().error("We currently do not support reading the type \"{}\"", type);
200  assert(false);
201  }
202  }
203 
204  return mesh;
205 }
206 
207 template <typename T>
209  const T& default_val,
210  const std::string& name,
211  PrimitiveType pt,
212  int64_t stride,
213  const std::vector<T>& v,
214  Mesh& mesh)
215 {
217  mesh.has_attribute<T>(name, pt)
218  ? mesh.get_attribute_handle<T>(name, pt)
219  : mesh.register_attribute<T>(name, pt, stride, false, default_val);
220  const attribute::TypedAttributeHandle<T>& thandle = handle.as<T>();
221 
222  int64_t handle_dimension = mesh.get_attribute_dimension(thandle);
223  if (stride != handle_dimension) {
225  "Attribute does not have the expected dimension:\n expected {}\n actual {}",
226  stride,
227  handle_dimension);
228  }
229 
230  auto accessor = attribute::AccessorBase<T>(mesh, thandle);
231 
232  accessor.set_attribute(v);
233 }
234 
235 
236 } // namespace wmtk
void set_attribute(const T &default_val, const std::string &name, PrimitiveType pt, int64_t stride, const std::vector< T > &v, Mesh &mesh)
Definition: HDF5Reader.cpp:208
std::shared_ptr< Mesh > read(const std::filesystem::path &filename)
Definition: HDF5Reader.cpp:44
std::shared_ptr< Mesh > read_mesh(h5pp::File &hdf5_file, const std::string &dataset)
Definition: HDF5Reader.cpp:123
attribute::MeshAttributeHandle register_attribute(const std::string &name, PrimitiveType type, int64_t size, bool replace=false, T default_value=T(0))
attribute::MeshAttributeHandle get_attribute_handle(const std::string &name, const PrimitiveType ptype) const
Definition: Mesh.hpp:918
int64_t get_attribute_dimension(const TypedAttributeHandle< T > &handle) const
Definition: Mesh.hpp:944
bool has_attribute(const std::string &name, const PrimitiveType ptype) const
Definition: Mesh.hpp:938
void init_from_binary(const std::string &v)
Definition: Rational.cpp:346
auto as() const -> const held_handle_type< held_type_from_primitive< T >()> &
Handle that represents attributes for some mesh.
static std::string parent_to_child_map_attribute_name(int64_t index)
static std::string child_to_parent_map_attribute_name()
Definition: Accessor.hpp:6
void log_and_throw_error(const std::string &msg)
Definition: Logger.cpp:101
spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:58