31 #ifndef OOMPH_TETGEN_MESH_HEADER 32 #define OOMPH_TETGEN_MESH_HEADER 36 #include <oomph-lib-config.h> 45 #include "../generic/tetgen_scaffold_mesh.h" 46 #include "../generic/tet_mesh.h" 55 template <
class ELEMENT>
65 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
70 const std::string& element_file_name,
71 const std::string& face_file_name,
72 TimeStepper* time_stepper_pt=
73 &Mesh::Default_TimeStepper,
74 const bool &use_attributes=
false)
79 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
85 Time_stepper_pt = time_stepper_pt;
89 TetgenScaffoldMesh(node_file_name,element_file_name,face_file_name);
99 unsigned nb=nboundary();
100 for (
unsigned b=0;b<nb;b++)
102 bool switch_normal=
false;
103 setup_boundary_coordinates<ELEMENT>(b,switch_normal);
110 TimeStepper* time_stepper_pt=
111 &Mesh::Default_TimeStepper,
112 const bool &use_attributes=
false)
116 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
122 Time_stepper_pt = time_stepper_pt;
130 TetgenScaffoldMesh(tetgen_data);
140 unsigned nb=nboundary();
141 for (
unsigned b=0;b<nb;b++)
143 bool switch_normal=
false;
144 setup_boundary_coordinates<ELEMENT>(b,switch_normal);
159 const std::string& element_file_name,
160 const std::string& face_file_name,
161 const bool& split_corner_elements,
162 TimeStepper* time_stepper_pt=
163 &Mesh::Default_TimeStepper,
164 const bool &use_attributes=
false)
168 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
174 Time_stepper_pt = time_stepper_pt;
182 TetgenScaffoldMesh(node_file_name,element_file_name,face_file_name);
192 if (split_corner_elements)
194 split_elements_in_corners<ELEMENT>();
198 unsigned nb=nboundary();
199 for (
unsigned b=0;b<nb;b++)
201 bool switch_normal=
false;
202 setup_boundary_coordinates<ELEMENT>(b,switch_normal);
216 const bool& split_corner_elements,
217 TimeStepper* time_stepper_pt=
218 &Mesh::Default_TimeStepper,
219 const bool &use_attributes=
false)
223 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
229 Time_stepper_pt = time_stepper_pt;
246 if (split_corner_elements)
248 split_elements_in_corners<ELEMENT>();
252 unsigned nb=nboundary();
253 for (
unsigned b=0;b<nb;b++)
255 bool switch_normal=
false;
256 setup_boundary_coordinates<ELEMENT>(b,switch_normal);
265 TetgenMesh(TetMeshFacetedClosedSurface*
const &outer_boundary_pt,
266 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
267 const double &element_volume,
268 TimeStepper* time_stepper_pt=
269 &Mesh::Default_TimeStepper,
270 const bool &use_attributes=
false,
271 const bool& split_corner_elements =
false)
274 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
280 Time_stepper_pt = time_stepper_pt;
283 Outer_boundary_pt=outer_boundary_pt;
287 unsigned n_facet=Outer_boundary_pt->nfacet();
288 for (
unsigned f=0;f<n_facet;f++)
290 unsigned b=Outer_boundary_pt->one_based_facet_boundary_id(f);
293 Tet_mesh_faceted_surface_pt[b-1]=Outer_boundary_pt;
294 Tet_mesh_facet_pt[b-1]=Outer_boundary_pt->facet_pt(f);
298 std::ostringstream error_message;
299 error_message <<
"Boundary IDs have to be one-based. Yours is " 301 throw OomphLibError(error_message.str(),
302 OOMPH_CURRENT_FUNCTION,
303 OOMPH_EXCEPTION_LOCATION);
310 Internal_surface_pt = internal_surface_pt;
314 unsigned n=Internal_surface_pt.size();
315 for (
unsigned i=0;i<n;i++)
317 unsigned n_facet=Internal_surface_pt[i]->nfacet();
318 for (
unsigned f=0;f<n_facet;f++)
320 unsigned b=Internal_surface_pt[i]->one_based_facet_boundary_id(f);
323 Tet_mesh_faceted_surface_pt[b-1]=Internal_surface_pt[i];
324 Tet_mesh_facet_pt[b-1]=Internal_surface_pt[i]->facet_pt(f);
328 std::ostringstream error_message;
329 error_message <<
"Boundary IDs have to be one-based. Yours is " 331 throw OomphLibError(error_message.str(),
332 OOMPH_CURRENT_FUNCTION,
333 OOMPH_EXCEPTION_LOCATION);
348 std::stringstream input_string;
349 input_string <<
"pAa" << element_volume;
356 bool can_boundaries_be_split =
357 outer_boundary_pt->boundaries_can_be_split_in_tetgen();
359 unsigned n_internal=internal_surface_pt.size();
360 for(
unsigned i=0;i<n_internal;i++)
362 can_boundaries_be_split &=
363 internal_surface_pt[i]->boundaries_can_be_split_in_tetgen();
368 if(can_boundaries_be_split==
false) {input_string <<
"Y";}
371 char tetswitches[100];
372 sprintf(tetswitches,
"%s",input_string.str().c_str());
377 tetrahedralize(tetswitches, &in, this->
Tetgenio_pt);
384 bool regions_exist =
false;
386 unsigned n_internal=internal_surface_pt.size();
387 for(
unsigned i=0;i<n_internal;i++)
389 TetMeshFacetedClosedSurface* srf_pt=
390 dynamic_cast<TetMeshFacetedClosedSurface*
>(internal_surface_pt[i]);
393 unsigned n_int_pts=srf_pt->ninternal_point_for_tetgen();
394 for (
unsigned j=0;j<n_int_pts;j++)
397 srf_pt->internal_point_identifies_region_for_tetgen(j);
404 if(regions_exist) {Use_attributes=
true;}
414 if (split_corner_elements)
416 split_elements_in_corners<ELEMENT>();
420 unsigned nb=nboundary();
421 for (
unsigned b=0;b<nb;b++)
423 bool switch_normal=
false;
424 setup_boundary_coordinates<ELEMENT>(b,switch_normal);
429 snap_nodes_onto_geometric_objects();
435 Vector<TetMeshFacetedSurface*>& internal_surface_pt,
441 tetgenio::polygon *p;
444 tetgen_io.firstnumber = 1;
446 tetgen_io.useindex =
true;
449 const unsigned n_internal = internal_surface_pt.size();
452 const unsigned n_outer_vertex = outer_boundary_pt->nvertex();
453 tetgen_io.numberofpoints = n_outer_vertex;
456 Vector<unsigned> n_internal_vertex(n_internal);
457 Vector<unsigned> internal_vertex_offset(n_internal);
458 for(
unsigned h=0;h<n_internal;++h)
460 n_internal_vertex[h] = internal_surface_pt[h]->nvertex();
461 internal_vertex_offset[h] = tetgen_io.numberofpoints;
462 tetgen_io.numberofpoints += n_internal_vertex[h];
466 tetgen_io.pointlist =
new double[tetgen_io.numberofpoints * 3];
467 tetgen_io.pointmarkerlist =
new int[tetgen_io.numberofpoints];
469 for(
unsigned n=0;n<n_outer_vertex;++n)
471 for(
unsigned i=0;i<3;++i)
473 tetgen_io.pointlist[counter] =
474 outer_boundary_pt->vertex_coordinate(n,i);
478 for(
unsigned h=0;h<n_internal;++h)
480 const unsigned n_inner = n_internal_vertex[h];
481 for(
unsigned n=0;n<n_inner;++n)
483 for(
unsigned i=0;i<3;++i)
485 tetgen_io.pointlist[counter] =
486 internal_surface_pt[h]->vertex_coordinate(n,i);
495 for(
unsigned n=0;n<n_outer_vertex;++n)
497 tetgen_io.pointmarkerlist[counter] =
498 outer_boundary_pt->one_based_vertex_boundary_id(n);
501 for(
unsigned h=0;h<n_internal;++h)
503 const unsigned n_inner = n_internal_vertex[h];
504 for(
unsigned n=0;n<n_inner;++n)
506 tetgen_io.pointmarkerlist[counter] =
507 internal_surface_pt[h]->one_based_vertex_boundary_id(n);
514 unsigned n_outer_facet = outer_boundary_pt->nfacet();
515 tetgen_io.numberoffacets = n_outer_facet;
516 Vector<unsigned> n_inner_facet(n_internal);
517 for(
unsigned h=0;h<n_internal;++h)
519 n_inner_facet[h] = internal_surface_pt[h]->nfacet();
520 tetgen_io.numberoffacets += n_inner_facet[h];
523 tetgen_io.facetlist =
new tetgenio::facet[tetgen_io.numberoffacets];
524 tetgen_io.facetmarkerlist =
new int[tetgen_io.numberoffacets];
528 for(
unsigned n=0;n<n_outer_facet;++n)
531 f = &tetgen_io.facetlist[counter];
532 f->numberofpolygons = 1;
533 f->polygonlist =
new tetgenio::polygon[f->numberofpolygons];
534 f->numberofholes = 0;
536 p = &f->polygonlist[0];
538 Vector<unsigned> facet = outer_boundary_pt->vertex_index_in_tetgen(n);
540 p->numberofvertices = facet.size();
541 p->vertexlist =
new int[p->numberofvertices];
542 for(
int i=0;i<p->numberofvertices;++i)
545 p->vertexlist[i] = facet[i] + 1;
549 tetgen_io.facetmarkerlist[counter] =
550 outer_boundary_pt->one_based_facet_boundary_id(n);
556 tetgen_io.numberofholes=0;
558 tetgen_io.numberofregions=0;
561 for(
unsigned h=0;h<n_internal;++h)
563 for(
unsigned n=0;n<n_inner_facet[h];++n)
566 f = &tetgen_io.facetlist[counter];
567 f->numberofpolygons = 1;
568 f->polygonlist =
new tetgenio::polygon[f->numberofpolygons];
569 f->numberofholes = 0;
571 p = &f->polygonlist[0];
573 Vector<unsigned> facet=internal_surface_pt[h]->vertex_index_in_tetgen(n);
575 p->numberofvertices = facet.size();
576 p->vertexlist =
new int[p->numberofvertices];
577 for(
int i=0;i<p->numberofvertices;++i)
580 p->vertexlist[i] = facet[i] + internal_vertex_offset[h] + 1;
583 tetgen_io.facetmarkerlist[counter] =
584 internal_surface_pt[h]->one_based_facet_boundary_id(n);
589 TetMeshFacetedClosedSurface* srf_pt=
590 dynamic_cast<TetMeshFacetedClosedSurface*
>(internal_surface_pt[h]);
593 unsigned n_int_pts=srf_pt->ninternal_point_for_tetgen();
594 for (
unsigned j=0;j<n_int_pts;j++)
596 if (srf_pt->internal_point_identifies_hole_for_tetgen(j))
598 ++tetgen_io.numberofholes;
603 if (srf_pt->internal_point_identifies_region_for_tetgen(j))
605 ++tetgen_io.numberofregions;
613 tetgen_io.holelist =
new double[3*tetgen_io.numberofholes];
617 for(
unsigned h=0;h<n_internal;++h)
619 TetMeshFacetedClosedSurface* srf_pt=
620 dynamic_cast<TetMeshFacetedClosedSurface*
>(internal_surface_pt[h]);
623 unsigned n_int_pts=srf_pt->ninternal_point_for_tetgen();
624 for (
unsigned j=0;j<n_int_pts;j++)
626 if (srf_pt->internal_point_identifies_hole_for_tetgen(j))
628 for(
unsigned i=0;i<3;++i)
630 tetgen_io.holelist[counter] =
631 srf_pt->internal_point_for_tetgen(j,i);
640 tetgen_io.regionlist =
new double[5*tetgen_io.numberofregions];
643 for(
unsigned h=0;h<n_internal;++h)
645 TetMeshFacetedClosedSurface* srf_pt=
646 dynamic_cast<TetMeshFacetedClosedSurface*
>(internal_surface_pt[h]);
649 unsigned n_int_pts=srf_pt->ninternal_point_for_tetgen();
650 for (
unsigned j=0;j<n_int_pts;j++)
652 if (srf_pt->internal_point_identifies_region_for_tetgen(j))
654 for(
unsigned i=0;i<3;++i)
656 tetgen_io.regionlist[counter] =
657 srf_pt->internal_point_for_tetgen(j,i);
660 tetgen_io.regionlist[counter] =
661 static_cast<double>(srf_pt->region_id_for_tetgen(j));
664 tetgen_io.regionlist[counter] = 0.0;
686 const bool &preserve_existing_data)
687 {this->Time_stepper_pt = time_stepper_pt;}
712 tetgenio* &output_pt);
721 const bool &use_attributes);
751 template<
class ELEMENT>
753 public virtual SolidMesh
761 const std::string& element_file_name,
762 const std::string& face_file_name,
763 const bool& split_corner_elements,
764 TimeStepper* time_stepper_pt=
765 &Mesh::Default_TimeStepper,
766 const bool &use_attributes=
false) :
767 TetgenMesh<ELEMENT>(node_file_name, element_file_name,
768 face_file_name, split_corner_elements,
769 time_stepper_pt, use_attributes)
772 set_lagrangian_nodal_coordinates();
779 const std::string& element_file_name,
780 const std::string& face_file_name,
781 const bool& split_corner_elements,
782 const bool& switch_normal,
783 TimeStepper* time_stepper_pt=
784 &Mesh::Default_TimeStepper,
785 const bool &use_attributes=
false) :
786 TetgenMesh<ELEMENT>(node_file_name, element_file_name,
787 face_file_name, split_corner_elements,
788 time_stepper_pt, use_attributes)
791 set_lagrangian_nodal_coordinates();
795 unsigned nb=this->nboundary();
796 for (
unsigned b=0;b<nb;b++)
798 this->
template setup_boundary_coordinates<ELEMENT>(b,switch_normal);
void build_from_scaffold(TimeStepper *time_stepper_pt, const bool &use_attributes)
Build mesh from scaffold.
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...
TetgenMesh()
Empty constructor.
TetgenScaffoldMesh * Tmp_mesh_pt
Temporary scaffold mesh.
bool Use_attributes
Boolean flag to indicate whether to use attributes or not (required for multidomain meshes) ...
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.
~TetgenMesh()
Empty destructor.
TetgenMesh(tetgenio &tetgen_data, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false)
Constructor with tetgenio data structure.
bool Tetgenio_exists
Boolean to indicate whether a tetgenio representation of the mesh exists.
Unstructured tet mesh based on output from Tetgen: http://wias-berlin.de/software/tetgen/.
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 build_tetgenio(TetMeshFacetedSurface *const &outer_boundary_pt, Vector< TetMeshFacetedSurface *> &internal_surface_pt, tetgenio &tetgen_io)
Build tetgenio object from the TetMeshFacetedSurfaces.
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 ...
void deep_copy_of_tetgenio(tetgenio *const &input_pt, tetgenio *&output_pt)
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...
tetgenio *& tetgenio_pt()
Access to the triangulateio representation of the mesh.
bool tetgenio_exists() const
Boolen defining whether tetgenio object has been built or not.
virtual ~SolidTetgenMesh()
Empty Destructor.
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.
void set_deep_copy_tetgenio_pt(tetgenio *const &tetgenio_pt)
Set the tetgen pointer by a deep copy.
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)
Build mesh, based on a TetgenMeshFactedClosedSurface that specifies the outer boundary of the domain ...
tetgenio * Tetgenio_pt
Tetgen representation of mesh.