cell_hex8.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2014 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}, // Side 0
48  {1, 2}, // Side 1
49  {2, 3}, // Side 2
50  {0, 3}, // Side 3
51  {0, 4}, // Side 4
52  {1, 5}, // Side 5
53  {2, 6}, // Side 6
54  {3, 7}, // Side 7
55  {4, 5}, // Side 8
56  {5, 6}, // Side 9
57  {6, 7}, // Side 10
58  {4, 7} // Side 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 
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 AutoPtr<Elem> Hex8::build_side (const unsigned int i,
121  bool proxy) const
122 {
123  libmesh_assert_less (i, this->n_sides());
124 
125  if (proxy)
126  {
127  AutoPtr<Elem> ap(new Side<Quad4,Hex8>(this,i));
128  return ap;
129  }
130 
131  else
132  {
133  AutoPtr<Elem> face(new Quad4);
134  face->subdomain_id() = this->subdomain_id();
135 
136  // Think of a unit cube: (-1,1) x (-1,1)x (-1,1)
137  switch (i)
138  {
139  case 0: // the face at z = -1
140  {
141  face->set_node(0) = this->get_node(0);
142  face->set_node(1) = this->get_node(3);
143  face->set_node(2) = this->get_node(2);
144  face->set_node(3) = this->get_node(1);
145 
146  return face;
147  }
148  case 1: // the face at y = -1
149  {
150  face->set_node(0) = this->get_node(0);
151  face->set_node(1) = this->get_node(1);
152  face->set_node(2) = this->get_node(5);
153  face->set_node(3) = this->get_node(4);
154 
155  return face;
156  }
157  case 2: // the face at x = 1
158  {
159  face->set_node(0) = this->get_node(1);
160  face->set_node(1) = this->get_node(2);
161  face->set_node(2) = this->get_node(6);
162  face->set_node(3) = this->get_node(5);
163 
164  return face;
165  }
166  case 3: // the face at y = 1
167  {
168  face->set_node(0) = this->get_node(2);
169  face->set_node(1) = this->get_node(3);
170  face->set_node(2) = this->get_node(7);
171  face->set_node(3) = this->get_node(6);
172 
173  return face;
174  }
175  case 4: // the face at x = -1
176  {
177  face->set_node(0) = this->get_node(3);
178  face->set_node(1) = this->get_node(0);
179  face->set_node(2) = this->get_node(4);
180  face->set_node(3) = this->get_node(7);
181 
182  return face;
183  }
184  case 5: // the face at z = 1
185  {
186  face->set_node(0) = this->get_node(4);
187  face->set_node(1) = this->get_node(5);
188  face->set_node(2) = this->get_node(6);
189  face->set_node(3) = this->get_node(7);
190 
191  return face;
192  }
193  default:
194  {
195  libmesh_error();
196  return face;
197  }
198  }
199  }
200 
201  // We'll never get here.
202  libmesh_error();
203  AutoPtr<Elem> ap(NULL); return ap;
204 }
205 
206 
207 
208 AutoPtr<Elem> Hex8::build_edge (const unsigned int i) const
209 {
210  libmesh_assert_less (i, this->n_edges());
211 
212  AutoPtr<Elem> ap(new SideEdge<Edge2,Hex8>(this,i));
213  return ap;
214 }
215 
216 
217 
218 void Hex8::connectivity(const unsigned int libmesh_dbg_var(sc),
219  const IOPackage iop,
220  std::vector<dof_id_type>& conn) const
221 {
223  libmesh_assert_less (sc, this->n_sub_elem());
224  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
225 
226  conn.resize(8);
227 
228  switch (iop)
229  {
230  case TECPLOT:
231  {
232  conn[0] = this->node(0)+1;
233  conn[1] = this->node(1)+1;
234  conn[2] = this->node(2)+1;
235  conn[3] = this->node(3)+1;
236  conn[4] = this->node(4)+1;
237  conn[5] = this->node(5)+1;
238  conn[6] = this->node(6)+1;
239  conn[7] = this->node(7)+1;
240  return;
241  }
242 
243  case VTK:
244  {
245  conn[0] = this->node(0);
246  conn[1] = this->node(1);
247  conn[2] = this->node(2);
248  conn[3] = this->node(3);
249  conn[4] = this->node(4);
250  conn[5] = this->node(5);
251  conn[6] = this->node(6);
252  conn[7] = this->node(7);
253  return;
254  }
255 
256  default:
257  libmesh_error();
258  }
259 
260  libmesh_error();
261 }
262 
263 
264 
265 #ifdef LIBMESH_ENABLE_AMR
266 
267 const float Hex8::_embedding_matrix[8][8][8] =
268 {
269  // The 8 children of the Hex-type elements can be thought of as being
270  // associated with the 8 vertices of the Hex. Some of the children are
271  // numbered the same as their corresponding vertex, while some are
272  // not. The children which are numbered differently have been marked
273  // with ** in the comments below.
274 
275  // embedding matrix for child 0 (child 0 is associated with vertex 0)
276  {
277  // 0 1 2 3 4 5 6 7
278  { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0
279  { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
280  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 2
281  { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0}, // 3
282  { 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0}, // 4
283  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 5
284  {.125, .125, .125, .125, .125, .125, .125, .125}, // 6
285  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25} // 7
286  },
287 
288  // embedding matrix for child 1 (child 1 is associated with vertex 1)
289  {
290  // 0 1 2 3 4 5 6 7
291  { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0
292  { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
293  { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2
294  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 3
295  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 4
296  { 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0}, // 5
297  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 6
298  {.125, .125, .125, .125, .125, .125, .125, .125} // 7
299  },
300 
301  // embedding matrix for child 2 (child 2 is associated with vertex 3**)
302  {
303  // 0 1 2 3 4 5 6 7
304  { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0
305  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 1
306  { 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 2
307  { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 3
308  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25}, // 4
309  {.125, .125, .125, .125, .125, .125, .125, .125}, // 5
310  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25}, // 6
311  { 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5} // 7
312  },
313 
314  // embedding matrix for child 3 (child 3 is associated with vertex 2**)
315  {
316  // 0 1 2 3 4 5 6 7
317  { .25, .25, .25, .25, 0.0, 0.0, 0.0, 0.0}, // 0
318  { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
319  { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2
320  { 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 3
321  {.125, .125, .125, .125, .125, .125, .125, .125}, // 4
322  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 5
323  { 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0}, // 6
324  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25} // 7
325  },
326 
327  // embedding matrix for child 4 (child 4 is associated with vertex 4)
328  {
329  // 0 1 2 3 4 5 6 7
330  { 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0}, // 0
331  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 1
332  {.125, .125, .125, .125, .125, .125, .125, .125}, // 2
333  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25}, // 3
334  { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 4
335  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0}, // 5
336  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25}, // 6
337  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5} // 7
338  },
339 
340  // embedding matrix for child 5 (child 5 is associated with vertex 5)
341  {
342  // 0 1 2 3 4 5 6 7
343  { .25, .25, 0.0, 0.0, .25, .25, 0.0, 0.0}, // 0
344  { 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0}, // 1
345  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 2
346  {.125, .125, .125, .125, .125, .125, .125, .125}, // 3
347  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0}, // 4
348  { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 5
349  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 6
350  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25} // 7
351  },
352 
353  // embedding matrix for child 6 (child 6 is associated with vertex 7**)
354  {
355  // 0 1 2 3 4 5 6 7
356  { .25, 0.0, 0.0, .25, .25, 0.0, 0.0, .25}, // 0
357  {.125, .125, .125, .125, .125, .125, .125, .125}, // 1
358  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25}, // 2
359  { 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}, // 3
360  { 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5}, // 4
361  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25}, // 5
362  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 6
363  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0} // 7
364  },
365 
366  // embedding matrix for child 7 (child 7 is associated with vertex 6**)
367  {
368  // 0 1 2 3 4 5 6 7
369  {.125, .125, .125, .125, .125, .125, .125, .125}, // 0
370  { 0.0, .25, .25, 0.0, 0.0, .25, .25, 0.0}, // 1
371  { 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0}, // 2
372  { 0.0, 0.0, .25, .25, 0.0, 0.0, .25, .25}, // 3
373  { 0.0, 0.0, 0.0, 0.0, .25, .25, .25, .25}, // 4
374  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 5
375  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 6
376  { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5} // 7
377  }
378 };
379 
380 
381 
382 
383 #endif
384 
385 
386 
388 {
389  // Compute the volume of the tri-linear hex by splitting it
390  // into 6 sub-pyramids and applying the formula in:
391  // "Calculation of the Volume of a General Hexahedron
392  // for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954-
393 
394  static const unsigned char sub_pyr[6][4] =
395  {
396  {0, 3, 2, 1},
397  {6, 7, 4, 5},
398  {0, 1, 5, 4},
399  {3, 7, 6, 2},
400  {0, 4, 7, 3},
401  {1, 2, 6, 5}
402  };
403 
404  // The centroid is a convenient point to use
405  // for the apex of all the pyramids.
406  const Point R = this->centroid();
407  Node* pyr_base[4];
408 
409  Real vol=0.;
410 
411  // Compute the volume using 6 sub-pyramids
412  for (unsigned int n=0; n<6; ++n)
413  {
414  // Set the nodes of the pyramid base
415  for (unsigned int i=0; i<4; ++i)
416  pyr_base[i] = this->_nodes[sub_pyr[n][i]];
417 
418  // Compute diff vectors
419  Point a ( *pyr_base[0] - R );
420  Point b ( *pyr_base[1] - *pyr_base[3] );
421  Point c ( *pyr_base[2] - *pyr_base[0] );
422  Point d ( *pyr_base[3] - *pyr_base[0] );
423  Point e ( *pyr_base[1] - *pyr_base[0] );
424 
425  // Compute pyramid volume
426  Real sub_vol = (1./6.)*(a*(b.cross(c))) + (1./12.)*(c*(d.cross(e)));
427 
428  libmesh_assert (sub_vol>0.);
429 
430  vol += sub_vol;
431  }
432 
433  return vol;
434 }
435 
436 } // namespace libMesh

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:04 UTC

Hosted By:
SourceForge.net Logo