libMesh
Loading...
Searching...
No Matches
edge_edge3.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_edge3.h"
22#include "libmesh/enum_io_package.h"
23#include "libmesh/enum_order.h"
24
25namespace libMesh
26{
27
28// ------------------------------------------------------------
29// Edge3 class static member initializations
30const int Edge3::num_nodes;
31
32#ifdef LIBMESH_ENABLE_AMR
33
34const Real Edge3::_embedding_matrix[2][3][3] =
35 {
36 // embedding matrix for child 0
37 {
38 // 0 1 2
39 {1.0, 0.0, 0.0}, // left
40 {0.0, 0.0, 1.0}, // right
41 {0.375,-0.125,0.75} // middle
42 },
43
44 // embedding matrix for child 1
45 {
46 // 0 1 2
47 {0.0, 0.0, 1.0}, // left
48 {0.0, 1.0, 0.0}, // right
49 {-0.125,0.375,0.75} // middle
50 }
51 };
52
53#endif
54
55bool Edge3::is_vertex(const unsigned int i) const
56{
57 if (i < 2)
58 return true;
59 return false;
60}
61
62bool Edge3::is_edge(const unsigned int i) const
63{
64 if (i < 2)
65 return false;
66 return true;
67}
68
69bool Edge3::is_face(const unsigned int ) const
70{
71 return false;
72}
73
74bool Edge3::is_node_on_side(const unsigned int n,
75 const unsigned int s) const
76{
77 libmesh_assert_less (s, 2);
78 libmesh_assert_less (n, Edge3::num_nodes);
79 return (s == n);
80}
81
82bool Edge3::is_node_on_edge(const unsigned int,
83 const unsigned int libmesh_dbg_var(e)) const
84{
85 libmesh_assert_equal_to (e, 0);
86 return true;
87}
88
89
90
92{
93 Point v = this->point(1) - this->point(0);
94 return (v.relative_fuzzy_equals
95 ((this->point(2) - this->point(0))*2, affine_tol));
96}
97
98
99
101{
102 // At the moment this only makes sense for Lagrange elements
103 libmesh_assert_equal_to(this->mapping_type(), LAGRANGE_MAP);
104
105 // The "Jacobian vector" (dx/dxi, dy/dxi, dz/dxi) is:
106 // j(xi) := a*xi + b, where
107 Point a = this->point(0) + this->point(1) - 2 * this->point(2);
108 Point b = Real(.5) * (this->point(1) - this->point(0));
109
110 // Now we solve for the point xi_m where j(xi_m) \cdot j(0) = 0.
111 // If this occurs somewhere on the reference element, then the
112 // element is not invertible.
113 // j(xi_m) . j(0) = 0
114 // <=>
115 // (a*xi_m + b) . b = 0
116 // <=>
117 // (a.b)*xi_m + b.b = 0
118 // <=>
119 // xi_m = -(b.b) / (a.b)
120
121 // 1.) If b.b==0, then the endpoints of the Edge3 are at the same
122 // location, and the map is therefore not invertible.
123 Real b_norm2 = b.norm_sq();
124 if (b_norm2 <= tol*tol)
125 return false;
126
127 // 2.) If a.b==0, but b != 0 (see above), then the element is
128 // invertible but we don't want to divide by zero in the
129 // formula, so simply return true.
130 Real ab = a * b;
131 if (std::abs(ab) <= tol*tol)
132 return true;
133
134 Real xi_m = -b_norm2 / ab;
135 return (xi_m < -1.) || (xi_m > 1.);
136}
137
138
139
141{
142 return SECOND;
143}
144
145
146
147void Edge3::connectivity(const unsigned int sc,
148 const IOPackage iop,
149 std::vector<dof_id_type> & conn) const
150{
151 libmesh_assert_less_equal (sc, 1);
152 libmesh_assert_less (sc, this->n_sub_elem());
153 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
154
155 // Create storage
156 conn.resize(2);
157
158 switch (iop)
159 {
160 case TECPLOT:
161 {
162 switch (sc)
163 {
164 case 0:
165 conn[0] = this->node_id(0)+1;
166 conn[1] = this->node_id(2)+1;
167 return;
168
169 case 1:
170 conn[0] = this->node_id(2)+1;
171 conn[1] = this->node_id(1)+1;
172 return;
173
174 default:
175 libmesh_error_msg("Invalid sc = " << sc);
176 }
177 }
178
179
180 case VTK:
181 {
182 conn.resize(3);
183 conn[0] = this->node_id(0);
184 conn[1] = this->node_id(1);
185 conn[2] = this->node_id(2);
186 return;
187
188 /*
189 switch (sc)
190 {
191 case 0:
192 conn[0] = this->node_id(0);
193 conn[1] = this->node_id(2);
194
195 return;
196
197 case 1:
198 conn[0] = this->node_id(2);
199 conn[1] = this->node_id(1);
200
201 return;
202
203 default:
204 libmesh_error_msg("Invalid sc = " << sc);
205 }
206 */
207 }
208
209 default:
210 libmesh_error_msg("Unsupported IO package " << iop);
211 }
212}
213
214
215
216std::pair<unsigned short int, unsigned short int>
217Edge3::second_order_child_vertex (const unsigned int) const
218{
219 return std::pair<unsigned short int, unsigned short int>(0,0);
220}
221
222
223
225{
226 // This specialization is good for Lagrange mappings only in general
227 if (this->mapping_type() != LAGRANGE_MAP)
228 return this->Elem::volume();
229
230 // Finding the (exact) length of a general quadratic element
231 // is a surprisingly complicated formula.
232 Point A = this->point(0) + this->point(1) - 2*this->point(2);
233 Point B = (this->point(1) - this->point(0))/2;
234
235 const Real a = A.norm_sq();
236 const Real c = B.norm_sq();
237
238 // Degenerate straight line case
239 if (a == 0.)
240 return 2. * std::sqrt(c);
241
242 const Real b = -2.*std::abs(A*B);
243
244 const Real sqrt_term1 = a - b + c;
245 const Real sqrt_term2 = a + b + c;
246
247 // Fall back on straight line case instead of computing nan
248 // Note: b can be positive or negative so we have to check both cases.
249 if (sqrt_term1 < 0. || sqrt_term2 < 0.)
250 return 2. * std::sqrt(c);
251
252 const Real r1 = std::sqrt(sqrt_term1);
253 const Real r2 = std::sqrt(sqrt_term2);
254 const Real rsum = r1 + r2;
255 const Real root_a = std::sqrt(a);
256 const Real b_over_root_a = b / root_a;
257
258 // Pre-compute the denominator of the log term. If it's zero, fall
259 // back on the straight line case.
260 const Real log_term_denom = -root_a - 0.5*b_over_root_a + r2;
261 if (log_term_denom == 0. || rsum == 0.)
262 return 2. * std::sqrt(c);
263
264 Real log1p_arg = 2*(root_a - b/rsum) / log_term_denom;
265
266 return
267 0.5*(rsum + b_over_root_a*b_over_root_a/rsum +
268 (c-0.25*b_over_root_a*b_over_root_a)*std::log1p(log1p_arg)/root_a);
269}
270
271
272
274{
275 // This might be a curved line through 2-space or 3-space, in which
276 // case the full bounding box can be larger than the bounding box of
277 // just the nodes.
278 Point pmin, pmax;
279
280 for (unsigned d=0; d<LIBMESH_DIM; ++d)
281 {
282 Real center = this->point(2)(d);
283 Real hd = std::max(std::abs(center - this->point(0)(d)),
284 std::abs(center - this->point(1)(d)));
285
286 pmin(d) = center - hd;
287 pmax(d) = center + hd;
288 }
289
290 return BoundingBox(pmin, pmax);
291}
292
293
294
296{
297 return this->compute_key(this->node_id(2));
298}
299
300
301void Edge3::flip(BoundaryInfo * boundary_info)
302{
303 libmesh_assert(boundary_info);
304
305 swap2nodes(0,1);
306 swap2neighbors(0,1);
307 swap2boundarysides(0,1,boundary_info);
308}
309
310
311} // 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_node_on_side(const unsigned int n, const unsigned int s) const override
Definition edge_edge3.C:74
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
Definition edge_edge3.C:147
virtual bool is_vertex(const unsigned int i) const override
Definition edge_edge3.C:55
virtual bool is_face(const unsigned int i) const override
Definition edge_edge3.C:69
virtual Order default_order() const override
Definition edge_edge3.C:140
static const int num_nodes
Geometric constants for Edge3.
Definition edge_edge3.h:200
virtual bool is_edge(const unsigned int i) const override
Definition edge_edge3.C:62
virtual std::pair< unsigned short int, unsigned short int > second_order_child_vertex(const unsigned int n) const override
Definition edge_edge3.C:217
virtual unsigned int n_sub_elem() const override
Definition edge_edge3.h:83
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
Definition edge_edge3.C:82
virtual dof_id_type key() const override
Compute a unique key for this element which is suitable for hashing (not necessarily unique,...
Definition edge_edge3.C:295
virtual bool has_invertible_map(Real tol) const override
Definition edge_edge3.C:100
virtual BoundingBox loose_bounding_box() const override
Definition edge_edge3.C:273
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_edge3.h:227
virtual bool has_affine_map() const override
Definition edge_edge3.C:91
virtual Real volume() const override
An optimized method for computing the length of a 3-node edge.
Definition edge_edge3.C:224
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_edge3.C:301
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
auto norm_sq() const
bool relative_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) 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
Definition assembly.h:39