Skip to content

Commit 54b90a3

Browse files
authored
Merge pull request #821 from wildmeshing/mtao/map_invariant
simplifying multimesh map invariant
2 parents 40576b4 + c16d84d commit 54b90a3

File tree

2 files changed

+87
-79
lines changed

2 files changed

+87
-79
lines changed

src/wmtk/invariants/MultiMeshMapValidInvariant.cpp

Lines changed: 74 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,101 +7,100 @@
77
#include <wmtk/TetMesh.hpp>
88
#include <wmtk/TriMesh.hpp>
99
#include <wmtk/multimesh/MultiMeshSimplexVisitor.hpp>
10+
#include <wmtk/simplex/cofaces_single_dimension_iterable.hpp>
1011
#include <wmtk/simplex/top_dimension_cofaces.hpp>
12+
#include "wmtk/simplex/cofaces_single_dimension.hpp"
1113

1214
namespace wmtk {
1315
namespace {
1416

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)
1623
{
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);
2425
}
2526

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)
2731
{
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);
3560
}
3661

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)
3870
{
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+
}
4590

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();
5391

54-
return (find_ear_0 && find_ear_1) || (find_ear_2 && find_ear_3);
55-
}
5692
struct MultiMeshMapValidFunctor
5793
{
5894
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)
6796
{
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);
8398
}
84-
bool operator()(const TetMesh& m, const simplex::Simplex& s) const
99+
bool operator()(const Mesh& m, const simplex::Simplex& s) const
85100
{
86-
const std::vector<Tuple> equivalent_tuples = simplex::top_dimension_cofaces_tuples(m, s);
87-
88101
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;
105104
}
106105
}
107106
return true;
@@ -119,7 +118,7 @@ bool MultiMeshMapValidInvariant::before(const simplex::Simplex& t) const
119118
std::integral_constant<int64_t, 1>{}, // specify that this runs on edges
120119
MultiMeshMapValidFunctor{});
121120
// 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));
123122
const auto& data = visitor.cache();
124123

125124
for (const auto& [key, value_var] : data) {

src/wmtk/simplex/Simplex.hpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace wmtk {
77
class Mesh;
88

99
namespace multimesh {
10-
class MultiMeshManager;
10+
class MultiMeshManager;
1111
}
1212
template <typename Derived>
1313
class MeshCRTP;
@@ -30,17 +30,17 @@ class Simplex
3030
friend class NavigatableSimplex;
3131
PrimitiveType m_primitive_type;
3232
Tuple m_tuple;
33+
34+
public:
3335
// the mesh class can use this index value to cache/accelerate operations
34-
protected:
35-
// private constructor mesh might want to use if it knows the ids beforehand
3636
Simplex(const PrimitiveType& ptype, const Tuple& t)
3737
: m_primitive_type{ptype}
3838
, m_tuple{t}
3939
{}
4040

4141

42-
public:
4342
Simplex() = default;
43+
// TODO: deprecate
4444
Simplex(const Mesh& m, const PrimitiveType& ptype, const Tuple& t);
4545

4646
Simplex(const Simplex&) = default;
@@ -52,20 +52,29 @@ class Simplex
5252
int64_t dimension() const { return get_primitive_type_id(m_primitive_type); }
5353
const Tuple& tuple() const { return m_tuple; }
5454

55+
// TODO: deprecate
5556
static Simplex vertex(const Mesh& m, const Tuple& t)
5657
{
5758
return Simplex(PrimitiveType::Vertex, t);
5859
}
60+
// TODO: deprecate
5961
static Simplex edge(const Mesh& m, const Tuple& t) { return Simplex(PrimitiveType::Edge, t); }
62+
// TODO: deprecate
6063
static Simplex face(const Mesh& m, const Tuple& t)
6164
{
6265
return Simplex(PrimitiveType::Triangle, t);
6366
}
67+
// TODO: deprecate
6468
static Simplex tetrahedron(const Mesh& m, const Tuple& t)
6569
{
6670
return Simplex(PrimitiveType::Tetrahedron, t);
6771
}
6872

73+
static Simplex vertex(const Tuple& t) { return Simplex(PrimitiveType::Vertex, t); }
74+
static Simplex edge(const Tuple& t) { return Simplex(PrimitiveType::Edge, t); }
75+
static Simplex face(const Tuple& t) { return Simplex(PrimitiveType::Triangle, t); }
76+
static Simplex tetrahedron(const Tuple& t) { return Simplex(PrimitiveType::Tetrahedron, t); }
77+
6978
// these operations are only internally defined if caching is enabled to make sure there's a
7079
// consistent semantic when simplex id caching is enabled vs not
7180
#if defined(WMTK_ENABLE_SIMPLEX_ID_CACHING)

0 commit comments

Comments
 (0)