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