libMesh
Loading...
Searching...
No Matches
cell_prism6.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/cell_prism6.h"
21#include "libmesh/edge_edge2.h"
22#include "libmesh/face_quad4.h"
23#include "libmesh/face_tri3.h"
24#include "libmesh/enum_io_package.h"
25#include "libmesh/enum_order.h"
26#include "libmesh/fe_lagrange_shape_1D.h"
27
28// C++ includes
29#include <array>
30
31// Helper functions for computing volume() and true_centroid()
32namespace {
33
34using namespace libMesh;
35
36// Templated numerical quadrature implementation function used by both
37// Prism6::volume() and Prism6::true_centroid() routines.
38template <typename T>
39void cell_integral(const Elem * elem, T & t);
40
44struct VolumeIntegral
45{
46 // API
47 void accumulate_qp(Real /*xi*/, Real /*eta*/, Real /*zeta*/, Real JxW)
48 {
49 vol += JxW;
50 };
51
52 Real vol = 0.;
53};
54
59struct NodalVolumeIntegral
60{
61 // API
62 void accumulate_qp(Real xi, Real eta, Real zeta, Real JxW)
63 {
64 // Copied from fe_lagrange_shape_3D.C
65 static const unsigned int i0[] = {0, 0, 0, 1, 1, 1};
66 static const unsigned int i1[] = {0, 1, 2, 0, 1, 2};
67
68 // Copied from fe_lagrange_shape_2D.C
69 auto tri3_phi = [](int i, Real x, Real y)
70 {
71 switch(i)
72 {
73 case 0:
74 return 1 - x - y;
75
76 case 1:
77 return x;
78
79 case 2:
80 return y;
81
82 default:
83 libmesh_error_msg("Invalid shape function index i = " << i);
84 }
85 };
86
87 for (int i=0; i<6; ++i)
88 {
89 Real phi =
90 tri3_phi(i1[i], xi, eta) * fe_lagrange_1D_linear_shape(i0[i], zeta);
91
92 V[i] += phi * JxW;
93 }
94 };
95
96 // nodal volumes
97 std::array<Real, 6> V {};
98};
99
100}
101
102namespace libMesh
103{
104
105
106
107// ------------------------------------------------------------
108// Prism6 class static member initializations
109const int Prism6::num_nodes;
110const int Prism6::nodes_per_side;
111const int Prism6::nodes_per_edge;
112
114 {
115 {0, 1, 2, 3}, // Side 0
116 {0, 1, 4, 5}, // Side 1
117 {1, 2, 5, 6}, // Side 2
118 {0, 2, 4, 6}, // Side 3
119 {4, 5, 6, 7} // Side 4
120 };
121
122// ------------------------------------------------------------
123// Prism6 class member functions
124
125bool Prism6::is_vertex(const unsigned int libmesh_dbg_var(n)) const
126{
127 libmesh_assert_not_equal_to (n, invalid_uint);
128 return true;
129}
130
131bool Prism6::is_edge(const unsigned int) const
132{
133 return false;
134}
135
136
137bool Prism6::is_face(const unsigned int) const
138{
139 return false;
140}
141
142bool Prism6::is_node_on_side(const unsigned int n,
143 const unsigned int s) const
144{
145 libmesh_assert_less (s, n_sides());
146 return std::find(std::begin(side_nodes_map[s]),
147 std::end(side_nodes_map[s]),
148 n) != std::end(side_nodes_map[s]);
149}
150
151std::vector<unsigned>
152Prism6::nodes_on_side(const unsigned int s) const
153{
154 libmesh_assert_less(s, n_sides());
155 auto trim = (s > 0 && s < 4) ? 0 : 1;
156 return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
157}
158
159std::vector<unsigned>
160Prism6::nodes_on_edge(const unsigned int e) const
161{
162 libmesh_assert_less(e, n_edges());
163 return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
164}
165
166bool Prism6::is_node_on_edge(const unsigned int n,
167 const unsigned int e) const
168{
169 libmesh_assert_less (e, n_edges());
170 return std::find(std::begin(edge_nodes_map[e]),
171 std::end(edge_nodes_map[e]),
172 n) != std::end(edge_nodes_map[e]);
173}
174
175
176
178{
179 // Make sure z edges are affine
180 Point v = this->point(3) - this->point(0);
181 if (!v.relative_fuzzy_equals(this->point(4) - this->point(1), affine_tol) ||
182 !v.relative_fuzzy_equals(this->point(5) - this->point(2), affine_tol))
183 return false;
184 return true;
185}
186
187
188
190{
191 return FIRST;
192}
193
194
195
196std::unique_ptr<Elem> Prism6::build_side_ptr (const unsigned int i)
197{
198 libmesh_assert_less (i, this->n_sides());
199
200 std::unique_ptr<Elem> face;
201
202 switch (i)
203 {
204 case 0: // the triangular face at z=-1
205 case 4: // the triangular face at z=1
206 {
207 face = std::make_unique<Tri3>();
208 break;
209 }
210 case 1: // the quad face at y=0
211 case 2: // the other quad face
212 case 3: // the quad face at x=0
213 {
214 face = std::make_unique<Quad4>();
215 break;
216 }
217 default:
218 libmesh_error_msg("Invalid side i = " << i);
219 }
220
221 // Set the nodes
222 for (auto n : face->node_index_range())
223 face->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
224
225 face->set_interior_parent(this);
226 face->inherit_data_from(*this);
227
228 return face;
229}
230
231
232
233void Prism6::build_side_ptr (std::unique_ptr<Elem> & side,
234 const unsigned int i)
235{
236 this->side_ptr(side, i);
237 side->set_interior_parent(this);
238 side->inherit_data_from(*this);
239}
240
241
242
243std::unique_ptr<Elem> Prism6::build_edge_ptr (const unsigned int i)
244{
245 return this->simple_build_edge_ptr<Edge2,Prism6>(i);
246}
247
248
249
250void Prism6::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
251{
252 this->simple_build_edge_ptr<Prism6>(edge, i, EDGE2);
253}
254
255
256
257void Prism6::connectivity(const unsigned int libmesh_dbg_var(sc),
258 const IOPackage iop,
259 std::vector<dof_id_type> & conn) const
260{
262 libmesh_assert_less (sc, this->n_sub_elem());
263 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
264
265 switch (iop)
266 {
267 case TECPLOT:
268 {
269 conn.resize(8);
270 conn[0] = this->node_id(0)+1;
271 conn[1] = this->node_id(1)+1;
272 conn[2] = this->node_id(2)+1;
273 conn[3] = this->node_id(2)+1;
274 conn[4] = this->node_id(3)+1;
275 conn[5] = this->node_id(4)+1;
276 conn[6] = this->node_id(5)+1;
277 conn[7] = this->node_id(5)+1;
278 return;
279 }
280
281 case VTK:
282 {
283 conn.resize(6);
284 conn[0] = this->node_id(0);
285 conn[1] = this->node_id(2);
286 conn[2] = this->node_id(1);
287 conn[3] = this->node_id(3);
288 conn[4] = this->node_id(5);
289 conn[5] = this->node_id(4);
290 return;
291 }
292
293 default:
294 libmesh_error_msg("Unsupported IO package " << iop);
295 }
296}
297
298
299
300#ifdef LIBMESH_ENABLE_AMR
301
303 {
304 // embedding matrix for child 0
305 {
306 // 0 1 2 3 4 5
307 { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0
308 { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 1
309 { 0.5, 0.0, 0.5, 0.0, 0.0, 0.0}, // 2
310 { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0}, // 3
311 { .25, .25, 0.0, .25, .25, 0.0}, // 4
312 { .25, 0.0, .25, .25, 0.0, .25} // 5
313 },
314
315 // embedding matrix for child 1
316 {
317 // 0 1 2 3 4 5
318 { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0
319 { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1
320 { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0}, // 2
321 { .25, .25, 0.0, .25, .25, 0.0}, // 3
322 { 0.0, 0.5, 0.0, 0.0, 0.5, 0.0}, // 4
323 { 0.0, .25, .25, 0.0, .25, .25} // 5
324 },
325
326 // embedding matrix for child 2
327 {
328 // 0 1 2 3 4 5
329 { 0.5, 0.0, 0.5, 0.0, 0.0, 0.0}, // 0
330 { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0}, // 1
331 { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 2
332 { .25, 0.0, .25, .25, 0.0, .25}, // 3
333 { 0.0, .25, .25, 0.0, .25, .25}, // 4
334 { 0.0, 0.0, 0.5, 0.0, 0.0, 0.5} // 5
335 },
336
337 // embedding matrix for child 3
338 {
339 // 0 1 2 3 4 5
340 { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0
341 { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0}, // 1
342 { 0.5, 0.0, 0.5, 0.0, 0.0, 0.0}, // 2
343 { .25, .25, 0.0, .25, .25, 0.0}, // 3
344 { 0.0, .25, .25, 0.0, .25, .25}, // 4
345 { .25, 0.0, .25, .25, 0.0, .25} // 5
346 },
347
348 // embedding matrix for child 4
349 {
350 // 0 1 2 3 4 5
351 { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0}, // 0
352 { .25, .25, 0.0, .25, .25, 0.0}, // 1
353 { .25, 0.0, .25, .25, 0.0, .25}, // 2
354 { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 3
355 { 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 4
356 { 0.0, 0.0, 0.0, 0.5, 0.0, 0.5} // 5
357 },
358
359 // embedding matrix for child 5
360 {
361 // 0 1 2 3 4 5
362 { .25, .25, 0.0, .25, .25, 0.0}, // 0
363 { 0.0, 0.5, 0.0, 0.0, 0.5, 0.0}, // 1
364 { 0.0, .25, .25, 0.0, .25, .25}, // 2
365 { 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 3
366 { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 4
367 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5} // 5
368 },
369
370 // embedding matrix for child 6
371 {
372 // 0 1 2 3 4 5
373 { .25, 0.0, .25, .25, 0.0, .25}, // 0
374 { 0.0, .25, .25, 0.0, .25, .25}, // 1
375 { 0.0, 0.0, 0.5, 0.0, 0.0, 0.5}, // 2
376 { 0.0, 0.0, 0.0, 0.5, 0.0, 0.5}, // 3
377 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 4
378 { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0} // 5
379 },
380
381 // embedding matrix for child 7
382 {
383 // 0 1 2 3 4 5
384 { .25, .25, 0.0, .25, .25, 0.0}, // 0
385 { 0.0, .25, .25, 0.0, .25, .25}, // 1
386 { .25, 0.0, .25, .25, 0.0, .25}, // 2
387 { 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 3
388 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 4
389 { 0.0, 0.0, 0.0, 0.5, 0.0, 0.5} // 5
390 }
391 };
392
393#endif
394
395
396
398{
399 NodalVolumeIntegral nvi;
400 cell_integral(this, nvi);
401
402 // Compute centroid
403 Point cp;
404 Real vol = 0.;
405
406 for (int i=0; i<6; ++i)
407 {
408 cp += this->point(i) * nvi.V[i];
409 vol += nvi.V[i];
410 }
411
412 return cp / vol;
413}
414
416{
417 // This specialization is good for Lagrange mappings only in general
418 if (this->mapping_type() != LAGRANGE_MAP)
419 return this->Elem::volume();
420
421 VolumeIntegral vi;
422 cell_integral(this, vi);
423 return vi.vol;
424}
425
431
432
433void
434Prism6::permute(unsigned int perm_num)
435{
436 libmesh_assert_less (perm_num, 6);
437 const unsigned int side = perm_num % 2;
438 const unsigned int rotate = perm_num / 2;
439
440 for (unsigned int i = 0; i != rotate; ++i)
441 {
442 swap3nodes(0,1,2);
443 swap3nodes(3,4,5);
444 swap3neighbors(1,2,3);
445 }
446
447 switch (side) {
448 case 0:
449 break;
450 case 1:
451 swap2nodes(1,3);
452 swap2nodes(0,4);
453 swap2nodes(2,5);
454 swap2neighbors(0,4);
455 swap2neighbors(2,3);
456 break;
457 default:
458 libmesh_error();
459 }
460
461}
462
463
464void
466{
467 libmesh_assert(boundary_info);
468
469 swap2nodes(0,1);
470 swap2nodes(3,4);
471 swap2neighbors(2,3);
472 swap2boundarysides(2,3,boundary_info);
473 swap2boundaryedges(0,1,boundary_info);
474 swap2boundaryedges(3,4,boundary_info);
475 swap2boundaryedges(7,8,boundary_info);
476}
477
478
480Prism6::side_type (const unsigned int s) const
481{
482 libmesh_assert_less (s, 5);
483 if (s == 0 || s == 4)
484 return TRI3;
485 return QUAD4;
486}
487
488Point
489Prism6::side_vertex_average_normal(const unsigned int s) const
490{
491 libmesh_assert_less (s, 5);
492 libmesh_assert_equal_to(this->mapping_type(), LAGRANGE_MAP);
493
494 switch (s)
495 {
496 case 0: // the triangular face at z=-1
497 case 4: // the triangular face at z=1
498 {
499 const Point n1 = this->point(side_nodes_map[s][1]) -
500 this->point(side_nodes_map[s][0]);
501 const Point n2 = this->point(side_nodes_map[s][2]) -
502 this->point(side_nodes_map[s][1]);
503 const Point pointing_out = n1.cross(n2);
504 return pointing_out.unit();
505 }
506 case 1: // the quad face at y=0
507 case 2: // the other quad face
508 case 3: // the quad face at x=0
509 {
510 // At the side vertex average, things simplify a bit
511 // We get the side "plane" normal at all vertices, then average them
512 Point normal;
513 Point current_edge = this->point(side_nodes_map[s][1]) -
514 this->point(side_nodes_map[s][0]);
515 for (auto i : make_range(4))
516 {
517 const Point next_edge = this->point(side_nodes_map[s][(i + 2) % 4]) -
518 this->point(side_nodes_map[s][(i + 1) % 4]);
519 const Point normal_at_vertex = current_edge.cross(next_edge);
520 normal += normal_at_vertex;
521 current_edge = next_edge;
522 }
523 normal /= 4;
524 return normal.unit();
525 }
526 default:
527 libmesh_error_msg("Invalid side s = " << s);
528 }
529}
530
531} // namespace libMesh
532
533namespace // anonymous
534{
535
536template <typename T>
537void cell_integral(const Elem * elem, T & t)
538{
539 // Conveient references to our points.
540 const Point
541 &x0 = elem->point(0), &x1 = elem->point(1), &x2 = elem->point(2),
542 &x3 = elem->point(3), &x4 = elem->point(4), &x5 = elem->point(5);
543
544 // constant and zeta terms only. These are copied directly from a
545 // Python script.
546 Point dx_dxi[2] =
547 {
548 -x0/2 + x1/2 - x3/2 + x4/2, // constant
549 x0/2 - x1/2 - x3/2 + x4/2, // zeta
550 };
551
552 // constant and zeta terms only. These are copied directly from a
553 // Python script.
554 Point dx_deta[2] =
555 {
556 -x0/2 + x2/2 - x3/2 + x5/2, // constant
557 x0/2 - x2/2 - x3/2 + x5/2, // zeta
558 };
559
560 // Constant, xi, and eta terms
561 Point dx_dzeta[3] =
562 {
563 -x0/2 + x3/2, // constant
564 x0/2 - x2/2 - x3/2 + x5/2, // eta
565 x0/2 - x1/2 - x3/2 + x4/2 // xi
566 };
567
568 // The quadrature rule for the Prism6 is a tensor product between a
569 // four-point TRI3 rule (in xi, eta) and a two-point EDGE2 rule (in
570 // zeta) which is capable of integrating cubics exactly.
571
572 // Number of points in the 2D quadrature rule.
573 const int N2D = 4;
574
575 static const Real w2D[N2D] =
576 {
577 1.5902069087198858469718450103758e-01_R,
578 9.0979309128011415302815498962418e-02_R,
579 1.5902069087198858469718450103758e-01_R,
580 9.0979309128011415302815498962418e-02_R
581 };
582
583 static const Real xi[N2D] =
584 {
585 1.5505102572168219018027159252941e-01_R,
586 6.4494897427831780981972840747059e-01_R,
587 1.5505102572168219018027159252941e-01_R,
588 6.4494897427831780981972840747059e-01_R
589 };
590
591 static const Real eta[N2D] =
592 {
593 1.7855872826361642311703513337422e-01_R,
594 7.5031110222608118177475598324603e-02_R,
595 6.6639024601470138670269327409637e-01_R,
596 2.8001991549907407200279599420481e-01_R
597 };
598
599 // Number of points in the 1D quadrature rule. The weights of the
600 // 1D quadrature rule are equal to 1.
601 const int N1D = 2;
602
603 // Points of the 1D quadrature rule
604 static const Real zeta[N1D] =
605 {
606 -std::sqrt(Real(3))/3,
607 std::sqrt(Real(3))/3.
608 };
609
610 for (int i=0; i<N2D; ++i)
611 {
612 // dx_dzeta depends only on the 2D quadrature rule points.
613 Point dx_dzeta_q = dx_dzeta[0] + eta[i]*dx_dzeta[1] + xi[i]*dx_dzeta[2];
614
615 for (int j=0; j<N1D; ++j)
616 {
617 // dx_dxi and dx_deta only depend on the 1D quadrature rule points.
618 Point
619 dx_dxi_q = dx_dxi[0] + zeta[j]*dx_dxi[1],
620 dx_deta_q = dx_deta[0] + zeta[j]*dx_deta[1];
621
622 // Compute t-specific contributions at current qp
623 t.accumulate_qp(xi[i], eta[i], zeta[j], w2D[i] * triple_product(dx_dxi_q, dx_deta_q, dx_dzeta_q));
624 }
625 }
626}
627
628}
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
Defines a Cartesian bounding box by the two corner extremum.
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual BoundingBox loose_bounding_box() const
Definition elem.C:3901
static constexpr Real affine_tol
Default tolerance to use in has_affine_map().
Definition elem.h:2191
const Point & point(const unsigned int i) const
Definition elem.h:2583
void swap2nodes(unsigned int n1, unsigned int n2)
Swaps two node_ptrs.
Definition elem.h:2222
void swap3neighbors(unsigned int n1, unsigned int n2, unsigned int n3)
Swaps three neighbor_ptrs, "rotating" them.
Definition elem.h:2263
Node ** _nodes
Pointers to the nodes we are connected to.
Definition elem.h:2375
void swap2neighbors(unsigned int n1, unsigned int n2)
Swaps two neighbor_ptrs.
Definition elem.h:2232
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:3982
ElemMappingType mapping_type() const
Definition elem.h:3258
void swap3nodes(unsigned int n1, unsigned int n2, unsigned int n3)
Swaps three node_ptrs, "rotating" them.
Definition elem.h:2254
virtual Real volume() const
Definition elem.C:3865
void swap2boundaryedges(unsigned short e1, unsigned short e2, BoundaryInfo *boundary_info) const
Swaps two edges in boundary_info, if it is non-null.
Definition elem.C:3998
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2605
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:41
virtual std::vector< unsigned int > nodes_on_side(const unsigned int s) const override
static constexpr unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
virtual Order default_order() const override
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i) override
Builds a EDGE2 or INFEDGE2 built coincident with face i.
virtual bool is_face(const unsigned int i) const override
virtual BoundingBox loose_bounding_box() const override
Builds a bounding box out of the nodal positions.
virtual Point true_centroid() const override
An Optimized numerical quadrature approach for computing the centroid of the Prism6.
virtual std::vector< unsigned int > nodes_on_edge(const unsigned int e) const override
virtual unsigned int n_sub_elem() const override
Definition cell_prism6.h:84
virtual bool is_edge(const unsigned int i) const override
virtual bool has_affine_map() const override
virtual void permute(unsigned int perm_num) override final
Permutes the element (by swapping node and neighbor pointers) according to the specified index.
static const unsigned int side_elems_map[num_sides][nodes_per_side]
This maps the child elements with the associated side of the parent element.
virtual void flip(BoundaryInfo *) override final
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
static const int nodes_per_edge
virtual Real volume() const override
Specialized function for computing the element volume.
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
static const int nodes_per_side
static const int num_nodes
Geometric constants for Prism6.
static const Real _embedding_matrix[num_children][num_nodes][num_nodes]
Matrix that computes new nodal locations/solution values from current nodes/solution.
ElemType side_type(const unsigned int s) const override final
virtual bool is_vertex(const unsigned int i) const override
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i) override
Builds a QUAD4 or TRI3 built coincident with face i.
virtual Point side_vertex_average_normal(const unsigned int s) const override final
static constexpr unsigned int edge_nodes_map[num_edges][nodes_per_edge]
This maps the node of the edge to element node numbers.
virtual unsigned int n_edges() const override final
Definition cell_prism.h:96
static const int num_children
Definition cell_prism.h:75
virtual unsigned int n_sides() const override final
Definition cell_prism.h:86
static const int num_sides
Geometric constants for all Prisms.
Definition cell_prism.h:73
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
Definition cell_prism.C:170
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
LIBMESH_DEVICE_INLINE TypeVector< T > unit() const
bool relative_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
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_DEVICE_INLINE T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
ElemType
Defines an enum for geometric element types.
libmesh_assert(ctx)
Real fe_lagrange_1D_linear_shape(const unsigned int i, const Real xi)
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176