Wildmeshing Toolkit
top_dimension_cofaces.cpp
Go to the documentation of this file.
2 #include <wmtk/utils/Logger.hpp>
6 
7 #include <queue>
8 #include <set>
9 
10 #include <wmtk/EdgeMesh.hpp>
11 #include <wmtk/PointMesh.hpp>
12 #include <wmtk/TetMesh.hpp>
13 #include <wmtk/TriMesh.hpp>
14 
16 
17 namespace wmtk::simplex {
18 
19 namespace {
20 
21 
22 void top_dimension_cofaces_tuples_vertex(
23  const TriMesh& mesh,
24  const Tuple& t_in,
25  std::vector<Tuple>& collection)
26 {
27  assert(mesh.is_valid(t_in));
28  Tuple t = t_in;
29  do {
30  collection.emplace_back(t);
31 
32  if (mesh.is_boundary_edge(t)) {
33  break;
34  }
35  t = mesh.switch_tuples(t, {PrimitiveType::Triangle, PrimitiveType::Edge});
36  } while (t != t_in);
37 
38  if (t == t_in && !mesh.is_boundary_edge(t)) {
39  return;
40  }
41 
42  t = mesh.switch_edge(t_in);
43 
44  if (mesh.is_boundary_edge(t)) {
45  return;
46  }
47  t = mesh.switch_tuples(t, {PrimitiveType::Triangle, PrimitiveType::Edge});
48 
49  do {
50  collection.emplace_back(t);
51 
52  if (mesh.is_boundary_edge(t)) {
53  break;
54  }
55  t = mesh.switch_tuples(t, {PrimitiveType::Triangle, PrimitiveType::Edge});
56  } while (true);
57 }
58 void top_dimension_cofaces_tuples_edge(
59  const TriMesh& mesh,
60  const Tuple& t,
61  std::vector<Tuple>& collection)
62 {
63  collection.emplace_back(t);
64  if (!mesh.is_boundary_edge(t)) {
65  collection.emplace_back(mesh.switch_face(t));
66  }
67 }
68 void top_dimension_cofaces_tuples_face(
69  const TriMesh& mesh,
70  const Tuple& t,
71  std::vector<Tuple>& collection)
72 {
73  collection.emplace_back(t);
74 }
75 
76 void top_dimension_cofaces_tuples_vertex(
77  const TetMesh& mesh,
78  const Tuple& input,
79  std::vector<Tuple>& collection)
80 {
81  std::vector<int64_t> visited;
82  visited.reserve(50);
83 
84  auto is_visited = [&visited](const Tuple& t) -> bool {
85  const int64_t c = wmtk::utils::TupleInspector::global_cid(t);
86  for (const int64_t v : visited) {
87  if (v == c) {
88  return true;
89  }
90  }
91  visited.emplace_back(c);
92  return false;
93  };
94 
95  std::vector<Tuple> q(200);
96  size_t q_front = 0;
97  size_t q_back = 1;
98  q[0] = input;
99 
100  while (q_front != q_back) {
101  const Tuple t = q[q_front++];
102 
103 
104  if (is_visited(t)) {
105  continue;
106  }
107 
108  collection.emplace_back(t);
109 
110  if (q_back + 4 >= q.size()) {
111  q.resize(q.size() * 1.5);
112  // logger().info(
113  // "Increasing size of queue in top_dimension_cofaces_tuples_vertex to {}.",
114  // q.size());
115  // logger().info("Current collection size: {}", collection.size());
116  }
117 
118  const Tuple& t1 = t;
119  const Tuple t2 = mesh.switch_face(t);
120  const Tuple t3 = mesh.switch_tuples(t, {PrimitiveType::Edge, PrimitiveType::Triangle});
121 
122  if (!mesh.is_boundary_face(t1)) {
123  const Tuple ts = mesh.switch_tetrahedron(t1);
124  q[q_back++] = ts;
125  }
126  if (!mesh.is_boundary_face(t2)) {
127  const Tuple ts = mesh.switch_tetrahedron(t2);
128  q[q_back++] = ts;
129  }
130  if (!mesh.is_boundary_face(t3)) {
131  const Tuple ts = mesh.switch_tetrahedron(t3);
132  q[q_back++] = ts;
133  }
134  }
135 }
136 void top_dimension_cofaces_tuples_edge(
137  const TetMesh& mesh,
138  const Tuple& input,
139  std::vector<Tuple>& collection)
140 {
141  // std::set<Tuple, wmtk::utils::TupleCellLessThan> touched_cells;
142  // std::queue<Tuple> q;
143  // q.push(input);
144  // while (!q.empty()) {
145  // const Tuple t = q.front();
146  // q.pop();
147  //
148  // {
149  // // check if cell already exists
150  // const auto& [it, was_inserted] = touched_cells.insert(t);
151  // if (!was_inserted) {
152  // continue;
153  // }
154  // }
155  //
156  // collection.emplace_back(t);
157  //
158  // const Tuple& t1 = t;
159  // const Tuple t2 = mesh.switch_face(t);
160  //
161  // if (!mesh.is_boundary_face(t1)) {
162  // q.push(mesh.switch_tuples(t1, {PrimitiveType::Tetrahedron, PrimitiveType::Triangle}));
163  // }
164  // if (!mesh.is_boundary_face(t2)) {
165  // q.push(mesh.switch_tetrahedron(t2));
166  // }
167  //}
168 
169 
170  assert(mesh.is_valid(input));
171  Tuple t = input;
172  do {
173  collection.emplace_back(t);
174 
175  if (mesh.is_boundary_face(t)) {
176  break;
177  }
178  t = mesh.switch_tuples(t, {PrimitiveType::Tetrahedron, PrimitiveType::Triangle});
179  } while (t != input);
180 
181  if (t == input && !mesh.is_boundary_face(t)) {
182  return;
183  }
184 
185  t = input;
186 
187  if (mesh.is_boundary_face(mesh.switch_face(t))) {
188  return;
189  }
190 
191  t = mesh.switch_tuples(t, {PrimitiveType::Triangle, PrimitiveType::Tetrahedron});
192 
193  do {
194  collection.emplace_back(t);
195 
196  if (mesh.is_boundary_face(mesh.switch_face(t))) {
197  break;
198  }
199  t = mesh.switch_tuples(t, {PrimitiveType::Triangle, PrimitiveType::Tetrahedron});
200  } while (true);
201 
202  // t = mesh.switch_face(input);
203 
204  // if (mesh.is_boundary_face(t)) {
205  // return;
206  // }
207  // t = mesh.switch_tuples(t, {PrimitiveType::Tetrahedron, PrimitiveType::Triangle});
208 
209  // do {
210  // collection.emplace_back(t);
211 
212  // if (mesh.is_boundary_face(t)) {
213  // break;
214  // }
215  // t = mesh.switch_tuples(t, {PrimitiveType::Tetrahedron, PrimitiveType::Triangle});
216  // } while (true);
217 }
218 
219 void top_dimension_cofaces_tuples_face(
220  const TetMesh& mesh,
221  const Tuple& input,
222  std::vector<Tuple>& collection)
223 {
224  collection.emplace_back(input);
225  if (!mesh.is_boundary_face(input)) {
226  collection.emplace_back(mesh.switch_tetrahedron(input));
227  }
228 }
229 void top_dimension_cofaces_tuples_tet(
230  const TetMesh& mesh,
231  const Tuple& t,
232  std::vector<Tuple>& collection)
233 {
234  collection.emplace_back(t);
235 }
236 
237 std::vector<Tuple> top_dimension_cofaces_tuples_vertex(const TriMesh& mesh, const Tuple& t)
238 {
239  std::vector<Tuple> collection;
240  top_dimension_cofaces_tuples_vertex(mesh, t, collection);
241  return collection;
242 }
243 std::vector<Tuple> top_dimension_cofaces_tuples_edge(const TriMesh& mesh, const Tuple& t)
244 {
245  std::vector<Tuple> collection;
246  top_dimension_cofaces_tuples_edge(mesh, t, collection);
247  return collection;
248 }
249 std::vector<Tuple> top_dimension_cofaces_tuples_face(const TriMesh& mesh, const Tuple& t)
250 {
251  std::vector<Tuple> collection;
252  top_dimension_cofaces_tuples_face(mesh, t, collection);
253  return collection;
254 }
255 
256 std::vector<Tuple> top_dimension_cofaces_tuples_vertex(const TetMesh& mesh, const Tuple& input)
257 {
258  std::vector<Tuple> collection;
259  top_dimension_cofaces_tuples_vertex(mesh, input, collection);
260  return collection;
261 }
262 std::vector<Tuple> top_dimension_cofaces_tuples_edge(const TetMesh& mesh, const Tuple& input)
263 {
264  std::vector<Tuple> collection;
265  top_dimension_cofaces_tuples_edge(mesh, input, collection);
266  return collection;
267 }
268 std::vector<Tuple> top_dimension_cofaces_tuples_face(const TetMesh& mesh, const Tuple& input)
269 {
270  std::vector<Tuple> collection;
271  top_dimension_cofaces_tuples_face(mesh, input, collection);
272  return collection;
273 }
274 std::vector<Tuple> top_dimension_cofaces_tuples_tet(const TetMesh& mesh, const Tuple& t)
275 {
276  std::vector<Tuple> collection;
277  top_dimension_cofaces_tuples_tet(mesh, t, collection);
278  return collection;
279 }
280 
281 
282 } // namespace
283 
284 namespace {
285 
286 
287 void top_dimension_cofaces_tuples_vertex(
288  const TriMesh& mesh,
289  const Tuple& t_in,
290  SimplexCollection& collection)
291 {
292  assert(mesh.is_valid(t_in));
293  std::set<Tuple, wmtk::utils::TupleCellLessThan> touched_cells;
294  std::queue<Tuple> q;
295  q.push(t_in);
296  while (!q.empty()) {
297  const Tuple t = q.front();
298  q.pop();
299 
300  {
301  // check if cell already exists
302  const auto [it, did_insert] = touched_cells.insert(t);
303  if (!did_insert) {
304  continue;
305  }
306  }
307  collection.add(PrimitiveType::Triangle, t);
308 
309  if (!mesh.is_boundary_edge(t)) {
310  q.push(mesh.switch_tuples(t, {PrimitiveType::Triangle, PrimitiveType::Edge}));
311  }
312  const Tuple t_other = mesh.switch_edge(t);
313  if (!mesh.is_boundary_edge(t_other)) {
314  q.push(mesh.switch_face(t_other));
315  }
316  }
317 }
318 void top_dimension_cofaces_tuples_edge(
319  const TriMesh& mesh,
320  const Tuple& t,
321  SimplexCollection& collection)
322 {
323  collection.add(PrimitiveType::Triangle, t);
324  if (!mesh.is_boundary_edge(t)) {
325  collection.add(PrimitiveType::Triangle, mesh.switch_face(t));
326  }
327 }
328 void top_dimension_cofaces_tuples_face(
329  const TriMesh& mesh,
330  const Tuple& t,
331  SimplexCollection& collection)
332 {
333  collection.add(PrimitiveType::Triangle, t);
334 }
335 
336 void top_dimension_cofaces_tuples_vertex(
337  const TetMesh& mesh,
338  const Tuple& input,
339  SimplexCollection& collection)
340 {
341  std::set<Tuple, wmtk::utils::TupleCellLessThan> touched_cells;
342  std::queue<Tuple> q;
343  q.push(input);
344  while (!q.empty()) {
345  const Tuple t = q.front();
346  q.pop();
347 
348  {
349  // check if cell already exists
350  const auto& [it, was_inserted] = touched_cells.insert(t);
351  if (!was_inserted) {
352  continue;
353  }
354  }
355 
356  collection.add(PrimitiveType::Tetrahedron, t);
357 
358  const Tuple& t1 = t;
359  const Tuple t2 = mesh.switch_face(t);
360  const Tuple t3 = mesh.switch_tuples(t, {PrimitiveType::Edge, PrimitiveType::Triangle});
361 
362  if (!mesh.is_boundary_face(t1)) {
363  q.push(mesh.switch_tetrahedron(t1));
364  }
365  if (!mesh.is_boundary_face(t2)) {
366  q.push(mesh.switch_tetrahedron(t2));
367  }
368  if (!mesh.is_boundary_face(t3)) {
369  q.push(mesh.switch_tetrahedron(t3));
370  }
371  }
372 }
373 void top_dimension_cofaces_tuples_edge(
374  const TetMesh& mesh,
375  const Tuple& input,
376  SimplexCollection& collection)
377 {
378  std::set<Tuple, wmtk::utils::TupleCellLessThan> touched_cells;
379  std::queue<Tuple> q;
380  q.push(input);
381  while (!q.empty()) {
382  const Tuple t = q.front();
383  q.pop();
384 
385  {
386  // check if cell already exists
387  const auto& [it, was_inserted] = touched_cells.insert(t);
388  if (!was_inserted) {
389  continue;
390  }
391  }
392 
393  collection.add(PrimitiveType::Tetrahedron, t);
394 
395  const Tuple& t1 = t;
396  const Tuple t2 = mesh.switch_face(t);
397 
398  if (!mesh.is_boundary_face(t1)) {
399  q.push(mesh.switch_tuples(t1, {PrimitiveType::Tetrahedron, PrimitiveType::Triangle}));
400  }
401  if (!mesh.is_boundary_face(t2)) {
402  q.push(mesh.switch_tetrahedron(t2));
403  }
404  }
405 }
406 
407 void top_dimension_cofaces_tuples_face(
408  const TetMesh& mesh,
409  const Tuple& input,
410  SimplexCollection& collection)
411 {
412  collection.add(PrimitiveType::Tetrahedron, input);
413  if (!mesh.is_boundary_face(input)) {
414  collection.add(PrimitiveType::Tetrahedron, mesh.switch_tetrahedron(input));
415  }
416 }
417 void top_dimension_cofaces_tuples_tet(
418  const TetMesh& mesh,
419  const Tuple& t,
420  SimplexCollection& collection)
421 {
422  collection.add(PrimitiveType::Tetrahedron, t);
423 }
424 
425 
426 } // namespace
427 
429  const Simplex& simplex,
430  SimplexCollection& simplex_collection,
431  const bool sort_and_clean)
432 {
433  const auto& m = simplex_collection.mesh();
434  top_dimension_cofaces_tuples(m, simplex, simplex_collection);
435  if (sort_and_clean) {
436  simplex_collection.sort_and_clean();
437  }
438 }
439 
441  const PointMesh& mesh,
442  const Simplex& simplex,
443  SimplexCollection& collection)
444 {
445  switch (simplex.primitive_type()) {
446  case PrimitiveType::Vertex: {
447  collection.add(simplex);
448  break;
449  }
450  case PrimitiveType::Edge: {
451  log_and_throw_error("top_dimension_cofaces_tuples not implemented for Edge in PointMesh");
452  break;
453  }
455  log_and_throw_error("top_dimension_cofaces_tuples not implemented for Face in PointMesh");
456  }
459  "top_dimension_cofaces_tuples not implemented for Tetrahedron in PointMesh");
460  default: assert(false); break;
461  }
462 }
463 
465  const EdgeMesh& mesh,
466  const Simplex& simplex,
467  SimplexCollection& collection)
468 {
469  switch (simplex.primitive_type()) {
470  case PrimitiveType::Vertex: {
471  collection.add(simplex);
472  if (!mesh.is_boundary_vertex(simplex.tuple())) {
473  collection.add(simplex.primitive_type(), mesh.switch_edge(simplex.tuple()));
474  }
475  break;
476  }
477  case PrimitiveType::Edge: {
478  collection.add(simplex);
479  break;
480  }
482  log_and_throw_error("top_dimension_cofaces_tuples not implemented for Face in EdgeMesh");
483  }
485  default: assert(false); break;
486  }
487 }
488 
490  const TriMesh& mesh,
491  const Simplex& simplex,
492  SimplexCollection& collection)
493 {
494  switch (simplex.primitive_type()) {
495  case PrimitiveType::Vertex: {
496  top_dimension_cofaces_tuples_vertex(mesh, simplex.tuple(), collection);
497  break;
498  }
499  case PrimitiveType::Edge: {
500  top_dimension_cofaces_tuples_edge(mesh, simplex.tuple(), collection);
501  break;
502  }
504  top_dimension_cofaces_tuples_face(mesh, simplex.tuple(), collection);
505  break;
506  }
508  default: assert(false); break;
509  }
510 }
511 
513  const TetMesh& mesh,
514  const Simplex& simplex,
515  SimplexCollection& collection)
516 {
517  switch (simplex.primitive_type()) {
518  case PrimitiveType::Vertex: {
519  top_dimension_cofaces_tuples_vertex(mesh, simplex.tuple(), collection);
520  break;
521  }
522  case PrimitiveType::Edge: {
523  top_dimension_cofaces_tuples_edge(mesh, simplex.tuple(), collection);
524  break;
525  }
527  top_dimension_cofaces_tuples_face(mesh, simplex.tuple(), collection);
528  break;
529  }
531  top_dimension_cofaces_tuples_tet(mesh, simplex.tuple(), collection);
532  break;
533  }
534  default: assert(false); break;
535  }
536 }
537 
539  const Mesh& mesh,
540  const Simplex& simplex,
541  SimplexCollection& collection)
542 {
543  switch (mesh.top_simplex_type()) {
545  top_dimension_cofaces_tuples(static_cast<const TriMesh&>(mesh), simplex, collection);
546  break;
548  top_dimension_cofaces_tuples(static_cast<const TetMesh&>(mesh), simplex, collection);
549  break;
550  case PrimitiveType::Edge:
551  top_dimension_cofaces_tuples(static_cast<const EdgeMesh&>(mesh), simplex, collection);
552  break;
554  top_dimension_cofaces_tuples(static_cast<const PointMesh&>(mesh), simplex, collection);
555  break;
556  default: log_and_throw_error("unknown mesh type in top_dimension_cofaces_tuples");
557  }
558 }
559 
560 
562  const PointMesh& mesh,
563  const Simplex& simplex,
564  std::vector<Tuple>& collection)
565 {
566  switch (simplex.primitive_type()) {
567  case PrimitiveType::Vertex: {
568  collection.emplace_back(simplex.tuple());
569  break;
570  }
571  case PrimitiveType::Edge: {
572  log_and_throw_error("top_dimension_cofaces_tuples not implemented for Edge in PointMesh");
573  break;
574  }
576  log_and_throw_error("top_dimension_cofaces_tuples not implemented for Face in PointMesh");
577  }
580  "top_dimension_cofaces_tuples not implemented for Tetrahedron in PointMesh");
581  default: assert(false); break;
582  }
583 }
585  const EdgeMesh& mesh,
586  const Simplex& simplex,
587  std::vector<Tuple>& collection)
588 {
589  switch (simplex.primitive_type()) {
590  case PrimitiveType::Vertex: {
591  collection.emplace_back(simplex.tuple());
592  if (!mesh.is_boundary_vertex(simplex.tuple())) {
593  collection.emplace_back(mesh.switch_edge(simplex.tuple()));
594  }
595  break;
596  }
597  case PrimitiveType::Edge: {
598  collection.emplace_back(simplex.tuple());
599  break;
600  }
602  throw std::runtime_error(
603  "top_dimension_cofaces_tuples not implemented for Face in EdgeMesh");
604  break;
605  }
607  default: assert(false); break;
608  }
609 }
610 
612  const TriMesh& mesh,
613  const Simplex& simplex,
614  std::vector<Tuple>& collection)
615 {
616  switch (simplex.primitive_type()) {
617  case PrimitiveType::Vertex: {
618  collection = top_dimension_cofaces_tuples_vertex(mesh, simplex.tuple());
619  break;
620  }
621  case PrimitiveType::Edge: {
622  collection = top_dimension_cofaces_tuples_edge(mesh, simplex.tuple());
623  break;
624  }
626  collection = top_dimension_cofaces_tuples_face(mesh, simplex.tuple());
627  break;
628  }
630  default: assert(false); break;
631  }
632 }
633 
635  const TetMesh& mesh,
636  const Simplex& simplex,
637  std::vector<Tuple>& collection)
638 {
639  switch (simplex.primitive_type()) {
640  case PrimitiveType::Vertex: {
641  collection = top_dimension_cofaces_tuples_vertex(mesh, simplex.tuple());
642  break;
643  }
644  case PrimitiveType::Edge: {
645  collection = top_dimension_cofaces_tuples_edge(mesh, simplex.tuple());
646  break;
647  }
649  collection = top_dimension_cofaces_tuples_face(mesh, simplex.tuple());
650  break;
651  }
653  collection = top_dimension_cofaces_tuples_tet(mesh, simplex.tuple());
654  break;
655  }
656  default: assert(false); break;
657  }
658 }
659 
661  const Mesh& mesh,
662  const Simplex& simplex,
663  std::vector<Tuple>& tuples)
664 {
665  switch (mesh.top_simplex_type()) {
667  top_dimension_cofaces_tuples(static_cast<const TriMesh&>(mesh), simplex, tuples);
668  break;
670  top_dimension_cofaces_tuples(static_cast<const TetMesh&>(mesh), simplex, tuples);
671  break;
672  case PrimitiveType::Edge:
673  top_dimension_cofaces_tuples(static_cast<const EdgeMesh&>(mesh), simplex, tuples);
674  break;
676  top_dimension_cofaces_tuples(static_cast<const PointMesh&>(mesh), simplex, tuples);
677  break;
678  default: assert(false); //"unknown mesh type in top_dimension_cofaces_tuples"
679  }
680 }
681 
682 
683 SimplexCollection
684 top_dimension_cofaces(const TriMesh& mesh, const Simplex& simplex, const bool sort_and_clean)
685 {
686  SimplexCollection collection(
687  mesh,
689  mesh,
690  top_dimension_cofaces_tuples(mesh, simplex),
692  if (sort_and_clean) {
693  collection.sort_and_clean();
694  }
695 
696  return collection;
697 }
698 
699 SimplexCollection
700 top_dimension_cofaces(const TetMesh& mesh, const Simplex& simplex, const bool sort_and_clean)
701 {
702  SimplexCollection collection(
703  mesh,
705  mesh,
706  top_dimension_cofaces_tuples(mesh, simplex),
708  if (sort_and_clean) {
709  collection.sort_and_clean();
710  }
711 
712  return collection;
713 }
714 
715 SimplexCollection
716 top_dimension_cofaces(const Mesh& mesh, const Simplex& simplex, const bool sort_and_clean)
717 {
718  SimplexCollection collection(
719  mesh,
721  mesh,
722  top_dimension_cofaces_tuples(mesh, simplex),
723  mesh.top_simplex_type()));
724  if (sort_and_clean) {
725  collection.sort_and_clean();
726  }
727 
728  return collection;
729 }
730 
731 std::vector<Tuple> top_dimension_cofaces_tuples(const PointMesh& mesh, const Simplex& simplex)
732 {
733  std::vector<Tuple> collection;
734  top_dimension_cofaces_tuples(mesh, simplex, collection);
735  return collection;
736 }
737 
738 
739 std::vector<Tuple> top_dimension_cofaces_tuples(const EdgeMesh& mesh, const Simplex& simplex)
740 {
741  std::vector<Tuple> collection;
742  top_dimension_cofaces_tuples(mesh, simplex, collection);
743  return collection;
744 }
745 
746 std::vector<Tuple> top_dimension_cofaces_tuples(const TriMesh& mesh, const Simplex& simplex)
747 {
748  std::vector<Tuple> collection;
749  top_dimension_cofaces_tuples(mesh, simplex, collection);
750  return collection;
751 }
752 
753 std::vector<Tuple> top_dimension_cofaces_tuples(const TetMesh& mesh, const Simplex& simplex)
754 {
755  std::vector<Tuple> collection;
756  top_dimension_cofaces_tuples(mesh, simplex, collection);
757  return collection;
758 }
759 
760 std::vector<Tuple> top_dimension_cofaces_tuples(const Mesh& mesh, const Simplex& simplex)
761 {
762  switch (mesh.top_simplex_type()) {
764  return top_dimension_cofaces_tuples(static_cast<const TriMesh&>(mesh), simplex);
766  return top_dimension_cofaces_tuples(static_cast<const TetMesh&>(mesh), simplex);
767  case PrimitiveType::Edge:
768  return top_dimension_cofaces_tuples(static_cast<const EdgeMesh&>(mesh), simplex);
770  return top_dimension_cofaces_tuples(static_cast<const PointMesh&>(mesh), simplex);
771  default:
772  assert(false);
773  throw std::runtime_error("unknown mesh type in top_dimension_cofaces_tuples");
774  }
775 }
776 
777 } // namespace wmtk::simplex
Tuple switch_edge(const Tuple &tuple) const
Definition: EdgeMesh.hpp:94
bool is_boundary_vertex(const Tuple &tuple) const
Definition: EdgeMesh.cpp:31
PrimitiveType top_simplex_type() const
Definition: Mesh.hpp:996
void add(const Simplex &simplex)
Add simplex to the collection.
void sort_and_clean()
Sort simplex vector and remove duplicates.
const Tuple & tuple() const
Definition: Simplex.hpp:53
PrimitiveType primitive_type() const
Definition: Simplex.hpp:51
static int64_t global_cid(const Tuple &t)
std::shared_ptr< Mesh > input(const std::filesystem::path &file, const bool ignore_z_if_zero, const std::vector< std::string > &tetrahedron_attributes)
Definition: input.cpp:12
std::vector< Simplex > tuple_vector_to_homogeneous_simplex_vector(const Mesh &m, const std::vector< Tuple > &tups, PrimitiveType primitive)
void top_dimension_cofaces_tuples(const PointMesh &mesh, const Simplex &simplex, SimplexCollection &collection)
void top_dimension_cofaces(const Simplex &simplex, SimplexCollection &simplex_collection, const bool sort_and_clean)
Get all top dimension cofaces of the given simplex.
void log_and_throw_error(const std::string &msg)
Definition: Logger.cpp:101