libMesh
Loading...
Searching...
No Matches
edge_edge4.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
20// Local includes
21#include "libmesh/edge_edge4.h"
22#include "libmesh/enum_io_package.h"
23#include "libmesh/enum_order.h"
24
25namespace libMesh
26{
27
28// ------------------------------------------------------------
29// Edge4 class static member initializations
30const int Edge4::num_nodes;
31
32#ifdef LIBMESH_ENABLE_AMR
33
35 {
36 // embedding matrix for child 0
37
38 {
39 // 0 1 2 3 // Shape function index
40 {1.0, 0.0, 0.0, 0.0}, // left, xi = -1
41 {-0.0625, -0.0625, 0.5625, 0.5625}, // right, xi = 0
42 {0.3125, 0.0625, 0.9375, -0.3125}, // middle left, xi = -2/3
43 {0.0, 0.0, 1.0, 0.0} // middle right, xi = -1/3
44 },
45
46 // embedding matrix for child 1
47 {
48 // 0 1 2 3 // Shape function index
49 {-0.0625, -0.0625, 0.5625, 0.5625}, // left, xi = 0
50 {0.0, 1.0, 0.0, 0.0}, // right, xi = 1
51 {0.0, 0.0, 0.0, 1.0}, // middle left, xi = 1/3
52 {0.0625, 0.3125, -0.3125, 0.9375} // middle right, xi = 2/3
53 }
54 };
55
56#endif
57
58bool Edge4::is_vertex(const unsigned int i) const
59{
60 return (i==0) || (i==1);
61}
62
63bool Edge4::is_edge(const unsigned int i) const
64{
65 return (i==2) || (i==3);
66}
67
68bool Edge4::is_face(const unsigned int ) const
69{
70 return false;
71}
72
73bool Edge4::is_node_on_side(const unsigned int n,
74 const unsigned int s) const
75{
76 libmesh_assert_less (s, 2);
77 libmesh_assert_less (n, Edge4::num_nodes);
78 return (s == n);
79}
80
81bool Edge4::is_node_on_edge(const unsigned int,
82 const unsigned int libmesh_dbg_var(e)) const
83{
84 libmesh_assert_equal_to (e, 0);
85 return true;
86}
87
88
89
91{
92 Point v = this->point(1) - this->point(0);
94 ((this->point(2) - this->point(0))*3, affine_tol))
95 return false;
97 ((this->point(3) - this->point(0))*1.5, affine_tol))
98 return false;
99 return true;
100}
101
102
103
105{
106 // At the moment this only makes sense for Lagrange elements
107 libmesh_assert_equal_to(this->mapping_type(), LAGRANGE_MAP);
108
109 // dx/dxi = a*xi^2 + b*xi + c,
110 // where a, b, and c are vector quantities that depend on the
111 // nodal positions as follows:
112 const Point & x0 = this->point(0);
113 const Point & x1 = this->point(1);
114 const Point & x2 = this->point(2);
115 const Point & x3 = this->point(3);
116
117 Point a = Real(27)/16 * (x1 - x0 + 3*(x2 - x3));
118 Point b = Real(18)/16 * (x0 + x1 - x2 - x3);
119 Point c = Real(1)/16 * (x0 - x1 + 27*(x3 - x2));
120
121 // Normalized midpoint value of Jacobian. If c==0, then dx/dxi(0) =
122 // 0 and the Jacobian is either zero on the whole element, or
123 // changes sign within the element. Either way, the element is not
124 // invertible. Note: use <= tol, so that if someone passes 0 for tol
125 // it still works.
126 Real c_norm = c.norm();
127 if (c_norm <= tol)
128 return false;
129
130 // Coefficients of the quadratic scalar function
131 // j(xi) := dot(c.unit(), dx/dxi)
132 // = alpha*xi^2 + beta*xi + gamma
133 Real alpha = (a * c) / c_norm;
134 Real beta = (b * c) / c_norm;
135 Real gamma = c_norm;
136
137 // If alpha and beta are both (approximately) zero, then the
138 // Jacobian is actually constant but it's not zero (as we already
139 // checked) so the element is invertible!
140 if ((std::abs(alpha) <= tol) && (std::abs(beta) <= tol))
141 return true;
142
143 // If alpha is approximately zero, but beta is not, then j(xi) is
144 // actually linear and the Jacobian changes sign at the point xi =
145 // -gamma/beta, so we need to check whether that's in the
146 // element.
147 if (std::abs(alpha) <= tol)
148 {
149 // Debugging:
150 // libMesh::out << "alpha = " << alpha << ", std::abs(alpha) <= tol" << std::endl;
151
152 Real xi_0 = -gamma / beta;
153 return ((xi_0 < -1.) || (xi_0 > 1.));
154 }
155
156 // If alpha is not (approximately) zero, then j(xi) is quadratic
157 // and we need to solve for the roots.
158 Real sqrt_term = beta*beta - 4*alpha*gamma;
159
160 // Debugging:
161 // libMesh::out << "sqrt_term = " << sqrt_term << std::endl;
162
163 // If the term under the square root is negative, then the roots are
164 // imaginary and the element is invertible.
165 if (sqrt_term < 0)
166 return true;
167
168 sqrt_term = std::sqrt(sqrt_term);
169 Real
170 xi_1 = 0.5 * (-beta + sqrt_term) / alpha,
171 xi_2 = 0.5 * (-beta - sqrt_term) / alpha;
172
173 // libMesh::out << "xi_1 = " << xi_1 << std::endl;
174 // libMesh::out << "xi_2 = " << xi_2 << std::endl;
175
176 // If a root is outside the reference element, it is "OK".
177 bool
178 xi_1_ok = ((xi_1 < -1.) || (xi_1 > 1.)),
179 xi_2_ok = ((xi_2 < -1.) || (xi_2 > 1.));
180
181 // If both roots are OK, the element is invertible.
182 return xi_1_ok && xi_2_ok;
183}
184
185
186
188{
189 return THIRD;
190}
191
192
193
194void Edge4::connectivity(const unsigned int sc,
195 const IOPackage iop,
196 std::vector<dof_id_type> & conn) const
197{
198 libmesh_assert_less_equal (sc, 2);
199 libmesh_assert_less (sc, this->n_sub_elem());
200 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
201
202 // Create storage
203 conn.resize(2);
204
205 switch(iop)
206 {
207 case TECPLOT:
208 {
209 switch (sc)
210 {
211 case 0:
212 conn[0] = this->node_id(0)+1;
213 conn[1] = this->node_id(2)+1;
214 return;
215
216 case 1:
217 conn[0] = this->node_id(2)+1;
218 conn[1] = this->node_id(3)+1;
219 return;
220
221 case 2:
222 conn[0] = this->node_id(3)+1;
223 conn[1] = this->node_id(1)+1;
224 return;
225
226 default:
227 libmesh_error_msg("Invalid sc = " << sc);
228 }
229
230 }
231
232 case VTK:
233 {
234
235 switch (sc)
236 {
237 case 0:
238 conn[0] = this->node_id(0);
239 conn[1] = this->node_id(2);
240 return;
241
242 case 1:
243 conn[0] = this->node_id(2);
244 conn[1] = this->node_id(3);
245 return;
246
247 case 2:
248 conn[0] = this->node_id(3);
249 conn[1] = this->node_id(1);
250 return;
251
252 default:
253 libmesh_error_msg("Invalid sc = " << sc);
254 }
255 }
256
257 default:
258 libmesh_error_msg("Unsupported IO package " << iop);
259 }
260}
261
262
263
265{
266 // This might be a curved line through 2-space or 3-space, in which
267 // case the full bounding box can be larger than the bounding box of
268 // just the nodes.
269 //
270 // FIXME - I haven't yet proven the formula below to be correct for
271 // cubics - RHS
272 Point pmin, pmax;
273
274 for (unsigned d=0; d<LIBMESH_DIM; ++d)
275 {
276 Real center = (this->point(2)(d) + this->point(3)(d))/2;
277 Real hd = std::max(std::abs(center - this->point(0)(d)),
278 std::abs(center - this->point(1)(d)));
279
280 pmin(d) = center - hd;
281 pmax(d) = center + hd;
282 }
283
284 return BoundingBox(pmin, pmax);
285}
286
287
288
290{
291 return this->compute_key(this->node_id(0),
292 this->node_id(1),
293 this->node_id(2),
294 this->node_id(3));
295}
296
297
298
300{
301 // This specialization is good for Lagrange mappings only in general
302 if (this->mapping_type() != LAGRANGE_MAP)
303 return this->Elem::volume();
304
305 // Make copies of our points. It makes the subsequent calculations a bit
306 // shorter and avoids dereferencing the same pointer multiple times.
307 Point
308 x0 = point(0),
309 x1 = point(1),
310 x2 = point(2),
311 x3 = point(3);
312
313 // Construct constant data vectors.
314 // \vec{x}_{\xi} = \vec{a1}*xi**2 + \vec{b1}*xi + \vec{c1}
315 // This is copy-pasted directly from the output of a Python script.
316 Point
317 a1 = -27*x0/16 + 27*x1/16 + 81*x2/16 - 81*x3/16,
318 b1 = 9*x0/8 + 9*x1/8 - 9*x2/8 - 9*x3/8,
319 c1 = x0/16 - x1/16 - 27*x2/16 + 27*x3/16;
320
321 // 4 point quadrature, 7th-order accurate
322 const unsigned int N = 4;
323 const Real q[N] = {-std::sqrt(525 + 70*std::sqrt(30.)) / 35,
324 -std::sqrt(525 - 70*std::sqrt(30.)) / 35,
325 std::sqrt(525 - 70*std::sqrt(30.)) / 35,
326 std::sqrt(525 + 70*std::sqrt(30.)) / 35};
327 const Real w[N] = {(18 - std::sqrt(30.)) / 36,
328 (18 + std::sqrt(30.)) / 36,
329 (18 + std::sqrt(30.)) / 36,
330 (18 - std::sqrt(30.)) / 36};
331
332 Real vol=0.;
333 for (unsigned int i=0; i<N; ++i)
334 vol += w[i] * (q[i]*q[i]*a1 + q[i]*b1 + c1).norm();
335
336 return vol;
337}
338
339
340void Edge4::flip(BoundaryInfo * boundary_info)
341{
342 libmesh_assert(boundary_info);
343
344 swap2nodes(0,1);
345 swap2nodes(2,3);
346 swap2neighbors(0,1);
347 swap2boundarysides(0,1,boundary_info);
348}
349
350
351} // namespace libMesh
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
Defines a Cartesian bounding box by the two corner extremum.
virtual bool is_edge(const unsigned int i) const override
Definition edge_edge4.C:63
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
Definition edge_edge4.C:194
virtual bool has_affine_map() const override
Definition edge_edge4.C:90
virtual bool is_vertex(const unsigned int i) const override
Definition edge_edge4.C:58
virtual BoundingBox loose_bounding_box() const override
Definition edge_edge4.C:264
virtual dof_id_type key() const override
Definition edge_edge4.C:289
static const Real _embedding_matrix[num_children][num_nodes][num_nodes]
Matrix that computes new nodal locations/solution values from current nodes/solution.
Definition edge_edge4.h:221
virtual Order default_order() const override
Definition edge_edge4.C:187
virtual Real volume() const override
An optimized method for approximating the length of an EDGE4 using quadrature.
Definition edge_edge4.C:299
static const int num_nodes
Geometric constants for Edge4.
Definition edge_edge4.h:194
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
Definition edge_edge4.C:81
virtual unsigned int n_sub_elem() const override
Definition edge_edge4.h:84
virtual void flip(BoundaryInfo *) override final
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
Definition edge_edge4.C:340
virtual bool has_invertible_map(Real tol) const override
Definition edge_edge4.C:104
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
Definition edge_edge4.C:73
virtual bool is_face(const unsigned int i) const override
Definition edge_edge4.C:68
static const int num_children
Definition edge.h:66
static constexpr Real affine_tol
Default tolerance to use in has_affine_map().
Definition elem.h:2070
const Point & point(const unsigned int i) const
Definition elem.h:2462
void swap2nodes(unsigned int n1, unsigned int n2)
Swaps two node_ptrs.
Definition elem.h:2101
void swap2neighbors(unsigned int n1, unsigned int n2)
Swaps two neighbor_ptrs.
Definition elem.h:2111
void swap2boundarysides(unsigned short s1, unsigned short s2, BoundaryInfo *boundary_info) const
Swaps two sides in boundary_info, if it is non-null.
Definition elem.C:3579
ElemMappingType mapping_type() const
Definition elem.h:3137
static dof_id_type compute_key(dof_id_type n0)
Definition elem.h:3311
virtual Real volume() const
Definition elem.C:3462
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2484
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
bool relative_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
auto norm() const
static const Real b
The libMesh namespace provides an interface to certain functionality in the library.
IOPackage
libMesh interfaces with several different software packages for the purposes of creating,...
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real