Wildmeshing Toolkit
Loading...
Searching...
No Matches
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>
32
34
35#include <h5pp/h5pp.h>
36
37#include <regex>
38
39
40namespace wmtk {
41namespace {
42template <typename T>
43std::string get_type()
44{
45 return "";
46}
47
48template <>
49std::string get_type<int64_t>()
50{
51 return "int64_t";
52}
53
54template <>
55std::string get_type<double>()
56{
57 return "double";
58}
59
60template <>
61std::string get_type<char>()
62{
63 return "char";
64}
65// template <>
66// std::string get_type<short>()
67//{
68// return "char";
69// }
70
71template <>
72std::string get_type<wmtk::Rational>()
73{
74 return "rational";
75}
76// template <>
77// std::string get_type<std::string>()
78//{
79// return "rational";
80// }
81} // namespace
82
84
85
86std::shared_ptr<Mesh> HDF5Reader::read(const std::filesystem::path& filename)
87{
88 constexpr static int64_t TWO_TUPLE_SIZE = wmtk::multimesh::utils::TWO_TUPLE_SIZE;
89 constexpr static int64_t DEFAULT_TUPLES_VALUES = wmtk::multimesh::utils::DEFAULT_TUPLES_VALUES;
90
91 h5pp::File hdf5_file(filename, h5pp::FileAccess::READONLY);
92
93 auto root = read_mesh(hdf5_file, "WMTK");
94
95 if (hdf5_file.linkExists("WMTK/multimesh")) {
96 std::map<std::vector<int64_t>, std::shared_ptr<Mesh>> meshes;
97 meshes[{}] = root;
98
99 const auto dsets = hdf5_file.findGroups("mesh_", "WMTK/multimesh", -1, 1);
100 for (auto& s : dsets) {
101 const std::string dataset = "WMTK/multimesh/" + s;
102
103 auto absolute_id =
104 hdf5_file.readAttribute<std::vector<int64_t>>(dataset, "absolute_id");
105 meshes[absolute_id] = read_mesh(hdf5_file, dataset);
106 }
107
108
109 for (auto& p : meshes) {
110 if (p.first.empty()) continue;
111
112 const std::vector<int64_t>& child_id = p.first;
113 const auto child_index = child_id.back();
114
115 std::vector<int64_t> parent_id = child_id;
116 parent_id.pop_back();
117
118 auto parent_mesh = meshes.at(parent_id);
119 auto child_mesh = p.second;
120
121 const PrimitiveType child_primitive_type = child_mesh->top_simplex_type();
122
123
124 assert(parent_mesh->m_multi_mesh_manager.m_children.size() == child_index);
125
126 auto child_to_parent_handle =
127 child_mesh
128 ->get_attribute_handle<int64_t>(
130 child_primitive_type)
131 .as<int64_t>();
132
133 auto parent_to_child_handle =
134 parent_mesh
135 ->get_attribute_handle<int64_t>(
137 child_index),
138 child_primitive_type)
139 .as<int64_t>();
140
141 child_mesh->m_multi_mesh_manager.m_parent = parent_mesh.get();
142 child_mesh->m_multi_mesh_manager.m_child_id = child_index;
143 child_mesh->m_multi_mesh_manager.map_to_parent_handle = child_to_parent_handle;
144
145 parent_mesh->m_multi_mesh_manager.m_children.emplace_back();
146 parent_mesh->m_multi_mesh_manager.m_children.back().mesh = child_mesh;
147 parent_mesh->m_multi_mesh_manager.m_children.back().map_handle = parent_to_child_handle;
148 parent_mesh->m_multi_mesh_manager
149 .m_has_child_mesh_in_dimension[child_mesh->top_cell_dimension()] = true;
150 parent_mesh->assert_capacity_valid();
151 child_mesh->assert_capacity_valid();
152 }
153
154#if !defined(NDEBUG)
155 for (auto& p : meshes) {
156 assert(p.first == p.second->m_multi_mesh_manager.absolute_id());
157 }
158#endif
159 }
160
161
162 return root;
163}
164
165std::shared_ptr<Mesh> HDF5Reader::read_mesh(h5pp::File& hdf5_file, const std::string& root_dataset)
166{
167 PrimitiveType top_simplex_type =
168 hdf5_file.readAttribute<PrimitiveType>(root_dataset, "top_simplex_type");
169
170 std::shared_ptr<Mesh> mesh;
171
172 switch (top_simplex_type) {
173 case PrimitiveType::Vertex: mesh = std::make_shared<PointMesh>(); break;
174 case PrimitiveType::Edge: mesh = std::make_shared<EdgeMesh>(); break;
175 case PrimitiveType::Triangle: mesh = std::make_shared<TriMesh>(); break;
176 case PrimitiveType::Tetrahedron: mesh = std::make_shared<TetMesh>(); break;
177 default: break;
178 }
179
180 std::vector<int64_t> capacities =
181 hdf5_file.readAttribute<std::vector<int64_t>>(root_dataset, "capacities");
182
183
184 mesh->set_capacities(capacities);
185
186 {
187 bool found_something = false;
188 auto searcher = [&](int dim, auto&& t) {
189 using T = std::decay_t<decltype(t)>;
190 const static std::string name = get_type<T>();
191
192 std::string attr_dset_name =
193 fmt::format("{}/ATTRIBUTE_LIST_{}/{}", root_dataset, name, dim);
194 try {
195 auto names = hdf5_file.readDataset<std::vector<std::string>>(attr_dset_name);
196 for (const auto& v : names) {
197 found_something = true;
198 const std::string dataset = fmt::format("{}/{}/{}", root_dataset, dim, v);
199 read_attribute(hdf5_file, *mesh, dataset, v);
200 }
201 } catch (const std::exception& e) {
202 }
203 };
204 auto search = [&](int dim) {
205 searcher(dim, double{});
206 searcher(dim, wmtk::Rational{});
207 searcher(dim, int64_t{});
208 searcher(dim, char{});
209 };
210 switch (top_simplex_type) {
211 case PrimitiveType::Tetrahedron: search(3); [[fallthrough]];
212 case PrimitiveType::Triangle: search(2); [[fallthrough]];
213 case PrimitiveType::Edge: search(1); [[fallthrough]];
214 case PrimitiveType::Vertex: search(0); [[fallthrough]];
215 default: break;
216 }
217
218 if (found_something) { // if we didnt find attribute lists assume we are using an old format
219 // mesh
220 return mesh;
221 }
222 }
223
224
225 const auto dsets = hdf5_file.findDatasets("", root_dataset, -1, 1);
226 for (auto& s : dsets) {
227 const std::string dataset = fmt::format("{}/{}", root_dataset, s);
228 read_attribute(hdf5_file, *mesh, dataset, s);
229 }
230
231 return mesh;
232}
234 h5pp::File& hdf5_file,
235 Mesh& mesh,
236 const std::string& dataset,
237 const std::string& name_)
238{
239 const int64_t stride = hdf5_file.readAttribute<int64_t>(dataset, "stride");
240 const int64_t dimension = hdf5_file.readAttribute<int64_t>(dataset, "dimension");
241 const std::string type = hdf5_file.readAttribute<std::string>(dataset, "type");
242 const std::string name =
243 std::regex_replace(name_, std::regex(std::to_string(dimension) + "/"), "");
244
245 auto pt = PrimitiveType(dimension);
246
247 if (type == "int64_t") {
248 auto v = hdf5_file.readDataset<std::vector<int64_t>>(dataset);
249 const auto default_val = hdf5_file.readAttribute<int64_t>(dataset, "default_value");
250
251 set_attribute<int64_t>(default_val, name, pt, stride, v, mesh);
252 } else if (type == "char") {
253 auto tmp = hdf5_file.readDataset<std::vector<short>>(dataset);
254 const auto default_val = char(hdf5_file.readAttribute<short>(dataset, "default_value"));
255
256 std::vector<char> v;
257 v.reserve(tmp.size());
258 for (auto val : tmp) v.push_back(char(val));
259
260
261 set_attribute<char>(default_val, name, pt, stride, v, mesh);
262 } else if (type == "double") {
263 auto v = hdf5_file.readDataset<std::vector<double>>(dataset);
264 const auto default_val = hdf5_file.readAttribute<double>(dataset, "default_value");
265
266
267 set_attribute<double>(default_val, name, pt, stride, v, mesh);
268 } else if (type == "rational") {
269 const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> tmp =
270 hdf5_file
271 .readDataset<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(
272 dataset);
273 const Eigen::Matrix<char, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> tmp_char =
274 tmp.cast<char>();
275
276 const std::string data = hdf5_file.readAttribute<std::string>(dataset, "default_value");
277 Rational default_val;
278 default_val.init_from_binary(data);
279
280 std::vector<Rational> v;
281 v.reserve(tmp.rows());
282 for (size_t i = 0; i < tmp.rows(); ++i) {
283 v.emplace_back(tmp_char.row(i));
284 }
285
286 set_attribute<Rational>(default_val, name, pt, stride, v, mesh);
287
288 } else {
289 logger().error("We currently do not support reading the type \"{}\"", type);
290 assert(false);
291 }
292}
293
294template <typename T>
296 const T& default_val,
297 const std::string& name,
298 PrimitiveType pt,
299 int64_t stride,
300 const std::vector<T>& v,
301 Mesh& mesh)
302{
304 mesh.has_attribute<T>(name, pt)
305 ? mesh.get_attribute_handle<T>(name, pt)
306 : mesh.register_attribute<T>(name, pt, stride, false, default_val);
307 const attribute::TypedAttributeHandle<T>& thandle = handle.as<T>();
308
309 int64_t handle_dimension = mesh.get_attribute_dimension(thandle);
310 if (stride != handle_dimension) {
312 "Attribute does not have the expected dimension:\n expected {}\n actual {}",
313 stride,
314 handle_dimension);
315 }
316
317 auto accessor = mesh.create_accessor<T>(thandle);
318
319 accessor.attribute().set(v);
320}
321
322
323} // namespace wmtk
void read_attribute(h5pp::File &hdf5_file, Mesh &m, const std::string &dataset, const std::string &name)
void set_attribute(const T &default_val, const std::string &name, PrimitiveType pt, int64_t stride, const std::vector< T > &v, Mesh &mesh)
std::shared_ptr< Mesh > read(const std::filesystem::path &filename)
std::shared_ptr< Mesh > read_mesh(h5pp::File &hdf5_file, const std::string &dataset)
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:901
int64_t get_attribute_dimension(const TypedAttributeHandle< T > &handle) const
Definition Mesh.hpp:927
bool has_attribute(const std::string &name, const PrimitiveType ptype) const
Definition Mesh.hpp:921
attribute::Accessor< T, Mesh, attribute::CachingAttribute< T >, D > create_accessor(const attribute::MeshAttributeHandle &handle)
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()
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:101
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58