libMesh
Loading...
Searching...
No Matches
mesh_triangle_wrapper.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
33namespace libMesh
34{
35
36void 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
73void 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
105void 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
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
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.
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual Node *& set_node(const unsigned int i)
Definition elem.h:2567
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
subdomain_id_type subdomain_id() const
Definition elem.h:2591
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
virtual const Node * node_ptr(const dof_id_type i) const =0
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
Definition mesh_base.h:423
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.
virtual void clear()
Deletes all the element and node data that is currently stored.
Definition mesh_base.C:1036
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The UnstructuredMesh class is derived from the MeshBase class.
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true, const bool assert_valid=true) override
Other functions from MeshBase requiring re-definition.
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.
void destroy(triangulateio &t, IO_Type)
Frees any memory which has been dynamically allocated by Triangle.
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
ElemType
Defines an enum for geometric element types.