Wildmeshing Toolkit
Loading...
Searching...
No Matches
TetMesh.h
1#pragma once
2
3#include <wmtk/utils/VectorUtils.h>
4#include <wmtk/AttributeCollection.hpp>
5#include <wmtk/Types.hpp>
6#include <wmtk/simplex/Simplex.hpp>
7#include <wmtk/simplex/SimplexCollection.hpp>
8#include <wmtk/threading/enumerable_thread_specific.hpp>
9#include <wmtk/threading/vertex_mutex.hpp>
10#include <wmtk/utils/Logger.hpp>
11
12#include <array>
13#include <atomic>
14#include <cassert>
15#include <cmath>
16#include <cstdint>
17#include <limits>
18#include <map>
19#include <optional>
20#include <vector>
21
22namespace wmtk {
24{
25private:
30 static constexpr std::array<std::array<int, 2>, 6> m_local_edges = {
31 {{{0, 1}}, {{1, 2}}, {{0, 2}}, {{0, 3}}, {{1, 3}}, {{2, 3}}}};
32
33 static constexpr std::array<int, 4> m_map_vertex2edge = {{0, 0, 1, 3}};
34 static constexpr std::array<int, 4> m_map_vertex2oppo_face = {{3, 1, 2, 0}};
35 static constexpr std::array<int, 6> m_map_edge2face = {{0, 0, 0, 1, 2, 1}};
36 static constexpr std::array<std::array<int, 3>, 4> m_local_faces = {
37 {{{0, 1, 2}}, {{0, 2, 3}}, {{0, 1, 3}}, {{1, 2, 3}}}}; // sorted local vids
38 static constexpr std::array<std::array<int, 3>, 4> m_local_edges_in_a_face = {
39 {{{0, 1, 2}}, {{2, 5, 3}}, {{3, 4, 0}}, {{5, 1, 4}}}};
40
41public:
42 // Cell Tuple Navigator
48 class Tuple
49 {
50 size_t m_global_vid = std::numeric_limits<size_t>::max();
51 size_t m_local_eid = std::numeric_limits<size_t>::max();
52 size_t m_local_fid = std::numeric_limits<size_t>::max();
53 size_t m_global_tid = std::numeric_limits<size_t>::max();
54
55 int m_hash = 0;
56
57 private:
67 Tuple(const TetMesh& m, size_t vid, size_t local_eid, size_t local_fid, size_t tid);
68
69 public:
70 Tuple() {}
71
72 friend TetMesh;
73
81 bool is_valid(const TetMesh& m) const;
88 bool is_boundary_edge(const TetMesh& m) const;
95 bool is_boundary_face(const TetMesh& m) const;
96
101 void print_info() const;
102
108 void print_info(const TetMesh& m) const;
109
115 size_t vid(const TetMesh& m) const;
116
125 size_t eid(const TetMesh& m) const;
126
134 size_t fid(const TetMesh& m) const;
135
142 size_t tid(const TetMesh& m) const;
143
150 Tuple switch_vertex(const TetMesh& m) const;
157 Tuple switch_edge(const TetMesh& m) const;
164 Tuple switch_face(const TetMesh& m) const;
165
173 std::optional<Tuple> switch_tetrahedron(const TetMesh& m) const;
174 std::optional<Tuple> switch_tetrahedron_slow(const TetMesh& m) const;
175
176
178
181 void check_validity(const TetMesh& m) const;
182 friend bool operator==(const Tuple& a, const Tuple& t)
183 {
184 return (
185 std::tie(a.m_global_vid, a.m_local_eid, a.m_local_fid, a.m_global_tid, a.m_hash) ==
186 std::tie(t.m_global_vid, t.m_local_eid, t.m_local_fid, t.m_global_tid, t.m_hash));
187 }
188 friend bool operator<(const Tuple& a, const Tuple& t)
189 {
190 return (
191 std::tie(a.m_global_vid, a.m_local_eid, a.m_local_fid, a.m_global_tid, a.m_hash) <
192 std::tie(t.m_global_vid, t.m_local_eid, t.m_local_fid, t.m_global_tid, t.m_hash));
193 }
194 };
195
201 {
202 const TetMesh& m_mesh;
203 Tuple m_tuple;
204
205 public:
206 SmartTuple(const TetMesh& mesh, const Tuple& t)
207 : m_mesh(mesh)
208 , m_tuple(t)
209 {}
210
211 const Tuple& tuple() { return m_tuple; }
212 const TetMesh& mesh() { return m_mesh; }
213
214 SmartTuple& operator=(const SmartTuple& t)
215 {
216 m_tuple = t.m_tuple;
217 return *this;
218 }
219
220 bool is_valid() const { return m_tuple.is_valid(m_mesh); }
221 bool is_boundary_edge() const { return m_tuple.is_boundary_edge(m_mesh); }
222 bool is_boundary_face() const { return m_tuple.is_boundary_face(m_mesh); }
223 size_t vid() const { return m_tuple.vid(m_mesh); }
224 size_t eid() const { return m_tuple.eid(m_mesh); }
225 size_t fid() const { return m_tuple.fid(m_mesh); }
226 size_t tid() const { return m_tuple.tid(m_mesh); }
227 SmartTuple switch_vertex() const { return {m_mesh, m_tuple.switch_vertex(m_mesh)}; }
228 SmartTuple switch_edge() const { return {m_mesh, m_tuple.switch_edge(m_mesh)}; }
229 SmartTuple switch_face() const { return {m_mesh, m_tuple.switch_face(m_mesh)}; }
230 std::optional<SmartTuple> switch_tetrahedron() const
231 {
232 const std::optional<Tuple> t = m_tuple.switch_tetrahedron(m_mesh);
233 if (t) {
234 return std::optional<SmartTuple>({m_mesh, t.value()});
235 }
236 return {};
237 }
238 void check_validity() const { return m_tuple.check_validity(m_mesh); }
239 };
240
247 {
248 public:
249 std::vector<size_t> m_conn_tets; // todo: always keep it sorted
250 bool m_is_removed = false;
251
252 size_t& operator[](const size_t index)
253 {
254 assert(index < m_conn_tets.size());
255 return m_conn_tets[index];
256 }
257
258 size_t operator[](const size_t index) const
259 {
260 assert(index < m_conn_tets.size());
261 return m_conn_tets[index];
262 }
263
264 friend bool operator==(const VertexConnectivity& l, const VertexConnectivity& r)
265 {
266 return std::tie(l.m_conn_tets, l.m_is_removed) ==
267 std::tie(r.m_conn_tets, r.m_is_removed); // keep the same order
268 }
269
270 void print_info() {}
271 };
272
278 {
279 public:
280 std::array<size_t, 4> m_indices;
281 bool m_is_removed = false;
282
283 int hash = 0;
284
285 size_t& operator[](size_t index)
286 {
287 assert(index < 4);
288 return m_indices[index];
289 }
290
291 size_t operator[](size_t index) const
292 {
293 assert(index < 4);
294 return m_indices[index];
295 }
296
297 int find(size_t v_id) const
298 {
299 for (int j = 0; j < 4; j++) {
300 if (v_id == m_indices[j]) return j;
301 }
302 return -1;
303 }
304
305 int find_local_edge(size_t v1_id, size_t v2_id) const
306 {
307 std::array<int, 2> e;
308 for (int j = 0; j < 4; j++) {
309 if (v1_id == m_indices[j])
310 e[0] = j;
311 else if (v2_id == m_indices[j])
312 e[1] = j;
313 }
314 if (e[0] > e[1]) std::swap(e[0], e[1]);
315 int i =
316 std::find(m_local_edges.begin(), m_local_edges.end(), e) - m_local_edges.begin();
317 if (i >= m_local_edges.size()) return -1;
318 return i;
319 }
320
321 int find_local_face(size_t v1_id, size_t v2_id, size_t v3_id) const
322 {
323 std::array<int, 3> f;
324 for (int j = 0; j < 4; j++) {
325 if (v1_id == m_indices[j])
326 f[0] = j;
327 else if (v2_id == m_indices[j])
328 f[1] = j;
329 else if (v3_id == m_indices[j])
330 f[2] = j;
331 }
332 std::sort(f.begin(), f.end());
333 int i =
334 std::find(m_local_faces.begin(), m_local_faces.end(), f) - m_local_faces.begin();
335 if (i >= m_local_edges.size()) return -1;
336 return i;
337 }
338
339 friend bool operator==(const TetrahedronConnectivity& l, const TetrahedronConnectivity& r)
340 {
341 return std::tie(l.m_indices, l.m_is_removed, l.hash) ==
342 std::tie(r.m_indices, r.m_is_removed, r.hash); // keep the same order
343 }
344
345 void print_info() {}
346 };
347
348 TetMesh();
349 virtual ~TetMesh() = default;
355 size_t vert_capacity() const { return current_vert_size; }
361 size_t tet_capacity() const { return current_tet_size; }
362
372 static constexpr int EDGES_PER_CELL = 6;
373 static constexpr int FACES_PER_CELL = 4;
374 size_t cell_capacity() const { return tet_capacity(); }
375 Tuple tuple_from_cell(size_t cid) const { return tuple_from_tet(cid); }
382 size_t vertex_size() const
383 {
384 int cnt = 0;
385 for (auto i = 0; i < vert_capacity(); i++) {
386 if (!m_vertex_connectivity[i].m_is_removed) cnt++;
387 }
388 return cnt;
389 }
394 size_t tet_size() const
395 {
396 int cnt = 0;
397 for (auto i = 0; i < tet_capacity(); i++) {
398 if (!m_tet_connectivity[i].m_is_removed) cnt++;
399 }
400 return cnt;
401 }
411 void init(size_t n_vertices, const std::vector<std::array<size_t, 4>>& tets);
412 void init_with_isolated_vertices(
413 size_t n_vertices,
414 const std::vector<std::array<size_t, 4>>& tets);
415
421 void init(const MatrixXi& T);
422
430 bool split_edge(const Tuple& t, std::vector<Tuple>& new_tets);
438 virtual bool collapse_edge(const Tuple& t, std::vector<Tuple>& new_tets);
439
440 bool link_condition(const Tuple& t);
441
460 const Tuple& loc0,
461 size_t& v1_id,
462 Tuple& new_loc,
463 std::map<size_t, wmtk::TetMesh::VertexConnectivity>& rollback_vert_conn,
464 std::vector<size_t>& n1_t_ids_copy,
465 std::vector<size_t>& new_tet_id,
466 std::vector<TetrahedronConnectivity>& old_tets);
467
476 bool collapse_edge_check_topology(const std::vector<size_t>& new_tet_id);
477
491 size_t& v1_id,
492 std::map<size_t, wmtk::TetMesh::VertexConnectivity>& rollback_vert_conn,
493 std::vector<size_t>& n1_t_ids,
494 std::vector<size_t>& new_tet_id,
495 std::vector<TetrahedronConnectivity>& old_tets);
496
505 bool swap_edge_56(const Tuple& t, std::vector<Tuple>& new_tets);
514 bool swap_edge_44(const Tuple& t, std::vector<Tuple>& new_tets);
523 bool swap_edge(const Tuple& t, std::vector<Tuple>& new_tets);
530 bool swap_face(const Tuple& t, std::vector<Tuple>& new_tets);
538 bool smooth_vertex(const Tuple& t);
539
548 bool split_tet(const Tuple& t, std::vector<Tuple>& new_tets);
549
560 bool split_face(const Tuple& t, std::vector<Tuple>& new_tets);
561
570 const std::vector<Tuple>& intersected_tets,
571 const std::vector<Tuple>& intersected_edges,
572 std::vector<size_t>& new_edge_vids,
573 std::vector<size_t>& new_center_vids,
574 std::vector<std::array<size_t, 4>>& center_split_tets);
575
585 bool insert_point(const Tuple& t, std::vector<Tuple>& new_tets);
586 virtual bool insert_point_before(const Tuple& t) { return true; };
587 virtual bool insert_point_after(std::vector<Tuple>& new_tets) { return true; };
593 void consolidate_mesh();
594
600 std::vector<Tuple> get_edges() const;
606 std::vector<Tuple> get_faces() const;
612 std::vector<Tuple> get_vertices() const;
618 std::vector<Tuple> get_tets() const;
623 // virtual void for_each_edge(const std::function<void(const TetMesh::Tuple&)>&);
624
625 // TODO: make this concurrent
630 virtual void for_each_face(const std::function<void(const TetMesh::Tuple&)>&);
631 // /**
632 // * @brief looping through all the unique vertices and perform the given function
633 // *
634 // */
635 // virtual void for_each_vertex(const std::function<void(const TetMesh::Tuple&)>&);
636 // /**
637 // * @brief looping through all the unique tet and perform the given function
638 // *
639 // */
640 // virtual void for_each_tetra(const std::function<void(const TetMesh::Tuple&)>&);
641
642public:
643 template <typename T>
644 using vector = std::vector<T>;
645
646public:
647 AbstractAttributeContainer* p_vertex_attrs = nullptr;
648 AbstractAttributeContainer* p_edge_attrs = nullptr;
649 AbstractAttributeContainer* p_face_attrs = nullptr;
650 AbstractAttributeContainer* p_tet_attrs = nullptr;
651 // AbstractAttributeContainer vertex_attrs, edge_attrs, face_attrs, tet_attrs;
652
653
654public:
662 void set_preallocation_factor(double factor)
663 {
664 if (factor >= 1.0) m_preallocation_factor = factor;
665 }
666 double preallocation_factor() const { return m_preallocation_factor; }
667
668 // Atomically reserve `n` contiguous fresh tet/vertex slots. Returns the first
669 // index of the block, or -1 if that would exceed the preallocated capacity (the
670 // caller must then abort the operation before mutating any connectivity).
671 long request_tet_slots(size_t n);
672 long request_vert_slots(size_t n);
673
674 // Construction/insertion helpers (single-threaded ONLY): guarantee at least
675 // `extra` free tet/vertex slots beyond the current used count, growing the
676 // storage geometrically if necessary. Unlike request_*_slots these never fail;
677 // they are used by the (legacy, non-concurrent) triangle-insertion path where
678 // the mesh is being built rather than edited by concurrent operations.
679 void ensure_free_tet_capacity(size_t extra)
680 {
681 const size_t need = static_cast<size_t>(current_tet_size.load()) + extra;
682 if (m_tet_connectivity.size() >= need) return;
683 const size_t newcap = std::max(need, m_tet_connectivity.size() * 2 + 1);
684 m_tet_connectivity.resize(newcap);
685 if (p_tet_attrs) p_tet_attrs->resize(newcap);
686 if (p_face_attrs) p_face_attrs->resize(4 * newcap);
687 if (p_edge_attrs) p_edge_attrs->resize(6 * newcap);
688 }
689 void ensure_free_vert_capacity(size_t extra)
690 {
691 const size_t need = static_cast<size_t>(current_vert_size.load()) + extra;
692 if (m_vertex_connectivity.size() >= need) return;
693 const size_t newcap = std::max(need, m_vertex_connectivity.size() * 2 + 1);
694 m_vertex_connectivity.resize(newcap);
695 resize_vertex_mutex(newcap);
696 if (p_vertex_attrs) p_vertex_attrs->resize(newcap);
697 }
698
699private:
700 // capacity to reserve for a live element count
701 size_t reserved_capacity(size_t live_count) const
702 {
703 const size_t floor = 64;
704 double c = std::ceil(m_preallocation_factor * static_cast<double>(live_count));
705 size_t capacity = static_cast<size_t>(c);
706 if (capacity < live_count) capacity = live_count;
707 return capacity < floor ? floor : capacity;
708 }
709
710 // Stores the connectivity of the mesh
711 vector<VertexConnectivity> m_vertex_connectivity;
712 vector<TetrahedronConnectivity> m_tet_connectivity;
713 std::atomic_long current_vert_size;
714 std::atomic_long current_tet_size;
715 double m_preallocation_factor = 6.0;
716
717 int m_t_empty_slot = 0;
718 int m_v_empty_slot = 0;
719 int get_next_empty_slot_t();
720 int get_next_empty_slot_v();
721
722 // TODO: subdivide_tets function should not be in the TetMesh API.
723 void subdivide_tets(
724 const std::vector<size_t> t_ids,
725 const std::vector<bool>& mark_surface,
726 const std::map<std::array<size_t, 2>, size_t>& map_edge2vid,
727 std::map<std::array<size_t, 3>, std::vector<std::array<size_t, 5>>>& new_face_vids,
728 const std::vector<size_t>& new_vids,
729 std::vector<size_t>& new_tids,
730 std::vector<size_t>& new_center_vids,
731 std::vector<std::array<size_t, 4>>& center_split_tets);
732 void subdivide_a_tet(
733 size_t t_id,
734 const std::array<int, 6>& new_v_ids,
735 bool mark_surface,
736 std::map<std::array<size_t, 3>, std::vector<std::array<size_t, 5>>>& new_face_vids,
737 std::vector<size_t>& new_tids,
738 std::vector<size_t>& new_center_vids,
739 std::vector<std::array<size_t, 4>>& center_split_tets);
740
741public:
742 virtual bool invariants(const std::vector<Tuple>&) { return true; }
743
744protected:
745 virtual bool triangle_insertion_before(const std::vector<Tuple>& faces) { return true; }
746 virtual bool triangle_insertion_after(const std::vector<std::vector<Tuple>>&) { return true; }
747
749 // Checks if the split should be performed or not (user controlled)
756 virtual bool split_edge_before(const Tuple& t) { return true; } // check edge condition
757 // This function computes the attributes for the added simplices
758 // if it returns false then the operation is undone
765 virtual bool split_edge_after(const Tuple& t) { return true; } // check tet condition
766
768 // Checks if the collapse should be performed or not (user controlled)
776 virtual bool collapse_edge_before(const Tuple& t) { return true; }
777 // If it returns false then the operation is undone (the tuple indexes a vertex and tet that
778 // survived)
785 virtual bool collapse_edge_after(const Tuple& t) { return true; }
793 virtual bool swap_edge_44_before(const Tuple& t) { return true; }
804 virtual double swap_edge_44_energy(
805 const std::vector<std::array<size_t, 4>>& tets,
806 const int op_case)
807 {
808 return -op_case;
809 }
816 virtual bool swap_edge_44_after(const Tuple& t) { return true; }
829 virtual bool swap_edge_44_accept_case(const std::array<size_t, 2>& new_edge) { return true; }
837 virtual bool swap_edge_56_before(const Tuple& t) { return true; }
848 virtual double swap_edge_56_energy(
849 const std::vector<std::array<size_t, 4>>& tets,
850 const int op_case)
851 {
852 return -op_case;
853 }
860 virtual bool swap_edge_56_after(const Tuple& t) { return true; }
873 virtual bool swap_edge_56_accept_case(const std::array<size_t, 3>& new_face) { return true; }
881 virtual bool swap_edge_before(const Tuple& t) { return true; }
888 virtual bool swap_edge_after(const Tuple& t) { return true; }
896 virtual bool swap_face_before(const Tuple& t) { return true; }
903 virtual bool swap_face_after(const Tuple& t) { return true; }
910 virtual bool smooth_before(const Tuple& t) { return true; }
917 virtual bool smooth_after(const Tuple& t) { return true; }
918
925 virtual bool split_face_before(const Tuple& t) { return true; }
926
934 virtual bool split_face_after(const Tuple& t) { return true; }
935
942 virtual bool split_tet_before(const Tuple& t) { return true; }
943
951 virtual bool split_tet_after(const Tuple& t) { return true; }
952
953 // virtual void resize_vertex_mutex(size_t v) {}
954
955public:
962 Tuple tuple_from_edge(size_t tid, int local_eid) const;
968 Tuple tuple_from_edge(const std::array<size_t, 2>& vids) const;
969
976 Tuple tuple_from_face(size_t tid, int local_fid) const;
977
983 std::tuple<Tuple, size_t> tuple_from_face(const std::array<size_t, 3>& vids) const;
991 std::optional<std::tuple<Tuple, size_t>> try_tuple_from_face(
992 const std::array<size_t, 3>& vids) const;
993
1000 size_t lowest_common_tet(size_t v0_id, size_t v1_id, size_t v2_id) const;
1001
1008 size_t vertex_valence(const size_t vid) const
1009 {
1010 return m_vertex_connectivity[vid].m_conn_tets.size();
1011 }
1012 std::tuple<Tuple, size_t> tuple_from_face(const simplex::Face& f) const;
1013
1019 Tuple tuple_from_vertex(size_t vid) const;
1020
1026 Tuple tuple_from_tet(size_t tid) const;
1027
1032 Tuple tuple_from_vids(size_t vid0, size_t vid1, size_t vid2, size_t vid3) const;
1033
1034 simplex::Tet simplex_from_tet(const Tuple& t) const;
1035 simplex::Tet simplex_from_tet(const size_t tid) const;
1036 simplex::Face simplex_from_face(const Tuple& t) const;
1037 simplex::Edge simplex_from_edge(const Tuple& t) const;
1038
1039
1043 Tuple switch_vertex(const Tuple& t) const
1044 {
1045 auto loc = t.switch_vertex(*this);
1047 return loc;
1048 }
1052 Tuple switch_edge(const Tuple& t) const
1053 {
1054 auto loc = t.switch_edge(*this);
1056 return loc;
1057 }
1061 Tuple switch_face(const Tuple& t) const
1062 {
1063 auto loc = t.switch_face(*this);
1065 return loc;
1066 }
1070 std::optional<Tuple> switch_tetrahedron(const Tuple& t) const
1071 {
1072 auto loc = t.switch_tetrahedron(*this);
1073 if (loc.has_value()) check_tuple_validity(loc.value());
1074 return loc;
1075 }
1076
1083 std::vector<Tuple> get_one_ring_tets_for_vertex(const Tuple& t) const;
1090 const std::vector<size_t>& get_one_ring_tids_for_vertex(const Tuple& t) const;
1091 const std::vector<size_t>& get_one_ring_tids_for_vertex(const size_t vid) const;
1092
1099 std::vector<Tuple> get_one_ring_vertices_for_vertex(const Tuple& t) const;
1107 std::vector<size_t> get_one_ring_vids_for_vertex(size_t vid, std::vector<size_t>& cache);
1114 std::vector<size_t> get_one_ring_vids_for_vertex(size_t vid) const;
1119 std::vector<size_t> get_one_ring_vids_for_vertex_adj(size_t vid) const;
1124 std::vector<size_t> get_one_ring_vids_for_vertex_adj(size_t vid, std::vector<size_t>& cache);
1125
1132 std::vector<Tuple> get_incident_tets_for_edge(const Tuple& t) const;
1133 std::vector<Tuple> get_incident_tets_for_edge(const size_t vid0, const size_t vid1) const;
1134
1135 std::vector<size_t> get_incident_tids_for_edge(const Tuple& t) const;
1136 std::vector<size_t> get_incident_tids_for_edge(const size_t vid0, const size_t vid1) const;
1137
1144 std::vector<Tuple> get_one_ring_tets_for_edge(const Tuple& t) const;
1145
1152 std::vector<std::array<size_t, 3>> vertex_adjacent_boundary_faces(const Tuple& t) const;
1157 std::array<Tuple, 4> oriented_tet_vertices(const Tuple& t) const;
1162 std::array<size_t, 4> oriented_tet_vids(const Tuple& t) const;
1163 std::array<size_t, 4> oriented_tet_vids(const size_t tid) const;
1170 std::array<Tuple, 3> get_face_vertices(const Tuple& t) const;
1171 std::array<size_t, 3> get_face_vids(const Tuple& t) const;
1172
1180 std::array<Tuple, 6> tet_edges(const Tuple& t) const;
1184 void check_tuple_validity(const Tuple& t) const { t.check_validity(*this); }
1197 void remove_tets_by_ids(const std::vector<size_t>& tids)
1198 {
1199 for (size_t tid : tids) {
1200 m_tet_connectivity[tid].m_is_removed = true;
1201 for (int j = 0; j < 4; j++)
1202 vector_erase(m_vertex_connectivity[m_tet_connectivity[tid][j]].m_conn_tets, tid);
1203 }
1204 for (auto& v : m_vertex_connectivity) {
1205 if (v.m_is_removed) continue;
1206 if (v.m_conn_tets.empty()) v.m_is_removed = true;
1207 }
1208 }
1209 bool m_collapse_check_link_condition = true; // classical link condition
1210 bool m_collapse_check_topology = false; // sanity check
1211 bool m_collapse_check_manifold = true; // manifoldness check after collapse
1212
1213private:
1214 // `ok` is set to false if the operation ran out of preallocated tet slots; in
1215 // that case no connectivity is mutated and the caller must abort the operation.
1216 std::map<size_t, VertexConnectivity> operation_update_connectivity_impl(
1217 std::vector<size_t>& affected_tid,
1218 const std::vector<std::array<size_t, 4>>& new_tet_conn,
1219 bool& ok);
1220 void operation_failure_rollback_imp(
1221 std::map<size_t, VertexConnectivity>& rollback_vert_conn,
1222 const std::vector<size_t>& affected,
1223 const std::vector<size_t>& new_tet_id,
1224 const std::vector<TetrahedronConnectivity>& old_tets);
1225 std::map<size_t, VertexConnectivity> operation_update_connectivity_impl(
1226 const std::vector<size_t>& remove_id,
1227 const std::vector<std::array<size_t, 4>>& new_tet_conn,
1228 std::vector<size_t>& allocate_id,
1229 bool& ok);
1230 static std::vector<TetrahedronConnectivity> record_old_tet_connectivity(
1231 const TetMesh::vector<TetrahedronConnectivity>& conn,
1232 const std::vector<size_t>& tets)
1233 {
1234 std::vector<TetrahedronConnectivity> tet_conn;
1235 for (size_t i : tets) {
1236 tet_conn.push_back(conn[i]);
1237 }
1238 return tet_conn;
1239 }
1240
1241public:
1242 void start_protect_attributes()
1243 {
1244 if (p_vertex_attrs) {
1245 p_vertex_attrs->begin_protect();
1246 }
1247 if (p_edge_attrs) {
1248 p_edge_attrs->begin_protect();
1249 }
1250 if (p_face_attrs) {
1251 p_face_attrs->begin_protect();
1252 }
1253 if (p_tet_attrs) {
1254 p_tet_attrs->begin_protect();
1255 }
1256 }
1257
1258 void release_protect_attributes()
1259 {
1260 if (p_vertex_attrs) {
1261 p_vertex_attrs->end_protect();
1262 }
1263 if (p_edge_attrs) {
1264 p_edge_attrs->end_protect();
1265 }
1266 if (p_face_attrs) {
1267 p_face_attrs->end_protect();
1268 }
1269 if (p_tet_attrs) {
1270 p_tet_attrs->end_protect();
1271 }
1272 }
1273
1274 void rollback_protected_attributes()
1275 {
1276 if (p_vertex_attrs) {
1277 p_vertex_attrs->rollback();
1278 }
1279 if (p_edge_attrs) {
1280 p_edge_attrs->rollback();
1281 }
1282 if (p_face_attrs) {
1283 p_face_attrs->rollback();
1284 }
1285 if (p_tet_attrs) {
1286 p_tet_attrs->rollback();
1287 }
1288 }
1289
1290public:
1294
1295private:
1296 std::vector<VertexMutex> m_vertex_mutex;
1297
1298 bool try_set_vertex_mutex(const Tuple& v, int threadid)
1299 {
1300 bool got = m_vertex_mutex[v.vid(*this)].trylock();
1301 if (got) m_vertex_mutex[v.vid(*this)].set_owner(threadid);
1302 return got;
1303 }
1304 bool try_set_vertex_mutex(size_t vid, int threadid)
1305 {
1306 bool got = m_vertex_mutex[vid].trylock();
1307 if (got) m_vertex_mutex[vid].set_owner(threadid);
1308 return got;
1309 }
1310
1311 void unlock_vertex_mutex(const Tuple& v) { m_vertex_mutex[v.vid(*this)].unlock(); }
1312 void unlock_vertex_mutex(size_t vid) { m_vertex_mutex[vid].unlock(); }
1313
1321 {
1322 std::vector<uint32_t> stamp;
1323 uint32_t epoch = 0;
1324 std::vector<size_t> frontier;
1325 std::vector<size_t> next;
1326 std::vector<size_t> one_ring;
1327 };
1329
1331 bool lock_vertex_ball(const size_t* seeds, size_t n_seeds, int threadid, int n, size_t mark);
1332
1333protected:
1334 void resize_vertex_mutex(size_t v)
1335 {
1336 if (m_vertex_mutex.size() < v) m_vertex_mutex.resize(v);
1337 }
1338
1339public:
1342
1343 // void init(size_t n_vertices, const std::vector<std::array<size_t, 4>>& tets);
1344 int release_vertex_mutex_in_stack();
1352 int release_vertex_mutex_to(size_t mark);
1353
1370 bool try_set_vertex_mutex_n_ring(const Tuple& v, int threadid, int n);
1371 bool try_set_vertex_mutex_n_ring(size_t vid, int threadid, int n);
1375 bool try_set_edge_mutex_n_ring(const Tuple& e, int threadid, int n);
1379 bool try_set_face_mutex_n_ring(size_t v1, size_t v2, size_t v3, int threadid, int n);
1380
1421 bool try_set_vertex_mutex_two_ring(const Tuple& v, int threadid);
1423 bool try_set_vertex_mutex_two_ring_vid(const Tuple& v, int threadid);
1425 bool try_set_vertex_mutex_two_ring_vid(size_t v, int threadid);
1427 bool try_set_edge_mutex_two_ring(const Tuple& e, int threadid = 0);
1429 bool try_set_face_mutex_two_ring(const Tuple& f, int threadid = 0);
1432 const Tuple& v1,
1433 const Tuple& v2,
1434 const Tuple& v3,
1435 int threadid = 0);
1437 bool try_set_face_mutex_two_ring(size_t v1, size_t v2, size_t v3, int threadid = 0);
1439 bool try_set_vertex_mutex_one_ring(const Tuple& v, int threadid = 0);
1442public:
1447 void for_each_edge(const std::function<void(const TetMesh::Tuple&)>&);
1452 void for_each_vertex(const std::function<void(const TetMesh::Tuple&)>&);
1457 void for_each_tetra(const std::function<void(const TetMesh::Tuple&)>&);
1458 int NUM_THREADS = 0;
1459
1460public:
1461 // substructure functionality
1462
1468 virtual bool vertex_is_on_surface(const size_t vid) const { return false; }
1469
1475 virtual bool face_is_on_surface(const size_t fid) const { return false; }
1476
1483
1489 simplex::SimplexCollection get_surface_faces_for_edge(const std::array<size_t, 2>& vids) const;
1495 size_t get_num_surface_faces_for_edge(const std::array<size_t, 2>& vids) const;
1496
1497
1506 size_t compute_vertex_order(const size_t vid) const;
1507
1522 virtual size_t get_order_of_vertex(const size_t vid) const { return compute_vertex_order(vid); }
1523
1534 size_t get_order_of_edge(const std::array<size_t, 2>& vids) const;
1535
1549 bool substructure_link_condition(const Tuple& e_tuple) const;
1550};
1551
1552
1553} // namespace wmtk
Definition TetMesh.h:201
a Tuple refers to a global vid and a global tet id, and a local edge id and local face id
Definition TetMesh.h:49
Tuple switch_face(const TetMesh &m) const
Definition TetMeshTuple.cpp:284
bool is_valid(const TetMesh &m) const
Definition TetMeshTuple.cpp:57
bool is_boundary_face(const TetMesh &m) const
Definition TetMeshTuple.cpp:17
void print_info() const
prints the tuple
Definition TetMeshTuple.cpp:68
std::optional< Tuple > switch_tetrahedron(const TetMesh &m) const
Definition TetMeshTuple.cpp:304
size_t eid(const TetMesh &m) const
Definition TetMeshTuple.cpp:111
Tuple switch_edge(const TetMesh &m) const
Definition TetMeshTuple.cpp:269
Tuple switch_vertex(const TetMesh &m) const
Definition TetMeshTuple.cpp:255
size_t tid(const TetMesh &m) const
Definition TetMeshTuple.cpp:250
size_t vid(const TetMesh &m) const
Definition TetMeshTuple.cpp:106
size_t fid(const TetMesh &m) const
Definition TetMeshTuple.cpp:184
bool is_boundary_edge(const TetMesh &m) const
Definition TetMeshTuple.cpp:34
void check_validity(const TetMesh &m) const
check Tuple validity and connectivity validity
Definition TetMeshTuple.cpp:389
Definition TetMesh.h:247
Definition TetMesh.h:24
size_t compute_vertex_order(const size_t vid) const
Compute the vertex order for a single vertex.
Definition TetMeshSubstructure.cpp:117
virtual bool swap_edge_44_after(const Tuple &t)
User specified modifications and desideratas for after a 4-4 edge swap.
Definition TetMesh.h:816
std::vector< Tuple > get_one_ring_vertices_for_vertex(const Tuple &t) const
Get the one ring vertices for a vertex.
Definition TetMesh.cpp:787
size_t vertex_valence(const size_t vid) const
Number of tets incident to a vertex, in O(1).
Definition TetMesh.h:1008
virtual bool swap_edge_44_before(const Tuple &t)
User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity.
Definition TetMesh.h:793
virtual bool split_tet_before(const Tuple &t)
User specified preparations and desideratas for a tet split before changing the connectivity.
Definition TetMesh.h:942
size_t lowest_common_tet(size_t v0_id, size_t v1_id, size_t v2_id) const
Lowest tet id incident to all three vertices, or size_t(-1) if there is none.
Definition TetMesh.cpp:407
bool try_set_face_mutex_n_ring(size_t v1, size_t v2, size_t v3, int threadid, int n)
try_set_vertex_mutex_n_ring seeded from the three vertices of a face.
Definition TetMesh.cpp:1148
size_t tet_size() const
get the number of unremoved tets
Definition TetMesh.h:394
virtual size_t get_order_of_vertex(const size_t vid) const
Get the order of a vertex.
Definition TetMesh.h:1522
std::vector< Tuple > get_faces() const
Definition TetMesh.cpp:235
std::array< Tuple, 6 > tet_edges(const Tuple &t) const
get the 6 edges of a tet represented by Tuples
Definition TetMesh.cpp:750
virtual bool smooth_after(const Tuple &t)
User specified modifications and desideratas for after smoothing a vertex.
Definition TetMesh.h:917
void consolidate_mesh()
cleans up the deleted vertices or tetrahedra, fixes the corresponding indices, and reset the version ...
Definition TetMesh.cpp:915
size_t vert_capacity() const
get the current largest global vid
Definition TetMesh.h:355
virtual bool collapse_edge_after(const Tuple &t)
User specified modifications and desideratas for after an edge collapse.
Definition TetMesh.h:785
void set_preallocation_factor(double factor)
Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so op...
Definition TetMesh.h:662
virtual bool swap_edge_after(const Tuple &t)
User specified modifications and desideratas for after a 3-2 edge swap.
Definition TetMesh.h:888
size_t get_num_surface_faces_for_edge(const std::array< size_t, 2 > &vids) const
Get the number of surface faces incident to the edge.
Definition TetMeshSubstructure.cpp:82
bool smooth_vertex(const Tuple &t)
Definition TetMesh.cpp:363
virtual bool face_is_on_surface(const size_t fid) const
Is a face part of the substructure.
Definition TetMesh.h:1475
bool insert_point(const Tuple &t, std::vector< Tuple > &new_tets)
Insert a point into a tetmesh inside a tet. In general position, this split a tet into 4....
Definition TetMeshTriangleInsertionConn.cpp:415
bool split_edge(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshEdgeSplittingConn.cpp:6
Tuple switch_face(const Tuple &t) const
wrapper function from Tuple::switch_face
Definition TetMesh.h:1061
std::array< Tuple, 4 > oriented_tet_vertices(const Tuple &t) const
Definition TetMesh.cpp:710
void for_each_vertex(const std::function< void(const TetMesh::Tuple &)> &)
perform the given function for each vertex
Definition TetMesh.cpp:1565
bool try_set_vertex_mutex_one_ring(const Tuple &v, int threadid=0)
Lock v and its one-ring. Complete, unlike the two-ring family.
Definition TetMesh.cpp:1477
std::array< size_t, 4 > oriented_tet_vids(const Tuple &t) const
Definition TetMesh.cpp:722
bool collapse_edge_check_topology(const std::vector< size_t > &new_tet_id)
Check topology after collapse connectivity change. This is a sanity check and should not be necessary...
Definition TetMeshEdgeCollapsingConn.cpp:418
bool try_set_vertex_mutex_two_ring_vid(const Tuple &v, int threadid)
try_set_vertex_mutex_two_ring reached through vids rather than Tuples.
Definition TetMesh.cpp:1182
Tuple tuple_from_tet(size_t tid) const
get a Tuple from global tetra index
Definition TetMesh.cpp:640
void subdivide_tets(const std::vector< size_t > t_ids, const std::vector< bool > &mark_surface, const std::map< std::array< size_t, 2 >, size_t > &map_edge2vid, std::map< std::array< size_t, 3 >, std::vector< std::array< size_t, 5 > > > &new_face_vids, const std::vector< size_t > &new_vids, std::vector< size_t > &new_tids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > &center_split_tets)
Definition TetMeshTriangleInsertionConn.cpp:142
void init(size_t n_vertices, const std::vector< std::array< size_t, 4 > > &tets)
Definition TetMesh.cpp:79
std::optional< std::tuple< Tuple, size_t > > try_tuple_from_face(const std::array< size_t, 3 > &vids) const
tuple_from_face for callers where a missing face is an answer, not a bug.
Definition TetMesh.cpp:465
void subdivide_a_tet(size_t t_id, const std::array< int, 6 > &new_v_ids, bool mark_surface, std::map< std::array< size_t, 3 >, std::vector< std::array< size_t, 5 > > > &new_face_vids, std::vector< size_t > &new_tids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > &center_split_tets)
Definition TetMeshTriangleInsertionConn.cpp:235
virtual bool swap_edge_56_before(const Tuple &t)
User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity.
Definition TetMesh.h:837
std::vector< Tuple > get_incident_tets_for_edge(const Tuple &t) const
Get the incident tets for edge.
Definition TetMesh.cpp:859
virtual bool split_face_after(const Tuple &t)
Compute the attributes for the added simplices.
Definition TetMesh.h:934
bool swap_edge_56(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshSwapMeshConnectivity.cpp:718
bool split_face(const Tuple &t, std::vector< Tuple > &new_tets)
Split a face in 3 faces.
Definition TetMeshFaceSplittingConn.cpp:6
bool link_condition(const Tuple &t)
Definition TetMeshEdgeCollapsingConn.cpp:309
std::vector< Tuple > get_one_ring_tets_for_edge(const Tuple &t) const
Get the one ring tets for edge.
Definition TetMesh.cpp:895
virtual bool split_face_before(const Tuple &t)
User specified preparations and desideratas for a face split before changing the connectivity.
Definition TetMesh.h:925
virtual double swap_edge_44_energy(const std::vector< std::array< size_t, 4 > > &tets, const int op_case)
User specified energy to decide which of the 4 possible orientations should be chosen.
Definition TetMesh.h:804
Tuple tuple_from_vertex(size_t vid) const
get a Tuple from global vertex index
Definition TetMesh.cpp:627
simplex::SimplexCollection get_surface_faces_for_vertex(const size_t vid) const
Get all faces on the surface that are incident to vid.
Definition TetMeshSubstructure.cpp:7
bool try_set_edge_mutex_n_ring(const Tuple &e, int threadid, int n)
try_set_vertex_mutex_n_ring seeded from both ends of an edge.
Definition TetMesh.cpp:1132
bool lock_vertex_ball(const size_t *seeds, size_t n_seeds, int threadid, int n, size_t mark)
The n-ring BFS. mark is the release-stack watermark to unwind to on failure.
Definition TetMesh.cpp:1042
virtual void for_each_face(const std::function< void(const TetMesh::Tuple &)> &)
looping through all the unique edges and perform the given function
Definition TetMesh.cpp:221
std::vector< size_t > get_one_ring_vids_for_vertex(size_t vid, std::vector< size_t > &cache)
Get the one ring vids for vertex.
Definition TetMesh.cpp:835
std::optional< Tuple > switch_tetrahedron(const Tuple &t) const
wrapper function from Tuple::switch_tetrahedron
Definition TetMesh.h:1070
size_t get_order_of_edge(const std::array< size_t, 2 > &vids) const
Compute the order of an edge.
Definition TetMeshSubstructure.cpp:203
const std::vector< size_t > & get_one_ring_tids_for_vertex(const Tuple &t) const
Get the one ring tids for vertex.
Definition TetMesh.cpp:763
std::vector< Tuple > get_tets() const
Definition TetMesh.cpp:330
virtual bool smooth_before(const Tuple &t)
User specified preparations and desideratas for smoothing a vertex.
Definition TetMesh.h:910
virtual bool split_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge split before changing the connectivity.
Definition TetMesh.h:756
std::vector< size_t > get_one_ring_vids_for_vertex_adj(size_t vid) const
Duplicate of the function TetMesh::get_one_ring_vids_for_vertex.
Definition TetMesh.cpp:821
virtual bool swap_edge_before(const Tuple &t)
User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity.
Definition TetMesh.h:881
void triangle_insertion(const std::vector< Tuple > &intersected_tets, const std::vector< Tuple > &intersected_edges, std::vector< size_t > &new_edge_vids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > &center_split_tets)
Insert a triangle into a tetmesh, with known intersection information.
Definition TetMeshTriangleInsertionConn.cpp:11
std::map< size_t, VertexConnectivity > operation_update_connectivity_impl(std::vector< size_t > &affected_tid, const std::vector< std::array< size_t, 4 > > &new_tet_conn, bool &ok)
Definition TetMeshSwapMeshConnectivity.cpp:43
bool check_mesh_connectivity_validity() const
checks the validity of the connectivity of the mesh. Including the validity of each Tuple
Definition TetMesh.cpp:256
bool split_tet(const Tuple &t, std::vector< Tuple > &new_tets)
Split a tet in 4 tets.
Definition TetMeshTetSplittingConn.cpp:6
Tuple tuple_from_edge(size_t tid, int local_eid) const
get a Tuple from global tetra index and local edge index (from 0-5).
Definition TetMesh.cpp:377
size_t vertex_size() const
get the number of unremoved verticies
Definition TetMesh.h:382
Tuple switch_vertex(const Tuple &t) const
wrapper function from Tuple::switch_vertex
Definition TetMesh.h:1043
simplex::SimplexCollection get_surface_faces_for_edge(const std::array< size_t, 2 > &vids) const
Get all faces on the surface that are incident to the edge.
Definition TetMeshSubstructure.cpp:42
bool substructure_link_condition(const Tuple &e_tuple) const
Link condition that also considers substructures.
Definition TetMeshSubstructure.cpp:218
virtual bool swap_face_before(const Tuple &t)
User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry.
Definition TetMesh.h:896
bool try_set_edge_mutex_two_ring(const Tuple &e, int threadid=0)
Lock the edge's one-ring and, partially, its two-ring. See the note above.
Definition TetMesh.cpp:1231
virtual bool vertex_is_on_surface(const size_t vid) const
Is a vertex part of the substructure.
Definition TetMesh.h:1468
bool swap_edge(const Tuple &t, std::vector< Tuple > &new_tets)
3-2 edge swap
Definition TetMeshSwapMeshConnectivity.cpp:135
Tuple switch_edge(const Tuple &t) const
wrapper function from Tuple::switch_edge
Definition TetMesh.h:1052
std::vector< Tuple > get_edges() const
Definition TetMesh.cpp:181
virtual bool split_tet_after(const Tuple &t)
Compute the attributes for the added simplices.
Definition TetMesh.h:951
void for_each_edge(const std::function< void(const TetMesh::Tuple &)> &)
perform the given function for each edge
Definition TetMesh.cpp:1506
int release_vertex_mutex_to(size_t mark)
Release the mutexes taken since the release stack held mark entries.
Definition TetMesh.cpp:1025
void check_tuple_validity(const Tuple &t) const
Definition TetMesh.h:1184
void collapse_edge_rollback(size_t &v1_id, std::map< size_t, wmtk::TetMesh::VertexConnectivity > &rollback_vert_conn, std::vector< size_t > &n1_t_ids, std::vector< size_t > &new_tet_id, std::vector< TetrahedronConnectivity > &old_tets)
Definition TetMeshEdgeCollapsingConn.cpp:437
bool try_set_vertex_mutex_two_ring(const Tuple &v, int threadid)
Lock v's one-ring and, partially, its two-ring. See the note above.
Definition TetMesh.cpp:1160
bool try_set_vertex_mutex_n_ring(const Tuple &v, int threadid, int n)
Lock every vertex within graph distance n of v, the seed included.
Definition TetMesh.cpp:1127
virtual bool collapse_edge(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshEdgeCollapsingConn.cpp:263
bool try_set_face_mutex_two_ring(const Tuple &f, int threadid=0)
Lock the face's one-ring and, partially, its two-ring. See the note above.
Definition TetMesh.cpp:1277
Tuple tuple_from_face(size_t tid, int local_fid) const
get a Tuple from global tetra index and local face index (from 0-3).
Definition TetMesh.cpp:387
virtual bool split_edge_after(const Tuple &t)
This function computes the attributes for the added simplices. User specified modifications and desid...
Definition TetMesh.h:765
static constexpr std::array< std::array< int, 2 >, 6 > m_local_edges
local edges within a tet
Definition TetMesh.h:30
std::array< Tuple, 3 > get_face_vertices(const Tuple &t) const
Get the 3 vertices of a face represented by Tuple.
Definition TetMesh.cpp:732
virtual bool swap_edge_56_after(const Tuple &t)
User specified modifications and desideratas for after a 5-6 edge swap.
Definition TetMesh.h:860
virtual bool collapse_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge collapse before changing the connectivity.
Definition TetMesh.h:776
std::vector< Tuple > get_vertices() const
Definition TetMesh.cpp:346
bool collapse_edge_conn(const Tuple &loc0, size_t &v1_id, Tuple &new_loc, std::map< size_t, wmtk::TetMesh::VertexConnectivity > &rollback_vert_conn, std::vector< size_t > &n1_t_ids_copy, std::vector< size_t > &new_tet_id, std::vector< TetrahedronConnectivity > &old_tets)
Definition TetMeshEdgeCollapsingConn.cpp:448
size_t tet_capacity() const
get the current largest global tid
Definition TetMesh.h:361
std::vector< Tuple > get_one_ring_tets_for_vertex(const Tuple &t) const
Get the one ring tets for a vertex.
Definition TetMesh.cpp:776
void for_each_tetra(const std::function< void(const TetMesh::Tuple &)> &)
perform the given function for each tet
Definition TetMesh.cpp:1539
bool swap_edge_44(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshSwapMeshConnectivity.cpp:491
virtual bool swap_edge_56_accept_case(const std::array< size_t, 3 > &new_face)
Filter which of the 5-6 orientations may be chosen.
Definition TetMesh.h:873
virtual bool swap_edge_44_accept_case(const std::array< size_t, 2 > &new_edge)
Filter which of the 4-4 orientations may be chosen.
Definition TetMesh.h:829
virtual double swap_edge_56_energy(const std::vector< std::array< size_t, 4 > > &tets, const int op_case)
User specified energy to decide which of the 5 possible orientations should be chosen.
Definition TetMesh.h:848
bool swap_face(const Tuple &t, std::vector< Tuple > &new_tets)
2-3 face swap
Definition TetMeshSwapMeshConnectivity.cpp:248
void remove_tets_by_ids(const std::vector< size_t > &tids)
remove the tetrahedrons in the mesh that have given tet ids
Definition TetMesh.h:1197
Tuple tuple_from_vids(size_t vid0, size_t vid1, size_t vid2, size_t vid3) const
Get a Tuple from global vertex IDs.
Definition TetMesh.cpp:651
std::vector< std::array< size_t, 3 > > vertex_adjacent_boundary_faces(const Tuple &t) const
Definition TetMesh.cpp:1000
virtual bool swap_face_after(const Tuple &t)
User specified modifications and desideratas for after a 2-3 face swap.
Definition TetMesh.h:903
Definition Simplex.hpp:46
Definition Simplex.hpp:57
Definition SimplexCollection.hpp:9
Definition Simplex.hpp:71
A per-vertex lock plus the id of the thread currently holding it.
Definition vertex_mutex.hpp:29
Definition enumerable_thread_specific.hpp:26
Per-thread buffers for the n-ring lock, so a lock acquisition allocates nothing.
Definition TetMesh.h:1321