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-2026 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
40#include "generic/tetgen_scaffold_mesh.h"
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
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
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
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
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 {
278 unsigned b = Outer_boundary_pt->one_based_facet_boundary_id(f);
279 if (b != 0)
280 {
281 Tet_mesh_faceted_surface_pt[b - 1] = Outer_boundary_pt;
282 Tet_mesh_facet_pt[b - 1] = Outer_boundary_pt->facet_pt(f);
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 {
310 Tet_mesh_faceted_surface_pt[b - 1] = Internal_surface_pt[i];
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 << "YY"; // Note that the second Y appears
367 // to be required; determined by trial and
368 // error.
369 }
370
371 // Now convert to a C-style string
372 char tetswitches[100];
373 snprintf(
374 tetswitches, sizeof(tetswitches), "%s", input_string.str().c_str());
375
376 // Make a new tetgen representation
377 this->Tetgenio_exists = true;
378 Tetgenio_pt = new tetgenio;
380
381 // Build scaffold
383
384 // If any of the objects are different regions then we need to use
385 // the atributes
386 bool regions_exist = false;
387 {
388 unsigned n_internal = internal_surface_pt.size();
389 for (unsigned i = 0; i < n_internal; i++)
390 {
392 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[i]);
393 if (srf_pt != 0)
394 {
395 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
396 for (unsigned j = 0; j < n_int_pts; j++)
397 {
399 srf_pt->internal_point_identifies_region_for_tetgen(j);
400 }
401 }
402 }
403 }
404
405 // If there are regions, use the attributes
406 if (regions_exist)
407 {
408 Use_attributes = true;
409 }
410
411 // Convert mesh from scaffold to actual mesh
413
414 // Kill the scaffold
415 delete Tmp_mesh_pt;
416 Tmp_mesh_pt = 0;
417
418 // Split corner elements
420 {
422 }
423
424 // Setup boundary coordinates
425 unsigned nb = nboundary();
426 for (unsigned b = 0; b < nb; b++)
427 {
428 bool switch_normal = false;
430 }
431
432 // Now snap onto geometric objects associated with triangular facets
433 // (if any!)
435 }
436
437 /// Build tetgenio object from the TetMeshFacetedSurfaces
439 TetMeshFacetedSurface* const& outer_boundary_pt,
440 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
443 {
444 // Pointer to Tetgen facet
445 tetgenio::facet* f;
446 // Pointer to Tetgen polygon
447 tetgenio::polygon* p;
448
449 // Start all indices from 1 (it's a choice and we've made it
450 tetgen_io.firstnumber = 1;
451 /// ALH: This may not be needed
452 tetgen_io.useindex = true;
453
454 // Find the number of internal surfaces
455 const unsigned n_internal = internal_surface_pt.size();
456
457 // Find the number of points on the outer boundary
458 const unsigned n_outer_vertex = outer_boundary_pt->nvertex();
459 tetgen_io.numberofpoints = n_outer_vertex;
460
461 // Find the number of points on the inner boundaries and add to the totals
464 for (unsigned h = 0; h < n_internal; ++h)
465 {
466 n_internal_vertex[h] = internal_surface_pt[h]->nvertex();
467 internal_vertex_offset[h] = tetgen_io.numberofpoints;
468 tetgen_io.numberofpoints += n_internal_vertex[h];
469 }
470
471 // Read the data into the point list
472 tetgen_io.pointlist = new double[tetgen_io.numberofpoints * 3];
473 tetgen_io.pointmarkerlist = new int[tetgen_io.numberofpoints];
474 unsigned counter = 0;
475 for (unsigned n = 0; n < n_outer_vertex; ++n)
476 {
477 for (unsigned i = 0; i < 3; ++i)
478 {
479 tetgen_io.pointlist[counter] =
480 outer_boundary_pt->vertex_coordinate(n, i);
481 ++counter;
482 }
483 }
484 for (unsigned h = 0; h < n_internal; ++h)
485 {
486 const unsigned n_inner = n_internal_vertex[h];
487 for (unsigned n = 0; n < n_inner; ++n)
488 {
489 for (unsigned i = 0; i < 3; ++i)
490 {
491 tetgen_io.pointlist[counter] =
492 internal_surface_pt[h]->vertex_coordinate(n, i);
493 ++counter;
494 }
495 }
496 }
497
498 // Set up the pointmarkers
499 counter = 0;
500 for (unsigned n = 0; n < n_outer_vertex; ++n)
501 {
502 tetgen_io.pointmarkerlist[counter] =
503 outer_boundary_pt->one_based_vertex_boundary_id(n);
504 ++counter;
505 }
506 for (unsigned h = 0; h < n_internal; ++h)
507 {
508 const unsigned n_inner = n_internal_vertex[h];
509 for (unsigned n = 0; n < n_inner; ++n)
510 {
511 tetgen_io.pointmarkerlist[counter] =
512 internal_surface_pt[h]->one_based_vertex_boundary_id(n);
513 ++counter;
514 }
515 }
516
517 // Now the facets
518 unsigned n_outer_facet = outer_boundary_pt->nfacet();
519 tetgen_io.numberoffacets = n_outer_facet;
521 for (unsigned h = 0; h < n_internal; ++h)
522 {
523 n_inner_facet[h] = internal_surface_pt[h]->nfacet();
524 tetgen_io.numberoffacets += n_inner_facet[h];
525 }
526
527 tetgen_io.facetlist = new tetgenio::facet[tetgen_io.numberoffacets];
528 tetgen_io.facetmarkerlist = new int[tetgen_io.numberoffacets];
529
530 counter = 0;
531 for (unsigned n = 0; n < n_outer_facet; ++n)
532 {
533 // Set pointer to facet
534 f = &tetgen_io.facetlist[counter];
535 f->numberofpolygons = 1;
536 f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
537 f->numberofholes = 0;
538 f->holelist = NULL;
539 p = &f->polygonlist[0];
540
541 Vector<unsigned> facet = outer_boundary_pt->vertex_index_in_tetgen(n);
542
543 p->numberofvertices = facet.size();
544 p->vertexlist = new int[p->numberofvertices];
545 for (int i = 0; i < p->numberofvertices; ++i)
546 {
547 // The offset here is because we have insisted on 1-based indexing
548 p->vertexlist[i] = facet[i] + 1;
549 }
550
551 // Set up the boundary markers
552 tetgen_io.facetmarkerlist[counter] =
553 outer_boundary_pt->one_based_facet_boundary_id(n);
554 // Increase the counter
555 ++counter;
556 }
557
558 // Initialise the number of holes
559 tetgen_io.numberofholes = 0;
560 // and the number of regions
561 tetgen_io.numberofregions = 0;
562
563 // Loop over the internal stuff
564 for (unsigned h = 0; h < n_internal; ++h)
565 {
566 for (unsigned n = 0; n < n_inner_facet[h]; ++n)
567 {
568 // Set pointer to facet
569 f = &tetgen_io.facetlist[counter];
570 f->numberofpolygons = 1;
571 f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
572 f->numberofholes = 0;
573 f->holelist = NULL;
574 p = &f->polygonlist[0];
575
577 internal_surface_pt[h]->vertex_index_in_tetgen(n);
578
579 p->numberofvertices = facet.size();
580 p->vertexlist = new int[p->numberofvertices];
581 for (int i = 0; i < p->numberofvertices; ++i)
582 {
583 // Add the 1-based and vertex offsets to get these number correct
584 p->vertexlist[i] = facet[i] + internal_vertex_offset[h] + 1;
585 }
586 // Set up the boundary markers
587 tetgen_io.facetmarkerlist[counter] =
588 internal_surface_pt[h]->one_based_facet_boundary_id(n);
589 ++counter;
590 }
591
592 // If it's a hole/region add it
594 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
595 if (srf_pt != 0)
596 {
597 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
598 for (unsigned j = 0; j < n_int_pts; j++)
599 {
600 if (srf_pt->internal_point_identifies_hole_for_tetgen(j))
601 {
602 ++tetgen_io.numberofholes;
603 }
604 // Otherwise it may be region
605 else
606 {
607 if (srf_pt->internal_point_identifies_region_for_tetgen(j))
608 {
609 ++tetgen_io.numberofregions;
610 }
611 }
612 }
613 }
614 }
615
616 // Set storage for the holes
617 tetgen_io.holelist = new double[3 * tetgen_io.numberofholes];
618
619 // Loop over all the internal boundaries again
620 counter = 0;
621 for (unsigned h = 0; h < n_internal; ++h)
622 {
624 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
625 if (srf_pt != 0)
626 {
627 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
628 for (unsigned j = 0; j < n_int_pts; j++)
629 {
630 if (srf_pt->internal_point_identifies_hole_for_tetgen(j))
631 {
632 for (unsigned i = 0; i < 3; ++i)
633 {
634 tetgen_io.holelist[counter] =
635 srf_pt->internal_point_for_tetgen(j, i);
636 ++counter;
637 }
638 }
639 }
640 }
641 }
642
643 // Set storage for the regions
644 tetgen_io.regionlist = new double[5 * tetgen_io.numberofregions];
645
646 // Loop over all the internal boundaries again
647 counter = 0;
648 for (unsigned h = 0; h < n_internal; ++h)
649 {
651 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
652 if (srf_pt != 0)
653 {
654 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
655 for (unsigned j = 0; j < n_int_pts; j++)
656 {
657 if (srf_pt->internal_point_identifies_region_for_tetgen(j))
658 {
659 for (unsigned i = 0; i < 3; ++i)
660 {
661 tetgen_io.regionlist[counter] =
662 srf_pt->internal_point_for_tetgen(j, i);
663 ++counter;
664 }
665 tetgen_io.regionlist[counter] =
666 static_cast<double>(srf_pt->region_id_for_tetgen(j));
667 ++counter;
668
669 // if there's no target volumes specified, default to zero
671 {
672 tetgen_io.regionlist[counter] = 0;
673 }
674 else
675 {
676 // deliberate integer division here to round down to the region
677 // number (five doubles per region)
678 tetgen_io.regionlist[counter] =
679 (*target_element_volume_in_region_pt)[unsigned(counter / 5)];
680 }
681
682 ++counter;
683 }
684 }
685 }
686 }
687 }
688
689 /// Empty destructor
691 {
692 if (Tetgenio_exists)
693 {
694 delete Tetgenio_pt;
695 }
696 }
697
698
699 /// Overload set_mesh_level_time_stepper so that the stored
700 /// time stepper now corresponds to the new timestepper
702 const bool& preserve_existing_data)
703 {
704 this->Time_stepper_pt = time_stepper_pt;
705 }
706
707 /// Boolen defining whether tetgenio object has been built or not
708 bool tetgenio_exists() const
709 {
710 return Tetgenio_exists;
711 }
712
713 /// Access to the triangulateio representation of the mesh
715 {
716 return Tetgenio_pt;
717 }
718
719 /// Set the tetgen pointer by a deep copy
721 {
722 // Delete the existing data
723 if (Tetgenio_exists)
724 {
725 delete Tetgenio_pt;
726 }
727 this->Tetgenio_pt = new tetgenio;
728 // Create a deep copy of tetgenio_pt and store the result in
729 // Tetgenio_pt
730 this->deep_copy_of_tetgenio(tetgenio_pt, this->Tetgenio_pt);
731 }
732
733 /// Transfer tetgenio data from the input to the output
734 /// The output is assumed to have been constructed and "empty"
736
737 protected:
738 /// Build mesh from scaffold
740 const bool& use_attributes);
741
742 /// Function to setup the reverse look-up schemes
745
746 /// Temporary scaffold mesh
748
749 /// Boolean to indicate whether a tetgenio representation of the
750 /// mesh exists
752
753 /// Tetgen representation of mesh
755
756 /// Boolean flag to indicate whether to use attributes or not
757 /// (required for multidomain meshes)
759
760 }; // end class
761
762
763 //////////////////////////////////////////////////////////////////
764 //////////////////////////////////////////////////////////////////
765 //////////////////////////////////////////////////////////////////
766
767 //==============start_mesh=================================================
768 /// Tetgen-based mesh upgraded to become a solid mesh. Automatically
769 /// enumerates all boundaries.
770 //=========================================================================
771 template<class ELEMENT>
772 class SolidTetgenMesh : public virtual TetgenMesh<ELEMENT>,
773 public virtual SolidMesh
774 {
775 public:
776 /// Constructor. Boundary coordinates are setup
777 /// automatically.
778 SolidTetgenMesh(const std::string& node_file_name,
779 const std::string& element_file_name,
780 const std::string& face_file_name,
781 const bool& split_corner_elements,
782 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
783 const bool& use_attributes = false)
790 {
791 // Assign the Lagrangian coordinates
793 }
794
795 /// Constructor. Boundary coordinates are re-setup
796 /// automatically, with the orientation of the outer unit
797 /// normal determined by switch_normal.
798 SolidTetgenMesh(const std::string& node_file_name,
799 const std::string& element_file_name,
800 const std::string& face_file_name,
801 const bool& split_corner_elements,
802 const bool& switch_normal,
803 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
804 const bool& use_attributes = false)
811 {
812 // Assign the Lagrangian coordinates
814
815 // Re-setup boundary coordinates for all boundaries with specified
816 // orientation of nnormal
817 unsigned nb = this->nboundary();
818 for (unsigned b = 0; b < nb; b++)
819 {
821 }
822 }
823
824 /// Empty Destructor
825 virtual ~SolidTetgenMesh() {}
826 };
827
828} // namespace oomph
829
831#endif
Unstructured refineable Triangle Mesh.
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.
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.