$extrastylesheet
cell_hex8.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 // C++ includes
00020 
00021 // Local includes
00022 #include "libmesh/side.h"
00023 #include "libmesh/cell_hex8.h"
00024 #include "libmesh/edge_edge2.h"
00025 #include "libmesh/face_quad4.h"
00026 
00027 namespace libMesh
00028 {
00029 
00030 
00031 
00032 
00033 // ------------------------------------------------------------
00034 // Hex8 class static member initializations
00035 const unsigned int Hex8::side_nodes_map[6][4] =
00036   {
00037     {0, 3, 2, 1}, // Side 0
00038     {0, 1, 5, 4}, // Side 1
00039     {1, 2, 6, 5}, // Side 2
00040     {2, 3, 7, 6}, // Side 3
00041     {3, 0, 4, 7}, // Side 4
00042     {4, 5, 6, 7}  // Side 5
00043   };
00044 
00045 const unsigned int Hex8::edge_nodes_map[12][2] =
00046   {
00047     {0, 1}, // Side 0
00048     {1, 2}, // Side 1
00049     {2, 3}, // Side 2
00050     {0, 3}, // Side 3
00051     {0, 4}, // Side 4
00052     {1, 5}, // Side 5
00053     {2, 6}, // Side 6
00054     {3, 7}, // Side 7
00055     {4, 5}, // Side 8
00056     {5, 6}, // Side 9
00057     {6, 7}, // Side 10
00058     {4, 7}  // Side 11
00059   };
00060 
00061 
00062 // ------------------------------------------------------------
00063 // Hex8 class member functions
00064 
00065 bool Hex8::is_vertex(const unsigned int) const
00066 {
00067   return true;
00068 }
00069 
00070 bool Hex8::is_edge(const unsigned int) const
00071 {
00072   return false;
00073 }
00074 
00075 bool Hex8::is_face(const unsigned int) const
00076 {
00077   return false;
00078 }
00079 
00080 bool Hex8::is_node_on_side(const unsigned int n,
00081                            const unsigned int s) const
00082 {
00083   libmesh_assert_less (s, n_sides());
00084   for (unsigned int i = 0; i != 4; ++i)
00085     if (side_nodes_map[s][i] == n)
00086       return true;
00087   return false;
00088 }
00089 
00090 bool Hex8::is_node_on_edge(const unsigned int n,
00091                            const unsigned int e) const
00092 {
00093   libmesh_assert_less (e, n_edges());
00094   for (unsigned int i = 0; i != 2; ++i)
00095     if (edge_nodes_map[e][i] == n)
00096       return true;
00097   return false;
00098 }
00099 
00100 
00101 
00102 bool Hex8::has_affine_map() const
00103 {
00104   // Make sure x-edge endpoints are affine
00105   Point v = this->point(1) - this->point(0);
00106   if (!v.relative_fuzzy_equals(this->point(2) - this->point(3)) ||
00107       !v.relative_fuzzy_equals(this->point(5) - this->point(4)) ||
00108       !v.relative_fuzzy_equals(this->point(6) - this->point(7)))
00109     return false;
00110   // Make sure xz-faces are identical parallelograms
00111   v = this->point(4) - this->point(0);
00112   if (!v.relative_fuzzy_equals(this->point(7) - this->point(3)))
00113     return false;
00114   // If all the above checks out, the map is affine
00115   return true;
00116 }
00117 
00118 
00119 
00120 UniquePtr<Elem> Hex8::build_side (const unsigned int i,
00121                                   bool proxy) const
00122 {
00123   libmesh_assert_less (i, this->n_sides());
00124 
00125   if (proxy)
00126     return UniquePtr<Elem>(new Side<Quad4,Hex8>(this,i));
00127 
00128   else
00129     {
00130       Elem* face = new Quad4;
00131       face->subdomain_id() = this->subdomain_id();
00132 
00133       // Think of a unit cube: (-1,1) x (-1,1) x (-1,1)
00134       switch (i)
00135         {
00136         case 0:  // the face at z = -1
00137           {
00138             face->set_node(0) = this->get_node(0);
00139             face->set_node(1) = this->get_node(3);
00140             face->set_node(2) = this->get_node(2);
00141             face->set_node(3) = this->get_node(1);
00142             break;
00143           }
00144         case 1:  // the face at y = -1
00145           {
00146             face->set_node(0) = this->get_node(0);
00147             face->set_node(1) = this->get_node(1);
00148             face->set_node(2) = this->get_node(5);
00149             face->set_node(3) = this->get_node(4);
00150             break;
00151           }
00152         case 2:  // the face at x = 1
00153           {
00154             face->set_node(0) = this->get_node(1);
00155             face->set_node(1) = this->get_node(2);
00156             face->set_node(2) = this->get_node(6);
00157             face->set_node(3) = this->get_node(5);
00158             break;
00159           }
00160         case 3: // the face at y = 1
00161           {
00162             face->set_node(0) = this->get_node(2);
00163             face->set_node(1) = this->get_node(3);
00164             face->set_node(2) = this->get_node(7);
00165             face->set_node(3) = this->get_node(6);
00166             break;
00167           }
00168         case 4: // the face at x = -1
00169           {
00170             face->set_node(0) = this->get_node(3);
00171             face->set_node(1) = this->get_node(0);
00172             face->set_node(2) = this->get_node(4);
00173             face->set_node(3) = this->get_node(7);
00174             break;
00175           }
00176         case 5: // the face at z = 1
00177           {
00178             face->set_node(0) = this->get_node(4);
00179             face->set_node(1) = this->get_node(5);
00180             face->set_node(2) = this->get_node(6);
00181             face->set_node(3) = this->get_node(7);
00182             break;
00183           }
00184         default:
00185           libmesh_error_msg("Invalid side i = " << i);
00186         }
00187 
00188       return UniquePtr<Elem>(face);
00189     }
00190 
00191   libmesh_error_msg("We'll never get here!");
00192   return UniquePtr<Elem>();
00193 }
00194 
00195 
00196 
00197 UniquePtr<Elem> Hex8::build_edge (const unsigned int i) const
00198 {
00199   libmesh_assert_less (i, this->n_edges());
00200 
00201   return UniquePtr<Elem>(new SideEdge<Edge2,Hex8>(this,i));
00202 }
00203 
00204 
00205 
00206 void Hex8::connectivity(const unsigned int libmesh_dbg_var(sc),
00207                         const IOPackage iop,
00208                         std::vector<dof_id_type>& conn) const
00209 {
00210   libmesh_assert(_nodes);
00211   libmesh_assert_less (sc, this->n_sub_elem());
00212   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
00213 
00214   conn.resize(8);
00215 
00216   switch (iop)
00217     {
00218     case TECPLOT:
00219       {
00220         conn[0] = this->node(0)+1;
00221         conn[1] = this->node(1)+1;
00222         conn[2] = this->node(2)+1;
00223         conn[3] = this->node(3)+1;
00224         conn[4] = this->node(4)+1;
00225         conn[5] = this->node(5)+1;
00226         conn[6] = this->node(6)+1;
00227         conn[7] = this->node(7)+1;
00228         return;
00229       }
00230 
00231     case VTK:
00232       {
00233         conn[0] = this->node(0);
00234         conn[1] = this->node(1);
00235         conn[2] = this->node(2);
00236         conn[3] = this->node(3);
00237         conn[4] = this->node(4);
00238         conn[5] = this->node(5);
00239         conn[6] = this->node(6);
00240         conn[7] = this->node(7);
00241         return;
00242       }
00243 
00244     default:
00245       libmesh_error_msg("Unsupported IO package " << iop);
00246     }
00247 }
00248 
00249 
00250 
00251 #ifdef LIBMESH_ENABLE_AMR
00252 
00253 const float Hex8::_embedding_matrix[8][8][8] =
00254   {
00255     // The 8 children of the Hex-type elements can be thought of as being
00256     // associated with the 8 vertices of the Hex.  Some of the children are
00257     // numbered the same as their corresponding vertex, while some are
00258     // not.  The children which are numbered differently have been marked
00259     // with ** in the comments below.
00260 
00261     // embedding matrix for child 0 (child 0 is associated with vertex 0)
00262     {
00263       //  0     1     2     3     4     5     6     7
00264       { 1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 0
00265       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 1
00266       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 2
00267       { 0.5,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.0}, // 3
00268       { 0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0}, // 4
00269       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 5
00270       {.125, .125, .125, .125, .125, .125, .125, .125}, // 6
00271       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}  // 7
00272     },
00273 
00274     // embedding matrix for child 1 (child 1 is associated with vertex 1)
00275     {
00276       //  0     1     2     3     4     5     6     7
00277       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 0
00278       { 0.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 1
00279       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0}, // 2
00280       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 3
00281       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 4
00282       { 0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0}, // 5
00283       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 6
00284       {.125, .125, .125, .125, .125, .125, .125, .125}  // 7
00285     },
00286 
00287     // embedding matrix for child 2 (child 2 is associated with vertex 3**)
00288     {
00289       //  0      1    2     3     4     5     6     7
00290       { 0.5,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.0}, // 0
00291       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 1
00292       { 0.0,  0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 2
00293       { 0.0,  0.0,  0.0,  1.0,  0.0,  0.0,  0.0,  0.0}, // 3
00294       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}, // 4
00295       {.125, .125, .125, .125, .125, .125, .125, .125}, // 5
00296       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}, // 6
00297       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5}  // 7
00298     },
00299 
00300     // embedding matrix for child 3 (child 3 is associated with vertex 2**)
00301     {
00302       //  0      1    2     3     4     5     6     7
00303       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 0
00304       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0}, // 1
00305       { 0.0,  0.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 2
00306       { 0.0,  0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 3
00307       {.125, .125, .125, .125, .125, .125, .125, .125}, // 4
00308       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 5
00309       { 0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0}, // 6
00310       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}  // 7
00311     },
00312 
00313     // embedding matrix for child 4 (child 4 is associated with vertex 4)
00314     {
00315       //  0      1    2     3     4     5     6     7
00316       { 0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0}, // 0
00317       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 1
00318       {.125, .125, .125, .125, .125, .125, .125, .125}, // 2
00319       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}, // 3
00320       { 0.0,  0.0,  0.0,  0.0,  1.0,  0.0,  0.0,  0.0}, // 4
00321       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0,  0.0}, // 5
00322       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}, // 6
00323       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.5}  // 7
00324     },
00325 
00326     // embedding matrix for child 5 (child 5 is associated with vertex 5)
00327     {
00328       //  0      1    2     3     4     5     6     7
00329       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 0
00330       { 0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0}, // 1
00331       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 2
00332       {.125, .125, .125, .125, .125, .125, .125, .125}, // 3
00333       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0,  0.0}, // 4
00334       { 0.0,  0.0,  0.0,  0.0,  0.0,  1.0,  0.0,  0.0}, // 5
00335       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 6
00336       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}  // 7
00337     },
00338 
00339     // embedding matrix for child 6 (child 6 is associated with vertex 7**)
00340     {
00341       //  0      1    2     3     4     5     6     7
00342       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}, // 0
00343       {.125, .125, .125, .125, .125, .125, .125, .125}, // 1
00344       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}, // 2
00345       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5}, // 3
00346       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.5}, // 4
00347       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}, // 5
00348       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5}, // 6
00349       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  1.0}  // 7
00350     },
00351 
00352     // embedding matrix for child 7 (child 7 is associated with vertex 6**)
00353     {
00354       //  0      1    2     3     4     5     6     7
00355       {.125, .125, .125, .125, .125, .125, .125, .125}, // 0
00356       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 1
00357       { 0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0}, // 2
00358       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}, // 3
00359       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}, // 4
00360       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 5
00361       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  1.0,  0.0}, // 6
00362       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5}  // 7
00363     }
00364   };
00365 
00366 
00367 
00368 
00369 #endif
00370 
00371 
00372 
00373 Real Hex8::volume () const
00374 {
00375   // Compute the volume of the tri-linear hex by splitting it
00376   // into 6 sub-pyramids and applying the formula in:
00377   // "Calculation of the Volume of a General Hexahedron
00378   // for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954-
00379 
00380   static const unsigned char sub_pyr[6][4] =
00381     {
00382       {0, 3, 2, 1},
00383       {6, 7, 4, 5},
00384       {0, 1, 5, 4},
00385       {3, 7, 6, 2},
00386       {0, 4, 7, 3},
00387       {1, 2, 6, 5}
00388     };
00389 
00390   // The centroid is a convenient point to use
00391   // for the apex of all the pyramids.
00392   const Point R = this->centroid();
00393   Node* pyr_base[4];
00394 
00395   Real vol=0.;
00396 
00397   // Compute the volume using 6 sub-pyramids
00398   for (unsigned int n=0; n<6; ++n)
00399     {
00400       // Set the nodes of the pyramid base
00401       for (unsigned int i=0; i<4; ++i)
00402         pyr_base[i] = this->_nodes[sub_pyr[n][i]];
00403 
00404       // Compute diff vectors
00405       Point a ( *pyr_base[0] - R );
00406       Point b ( *pyr_base[1] - *pyr_base[3] );
00407       Point c ( *pyr_base[2] - *pyr_base[0] );
00408       Point d ( *pyr_base[3] - *pyr_base[0] );
00409       Point e ( *pyr_base[1] - *pyr_base[0] );
00410 
00411       // Compute pyramid volume
00412       Real sub_vol = (1./6.)*(a*(b.cross(c))) + (1./12.)*(c*(d.cross(e)));
00413 
00414       libmesh_assert (sub_vol>0.);
00415 
00416       vol += sub_vol;
00417     }
00418 
00419   return vol;
00420 }
00421 
00422 } // namespace libMesh