Wildmeshing Toolkit
Loading...
Searching...
No Matches
TypedAttributeManager.cpp
Go to the documentation of this file.
5
10
11#include <cassert>
12#include <functional>
13#include <stdexcept>
14#include <string>
15#include <utility>
16
17namespace wmtk::attribute {
18
19
20template <typename T>
21void TypedAttributeManager<T>::serialize(const int dim, MeshWriter& writer) const
22{
23 std::vector<std::string> attribute_names;
24 std::transform(
25 m_attributes.begin(),
26 m_attributes.end(),
27 std::back_inserter(attribute_names),
28 [](const auto& ptr) -> std::string {
29 if (ptr) {
30 return ptr->name();
31 } else {
32 return {};
33 }
34 });
35
36 attribute_names.erase(
37 std::remove_if(
38 attribute_names.begin(),
39 attribute_names.end(),
40 [](const std::string& name) { return name.empty(); }),
41 attribute_names.end());
42
43 HDF5Writer* hdf5_w = dynamic_cast<HDF5Writer*>(&writer);
44 if (hdf5_w != nullptr) {
45 hdf5_w->write_attribute_names<T>(dim, attribute_names);
46 }
47
48 for (const auto& attr_ptr : m_attributes) {
49 if (bool(attr_ptr)) {
50 attr_ptr->serialize(dim, writer);
51 }
52 }
53}
54
55template <typename T>
56std::map<std::string, std::size_t> TypedAttributeManager<T>::child_hashes() const
57{
58 // default implementation pulls the child attributes (ie the attributes)
59 std::map<std::string, std::size_t> ret = wmtk::utils::MerkleTreeInteriorNode::child_hashes();
60
61 // hash handle data
62 for (const auto& [name, handle] : m_handles) {
63 ret["attr_handle_" + name] = std::hash<AttributeHandle>{}(handle);
64 }
65 return ret;
66}
67template <typename T>
68std::map<std::string, const wmtk::utils::Hashable*> TypedAttributeManager<T>::child_hashables()
69 const
70
71{
72 std::map<std::string, const wmtk::utils::Hashable*> ret;
73 for (const auto& [name, handle] : m_handles) {
74 const auto& attr = attribute(handle);
75 ret["attr_" + name] = &attr;
76 }
77 return ret;
78}
79
80template <typename T>
82{
83 for (auto& attr_ptr : m_attributes) {
84 if (bool(attr_ptr)) {
85 attr_ptr->push_scope();
86 }
87 }
88}
89template <typename T>
91{
92 for (auto& attr_ptr : m_attributes) {
93 if (bool(attr_ptr)) {
94 attr_ptr->pop_scope(apply_updates);
95 }
96 }
97}
98template <typename T>
100{
101 for (auto& attr_ptr : m_attributes) {
102 if (bool(attr_ptr)) {
103 attr_ptr->rollback_current_scope();
104 }
105 }
106}
107template <typename T>
109{
110 for (const auto& attr_ptr : m_attributes) {
111 if (bool(attr_ptr)) {
112 attr_ptr->change_to_next_scope();
113 }
114 }
115}
116
117template <typename T>
119{
120 for (const auto& attr_ptr : m_attributes) {
121 if (bool(attr_ptr)) {
122 attr_ptr->change_to_previous_scope();
123 }
124 }
125}
126
127template <typename T>
129 const std::string& name,
130 int64_t dimension,
131 bool replace,
132 T default_value)
133{
134 if (!replace && has_attribute(name)) {
136 "Cannot register attribute '{}' because it exists already. Set replace to true if you "
137 "want to overwrite the attribute",
138 name);
139 }
140
141 AttributeHandle handle;
142
143
144 if (replace && m_handles.find(name) != m_handles.end()) {
145 auto it = m_handles.find(name);
146 handle = it->second.index();
147 } else {
148 handle = m_attributes.size();
149 m_attributes.emplace_back(
150 std::make_unique<CachingAttribute<T>>(name, dimension, default_value, reserved_size()));
151 }
152 m_handles[name] = handle;
153
154
155 return handle;
156}
157
158template <typename T>
160{
161 for (const auto& a : m_attributes) {
162 if (bool(a)) {
163 assert(a->reserved_size() >= cap);
164 }
165 }
166}
167template <typename T>
169{
170 auto it = m_handles.find(name);
171 if (it == m_handles.end()) {
172 log_and_throw_error("Cannot find handle for attribute named {}", name);
173 }
174 return it->second;
175}
176template <typename T>
177bool TypedAttributeManager<T>::has_attribute(const std::string& name) const
178{
179 auto it = m_handles.find(name);
180 return it != m_handles.end() && bool(m_attributes[it->second.index()]);
181}
182
183template <typename T>
185{
186 if (m_handles != other.m_handles) {
187 return false;
188 }
189 if (m_attributes.size() != other.m_attributes.size()) {
190 return false;
191 }
192 for (size_t j = 0; j < m_attributes.size(); ++j) {
193 const bool exists = bool(m_attributes[j]);
194 const bool o_exists = bool(other.m_attributes[j]);
195 if (exists != o_exists) {
196 return false;
197 } else if (exists && o_exists && !(*m_attributes[j] == *other.m_attributes[j])) {
198 return false;
199 }
200 }
201 return true;
202}
203
204
205template <typename T>
206void TypedAttributeManager<T>::set(const AttributeHandle& handle, std::vector<T> val)
207{
208 // TODO: should we validate the size of val compared to the internally held data?
209 auto& attr_ptr = m_attributes[handle.index()];
210 assert(bool(attr_ptr));
211 auto& attr = *attr_ptr;
212 attr.set(std::move(val));
213}
214
215template <typename T>
217{
218 auto& attr_ptr = m_attributes[handle.index()];
219 assert(bool(attr_ptr));
220 return attr_ptr->reserved_size();
221}
222
223template <typename T>
225{
226 return m_reserved_size;
227}
228
229template <typename T>
231{
232 return active_attributes().size();
233}
234template <typename T>
236{
237 std::vector<AttributeHandle> handles;
238 handles.reserve(m_attributes.size());
239 for (size_t j = 0; j < m_attributes.size(); ++j) {
240 if (bool(m_attributes[j])) {
241 handles.emplace_back(AttributeHandle(j));
242 }
243 }
244
245 return handles;
246}
247template <typename T>
249{
250 const size_t index = h.index();
251 assert(index < m_attributes.size());
252 return bool(m_attributes[index]);
253}
254
255template <typename T>
256void TypedAttributeManager<T>::reserve(const int64_t size)
257{
258 m_reserved_size = size;
259 for (auto& attr_ptr : m_attributes) {
260 if (bool(attr_ptr)) {
261 attr_ptr->reserve(size);
262 }
263 }
264}
265
266template <typename T>
268{
269 reserve(m_reserved_size + size);
270}
271
272template <typename T>
274{
275 if (size > m_reserved_size) {
276 // logger().warn("Pre-reserve enough simplices before your operation.");
277 reserve(size);
278 }
279}
280
281template <typename T>
282void TypedAttributeManager<T>::remove_attributes(const std::vector<AttributeHandle>& attributes)
283{
284 for (const AttributeHandle& i : attributes) {
285 remove_attribute(i);
286 }
287}
288
289
290template <typename T>
292{
293 auto& attr = m_attributes[attribute.index()];
294 if (!attr) {
295 logger().warn("Attribute was already deleted.");
296 return;
297 }
298
299 const std::string& name = attr->name();
300 m_handles.erase(name);
301 m_attributes[attribute.index()].reset();
302}
303
304template <typename T>
306{
307 if (m_handles.size() > m_attributes.size()) {
308 logger().warn(
309 "More handles than attributes. Handles: {}, attributes: {}",
310 m_handles.size(),
311 m_attributes.size());
312 return false;
313 }
314 for (const auto& [name, handle] : m_handles) {
315 if (handle.index() >= m_attributes.size()) {
316 logger().warn(
317 "Handle index for `{}` is out of bounds for attributes vector. Handle index: {}, "
318 "attributes "
319 "vector size: {}",
320 name,
321 handle.index(),
322 m_attributes.size());
323 return false;
324 }
325 if (!m_attributes[handle.index()]) {
326 continue;
327 }
328 const auto& attr = m_attributes[handle.index()];
329 if (attr->name() != name) {
330 logger().warn(
331 "Attribute name is not the same as the name in the handles map. Attribute: {}, "
332 "handles map: {}",
333 attr->name(),
334 name);
335 return false;
336 }
337 }
338
339 return true;
340}
341
342template <typename T>
344{
345 for (const auto& [name, h] : m_handles) {
346 if (h.index() != handle.index()) {
347 continue;
348 }
349 if (!m_attributes[handle.index()]) {
350 return true;
351 }
352 const auto& attr_name = m_attributes[handle.index()]->name();
353 if (attr_name != name) {
354 logger().warn(
355 "Attribute name is not the same as the name in the handles map. Attribute: {}, "
356 "handles map: {}",
357 attr_name,
358 name);
359 return false;
360 }
361
362 return true;
363 }
364
365 logger().warn("Handle with index `{}` was not found in the handles map.", handle.index());
366 return false;
367}
368
369template <typename T>
371{
372 size_t old_index = 0;
373 size_t new_index = 0;
374 std::vector<int64_t> old_to_new_id(m_attributes.size(), -1);
375 for (old_index = 0; old_index < m_attributes.size(); ++old_index) {
376 if (bool(m_attributes[old_index])) {
377 old_to_new_id[old_index] = new_index;
378 m_attributes[new_index++] = std::move(m_attributes[old_index]);
379 }
380 }
381 m_attributes.resize(new_index);
382
383 // clean up m_handles
384 for (auto it = m_handles.begin(); it != m_handles.end(); /* no increment */) {
385 if (int64_t new_ind = old_to_new_id[it->second.index()]; new_ind == -1) {
386 it = m_handles.erase(it);
387 } else {
388 it->second = new_ind;
389 ++it;
390 }
391 }
392}
393template <typename T>
395{
396 for (const auto& [key, value] : m_handles) {
397 if (value == handle) {
398 return key;
399 }
400 }
401 throw std::runtime_error("Could not find handle in TypedAttributeManager");
402 return "UNKNOWN";
403}
404
405template <typename T>
406void TypedAttributeManager<T>::set_name(const AttributeHandle& handle, const std::string& name)
407{
408 const std::string old_name = get_name(handle);
409
410 if (old_name == name) {
411 return;
412 }
413
414 auto& attr = m_attributes[handle.index()];
415 assert(bool(attr));
416 assert(attr->name() == old_name);
417
418 assert(!has_attribute(name)); // name should not exist already
419
420 attr->set_name(name);
421 m_handles[name] = m_handles[old_name];
422 m_handles.erase(old_name);
423}
424
425template class TypedAttributeManager<char>;
426template class TypedAttributeManager<int64_t>;
427template class TypedAttributeManager<double>;
429
430} // namespace wmtk::attribute
void write_attribute_names(int dim, const std::vector< std::string > &names)
Internal handle representation used by TypedAttributeManager.
int64_t index() const noexcept
Contains all attributes of type T for a single mesh.
std::map< std::string, AttributeHandle > m_handles
std::vector< std::unique_ptr< CachingAttribute< T > > > m_attributes
void serialize(const int dim, MeshWriter &writer) const
std::map< std::string, std::size_t > child_hashes() const override
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:101
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58