cell_hex8.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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/side.h"
21 #include "libmesh/cell_hex8.h"
22 #include "libmesh/edge_edge2.h"
23 #include "libmesh/face_quad4.h"
25 #include "libmesh/enum_order.h"
26 
27 namespace libMesh
28 {
29 
30 
31 
32 
33 // ------------------------------------------------------------
34 // Hex8 class static member initializations
35 const int Hex8::num_nodes;
36 const int Hex8::num_sides;
37 const int Hex8::num_edges;
38 const int Hex8::num_children;
39 const int Hex8::nodes_per_side;
40 const int Hex8::nodes_per_edge;
41 
43  {
44  {0, 3, 2, 1}, // Side 0
45  {0, 1, 5, 4}, // Side 1
46  {1, 2, 6, 5}, // Side 2
47  {2, 3, 7, 6}, // Side 3
48  {3, 0, 4, 7}, // Side 4
49  {4, 5, 6, 7} // Side 5
50  };
51 
53  {
54  {0, 1}, // Edge 0
55  {1, 2}, // Edge 1
56  {2, 3}, // Edge 2
57  {0, 3}, // Edge 3
58  {0, 4}, // Edge 4
59  {1, 5}, // Edge 5
60  {2, 6}, // Edge 6
61  {3, 7}, // Edge 7
62  {4, 5}, // Edge 8
63  {5, 6}, // Edge 9
64  {6, 7}, // Edge 10
65  {4, 7} // Edge 11
66  };
67 
68 
69 // ------------------------------------------------------------
70 // Hex8 class member functions
71 
72 bool Hex8::is_vertex(const unsigned int) const
73 {
74  return true;
75 }
76 
77 bool Hex8::is_edge(const unsigned int) const
78 {
79  return false;
80 }
81 
82 bool Hex8::is_face(const unsigned int) const
83 {
84  return false;
85 }
86 
87 bool Hex8::is_node_on_side(const unsigned int n,
88  const unsigned int s) const
89 {
90  libmesh_assert_less (s, n_sides());
91  return std::find(std::begin(side_nodes_map[s]),
93  n) != std::end(side_nodes_map[s]);
94 }
95 
96 std::vector<unsigned>
97 Hex8::nodes_on_side(const unsigned int s) const
98 {
99  libmesh_assert_less(s, n_sides());
100  return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s])};
101 }
102 
103 bool Hex8::is_node_on_edge(const unsigned int n,
104  const unsigned int e) const
105 {
106  libmesh_assert_less (e, n_edges());
107  return std::find(std::begin(edge_nodes_map[e]),
109  n) != std::end(edge_nodes_map[e]);
110 }
111 
112 
113 
115 {
116  // Make sure x-edge endpoints are affine
117  Point v = this->point(1) - this->point(0);
118  if (!v.relative_fuzzy_equals(this->point(2) - this->point(3)) ||
119  !v.relative_fuzzy_equals(this->point(5) - this->point(4)) ||
120  !v.relative_fuzzy_equals(this->point(6) - this->point(7)))
121  return false;
122  // Make sure xz-faces are identical parallelograms
123  v = this->point(4) - this->point(0);
124  if (!v.relative_fuzzy_equals(this->point(7) - this->point(3)))
125  return false;
126  // If all the above checks out, the map is affine
127  return true;
128 }
129 
130 
131 
133 {
134  return FIRST;
135 }
136 
137 
138 
139 std::unique_ptr<Elem> Hex8::build_side_ptr (const unsigned int i,
140  bool proxy)
141 {
142  libmesh_assert_less (i, this->n_sides());
143 
144  if (proxy)
145  return libmesh_make_unique<Side<Quad4,Hex8>>(this,i);
146 
147  else
148  {
149  std::unique_ptr<Elem> face = libmesh_make_unique<Quad4>();
150  face->subdomain_id() = this->subdomain_id();
151 
152  for (unsigned n=0; n<face->n_nodes(); ++n)
153  face->set_node(n) = this->node_ptr(Hex8::side_nodes_map[i][n]);
154 
155  return face;
156  }
157 }
158 
159 
160 
161 void Hex8::build_side_ptr (std::unique_ptr<Elem> & side,
162  const unsigned int i)
163 {
164  this->simple_build_side_ptr<Hex8>(side, i, QUAD4);
165 }
166 
167 
168 
169 std::unique_ptr<Elem> Hex8::build_edge_ptr (const unsigned int i)
170 {
171  libmesh_assert_less (i, this->n_edges());
172 
173  return libmesh_make_unique<SideEdge<Edge2,Hex8>>(this,i);
174 }
175 
176 
177 
178 void Hex8::connectivity(const unsigned int libmesh_dbg_var(sc),
179  const IOPackage iop,
180  std::vector<dof_id_type> & conn) const
181 {
182  libmesh_assert(_nodes);
183  libmesh_assert_less (sc, this->n_sub_elem());
184  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
185 
186  conn.resize(8);
187 
188  switch (iop)
189  {
190  case TECPLOT:
191  {
192  conn[0] = this->node_id(0)+1;
193  conn[1] = this->node_id(1)+1;
194  conn[2] = this->node_id(2)+1;
195  conn[3] = this->node_id(3)+1;
196  conn[4] = this->node_id(4)+1;
197  conn[5] = this->node_id(5)+1;
198  conn[6] = this->node_id(6)+1;
199  conn[7] = this->node_id(7)+1;
200  return;
201  }
202 
203  case VTK:
204  {
205  conn[0] = this->node_id(0);
206  conn[1] = this->node_id(1);
207  conn[2] = this->node_id(2);
208  conn[3] = this->node_id(3);
209  conn[4] = this->node_id(4);
210  conn[5] = this->node_id(5);
211  conn[6] = this->node_id(6);
212  conn[7] = this->node_id(7);
213  return;
214  }
215 
216  default:
217  libmesh_error_msg("Unsupported IO package " << iop);
218  }
219 }
220 
221 
222 
223 #ifdef LIBMESH_ENABLE_AMR
224 
226  {
227  // The 8 children of the Hex-type elements can be thought of as being
228  // associated with the 8 vertices of the Hex. Some of the children are
229  // numbered the same as their corresponding vertex, while some are
230  // not. The children which are numbered differently have been marked
231  // with ** in the comments below.
232 
233  // embedding matrix for child 0 (child 0 is associated with vertex 0)
234  {
235  // 0 1 2 3 4 5 6 7
236  { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0
237  { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
238  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 2
239  { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0}, // 3
240  { 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0}, // 4
241  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 5
242  {.125, .125, .125, .125, .125, .125, .125, .125}, // 6
243  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25} // 7
244  },
245 
246  // embedding matrix for child 1 (child 1 is associated with vertex 1)
247  {
248  // 0 1 2 3 4 5 6 7
249  { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0
250  { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
251  { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2
252  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 3
253  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 4
254  { 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0}, // 5
255  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 6
256  {.125, .125, .125, .125, .125, .125, .125, .125} // 7
257  },
258 
259  // embedding matrix for child 2 (child 2 is associated with vertex 3**)
260  {
261  // 0 1 2 3 4 5 6 7
262  { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0
263  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 1
264  { 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 2
265  { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 3
266  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25}, // 4
267  {.125, .125, .125, .125, .125, .125, .125, .125}, // 5
268  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25}, // 6
269  { 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5} // 7
270  },
271 
272  // embedding matrix for child 3 (child 3 is associated with vertex 2**)
273  {
274  // 0 1 2 3 4 5 6 7
275  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 0
276  { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
277  { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2
278  { 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 3
279  {.125, .125, .125, .125, .125, .125, .125, .125}, // 4
280  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 5
281  { 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0}, // 6
282  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25} // 7
283  },
284 
285  // embedding matrix for child 4 (child 4 is associated with vertex 4)
286  {
287  // 0 1 2 3 4 5 6 7
288  { 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0}, // 0
289  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 1
290  {.125, .125, .125, .125, .125, .125, .125, .125}, // 2
291  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25}, // 3
292  { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 4
293  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0}, // 5
294  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25}, // 6
295  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5} // 7
296  },
297 
298  // embedding matrix for child 5 (child 5 is associated with vertex 5)
299  {
300  // 0 1 2 3 4 5 6 7
301  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 0
302  { 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0}, // 1
303  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 2
304  {.125, .125, .125, .125, .125, .125, .125, .125}, // 3
305  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0}, // 4
306  { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 5
307  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 6
308  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25} // 7
309  },
310 
311  // embedding matrix for child 6 (child 6 is associated with vertex 7**)
312  {
313  // 0 1 2 3 4 5 6 7
314  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25}, // 0
315  {.125, .125, .125, .125, .125, .125, .125, .125}, // 1
316  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25}, // 2
317  { 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}, // 3
318  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5}, // 4
319  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25}, // 5
320  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 6
321  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0} // 7
322  },
323 
324  // embedding matrix for child 7 (child 7 is associated with vertex 6**)
325  {
326  // 0 1 2 3 4 5 6 7
327  {.125, .125, .125, .125, .125, .125, .125, .125}, // 0
328  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 1
329  { 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0}, // 2
330  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25}, // 3
331  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25}, // 4
332  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 5
333  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 6
334  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5} // 7
335  }
336  };
337 
338 
339 
340 
341 #endif
342 
343 
344 
346 {
347  // Make copies of our points. It makes the subsequent calculations a bit
348  // shorter and avoids dereferencing the same pointer multiple times.
349  Point
350  x0 = point(0), x1 = point(1), x2 = point(2), x3 = point(3),
351  x4 = point(4), x5 = point(5), x6 = point(6), x7 = point(7);
352 
353  // Construct constant data vectors. The notation is:
354  // \vec{x}_{\xi} = \vec{a1}*eta*zeta + \vec{b1}*eta + \vec{c1}*zeta + \vec{d1}
355  // \vec{x}_{\eta} = \vec{a2}*xi*zeta + \vec{b2}*xi + \vec{c2}*zeta + \vec{d2}
356  // \vec{x}_{\zeta} = \vec{a3}*xi*eta + \vec{b3}*xi + \vec{c3}*eta + \vec{d3}
357  // but it turns out that a1, a2, and a3 are not needed for the volume calculation.
358 
359  // Build up the 6 unique vectors which make up dx/dxi, dx/deta, and dx/dzeta.
360  Point q[6] =
361  {
362  /*b1*/ x0 - x1 + x2 - x3 + x4 - x5 + x6 - x7, /*=b2*/
363  /*c1*/ x0 - x1 - x2 + x3 - x4 + x5 + x6 - x7, /*=b3*/
364  /*d1*/ -x0 + x1 + x2 - x3 - x4 + x5 + x6 - x7,
365  /*c2*/ x0 + x1 - x2 - x3 - x4 - x5 + x6 + x7, /*=c3*/
366  /*d2*/ -x0 - x1 + x2 + x3 - x4 - x5 + x6 + x7,
367  /*d3*/ -x0 - x1 - x2 - x3 + x4 + x5 + x6 + x7
368  };
369 
370  // We could check for a linear element, but it's probably faster to
371  // just compute the result...
372  return
373  (triple_product(q[0], q[4], q[3]) +
374  triple_product(q[2], q[0], q[1]) +
375  triple_product(q[1], q[3], q[5])) / 192. +
376  triple_product(q[2], q[4], q[5]) / 64.;
377 }
378 
381 {
382  return Elem::loose_bounding_box();
383 }
384 
385 } // namespace libMesh
static const int num_nodes
Definition: cell_hex8.h:154
virtual std::vector< unsigned int > nodes_on_side(const unsigned int s) const override
Definition: cell_hex8.C:97
static const int num_sides
Definition: cell_hex8.h:155
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i) override
Definition: cell_hex8.C:169
Node ** _nodes
Definition: elem.h:1695
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i, bool proxy) override
Definition: cell_hex8.C:139
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
Definition: cell_hex8.C:178
static const int num_edges
Definition: cell_hex8.h:156
unsigned short int side
Definition: xdr_io.C:50
virtual BoundingBox loose_bounding_box() const
Definition: elem.C:2857
virtual Real volume() const override
Definition: cell_hex8.C:345
IterBase * end
virtual unsigned int n_sub_elem() const override
Definition: cell_hex8.h:84
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
Definition: cell_hex8.h:165
virtual Order default_order() const override
Definition: cell_hex8.C:132
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
Definition: type_vector.h:1054
static const unsigned int edge_nodes_map[num_edges][nodes_per_edge]
Definition: cell_hex8.h:171
static const int nodes_per_edge
Definition: cell_hex8.h:159
static const float _embedding_matrix[num_children][num_nodes][num_nodes]
Definition: cell_hex8.h:207
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
Definition: cell_hex8.C:87
virtual bool has_affine_map() const override
Definition: cell_hex8.C:114
virtual unsigned int n_edges() const override final
Definition: cell_hex.h:83
virtual bool is_face(const unsigned int i) const override
Definition: cell_hex8.C:82
static const int nodes_per_side
Definition: cell_hex8.h:158
virtual bool is_edge(const unsigned int i) const override
Definition: cell_hex8.C:77
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
Definition: elem.h:2034
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
Definition: cell_hex8.C:103
virtual unsigned int n_sides() const override final
Definition: cell_hex.h:73
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:1957
virtual BoundingBox loose_bounding_box() const override
Definition: cell_hex8.C:380
virtual bool is_vertex(const unsigned int i) const override
Definition: cell_hex8.C:72
A geometric point in (x,y,z) space.
Definition: point.h:38
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1914
const Point & point(const unsigned int i) const
Definition: elem.h:1892
bool relative_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
Definition: type_vector.h:990
std::unique_ptr< Elem > side(const unsigned int i) const
Definition: elem.h:2202
static const int num_children
Definition: cell_hex8.h:157