7
7
#include < wmtk/TetMesh.hpp>
8
8
#include < wmtk/TriMesh.hpp>
9
9
#include < wmtk/multimesh/MultiMeshSimplexVisitor.hpp>
10
+ #include < wmtk/simplex/cofaces_single_dimension_iterable.hpp>
10
11
#include < wmtk/simplex/top_dimension_cofaces.hpp>
12
+ #include " wmtk/simplex/cofaces_single_dimension.hpp"
11
13
12
14
namespace wmtk {
13
15
namespace {
14
16
15
- bool are_all_ears_in_child (const TriMesh& parent, const EdgeMesh& child, const Tuple& t)
17
+ // checks if two simplices both are mappable
18
+ bool both_map_to_child (
19
+ const Mesh& parent,
20
+ const Mesh& child,
21
+ const simplex::Simplex& left,
22
+ const simplex::Simplex& right)
16
23
{
17
- const Tuple parent_ear_0 = parent.switch_edge (t);
18
- const Tuple paretn_ear_1 = parent.switch_edge (parent.switch_vertex (t));
19
- bool find_ear_0 =
20
- !parent.map_to_child (child, simplex::Simplex::edge (parent, parent_ear_0)).empty ();
21
- bool find_ear_1 =
22
- !parent.map_to_child (child, simplex::Simplex::edge (parent, paretn_ear_1)).empty ();
23
- return find_ear_0 && find_ear_1;
24
+ return parent.can_map (child, left) && parent.can_map (child, right);
24
25
}
25
26
26
- bool are_all_ears_in_child (const TetMesh& parent, const TriMesh& child, const Tuple& t)
27
+
28
+ // computes teh two ears in a K+1 simplex over the input edge to see if their facets will be mapped
29
+ // into one another
30
+ bool both_map_to_child (const Mesh& parent, const Mesh& child, const Tuple& input)
27
31
{
28
- const Tuple parent_ear_0 = parent.switch_face (parent.switch_edge (t));
29
- const Tuple parent_ear_1 = parent.switch_face (parent.switch_edge (parent.switch_vertex (t)));
30
- bool find_ear_0 =
31
- !parent.map_to_child (child, simplex::Simplex::face (parent, parent_ear_0)).empty ();
32
- bool find_ear_1 =
33
- !parent.map_to_child (child, simplex::Simplex::face (parent, parent_ear_1)).empty ();
34
- return find_ear_0 && find_ear_1;
32
+ const PrimitiveType child_type = child.top_simplex_type ();
33
+ const PrimitiveType parent_type = parent.top_simplex_type ();
34
+ assert (parent_type > child_type);
35
+ const PrimitiveType collapsed_simplex_type = std::min (child_type + 1 , parent_type);
36
+ auto opposite = [&parent, collapsed_simplex_type](Tuple t) {
37
+ // switch(collapsed_simplex_type) {
38
+ // case PrimitiveType::Tetrahedron:
39
+ // t = parent.switch_tuples(t, {PrimitiveType::Vertex, PrimitiveType::Edge, PrimitiveType::Triangle});
40
+ // case PrimitiveType::Triangle:
41
+ // t = parent.switch_tuples(t, {PrimitiveType::Vertex, PrimitiveType::Edge});
42
+ // case PrimitiveType::Edge:
43
+ // t = parent.switch_tuple(t, PrimitiveType::Vertex);
44
+
45
+ // default:
46
+ // case PrimitiveType::Vertex:
47
+ // break;
48
+ // }
49
+ for (PrimitiveType pt = PrimitiveType::Vertex; pt < collapsed_simplex_type; pt = pt + 1 ) {
50
+ assert (pt < parent.top_simplex_type ());
51
+ t = parent.switch_tuple (t, pt);
52
+ }
53
+ return t;
54
+ };
55
+ const simplex::Simplex left (child_type, opposite (input));
56
+ const simplex::Simplex right (
57
+ child_type,
58
+ opposite (parent.switch_tuple (input, PrimitiveType::Vertex)));
59
+ return both_map_to_child (parent, child, left, right);
35
60
}
36
61
37
- bool are_all_ears_in_child (const TetMesh& parent, const EdgeMesh& child, const Tuple& t)
62
+
63
+ // two child K-facets will merge into one another if they are the ears of a K+1 simplex whose
64
+ // "input edge" is the input edge. This function iterates through those K+1 simplices and lets
65
+ // both_map_to_child check for if both ears are mapped
66
+ bool any_pairs_both_map_to_child (
67
+ const Mesh& parent,
68
+ const Mesh& child,
69
+ const simplex::Simplex& edge)
38
70
{
39
- const Tuple parent_ear_0 = parent.switch_edge (t);
40
- const Tuple parent_ear_1 = parent.switch_edge (parent.switch_vertex (t));
41
- bool find_ear_0 =
42
- !parent.map_to_child (child, simplex::Simplex::edge (parent, parent_ear_0)).empty ();
43
- bool find_ear_1 =
44
- !parent.map_to_child (child, simplex::Simplex::edge (parent, parent_ear_1)).empty ();
71
+ assert (edge.primitive_type () == PrimitiveType::Edge);
72
+ const PrimitiveType parent_type = parent.top_simplex_type ();
73
+ const PrimitiveType child_type = child.top_simplex_type ();
74
+ assert (parent_type > child_type);
75
+ if (parent_type == child_type) {
76
+ // if the meshes are the same dimension then there isn't a pair, so this function returns
77
+ // false
78
+ return false ;
79
+ } else if (parent_type == child_type + 1 ) {
80
+ return both_map_to_child (parent, child, edge.tuple ());
81
+ }
82
+ for (const Tuple& tuple :
83
+ simplex::cofaces_single_dimension_iterable (parent, edge, child.top_simplex_type () + 1 )) {
84
+ if (both_map_to_child (parent, child, tuple)) {
85
+ return true ;
86
+ }
87
+ }
88
+ return false ;
89
+ }
45
90
46
- const Tuple t_switch_face = parent.switch_face (t);
47
- const Tuple parent_ear_2 = parent.switch_edge (t_switch_face);
48
- const Tuple parent_ear_3 = parent.switch_edge (parent.switch_vertex (t_switch_face));
49
- bool find_ear_2 =
50
- !parent.map_to_child (child, simplex::Simplex::edge (parent, parent_ear_2)).empty ();
51
- bool find_ear_3 =
52
- !parent.map_to_child (child, simplex::Simplex::edge (parent, parent_ear_3)).empty ();
53
91
54
- return (find_ear_0 && find_ear_1) || (find_ear_2 && find_ear_3);
55
- }
56
92
struct MultiMeshMapValidFunctor
57
93
{
58
94
template <typename T>
59
- bool operator ()(const T& m, const simplex::Simplex& s, int64_t ) {
60
- return this ->operator ()(m,s);
61
- }
62
- bool operator ()(const Mesh& m, const simplex::Simplex& s) const { return false ; }
63
- bool operator ()(const PointMesh& m, const simplex::Simplex& s) const { return false ; }
64
-
65
- bool operator ()(const EdgeMesh& m, const simplex::Simplex& s) const { return false ; }
66
- bool operator ()(const TriMesh& m, const simplex::Simplex& s) const
95
+ bool operator ()(const T& m, const simplex::Simplex& s, int64_t )
67
96
{
68
- const std::vector<Tuple> equivalent_tuples = simplex::top_dimension_cofaces_tuples (m, s);
69
-
70
- for (auto child_ptr : m.get_child_meshes ()) {
71
- if (child_ptr->top_cell_dimension () != 1 ) {
72
- continue ;
73
- }
74
-
75
- for (const Tuple& t : equivalent_tuples) {
76
- const EdgeMesh& child = dynamic_cast <const EdgeMesh&>(*child_ptr);
77
- if (m.map_to_child (child, s).empty () && are_all_ears_in_child (m, child, t)) {
78
- return false ;
79
- }
80
- }
81
- }
82
- return true ;
97
+ return this ->operator ()(m, s);
83
98
}
84
- bool operator ()(const TetMesh & m, const simplex::Simplex& s) const
99
+ bool operator ()(const Mesh & m, const simplex::Simplex& s) const
85
100
{
86
- const std::vector<Tuple> equivalent_tuples = simplex::top_dimension_cofaces_tuples (m, s);
87
-
88
101
for (auto child_ptr : m.get_child_meshes ()) {
89
- if (child_ptr->top_cell_dimension () != 2 && child_ptr->top_cell_dimension () != 1 ) {
90
- continue ;
91
- }
92
-
93
- for (const Tuple& t : equivalent_tuples) {
94
- if (child_ptr->top_cell_dimension () == 2 ) {
95
- const TriMesh& child = dynamic_cast <const TriMesh&>(*child_ptr);
96
- if (m.map_to_child (child, s).empty () && are_all_ears_in_child (m, child, t)) {
97
- return false ;
98
- }
99
- } else {
100
- const EdgeMesh& child = dynamic_cast <const EdgeMesh&>(*child_ptr);
101
- if (m.map_to_child (child, s).empty () && are_all_ears_in_child (m, child, t)) {
102
- return false ;
103
- }
104
- }
102
+ if (any_pairs_both_map_to_child (m, *child_ptr, s)) {
103
+ return false ;
105
104
}
106
105
}
107
106
return true ;
@@ -119,7 +118,7 @@ bool MultiMeshMapValidInvariant::before(const simplex::Simplex& t) const
119
118
std::integral_constant<int64_t , 1 >{}, // specify that this runs on edges
120
119
MultiMeshMapValidFunctor{});
121
120
// TODO: fix visitor to work for const data
122
- visitor.execute_from_root (const_cast <Mesh&>(mesh ()), simplex::NavigatableSimplex (mesh (),t));
121
+ visitor.execute_from_root (const_cast <Mesh&>(mesh ()), simplex::NavigatableSimplex (mesh (), t));
123
122
const auto & data = visitor.cache ();
124
123
125
124
for (const auto & [key, value_var] : data) {
0 commit comments