libMesh
Loading...
Searching...
No Matches
mesh_tet_test.C
Go to the documentation of this file.
1#include <libmesh/boundary_info.h>
2#include <libmesh/elem.h>
3#include <libmesh/mesh.h>
4#include <libmesh/mesh_generation.h>
5#include <libmesh/mesh_netgen_interface.h>
6#include <libmesh/mesh_tetgen_interface.h>
7#include <libmesh/mesh_tet_interface.h>
8#include <libmesh/mesh_tools.h>
9#include <libmesh/parallel_implementation.h> // max()
10
11#include "test_comm.h"
12#include "libmesh_cppunit.h"
13
14#include <algorithm>
15#include <array>
16#include <cmath>
17#include <map>
18#include <regex>
19
20
21using namespace libMesh;
22
23namespace {
24
25Real build_octahedron (UnstructuredMesh & mesh, bool flip_tris,
26 Real xmin, Real xmax,
27 Real ymin, Real ymax,
28 Real zmin, Real zmax)
29{
31 (mesh, xmin, xmax, ymin, ymax, zmin, zmax, flip_tris);
32
33 // Octahedron volume
34 return (xmax-xmin)*(ymax-ymin)*(zmax-zmin)/6;
35}
36
37}
38
39
40class MeshTetTest : public CppUnit::TestCase
41{
46public:
48
49#ifdef LIBMESH_HAVE_NETGEN
50 // The most basic test to start with
61
62#ifdef LIBMESH_ENABLE_AMR
64#endif
65
66 // We'll get to more advanced features later
67 /*
68 CPPUNIT_TEST( testNetGenInterp );
69 CPPUNIT_TEST( testNetGenInterp2 );
70 CPPUNIT_TEST( testNetGenRefined );
71 CPPUNIT_TEST( testNetGenNonRefined );
72 CPPUNIT_TEST( testNetGenExtraRefined );
73 */
74#endif
75
76 // Still need to work out the basics here - non-convex domains,
77 // precise control of refinement, etc.
78#ifdef LIBMESH_HAVE_TETGEN
79 /*
80 CPPUNIT_TEST( testTetGen );
81 CPPUNIT_TEST( testTetGenError );
82 CPPUNIT_TEST( testTetGenInterp );
83 CPPUNIT_TEST( testTetGenInterp2 );
84 */
85#endif
86
88
89public:
90 void setUp() {}
91
92 void tearDown() {}
93
94 void testExceptionBase(const char * re,
95 MeshBase & mesh,
96 MeshTetInterface & tetinterface,
97 dof_id_type expected_n_elem = DofObject::invalid_id,
98 dof_id_type expected_n_nodes = DofObject::invalid_id,
99 Real expected_volume = 0)
100 {
101#ifdef LIBMESH_ENABLE_EXCEPTIONS
102 // We can't just CPPUNIT_ASSERT_THROW, because we want to make
103 // sure we were thrown from the right place with the right error
104 // message!
105 bool threw_desired_exception = false;
106 try {
107 this->testTetInterfaceBase(mesh, tetinterface, expected_n_elem,
108 expected_n_nodes, expected_volume);
109 }
110 catch (libMesh::LogicError & e) {
111 std::regex msg_regex(re);
112 CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
113 threw_desired_exception = true;
114 }
115 catch (CppUnit::Exception & e) {
116 throw e;
117 }
118 catch (...) {
119 CPPUNIT_ASSERT_MESSAGE("Unexpected exception type thrown", false);
120 }
121 CPPUNIT_ASSERT(threw_desired_exception);
122#endif
123 }
124
125
127 MeshTetInterface & triangulator,
128 dof_id_type expected_n_elem = DofObject::invalid_id,
129 dof_id_type expected_n_nodes = DofObject::invalid_id,
130 Real expected_volume = 0)
131 {
132 triangulator.triangulate();
133
134 if (expected_n_elem != DofObject::invalid_id)
135 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), expected_n_elem);
136
137 if (expected_n_nodes != DofObject::invalid_id)
138 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), expected_n_nodes);
139
140 if (expected_volume != 0)
141 LIBMESH_ASSERT_FP_EQUAL(MeshTools::volume(mesh),
142 expected_volume,
144
145 for (const auto & elem : mesh.element_ptr_range())
146 {
147 CPPUNIT_ASSERT_EQUAL(elem->type(), TET4);
148
149 // Make sure we're not getting any inverted elements
150 CPPUNIT_ASSERT(!elem->is_flipped());
151 }
152 }
153
154
156 {
158 for (const auto & elem : mesh.element_ptr_range())
159 {
160 for (auto s : elem->side_index_range())
161 {
162 auto neigh = elem->neighbor_ptr(s);
163
164 if (neigh)
165 {
166 CPPUNIT_ASSERT_EQUAL(bi.n_boundary_ids(elem, s), 0u);
167 continue;
168 }
169
170 CPPUNIT_ASSERT_EQUAL(bi.n_boundary_ids(elem, s), 1u);
171
172 auto side = elem->side_ptr(s);
173 auto normal = (side->point(1) - side->point(0)).cross
174 (side->point(2) - side->point(0));
175 // Outer faces, in these tests
176 if (normal * side->vertex_average() > 0)
177 CPPUNIT_ASSERT(bi.has_boundary_id(elem, s, 0));
178 // Inner faces, with one-hole tests
179 else
180 CPPUNIT_ASSERT(bi.has_boundary_id(elem, s, 1));
181 }
182 }
183 }
184
185
187 MeshTetInterface & triangulator)
188 {
189 std::unique_ptr<UnstructuredMesh> holemesh =
190 std::make_unique<Mesh>(*TestCommWorld);
191
193 -2, 2, -2, 2, -2, 2);
194
195 const Real hole_volume =
196 build_octahedron(*holemesh, false, -1, 1, -1, 1, -1, 1);
197
198 auto holes =
199 std::make_unique<std::vector<std::unique_ptr<UnstructuredMesh>>>();
200
201 holes->push_back(std::move(holemesh));
202
203 triangulator.attach_hole_list(std::move(holes));
204
205 const Real expected_volume =
206 MeshTools::volume(mesh) - hole_volume;
207 this->testTetInterfaceBase(mesh, triangulator, 32, 14,
208 expected_volume);
209 }
210
211
212#ifdef LIBMESH_ENABLE_AMR
214 MeshTetInterface & triangulator)
215 {
216 std::unique_ptr<UnstructuredMesh> holemesh =
217 std::make_unique<Mesh>(*TestCommWorld);
218
219 MeshTools::Generation::build_sphere (*holemesh, 1, 2, TET4);
220
222
223 auto holes =
224 std::make_unique<std::vector<std::unique_ptr<UnstructuredMesh>>>();
225
226 holes->push_back(std::move(holemesh));
227
228 triangulator.attach_hole_list(std::move(holes));
229
230 // Netgen can't seem to triangulate this without inserting points,
231 // so let MeshNetgenInterface know that we're allowed to insert
232 // points
233 triangulator.desired_volume() = 1000;
234
235 this->testTetInterfaceBase(mesh, triangulator);
236 }
237#endif
238
239
241 MeshTetInterface & triangulator,
242 bool flip_tris = false,
243 bool flip_some_tris = false)
244 {
245 // An asymmetric octahedron, so we hopefully have an unambiguous
246 // choice of shortest diagonal for a Delaunay algorithm to pick.
247 const Real expected_volume =
248 build_octahedron(mesh, flip_tris, -1, 1, -1, 1, -0.1, 0.1);
249
250 // Flip a couple tri, breaking the mesh in a way we can fix
251 if (flip_some_tris)
252 for (auto elem : mesh.element_ptr_range())
253 {
254 Point center = elem->vertex_average();
255 if ((center(0) > 0 &&
256 center(1) > 0 &&
257 center(2) > 0) ||
258 (center(0) < 0 &&
259 center(1) < 0 &&
260 center(2) < 0))
261 elem->flip(&mesh.get_boundary_info());
262
264 }
265
266 this->testTetInterfaceBase(mesh, triangulator, /* n_elem = */ 4,
267 /* n_nodes = */ 6, expected_volume);
268 }
269
270
272 MeshTetInterface & triangulator,
273 bool flip_tris = false)
274 {
275 const Real expected_volume =
276 build_octahedron(mesh, flip_tris, -1, 1, -1, 1, -0.1, 0.1);
277
278 // Remove one tri, breaking the mesh
279 for (auto elem : mesh.element_ptr_range())
280 {
281 Point center = elem->vertex_average();
282 if (center(0) > 0 &&
283 center(1) > 0 &&
284 center(2) > 0)
285 mesh.delete_elem(elem);
286 }
288
289 this->testExceptionBase("element with a null neighbor", mesh, triangulator,
290 /* n_elem = */ 4, /* n_nodes = */ 6,
291 expected_volume);
292 }
293
294
296 MeshTetInterface & triangulator)
297 {
298 // An asymmetric octahedron, so we hopefully have an unambiguous
299 // choice of shortest diagonal for a Delaunay algorithm to pick.
300 mesh.add_point(Point(0,0,-0.1), 0);
301 mesh.add_point(Point(1,0,0), 1);
302 mesh.add_point(Point(0,1,0), 2);
303 mesh.add_point(Point(-1,0,0), 3);
304 mesh.add_point(Point(0,-1,0), 4);
305 mesh.add_point(Point(0,0,0.1), 5);
306
307 auto add_tet = [&mesh](std::array<dof_id_type,4> nodes)
308 {
309 auto elem = mesh.add_elem(Elem::build(TET4));
310 elem->set_node(0, mesh.node_ptr(nodes[0]));
311 elem->set_node(1, mesh.node_ptr(nodes[1]));
312 elem->set_node(2, mesh.node_ptr(nodes[2]));
313 elem->set_node(3, mesh.node_ptr(nodes[3]));
314 };
315
316 // Split along a different diagonal to start
317 add_tet({1,3,4,5});
318 add_tet({1,3,5,2});
319 add_tet({1,3,2,0});
320 add_tet({1,3,0,4});
321
323
324 const Real expected_volume = MeshTools::volume(mesh);
325
326 this->testTetInterfaceBase(mesh, triangulator, /* n_elem = */ 4,
327 /* n_nodes = */ 6, expected_volume);
328 }
329
330
331#ifdef LIBMESH_HAVE_TETGEN
333 {
334 LOG_UNIT_TEST;
335
337 TetGenMeshInterface tet_tet(mesh);
338 testTrisToTets(mesh, tet_tet);
339 }
340
341
343 {
344 LOG_UNIT_TEST;
345
347 TetGenMeshInterface tet_tet(mesh);
348 testTrisToTetsError(mesh, tet_tet);
349 }
350
351
352
353 /*
354 void testTetGenInterp()
355 {
356 LOG_UNIT_TEST;
357
358 Mesh mesh(*TestCommWorld);
359 TetGenMeshInterface tet_tet(mesh);
360 testTrisToTetsInterp(mesh, tet_tet, 1, 6);
361 }
362
363
364 void testTetGenInterp2()
365 {
366 LOG_UNIT_TEST;
367
368 Mesh mesh(*TestCommWorld);
369 TetGenMeshInterface tet_tet(mesh);
370 testTrisToTetsInterp(mesh, tet_tet, 2, 10);
371 }
372 */
373
374#endif // LIBMESH_HAVE_TETGEN
375
376
377#ifdef LIBMESH_HAVE_NETGEN
379 {
380 LOG_UNIT_TEST;
381
383 NetGenMeshInterface net_tet(mesh);
384
385 // This should give no output for our correctly-set-up inputs
386 net_tet.set_verbosity(50);
387
388 testTrisToTets(mesh, net_tet);
390 }
391
392
394 {
395 LOG_UNIT_TEST;
396
398 NetGenMeshInterface net_tet(mesh);
399 testTrisToTetsError(mesh, net_tet);
400 }
401
402
404 {
405 LOG_UNIT_TEST;
406
408 NetGenMeshInterface net_tet(mesh);
409 testTetsToTets(mesh, net_tet);
411 }
412
413
415 {
416 LOG_UNIT_TEST;
417
419 NetGenMeshInterface net_tet(mesh);
420 testTrisToTets(mesh, net_tet, true);
422 }
423
424
426 {
427 LOG_UNIT_TEST;
428
430 NetGenMeshInterface net_tet(mesh);
431 testTrisToTets(mesh, net_tet, true, true);
433 }
434
435
437 {
438 LOG_UNIT_TEST;
439
441 NetGenMeshInterface net_tet(mesh);
442 testHole(mesh, net_tet);
444 }
445
446
448 {
449 LOG_UNIT_TEST;
450
452 NetGenMeshInterface net_tet(mesh);
453 net_tet.elem_type() = TET10;
454
455 const Real expected_volume =
456 build_octahedron(mesh, false, -1, 1, -1, 1, -0.1, 0.1);
457
458 net_tet.triangulate();
459
460 LIBMESH_ASSERT_FP_EQUAL(MeshTools::volume(mesh),
461 expected_volume,
463
464 for (const auto & elem : mesh.element_ptr_range())
465 {
466 CPPUNIT_ASSERT_EQUAL(elem->type(), TET10);
467 CPPUNIT_ASSERT_EQUAL(elem->n_nodes(), 10u);
468 CPPUNIT_ASSERT(!elem->is_flipped());
469 }
470
471 // Boundary ids should survive the increase to second order
473 }
474
475
477 {
478 LOG_UNIT_TEST;
479
481 NetGenMeshInterface net_tet(mesh);
482 net_tet.elem_type() = TET14;
483
484 const Real expected_volume =
485 build_octahedron(mesh, false, -1, 1, -1, 1, -0.1, 0.1);
486
487 net_tet.triangulate();
488
489 LIBMESH_ASSERT_FP_EQUAL(MeshTools::volume(mesh),
490 expected_volume,
492
493 for (const auto & elem : mesh.element_ptr_range())
494 {
495 CPPUNIT_ASSERT_EQUAL(elem->type(), TET14);
496 CPPUNIT_ASSERT_EQUAL(elem->n_nodes(), 14u);
497 CPPUNIT_ASSERT(!elem->is_flipped());
498 }
499
500 // Boundary ids should survive the increase to complete order
502 }
503
504
506 {
507 LOG_UNIT_TEST;
508
510 NetGenMeshInterface net_tet(mesh);
511 net_tet.elem_type() = TET10;
512
513 // Build TRI3 octahedron then upconvert to TRI6 with geometric midpoints.
514 build_octahedron(mesh, false, -1, 1, -1, 1, -0.1, 0.1);
517
518 // Perturb every TRI6 midpoint outward to simulate a curved boundary.
519 // Key by sorted pair of corner positions (same scheme as record_and_strip).
520 const Real eps = 0.05;
521 std::map<std::pair<Point,Point>, Point> expected;
522
523 for (const auto & elem : mesh.element_ptr_range())
524 {
525 libmesh_assert_equal_to(elem->type(), TRI6);
526 for (auto e : make_range(3u))
527 {
528 const Point & pa = elem->point(e);
529 const Point & pb = elem->point((e+1)%3);
530 auto key = pa < pb ? std::make_pair(pa, pb)
531 : std::make_pair(pb, pa);
532 if (expected.count(key))
533 continue;
534
535 // Perturb midpoint radially outward via mutable Point & ref.
536 Point & mid = elem->point(e+3);
537 mid += eps * mid.unit();
538 expected[key] = mid;
539 }
540 }
541
542 net_tet.triangulate();
543
544 // For every boundary face of the resulting TET10 mesh, verify that edge
545 // midpoints match the perturbed positions — not geometric averages.
546 unsigned int n_checked = 0;
547 for (const auto & elem : mesh.element_ptr_range())
548 for (auto s : elem->side_index_range())
549 {
550 if (elem->neighbor_ptr(s)) continue;
551
552 auto side = elem->build_side_ptr(s); // TRI6, nodes into mesh
553 for (auto e : make_range(3u))
554 {
555 const Point & pa = side->point(e);
556 const Point & pb = side->point((e+1)%3);
557 auto key = pa < pb ? std::make_pair(pa, pb)
558 : std::make_pair(pb, pa);
559 auto it = expected.find(key);
560 if (it == expected.end())
561 continue;
562 const Point & exp = it->second;
563 const Point & got = side->point(e+3);
564 LIBMESH_ASSERT_FP_EQUAL(exp(0), got(0), TOLERANCE);
565 LIBMESH_ASSERT_FP_EQUAL(exp(1), got(1), TOLERANCE);
566 LIBMESH_ASSERT_FP_EQUAL(exp(2), got(2), TOLERANCE);
567 ++n_checked;
568 }
569 }
570
571 CPPUNIT_ASSERT_GREATER(0u, n_checked);
572
573 // Boundary ids should survive the increase to second order, even with
574 // perturbed (curved) boundary midpoints
576 }
577
578
580 {
581 LOG_UNIT_TEST;
582
584 NetGenMeshInterface net_tet(mesh);
585 net_tet.elem_type() = TET14;
586
587 // Build TRI3 octahedron then upconvert to TRI7 (edge mids + centroid).
588 build_octahedron(mesh, false, -1, 1, -1, 1, -0.1, 0.1);
591
592 const Real eps = 0.05;
593 std::map<std::pair<Point,Point>, Point> expected_mid;
594 std::map<std::array<Point,3>, Point> expected_cen;
595
596 for (const auto & elem : mesh.element_ptr_range())
597 {
598 libmesh_assert_equal_to(elem->type(), TRI7);
599 for (auto e : make_range(3u))
600 {
601 const Point & pa = elem->point(e);
602 const Point & pb = elem->point((e+1)%3);
603 auto key = pa < pb ? std::make_pair(pa, pb)
604 : std::make_pair(pb, pa);
605 if (!expected_mid.count(key))
606 {
607 Point & mid = elem->point(e+3);
608 mid += eps * mid.unit();
609 expected_mid[key] = mid;
610 }
611 }
612 // Perturb the face-centroid node (index 6) radially outward.
613 std::array<Point,3> corners =
614 {elem->point(0), elem->point(1), elem->point(2)};
615 std::sort(corners.begin(), corners.end());
616 Point & cen = elem->point(6);
617 cen += eps * cen.unit();
618 expected_cen[corners] = cen;
619 }
620
621 net_tet.triangulate();
622
623 unsigned int n_mid = 0, n_cen = 0;
624 for (const auto & elem : mesh.element_ptr_range())
625 for (auto s : elem->side_index_range())
626 {
627 if (elem->neighbor_ptr(s)) continue;
628 auto side = elem->build_side_ptr(s);
629 CPPUNIT_ASSERT_EQUAL(side->type(), TRI7);
630 for (auto e : make_range(3u))
631 {
632 const Point & pa = side->point(e);
633 const Point & pb = side->point((e+1)%3);
634 auto key = pa < pb ? std::make_pair(pa, pb)
635 : std::make_pair(pb, pa);
636 auto it = expected_mid.find(key);
637 if (it == expected_mid.end()) continue;
638 const Point & exp = it->second;
639 const Point & got = side->point(e+3);
640 LIBMESH_ASSERT_FP_EQUAL(exp(0), got(0), TOLERANCE);
641 LIBMESH_ASSERT_FP_EQUAL(exp(1), got(1), TOLERANCE);
642 LIBMESH_ASSERT_FP_EQUAL(exp(2), got(2), TOLERANCE);
643 ++n_mid;
644 }
645 std::array<Point,3> corners =
646 {side->point(0), side->point(1), side->point(2)};
647 std::sort(corners.begin(), corners.end());
648 auto it = expected_cen.find(corners);
649 if (it == expected_cen.end()) continue;
650 const Point & exp = it->second;
651 const Point & got = side->point(6);
652 LIBMESH_ASSERT_FP_EQUAL(exp(0), got(0), TOLERANCE);
653 LIBMESH_ASSERT_FP_EQUAL(exp(1), got(1), TOLERANCE);
654 LIBMESH_ASSERT_FP_EQUAL(exp(2), got(2), TOLERANCE);
655 ++n_cen;
656 }
657
658 CPPUNIT_ASSERT_GREATER(0u, n_mid);
659 CPPUNIT_ASSERT_GREATER(0u, n_cen);
660
662 }
663
664
665#ifdef LIBMESH_ENABLE_AMR
667 {
668 LOG_UNIT_TEST;
669
671 NetGenMeshInterface net_tet(mesh);
672 testSphereShell(mesh, net_tet);
674 }
675#endif
676
677
678 /*
679 void testNetGenInterp()
680 {
681 LOG_UNIT_TEST;
682
683 Mesh mesh(*TestCommWorld);
684 NetGenMeshInterface net_tet(mesh);
685 testTrisToTetsInterp(mesh, net_tet, 1, 6);
686 }
687
688
689 void testNetGenInterp2()
690 {
691 LOG_UNIT_TEST;
692
693 Mesh mesh(*TestCommWorld);
694 NetGenMeshInterface net_tet(mesh);
695 testTrisToTetsInterp(mesh, net_tet, 2, 10);
696 }
697
698
699 void testNetGenRefinementBase
700 (UnstructuredMesh & mesh,
701 const std::vector<MeshTetInterface::Hole*> * holes,
702 Real expected_total_area,
703 dof_id_type n_original_elem,
704 Real desired_area = 0.1,
705 FunctionBase<Real> * area_func = nullptr)
706 {
707 NetGenMeshInterface triangulator(mesh);
708
709 if (holes)
710 triangulator.attach_hole_list(holes);
711
712 // Try to insert points!
713 triangulator.desired_area() = desired_area;
714 triangulator.set_desired_area_function(area_func);
715
716 triangulator.triangulate();
717
718 // If refinement should have increased our element count, check it
719 if (desired_area || area_func)
720 CPPUNIT_ASSERT_GREATER(n_original_elem, mesh.n_elem()); // n_elem+++
721 else
722 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), n_original_elem);
723
724 Real area = 0;
725 for (const auto & elem : mesh.active_local_element_ptr_range())
726 {
727 CPPUNIT_ASSERT_EQUAL(elem->level(), 0u);
728 CPPUNIT_ASSERT_EQUAL(elem->type(), TRI3);
729
730 const Real my_area = elem->volume();
731
732 // my_area <= desired_area, wow this macro ordering hurts
733 if (desired_area != 0)
734 CPPUNIT_ASSERT_LESSEQUAL(desired_area, my_area);
735
736 if (area_func != nullptr)
737 for (auto v : make_range(elem->n_vertices()))
738 {
739 const Real local_desired_area =
740 (*area_func)(elem->point(v));
741 CPPUNIT_ASSERT_LESSEQUAL(local_desired_area, my_area);
742 }
743
744 area += my_area;
745 }
746
747 mesh.comm().sum(area);
748
749 LIBMESH_ASSERT_FP_EQUAL(area, expected_total_area, TOLERANCE*TOLERANCE);
750 }
751
752 void testNetGenRefined()
753 {
754 LOG_UNIT_TEST;
755
756 Mesh mesh(*TestCommWorld);
757 testTriangulatorTrapMesh(mesh);
758 testPoly2TriRefinementBase(mesh, nullptr, 1.5, 15);
759 }
760
761 void testNetGenNonRefined()
762 {
763 LOG_UNIT_TEST;
764
765 Mesh mesh(*TestCommWorld);
766 testTriangulatorTrapMesh(mesh);
767 // Make sure we see 0 as "don't refine", not "infinitely refine"
768 testPoly2TriRefinementBase(mesh, nullptr, 1.5, 2, 0);
769 }
770
771
772 void testNetGenExtraRefined()
773 {
774 LOG_UNIT_TEST;
775
776 Mesh mesh(*TestCommWorld);
777 testTriangulatorTrapMesh(mesh);
778 testPoly2TriRefinementBase(mesh, nullptr, 1.5, 150, 0.01);
779 }
780*/
781
782#endif // LIBMESH_HAVE_NETGEN
783
784};
785
786
CPPUNIT_TEST(testNetGenQuadraticCurved)
void testNetGenError()
void testSphereShell(UnstructuredMesh &mesh, MeshTetInterface &triangulator)
void testNetGen()
CPPUNIT_TEST(testNetGenTet14)
void testNetGenTets()
CPPUNIT_TEST(testNetGenSphereShell)
CPPUNIT_TEST(testNetGenTets)
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST(testNetGenFlippedTris)
void testNetGenTet14Curved()
void testNetGenSphereShell()
void tearDown()
LIBMESH_CPPUNIT_TEST_SUITE(MeshTetTest)
The goal of this test is to verify proper operation of the interfaces to tetrahedralization libraries...
void testTrisToTetsError(UnstructuredMesh &mesh, MeshTetInterface &triangulator, bool flip_tris=false)
CPPUNIT_TEST(testNetGenError)
CPPUNIT_TEST(testNetGenTet14Curved)
void testNetGenFlippedTris()
void testNetGenHole()
void testNetGenQuadraticCurved()
void testTetsToTets(MeshBase &mesh, MeshTetInterface &triangulator)
void testTetGen()
void testExceptionBase(const char *re, MeshBase &mesh, MeshTetInterface &tetinterface, dof_id_type expected_n_elem=DofObject::invalid_id, dof_id_type expected_n_nodes=DofObject::invalid_id, Real expected_volume=0)
void testTetGenError()
void testTetInterfaceBase(MeshBase &mesh, MeshTetInterface &triangulator, dof_id_type expected_n_elem=DofObject::invalid_id, dof_id_type expected_n_nodes=DofObject::invalid_id, Real expected_volume=0)
void testNetGenQuadratic()
void testTrisToTets(UnstructuredMesh &mesh, MeshTetInterface &triangulator, bool flip_tris=false, bool flip_some_tris=false)
void testHole(UnstructuredMesh &mesh, MeshTetInterface &triangulator)
void testNetGenTet14()
void testBcids(UnstructuredMesh &mesh)
CPPUNIT_TEST(testNetGenHole)
void testNetGenNonOriented()
CPPUNIT_TEST(testNetGenNonOriented)
CPPUNIT_TEST(testNetGenQuadratic)
CPPUNIT_TEST(testNetGen)
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
std::size_t n_boundary_ids() const
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition dof_object.h:473
virtual Node *& set_node(const unsigned int i)
Definition elem.h:2567
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
This is the MeshBase class.
Definition mesh_base.h:81
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
virtual const Node * node_ptr(const dof_id_type i) const =0
virtual dof_id_type n_elem() const =0
void all_second_order(const bool full_ordered=true)
Calls the range-based version of this function with a range consisting of all elements in the mesh.
Definition mesh_base.C:1803
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition mesh_base.C:824
virtual dof_id_type n_nodes() const =0
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual void all_complete_order()
Calls the range-based version of this function with a range consisting of all elements in the mesh.
Definition mesh_base.C:1808
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
void unset_is_prepared()
Tells this we have done some operation where we should no longer consider ourself prepared.
Definition mesh_base.C:1070
Class MeshTetInterface provides an abstract interface for tetrahedralization of meshes by subclasses.
ElemType & elem_type()
Sets and/or gets the desired element type.
virtual void triangulate()=0
This is the main public interface for this function.
Real & desired_volume()
Sets and/or gets the desired tetrahedron volume.
void attach_hole_list(std::unique_ptr< std::vector< std::unique_ptr< UnstructuredMesh > > > holes)
Attaches a vector of Mesh pointers defining holes which will be meshed around.
void set_verbosity(unsigned int v)
Sets a verbosity level, defaulting to 0 (print nothing), to be set as high as 100 (print everything).
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
Class NetGenMeshInterface provides an interface for tetrahedralization of meshes using the NetGen lib...
virtual void triangulate() override
Method invokes NetGen library to compute a tetrahedralization.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
Class TetGenMeshInterface provides an interface for tetrahedralization of meshes using the TetGen lib...
TypeVector< T > unit() const
The UnstructuredMesh class is derived from the MeshBase class.
Communicator * TestCommWorld
MeshBase & mesh
CPPUNIT_TEST_SUITE_REGISTRATION(MeshTetTest)
void build_sphere(UnstructuredMesh &mesh, const Real radius=1, const unsigned int n_refinements=2, const ElemType type=INVALID_ELEM, const unsigned int n_smooth=2, const bool flat=true)
Fills mesh with a mesh discretizing a ball (||x||<= radius) or sphere (||x|| = radius) domain.
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
void surface_octahedron(UnstructuredMesh &mesh, Real xmin, Real xmax, Real ymin, Real ymax, Real zmin, Real zmax, bool flip_tris=false)
Meshes the surface of an octahedron with 8 Tri3 elements, with counter-clockwise (libMesh default) no...
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
Find the total volume of a mesh (interpreting that as area for dim = 2, or total arc length for dim =...
The libMesh namespace provides an interface to certain functionality in the library.
static constexpr Real TOLERANCE
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176