Wildmeshing Toolkit
MeshAttributes.cpp
Go to the documentation of this file.
1 #include "MeshAttributes.hpp"
5 
6 #include <wmtk/io/MeshWriter.hpp>
7 #include <wmtk/utils/Logger.hpp>
9 
10 #include <cassert>
11 #include <functional>
12 #include <stdexcept>
13 #include <string>
14 #include <utility>
15 
16 namespace wmtk::attribute {
17 
18 
19 template <typename T>
20 void MeshAttributes<T>::serialize(const int dim, MeshWriter& writer) const
21 {
22  for (const auto& p : m_handles) {
23  const auto& handle = p.second;
24  const auto& attr_ptr = attribute(handle);
25  if (is_active(handle)) {
26  const auto& attr = *m_attributes[handle.index];
27  attr.serialize(p.first, dim, writer);
28  }
29  }
30 }
31 
32 template <typename T>
33 std::map<std::string, std::size_t> MeshAttributes<T>::child_hashes() const
34 {
35  // default implementation pulls the child attributes (ie the attributes)
36  std::map<std::string, std::size_t> ret = wmtk::utils::MerkleTreeInteriorNode::child_hashes();
37 
38  // hash handle data
39  for (const auto& [name, handle] : m_handles) {
40  ret["attr_handle_" + name] = std::hash<AttributeHandle>{}(handle);
41  }
42  return ret;
43 }
44 template <typename T>
45 std::map<std::string, const wmtk::utils::Hashable*> MeshAttributes<T>::child_hashables() const
46 
47 {
48  std::map<std::string, const wmtk::utils::Hashable*> ret;
49  for (const auto& [name, handle] : m_handles) {
50  const auto& attr = attribute(handle);
51  ret["attr_" + name] = &attr;
52  }
53  return ret;
54 }
55 
56 template <typename T>
58 {
59  for (auto& attr_ptr : m_attributes) {
60  if (bool(attr_ptr)) {
61  attr_ptr->push_scope();
62  }
63  }
64 }
65 template <typename T>
66 void MeshAttributes<T>::pop_scope(bool apply_updates)
67 {
68  for (auto& attr_ptr : m_attributes) {
69  if (bool(attr_ptr)) {
70  attr_ptr->pop_scope(apply_updates);
71  }
72  }
73 }
74 template <typename T>
76 {
77  for (auto& attr_ptr : m_attributes) {
78  if (bool(attr_ptr)) {
79  attr_ptr->rollback_current_scope();
80  }
81  }
82 }
83 template <typename T>
85 {
86  for (const auto& attr_ptr : m_attributes) {
87  if (bool(attr_ptr)) {
88  auto& stack = attr_ptr->get_local_scope_stack();
89 
90  stack.change_to_next_scope();
91  }
92  }
93 }
94 
95 template <typename T>
97 {
98  for (const auto& attr_ptr : m_attributes) {
99  if (bool(attr_ptr)) {
100  attr_ptr->get_local_scope_stack().change_to_previous_scope();
101  }
102  }
103 }
104 
105 template <typename T>
107  const std::string& name,
108  int64_t dimension,
109  bool replace,
110  T default_value)
111 {
112  if (!replace && m_handles.find(name) != m_handles.end()) {
114  "Cannot register attribute '{}' because it exists already. Set replace to true if you "
115  "want to overwrite the attribute",
116  name);
117  }
118 
119  AttributeHandle handle;
120 
121 
122  if (replace && m_handles.find(name) != m_handles.end()) {
123  auto it = m_handles.find(name);
124  handle.index = it->second.index;
125  } else {
126  handle.index = m_attributes.size();
127  m_attributes.emplace_back(
128  std::make_unique<Attribute<T>>(name, dimension, default_value, reserved_size()));
129  }
130  m_handles[name] = handle;
131 
132 
133  return handle;
134 }
135 
136 template <typename T>
138 {
139  for (const auto& a : m_attributes) {
140  if (bool(a)) {
141  assert(a->reserved_size() >= cap);
142  }
143  }
144 }
145 template <typename T>
147 {
148  return m_handles.at(name);
149 }
150 template <typename T>
151 bool MeshAttributes<T>::has_attribute(const std::string& name) const
152 {
153  auto it = m_handles.find(name);
154  return it != m_handles.end() && bool(m_attributes[it->second.index]);
155 }
156 
157 template <typename T>
159 {
160  if (m_handles != other.m_handles) {
161  return false;
162  }
163  if (m_attributes.size() != other.m_attributes.size()) {
164  return false;
165  }
166  for (size_t j = 0; j < m_attributes.size(); ++j) {
167  const bool exists = bool(m_attributes[j]);
168  const bool o_exists = bool(other.m_attributes[j]);
169  if (exists != o_exists) {
170  return false;
171  } else if (exists && o_exists && !(*m_attributes[j] == *other.m_attributes[j])) {
172  return false;
173  }
174  }
175  return true;
176 }
177 
178 
179 template <typename T>
180 void MeshAttributes<T>::set(const AttributeHandle& handle, std::vector<T> val)
181 {
182  // TODO: should we validate the size of val compared to the internally held data?
183  auto& attr_ptr = m_attributes[handle.index];
184  assert(bool(attr_ptr));
185  auto& attr = *attr_ptr;
186  attr.set(std::move(val));
187 }
188 
189 template <typename T>
191 {
192  auto& attr_ptr = m_attributes[handle.index];
193  assert(bool(attr_ptr));
194  return attr_ptr->reserved_size();
195 }
196 
197 template <typename T>
199 {
200  return m_reserved_size;
201 }
202 
203 template <typename T>
205 {
206  return active_attributes().size();
207 }
208 template <typename T>
210 {
211  std::vector<AttributeHandle> handles;
212  handles.reserve(m_attributes.size());
213  for (size_t j = 0; j < m_attributes.size(); ++j) {
214  if (bool(m_attributes[j])) {
215  handles.emplace_back(j);
216  }
217  }
218 
219  return handles;
220 }
221 template <typename T>
223 {
224  const size_t index = h.index;
225  assert(index < m_attributes.size());
226  return bool(m_attributes[index]);
227 }
228 
229 template <typename T>
230 void MeshAttributes<T>::reserve(const int64_t size)
231 {
232  m_reserved_size = size;
233  for (auto& attr_ptr : m_attributes) {
234  if (bool(attr_ptr)) {
235  attr_ptr->reserve(size);
236  }
237  }
238 }
239 
240 template <typename T>
241 void MeshAttributes<T>::reserve_more(const int64_t size)
242 {
243  reserve(m_reserved_size + size);
244 }
245 
246 template <typename T>
248 {
249  if (size > m_reserved_size) {
250  // logger().warn("Pre-reserve enough simplices before your operation.");
251  reserve(size);
252  }
253 }
254 
255 template <typename T>
257  const std::vector<AttributeHandle>& attributes,
258  bool invalidate_handles)
259 {
260  if (attributes.empty()) {
261  return;
262  }
263  std::vector<int64_t> remove_indices;
264  std::transform(
265  attributes.begin(),
266  attributes.end(),
267  std::back_inserter(remove_indices),
268  [](const AttributeHandle& h) { return h.index; });
269  std::sort(remove_indices.begin(), remove_indices.end());
270  remove_indices.erase(
271  std::unique(remove_indices.begin(), remove_indices.end()),
272  remove_indices.end());
273 
274 
275  for (const int64_t& i : remove_indices) {
276  m_attributes[i].reset();
277  }
278 
279 
280  if (invalidate_handles) {
281  clear_dead_attributes();
282  }
283 }
284 
285 
286 template <typename T>
288 {
289  m_attributes[attribute.index].reset();
290 }
291 
292 template <typename T>
294 {
295  size_t old_index = 0;
296  size_t new_index = 0;
297  std::vector<int64_t> old_to_new_id(m_attributes.size(), -1);
298  for (old_index = 0; old_index < m_attributes.size(); ++old_index) {
299  if (bool(m_attributes[old_index])) {
300  old_to_new_id[old_index] = new_index;
301  m_attributes[new_index++] = std::move(m_attributes[old_index]);
302  }
303  }
304  m_attributes.resize(new_index);
305 
306  // clean up m_handles
307  for (auto it = m_handles.begin(); it != m_handles.end(); /* no increment */) {
308  if (int64_t new_ind = old_to_new_id[it->second.index]; new_ind == -1) {
309  it = m_handles.erase(it);
310  } else {
311  it->second.index = new_ind;
312  ++it;
313  }
314  }
315 }
316 template <typename T>
317 std::string MeshAttributes<T>::get_name(const AttributeHandle& handle) const
318 {
319  for (const auto& [key, value] : m_handles) {
320  if (value == handle) {
321  return key;
322  }
323  }
324  throw std::runtime_error("Could not find handle in MeshAttributes");
325  return "UNKNOWN";
326 }
327 
328 template <typename T>
329 void MeshAttributes<T>::set_name(const AttributeHandle& handle, const std::string& name)
330 {
331  const std::string old_name = get_name(handle);
332 
333  if (old_name == name) {
334  return;
335  }
336 
337  auto& attr = m_attributes[handle.index];
338  assert(bool(attr));
339  assert(attr->m_name == old_name);
340 
341  assert(m_handles.count(name) == 0); // name should not exist already
342 
343  attr->m_name = name;
344  m_handles[name] = m_handles[old_name];
345  m_handles.erase(old_name);
346 }
347 
348 template class MeshAttributes<char>;
349 template class MeshAttributes<int64_t>;
350 template class MeshAttributes<double>;
351 template class MeshAttributes<Rational>;
352 
353 } // namespace wmtk::attribute
Internal handle representation used by MeshAttributes.
This class stores data of type T in a vector.
Definition: Attribute.hpp:32
Contains all attributes of type T for a single mesh.
std::map< std::string, std::size_t > child_hashes() const override
size_t attribute_size(const AttributeHandle &handle) const
void clear_dead_attributes()
Clears and compactifies the attribute list. This invalidates all existing handles.
std::vector< std::unique_ptr< Attribute< T > > > m_attributes
bool is_active(const AttributeHandle &handle) const
void guarantee_at_least(int64_t size)
std::map< std::string, AttributeHandle > m_handles
std::map< std::string, const wmtk::utils::Hashable * > child_hashables() const override
void remove_attributes(const std::vector< AttributeHandle > &attributes, bool invalidate_handles=true)
Remove all passed in attributes.
bool operator==(const MeshAttributes< T > &other) const
AttributeHandle attribute_handle(const std::string &name) const
std::vector< AttributeHandle > active_attributes() const
void remove_attribute(const AttributeHandle &attribute)
Remove a single attribute.
AttributeHandle register_attribute(const std::string &name, int64_t dimension, bool replace=false, T default_value=T(0))
void assert_capacity_valid(int64_t cap) const
void set(const AttributeHandle &handle, std::vector< T > val)
void reserve(const int64_t size)
void pop_scope(bool apply_updates=true)
bool has_attribute(const std::string &name) const
void set_name(const AttributeHandle &handle, const std::string &name)
std::string get_name(const AttributeHandle &handle) const
void serialize(const int dim, MeshWriter &writer) const
std::map< std::string, std::size_t > child_hashes() const override
Definition: autodiff.h:995
std::vector< Simplex > make_unique(const Mesh &m, const std::vector< Simplex > &s)
Definition: make_unique.cpp:8
void log_and_throw_error(const std::string &msg)
Definition: Logger.cpp:101