tetgen_mesh.h
Go to the documentation of this file.
1// LIC// ====================================================================
2// LIC// This file forms part of oomph-lib, the object-oriented,
3// LIC// multi-physics finite-element library, available
4// LIC// at http://www.oomph-lib.org.
5// LIC//
6// LIC// Copyright (C) 2006-2025 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26
27#ifndef OOMPH_TETGEN_MESH_HEADER
28#define OOMPH_TETGEN_MESH_HEADER
29
30// Config header
31#ifdef HAVE_CONFIG_H
32#include <oomph-lib-config.h>
33#endif
34
35#ifdef OOMPH_HAS_MPI
36// mpi headers
37#include "mpi.h"
38#endif
39
41#include "generic/tet_mesh.h"
42
43namespace oomph
44{
45 //=========start of TetgenMesh class======================================
46 /// Unstructured tet mesh based on output from Tetgen:
47 /// http://wias-berlin.de/software/tetgen/
48 //========================================================================
49 template<class ELEMENT>
50 class TetgenMesh : public virtual TetMeshBase
51 {
52 public:
53 /// Empty constructor
55 {
56 // Mesh can only be built with 3D Telements.
57 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
58 }
59
60 /// Constructor with the input files
61 TetgenMesh(const std::string& node_file_name,
62 const std::string& element_file_name,
63 const std::string& face_file_name,
64 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
65 const bool& use_attributes = false)
67 {
68 // Mesh can only be built with 3D Telements.
69 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
70
71 // Store the attributes
73
74 // Store timestepper used to build elements
75 Time_stepper_pt = time_stepper_pt;
76
77 // Build scaffold
80
81 // Convert mesh from scaffold to actual mesh
82 build_from_scaffold(time_stepper_pt, use_attributes);
83
84 // Kill the scaffold
85 delete Tmp_mesh_pt;
86 Tmp_mesh_pt = 0;
87
88 // Setup boundary coordinates
89 unsigned nb = nboundary();
90 for (unsigned b = 0; b < nb; b++)
91 {
92 bool switch_normal = false;
94 }
95 }
96
97
98 /// Constructor with tetgenio data structure
100 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
101 const bool& use_attributes = false)
102
103 {
104 // Mesh can only be built with 3D Telements.
105 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
106
107 // Store the attributes
109
110 // Store timestepper used to build elements
111 Time_stepper_pt = time_stepper_pt;
112
113 // We do not have a tetgenio representation
114 Tetgenio_exists = false;
115 Tetgenio_pt = 0;
116
117 // Build scaffold
119
120 // Convert mesh from scaffold to actual mesh
121 build_from_scaffold(time_stepper_pt, use_attributes);
122
123 // Kill the scaffold
124 delete Tmp_mesh_pt;
125 Tmp_mesh_pt = 0;
126
127 // Setup boundary coordinates
128 unsigned nb = nboundary();
129 for (unsigned b = 0; b < nb; b++)
130 {
131 bool switch_normal = false;
133 }
134 }
135
136
137 /// Constructor with the input files. Setting the boolean
138 /// flag to true splits "corner" elements, i.e. elements that
139 /// that have at least three faces on a domain boundary. The
140 /// relevant elements are split without introducing hanging
141 /// nodes so the sons have a "worse" shape than their fathers.
142 /// However, this step avoids otherwise-hard-to-diagnose
143 /// problems in fluids problems where the application of
144 /// boundary conditions at such "corner" elements can
145 /// overconstrain the solution.
146 TetgenMesh(const std::string& node_file_name,
147 const std::string& element_file_name,
148 const std::string& face_file_name,
149 const bool& split_corner_elements,
150 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
151 const bool& use_attributes = false)
152
153 {
154 // Mesh can only be built with 3D Telements.
155 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
156
157 // Store the attributes
159
160 // Store timestepper used to build elements
161 Time_stepper_pt = time_stepper_pt;
162
163 // We do not have a tetgenio representation
164 this->Tetgenio_exists = false;
165 this->Tetgenio_pt = 0;
166
167 // Build scaffold
170
171 // Convert mesh from scaffold to actual mesh
172 build_from_scaffold(time_stepper_pt, use_attributes);
173
174 // Kill the scaffold
175 delete Tmp_mesh_pt;
176 Tmp_mesh_pt = 0;
177
178 // Split corner elements
180 {
182 }
183
184 // Setup boundary coordinates
185 unsigned nb = nboundary();
186 for (unsigned b = 0; b < nb; b++)
187 {
188 bool switch_normal = false;
190 }
191 }
192
193 /// Constructor with tetgen data structure Setting the boolean
194 /// flag to true splits "corner" elements, i.e. elements that
195 /// that have at least three faces on a domain boundary. The
196 /// relevant elements are split without introducing hanging
197 /// nodes so the sons have a "worse" shape than their fathers.
198 /// However, this step avoids otherwise-hard-to-diagnose
199 /// problems in fluids problems where the application of
200 /// boundary conditions at such "corner" elements can
201 /// overconstrain the solution.
203 const bool& split_corner_elements,
204 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
205 const bool& use_attributes = false)
206
207 {
208 // Mesh can only be built with 3D Telements.
209 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
210
211 // Store the attributes
213
214 // Store timestepper used to build elements
215 Time_stepper_pt = time_stepper_pt;
216
217 // We do not have a tetgenio representation
218 this->Tetgenio_exists = false;
219 this->Tetgenio_pt = nullptr;
220
221 // Build scaffold
223
224 // Convert mesh from scaffold to actual mesh
225 build_from_scaffold(time_stepper_pt, use_attributes);
226
227 // Kill the scaffold
228 delete Tmp_mesh_pt;
229 Tmp_mesh_pt = nullptr;
230
231 // Split corner elements
233 {
235 }
236
237 // Setup boundary coordinates
238 unsigned nb = nboundary();
239 for (unsigned b = 0; b < nb; b++)
240 {
241 bool switch_normal = false;
243 }
244 }
245
246
247 /// Build mesh, based on a TetgenMeshFactedClosedSurface that
248 /// specifies the outer boundary of the domain and any number of internal
249 /// boundaries, specified by TetMeshFacetedSurfaces.
250 /// Also specify target size for uniform element size.
251 /// Optionally specify the target element volume in each region.
253 TetMeshFacetedClosedSurface* const& outer_boundary_pt,
254 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
255 const double& element_volume,
256 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
257 const bool& use_attributes = false,
258 const bool& split_corner_elements = false,
260 {
261 // Mesh can only be built with 3D Telements.
262 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
263
264 // Store the attributes
266
267 // Store timestepper used to build elements
268 Time_stepper_pt = time_stepper_pt;
269
270 // Copy across
271 Outer_boundary_pt = outer_boundary_pt;
272
273 // Setup reverse lookup scheme
274 {
275 unsigned n_facet = Outer_boundary_pt->nfacet();
276 for (unsigned f = 0; f < n_facet; f++)
277 {
279 if (b != 0)
280 {
283 }
284 else
285 {
286 std::ostringstream error_message;
287 error_message << "Boundary IDs have to be one-based. Yours is " << b
288 << "\n";
289 throw OomphLibError(error_message.str(),
292 }
293 }
294 }
295
296 // Store the internal boundary
297 Internal_surface_pt = internal_surface_pt;
298
299 // Setup reverse lookup scheme
300 {
301 unsigned n = Internal_surface_pt.size();
302 for (unsigned i = 0; i < n; i++)
303 {
304 unsigned n_facet = Internal_surface_pt[i]->nfacet();
305 for (unsigned f = 0; f < n_facet; f++)
306 {
307 unsigned b = Internal_surface_pt[i]->one_based_facet_boundary_id(f);
308 if (b != 0)
309 {
311 Tet_mesh_facet_pt[b - 1] = Internal_surface_pt[i]->facet_pt(f);
312 }
313 else
314 {
315 std::ostringstream error_message;
316 error_message << "Boundary IDs have to be one-based. Yours is "
317 << b << "\n";
318 throw OomphLibError(error_message.str(),
321 }
322 }
323 }
324 }
325
326 // Tetgen data structure for the input and output
327 tetgenio in;
328 this->build_tetgenio(outer_boundary_pt,
329 internal_surface_pt,
331 in);
332
333 // Now tetrahedralise
334
335 // The 'p' switch reads a Piecewise Linear Complex, which generates a
336 // Delaunay tetrahedralization of the input. The 'q' switch prevents
337 // generation of high-aspect ratio tets (slivers), with the trailing float
338 // indicating the maximum allowed aspect ratio (default is 2.0). The 'a'
339 // switch without subsequent floating-point number switches on the
340 // specific element volume constraints for particular regions (the 5th
341 // index in the tetgenio.regionlist array). The 'A' enables region
342 // attributes, and the second 'a' switch with the subsequent float sets
343 // the global (non-region-specific) element volume constraint.
344 std::stringstream input_string;
345 input_string << "pq2.0aAa" << element_volume;
346
347 // input_string << "Vpq1.414Aa" << element_volume;
348 // << "Q"; // Q for quiet!
349 // << "V"; // V for verbose incl. quality output!
350
351 // If any of the boundaries should not be split add the "Y" flag
353 outer_boundary_pt->boundaries_can_be_split_in_tetgen();
354 {
355 unsigned n_internal = internal_surface_pt.size();
356 for (unsigned i = 0; i < n_internal; i++)
357 {
359 internal_surface_pt[i]->boundaries_can_be_split_in_tetgen();
360 }
361 }
362
363 // If we can't split the boundaries add the flag
364 if (can_boundaries_be_split == false)
365 {
366 input_string << "Y";
367 }
368
369 // Now convert to a C-style string
370 char tetswitches[100];
371 snprintf(
372 tetswitches, sizeof(tetswitches), "%s", input_string.str().c_str());
373
374 // Make a new tetgen representation
375 this->Tetgenio_exists = true;
376 Tetgenio_pt = new tetgenio;
378
379 // Build scaffold
381
382 // If any of the objects are different regions then we need to use
383 // the atributes
384 bool regions_exist = false;
385 {
386 unsigned n_internal = internal_surface_pt.size();
387 for (unsigned i = 0; i < n_internal; i++)
388 {
390 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[i]);
391 if (srf_pt != 0)
392 {
393 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
394 for (unsigned j = 0; j < n_int_pts; j++)
395 {
397 srf_pt->internal_point_identifies_region_for_tetgen(j);
398 }
399 }
400 }
401 }
402
403 // If there are regions, use the attributes
404 if (regions_exist)
405 {
406 Use_attributes = true;
407 }
408
409 // Convert mesh from scaffold to actual mesh
410 build_from_scaffold(time_stepper_pt, Use_attributes);
411
412 // Kill the scaffold
413 delete Tmp_mesh_pt;
414 Tmp_mesh_pt = 0;
415
416 // Split corner elements
418 {
420 }
421
422 // Setup boundary coordinates
423 unsigned nb = nboundary();
424 for (unsigned b = 0; b < nb; b++)
425 {
426 bool switch_normal = false;
428 }
429
430 // Now snap onto geometric objects associated with triangular facets
431 // (if any!)
433 }
434
435 /// Build tetgenio object from the TetMeshFacetedSurfaces
437 TetMeshFacetedSurface* const& outer_boundary_pt,
438 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
441 {
442 // Pointer to Tetgen facet
443 tetgenio::facet* f;
444 // Pointer to Tetgen polygon
445 tetgenio::polygon* p;
446
447 // Start all indices from 1 (it's a choice and we've made it
448 tetgen_io.firstnumber = 1;
449 /// ALH: This may not be needed
450 tetgen_io.useindex = true;
451
452 // Find the number of internal surfaces
453 const unsigned n_internal = internal_surface_pt.size();
454
455 // Find the number of points on the outer boundary
456 const unsigned n_outer_vertex = outer_boundary_pt->nvertex();
457 tetgen_io.numberofpoints = n_outer_vertex;
458
459 // Find the number of points on the inner boundaries and add to the totals
462 for (unsigned h = 0; h < n_internal; ++h)
463 {
464 n_internal_vertex[h] = internal_surface_pt[h]->nvertex();
465 internal_vertex_offset[h] = tetgen_io.numberofpoints;
466 tetgen_io.numberofpoints += n_internal_vertex[h];
467 }
468
469 // Read the data into the point list
470 tetgen_io.pointlist = new double[tetgen_io.numberofpoints * 3];
471 tetgen_io.pointmarkerlist = new int[tetgen_io.numberofpoints];
472 unsigned counter = 0;
473 for (unsigned n = 0; n < n_outer_vertex; ++n)
474 {
475 for (unsigned i = 0; i < 3; ++i)
476 {
477 tetgen_io.pointlist[counter] =
478 outer_boundary_pt->vertex_coordinate(n, i);
479 ++counter;
480 }
481 }
482 for (unsigned h = 0; h < n_internal; ++h)
483 {
484 const unsigned n_inner = n_internal_vertex[h];
485 for (unsigned n = 0; n < n_inner; ++n)
486 {
487 for (unsigned i = 0; i < 3; ++i)
488 {
489 tetgen_io.pointlist[counter] =
490 internal_surface_pt[h]->vertex_coordinate(n, i);
491 ++counter;
492 }
493 }
494 }
495
496 // Set up the pointmarkers
497 counter = 0;
498 for (unsigned n = 0; n < n_outer_vertex; ++n)
499 {
500 tetgen_io.pointmarkerlist[counter] =
501 outer_boundary_pt->one_based_vertex_boundary_id(n);
502 ++counter;
503 }
504 for (unsigned h = 0; h < n_internal; ++h)
505 {
506 const unsigned n_inner = n_internal_vertex[h];
507 for (unsigned n = 0; n < n_inner; ++n)
508 {
509 tetgen_io.pointmarkerlist[counter] =
510 internal_surface_pt[h]->one_based_vertex_boundary_id(n);
511 ++counter;
512 }
513 }
514
515 // Now the facets
516 unsigned n_outer_facet = outer_boundary_pt->nfacet();
517 tetgen_io.numberoffacets = n_outer_facet;
519 for (unsigned h = 0; h < n_internal; ++h)
520 {
521 n_inner_facet[h] = internal_surface_pt[h]->nfacet();
522 tetgen_io.numberoffacets += n_inner_facet[h];
523 }
524
525 tetgen_io.facetlist = new tetgenio::facet[tetgen_io.numberoffacets];
526 tetgen_io.facetmarkerlist = new int[tetgen_io.numberoffacets];
527
528 counter = 0;
529 for (unsigned n = 0; n < n_outer_facet; ++n)
530 {
531 // Set pointer to facet
532 f = &tetgen_io.facetlist[counter];
533 f->numberofpolygons = 1;
534 f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
535 f->numberofholes = 0;
536 f->holelist = NULL;
537 p = &f->polygonlist[0];
538
539 Vector<unsigned> facet = outer_boundary_pt->vertex_index_in_tetgen(n);
540
541 p->numberofvertices = facet.size();
542 p->vertexlist = new int[p->numberofvertices];
543 for (int i = 0; i < p->numberofvertices; ++i)
544 {
545 // The offset here is because we have insisted on 1-based indexing
546 p->vertexlist[i] = facet[i] + 1;
547 }
548
549 // Set up the boundary markers
550 tetgen_io.facetmarkerlist[counter] =
551 outer_boundary_pt->one_based_facet_boundary_id(n);
552 // Increase the counter
553 ++counter;
554 }
555
556 // Initialise the number of holes
557 tetgen_io.numberofholes = 0;
558 // and the number of regions
559 tetgen_io.numberofregions = 0;
560
561 // Loop over the internal stuff
562 for (unsigned h = 0; h < n_internal; ++h)
563 {
564 for (unsigned n = 0; n < n_inner_facet[h]; ++n)
565 {
566 // Set pointer to facet
567 f = &tetgen_io.facetlist[counter];
568 f->numberofpolygons = 1;
569 f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
570 f->numberofholes = 0;
571 f->holelist = NULL;
572 p = &f->polygonlist[0];
573
575 internal_surface_pt[h]->vertex_index_in_tetgen(n);
576
577 p->numberofvertices = facet.size();
578 p->vertexlist = new int[p->numberofvertices];
579 for (int i = 0; i < p->numberofvertices; ++i)
580 {
581 // Add the 1-based and vertex offsets to get these number correct
582 p->vertexlist[i] = facet[i] + internal_vertex_offset[h] + 1;
583 }
584 // Set up the boundary markers
585 tetgen_io.facetmarkerlist[counter] =
586 internal_surface_pt[h]->one_based_facet_boundary_id(n);
587 ++counter;
588 }
589
590 // If it's a hole/region add it
592 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
593 if (srf_pt != 0)
594 {
595 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
596 for (unsigned j = 0; j < n_int_pts; j++)
597 {
598 if (srf_pt->internal_point_identifies_hole_for_tetgen(j))
599 {
600 ++tetgen_io.numberofholes;
601 }
602 // Otherwise it may be region
603 else
604 {
605 if (srf_pt->internal_point_identifies_region_for_tetgen(j))
606 {
607 ++tetgen_io.numberofregions;
608 }
609 }
610 }
611 }
612 }
613
614 // Set storage for the holes
615 tetgen_io.holelist = new double[3 * tetgen_io.numberofholes];
616
617 // Loop over all the internal boundaries again
618 counter = 0;
619 for (unsigned h = 0; h < n_internal; ++h)
620 {
622 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
623 if (srf_pt != 0)
624 {
625 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
626 for (unsigned j = 0; j < n_int_pts; j++)
627 {
628 if (srf_pt->internal_point_identifies_hole_for_tetgen(j))
629 {
630 for (unsigned i = 0; i < 3; ++i)
631 {
632 tetgen_io.holelist[counter] =
633 srf_pt->internal_point_for_tetgen(j, i);
634 ++counter;
635 }
636 }
637 }
638 }
639 }
640
641 // Set storage for the regions
642 tetgen_io.regionlist = new double[5 * tetgen_io.numberofregions];
643
644 // Loop over all the internal boundaries again
645 counter = 0;
646 for (unsigned h = 0; h < n_internal; ++h)
647 {
649 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
650 if (srf_pt != 0)
651 {
652 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
653 for (unsigned j = 0; j < n_int_pts; j++)
654 {
655 if (srf_pt->internal_point_identifies_region_for_tetgen(j))
656 {
657 for (unsigned i = 0; i < 3; ++i)
658 {
659 tetgen_io.regionlist[counter] =
660 srf_pt->internal_point_for_tetgen(j, i);
661 ++counter;
662 }
663 tetgen_io.regionlist[counter] =
664 static_cast<double>(srf_pt->region_id_for_tetgen(j));
665 ++counter;
666
667 // if there's no target volumes specified, default to zero
669 {
670 tetgen_io.regionlist[counter] = 0;
671 }
672 else
673 {
674 // deliberate integer division here to round down to the region
675 // number (five doubles per region)
676 tetgen_io.regionlist[counter] =
677 (*target_element_volume_in_region_pt)[unsigned(counter / 5)];
678 }
679
680 ++counter;
681 }
682 }
683 }
684 }
685 }
686
687 /// Empty destructor
689 {
690 if (Tetgenio_exists)
691 {
692 delete Tetgenio_pt;
693 }
694 }
695
696
697 /// Overload set_mesh_level_time_stepper so that the stored
698 /// time stepper now corresponds to the new timestepper
699 void set_mesh_level_time_stepper(TimeStepper* const& time_stepper_pt,
700 const bool& preserve_existing_data)
701 {
702 this->Time_stepper_pt = time_stepper_pt;
703 }
704
705 /// Boolen defining whether tetgenio object has been built or not
706 bool tetgenio_exists() const
707 {
708 return Tetgenio_exists;
709 }
710
711 /// Access to the triangulateio representation of the mesh
713 {
714 return Tetgenio_pt;
715 }
716
717 /// Set the tetgen pointer by a deep copy
719 {
720 // Delete the existing data
721 if (Tetgenio_exists)
722 {
723 delete Tetgenio_pt;
724 }
725 this->Tetgenio_pt = new tetgenio;
726 // Create a deep copy of tetgenio_pt and store the result in
727 // Tetgenio_pt
728 this->deep_copy_of_tetgenio(tetgenio_pt, this->Tetgenio_pt);
729 }
730
731 /// Transfer tetgenio data from the input to the output
732 /// The output is assumed to have been constructed and "empty"
734
735 protected:
736 /// Build mesh from scaffold
737 void build_from_scaffold(TimeStepper* time_stepper_pt,
738 const bool& use_attributes);
739
740 /// Function to setup the reverse look-up schemes
743
744 /// Temporary scaffold mesh
746
747 /// Boolean to indicate whether a tetgenio representation of the
748 /// mesh exists
750
751 /// Tetgen representation of mesh
753
754 /// Boolean flag to indicate whether to use attributes or not
755 /// (required for multidomain meshes)
757
758 }; // end class
759
760
761 //////////////////////////////////////////////////////////////////
762 //////////////////////////////////////////////////////////////////
763 //////////////////////////////////////////////////////////////////
764
765 //==============start_mesh=================================================
766 /// Tetgen-based mesh upgraded to become a solid mesh. Automatically
767 /// enumerates all boundaries.
768 //=========================================================================
769 template<class ELEMENT>
770 class SolidTetgenMesh : public virtual TetgenMesh<ELEMENT>,
771 public virtual SolidMesh
772 {
773 public:
774 /// Constructor. Boundary coordinates are setup
775 /// automatically.
776 SolidTetgenMesh(const std::string& node_file_name,
777 const std::string& element_file_name,
778 const std::string& face_file_name,
779 const bool& split_corner_elements,
780 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
781 const bool& use_attributes = false)
782 : TetgenMesh<ELEMENT>(node_file_name,
786 time_stepper_pt,
788 {
789 // Assign the Lagrangian coordinates
791 }
792
793 /// Constructor. Boundary coordinates are re-setup
794 /// automatically, with the orientation of the outer unit
795 /// normal determined by switch_normal.
796 SolidTetgenMesh(const std::string& node_file_name,
797 const std::string& element_file_name,
798 const std::string& face_file_name,
799 const bool& split_corner_elements,
800 const bool& switch_normal,
801 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
802 const bool& use_attributes = false)
803 : TetgenMesh<ELEMENT>(node_file_name,
807 time_stepper_pt,
809 {
810 // Assign the Lagrangian coordinates
812
813 // Re-setup boundary coordinates for all boundaries with specified
814 // orientation of nnormal
815 unsigned nb = this->nboundary();
816 for (unsigned b = 0; b < nb; b++)
817 {
819 }
820 }
821
822 /// Empty Destructor
823 virtual ~SolidTetgenMesh() {}
824 };
825
826} // namespace oomph
827
829#endif
cstr elem_len * i
Definition cfortran.h:603
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
static Steady< 0 > Default_TimeStepper
Default Steady Timestepper, to be used in default arguments to Mesh constructors.
Definition mesh.h:75
unsigned nboundary() const
Return number of boundaries.
Definition mesh.h:835
An OomphLibError object which should be thrown when an run-time error is encountered....
General SolidMesh class.
Definition mesh.h:2570
void set_lagrangian_nodal_coordinates()
Make the current configuration the undeformed one by setting the nodal Lagrangian coordinates to thei...
Definition mesh.cc:9564
Tetgen-based mesh upgraded to become a solid mesh. Automatically enumerates all boundaries.
SolidTetgenMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &face_file_name, const bool &split_corner_elements, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor. Boundary coordinates are setup automatically.
SolidTetgenMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &face_file_name, const bool &split_corner_elements, const bool &switch_normal, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor. Boundary coordinates are re-setup automatically, with the orientation of the outer unit ...
virtual ~SolidTetgenMesh()
Empty Destructor.
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
Base class for tet meshes (meshes made of 3D tet elements).
Definition tet_mesh.h:847
void snap_nodes_onto_geometric_objects()
Move the nodes on boundaries with associated GeomObjects so that they exactly coincide with the geome...
Definition tet_mesh.cc:638
TimeStepper * Time_stepper_pt
Timestepper used to build nodes.
Definition tet_mesh.h:1254
std::map< unsigned, TetMeshFacetedSurface * > Tet_mesh_faceted_surface_pt
Reverse lookup scheme: Pointer to faceted surface (if any!) associated with boundary b.
Definition tet_mesh.h:1242
Vector< TetMeshFacetedSurface * > Internal_surface_pt
Vector to faceted surfaces that define internal boundaries.
Definition tet_mesh.h:1238
std::map< unsigned, TetMeshFacet * > Tet_mesh_facet_pt
Reverse lookup scheme: Pointer to facet (if any!) associated with boundary b.
Definition tet_mesh.h:1246
TetMeshFacetedClosedSurface * Outer_boundary_pt
Faceted surface that defines outer boundaries.
Definition tet_mesh.h:1235
Base class for closed tet mesh boundary bounded by polygonal planar facets.
Definition tet_mesh.h:724
Base class for tet mesh boundary defined by polygonal planar facets.
Definition tet_mesh.h:306
TetMeshFacet * facet_pt(const unsigned &j) const
Pointer to j-th facet.
Definition tet_mesh.h:373
unsigned nfacet() const
Number of facets.
Definition tet_mesh.h:325
Vector< unsigned > vertex_index_in_tetgen(const unsigned &f)
Facet connectivity: vertex_index[j] is the index of the j-th vertex (in the Vertex_pt vector) in face...
Definition tet_mesh.h:658
bool boundaries_can_be_split_in_tetgen()
Test whether boundary can be split in tetgen.
Definition tet_mesh.h:355
unsigned one_based_facet_boundary_id(const unsigned &j) const
One-based boundary id of j-th facet.
Definition tet_mesh.h:331
double vertex_coordinate(const unsigned &j, const unsigned &i) const
i-th coordinate of j-th vertex
Definition tet_mesh.h:343
unsigned nvertex() const
Number of vertices.
Definition tet_mesh.h:319
unsigned one_based_vertex_boundary_id(const unsigned &j) const
First (of possibly multiple) one-based boundary id of j-th vertex.
Definition tet_mesh.h:337
Unstructured tet mesh based on output from Tetgen: http://wias-berlin.de/software/tetgen/.
Definition tetgen_mesh.h:51
TetgenMesh(tetgenio &tetgen_data, const bool &split_corner_elements, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor with tetgen data structure Setting the boolean flag to true splits "corner" elements,...
TetgenMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &face_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor with the input files.
Definition tetgen_mesh.h:61
TetgenMesh()
Empty constructor.
Definition tetgen_mesh.h:54
void build_from_scaffold(TimeStepper *time_stepper_pt, const bool &use_attributes)
Build mesh from scaffold.
tetgenio *& tetgenio_pt()
Access to the triangulateio representation of the mesh.
tetgenio * Tetgenio_pt
Tetgen representation of mesh.
TetgenMesh(TetMeshFacetedClosedSurface *const &outer_boundary_pt, Vector< TetMeshFacetedSurface * > &internal_surface_pt, const double &element_volume, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false, const bool &split_corner_elements=false, Vector< double > *const &target_element_volume_in_region_pt=nullptr)
Build mesh, based on a TetgenMeshFactedClosedSurface that specifies the outer boundary of the domain ...
void setup_reverse_lookup_schemes_for_faceted_surface(TetMeshFacetedSurface *const &faceted_surface_pt)
Function to setup the reverse look-up schemes.
TetgenMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &face_file_name, const bool &split_corner_elements, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor with the input files. Setting the boolean flag to true splits "corner" elements,...
void set_deep_copy_tetgenio_pt(tetgenio *const &tetgenio_pt)
Set the tetgen pointer by a deep copy.
void deep_copy_of_tetgenio(tetgenio *const &input_pt, tetgenio *&output_pt)
Transfer tetgenio data from the input to the output The output is assumed to have been constructed an...
bool Use_attributes
Boolean flag to indicate whether to use attributes or not (required for multidomain meshes)
~TetgenMesh()
Empty destructor.
void set_mesh_level_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Overload set_mesh_level_time_stepper so that the stored time stepper now corresponds to the new times...
void build_tetgenio(TetMeshFacetedSurface *const &outer_boundary_pt, Vector< TetMeshFacetedSurface * > &internal_surface_pt, Vector< double > *const &target_element_volume_in_region_pt, tetgenio &tetgen_io)
Build tetgenio object from the TetMeshFacetedSurfaces.
bool Tetgenio_exists
Boolean to indicate whether a tetgenio representation of the mesh exists.
TetgenScaffoldMesh * Tmp_mesh_pt
Temporary scaffold mesh.
TetgenMesh(tetgenio &tetgen_data, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor with tetgenio data structure.
Definition tetgen_mesh.h:99
bool tetgenio_exists() const
Boolen defining whether tetgenio object has been built or not.
Mesh that is based on input files generated by the tetrahedra mesh generator tetgen.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).