Wildmeshing Toolkit
Loading...
Searching...
No Matches
MultiMeshManager.cpp
Go to the documentation of this file.
2#include <cassert>
4//#include <fmt/ranges.h>
5#include <functional>
6#include <wmtk/Mesh.hpp>
13#include <wmtk/utils/Logger.hpp>
18
19namespace wmtk::multimesh {
20
21namespace {} // namespace
22
23
25{
26 for (auto& data : m_children) {
27 auto& m = *data.mesh;
28 m.m_multi_mesh_manager.m_parent = nullptr;
29 m.m_multi_mesh_manager.m_child_id = -1;
30 // TODO: delete attributes
31 }
32
33 m_children.clear();
34}
35
37 const Mesh& source_mesh,
38 const Mesh& target_mesh,
39 const wmtk::attribute::Accessor<int64_t>& map_accessor,
40 const Tuple& source_tuple)
41{
42 assert(source_mesh.is_valid(source_tuple));
43
44 PrimitiveType source_mesh_primitive_type = source_mesh.top_simplex_type();
45 PrimitiveType target_mesh_primitive_type = target_mesh.top_simplex_type();
46 PrimitiveType min_primitive_type =
47 std::min(source_mesh_primitive_type, target_mesh_primitive_type);
48 Tuple source_mesh_target_tuple = source_tuple;
49 auto [source_mesh_base_tuple, target_mesh_base_tuple] =
50 multimesh::utils::read_tuple_map_attribute(map_accessor, source_tuple);
51
52 if (source_mesh_base_tuple.is_null() || target_mesh_base_tuple.is_null()) {
53 return Tuple(); // return null tuple
54 }
55
56 // assert(source_mesh.is_valid(source_mesh_base_tuple));
57 // assert(target_mesh.is_valid(target_mesh_base_tuple));
58
59
60 if (source_mesh_base_tuple.global_cid() != source_mesh_target_tuple.global_cid()) {
61 // guarantee that the source and target tuples refer to the same simplex
62 assert(source_mesh_primitive_type > target_mesh_primitive_type);
63 const std::vector<Tuple> equivalent_tuples = simplex::top_dimension_cofaces_tuples(
64 source_mesh,
65 simplex::Simplex(source_mesh, target_mesh_primitive_type, source_tuple));
66 for (const Tuple& t : equivalent_tuples) {
67 if (t.global_cid() == source_mesh_base_tuple.global_cid()) {
68 // specific for tet->edge
69 if (source_mesh_primitive_type == PrimitiveType::Tetrahedron &&
70 target_mesh_primitive_type == PrimitiveType::Edge) {
71 if (t.local_fid() == source_mesh_base_tuple.local_fid()) {
72 source_mesh_target_tuple = t;
73 break;
74 } else {
75 source_mesh_target_tuple =
77 break;
78 }
79 } else {
80 source_mesh_target_tuple = t;
81 break;
82 }
83 }
84 }
85 }
86
87 if (source_mesh_primitive_type == PrimitiveType::Tetrahedron &&
88 target_mesh_primitive_type == PrimitiveType::Edge) {
89 if (source_mesh_target_tuple.local_fid() != source_mesh_base_tuple.local_fid()) {
90 source_mesh_target_tuple =
91 source_mesh.switch_tuple(source_mesh_target_tuple, PrimitiveType::Triangle);
92 }
93 }
94
95 assert(
96 source_mesh_base_tuple.global_cid() ==
97 source_mesh_target_tuple
98 .global_cid()); // make sure that local tuple operations will find a valid sequence
99
100 // we want to repeat switches from source_base_tuple -> source_tuple to
101 // target_base _tuple -> return value
102 //
104 source_mesh_base_tuple,
105 source_mesh_target_tuple,
106 source_mesh_primitive_type,
107 target_mesh_base_tuple,
108 target_mesh_primitive_type);
109}
110
111
113 : m_has_child_mesh_in_dimension(dimension, false)
114{}
115
121
122// attribute directly hashes its "children" components so it overrides "child_hashes"
123std::map<std::string, const wmtk::utils::Hashable*> MultiMeshManager::child_hashables() const
124{
125 std::map<std::string, const wmtk::utils::Hashable*> ret;
126 for (const auto& c : m_children) {
127 assert(bool(c.mesh));
128 auto id = c.mesh->absolute_multi_mesh_id();
129 std::string name = fmt::format("child_map_[{}]", fmt::join(id, ","));
130 ret[name] = c.mesh.get();
131 }
132 return ret;
133}
134std::map<std::string, std::size_t> MultiMeshManager::child_hashes() const
135{
136 // default implementation pulls the child attributes (ie the attributes)
137 std::map<std::string, std::size_t> ret = wmtk::utils::MerkleTreeInteriorNode::child_hashes();
138 ret["child_id"] = m_child_id;
139
140 if (m_parent != nullptr) {
141 auto id = m_parent->absolute_multi_mesh_id();
142 ret["parent_map"] = wmtk::utils::vector_hash(id);
143 } else {
144 ret["parent_map"] = 0;
145 }
146
147
148 const std::hash<TypedAttributeHandle<int64_t>> attr_hasher;
149 ret["parent_map_handle"] = attr_hasher(map_to_parent_handle);
150 for (const auto& c : m_children) {
151 assert(bool(c.mesh));
152 auto id = c.mesh->absolute_multi_mesh_id();
153 std::string name = fmt::format("child_map_[{}]", fmt::join(id, ","));
154 ret[name] = attr_hasher(c.map_handle);
155 }
156 return ret;
157}
158
160{
161 return m_parent == nullptr;
162}
163
165{
166 if (is_root()) {
167 throw std::runtime_error("Tried to access the child id of a mesh that is in fact a root");
168 }
169 return m_child_id;
170}
171
172std::vector<int64_t> MultiMeshManager::absolute_id() const
173{
174 if (is_root()) {
175 return {};
176 } else {
178 id.emplace_back(m_child_id);
179 return id;
180 }
181}
182std::vector<int64_t> MultiMeshManager::relative_id(const Mesh& my_mesh, const Mesh& parent) const
183{
184 assert(is_child(my_mesh, parent));
185 if (&parent == &my_mesh) {
186 return {};
187 } else {
188 assert(!is_root());
190 id.emplace_back(m_child_id);
191 return id;
192 }
193}
194
195bool MultiMeshManager::is_child(const Mesh& my_mesh, const Mesh& parent_mesh) const
196{
197 if (&parent_mesh == &my_mesh) {
198 return true;
199 } else {
200 if (is_root()) {
201 return false;
202 } else {
203 return m_parent->m_multi_mesh_manager.is_child(*m_parent, parent_mesh);
204 }
205 }
206}
207
208
210 Mesh& my_mesh,
211 const std::shared_ptr<Mesh>& child_mesh_ptr,
212 const std::vector<std::array<Tuple, 2>>& child_tuple_my_tuple_map)
213{
214 assert((&my_mesh.m_multi_mesh_manager) == this);
215 assert(bool(child_mesh_ptr));
216
217 Mesh& child_mesh = *child_mesh_ptr;
218
219 const PrimitiveType child_primitive_type = child_mesh.top_simplex_type();
220 const int64_t new_child_id = int64_t(m_children.size());
221
223
224 auto child_to_parent_handle = child_mesh.register_attribute_typed<int64_t>(
226 child_primitive_type,
227 wmtk::multimesh::utils::TWO_TUPLE_SIZE,
228 false,
229 wmtk::multimesh::utils::DEFAULT_TUPLES_VALUES);
230
231 // TODO: make sure that this attribute doesnt already exist
232 auto parent_to_child_handle = my_mesh.register_attribute_typed<int64_t>(
234 child_primitive_type,
235 wmtk::multimesh::utils::TWO_TUPLE_SIZE,
236 false,
237 wmtk::multimesh::utils::DEFAULT_TUPLES_VALUES);
238
239
240 auto child_to_parent_accessor = child_mesh.create_accessor(child_to_parent_handle);
241 auto parent_to_child_accessor = my_mesh.create_accessor(parent_to_child_handle);
242
243
244 MultiMeshManager& child_manager = child_mesh.m_multi_mesh_manager;
245
246 // update on child_mesh
247 child_manager.map_to_parent_handle = child_to_parent_handle;
248 child_manager.m_child_id = new_child_id;
249 child_manager.m_parent = &my_mesh;
250
251 // update myself
252 m_children.emplace_back(ChildData{child_mesh_ptr, parent_to_child_handle});
253
254 // register maps
255 for (const auto& [child_tuple, my_tuple] : child_tuple_my_tuple_map) {
256 assert(my_mesh.is_valid(my_tuple));
257 assert(child_mesh_ptr->is_valid(child_tuple));
259 parent_to_child_accessor,
260 child_to_parent_accessor,
261 my_tuple,
262 child_tuple);
263 }
264}
265
267 Mesh& my_mesh,
268 const std::shared_ptr<Mesh>& child_mesh_ptr)
269{
270 Mesh& child_mesh = *child_mesh_ptr;
271
272 MultiMeshManager& child_manager = child_mesh.m_multi_mesh_manager;
273 MultiMeshManager& parent_manager = my_mesh.m_multi_mesh_manager;
274
275
276 auto& child_to_parent_handle = child_manager.map_to_parent_handle;
277
278 const int64_t child_id = child_manager.child_id();
279 ChildData& child_data = parent_manager.m_children[child_id];
280 auto& parent_to_child_handle = child_data.map_handle;
281
282 assert(child_data.mesh == child_mesh_ptr);
283 assert(child_manager.children()
284 .empty()); // The current implementation does not update the attributes properly for
285 // the case that the child also has children
286
287 // remove map attribute from parent
288 my_mesh.m_attribute_manager.get<int64_t>(child_mesh.top_simplex_type())
289 .remove_attributes({parent_to_child_handle.base_handle()});
290
291 // remove map attribute from child
292 child_mesh.m_attribute_manager.get<int64_t>(child_mesh.top_simplex_type())
293 .remove_attributes({child_to_parent_handle.base_handle()});
294
295 // set child_id to -1 --> make it a root
296 child_manager.m_child_id = -1;
297 // remove parent pointer
298 child_manager.m_parent = nullptr;
299
300 // remove child_data from parent
301 auto& children = parent_manager.m_children;
302 children.erase(children.begin() + child_id);
303
304 update_child_handles(my_mesh);
305}
306
307
308std::vector<wmtk::attribute::TypedAttributeHandle<int64_t>> MultiMeshManager::map_handles() const
309{
310 std::vector<wmtk::attribute::TypedAttributeHandle<int64_t>> handles;
312 handles.emplace_back(map_to_parent_handle);
313 }
314 for (const auto& cd : m_children) {
315 handles.emplace_back(cd.map_handle);
316 }
317 return handles;
318}
319
320/*
321 * TODO: It is the consumer's responsibility to generate the identity map via a utility function
322void MultiMeshManager::register_child_mesh(
323 Mesh& my_mesh,
324 std::shared_ptr<Mesh> child_mesh,
325 const std::vector<int64_t>& child_mesh_simplex_id_map)
326{
327 PrimitiveType map_type = child_mesh->top_simplex_type();
328 std::vector<std::array<Tuple, 2>> child_tuple_my_tuple_map;
329
330 for (int64_t child_cell_id = 0; child_cell_id < int64_t(child_mesh_simplex_id_map.size());
331 ++child_cell_id) {
332 int64_t parent_cell_id = child_mesh_simplex_id_map[child_cell_id];
333 child_tuple_my_tuple_map.push_back(
334 {child_mesh->tuple_from_id(map_type, child_cell_id),
335 my_mesh.tuple_from_id(map_type, parent_cell_id)});
336 }
337 register_child_mesh(my_mesh, child_mesh, child_tuple_my_tuple_map);
338}
339*/
340
341const Mesh& MultiMeshManager::get_root_mesh(const Mesh& my_mesh) const
342{
343 if (is_root()) {
344 return my_mesh;
345 } else {
347 }
348}
350{
351 if (is_root()) {
352 return my_mesh;
353 } else {
355 }
356}
357
359 const Mesh& my_mesh,
360 const std::vector<int64_t>& relative_id) const
361{
362 assert((&my_mesh.m_multi_mesh_manager) == this);
363
364 const Mesh* cur_mesh = &my_mesh;
365
366 for (auto it = relative_id.cbegin(); it != relative_id.cend(); ++it) {
367 // get the select ID from the child map
368 int64_t child_index = *it;
369 const ChildData& cd = cur_mesh->m_multi_mesh_manager.m_children.at(child_index);
370
371 cur_mesh = cd.mesh.get();
372
373 // the front id of the current mesh should be the child index from this iteration
374 assert(cur_mesh->m_multi_mesh_manager.m_child_id == child_index);
375 }
376
377 return *cur_mesh;
378}
379Mesh& MultiMeshManager::get_child_mesh(Mesh& my_mesh, const std::vector<int64_t>& relative_id)
380{
381 return const_cast<Mesh&>(get_child_mesh(const_cast<const Mesh&>(my_mesh), relative_id));
382}
383const Mesh& MultiMeshManager::get_mesh(const Mesh& my_mesh, const std::vector<int64_t>& absolute_id)
384 const
385{
386 const Mesh& root = get_root_mesh(my_mesh);
388}
389
390Mesh& MultiMeshManager::get_mesh(Mesh& my_mesh, const std::vector<int64_t>& absolute_id)
391{
392 Mesh& root = get_root_mesh(my_mesh);
394}
395std::vector<std::shared_ptr<Mesh>> MultiMeshManager::get_child_meshes() const
396{
397 std::vector<std::shared_ptr<Mesh>> ret;
398 ret.reserve(m_children.size());
399 for (const ChildData& cd : m_children) {
400 ret.emplace_back(cd.mesh);
401 }
402 return ret;
403}
404
405std::vector<simplex::Simplex> MultiMeshManager::map(
406 const Mesh& my_mesh,
407 const Mesh& other_mesh,
408 const simplex::Simplex& my_simplex) const
409{
410 const auto ret_tups = map_tuples(my_mesh, other_mesh, my_simplex);
412 other_mesh,
413 ret_tups,
414 my_simplex.primitive_type());
415}
416std::vector<simplex::Simplex> MultiMeshManager::lub_map(
417 const Mesh& my_mesh,
418 const Mesh& other_mesh,
419 const simplex::Simplex& my_simplex) const
420{
421 if (&my_mesh == &other_mesh) {
422 return {my_simplex};
423 }
424 const auto ret_tups = lub_map_tuples(my_mesh, other_mesh, my_simplex);
426 other_mesh,
427 ret_tups,
428 my_simplex.primitive_type());
429}
430
431std::pair<const Mesh&, Tuple> MultiMeshManager::map_up_to_tuples(
432 const Mesh& my_mesh,
433 const simplex::Simplex& my_simplex,
434 int64_t depth) const
435{
436 assert((&my_mesh.m_multi_mesh_manager) == this);
437 const PrimitiveType pt = my_simplex.primitive_type();
438
439 // get a root tuple by converting the tuple up parent meshes until root is found
440 Tuple cur_tuple = my_simplex.tuple();
441 const Mesh* cur_mesh = &my_mesh;
442 for (int64_t d = 0; d < depth; ++d) {
443 cur_tuple = cur_mesh->m_multi_mesh_manager.map_tuple_to_parent_tuple(*cur_mesh, cur_tuple);
444 cur_mesh = cur_mesh->m_multi_mesh_manager.m_parent;
445 assert(cur_mesh != nullptr);
446 }
447 // assert(cur_mesh->m_multi_mesh_manager
448 // .is_root()); // cur_mesh == nullptr if we just walked past the root node so we stop
449
450 // bieng lazy about how i set cur_mesh to nullptr above - could simplify the loop to optimize
451 return std::pair<const Mesh&, Tuple>(*cur_mesh, cur_tuple);
452}
453
455 const Mesh& my_mesh,
456 const simplex::Simplex& my_simplex,
457 const std::vector<int64_t>& relative_id) const
458{
459 assert((&my_mesh.m_multi_mesh_manager) == this);
460
461 const PrimitiveType pt = my_simplex.primitive_type();
462 // note that (cur_mesh, tuples) always match (i.e tuples are tuples from cur_mesh)
463 std::vector<Tuple> tuples;
464 tuples.emplace_back(my_simplex.tuple());
465 const Mesh* cur_mesh = &my_mesh;
466
467 for (auto it = relative_id.cbegin(); it != relative_id.cend(); ++it) {
468 // get the select ID from the child map
469 int64_t child_index = *it;
470 const ChildData& cd = cur_mesh->m_multi_mesh_manager.m_children.at(child_index);
471
472 // for every tuple we have try to collect all versions
473 std::vector<Tuple> new_tuples;
474 for (const Tuple& t : tuples) {
475 // get new tuples for every version that exists
476 std::vector<Tuple> n = cur_mesh->m_multi_mesh_manager.map_to_child_tuples(
477 *cur_mesh,
478 cd,
479 simplex::Simplex(*cur_mesh, pt, t));
480 // append to the current set of new tuples
481 new_tuples.insert(new_tuples.end(), n.begin(), n.end());
482 }
483 // update the (mesh,tuples) pair
484 tuples = std::move(new_tuples);
485 cur_mesh = cd.mesh.get();
486
487 // the front id of the current mesh should be the child index from this iteration
488 assert(cur_mesh->m_multi_mesh_manager.m_child_id == child_index);
489 }
490
491 // visitor.map(equivalent_tuples, my_simplex.primitive_type());
492
493 return tuples;
494}
495
497 const Mesh& my_mesh,
498 const Mesh& other_mesh,
499 const simplex::Simplex& my_simplex) const
500{
501 const auto my_id = absolute_id();
502 const auto other_id = other_mesh.absolute_multi_mesh_id();
503
504 int64_t depth = my_id.size();
505
506 auto [root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
507 const simplex::Simplex simplex(root_ref, my_simplex.primitive_type(), tuple);
508
509 return root_ref.m_multi_mesh_manager.map_down_relative_tuples(root_ref, simplex, other_id);
510}
511
513 const Mesh& my_mesh,
514 const Mesh& other_mesh,
515 const simplex::Simplex& my_simplex) const
516{
517 if (&my_mesh == &other_mesh) {
518 return {my_simplex.tuple()};
519 }
520 const auto my_id = absolute_id();
521 const auto other_id = other_mesh.absolute_multi_mesh_id();
522 const auto lub_id = least_upper_bound_id(my_id, other_id);
523
524 int64_t depth = my_id.size() - lub_id.size();
525
526 auto [local_root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
527 assert(other_mesh.m_multi_mesh_manager.is_child(other_mesh, local_root_ref));
528
529 const simplex::Simplex simplex(local_root_ref, my_simplex.primitive_type(), tuple);
530
531 auto other_relative_id = relative_id(lub_id, other_id);
532 return local_root_ref.m_multi_mesh_manager.map_down_relative_tuples(
533 local_root_ref,
534 simplex,
535 other_relative_id);
536}
537
539 const Mesh& my_mesh,
540 const simplex::Simplex& my_simplex) const
541{
542 return simplex::Simplex(my_simplex.primitive_type(), map_to_root_tuple(my_mesh, my_simplex));
543}
544
546 const
547{
548 const Tuple t = map_tuple_to_root_tuple(my_mesh, my_simplex.tuple());
549 assert(get_root_mesh(my_mesh).is_valid(t));
550 return t;
551}
552Tuple MultiMeshManager::map_tuple_to_root_tuple(const Mesh& my_mesh, const Tuple& my_tuple) const
553{
554 assert(&my_mesh.m_multi_mesh_manager == this);
555 if (my_mesh.m_multi_mesh_manager.is_root()) {
556 assert(my_mesh.is_valid(my_tuple));
557 return my_tuple;
558 } else {
559 const Tuple ptup = map_tuple_to_parent_tuple(my_mesh, my_tuple);
560 assert(m_parent->is_valid(ptup));
562 }
563}
564
565
567 const Mesh& my_mesh,
568 const simplex::Simplex& my_simplex) const
569{
570 return simplex::Simplex(
571 my_simplex.primitive_type(),
572 map_tuple_to_parent_tuple(my_mesh, my_simplex.tuple()));
573}
575 const
576{
577 return map_tuple_to_parent_tuple(my_mesh, my_simplex.tuple());
578}
579
580Tuple MultiMeshManager::map_tuple_to_parent_tuple(const Mesh& my_mesh, const Tuple& my_tuple) const
581{
582 assert((&my_mesh.m_multi_mesh_manager) == this);
583 assert(!is_root());
584
585 const Mesh& parent_mesh = *m_parent;
586
587 const auto& map_handle = map_to_parent_handle;
588 // assert(!map_handle.is_null());
589
590 auto map_accessor = my_mesh.create_const_accessor(map_handle);
591 return map_tuple_between_meshes(my_mesh, parent_mesh, map_accessor, my_tuple);
592}
593
594
596 const Mesh& my_mesh,
597 const ChildData& child_data,
598 const simplex::Simplex& my_simplex) const
599{
600 assert((&my_mesh.m_multi_mesh_manager) == this);
601
602 const Mesh& child_mesh = *child_data.mesh;
603 if (child_mesh.top_simplex_type() < my_simplex.primitive_type()) {
604 return {};
605 }
606 const auto map_handle = child_data.map_handle;
607 // we will overwrite these tuples inline with the mapped ones while running down the map
608 // functionalities
609
610 std::vector<Tuple> tuples = simplex::cofaces_single_dimension_tuples(
611 my_mesh,
612 my_simplex,
613 child_mesh.top_simplex_type());
614
615 /*
616 get all tuples of child mesh top simplex type that contain my_simplex
617 */
618
619 auto map_accessor = my_mesh.create_const_accessor(map_handle);
620 for (Tuple& tuple : tuples) {
621 tuple = map_tuple_between_meshes(my_mesh, child_mesh, map_accessor, tuple);
622 }
623 tuples.erase(
624 std::remove_if(
625 tuples.begin(),
626 tuples.end(),
627 [](const Tuple& t) -> bool { return t.is_null(); }),
628 tuples.end());
629 tuples =
630 wmtk::simplex::utils::make_unique_tuples(child_mesh, tuples, my_simplex.primitive_type());
631
632 return tuples;
633}
634
636 const Mesh& my_mesh,
637 const Mesh& child_mesh,
638 const simplex::Simplex& my_simplex) const
639{
640 return map_to_child_tuples(my_mesh, child_mesh.m_multi_mesh_manager.child_id(), my_simplex);
641}
642
644 const Mesh& my_mesh,
645 int64_t child_id,
646 const simplex::Simplex& my_simplex) const
647{
648 // this is just to do a little redirection for simpplifying map_to_child (and potentially for a
649 // visitor pattern)
650 return map_to_child_tuples(my_mesh, m_children.at(child_id), my_simplex);
651}
652
653std::vector<simplex::Simplex> MultiMeshManager::map_to_child(
654 const Mesh& my_mesh,
655 const Mesh& child_mesh,
656 const simplex::Simplex& my_simplex) const
657{
658 auto tuples = map_to_child_tuples(my_mesh, child_mesh, my_simplex);
659
661 child_mesh,
662 tuples,
663 my_simplex.primitive_type());
664}
665
666
668 const Mesh& parent,
669 const Mesh& child,
670 const std::vector<int64_t>& parent_simplices)
671{
672 PrimitiveType primitive_type = parent.top_simplex_type();
673#if !defined(NDEBUG)
674 if (primitive_type != child.top_simplex_type()) {
675 throw std::runtime_error(
676 "Cannot use same_simplex_dimension_bijection on meshes with simplex dimensions");
677 }
678#endif
679
680 int64_t size = child.capacity(primitive_type);
681 assert(size == int64_t(parent_simplices.size()));
682 std::vector<std::array<Tuple, 2>> ret;
683 ret.reserve(size);
684
685 auto parent_flag_accessor = parent.get_const_flag_accessor(primitive_type);
686 auto child_flag_accessor = child.get_const_flag_accessor(primitive_type);
687
688 for (int64_t index = 0; index < size; ++index) {
689 const Tuple ct = child.tuple_from_id(primitive_type, index);
690 const Tuple pt = parent.tuple_from_id(primitive_type, parent_simplices.at(index));
691 if (!(parent_flag_accessor.is_active(pt))) {
692 continue;
693 }
694 if (!(child_flag_accessor.is_active(ct))) {
695 continue;
696 }
697
698 ret.emplace_back(std::array<Tuple, 2>{{ct, pt}});
699 }
700 return ret;
701}
702
704{
705 return fmt::format("map_to_child_{}", index);
706}
707std::array<wmtk::attribute::Accessor<int64_t>, 2> MultiMeshManager::get_map_accessors(
708 Mesh& my_mesh,
709 ChildData& c)
710{
711 Mesh& child_mesh = *c.mesh;
712 const auto& child_to_parent_handle = child_mesh.m_multi_mesh_manager.map_to_parent_handle;
713 const auto& parent_to_child_handle = c.map_handle;
714
715
716 return std::array<wmtk::attribute::Accessor<int64_t>, 2>{
717 {my_mesh.create_accessor(parent_to_child_handle),
718 child_mesh.create_accessor(child_to_parent_handle)}};
719}
720std::array<const wmtk::attribute::Accessor<int64_t>, 2> MultiMeshManager::get_map_const_accessors(
721 const Mesh& my_mesh,
722 const ChildData& c) const
723{
724 const Mesh& child_mesh = *c.mesh;
725 const auto& child_to_parent_handle = child_mesh.m_multi_mesh_manager.map_to_parent_handle;
726 const auto& parent_to_child_handle = c.map_handle;
727
728
729 return std::array<const wmtk::attribute::Accessor<int64_t>, 2>{
730 {my_mesh.create_const_accessor(parent_to_child_handle),
731 child_mesh.create_const_accessor(child_to_parent_handle)}};
732}
734{
735 return "map_to_parent";
736}
737
738
739// remove after bug fix
740void MultiMeshManager::check_map_valid(const Mesh& my_mesh) const
741{
742 for (int64_t index = 0; index < int64_t(children().size()); ++index) {
743 const auto& child_data = children()[index];
744 assert(bool(child_data.mesh));
745 assert(child_data.mesh->absolute_multi_mesh_id().front() == index);
746 check_child_map_valid(my_mesh, child_data);
747 }
748}
749
750void MultiMeshManager::check_child_map_valid(const Mesh& my_mesh, const ChildData& child_data) const
751{
752 const Mesh& child_mesh = *child_data.mesh;
753 const auto parent_to_child_handle = child_data.map_handle;
754 PrimitiveType map_type = child_mesh.top_simplex_type();
755
756 const std::string c_to_p_name = child_to_parent_map_attribute_name();
757
758 assert(child_mesh.has_attribute<int64_t>(c_to_p_name, map_type));
759 auto child_to_parent_handle =
760 child_mesh.get_attribute_handle<int64_t>(c_to_p_name, map_type).as<int64_t>();
761 auto child_cell_flag_accessor = child_mesh.get_flag_accessor(map_type);
762
763 auto all_child_tuples = child_mesh.get_all(map_type);
764
765 for (const Tuple& child_tuple : all_child_tuples) {
766 logger().debug(
767 "[{} -> {}] Checking child tuple {}",
768 fmt::join(absolute_id(), ","),
769 fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
770 child_tuple.as_string());
771 // 1. test if all maps in child_mesh exisits
772 auto [child_tuple_from_child, parent_tuple_from_child] =
774 child_mesh,
775 child_to_parent_handle,
776 child_tuple);
777
778 // 2. test if tuples in maps are valid (and up_to_date)
779 {
780 logger().debug(
781 "[{} -> {}] Checking asserts from child {} {} (input tuple was {})",
782 fmt::join(absolute_id(), ","),
783 fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
784 child_tuple_from_child.as_string(),
785 child_tuple_from_child.as_string(),
786 child_tuple.as_string());
787 assert(child_mesh.is_valid(child_tuple_from_child));
788 assert(child_mesh.is_valid(child_tuple_from_child));
789 assert(my_mesh.is_valid(parent_tuple_from_child));
790 }
791
792 // 3. test if map is symmetric
793 {
794 auto [parent_tuple_from_parent, child_tuple_from_parent] =
796 my_mesh,
797 parent_to_child_handle,
798 parent_tuple_from_child);
799 logger().debug(
800 "[{} -> {}] Checking asserts from child {} {}",
801 fmt::join(absolute_id(), ","),
802 fmt::join(child_mesh.absolute_multi_mesh_id(), ","),
803 parent_tuple_from_parent.as_string(),
804 child_tuple_from_parent.as_string());
805
806 assert(
807 (child_tuple_from_child == child_tuple_from_parent &&
808 parent_tuple_from_child == parent_tuple_from_parent));
809 }
810
811 // 4. test switch_top_simplex operation
812 // for 4, current code support only mapping between triangle meshes
813 if (map_type == PrimitiveType::Triangle &&
815 Tuple cur_child_tuple = child_tuple_from_child;
816 Tuple cur_parent_tuple = parent_tuple_from_child;
817
818 auto child_to_parent_accessor =
819 child_mesh.create_const_accessor(child_to_parent_handle);
820 for (int i = 0; i < 3; i++) {
821 if (!child_mesh.is_boundary(PrimitiveType::Edge, cur_child_tuple)) {
822 assert(!my_mesh.is_boundary(PrimitiveType::Edge, cur_parent_tuple));
823
824#ifndef NDEBUG
825 Tuple child_tuple_opp =
826 child_mesh.switch_tuple(cur_child_tuple, PrimitiveType::Triangle);
827 Tuple parent_tuple_opp =
828 my_mesh.switch_tuple(cur_parent_tuple, PrimitiveType::Triangle);
829 assert(
830 parent_tuple_opp == map_tuple_between_meshes(
831 child_mesh,
832 my_mesh,
833 child_to_parent_accessor,
834 child_tuple_opp));
835#endif
836 }
837 cur_child_tuple = child_mesh.switch_tuples(
838 cur_child_tuple,
840 cur_parent_tuple = my_mesh.switch_tuples(
841 cur_parent_tuple,
843 }
844 } else if (
845 map_type == PrimitiveType::Edge &&
847 if (!my_mesh.is_boundary(PrimitiveType::Edge, parent_tuple_from_child)) {
848 auto parent_to_child_accessor =
849 my_mesh.create_const_accessor(parent_to_child_handle);
850#ifndef NDEBUG
851 const Tuple parent_tuple_opp =
852 my_mesh.switch_tuple(parent_tuple_from_child, PrimitiveType::Triangle);
853 assert(
854 child_tuple_from_child == map_tuple_between_meshes(
855 my_mesh,
856 child_mesh,
857 parent_to_child_accessor,
858 parent_tuple_opp));
859#endif
860 }
861 } else {
862 // TODO: implement other cases
863 continue;
864 }
865 }
866}
867
868
870 const std::vector<int64_t>& a,
871 const std::vector<int64_t>& b)
872{
873 std::vector<int64_t> ret;
874 size_t size = std::min(a.size(), b.size());
875 for (size_t j = 0; j < size; ++j) {
876 if (a[j] == b[j]) {
877 ret.emplace_back(a[j]);
878 } else {
879 break;
880 }
881 }
882 return ret;
883}
884std::vector<int64_t> MultiMeshManager::relative_id(
885 const std::vector<int64_t>& parent,
886 const std::vector<int64_t>& child)
887{
888 assert(is_child(child, parent));
889 std::vector<int64_t> ret;
890 std::copy(child.begin() + parent.size(), child.end(), std::back_inserter(ret));
891 return ret;
892}
894 const std::vector<int64_t>& child,
895 const std::vector<int64_t>& parent)
896{
897 if (parent.size() > child.size()) {
898 return false;
899 }
900 for (size_t j = 0; j < parent.size(); ++j) {
901 if (parent[j] != child[j]) {
902 return false;
903 }
904 }
905 return true;
906}
907
908void MultiMeshManager::serialize(MeshWriter& writer, const Mesh* local_root) const
909{
910 for (const auto& c : m_children) {
911 c.mesh->serialize(writer, local_root);
912 }
913}
914
916{
917 for (const bool c : m_has_child_mesh_in_dimension) {
918 if (c) {
919 return true;
920 }
921 }
922 return false;
923}
924
926 const Mesh& my_mesh,
927 const Mesh& other_mesh,
928 const simplex::Simplex& my_simplex) const
929{
930 auto& root = my_mesh.get_multi_mesh_root();
931 const simplex::Simplex root_simplex(
932 root,
933 my_simplex.primitive_type(),
934 map_to_root_tuple(my_mesh, my_simplex));
935 return root.m_multi_mesh_manager.can_map_child(root, other_mesh, root_simplex);
936}
938 const Mesh& my_mesh,
939 const Mesh& other_mesh,
940 const simplex::Simplex& my_simplex) const
941{
942 if (my_simplex.primitive_type() > other_mesh.top_simplex_type()) {
943 return false;
944 }
945 const auto my_id = absolute_id();
946 const auto other_id = other_mesh.absolute_multi_mesh_id();
947
948 int64_t depth = my_id.size();
949
950 auto [root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
951 const simplex::Simplex simplex(root_ref, my_simplex.primitive_type(), tuple);
952
953 return !root_ref.m_multi_mesh_manager.map_down_relative_tuples(root_ref, simplex, other_id)
954 .empty();
955}
956} // namespace wmtk::multimesh
std::vector< int64_t > absolute_multi_mesh_id() const
returns a unique identifier for this mesh within a single multimesh structure
attribute::MeshAttributeHandle get_attribute_handle(const std::string &name, const PrimitiveType ptype) const
Definition Mesh.hpp:903
const attribute::Accessor< T, Mesh, D > create_const_accessor(const attribute::MeshAttributeHandle &handle) const
int64_t capacity(PrimitiveType type) const
read in the m_capacities return the upper bound for the number of entities of the given dimension
attribute::TypedAttributeHandle< T > register_attribute_typed(const std::string &name, PrimitiveType type, int64_t size, bool replace=false, T default_value=T(0))
bool is_boundary(const simplex::Simplex &tuple) const
check if a simplex lies on a boundary or not
Definition Mesh.cpp:107
attribute::Accessor< T, Mesh, D > create_accessor(const attribute::MeshAttributeHandle &handle)
virtual Tuple tuple_from_id(const PrimitiveType type, const int64_t gid) const =0
internal function that returns the tuple of requested type, and has the global index cid
std::vector< Tuple > get_all(PrimitiveType type) const
Generate a vector of Tuples from global vertex/edge/triangle/tetrahedron index.
Definition Mesh.cpp:18
multimesh::MultiMeshManager m_multi_mesh_manager
Definition Mesh.hpp:827
Tuple switch_tuples(const Tuple &tuple, const ContainerType &op_sequence) const
Definition Mesh.hpp:953
bool has_attribute(const std::string &name, const PrimitiveType ptype) const
Definition Mesh.hpp:923
virtual bool is_valid(const Tuple &tuple) const
check validity of tuple including its hash
Definition Mesh.cpp:113
int64_t top_cell_dimension() const
Definition Mesh.hpp:978
virtual Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const =0
switch the orientation of the Tuple of the given dimension
Mesh & get_multi_mesh_root()
returns a reference to the root of a multimesh tree
PrimitiveType top_simplex_type() const
Definition Mesh.hpp:982
const attribute::FlagAccessor< Mesh > get_const_flag_accessor(PrimitiveType type) const
Definition Mesh.cpp:163
const attribute::FlagAccessor< Mesh > get_flag_accessor(PrimitiveType type) const
Definition Mesh.cpp:159
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
int8_t local_fid() const
Definition Tuple.hxx:62
int64_t global_cid() const
Definition Tuple.hxx:47
A CachingAccessor that uses tuples for accessing attributes instead of indices.
Definition Accessor.hpp:28
std::vector< MeshAttributes< T > > & get()
Implementation details for how the Mesh class implements multiple meshes.
void check_map_valid(const Mesh &my_mesh) const
update all the hashes of the top-simplces of the parent mesh around a vertex hashes of the parent tup...
Tuple map_to_root_tuple(const Mesh &my_mesh, const simplex::Simplex &my_simplex) const
maps a simplex from this mesh to the root mesh
int64_t child_id() const
Specifies the child id of this mesh if it a child mesh in a mult-mesh tree.
bool can_map_child(const Mesh &my_mesh, const Mesh &other_mesh, const simplex::Simplex &my_simplex) const
std::map< std::string, const wmtk::utils::Hashable * > child_hashables() const override
const Mesh & get_root_mesh(const Mesh &my_mesh) const
std::vector< ChildData > m_children
Mesh & get_mesh(Mesh &m, const std::vector< int64_t > &absolute_id)
static bool is_child(const std::vector< int64_t > &child, const std::vector< int64_t > &parent)
void deregister_child_mesh(Mesh &my_mesh, const std::shared_ptr< Mesh > &child_mesh_ptr)
Deregister a child mesh.
static Tuple map_tuple_between_meshes(const Mesh &source_mesh, const Mesh &target_mesh, const wmtk::attribute::Accessor< int64_t > &source_to_target_map_accessor, const Tuple &source_tuple)
bool is_root() const
Specifies whether this structure is the root of a multi-mesh tree.
std::vector< int64_t > absolute_id() const
static std::vector< int64_t > least_upper_bound_id(const std::vector< int64_t > &a, const std::vector< int64_t > &b)
static std::string parent_to_child_map_attribute_name(int64_t index)
static std::string child_to_parent_map_attribute_name()
friend std::vector< std::array< Tuple, 2 > > multimesh::same_simplex_dimension_surjection(const Mesh &parent, const Mesh &child, const std::vector< int64_t > &parent_simplices)
std::vector< simplex::Simplex > map(const Mesh &my_mesh, const Mesh &other_mesh, const simplex::Simplex &my_simplex) const
maps a simplex from this mesh to any other mesh
void serialize(MeshWriter &writer, const Mesh *local_root=nullptr) const
std::vector< std::shared_ptr< Mesh > > get_child_meshes() const
std::vector< Tuple > map_down_relative_tuples(const Mesh &my_mesh, const simplex::Simplex &my_simplex, const std::vector< int64_t > &local_id_path) const
std::vector< bool > m_has_child_mesh_in_dimension
TypedAttributeHandle< int64_t > map_to_parent_handle
MultiMeshManager & operator=(const MultiMeshManager &o)
static std::vector< int64_t > relative_id(const std::vector< int64_t > &parent, const std::vector< int64_t > &child)
std::vector< TypedAttributeHandle< int64_t > > map_handles() const
std::map< std::string, std::size_t > child_hashes() const override
std::vector< Tuple > lub_map_tuples(const Mesh &my_mesh, const Mesh &other_mesh, const simplex::Simplex &my_simplex) const
maps a simplex from this mesh to any other mesh using the LUB as the root
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)
Tuple map_tuple_to_root_tuple(const Mesh &my_mesh, const Tuple &my_tuple) const
simplex::Simplex map_to_root(const Mesh &my_mesh, const simplex::Simplex &my_simplex) const
maps a simplex from this mesh to the root mesh
simplex::Simplex map_to_parent(const Mesh &my_mesh, const simplex::Simplex &my_simplex) const
optimized map from a simplex from this mesh to its direct parent
const std::vector< ChildData > & children() const
std::array< const wmtk::attribute::Accessor< int64_t >, 2 > get_map_const_accessors(const Mesh &my_mesh, const ChildData &c) const
std::vector< Tuple > map_tuples(const Mesh &my_mesh, const Mesh &other_mesh, const simplex::Simplex &my_simplex) const
maps a simplex from this mesh to any other mesh
Tuple map_to_parent_tuple(const Mesh &my_mesh, const simplex::Simplex &my_simplex) const
optimized map from a simplex from this mesh to its direct parent
void check_child_map_valid(const Mesh &my_mesh, const ChildData &child_data) const
bool can_map(const Mesh &my_mesh, const Mesh &other_mesh, const simplex::Simplex &my_simplex) const
std::vector< Tuple > map_to_child_tuples(const Mesh &my_mesh, const Mesh &child_mesh, const simplex::Simplex &my_simplex) const
Mesh & get_child_mesh(Mesh &m, const std::vector< int64_t > &relative_id)
std::vector< simplex::Simplex > map_to_child(const Mesh &my_mesh, const Mesh &child_mesh, const simplex::Simplex &my_simplex) const
optimized map fromsimplex from this mesh to one of its direct children
std::pair< const Mesh &, Tuple > map_up_to_tuples(const Mesh &my_mesh, const simplex::Simplex &simplex, int64_t depth) const
void register_child_mesh(Mesh &my_mesh, const std::shared_ptr< Mesh > &child_mesh, const std::vector< std::array< Tuple, 2 > > &child_tuple_my_tuple_map)
register a another mesh as a child of this mesh.
Tuple map_tuple_to_parent_tuple(const Mesh &my_mesh, const Tuple &my_tuple) const
std::vector< simplex::Simplex > lub_map(const Mesh &my_mesh, const Mesh &other_mesh, const simplex::Simplex &my_simplex) const
maps a simplex from this mesh to any other mesh using the LUB as the root
const Tuple & tuple() const
Definition Simplex.hpp:53
PrimitiveType primitive_type() const
Definition Simplex.hpp:51
std::map< std::string, std::size_t > child_hashes() const override
std::tuple< Tuple, Tuple > read_tuple_map_attribute_slow(const Mesh &source_mesh, TypedAttributeHandle< int64_t > map_handle, const Tuple &source_tuple)
std::tuple< Tuple, Tuple > read_tuple_map_attribute(const wmtk::attribute::Accessor< int64_t, MeshType > &accessor, const Tuple &source_tuple)
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)
std::vector< Simplex > tuple_vector_to_homogeneous_simplex_vector(const Mesh &m, const std::vector< Tuple > &tups, PrimitiveType primitive)
std::vector< Tuple > make_unique_tuples(const Mesh &m, const std::vector< Tuple > &ts, PrimitiveType primitive)
void top_dimension_cofaces_tuples(const PointMesh &mesh, const Simplex &simplex, SimplexCollection &collection)
std::vector< Tuple > cofaces_single_dimension_tuples(const Mesh &mesh, const Simplex &my_simplex, PrimitiveType cofaces_type)
std::size_t vector_hash(const std::vector< size_t > &data)
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58