libMesh
cell_tet.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 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_tet.h"
21 #include "libmesh/cell_tet4.h"
22 #include "libmesh/face_tri3.h"
23 #include "libmesh/enum_elem_quality.h"
24 
25 namespace libMesh
26 {
27 
28 
29 
30 // ------------------------------------------------------------
31 // Tet class static member initializations
32 
33 
34 const Real Tet::_master_points[14][3] =
35  {
36  {0, 0, 0},
37  {1, 0, 0},
38  {0, 1, 0},
39  {0, 0, 1},
40  {0.5, 0, 0},
41  {0.5, 0.5, 0},
42  {0, 0.5, 0},
43  {0, 0, 0.5},
44  {0.5, 0, 0.5},
45  {0, 0.5, 0.5},
46  {1/Real(3), 1/Real(3), 0},
47  {1/Real(3), 0, 1/Real(3)},
48  {1/Real(3), 1/Real(3), 1/Real(3)},
49  {0, 1/Real(3), 1/Real(3)}
50  };
51 
52 const unsigned int Tet::edge_sides_map[6][2] =
53  {
54  {0, 1}, // Edge 0
55  {0, 2}, // Edge 1
56  {0, 3}, // Edge 2
57  {1, 3}, // Edge 3
58  {1, 2}, // Edge 4
59  {2, 3} // Edge 5
60  };
61 
62 // ------------------------------------------------------------
63 // Tet class member functions
64 dof_id_type Tet::key (const unsigned int s) const
65 {
66  libmesh_assert_less (s, this->n_sides());
67 
68  return this->compute_key(this->node_id(Tet4::side_nodes_map[s][0]),
69  this->node_id(Tet4::side_nodes_map[s][1]),
70  this->node_id(Tet4::side_nodes_map[s][2]));
71 }
72 
73 
74 
75 dof_id_type Tet::low_order_key (const unsigned int s) const
76 {
77  libmesh_assert_less (s, this->n_sides());
78 
79  return this->compute_key(this->node_id(Tet4::side_nodes_map[s][0]),
80  this->node_id(Tet4::side_nodes_map[s][1]),
81  this->node_id(Tet4::side_nodes_map[s][2]));
82 }
83 
84 
85 
86 unsigned int Tet::local_side_node(unsigned int side,
87  unsigned int side_node) const
88 {
89  libmesh_assert_less (side, this->n_sides());
90  libmesh_assert_less (side_node, Tet4::nodes_per_side);
91 
92  return Tet4::side_nodes_map[side][side_node];
93 }
94 
95 
96 
97 unsigned int Tet::local_edge_node(unsigned int edge,
98  unsigned int edge_node) const
99 {
100  libmesh_assert_less (edge, this->n_edges());
101  libmesh_assert_less (edge_node, Tet4::nodes_per_edge);
102 
103  return Tet4::edge_nodes_map[edge][edge_node];
104 }
105 
106 
107 std::unique_ptr<Elem> Tet::side_ptr (const unsigned int i)
108 {
109  libmesh_assert_less (i, this->n_sides());
110 
111  std::unique_ptr<Elem> face = std::make_unique<Tri3>();
112 
113  for (auto n : face->node_index_range())
114  face->set_node(n) = this->node_ptr(Tet4::side_nodes_map[i][n]);
115 
116  return face;
117 }
118 
119 
120 
121 void Tet::side_ptr (std::unique_ptr<Elem> & side,
122  const unsigned int i)
123 {
124  this->simple_side_ptr<Tet,Tet4>(side, i, TRI3);
125 }
126 
127 
128 
129 void Tet::select_diagonal (const Diagonal diag) const
130 {
131  libmesh_assert_equal_to (_diagonal_selection, INVALID_DIAG);
132  _diagonal_selection = diag;
133 }
134 
135 
136 
137 
138 
139 #ifdef LIBMESH_ENABLE_AMR
140 
141 
142 bool Tet::is_child_on_side_helper(const unsigned int c,
143  const unsigned int s,
144  const unsigned int checked_nodes[][3]) const
145 {
146  libmesh_assert_less (c, this->n_children());
147  libmesh_assert_less (s, this->n_sides());
148 
149  // For the 4 vertices, child c touches vertex c, so we can return
150  // true if that vertex is on side s
151  for (unsigned int i = 0; i != 3; ++i)
152  if (Tet4::side_nodes_map[s][i] == c)
153  return true;
154 
155  // If we are a "vertex child" and we didn't already return true,
156  // we must not be on the side in question
157  if (c < 4)
158  return false;
159 
160  // For the 4 non-vertex children, the child ordering depends on the
161  // diagonal selection. We'll let the embedding matrix figure that
162  // out: if this child has three nodes that don't depend on the
163  // position of the node_facing_side[s], then we're on side s. Which
164  // three nodes those are depends on the subclass, so their responsibility
165  // is to call this function with the proper check_nodes array
166  const unsigned int node_facing_side[4] = {3, 2, 0, 1};
167  const unsigned int n = node_facing_side[s];
168 
169  // Add up the absolute values of the entries of the embedding matrix for the
170  // nodes opposite node n. If it is equal to zero, then the child in question is
171  // on side s, so return true.
172  Real embedding_sum = 0.;
173  for (unsigned i=0; i<3; ++i)
174  embedding_sum += std::abs(this->embedding_matrix(c, checked_nodes[n][i], n));
175 
176  return ( std::abs(embedding_sum) < 1.e-3 );
177 }
178 
179 #else
180 
181 bool Tet::is_child_on_side_helper(const unsigned int /*c*/,
182  const unsigned int /*s*/,
183  const unsigned int /*checked_nodes*/[][3]) const
184 {
185  libmesh_not_implemented();
186  return false;
187 }
188 
189 #endif //LIBMESH_ENABLE_AMR
190 
191 
192 
193 
195 {
196  // Check for uninitialized diagonal selection
198  {
199  Real diag_01_23 = (this->point(0) + this->point(1) - this->point(2) - this->point(3)).norm_sq();
200  Real diag_02_13 = (this->point(0) - this->point(1) + this->point(2) - this->point(3)).norm_sq();
201  Real diag_03_12 = (this->point(0) - this->point(1) - this->point(2) + this->point(3)).norm_sq();
202 
204 
205  if (diag_01_23 < diag_02_13 || diag_03_12 < diag_02_13)
206  {
207  if (diag_01_23 < diag_03_12)
209 
210  else
212  }
213  }
214 }
215 
216 
217 
218 bool Tet::is_edge_on_side(const unsigned int e,
219  const unsigned int s) const
220 {
221  libmesh_assert_less (e, this->n_edges());
222  libmesh_assert_less (s, this->n_sides());
223 
224  return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
225 }
226 
227 
228 
229 std::vector<unsigned int> Tet::sides_on_edge(const unsigned int e) const
230 {
231  libmesh_assert_less (e, this->n_edges());
232  return {edge_sides_map[e][0], edge_sides_map[e][1]};
233 }
234 
235 
236 
237 bool
239 {
240  return (triple_product(this->point(1)-this->point(0),
241  this->point(2)-this->point(0),
242  this->point(3)-this->point(0)) < 0);
243 }
244 
245 
246 
248 {
249  return Elem::quality(q); // Not implemented
250 }
251 
252 
253 
254 
255 std::pair<Real, Real> Tet::qual_bounds (const ElemQuality q) const
256 {
257  std::pair<Real, Real> bounds;
258 
259  switch (q)
260  {
261 
262  case ASPECT_RATIO_BETA:
263  case ASPECT_RATIO_GAMMA:
264  bounds.first = 1.;
265  bounds.second = 3.;
266  break;
267 
268  case SIZE:
269  case SHAPE:
270  bounds.first = 0.2;
271  bounds.second = 1.;
272  break;
273 
274  case CONDITION:
275  bounds.first = 1.;
276  bounds.second = 3.;
277  break;
278 
279  case DISTORTION:
280  bounds.first = 0.6;
281  bounds.second = 1.;
282  break;
283 
284  case JACOBIAN:
285  bounds.first = 0.5;
286  bounds.second = 1.414;
287  break;
288 
289  default:
290  libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
291  bounds.first = -1;
292  bounds.second = -1;
293  }
294 
295  return bounds;
296 }
297 
298 } // namespace libMesh
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override final
Definition: cell_tet.C:218
virtual Real quality(const ElemQuality q) const override
Definition: cell_tet.C:247
static const unsigned int edge_sides_map[6][2]
This maps each edge to the sides that contain said edge.
Definition: cell_tet.h:211
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
Definition: cell_tet.C:86
virtual dof_id_type key() const
Definition: elem.C:563
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:196
virtual unsigned int n_sides() const override final
Definition: cell_tet.h:74
Diagonal
This enumeration keeps track of which diagonal is selected during refinement.
Definition: cell_tet.h:162
virtual unsigned int n_children() const override final
Definition: cell_tet.h:94
Diagonal _diagonal_selection
The currently-selected diagonal used during refinement.
Definition: cell_tet.h:237
The libMesh namespace provides an interface to certain functionality in the library.
virtual std::pair< Real, Real > qual_bounds(const ElemQuality q) const override
Definition: cell_tet.C:255
virtual bool is_flipped() const override final
Definition: cell_tet.C:238
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const override
Definition: cell_tet.C:97
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:57
static const Real _master_points[14][3]
Master element node locations.
Definition: cell_tet.h:223
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
Definition: type_vector.h:1068
static const int nodes_per_side
Definition: cell_tet4.h:189
virtual dof_id_type low_order_key(const unsigned int s) const override
Definition: cell_tet.C:75
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
Definition: cell_tet.C:107
virtual unsigned int n_edges() const override final
Definition: cell_tet.h:84
ElemQuality
Defines an enum for element quality metrics.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:2331
auto norm_sq(const T &a) -> decltype(std::norm(a))
Definition: tensor_tools.h:104
OStreamProxy out
virtual Real quality(const ElemQuality q) const
Definition: elem.C:1582
void select_diagonal(const Diagonal diag) const
Allows the user to select the diagonal for the refinement.
Definition: cell_tet.C:129
virtual std::vector< unsigned int > sides_on_edge(const unsigned int e) const override final
Definition: cell_tet.C:229
void choose_diagonal() const
Derived classes use this function to select an initial diagonal during refinement.
Definition: cell_tet.C:194
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:202
static dof_id_type compute_key(dof_id_type n0)
Definition: elem.h:3131
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:142
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2299
const Point & point(const unsigned int i) const
Definition: elem.h:2277
static const int nodes_per_edge
Definition: cell_tet4.h:190
uint8_t dof_id_type
Definition: id_types.h:67