tetgen_mesh.template.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-2022 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 generated by autoconfig
31#ifdef HAVE_CONFIG_H
32#include <oomph-lib-config.h>
33#endif
34
35
36#ifdef OOMPH_HAS_MPI
37// mpi headers
38#include "mpi.h"
39#endif
40
41#include "../generic/tetgen_scaffold_mesh.h"
42#include "../generic/tet_mesh.h"
43
44namespace oomph
45{
46 //=========start of TetgenMesh class======================================
47 /// Unstructured tet mesh based on output from Tetgen:
48 /// http://wias-berlin.de/software/tetgen/
49 //========================================================================
50 template<class ELEMENT>
51 class TetgenMesh : public virtual TetMeshBase
52 {
53 public:
54 /// Empty constructor
56 {
57 // Mesh can only be built with 3D Telements.
58 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
59 }
60
61 /// Constructor with the input files
62 TetgenMesh(const std::string& node_file_name,
63 const std::string& element_file_name,
64 const std::string& face_file_name,
65 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
66 const bool& use_attributes = false)
67 : Tetgenio_exists(false), Tetgenio_pt(nullptr)
68 {
69 // Mesh can only be built with 3D Telements.
70 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
71
72 // Store the attributes
73 Use_attributes = use_attributes;
74
75 // Store timestepper used to build elements
76 Time_stepper_pt = time_stepper_pt;
77
78 // Build scaffold
80 node_file_name, element_file_name, face_file_name);
81
82 // Convert mesh from scaffold to actual mesh
83 build_from_scaffold(time_stepper_pt, use_attributes);
84
85 // Kill the scaffold
86 delete Tmp_mesh_pt;
87 Tmp_mesh_pt = 0;
88
89 // Setup boundary coordinates
90 unsigned nb = nboundary();
91 for (unsigned b = 0; b < nb; b++)
92 {
93 bool switch_normal = false;
94 setup_boundary_coordinates<ELEMENT>(b, switch_normal);
95 }
96 }
97
98
99 /// Constructor with tetgenio data structure
100 TetgenMesh(tetgenio& tetgen_data,
101 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
102 const bool& use_attributes = false)
103
104 {
105 // Mesh can only be built with 3D Telements.
106 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
107
108 // Store the attributes
109 Use_attributes = use_attributes;
110
111 // Store timestepper used to build elements
112 Time_stepper_pt = time_stepper_pt;
113
114 // We do not have a tetgenio representation
115 Tetgenio_exists = false;
116 Tetgenio_pt = 0;
117
118 // Build scaffold
119 Tmp_mesh_pt = new TetgenScaffoldMesh(tetgen_data);
120
121 // Convert mesh from scaffold to actual mesh
122 build_from_scaffold(time_stepper_pt, use_attributes);
123
124 // Kill the scaffold
125 delete Tmp_mesh_pt;
126 Tmp_mesh_pt = 0;
127
128 // Setup boundary coordinates
129 unsigned nb = nboundary();
130 for (unsigned b = 0; b < nb; b++)
131 {
132 bool switch_normal = false;
133 setup_boundary_coordinates<ELEMENT>(b, switch_normal);
134 }
135 }
136
137
138 /// Constructor with the input files. Setting the boolean
139 /// flag to true splits "corner" elements, i.e. elements that
140 /// that have at least three faces on a domain boundary. The
141 /// relevant elements are split without introducing hanging
142 /// nodes so the sons have a "worse" shape than their fathers.
143 /// However, this step avoids otherwise-hard-to-diagnose
144 /// problems in fluids problems where the application of
145 /// boundary conditions at such "corner" elements can
146 /// overconstrain the solution.
147 TetgenMesh(const std::string& node_file_name,
148 const std::string& element_file_name,
149 const std::string& face_file_name,
150 const bool& split_corner_elements,
151 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
152 const bool& use_attributes = false)
153
154 {
155 // Mesh can only be built with 3D Telements.
156 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
157
158 // Store the attributes
159 Use_attributes = use_attributes;
160
161 // Store timestepper used to build elements
162 Time_stepper_pt = time_stepper_pt;
163
164 // We do not have a tetgenio representation
165 this->Tetgenio_exists = false;
166 this->Tetgenio_pt = 0;
167
168 // Build scaffold
170 node_file_name, element_file_name, face_file_name);
171
172 // Convert mesh from scaffold to actual mesh
173 build_from_scaffold(time_stepper_pt, use_attributes);
174
175 // Kill the scaffold
176 delete Tmp_mesh_pt;
177 Tmp_mesh_pt = 0;
178
179 // Split corner elements
180 if (split_corner_elements)
181 {
182 split_elements_in_corners<ELEMENT>();
183 }
184
185 // Setup boundary coordinates
186 unsigned nb = nboundary();
187 for (unsigned b = 0; b < nb; b++)
188 {
189 bool switch_normal = false;
190 setup_boundary_coordinates<ELEMENT>(b, switch_normal);
191 }
192 }
193
194 /// Constructor with tetgen data structure Setting the boolean
195 /// flag to true splits "corner" elements, i.e. elements that
196 /// that have at least three faces on a domain boundary. The
197 /// relevant elements are split without introducing hanging
198 /// nodes so the sons have a "worse" shape than their fathers.
199 /// However, this step avoids otherwise-hard-to-diagnose
200 /// problems in fluids problems where the application of
201 /// boundary conditions at such "corner" elements can
202 /// overconstrain the solution.
203 TetgenMesh(tetgenio& tetgen_data,
204 const bool& split_corner_elements,
205 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
206 const bool& use_attributes = false)
207
208 {
209 // Mesh can only be built with 3D Telements.
210 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
211
212 // Store the attributes
213 Use_attributes = use_attributes;
214
215 // Store timestepper used to build elements
216 Time_stepper_pt = time_stepper_pt;
217
218 // We do not have a tetgenio representation
219 this->Tetgenio_exists = false;
220 this->Tetgenio_pt = nullptr;
221
222 // Build scaffold
223 Tmp_mesh_pt = new TetgenScaffoldMesh(tetgen_data);
224
225 // Convert mesh from scaffold to actual mesh
226 build_from_scaffold(time_stepper_pt, use_attributes);
227
228 // Kill the scaffold
229 delete Tmp_mesh_pt;
230 Tmp_mesh_pt = nullptr;
231
232 // Split corner elements
233 if (split_corner_elements)
234 {
235 split_elements_in_corners<ELEMENT>();
236 }
237
238 // Setup boundary coordinates
239 unsigned nb = nboundary();
240 for (unsigned b = 0; b < nb; b++)
241 {
242 bool switch_normal = false;
243 setup_boundary_coordinates<ELEMENT>(b, switch_normal);
244 }
245 }
246
247
248 /// Build mesh, based on a TetgenMeshFactedClosedSurface that
249 /// specifies the outer boundary of the domain and any number of internal
250 /// boundaries, specified by TetMeshFacetedSurfaces.
251 /// Also specify target size for uniform element size.
252 /// Optionally specify the target element volume in each region.
254 TetMeshFacetedClosedSurface* const& outer_boundary_pt,
255 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
256 const double& element_volume,
257 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
258 const bool& use_attributes = false,
259 const bool& split_corner_elements = false,
260 Vector<double>* const& target_element_volume_in_region_pt = nullptr)
261 {
262 // Mesh can only be built with 3D Telements.
263 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
264
265 // Store the attributes
266 Use_attributes = use_attributes;
267
268 // Store timestepper used to build elements
269 Time_stepper_pt = time_stepper_pt;
270
271 // Copy across
272 Outer_boundary_pt = outer_boundary_pt;
273 // Setup the reverse lookup scheme
275 // Store the internal boundary
276 Internal_surface_pt = internal_surface_pt;
277 // Setup the reverse lookup schemes
278 {
279 unsigned n = this->Internal_surface_pt.size();
280 for (unsigned i = 0; i < n; i++)
281 {
284 }
285 }
286
287 // Tetgen data structure for the input and output
288 tetgenio in;
289 this->build_tetgenio(outer_boundary_pt,
290 internal_surface_pt,
291 target_element_volume_in_region_pt,
292 in);
293
294
295 // Now tetrahedralise
296
297 // The 'p' switch reads a Piecewise Linear Complex, which generates a
298 // Delaunay tetrahedralization of the input. The 'q' switch prevents
299 // generation of high-aspect ratio tets (slivers), with the trailing float
300 // indicating the maximum allowed aspect ratio (default is 2.0). The 'a'
301 // switch without subsequent floating-point number switches on the
302 // specific element volume constraints for particular regions (the 5th
303 // index in the tetgenio.regionlist array). The 'A' enables region
304 // attributes, and the second 'a' switch with the subsequent float sets
305 // the global (non-region-specific) element volume constraint.
306 std::stringstream input_string;
307 input_string << "pq2.0aAa" << element_volume;
308
309 // input_string << "Vpq1.414Aa" << element_volume;
310 // << "Q"; // Q for quiet!
311 // << "V"; // V for verbose incl. quality output!
312
313 // If any of the boundaries should not be split add the "Y" flag
314 bool can_boundaries_be_split =
315 outer_boundary_pt->boundaries_can_be_split_in_tetgen();
316 {
317 unsigned n_internal = internal_surface_pt.size();
318 for (unsigned i = 0; i < n_internal; i++)
319 {
320 can_boundaries_be_split &=
321 internal_surface_pt[i]->boundaries_can_be_split_in_tetgen();
322 }
323 }
324
325 // If we can't split the boundaries add the flag
326 if (can_boundaries_be_split == false)
327 {
328 input_string << "Y";
329 }
330
331 // Now convert to a C-style string
332 char tetswitches[100];
333 sprintf(tetswitches, "%s", input_string.str().c_str());
334
335 // Make a new tetgen representation
336 this->Tetgenio_exists = true;
337 Tetgenio_pt = new tetgenio;
338 tetrahedralize(tetswitches, &in, this->Tetgenio_pt);
339
340 // Build scaffold
342
343 // If any of the objects are different regions then we need to use
344 // the atributes
345 bool regions_exist = false;
346 {
347 unsigned n_internal = internal_surface_pt.size();
348 for (unsigned i = 0; i < n_internal; i++)
349 {
351 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[i]);
352 if (srf_pt != 0)
353 {
354 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
355 for (unsigned j = 0; j < n_int_pts; j++)
356 {
357 regions_exist |=
359 }
360 }
361 }
362 }
363
364 // If there are regions, use the attributes
365 if (regions_exist)
366 {
367 Use_attributes = true;
368 }
369
370 // Convert mesh from scaffold to actual mesh
371 build_from_scaffold(time_stepper_pt, Use_attributes);
372
373 // Kill the scaffold
374 delete Tmp_mesh_pt;
375 Tmp_mesh_pt = 0;
376
377 // Split corner elements
378 if (split_corner_elements)
379 {
380 split_elements_in_corners<ELEMENT>();
381 }
382
383 // Setup boundary coordinates
384 unsigned nb = nboundary();
385 for (unsigned b = 0; b < nb; b++)
386 {
387 bool switch_normal = false;
388 setup_boundary_coordinates<ELEMENT>(b, switch_normal);
389 }
390
391 // Now snap onto geometric objects associated with triangular facets
392 // (if any!)
394 }
395
396 /// Build tetgenio object from the TetMeshFacetedSurfaces
398 TetMeshFacetedSurface* const& outer_boundary_pt,
399 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
400 Vector<double>* const& target_element_volume_in_region_pt,
401 tetgenio& tetgen_io)
402 {
403 // Pointer to Tetgen facet
404 tetgenio::facet* f;
405 // Pointer to Tetgen polygon
406 tetgenio::polygon* p;
407
408 // Start all indices from 1 (it's a choice and we've made it
409 tetgen_io.firstnumber = 1;
410 /// ALH: This may not be needed
411 tetgen_io.useindex = true;
412
413 // Find the number of internal surfaces
414 const unsigned n_internal = internal_surface_pt.size();
415
416 // Find the number of points on the outer boundary
417 const unsigned n_outer_vertex = outer_boundary_pt->nvertex();
418 tetgen_io.numberofpoints = n_outer_vertex;
419
420 // Find the number of points on the inner boundaries and add to the totals
421 Vector<unsigned> n_internal_vertex(n_internal);
422 Vector<unsigned> internal_vertex_offset(n_internal);
423 for (unsigned h = 0; h < n_internal; ++h)
424 {
425 n_internal_vertex[h] = internal_surface_pt[h]->nvertex();
426 internal_vertex_offset[h] = tetgen_io.numberofpoints;
427 tetgen_io.numberofpoints += n_internal_vertex[h];
428 }
429
430 // Read the data into the point list
431 tetgen_io.pointlist = new double[tetgen_io.numberofpoints * 3];
432 tetgen_io.pointmarkerlist = new int[tetgen_io.numberofpoints];
433 unsigned counter = 0;
434 for (unsigned n = 0; n < n_outer_vertex; ++n)
435 {
436 for (unsigned i = 0; i < 3; ++i)
437 {
438 tetgen_io.pointlist[counter] =
439 outer_boundary_pt->vertex_coordinate(n, i);
440 ++counter;
441 }
442 }
443 for (unsigned h = 0; h < n_internal; ++h)
444 {
445 const unsigned n_inner = n_internal_vertex[h];
446 for (unsigned n = 0; n < n_inner; ++n)
447 {
448 for (unsigned i = 0; i < 3; ++i)
449 {
450 tetgen_io.pointlist[counter] =
451 internal_surface_pt[h]->vertex_coordinate(n, i);
452 ++counter;
453 }
454 }
455 }
456
457
458 // Set up the pointmarkers
459 counter = 0;
460 for (unsigned n = 0; n < n_outer_vertex; ++n)
461 {
462 tetgen_io.pointmarkerlist[counter] =
463 outer_boundary_pt->one_based_vertex_boundary_id(n);
464 ++counter;
465 }
466 for (unsigned h = 0; h < n_internal; ++h)
467 {
468 const unsigned n_inner = n_internal_vertex[h];
469 for (unsigned n = 0; n < n_inner; ++n)
470 {
471 tetgen_io.pointmarkerlist[counter] =
472 internal_surface_pt[h]->one_based_vertex_boundary_id(n);
473 ++counter;
474 }
475 }
476
477
478 // Now the facets
479 unsigned n_outer_facet = outer_boundary_pt->nfacet();
480 tetgen_io.numberoffacets = n_outer_facet;
481 Vector<unsigned> n_inner_facet(n_internal);
482 for (unsigned h = 0; h < n_internal; ++h)
483 {
484 n_inner_facet[h] = internal_surface_pt[h]->nfacet();
485 tetgen_io.numberoffacets += n_inner_facet[h];
486 }
487
488 tetgen_io.facetlist = new tetgenio::facet[tetgen_io.numberoffacets];
489 tetgen_io.facetmarkerlist = new int[tetgen_io.numberoffacets];
490
491
492 counter = 0;
493 for (unsigned n = 0; n < n_outer_facet; ++n)
494 {
495 // Set pointer to facet
496 f = &tetgen_io.facetlist[counter];
497 f->numberofpolygons = 1;
498 f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
499 f->numberofholes = 0;
500 f->holelist = NULL;
501 p = &f->polygonlist[0];
502
503 Vector<unsigned> facet = outer_boundary_pt->vertex_index_in_tetgen(n);
504
505 p->numberofvertices = facet.size();
506 p->vertexlist = new int[p->numberofvertices];
507 for (int i = 0; i < p->numberofvertices; ++i)
508 {
509 // The offset here is because we have insisted on 1-based indexing
510 p->vertexlist[i] = facet[i] + 1;
511 }
512
513 // Set up the boundary markers
514 tetgen_io.facetmarkerlist[counter] =
515 outer_boundary_pt->one_based_facet_boundary_id(n);
516 // Increase the counter
517 ++counter;
518 }
519
520 // Initialise the number of holes
521 tetgen_io.numberofholes = 0;
522 // and the number of regions
523 tetgen_io.numberofregions = 0;
524
525 // Loop over the internal stuff
526 for (unsigned h = 0; h < n_internal; ++h)
527 {
528 for (unsigned n = 0; n < n_inner_facet[h]; ++n)
529 {
530 // Set pointer to facet
531 f = &tetgen_io.facetlist[counter];
532 f->numberofpolygons = 1;
533 f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
534 f->numberofholes = 0;
535 f->holelist = NULL;
536 p = &f->polygonlist[0];
537
538 Vector<unsigned> facet =
539 internal_surface_pt[h]->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 // Add the 1-based and vertex offsets to get these number correct
546 p->vertexlist[i] = facet[i] + internal_vertex_offset[h] + 1;
547 }
548 // Set up the boundary markers
549 tetgen_io.facetmarkerlist[counter] =
550 internal_surface_pt[h]->one_based_facet_boundary_id(n);
551 ++counter;
552 }
553
554 // If it's a hole/region add it
556 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
557 if (srf_pt != 0)
558 {
559 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
560 for (unsigned j = 0; j < n_int_pts; j++)
561 {
563 {
564 ++tetgen_io.numberofholes;
565 }
566 // Otherwise it may be region
567 else
568 {
570 {
571 ++tetgen_io.numberofregions;
572 }
573 }
574 }
575 }
576 }
577
578 // Set storage for the holes
579 tetgen_io.holelist = new double[3 * tetgen_io.numberofholes];
580
581 // Loop over all the internal boundaries again
582 counter = 0;
583 for (unsigned h = 0; h < n_internal; ++h)
584 {
586 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
587 if (srf_pt != 0)
588 {
589 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
590 for (unsigned j = 0; j < n_int_pts; j++)
591 {
593 {
594 for (unsigned i = 0; i < 3; ++i)
595 {
596 tetgen_io.holelist[counter] =
597 srf_pt->internal_point_for_tetgen(j, i);
598 ++counter;
599 }
600 }
601 }
602 }
603 }
604
605 // Set storage for the regions
606 tetgen_io.regionlist = new double[5 * tetgen_io.numberofregions];
607
608 // Loop over all the internal boundaries again
609 counter = 0;
610 for (unsigned h = 0; h < n_internal; ++h)
611 {
613 dynamic_cast<TetMeshFacetedClosedSurface*>(internal_surface_pt[h]);
614 if (srf_pt != 0)
615 {
616 unsigned n_int_pts = srf_pt->ninternal_point_for_tetgen();
617 for (unsigned j = 0; j < n_int_pts; j++)
618 {
620 {
621 for (unsigned i = 0; i < 3; ++i)
622 {
623 tetgen_io.regionlist[counter] =
624 srf_pt->internal_point_for_tetgen(j, i);
625 ++counter;
626 }
627 tetgen_io.regionlist[counter] =
628 static_cast<double>(srf_pt->region_id_for_tetgen(j));
629 ++counter;
630
631 // if there's no target volumes specified, default to zero
632 if (target_element_volume_in_region_pt == nullptr)
633 {
634 tetgen_io.regionlist[counter] = 0;
635 }
636 else
637 {
638 // deliberate integer division here to round down to the region
639 // number (five doubles per region)
640 tetgen_io.regionlist[counter] =
641 (*target_element_volume_in_region_pt)[unsigned(counter / 5)];
642 }
643
644 ++counter;
645 }
646 }
647 }
648 }
649 }
650
651
652 /// Empty destructor
654 {
655 if (Tetgenio_exists)
656 {
657 delete Tetgenio_pt;
658 }
659 }
660
661
662 /// Overload set_mesh_level_time_stepper so that the stored
663 /// time stepper now corresponds to the new timestepper
664 void set_mesh_level_time_stepper(TimeStepper* const& time_stepper_pt,
665 const bool& preserve_existing_data)
666 {
667 this->Time_stepper_pt = time_stepper_pt;
668 }
669
670
671 /// Boolen defining whether tetgenio object has been built or not
672 bool tetgenio_exists() const
673 {
674 return Tetgenio_exists;
675 }
676
677
678 /// Access to the triangulateio representation of the mesh
679 tetgenio*& tetgenio_pt()
680 {
681 return Tetgenio_pt;
682 }
683
684 /// Set the tetgen pointer by a deep copy
686 {
687 // Delete the existing data
688 if (Tetgenio_exists)
689 {
690 delete Tetgenio_pt;
691 }
692 this->Tetgenio_pt = new tetgenio;
693 // Create a deep copy of tetgenio_pt and store the result in
694 // Tetgenio_pt
695 this->deep_copy_of_tetgenio(tetgenio_pt, this->Tetgenio_pt);
696 }
697
698 /// Transfer tetgenio data from the input to the output
699 /// The output is assumed to have been constructed and "empty"
700 void deep_copy_of_tetgenio(tetgenio* const& input_pt, tetgenio*& output_pt);
701
702
703 protected:
704 /// Build mesh from scaffold
705 void build_from_scaffold(TimeStepper* time_stepper_pt,
706 const bool& use_attributes);
707
708 /// Function to setup the reverse look-up schemes
710 TetMeshFacetedSurface* const& faceted_surface_pt);
711
712 /// Temporary scaffold mesh
714
715 /// Boolean to indicate whether a tetgenio representation of the
716 /// mesh exists
718
719 /// Tetgen representation of mesh
720 tetgenio* Tetgenio_pt;
721
722 /// Boolean flag to indicate whether to use attributes or not
723 /// (required for multidomain meshes)
725
726 }; // end class
727
728
729 /// ///////////////////////////////////////////////////////////////
730 /// ///////////////////////////////////////////////////////////////
731 /// ///////////////////////////////////////////////////////////////
732
733
734 //==============start_mesh=================================================
735 /// Tetgen-based mesh upgraded to become a solid mesh. Automatically
736 /// enumerates all boundaries.
737 //=========================================================================
738 template<class ELEMENT>
739 class SolidTetgenMesh : public virtual TetgenMesh<ELEMENT>,
740 public virtual SolidMesh
741 {
742 public:
743 /// Constructor. Boundary coordinates are setup
744 /// automatically.
745 SolidTetgenMesh(const std::string& node_file_name,
746 const std::string& element_file_name,
747 const std::string& face_file_name,
748 const bool& split_corner_elements,
749 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
750 const bool& use_attributes = false)
751 : TetgenMesh<ELEMENT>(node_file_name,
752 element_file_name,
753 face_file_name,
754 split_corner_elements,
755 time_stepper_pt,
756 use_attributes)
757 {
758 // Assign the Lagrangian coordinates
760 }
761
762 /// Constructor. Boundary coordinates are re-setup
763 /// automatically, with the orientation of the outer unit
764 /// normal determined by switch_normal.
765 SolidTetgenMesh(const std::string& node_file_name,
766 const std::string& element_file_name,
767 const std::string& face_file_name,
768 const bool& split_corner_elements,
769 const bool& switch_normal,
770 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper,
771 const bool& use_attributes = false)
772 : TetgenMesh<ELEMENT>(node_file_name,
773 element_file_name,
774 face_file_name,
775 split_corner_elements,
776 time_stepper_pt,
777 use_attributes)
778 {
779 // Assign the Lagrangian coordinates
781
782 // Re-setup boundary coordinates for all boundaries with specified
783 // orientation of nnormal
784 unsigned nb = this->nboundary();
785 for (unsigned b = 0; b < nb; b++)
786 {
787 this->template setup_boundary_coordinates<ELEMENT>(b, switch_normal);
788 }
789 }
790
791 /// Empty Destructor
792 virtual ~SolidTetgenMesh() {}
793 };
794
795
796} // namespace oomph
797
798#endif
cstr elem_len * i
Definition: cfortran.h:603
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:827
General SolidMesh class.
Definition: mesh.h:2562
void set_lagrangian_nodal_coordinates()
Make the current configuration the undeformed one by setting the nodal Lagrangian coordinates to thei...
Definition: mesh.cc:9564
/////////////////////////////////////////////////////////////// /////////////////////////////////////...
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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
Definition: tet_mesh.h:661
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:483
TimeStepper * Time_stepper_pt
Timestepper used to build nodes.
Definition: tet_mesh.h:1057
Vector< TetMeshFacetedSurface * > Internal_surface_pt
Vector to faceted surfaces that define internal boundaries.
Definition: tet_mesh.h:1041
TetMeshFacetedClosedSurface * Outer_boundary_pt
Faceted surface that defines outer boundaries.
Definition: tet_mesh.h:1038
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Definition: tet_mesh.h:538
unsigned ninternal_point_for_tetgen()
Number of internal points (identifying either regions or holes) for tetgen.
Definition: tet_mesh.h:591
bool internal_point_identifies_region_for_tetgen(const unsigned &j)
Is j-th internal point for tetgen associated with a region?
Definition: tet_mesh.h:611
const int & region_id_for_tetgen(const unsigned &j) const
Return the (zero-based) region ID of j-th internal point for tetgen. Negative if it's actually a hole...
Definition: tet_mesh.h:598
bool internal_point_identifies_hole_for_tetgen(const unsigned &j)
Is j-th internal point for tetgen associated with a hole?
Definition: tet_mesh.h:605
const double & internal_point_for_tetgen(const unsigned &j, const unsigned &i) const
i=th coordinate of the j-th internal point for tetgen
Definition: tet_mesh.h:568
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Definition: tet_mesh.h:306
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:472
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/.
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.
TetgenMesh()
Empty constructor.
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.
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.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Definition: timesteppers.h:231
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition: Vector.h:58
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...