Loading [MathJax]/extensions/tex2jax.js
libMesh
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
edge_edge4.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 
20 // Local includes
21 #include "libmesh/edge_edge4.h"
22 #include "libmesh/enum_io_package.h"
23 #include "libmesh/enum_order.h"
24 
25 namespace libMesh
26 {
27 
28 // ------------------------------------------------------------
29 // Edge4 class static member initializations
30 const 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 
58 bool Edge4::is_vertex(const unsigned int i) const
59 {
60  return (i==0) || (i==1);
61 }
62 
63 bool Edge4::is_edge(const unsigned int i) const
64 {
65  return (i==2) || (i==3);
66 }
67 
68 bool Edge4::is_face(const unsigned int ) const
69 {
70  return false;
71 }
72 
73 bool 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 
81 bool 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 
194 void 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  // Make copies of our points. It makes the subsequent calculations a bit
302  // shorter and avoids dereferencing the same pointer multiple times.
303  Point
304  x0 = point(0),
305  x1 = point(1),
306  x2 = point(2),
307  x3 = point(3);
308 
309  // Construct constant data vectors.
310  // \vec{x}_{\xi} = \vec{a1}*xi**2 + \vec{b1}*xi + \vec{c1}
311  // This is copy-pasted directly from the output of a Python script.
312  Point
313  a1 = -27*x0/16 + 27*x1/16 + 81*x2/16 - 81*x3/16,
314  b1 = 9*x0/8 + 9*x1/8 - 9*x2/8 - 9*x3/8,
315  c1 = x0/16 - x1/16 - 27*x2/16 + 27*x3/16;
316 
317  // 4 point quadrature, 7th-order accurate
318  const unsigned int N = 4;
319  const Real q[N] = {-std::sqrt(525 + 70*std::sqrt(30.)) / 35,
320  -std::sqrt(525 - 70*std::sqrt(30.)) / 35,
321  std::sqrt(525 - 70*std::sqrt(30.)) / 35,
322  std::sqrt(525 + 70*std::sqrt(30.)) / 35};
323  const Real w[N] = {(18 - std::sqrt(30.)) / 36,
324  (18 + std::sqrt(30.)) / 36,
325  (18 + std::sqrt(30.)) / 36,
326  (18 - std::sqrt(30.)) / 36};
327 
328  Real vol=0.;
329  for (unsigned int i=0; i<N; ++i)
330  vol += w[i] * (q[i]*q[i]*a1 + q[i]*b1 + c1).norm();
331 
332  return vol;
333 }
334 
335 
336 void Edge4::flip(BoundaryInfo * boundary_info)
337 {
338  libmesh_assert(boundary_info);
339 
340  swap2nodes(0,1);
341  swap2nodes(2,3);
342  swap2neighbors(0,1);
343  swap2boundarysides(0,1,boundary_info);
344 }
345 
346 
347 } // namespace libMesh
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
Definition: edge_edge4.C:73
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
Definition: edge_edge4.C:194
auto norm() const -> decltype(std::norm(T()))
Definition: type_vector.h:907
virtual BoundingBox loose_bounding_box() const override
Definition: edge_edge4.C:264
virtual bool is_edge(const unsigned int i) const override
Definition: edge_edge4.C:63
static const int num_nodes
Geometric constants for Edge4.
Definition: edge_edge4.h:194
IOPackage
libMesh interfaces with several different software packages for the purposes of creating, reading, and writing mesh files.
virtual dof_id_type key() const override
Definition: edge_edge4.C:289
virtual bool is_face(const unsigned int i) const override
Definition: edge_edge4.C:68
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:3534
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:336
The libMesh namespace provides an interface to certain functionality in the library.
static const int num_children
Definition: edge.h:66
virtual bool has_invertible_map(Real tol) const override
Definition: edge_edge4.C:104
ElemMappingType mapping_type() const
Definition: elem.h:3120
void swap2nodes(unsigned int n1, unsigned int n2)
Swaps two node_ptrs.
Definition: elem.h:2092
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
libmesh_assert(ctx)
static constexpr Real affine_tol
Default tolerance to use in has_affine_map().
Definition: elem.h:2061
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
void swap2neighbors(unsigned int n1, unsigned int n2)
Swaps two neighbor_ptrs.
Definition: elem.h:2102
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
virtual unsigned int n_sub_elem() const override
Definition: edge_edge4.h:84
virtual Real volume() const override
An optimized method for approximating the length of an EDGE4 using quadrature.
Definition: edge_edge4.C:299
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual bool is_vertex(const unsigned int i) const override
Definition: edge_edge4.C:58
virtual bool has_affine_map() const override
Definition: edge_edge4.C:90
virtual Order default_order() const override
Definition: edge_edge4.C:187
static dof_id_type compute_key(dof_id_type n0)
Definition: elem.h:3294
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
Definition: edge_edge4.C:81
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2475
const Point & point(const unsigned int i) const
Definition: elem.h:2453
bool relative_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
Definition: type_vector.h:981
uint8_t dof_id_type
Definition: id_types.h:67