Wildmeshing Toolkit
Loading...
Searching...
No Matches
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>
11#include <wmtk/utils/Logger.hpp>
12#include "MultiMeshManager.hpp"
16
17namespace wmtk::multimesh {
18
19namespace {
20
21
22Tuple find_valid_tuple(
23 const Mesh& my_mesh,
24 const wmtk::Tuple& tuple,
25 wmtk::PrimitiveType primitive_type,
27{
28 return std::visit(
29 [&](const auto& facet_data) -> wmtk::Tuple {
30 return facet_data->get_alternative(my_mesh.top_simplex_type(), tuple, primitive_type);
31 },
32 data.m_op_data);
33}
34
35} // namespace
36
37
38// TODO: verify why these names are necessary
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 // continue;
223 }
224 // assert(!child_mesh.is_removed(child_tuple));
225
226 // Find a valid representation of this simplex representation of the original tupl
227 Tuple old_tuple;
228 std::optional<Tuple> old_tuple_opt = find_tuple_from_gid(
229 my_mesh,
230 my_mesh.top_simplex_type(),
231 equivalent_parent_tuples,
232 parent_tuple.global_cid());
233 // assert(old_tuple_opt.has_value());
234 if (!old_tuple_opt.has_value()) {
235 continue;
236 }
237 simplex::Simplex old_simplex = my_mesh.parent_scope(
238 [&] { return simplex::Simplex(my_mesh, primitive_type, old_tuple_opt.value()); });
239
240 std::optional<Tuple> new_parent_shared_opt = find_valid_tuple(
241 my_mesh,
242 old_simplex,
243 original_parent_gid,
244 equivalent_parent_tuples,
245 split_cell_maps);
246
247
248 if (!new_parent_shared_opt.has_value()) {
249 // std::cout << "get skipped, someting is wrong?" << std::endl;
250 continue;
251 }
252 // assert(new_parent_shared_opt.has_value());
253
254 Tuple new_parent_tuple_shared = new_parent_shared_opt.value();
255
257 old_simplex.tuple(),
258 parent_tuple,
259 my_mesh.top_simplex_type(),
260 new_parent_tuple_shared,
261 my_mesh.top_simplex_type());
262 assert(my_mesh.is_valid(parent_tuple));
263 assert(child_mesh.is_valid(child_tuple));
264
265
267 parent_to_child_accessor,
268 child_to_parent_accessor,
269 parent_tuple,
270 child_tuple);
271 }
272 }
273}
275 Mesh& my_mesh,
276 const simplex::Simplex& old_simplex,
277 const int64_t old_gid,
278 const std::vector<Tuple>& equivalent_parent_tuples,
279 const std::vector<std::tuple<int64_t, std::array<int64_t, 2>>>& split_cell_maps) const
280{
281 // if old gid was one of the originals then do tuple
282 // otherwise just find some random tuple that still exists
283
284 std::optional<Tuple> split_attempt = find_valid_tuple_from_split(
285 my_mesh,
286 old_simplex,
287 old_gid,
288 equivalent_parent_tuples,
289 split_cell_maps);
290 if (!split_attempt.has_value()) {
292 my_mesh,
293 my_mesh.top_simplex_type(),
294 equivalent_parent_tuples);
295 }
296
297 return split_attempt;
298}
299
300
302 Mesh& my_mesh,
303 PrimitiveType primitive_type,
304 const std::vector<Tuple>& tuple_alternatives) const
305{
306 //auto parent_flag_accessor = my_mesh.get_const_flag_accessor(primitive_type);
307 // find a new sharer by finding a tuple that exists
308 auto it = std::find_if(
309 tuple_alternatives.begin(),
310 tuple_alternatives.end(),
311 [&](const Tuple& t) -> bool { return !my_mesh.is_removed(t); });
312 if (it != tuple_alternatives.end()) {
313 return *it;
314 } else {
315 return std::optional<Tuple>{};
316 }
317}
318
320 Mesh& my_mesh,
321 const simplex::Simplex& old_simplex,
322 const int64_t old_simplex_gid,
323 const std::vector<Tuple>& tuple_alternatives,
324 const std::vector<std::tuple<int64_t, std::array<int64_t, 2>>>& split_cell_maps) const
325{
326 const Tuple& old_tuple = old_simplex.tuple();
327 const PrimitiveType primitive_type = old_simplex.primitive_type();
328
329 for (const auto& [old_cid, new_cids] : split_cell_maps) {
330 if (old_cid != old_tuple.global_cid()) {
331 continue;
332 }
333
334 auto old_tuple_opt =
335 find_tuple_from_gid(my_mesh, my_mesh.top_simplex_type(), tuple_alternatives, old_cid);
336 // assert(old_tuple_opt.has_value());
337 if (!(old_tuple_opt.has_value())) {
338 return std::optional<Tuple>{};
339 }
340
341 const Tuple& old_cid_tuple = old_tuple_opt.value();
342 for (const int64_t new_cid : new_cids) {
343 Tuple tuple(
344 old_cid_tuple.local_vid(),
345 old_cid_tuple.local_eid(),
346 old_cid_tuple.local_fid(),
347 new_cid);
348
349
350 if (my_mesh.is_valid(tuple) && !my_mesh.is_removed(tuple) &&
351 old_simplex_gid == my_mesh.id(tuple, primitive_type)) {
352 return tuple;
353 }
354 }
355 }
356 return std::optional<Tuple>{};
357}
358
360 const Mesh& my_mesh,
361 PrimitiveType primitive_type,
362 const std::vector<Tuple>& tuples,
363 int64_t gid)
364{
365 // logger().trace("Finding gid {}", gid);
366
367 auto it = std::find_if(tuples.begin(), tuples.end(), [&](const Tuple& t) -> bool {
368 return (gid == my_mesh.id(t, primitive_type));
369 });
370 if (it == tuples.end()) {
371 // logger().trace("failed to find tuple");
372 return std::optional<Tuple>{};
373 } else {
374 // logger().trace("got tuple");
375 return *it;
376 }
377}
379 const wmtk::attribute::Accessor<int64_t>& parent_to_child,
380 int64_t parent_gid)
381{
382 // look at src/wmtk/multimesh/utils/tuple_map_attribute_io.cpp to see what index global_cid gets mapped to)
383 // 2 is the size of a tuple is 2 longs, global_cid currently gets written to position 3
384 // 5 is the size of a tuple is 5 longs, global_cid currently gets written to position 3
385 return Mesh::get_index_access(parent_to_child)
386 .const_vector_attribute(parent_gid)(
387 wmtk::multimesh::utils::TUPLE_SIZE + wmtk::multimesh::utils::GLOBAL_ID_INDEX);
388}
390 const wmtk::attribute::Accessor<int64_t>& child_to_parent,
391 int64_t child_gid)
392{
393 // look at src/wmtk/multimesh/utils/tuple_map_attribute_io.cpp to see what index global_cid gets mapped to)
394 // 2 is the size of a tuple is 2 longs, global_cid currently gets written to position 3
395 // 5 is the size of a tuple is 5 longs, global_cid currently gets written to position 2
396 return Mesh::get_index_access(child_to_parent)
397 .const_vector_attribute(child_gid)(
398 wmtk::multimesh::utils::TUPLE_SIZE + wmtk::multimesh::utils::GLOBAL_ID_INDEX);
399}
400
402 const wmtk::attribute::Accessor<int64_t>& child_to_parent,
403 int64_t child_gid)
404{
405 // look at src/wmtk/multimesh/utils/tuple_map_attribute_io.cpp to see what index global_cid gets mapped to)
406#if defined WMTK_DISABLE_COMPRESSED_MULTIMESH_TUPLE
407 // 5 is the size of a tuple is 5 longs, global_cid currently gets written to position 3
408 return Mesh::get_index_access(child_to_parent)
409 .const_vector_attribute(child_gid)(wmtk::multimesh::utils::TUPLE_SIZE + 2);
410#else
411 // pick hte index that isn't teh global id index
412 const int64_t v =
413 Mesh::get_index_access(child_to_parent)
414 .const_vector_attribute(child_gid)(
415 wmtk::multimesh::utils::TUPLE_SIZE + (1 - wmtk::multimesh::utils::GLOBAL_ID_INDEX));
416 auto vptr = reinterpret_cast<const int8_t*>(&v);
417 return vptr[2];
418#endif
419}
420
421
422} // namespace wmtk::multimesh
static auto & get_index_access(attribute::Accessor< T, MeshType > &attr)
Definition Mesh.hpp:811
attribute::TypedAttributeHandle< T > get_attribute_handle_typed(const std::string &name, const PrimitiveType ptype) const
Definition Mesh.hpp:911
int64_t id(const Tuple &tuple, PrimitiveType type) const
return the global id of the Tuple of the given dimension
Definition Mesh.hpp:1010
multimesh::MultiMeshManager m_multi_mesh_manager
Definition Mesh.hpp:829
virtual bool is_valid(const Tuple &tuple) const
check validity of tuple including its hash
Definition Mesh.cpp:113
PrimitiveType top_simplex_type() const
Definition Mesh.hpp:980
decltype(auto) parent_scope(Functor &&f, Args &&... args) const
Evaluate the passed in function inside the parent scope.
Definition Mesh.hpp:939
bool is_removed(const Tuple &tuple) const
Definition Mesh.cpp:126
attribute::AttributeManager m_attribute_manager
Definition Mesh.hpp:827
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
bool is_null() const
Checks if a tuple is "null". This merely implies the global index is -1.
Definition Tuple.hxx:41
int8_t local_vid() const
Definition Tuple.hxx:52
int8_t local_fid() const
Definition Tuple.hxx:62
int8_t local_eid() const
Definition Tuple.hxx:57
int64_t global_cid() const
Definition Tuple.hxx:47
An Accessor that uses tuples for accessing attributes instead of indices.
Definition Accessor.hpp:44
void set_name(const TypedAttributeHandle< T > &attr, const std::string &name)
Implementation details for how the Mesh class implements multiple meshes.
static int64_t child_global_cid(const wmtk::attribute::Accessor< int64_t > &parent_to_child, int64_t parent_gid)
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
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_global_cid(const wmtk::attribute::Accessor< int64_t > &child_to_parent, int64_t child_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
static std::string parent_to_child_map_attribute_name(int64_t index)
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={})
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)
const std::vector< ChildData > & children() const
static std::optional< Tuple > find_tuple_from_gid(const Mesh &my_mesh, PrimitiveType primitive_type, const std::vector< Tuple > &tuples, int64_t gid)
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