libMesh
Loading...
Searching...
No Matches
face_inf_quad.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// Local includes
20#include "libmesh/libmesh_config.h"
21#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
22
23// Local includes cont'd
24#include "libmesh/face_inf_quad.h"
25#include "libmesh/edge_edge2.h"
26#include "libmesh/edge_inf_edge2.h"
27#include "libmesh/face_inf_quad4.h"
28#include "libmesh/enum_elem_quality.h"
29
30namespace libMesh
31{
32
33
34// ------------------------------------------------------------
35// InfQuad class static member initializations
36const int InfQuad::num_sides;
37const int InfQuad::num_children;
38
39// Note: we can omit initialization of the third entry of each row because
40// static variables are automatically zero-initialized.
41const Real InfQuad::_master_points[6][3] =
42 {
43 {-1, 0},
44 {1, 0},
45 {-1, 1},
46 {1, 1},
47 {0, 0},
48 {0, 1}
49 };
50
51const unsigned int InfQuad::adjacent_sides_map[/*num_vertices*/4][/*max_adjacent_sides*/2] =
52 {
53 {0, 2}, // Sides adjacent to node 0
54 {0, 1}, // Sides adjacent to node 1
55 {2, 99}, // Sides adjacent to node 2
56 {1, 99} // Sides adjacent to node 3
57 };
58
59// ------------------------------------------------------------
60// InfQuad class member functions
61dof_id_type InfQuad::key (const unsigned int s) const
62{
63 libmesh_assert_less (s, this->n_sides());
64
65 // The order of the node ids does not matter, they are sorted by the
66 // compute_key() function.
67 return this->compute_key(this->node_id(InfQuad4::side_nodes_map[s][0]),
69}
70
71
72
73dof_id_type InfQuad::low_order_key (const unsigned int s) const
74{
75 libmesh_assert_less (s, this->n_sides());
76
77 // The order of the node ids does not matter, they are sorted by the
78 // compute_key() function.
79 return this->compute_key(this->node_id(InfQuad4::side_nodes_map[s][0]),
81}
82
83
84
85unsigned int InfQuad::local_side_node(unsigned int side,
86 unsigned int side_node) const
87{
88 libmesh_assert_less (side, this->n_sides());
89 libmesh_assert_less (side_node, 2);
90
91 return InfQuad4::side_nodes_map[side][side_node];
92}
93
94
95
96unsigned int InfQuad::local_edge_node(unsigned int edge,
97 unsigned int edge_node) const
98{
99 return local_side_node(edge, edge_node);
100}
101
102
103
104std::unique_ptr<Elem> InfQuad::side_ptr (const unsigned int i)
105{
106 libmesh_assert_less (i, this->n_sides());
107
108 // Return value
109 std::unique_ptr<Elem> edge;
110
111 switch (i)
112 {
113 case 0: // base face
114 {
115 edge = std::make_unique<Edge2>();
116 break;
117 }
118
119 case 1: // adjacent to another infinite element
120 case 2: // adjacent to another infinite element
121 {
122 edge = std::make_unique<InfEdge2>();
123 break;
124 }
125
126 default:
127 libmesh_error_msg("Invalid side i = " << i);
128 }
129
130 // Set the nodes
131 for (auto n : edge->node_index_range())
132 edge->set_node(n, this->node_ptr(InfQuad4::side_nodes_map[i][n]));
133
134 return edge;
135}
136
137
138
139void InfQuad::side_ptr (std::unique_ptr<Elem> & side,
140 const unsigned int i)
141{
142 libmesh_assert_less (i, this->n_sides());
143
144 switch (i)
145 {
146 // the base face
147 case 0:
148 {
149 if (!side.get() || side->type() != EDGE2)
150 {
151 side = this->side_ptr(i);
152 return;
153 }
154 break;
155 }
156
157 // connecting to another infinite element
158 case 1:
159 case 2:
160 {
161 if (!side.get() || side->type() != INFEDGE2)
162 {
163 side = this->side_ptr(i);
164 return;
165 }
166 break;
167 }
168
169 default:
170 libmesh_error_msg("Invalid side i = " << i);
171 }
172
173 side->subdomain_id() = this->subdomain_id();
174
175 // Set the nodes
176 for (auto n : side->node_index_range())
177 side->set_node(n, this->node_ptr(InfQuad4::side_nodes_map[i][n]));
178}
179
180
181bool InfQuad::is_child_on_side(const unsigned int c,
182 const unsigned int s) const
183{
184 libmesh_assert_less (c, this->n_children());
185 libmesh_assert_less (s, this->n_sides());
186
187 return (s == 0 ||
188 (c == 0 && s == 2) ||
189 (c == 1 && s == 1));
190}
191
192
193bool
195{
196 return (
197#if LIBMESH_DIM > 2
198 // Don't bother outside the XY plane
199 this->point(0)(2) && this->point(1)(2) &&
200 this->point(2)(2) && this->point(3)(2) &&
201#endif
202 ((this->point(1)(0)-this->point(0)(0))*
203 (this->point(2)(1)-this->point(0)(1)) >
204 (this->point(2)(0)-this->point(0)(0))*
205 (this->point(1)(1)-this->point(0)(1))));
206}
207
208
209std::vector<unsigned int>
210InfQuad::edges_adjacent_to_node(const unsigned int n) const
211{
212 libmesh_assert_less(n, this->n_nodes());
213
214 // For vertices, we use the adjacent_sides_map, otherwise node
215 // 4 is on side 0 and node 5 is not any any side.
216 if (this->is_vertex(n))
217 {
218 auto trim = (n < 2) ? 0 : 1;
219 return {std::begin(adjacent_sides_map[n]), std::end(adjacent_sides_map[n]) - trim};
220 }
221 else if (n == 4)
222 return {0};
223 else
224 return {};
225}
226
227
229{
230 return Elem::quality(q); // Not implemented
231}
232
233
234
235
236std::pair<Real, Real> InfQuad::qual_bounds (const ElemQuality q) const
237{
238 std::pair<Real, Real> bounds;
239
240 switch (q)
241 {
242
243 case ASPECT_RATIO:
244 bounds.first = 1.;
245 bounds.second = 4.;
246 break;
247
248 case SKEW:
249 bounds.first = 0.;
250 bounds.second = 0.5;
251 break;
252
253 case TAPER:
254 bounds.first = 0.;
255 bounds.second = 0.7;
256 break;
257
258 case WARP:
259 bounds.first = 0.9;
260 bounds.second = 1.;
261 break;
262
263 case STRETCH:
264 bounds.first = 0.25;
265 bounds.second = 1.;
266 break;
267
268 case MIN_ANGLE:
269 bounds.first = 45.;
270 bounds.second = 90.;
271 break;
272
273 case MAX_ANGLE:
274 bounds.first = 90.;
275 bounds.second = 135.;
276 break;
277
278 case CONDITION:
279 bounds.first = 1.;
280 bounds.second = 4.;
281 break;
282
283 case JACOBIAN:
284 case SCALED_JACOBIAN:
285 bounds.first = 0.5;
286 bounds.second = 1.;
287 break;
288
289 case SHEAR:
290 case SHAPE:
291 case SIZE:
292 bounds.first = 0.3;
293 bounds.second = 1.;
294 break;
295
296 case DISTORTION:
297 bounds.first = 0.6;
298 bounds.second = 1.;
299 break;
300
301 default:
302 libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
303 bounds.first = -1;
304 bounds.second = -1;
305 }
306
307 return bounds;
308}
309
310
311
313 const Real eps) const
314{
315 const Real & xi = p(0);
316 const Real & eta = p(1);
317
318 // The reference infquad is [-1,1]^2.
319 return ((xi >= -1.-eps) &&
320 (xi <= 1.+eps) &&
321 (eta >= -1.-eps) &&
322 (eta <= 1.+eps));
323}
324
325
326
327} // namespace libMesh
328
329
330
331#endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
const Point & point(const unsigned int i) const
Definition elem.h:2462
virtual unsigned int n_nodes() const =0
virtual Real quality(const ElemQuality q) const
Definition elem.C:1783
subdomain_id_type subdomain_id() const
Definition elem.h:2591
static dof_id_type compute_key(dof_id_type n0)
Definition elem.h:3311
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2484
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override final
virtual std::pair< Real, Real > qual_bounds(const ElemQuality q) const override
static const int num_sides
Geometric constants for all InfQuads.
virtual bool is_vertex(const unsigned int i) const override final
We number vertices first.
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int n) const override
static const Real _master_points[6][3]
Master element node locations.
virtual bool is_flipped() const override final
virtual unsigned int n_children() const override final
virtual dof_id_type low_order_key(const unsigned int s) const override
static const unsigned int adjacent_sides_map[4][2]
This maps the node to the one or two side id(s) adjacent to the node.
virtual Real quality(const ElemQuality q) const override
virtual dof_id_type key() const
Don't hide Elem::key() defined in the base class.
Definition elem.C:738
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const override
Calls local_side_node(edge, edge_node).
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const override final
static const int num_children
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
virtual unsigned int n_sides() const override final
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The libMesh namespace provides an interface to certain functionality in the library.
OStreamProxy out
ElemQuality
Defines an enum for element quality metrics.
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real