libMesh
mesh_triangle_wrapper.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #include "libmesh/libmesh_config.h"
20 
21 #ifdef LIBMESH_HAVE_TRIANGLE
22 
23 // libmesh includes
24 #include "libmesh/mesh_triangle_wrapper.h"
25 #include "libmesh/boundary_info.h"
26 #include "libmesh/enum_elem_type.h"
27 #include "libmesh/face_tri3.h"
28 #include "libmesh/face_tri6.h"
29 #include "libmesh/point.h"
30 #include "libmesh/unstructured_mesh.h"
31 #include "libmesh/enum_to_string.h"
32 
33 namespace libMesh
34 {
35 
36 void TriangleWrapper::init(TriangleWrapper::triangulateio & t)
37 {
38  t.pointlist = static_cast<REAL*>(nullptr);
39  t.pointattributelist = static_cast<REAL*>(nullptr);
40  t.pointmarkerlist = static_cast<int *>(nullptr);
41  t.numberofpoints = 0 ;
42  t.numberofpointattributes = 0 ;
43 
44  t.trianglelist = static_cast<int *>(nullptr);
45  t.triangleattributelist = static_cast<REAL*>(nullptr);
46  t.trianglearealist = static_cast<REAL*>(nullptr);
47  t.neighborlist = static_cast<int *>(nullptr);
48  t.numberoftriangles = 0;
49  t.numberofcorners = 0;
50  t.numberoftriangleattributes = 0;
51 
52  t.segmentlist = static_cast<int *>(nullptr);
53  t.segmentmarkerlist = static_cast<int *>(nullptr);
54  t.numberofsegments = 0;
55 
56  t.holelist = static_cast<REAL*>(nullptr);
57  t.numberofholes = 0;
58 
59  t.regionlist = static_cast<REAL*>(nullptr);
60  t.numberofregions = 0;
61 
62  t.edgelist = static_cast<int *>(nullptr);
63  t.edgemarkerlist = static_cast<int *>(nullptr);
64  t.normlist = static_cast<REAL*>(nullptr);
65  t.numberofedges = 0;
66 }
67 
68 
69 
70 
71 
72 
73 void TriangleWrapper::destroy(TriangleWrapper::triangulateio & t, TriangleWrapper::IO_Type io_type)
74 {
75  std::free (t.pointlist );
76  std::free (t.pointattributelist );
77  std::free (t.pointmarkerlist );
78  std::free (t.trianglelist );
79  std::free (t.triangleattributelist);
80  std::free (t.trianglearealist );
81  std::free (t.neighborlist );
82  std::free (t.segmentlist );
83  std::free (t.segmentmarkerlist );
84 
85  // Only attempt to free these when t was used as an input struct!
86  if (io_type==INPUT)
87  {
88  std::free (t.holelist );
89  std::free (t.regionlist);
90  }
91 
92  std::free (t.edgelist );
93  std::free (t.edgemarkerlist);
94  std::free (t.normlist );
95 
96  // Reset
97  // TriangleWrapper::init(t);
98 }
99 
100 
101 
102 
103 
104 
105 void TriangleWrapper::copy_tri_to_mesh(const triangulateio & triangle_data_input,
106  UnstructuredMesh & mesh_output,
107  const ElemType type,
108  const triangulateio * voronoi)
109 {
110  // Transfer the information into the LibMesh mesh.
111  mesh_output.clear();
112 
113  // Make sure the new Mesh will be 2D
114  mesh_output.set_mesh_dimension(2);
115 
116  // Node information
117  for (int i=0, c=0; c<triangle_data_input.numberofpoints; i+=2, ++c)
118  {
119  // Specify ID when adding point, otherwise, if this is DistributedMesh,
120  // it might add points with a non-sequential numbering...
121  mesh_output.add_point( Point(triangle_data_input.pointlist[i],
122  triangle_data_input.pointlist[i+1]),
123  /*id=*/c);
124  }
125 
126  // Element information
127  for (int i=0; i<triangle_data_input.numberoftriangles; ++i)
128  {
129  switch (type)
130  {
131  case TRI3:
132  {
133  Elem * elem = mesh_output.add_elem(Elem::build(TRI3));
134 
135  for (unsigned int n=0; n<3; ++n)
136  elem->set_node(n, mesh_output.node_ptr(triangle_data_input.trianglelist[i*3 + n]));
137 
138  // use the first attribute to set the subdomain ID
139  if (triangle_data_input.triangleattributelist)
140  elem->subdomain_id() =
141  std::round(triangle_data_input.
142  triangleattributelist[i * triangle_data_input.numberoftriangleattributes]);
143  break;
144  }
145 
146  case TRI6:
147  {
148  Elem * elem = mesh_output.add_elem(Elem::build(TRI6));
149 
150  // Triangle number TRI6 nodes in a different way to libMesh
151  elem->set_node(0, mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 0]));
152  elem->set_node(1, mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 1]));
153  elem->set_node(2, mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 2]));
154  elem->set_node(3, mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 5]));
155  elem->set_node(4, mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 3]));
156  elem->set_node(5, mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 4]));
157 
158  // use the first attribute to set the subdomain ID
159  if (triangle_data_input.triangleattributelist)
160  elem->subdomain_id() =
161  std::round(triangle_data_input.
162  triangleattributelist[i * triangle_data_input.numberoftriangleattributes]);
163  break;
164  }
165 
166  default:
167  libmesh_error_msg("ERROR: Unrecognized triangular element type == " << Utility::enum_to_string(type));
168  }
169  }
170 
171  // Note: If the input mesh was a parallel one, calling
172  // prepare_for_use() now will re-parallelize it by a call to
173  // delete_remote_elements()... We do not actually want to
174  // reparallelize it here though: the triangulate() function may
175  // still do some Mesh smoothing. The main thing needed (for
176  // smoothing) is the neighbor information, so let's just find
177  // neighbors...
178  //mesh_output.prepare_for_use(/*skip_renumber =*/false);
179  mesh_output.find_neighbors();
180 
181  // set boundary info
182  if (voronoi && triangle_data_input.edgemarkerlist)
183  {
184  BoundaryInfo & boundary_info = mesh_output.get_boundary_info();
185  for (int e=0; e<triangle_data_input.numberofedges; ++e)
186  {
187  if (triangle_data_input.edgemarkerlist[e] != 0)
188  {
189  int p1 = triangle_data_input.edgelist[e + e];
190  int p2 = triangle_data_input.edgelist[e + e + 1];
191  int elem_id = voronoi->edgelist[e + e];
192  unsigned short int s;
193  if (p1 == triangle_data_input.trianglelist[elem_id*3] &&
194  p2 == triangle_data_input.trianglelist[elem_id*3 + 1])
195  s = 0;
196  else if (p1 == triangle_data_input.trianglelist[elem_id*3 + 1] &&
197  p2 == triangle_data_input.trianglelist[elem_id*3 + 2])
198  s = 1;
199  else if (p1 == triangle_data_input.trianglelist[elem_id*3 + 2] &&
200  p2 == triangle_data_input.trianglelist[elem_id*3])
201  s = 2;
202  else
203  libmesh_error_msg("ERROR: finding element errors for boundary edges.");
204 
205  boundary_info.add_side(elem_id, s, triangle_data_input.edgemarkerlist[e]);
206  }
207  }
208  }
209 }
210 
211 
212 }
213 
214 #endif // LIBMESH_HAVE_TRIANGLE
ElemType
Defines an enum for geometric element types.
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2558
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true) override
Other functions from MeshBase requiring re-definition.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:165
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
The UnstructuredMesh class is derived from the MeshBase class.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:444
void copy_tri_to_mesh(const triangulateio &triangle_data_input, UnstructuredMesh &mesh_output, const ElemType type, const triangulateio *voronoi=nullptr)
Copies triangulation data computed by triangle from a triangulateio object to a LibMesh mesh...
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
Definition: mesh_base.h:275
virtual void clear()
Deletes all the element and node data that is currently stored.
Definition: mesh_base.C:920
std::string enum_to_string(const T e)
subdomain_id_type subdomain_id() const
Definition: elem.h:2582
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
void destroy(triangulateio &t, IO_Type)
Frees any memory which has been dynamically allocated by Triangle.
virtual const Node * node_ptr(const dof_id_type i) const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39