libMesh
Loading...
Searching...
No Matches
cell_tet4.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_tet4.h"
21#include "libmesh/edge_edge2.h"
22#include "libmesh/face_tri3.h"
23#include "libmesh/tensor_value.h"
24#include "libmesh/enum_io_package.h"
25#include "libmesh/enum_order.h"
26
27namespace libMesh
28{
29
30
31
32// ------------------------------------------------------------
33// Tet4 class static member initializations
34const int Tet4::num_nodes;
35const int Tet4::nodes_per_side;
36const int Tet4::nodes_per_edge;
37
39 {
40 {0, 2, 1}, // Side 0
41 {0, 1, 3}, // Side 1
42 {1, 2, 3}, // Side 2
43 {2, 0, 3} // Side 3
44 };
45
47 {
48 {0, 1}, // Edge 0
49 {1, 2}, // Edge 1
50 {0, 2}, // Edge 2
51 {0, 3}, // Edge 3
52 {1, 3}, // Edge 4
53 {2, 3} // Edge 5
54 };
55
56// ------------------------------------------------------------
57// Tet4 class member functions
58
59bool Tet4::is_vertex(const unsigned int libmesh_dbg_var(n)) const
60{
61 libmesh_assert_not_equal_to (n, invalid_uint);
62 return true;
63}
64
65bool Tet4::is_edge(const unsigned int) const
66{
67 return false;
68}
69
70bool Tet4::is_face(const unsigned int) const
71{
72 return false;
73}
74
75bool Tet4::is_node_on_edge(const unsigned int n,
76 const unsigned int e) const
77{
78 libmesh_assert_less (e, n_edges());
79 return std::find(std::begin(edge_nodes_map[e]),
80 std::end(edge_nodes_map[e]),
81 n) != std::end(edge_nodes_map[e]);
82}
83
84
85
86
87#ifdef LIBMESH_ENABLE_AMR
88
89// This function only works if LIBMESH_ENABLE_AMR...
90bool Tet4::is_child_on_side(const unsigned int c,
91 const unsigned int s) const
92{
93 // OK, for the Tet4, this is pretty obvious... it is sets of nodes
94 // not equal to the current node. But if we want this algorithm to
95 // be generic and work for Tet10 also it helps to do it this way.
96 const unsigned int nodes_opposite[4][3] =
97 {
98 {1,2,3}, // nodes opposite node 0
99 {0,2,3}, // nodes opposite node 1
100 {0,1,3}, // nodes opposite node 2
101 {0,1,2} // nodes opposite node 3
102 };
103
104 // Call the base class helper function
105 return Tet::is_child_on_side_helper(c, s, nodes_opposite);
106}
107
108#else
109
110bool Tet4::is_child_on_side(const unsigned int /*c*/,
111 const unsigned int /*s*/) const
112{
113 libmesh_not_implemented();
114 return false;
115}
116
117#endif //LIBMESH_ENABLE_AMR
118
119
120
122{
123 return this->volume() > tol;
124}
125
126
127
128bool Tet4::is_node_on_side(const unsigned int n,
129 const unsigned int s) const
130{
131 libmesh_assert_less (s, n_sides());
132 return std::find(std::begin(side_nodes_map[s]),
133 std::end(side_nodes_map[s]),
134 n) != std::end(side_nodes_map[s]);
135}
136
137std::vector<unsigned>
138Tet4::nodes_on_side(const unsigned int s) const
139{
140 libmesh_assert_less(s, n_sides());
141 return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s])};
142}
143
144std::vector<unsigned>
145Tet4::nodes_on_edge(const unsigned int e) const
146{
147 libmesh_assert_less(e, n_edges());
148 return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
149}
150
152{
153 return FIRST;
154}
155
156std::unique_ptr<Elem> Tet4::build_side_ptr (const unsigned int i)
157{
158 return this->simple_build_side_ptr<Tri3, Tet4>(i);
159}
160
161
162
163void Tet4::build_side_ptr (std::unique_ptr<Elem> & side,
164 const unsigned int i)
165{
166 this->simple_build_side_ptr<Tet4>(side, i, TRI3);
167}
168
169
170
171std::unique_ptr<Elem> Tet4::build_edge_ptr (const unsigned int i)
172{
173 return this->simple_build_edge_ptr<Edge2,Tet4>(i);
174}
175
176
177
178void Tet4::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
179{
180 this->simple_build_edge_ptr<Tet4>(edge, i, EDGE2);
181}
182
183
184
185void Tet4::connectivity(const unsigned int libmesh_dbg_var(sc),
186 const IOPackage iop,
187 std::vector<dof_id_type> & conn) const
188{
190 libmesh_assert_less (sc, this->n_sub_elem());
191 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
192
193
194 switch (iop)
195 {
196 case TECPLOT:
197 {
198 conn.resize(8);
199 conn[0] = this->node_id(0)+1;
200 conn[1] = this->node_id(1)+1;
201 conn[2] = this->node_id(2)+1;
202 conn[3] = this->node_id(2)+1;
203 conn[4] = this->node_id(3)+1;
204 conn[5] = this->node_id(3)+1;
205 conn[6] = this->node_id(3)+1;
206 conn[7] = this->node_id(3)+1;
207 return;
208 }
209
210 case VTK:
211 {
212 conn.resize(4);
213 conn[0] = this->node_id(0);
214 conn[1] = this->node_id(1);
215 conn[2] = this->node_id(2);
216 conn[3] = this->node_id(3);
217 return;
218 }
219
220 default:
221 libmesh_error_msg("Unsupported IO package " << iop);
222 }
223}
224
225
226
227#ifdef LIBMESH_ENABLE_AMR
228
230 {
231 // embedding matrix for child 0
232 {
233 // 0 1 2 3
234 {1.0, 0.0, 0.0, 0.0}, // 0
235 {0.5, 0.5, 0.0, 0.0}, // 1
236 {0.5, 0.0, 0.5, 0.0}, // 2
237 {0.5, 0.0, 0.0, 0.5} // 3
238 },
239
240 // embedding matrix for child 1
241 {
242 // 0 1 2 3
243 {0.5, 0.5, 0.0, 0.0}, // 0
244 {0.0, 1.0, 0.0, 0.0}, // 1
245 {0.0, 0.5, 0.5, 0.0}, // 2
246 {0.0, 0.5, 0.0, 0.5} // 3
247 },
248
249 // embedding matrix for child 2
250 {
251 // 0 1 2 3
252 {0.5, 0.0, 0.5, 0.0}, // 0
253 {0.0, 0.5, 0.5, 0.0}, // 1
254 {0.0, 0.0, 1.0, 0.0}, // 2
255 {0.0, 0.0, 0.5, 0.5} // 3
256 },
257
258 // embedding matrix for child 3
259 {
260 // 0 1 2 3
261 {0.5, 0.0, 0.0, 0.5}, // 0
262 {0.0, 0.5, 0.0, 0.5}, // 1
263 {0.0, 0.0, 0.5, 0.5}, // 2
264 {0.0, 0.0, 0.0, 1.0} // 3
265 },
266
267 // embedding matrix for child 4
268 {
269 // 0 1 2 3
270 {0.5, 0.5, 0.0, 0.0}, // 0
271 {0.0, 0.5, 0.0, 0.5}, // 1
272 {0.5, 0.0, 0.5, 0.0}, // 2
273 {0.5, 0.0, 0.0, 0.5} // 3
274 },
275
276 // embedding matrix for child 5
277 {
278 // 0 1 2 3
279 {0.5, 0.5, 0.0, 0.0}, // 0
280 {0.0, 0.5, 0.5, 0.0}, // 1
281 {0.5, 0.0, 0.5, 0.0}, // 2
282 {0.0, 0.5, 0.0, 0.5} // 3
283 },
284
285 // embedding matrix for child 6
286 {
287 // 0 1 2 3
288 {0.5, 0.0, 0.5, 0.0}, // 0
289 {0.0, 0.5, 0.5, 0.0}, // 1
290 {0.0, 0.0, 0.5, 0.5}, // 2
291 {0.0, 0.5, 0.0, 0.5} // 3
292 },
293
294 // embedding matrix for child 7
295 {
296 // 0 1 2 3
297 {0.5, 0.0, 0.5, 0.0}, // 0
298 {0.0, 0.5, 0.0, 0.5}, // 1
299 {0.0, 0.0, 0.5, 0.5}, // 2
300 {0.5, 0.0, 0.0, 0.5} // 3
301 }
302 };
303
304#endif // #ifdef LIBMESH_ENABLE_AMR
305
306
307
308
309
311{
312 return Elem::vertex_average();
313}
314
315
316
318{
319 // This specialization is good for non-Lagrange mappings too! Even
320 // with differing vertex weights we've still got p=1 planar faces.
321
322 // The volume of a tetrahedron is 1/6 the box product formed
323 // by its base and apex vectors
324 Point a = point(3) - point(0);
325
326 // b is the vector pointing from 0 to 1
327 Point b = point(1) - point(0);
328
329 // c is the vector pointing from 0 to 2
330 Point c = point(2) - point(0);
331
332 return triple_product(a, b, c) / 6.;
333}
334
335
336
337
338std::pair<Real, Real> Tet4::min_and_max_angle() const
339{
340 Point n[4];
341
342 // Compute the outward normal vectors on each face
343 n[0] = (this->point(2) - this->point(0)).cross(this->point(1) - this->point(0));
344 n[1] = (this->point(1) - this->point(0)).cross(this->point(3) - this->point(0));
345 n[2] = (this->point(2) - this->point(1)).cross(this->point(3) - this->point(1));
346 n[3] = (this->point(0) - this->point(2)).cross(this->point(3) - this->point(2));
347
348 Real dihedral_angles[6]; // 01, 02, 03, 12, 13, 23
349
350 // Compute dihedral angles
351 for (unsigned int k=0,i=0; i<4; ++i)
352 for (unsigned int j=i+1; j<4; ++j,k+=1)
353 dihedral_angles[k] = std::acos(n[i]*n[j] / n[i].norm() / n[j].norm()); // return value is between 0 and PI
354
355 // Return max/min dihedral angles
356 return std::make_pair(*std::min_element(dihedral_angles, dihedral_angles+6),
357 *std::max_element(dihedral_angles, dihedral_angles+6));
358
359}
360
361
362
364{
365 return this->compute_key(this->node_id(0),
366 this->node_id(1),
367 this->node_id(2),
368 this->node_id(3));
369}
370
371
372
373bool Tet4::contains_point (const Point & p, Real tol) const
374{
375 // See the response by Tony Noe on this thread.
376 // http://bbs.dartmouth.edu/~fangq/MATH/download/source/Point_in_Tetrahedron.htm
377 Point
378 col1 = point(1) - point(0),
379 col2 = point(2) - point(0),
380 col3 = point(3) - point(0);
381
382 Point r;
383
384 libmesh_try
385 {
386 RealTensorValue(col1(0), col2(0), col3(0),
387 col1(1), col2(1), col3(1),
388 col1(2), col2(2), col3(2)).solve(p - point(0), r);
389 }
390 libmesh_catch (ConvergenceFailure &)
391 {
392 // The Jacobian was singular, therefore the Tet had
393 // zero volume. In this degenerate case, it is not
394 // possible for the Tet to contain any points.
395 return false;
396 }
397
398 // The point p is inside the tetrahedron if r1 + r2 + r3 < 1 and
399 // 0 <= ri <= 1 for i = 1,2,3.
400 return
401 r(0) > -tol &&
402 r(1) > -tol &&
403 r(2) > -tol &&
404 r(0) + r(1) + r(2) < 1.0 + tol;
405}
406
407
408
409#ifdef LIBMESH_ENABLE_AMR
410Real Tet4::embedding_matrix (const unsigned int i,
411 const unsigned int j,
412 const unsigned int k) const
413{
414 // Choose an optimal diagonal, if one has not already been selected
415 this->choose_diagonal();
416
417 // Permuted j and k indices
418 unsigned int
419 jp=j,
420 kp=k;
421
422 if ((i>3) && (this->_diagonal_selection!=DIAG_02_13))
423 {
424 // Just the enum value cast to an unsigned int...
425 const unsigned ds = static_cast<unsigned int>(this->_diagonal_selection);
426
427 // Permute j, k:
428 // ds==1 ds==2
429 // 0 -> 1 0 -> 2
430 // 1 -> 2 1 -> 0
431 // 2 -> 0 2 -> 1
432 if (jp != 3)
433 jp = (jp+ds)%3;
434
435 if (kp != 3)
436 kp = (kp+ds)%3;
437 }
438
439 // Debugging
440 // libMesh::err << "Selected diagonal " << _diagonal_selection << std::endl;
441 // libMesh::err << "j=" << j << std::endl;
442 // libMesh::err << "k=" << k << std::endl;
443 // libMesh::err << "jp=" << jp << std::endl;
444 // libMesh::err << "kp=" << kp << std::endl;
445
446 // Call embedding matrix with permuted indices
447 return this->_embedding_matrix[i][jp][kp];
448}
449
450
451
452// void Tet4::reselect_diagonal (const Diagonal diag)
453// {
454// /* Make sure that the element has just been refined. */
455// libmesh_assert(_children);
456// libmesh_assert_equal_to (n_children(), 8);
457// libmesh_assert_equal_to (_children[0]->refinement_flag(), JUST_REFINED);
458// libmesh_assert_equal_to (_children[1]->refinement_flag(), JUST_REFINED);
459// libmesh_assert_equal_to (_children[2]->refinement_flag(), JUST_REFINED);
460// libmesh_assert_equal_to (_children[3]->refinement_flag(), JUST_REFINED);
461// libmesh_assert_equal_to (_children[4]->refinement_flag(), JUST_REFINED);
462// libmesh_assert_equal_to (_children[5]->refinement_flag(), JUST_REFINED);
463// libmesh_assert_equal_to (_children[6]->refinement_flag(), JUST_REFINED);
464// libmesh_assert_equal_to (_children[7]->refinement_flag(), JUST_REFINED);
465//
466// /* Check whether anything has to be changed. */
467// if (_diagonal_selection!=diag)
468// {
469// /* Set new diagonal selection. */
470// _diagonal_selection = diag;
471//
472// /* The first four children do not have to be changed. For the
473// others, only the nodes have to be changed. Note that we have
474// to keep track of the nodes ourselves since there is no \p
475// MeshRefinement object with a valid \p _new_nodes_map
476// available. */
477// for (unsigned int c=4; c<this->n_children(); c++)
478// {
479// Elem * child = this->child_ptr(c);
480// for (unsigned int nc=0; nc<child->n_nodes(); nc++)
481// {
482// /* Unassign the current node. */
483// child->set_node(nc, nullptr);
484//
485// /* We have to find the correct new node now. We know
486// that it exists somewhere. We make use of the fact
487// that the embedding matrix for these children consists
488// of entries 0.0 and 0.5 only. Also, we make use of
489// the properties of the embedding matrix for the first
490// (unchanged) four children, which allow us to use a
491// simple mechanism to find the required node. */
492//
493//
494// unsigned int first_05_in_embedding_matrix = libMesh::invalid_uint;
495// for (unsigned int n=0; n<this->n_nodes(); n++)
496// {
497// if (this->embedding_matrix(c,nc,n) != 0.0)
498// {
499// /* It must be 0.5 then. Check whether it's the
500// first or second time that we get a 0.5
501// value. */
502// if (first_05_in_embedding_matrix==libMesh::invalid_uint)
503// {
504// /* First time, so just remember this position. */
505// first_05_in_embedding_matrix = n;
506// }
507// else
508// {
509// /* Second time, so we know now which node to
510// use. */
511// child->set_node(nc, this->child_ptr(n)->node_ptr(first_05_in_embedding_matrix));
512// }
513//
514// }
515// }
516//
517// /* Make sure that a node has been found. */
518// libmesh_assert(child->node_ptr(nc));
519// }
520// }
521// }
522// }
523
524
525
526// void Tet4::reselect_optimal_diagonal (const Diagonal exclude_this)
527// {
528// Real diag_01_23 = (this->point(0)+this->point(1)-this->point(2)-this->point(3)).norm_sq();
529// Real diag_02_13 = (this->point(0)-this->point(1)+this->point(2)-this->point(3)).norm_sq();
530// Real diag_03_12 = (this->point(0)-this->point(1)-this->point(2)+this->point(3)).norm_sq();
531//
532// Diagonal use_this = INVALID_DIAG;
533// switch (exclude_this)
534// {
535// case DIAG_01_23:
536// use_this = DIAG_02_13;
537// if (diag_03_12 < diag_02_13)
538// {
539// use_this = DIAG_03_12;
540// }
541// break;
542//
543// case DIAG_02_13:
544// use_this = DIAG_03_12;
545// if (diag_01_23 < diag_03_12)
546// {
547// use_this = DIAG_01_23;
548// }
549// break;
550//
551// case DIAG_03_12:
552// use_this = DIAG_02_13;
553// if (diag_01_23 < diag_02_13)
554// {
555// use_this = DIAG_01_23;
556// }
557// break;
558//
559// default:
560// use_this = DIAG_02_13;
561// if (diag_01_23 < diag_02_13 || diag_03_12 < diag_02_13)
562// {
563// if (diag_01_23 < diag_03_12)
564// {
565// use_this = DIAG_01_23;
566// }
567// else
568// {
569// use_this = DIAG_03_12;
570// }
571// }
572// break;
573// }
574//
575// reselect_diagonal (use_this);
576// }
577#endif // #ifdef LIBMESH_ENABLE_AMR
578
579void Tet4::permute(unsigned int perm_num)
580{
581 libmesh_assert_less (perm_num, 12);
582
583 const unsigned int side = perm_num % 4;
584 const unsigned int rotate = perm_num / 4;
585
586 for (unsigned int i = 0; i != rotate; ++i)
587 {
588 swap3nodes(0,1,2);
589 swap3neighbors(1,2,3);
590 }
591
592 switch (side) {
593 case 0:
594 break;
595 case 1:
596 swap3nodes(0,2,3);
597 swap3neighbors(0,2,1);
598 break;
599 case 2:
600 swap3nodes(2,0,3);
601 swap3neighbors(0,1,2);
602 break;
603 case 3:
604 swap3nodes(2,1,3);
605 swap3neighbors(0,1,3);
606 break;
607 default:
608 libmesh_error();
609 }
610}
611
612
613void Tet4::flip(BoundaryInfo * boundary_info)
614{
615 libmesh_assert(boundary_info);
616
617 swap2nodes(0,2);
618 swap2neighbors(1,2);
619 swap2boundarysides(1,2,boundary_info);
620 swap2boundaryedges(0,1,boundary_info);
621 swap2boundaryedges(3,5,boundary_info);
622}
623
624
625ElemType Tet4::side_type (const unsigned int libmesh_dbg_var(s)) const
626{
627 libmesh_assert_less (s, 4);
628 return TRI3;
629}
630
631
632Point
633Tet4::side_vertex_average_normal(const unsigned int s) const
634{
635 libmesh_assert_less (s, 4);
636 const Point n1 = this->point(side_nodes_map[s][1]) -
637 this->point(side_nodes_map[s][0]);
638 const Point n2 = this->point(side_nodes_map[s][2]) -
639 this->point(side_nodes_map[s][1]);
640 const Point pointing_out = n1.cross(n2);
641 return pointing_out.unit();
642}
643
644
645} // namespace libMesh
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
A class representing a solver's failure to converge, to be thrown by "libmesh_convergence_failure();"...
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 swap3neighbors(unsigned int n1, unsigned int n2, unsigned int n3)
Swaps three neighbor_ptrs, "rotating" them.
Definition elem.h:2142
Node ** _nodes
Pointers to the nodes we are connected to.
Definition elem.h:2254
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
static dof_id_type compute_key(dof_id_type n0)
Definition elem.h:3311
void swap3nodes(unsigned int n1, unsigned int n2, unsigned int n3)
Swaps three node_ptrs, "rotating" them.
Definition elem.h:2133
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:3595
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2484
Point vertex_average() const
Definition elem.C:669
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i) override
Builds a TRI3 built coincident with face i.
Definition cell_tet4.C:156
static const int nodes_per_side
Definition cell_tet4.h:188
virtual Order default_order() const override
Definition cell_tet4.C:151
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
Definition cell_tet4.h:195
virtual bool is_vertex(const unsigned int i) const override
Definition cell_tet4.C:59
virtual dof_id_type key() const override
Definition cell_tet4.C:363
virtual bool is_face(const unsigned int i) const override
Definition cell_tet4.C:70
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i) override
Builds a EDGE2 built coincident with face i.
Definition cell_tet4.C:171
virtual void permute(unsigned int perm_num) override final
Permutes the element (by swapping node and neighbor pointers) according to the specified index.
Definition cell_tet4.C:579
virtual Point side_vertex_average_normal(const unsigned int s) const override final
Definition cell_tet4.C:633
virtual bool has_invertible_map(Real tol) const override
Definition cell_tet4.C:121
static const int num_nodes
Geometric constants for Tet4.
Definition cell_tet4.h:187
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override
Definition cell_tet4.C:90
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
Definition cell_tet4.C:75
virtual std::vector< unsigned int > nodes_on_edge(const unsigned int e) const override
Definition cell_tet4.C:145
virtual Point true_centroid() const override
The centroid of a 4-node tetrahedron is simply given by the average of its vertex positions.
Definition cell_tet4.C:310
static const Real _embedding_matrix[num_children][num_nodes][num_nodes]
Matrix that computes new nodal locations/solution values from current nodes/solution.
Definition cell_tet4.h:274
virtual Real embedding_matrix(const unsigned int i, const unsigned int j, const unsigned int k) const override
Matrix used to create the elements children.
Definition cell_tet4.C:410
virtual unsigned int n_sub_elem() const override
Definition cell_tet4.h:90
virtual std::vector< unsigned int > nodes_on_side(const unsigned int s) const override
Definition cell_tet4.C:138
ElemType side_type(const unsigned int s) const override final
Definition cell_tet4.C:625
virtual Real volume() const override
An optimized method for computing the area of a 4-node tetrahedron.
Definition cell_tet4.C:317
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
Definition cell_tet4.C:185
virtual void flip(BoundaryInfo *) override final
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
Definition cell_tet4.C:613
virtual bool contains_point(const Point &p, Real tol) const override
Uses simple geometric tests to determine if the point p is inside the tetrahedron.
Definition cell_tet4.C:373
static const int nodes_per_edge
Definition cell_tet4.h:189
std::pair< Real, Real > min_and_max_angle() const
Definition cell_tet4.C:338
virtual bool is_edge(const unsigned int i) const override
Definition cell_tet4.C:65
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
Definition cell_tet4.C:128
static const unsigned int edge_nodes_map[num_edges][nodes_per_edge]
This maps the node of the edge to element node numbers.
Definition cell_tet4.h:201
static const int num_edges
Definition cell_tet.h:75
virtual unsigned int n_edges() const override final
Definition cell_tet.h:91
void choose_diagonal() const
Derived classes use this function to select an initial diagonal during refinement.
Definition cell_tet.C:204
static const int num_sides
Geometric constants for all Tets.
Definition cell_tet.h:74
bool is_child_on_side_helper(const unsigned int c, const unsigned int s, const unsigned int checked_nodes[][3]) const
Called by descendant classes with appropriate data to determine if child c is on side s.
Definition cell_tet.C:152
virtual unsigned int n_sides() const override final
Definition cell_tet.h:81
Diagonal _diagonal_selection
The currently-selected diagonal used during refinement.
Definition cell_tet.h:249
static const int num_children
Definition cell_tet.h:76
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
auto norm() const
TypeVector< T > unit() 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,...
ElemType
Defines an enum for geometric element types.
TensorValue< Real > RealTensorValue
Useful typedefs to allow transparent switching between Real and Complex data types.
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
libmesh_assert(ctx)
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
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real