Wildmeshing Toolkit
MultiMeshManager_map_updates.cpp
Go to the documentation of this file.
1 
2 #include <cassert>
3 #include <functional>
4 #include <set>
5 #include <wmtk/Mesh.hpp>
6 #include <wmtk/autogen/Dart.hpp>
11 #include <wmtk/utils/Logger.hpp>
13 #include "MultiMeshManager.hpp"
17 
18 namespace wmtk::multimesh {
19 
20 namespace {
21 
22 
23 Tuple find_valid_tuple(
24  const Mesh& my_mesh,
25  const wmtk::Tuple& tuple,
26  wmtk::PrimitiveType primitive_type,
28 {
29  return std::visit(
30  [&](const auto& facet_data) -> wmtk::Tuple {
31  return facet_data->get_alternative(my_mesh.top_simplex_type(), tuple, primitive_type);
32  },
33  data.m_op_data);
34 }
35 
36 } // namespace
37 
38 
40 {
41  MultiMeshManager& parent_manager = my_mesh.m_multi_mesh_manager;
42  auto& children = parent_manager.m_children;
43  // update handles for all children
44  for (size_t i = 0; i < children.size(); ++i) {
45  auto new_handle = my_mesh.get_attribute_handle_typed<int64_t>(
46  parent_to_child_map_attribute_name(children[i].mesh->m_multi_mesh_manager.m_child_id),
47  children[i].mesh->top_simplex_type());
48  children[i] = ChildData{children[i].mesh, new_handle};
49  }
50 
51  // update child ids for all children
52  for (size_t i = 0; i < children.size(); ++i) {
53  children[i].mesh->m_multi_mesh_manager.m_child_id = i;
54  my_mesh.m_attribute_manager.set_name<int64_t>(
55  children[i].map_handle,
57  }
58 }
59 
61  Mesh& my_mesh,
62  PrimitiveType primitive_type,
63  const operations::EdgeOperationData& operation_data)
64 {
65  // Assumes that the child mesh does not have a simplex affected by the operation (such cases are
66  // evaluated by a multimesh topological guarantee or handled by operation specific code. This
67  // just makes sure that the tuple used to map to a child mesh still exists after an operation
68 
69  if (children().empty()) {
70  return;
71  }
72  auto parent_flag_accessor = my_mesh.get_const_flag_accessor(primitive_type);
73  // auto& update_tuple = [&](const auto& flag_accessor, Tuple& t) -> bool {
74  // if(acc.index_access().
75  // };
76 
77  std::vector<int64_t> gids; // get facet gids(primitive_type);
78 
79  // go over every child mesh and try to update their hashes
80  for (auto& child_data : children()) {
81  auto& child_mesh = *child_data.mesh;
82  // ignore ones whos map are the wrong dimension
83  if (child_mesh.top_simplex_type() != primitive_type) {
84  continue;
85  }
86  // logger().trace(
87  // "[{}->{}] Doing a child mesh",
88  // fmt::join(my_mesh.absolute_multi_mesh_id(), ","),
89  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","));
90  // get accessors to the maps
91  auto maps = get_map_accessors(my_mesh, child_data);
92  auto& [parent_to_child_accessor, child_to_parent_accessor] = maps;
93 
94  auto child_flag_accessor = child_mesh.get_const_flag_accessor(primitive_type);
95 
96 
97  for (const auto& gid : gids) {
98  const bool parent_exists = !my_mesh.is_removed(gid);
99  if (!parent_exists) {
100  logger().debug("parent doesnt exist, skip!");
101  continue;
102  }
103 
104  auto parent_to_child_data =
105  Mesh::get_index_access(parent_to_child_accessor).const_vector_attribute(gid);
106 
107  // wmtk::attribute::TupleAccessor<wmtk::Mesh> tuple_accessor(m, int64_t_handle);
108 
109  // read off the data in the Tuple format
110  Tuple parent_tuple, child_tuple;
111  std::tie(parent_tuple, child_tuple) =
112  wmtk::multimesh::utils::vectors_to_tuples(parent_to_child_data);
113 
114 
115  // If the parent tuple is valid, it means this parent-child pair has already been
116  // handled, so we can skip it
117  // If the parent tuple is invalid then there was no map so we can try the next cell
118  if (parent_tuple.is_null()) {
119  continue;
120  }
121 
122 
123  // it is not this function's responsibility to handle cases where
124  // teh child mesh's topology has changed on the mapped simplex, so we must make sure
125  // it's still there
126  const bool child_exists = !child_mesh.is_removed(child_tuple);
127  if (!child_exists) {
128  logger().debug("child doesnt exist, skip!");
129  continue;
130  }
131 
132 
133  parent_tuple = wmtk::multimesh::find_valid_tuple(
134  my_mesh,
135  parent_tuple,
136  primitive_type,
137  operation_data);
138 
139 
141  parent_to_child_accessor,
142  child_to_parent_accessor,
143  parent_tuple,
144  child_tuple);
145  }
146  }
147 }
148 
150  Mesh& my_mesh,
151  PrimitiveType primitive_type,
152  const std::vector<std::tuple<int64_t, std::vector<Tuple>>>& simplices_to_update,
153  const std::vector<std::tuple<int64_t, std::array<int64_t, 2>>>& split_cell_maps)
154 {
155  // logger().trace(
156  // "Update map on [{}] for {} (have {})",
157  // fmt::join(my_mesh.absolute_multi_mesh_id(), ","),
158  // primitive_type_name(primitive_type),
159  // simplices_to_update.size());
160  // for (const auto& [gid, tups] : simplices_to_update) {
161  // logger().trace(
162  // "[{}] Trying to update {}",
163  // fmt::join(my_mesh.absolute_multi_mesh_id(), ","),
164  // gid);
165  // }
166  // parent cells might have been destroyed
167  //
168 
169  const PrimitiveType parent_primitive_type = my_mesh.top_simplex_type();
170 
171  auto parent_flag_accessor = my_mesh.get_const_flag_accessor(primitive_type);
172  // auto& update_tuple = [&](const auto& flag_accessor, Tuple& t) -> bool {
173  // if(acc.index_access().
174  // };
175 
176 
177  // go over every child mesh and try to update their hashes
178  for (auto& child_data : children()) {
179  auto& child_mesh = *child_data.mesh;
180  // ignore ones whos map are the wrong dimension
181  if (child_mesh.top_simplex_type() != primitive_type) {
182  continue;
183  }
184  // logger().trace(
185  // "[{}->{}] Doing a child mesh",
186  // fmt::join(my_mesh.absolute_multi_mesh_id(), ","),
187  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","));
188  // get accessors to the maps
189  auto maps = get_map_accessors(my_mesh, child_data);
190  auto& [parent_to_child_accessor, child_to_parent_accessor] = maps;
191 
192  auto child_flag_accessor = child_mesh.get_const_flag_accessor(primitive_type);
193 
194 
195  for (const auto& [original_parent_gid, equivalent_parent_tuples] : simplices_to_update) {
196  // logger.trace()(
197  // "[{}->{}] Trying to update {}",
198  // fmt::join(my_mesh.absolute_multi_mesh_id(), ","),
199  // fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
200  // original_parent_gid);
201  // read off the original map's data
202  auto parent_to_child_data = Mesh::get_index_access(parent_to_child_accessor)
203  .const_vector_attribute(original_parent_gid);
204  // wmtk::attribute::TupleAccessor<wmtk::Mesh> tuple_accessor(m, int64_t_handle);
205 
206  // read off the data in the Tuple format
207  Tuple parent_tuple, child_tuple;
208  std::tie(parent_tuple, child_tuple) =
209  wmtk::multimesh::utils::vectors_to_tuples(parent_to_child_data);
210 
211  // If the parent tuple is valid, it means this parent-child pair has already been
212  // handled, so we can skip it
213  // If the parent tuple is invalid then there was no map so we can try the next cell
214  if (parent_tuple.is_null()) {
215  continue;
216  }
217 
218 
219  // check if the map is handled in the ear case
220  // if the child simplex is deleted then we can skip it
221  if (child_mesh.is_removed(child_tuple)) {
222  // spdlog::info("Perhaps incorrect tuple map {} => {}",
223  // wmtk::utils::TupleInspector::as_string(parent_tuple),
224  // wmtk::utils::TupleInspector::as_string(child_tuple));
225  // continue;
226  }
227  // assert(!child_mesh.is_removed(child_tuple));
228 
229  // Find a valid representation of this simplex representation of the original tupl
230  Tuple old_tuple;
231  std::optional<Tuple> old_tuple_opt = find_tuple_from_gid(
232  my_mesh,
233  my_mesh.top_simplex_type(),
234  equivalent_parent_tuples,
235  parent_tuple.m_global_cid);
236  // assert(old_tuple_opt.has_value());
237  if (!old_tuple_opt.has_value()) {
238  continue;
239  }
240  simplex::Simplex old_simplex = my_mesh.parent_scope(
241  [&] { return simplex::Simplex(my_mesh, primitive_type, old_tuple_opt.value()); });
242 
243  std::optional<Tuple> new_parent_shared_opt = find_valid_tuple(
244  my_mesh,
245  old_simplex,
246  original_parent_gid,
247  equivalent_parent_tuples,
248  split_cell_maps);
249 
250 
251  if (!new_parent_shared_opt.has_value()) {
252  // std::cout << "get skipped, someting is wrong?" << std::endl;
253  continue;
254  }
255  // assert(new_parent_shared_opt.has_value());
256 
257  Tuple new_parent_tuple_shared = new_parent_shared_opt.value();
258  // logger().trace(
259  // "{} => {} ==> {}",
260  // wmtk::utils::TupleInspector::as_string(old_simplex.tuple()),
261  // wmtk::utils::TupleInspector::as_string(parent_tuple),
262  // wmtk::utils::TupleInspector::as_string(child_tuple));
263 
265  old_simplex.tuple(),
266  parent_tuple,
267  my_mesh.top_simplex_type(),
268  new_parent_tuple_shared,
269  my_mesh.top_simplex_type());
270  assert(my_mesh.is_valid(parent_tuple));
271  assert(child_mesh.is_valid(child_tuple));
272 
273 
275  parent_to_child_accessor,
276  child_to_parent_accessor,
277  parent_tuple,
278  child_tuple);
279  }
280  }
281 }
283  Mesh& my_mesh,
284  const simplex::Simplex& old_simplex,
285  const int64_t old_gid,
286  const std::vector<Tuple>& equivalent_parent_tuples,
287  const std::vector<std::tuple<int64_t, std::array<int64_t, 2>>>& split_cell_maps) const
288 {
289  // if old gid was one of the originals then do tuple
290  // otherwise just find some random tuple that still exists
291 
292  std::optional<Tuple> split_attempt = find_valid_tuple_from_split(
293  my_mesh,
294  old_simplex,
295  old_gid,
296  equivalent_parent_tuples,
297  split_cell_maps);
298  if (!split_attempt.has_value()) {
299  split_attempt = find_valid_tuple_from_alternatives(
300  my_mesh,
301  my_mesh.top_simplex_type(),
302  equivalent_parent_tuples);
303  }
304 
305  return split_attempt;
306 }
307 
308 
310  Mesh& my_mesh,
311  PrimitiveType primitive_type,
312  const std::vector<Tuple>& tuple_alternatives) const
313 {
314  auto parent_flag_accessor = my_mesh.get_const_flag_accessor(primitive_type);
315  // find a new sharer by finding a tuple that exists
316  auto it = std::find_if(
317  tuple_alternatives.begin(),
318  tuple_alternatives.end(),
319  [&](const Tuple& t) -> bool { return !my_mesh.is_removed(t); });
320  if (it != tuple_alternatives.end()) {
321  return *it;
322  } else {
323  return std::optional<Tuple>{};
324  }
325 }
326 
328  Mesh& my_mesh,
329  const simplex::Simplex& old_simplex,
330  const int64_t old_simplex_gid,
331  const std::vector<Tuple>& tuple_alternatives,
332  const std::vector<std::tuple<int64_t, std::array<int64_t, 2>>>& split_cell_maps) const
333 {
334  const Tuple& old_tuple = old_simplex.tuple();
335  const PrimitiveType primitive_type = old_simplex.primitive_type();
336 
337  for (const auto& [old_cid, new_cids] : split_cell_maps) {
338  if (old_cid != old_tuple.m_global_cid) {
339  continue;
340  }
341 
342  auto old_tuple_opt =
343  find_tuple_from_gid(my_mesh, my_mesh.top_simplex_type(), tuple_alternatives, old_cid);
344  // assert(old_tuple_opt.has_value());
345  if (!(old_tuple_opt.has_value())) {
346  return std::optional<Tuple>{};
347  }
348 
349  const Tuple& old_cid_tuple = old_tuple_opt.value();
350  for (const int64_t new_cid : new_cids) {
351  Tuple tuple(
352  old_cid_tuple.m_local_vid,
353  old_cid_tuple.m_local_eid,
354  old_cid_tuple.m_local_fid,
355  new_cid);
356 
357 
358  if (my_mesh.is_valid(tuple) && !my_mesh.is_removed(tuple) &&
359  old_simplex_gid == my_mesh.id(tuple, primitive_type)) {
360  return tuple;
361  }
362  }
363  }
364  return std::optional<Tuple>{};
365 }
366 
368  const Mesh& my_mesh,
369  PrimitiveType primitive_type,
370  const std::vector<Tuple>& tuples,
371  int64_t gid)
372 {
373  // logger().trace("Finding gid {}", gid);
374 
375  auto it = std::find_if(tuples.begin(), tuples.end(), [&](const Tuple& t) -> bool {
376  return (gid == my_mesh.id(t, primitive_type));
377  });
378  if (it == tuples.end()) {
379  // logger().trace("failed to find tuple");
380  return std::optional<Tuple>{};
381  } else {
382  // logger().trace("got tuple");
383  return *it;
384  }
385 }
387  const wmtk::attribute::Accessor<int64_t>& parent_to_child,
388  int64_t parent_gid)
389 {
390  // look at src/wmtk/multimesh/utils/tuple_map_attribute_io.cpp to see what index global_cid gets mapped to)
391  // 2 is the size of a tuple is 2 longs, global_cid currently gets written to position 3
392  // 5 is the size of a tuple is 5 longs, global_cid currently gets written to position 3
393  return Mesh::get_index_access(parent_to_child)
394  .vector_attribute(parent_gid)(
395  wmtk::multimesh::utils::TUPLE_SIZE + wmtk::multimesh::utils::GLOBAL_ID_INDEX);
396 }
398  const wmtk::attribute::Accessor<int64_t>& child_to_parent,
399  int64_t child_gid)
400 {
401  // look at src/wmtk/multimesh/utils/tuple_map_attribute_io.cpp to see what index global_cid gets mapped to)
402  // 2 is the size of a tuple is 2 longs, global_cid currently gets written to position 3
403  // 5 is the size of a tuple is 5 longs, global_cid currently gets written to position 2
404  return Mesh::get_index_access(child_to_parent)
405  .vector_attribute(child_gid)(
406  wmtk::multimesh::utils::TUPLE_SIZE + wmtk::multimesh::utils::GLOBAL_ID_INDEX);
407 }
408 
410  const wmtk::attribute::Accessor<int64_t>& child_to_parent,
411  int64_t child_gid)
412 {
413  // look at src/wmtk/multimesh/utils/tuple_map_attribute_io.cpp to see what index global_cid gets mapped to)
414 #if defined WMTK_DISABLE_COMPRESSED_MULTIMESH_TUPLE
415  // 5 is the size of a tuple is 5 longs, global_cid currently gets written to position 3
416  return Mesh::get_index_access(child_to_parent)
417  .vector_attribute(child_gid)(wmtk::multimesh::utils::TUPLE_SIZE + 2);
418 #else
419  // pick hte index that isn't teh global id index
420  const int64_t v =
421  Mesh::get_index_access(child_to_parent)
422  .vector_attribute(child_gid)(
423  wmtk::multimesh::utils::TUPLE_SIZE + (1 - wmtk::multimesh::utils::GLOBAL_ID_INDEX));
424  auto vptr = reinterpret_cast<const int8_t*>(&v);
425  return vptr[2];
426 #endif
427 }
428 
429 
430 } // namespace wmtk::multimesh
attribute::TypedAttributeHandle< T > get_attribute_handle_typed(const std::string &name, const PrimitiveType ptype) const
Definition: Mesh.hpp:927
int64_t id(const Tuple &tuple, PrimitiveType type) const
return the global id of the Tuple of the given dimension
Definition: Mesh.hpp:1020
static auto & get_index_access(attribute::Accessor< T, MeshType > &attr)
Definition: Mesh.hpp:823
const attribute::Accessor< char > get_const_flag_accessor(PrimitiveType type) const
Definition: Mesh.cpp:162
multimesh::MultiMeshManager m_multi_mesh_manager
Definition: Mesh.hpp:841
virtual bool is_valid(const Tuple &tuple) const
check validity of tuple including its hash
Definition: Mesh.cpp:112
PrimitiveType top_simplex_type() const
Definition: Mesh.hpp:996
decltype(auto) parent_scope(Functor &&f, Args &&... args) const
Evaluate the passed in function inside the parent scope.
bool is_removed(const Tuple &tuple) const
Definition: Mesh.cpp:117
attribute::AttributeManager m_attribute_manager
Definition: Mesh.hpp:839
bool is_null() const
Checks if a tuple is "null". This merely implies the global index is -1.
Definition: Tuple.hxx:40
int8_t m_local_vid
Definition: Tuple.hpp:47
int8_t m_local_eid
Definition: Tuple.hpp:48
int64_t m_global_cid
Definition: Tuple.hpp:46
int8_t m_local_fid
Definition: Tuple.hpp:49
void set_name(const TypedAttributeHandle< T > &attr, const std::string &name)
Implementation details for how the Mesh class implements multiple meshes.
const std::vector< ChildData > & children() const
static int64_t child_global_cid(const wmtk::attribute::Accessor< int64_t > &parent_to_child, int64_t parent_gid)
std::optional< Tuple > find_valid_tuple_from_split(Mesh &my_mesh, const simplex::Simplex &old_simplex, const int64_t old_gid, const std::vector< Tuple > &tuple_alternatives, const std::vector< std::tuple< int64_t, std::array< int64_t, 2 >>> &split_cell_maps) const
static int64_t parent_local_fid(const wmtk::attribute::Accessor< int64_t > &child_to_parent, int64_t child_gid)
std::vector< ChildData > m_children
std::optional< Tuple > find_valid_tuple_from_alternatives(Mesh &my_mesh, PrimitiveType primitive_type, const std::vector< Tuple > &tuple_alternatives) const
static int64_t parent_global_cid(const wmtk::attribute::Accessor< int64_t > &child_to_parent, int64_t child_gid)
static std::string parent_to_child_map_attribute_name(int64_t index)
void update_child_handles(Mesh &my_mesh)
Clean up child data after deleting attributes.
std::array< wmtk::attribute::Accessor< int64_t >, 2 > get_map_accessors(Mesh &my_mesh, ChildData &c)
void update_map_tuple_hashes(Mesh &my_mesh, PrimitiveType primitive_type, const std::vector< std::tuple< int64_t, std::vector< Tuple >>> &simplices_to_update, const std::vector< std::tuple< int64_t, std::array< int64_t, 2 >>> &split_cell_maps={})
static std::optional< Tuple > find_tuple_from_gid(const Mesh &my_mesh, PrimitiveType primitive_type, const std::vector< Tuple > &tuples, int64_t gid)
std::optional< Tuple > find_valid_tuple(Mesh &my_mesh, const simplex::Simplex &old_simplex, const int64_t old_gid, const std::vector< Tuple > &tuple_alternatives, const std::vector< std::tuple< int64_t, std::array< int64_t, 2 >>> &split_cell_maps={}) const
void update_maps_from_edge_operation(Mesh &my_mesh, PrimitiveType primitive_type, const operations::EdgeOperationData &operation_data)
std::variant< std::unique_ptr< internal::SplitAlternateFacetData >, std::unique_ptr< internal::CollapseAlternateFacetData > > m_op_data
const Tuple & tuple() const
Definition: Simplex.hpp:53
PrimitiveType primitive_type() const
Definition: Simplex.hpp:51
std::tuple< Tuple, Tuple > vectors_to_tuples(const Eigen::Ref< const TwoTupleVector > &v)
Tuple transport_tuple(const Tuple &base_source, const Tuple &base_target, PrimitiveType base_primitive_type, const Tuple &source, PrimitiveType primitive_type)
void symmetric_write_tuple_map_attributes(wmtk::attribute::Accessor< int64_t, MeshA > &a_to_b, wmtk::attribute::Accessor< int64_t, MeshB > &b_to_a, const Tuple &a_tuple, const Tuple &b_tuple)
spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:58