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