$extrastylesheet
cell_hex.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 #include <algorithm> // for std::min, std::max
00021 
00022 // Local includes
00023 #include "libmesh/cell_hex.h"
00024 #include "libmesh/cell_hex8.h"
00025 #include "libmesh/face_quad4.h"
00026 
00027 namespace libMesh
00028 {
00029 
00030 
00031 
00032 
00033 // ------------------------------------------------------------
00034 // Hex class member functions
00035 dof_id_type Hex::key (const unsigned int s) const
00036 {
00037   libmesh_assert_less (s, this->n_sides());
00038 
00039   // Think of a unit cube: (-1,1) x (-1,1)x (-1,1)
00040   switch (s)
00041     {
00042     case 0:  // the face at z = -1
00043 
00044       return
00045         this->compute_key (this->node(0),
00046                            this->node(3),
00047                            this->node(2),
00048                            this->node(1));
00049 
00050     case 1:  // the face at y = -1
00051 
00052       return
00053         this->compute_key (this->node(0),
00054                            this->node(1),
00055                            this->node(5),
00056                            this->node(4));
00057 
00058     case 2:  // the face at x = 1
00059 
00060       return
00061         this->compute_key (this->node(1),
00062                            this->node(2),
00063                            this->node(6),
00064                            this->node(5));
00065 
00066     case 3: // the face at y = 1
00067 
00068       return
00069         this->compute_key (this->node(2),
00070                            this->node(3),
00071                            this->node(7),
00072                            this->node(6));
00073 
00074     case 4: // the face at x = -1
00075 
00076       return
00077         this->compute_key (this->node(3),
00078                            this->node(0),
00079                            this->node(4),
00080                            this->node(7));
00081 
00082     case 5: // the face at z = 1
00083 
00084       return
00085         this->compute_key (this->node(4),
00086                            this->node(5),
00087                            this->node(6),
00088                            this->node(7));
00089 
00090     default:
00091       libmesh_error_msg("Invalid s = " << s);
00092     }
00093 
00094   libmesh_error_msg("We'll never get here!");
00095   return 0;
00096 }
00097 
00098 
00099 
00100 UniquePtr<Elem> Hex::side (const unsigned int i) const
00101 {
00102   libmesh_assert_less (i, this->n_sides());
00103 
00104   Elem* face = new Quad4;
00105 
00106   // Think of a unit cube: (-1,1) x (-1,1) x (-1,1)
00107   switch (i)
00108     {
00109     case 0:  // the face at z = -1
00110       {
00111         face->set_node(0) = this->get_node(0);
00112         face->set_node(1) = this->get_node(3);
00113         face->set_node(2) = this->get_node(2);
00114         face->set_node(3) = this->get_node(1);
00115         break;
00116       }
00117     case 1:  // the face at y = -1
00118       {
00119         face->set_node(0) = this->get_node(0);
00120         face->set_node(1) = this->get_node(1);
00121         face->set_node(2) = this->get_node(5);
00122         face->set_node(3) = this->get_node(4);
00123         break;
00124       }
00125     case 2:  // the face at x = 1
00126       {
00127         face->set_node(0) = this->get_node(1);
00128         face->set_node(1) = this->get_node(2);
00129         face->set_node(2) = this->get_node(6);
00130         face->set_node(3) = this->get_node(5);
00131         break;
00132       }
00133     case 3: // the face at y = 1
00134       {
00135         face->set_node(0) = this->get_node(2);
00136         face->set_node(1) = this->get_node(3);
00137         face->set_node(2) = this->get_node(7);
00138         face->set_node(3) = this->get_node(6);
00139         break;
00140       }
00141     case 4: // the face at x = -1
00142       {
00143         face->set_node(0) = this->get_node(3);
00144         face->set_node(1) = this->get_node(0);
00145         face->set_node(2) = this->get_node(4);
00146         face->set_node(3) = this->get_node(7);
00147         break;
00148       }
00149     case 5: // the face at z = 1
00150       {
00151         face->set_node(0) = this->get_node(4);
00152         face->set_node(1) = this->get_node(5);
00153         face->set_node(2) = this->get_node(6);
00154         face->set_node(3) = this->get_node(7);
00155         break;
00156       }
00157     default:
00158       libmesh_error_msg("Unsupported side i = " << i);
00159     }
00160 
00161   return UniquePtr<Elem>(face);
00162 }
00163 
00164 
00165 
00166 bool Hex::is_child_on_side(const unsigned int c,
00167                            const unsigned int s) const
00168 {
00169   libmesh_assert_less (c, this->n_children());
00170   libmesh_assert_less (s, this->n_sides());
00171 
00172   // This array maps the Hex8 node numbering to the Hex8 child
00173   // numbering.  I.e.
00174   //   node 6 touches child 7, and
00175   //   node 7 touches child 6, etc.
00176   const unsigned int node_child_map[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
00177 
00178   for (unsigned int i = 0; i != 4; ++i)
00179     if (node_child_map[Hex8::side_nodes_map[s][i]] == c)
00180       return true;
00181 
00182   return false;
00183 }
00184 
00185 
00186 
00187 bool Hex::is_edge_on_side(const unsigned int e,
00188                           const unsigned int s) const
00189 {
00190   libmesh_assert_less (e, this->n_edges());
00191   libmesh_assert_less (s, this->n_sides());
00192 
00193   return (is_node_on_side(Hex8::edge_nodes_map[e][0],s) &&
00194           is_node_on_side(Hex8::edge_nodes_map[e][1],s));
00195 }
00196 
00197 
00198 
00199 unsigned int Hex::opposite_side(const unsigned int side_in) const
00200 {
00201   libmesh_assert_less (side_in, 6);
00202   static const unsigned char hex_opposites[6] = {5, 3, 4, 1, 2, 0};
00203   return hex_opposites[side_in];
00204 }
00205 
00206 
00207 
00208 unsigned int Hex::opposite_node(const unsigned int node_in,
00209                                 const unsigned int side_in) const
00210 {
00211   libmesh_assert_less (node_in, 26);
00212   libmesh_assert_less (node_in, this->n_nodes());
00213   libmesh_assert_less (side_in, this->n_sides());
00214   libmesh_assert(this->is_node_on_side(node_in, side_in));
00215 
00216   static const unsigned char side05_nodes_map[] =
00217     {4, 5, 6, 7, 0, 1, 2, 3, 16, 17, 18, 19, 255, 255, 255, 255, 8, 9, 10, 11, 25, 255, 255, 255, 255, 20};
00218   static const unsigned char side13_nodes_map[] =
00219     {3, 2, 1, 0, 7, 6, 5, 4, 10, 255, 8, 255, 15, 14, 13, 12, 18, 255, 16, 255, 255, 23, 255, 21, 255, 255};
00220   static const unsigned char side24_nodes_map[] =
00221     {1, 0, 3, 2, 5, 4, 7, 6, 255, 11, 255, 9, 13, 12, 15, 14, 255, 19, 255, 17, 255, 255, 24, 255, 22, 255};
00222 
00223   switch (side_in)
00224     {
00225     case 0:
00226     case 5:
00227       return side05_nodes_map[node_in];
00228     case 1:
00229     case 3:
00230       return side13_nodes_map[node_in];
00231     case 2:
00232     case 4:
00233       return side24_nodes_map[node_in];
00234     default:
00235       libmesh_error_msg("Unsupported side_in = " << side_in);
00236     }
00237 
00238   libmesh_error_msg("We'll never get here!");
00239   return 255;
00240 }
00241 
00242 
00243 
00244 Real Hex::quality (const ElemQuality q) const
00245 {
00246   switch (q)
00247     {
00248 
00253     case DIAGONAL:
00254       {
00255         // Diagonal between node 0 and node 6
00256         const Real d06 = this->length(0,6);
00257 
00258         // Diagonal between node 3 and node 5
00259         const Real d35 = this->length(3,5);
00260 
00261         // Diagonal between node 1 and node 7
00262         const Real d17 = this->length(1,7);
00263 
00264         // Diagonal between node 2 and node 4
00265         const Real d24 = this->length(2,4);
00266 
00267         // Find the biggest and smallest diagonals
00268         const Real min = std::min(d06, std::min(d35, std::min(d17, d24)));
00269         const Real max = std::max(d06, std::max(d35, std::max(d17, d24)));
00270 
00271         libmesh_assert_not_equal_to (max, 0.0);
00272 
00273         return min / max;
00274 
00275         break;
00276       }
00277 
00282     case TAPER:
00283       {
00284 
00288         const Real d01 = this->length(0,1);
00289         const Real d12 = this->length(1,2);
00290         const Real d23 = this->length(2,3);
00291         const Real d03 = this->length(0,3);
00292         const Real d45 = this->length(4,5);
00293         const Real d56 = this->length(5,6);
00294         const Real d67 = this->length(6,7);
00295         const Real d47 = this->length(4,7);
00296         const Real d04 = this->length(0,4);
00297         const Real d15 = this->length(1,5);
00298         const Real d37 = this->length(3,7);
00299         const Real d26 = this->length(2,6);
00300 
00301         std::vector<Real> edge_ratios(12);
00302         // Front
00303         edge_ratios[0] = std::min(d01, d45) / std::max(d01, d45);
00304         edge_ratios[1] = std::min(d04, d15) / std::max(d04, d15);
00305 
00306         // Right
00307         edge_ratios[2] = std::min(d15, d26) / std::max(d15, d26);
00308         edge_ratios[3] = std::min(d12, d56) / std::max(d12, d56);
00309 
00310         // Back
00311         edge_ratios[4] = std::min(d67, d23) / std::max(d67, d23);
00312         edge_ratios[5] = std::min(d26, d37) / std::max(d26, d37);
00313 
00314         // Left
00315         edge_ratios[6] = std::min(d04, d37) / std::max(d04, d37);
00316         edge_ratios[7] = std::min(d03, d47) / std::max(d03, d47);
00317 
00318         // Bottom
00319         edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23);
00320         edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12);
00321 
00322         // Top
00323         edge_ratios[10] = std::min(d45, d67) / std::max(d45, d67);
00324         edge_ratios[11] = std::min(d56, d47) / std::max(d56, d47);
00325 
00326         return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ;
00327 
00328         break;
00329       }
00330 
00331 
00336     case STRETCH:
00337       {
00338         const Real sqrt3 = 1.73205080756888;
00339 
00343         const Real d06 = this->length(0,6);
00344         const Real d17 = this->length(1,7);
00345         const Real d35 = this->length(3,5);
00346         const Real d24 = this->length(2,4);
00347         const Real max_diag = std::max(d06, std::max(d17, std::max(d35, d24)));
00348 
00349         libmesh_assert_not_equal_to ( max_diag, 0.0 );
00350 
00354         std::vector<Real> edges(12);
00355         edges[0]  = this->length(0,1);
00356         edges[1]  = this->length(1,2);
00357         edges[2]  = this->length(2,3);
00358         edges[3]  = this->length(0,3);
00359         edges[4]  = this->length(4,5);
00360         edges[5]  = this->length(5,6);
00361         edges[6]  = this->length(6,7);
00362         edges[7]  = this->length(4,7);
00363         edges[8]  = this->length(0,4);
00364         edges[9]  = this->length(1,5);
00365         edges[10] = this->length(2,6);
00366         edges[11] = this->length(3,7);
00367 
00368         const Real min_edge = *(std::min_element(edges.begin(), edges.end()));
00369         return sqrt3 * min_edge / max_diag ;
00370       }
00371 
00372 
00377     default:
00378       return Elem::quality(q);
00379     }
00380 
00381   libmesh_error_msg("We'll never get here!");
00382   return 0.;
00383 }
00384 
00385 
00386 
00387 std::pair<Real, Real> Hex::qual_bounds (const ElemQuality q) const
00388 {
00389   std::pair<Real, Real> bounds;
00390 
00391   switch (q)
00392     {
00393 
00394     case ASPECT_RATIO:
00395       bounds.first  = 1.;
00396       bounds.second = 4.;
00397       break;
00398 
00399     case SKEW:
00400       bounds.first  = 0.;
00401       bounds.second = 0.5;
00402       break;
00403 
00404     case SHEAR:
00405     case SHAPE:
00406       bounds.first  = 0.3;
00407       bounds.second = 1.;
00408       break;
00409 
00410     case CONDITION:
00411       bounds.first  = 1.;
00412       bounds.second = 8.;
00413       break;
00414 
00415     case JACOBIAN:
00416       bounds.first  = 0.5;
00417       bounds.second = 1.;
00418       break;
00419 
00420     case DISTORTION:
00421       bounds.first  = 0.6;
00422       bounds.second = 1.;
00423       break;
00424 
00425     case TAPER:
00426       bounds.first  = 0.;
00427       bounds.second = 0.4;
00428       break;
00429 
00430     case STRETCH:
00431       bounds.first  = 0.25;
00432       bounds.second = 1.;
00433       break;
00434 
00435     case DIAGONAL:
00436       bounds.first  = 0.65;
00437       bounds.second = 1.;
00438       break;
00439 
00440     case SIZE:
00441       bounds.first  = 0.5;
00442       bounds.second = 1.;
00443       break;
00444 
00445     default:
00446       libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
00447       bounds.first  = -1;
00448       bounds.second = -1;
00449     }
00450 
00451   return bounds;
00452 }
00453 
00454 
00455 
00456 const unsigned short int Hex::_second_order_vertex_child_number[27] =
00457   {
00458     99,99,99,99,99,99,99,99, // Vertices
00459     0,1,2,0,0,1,2,3,4,5,6,5, // Edges
00460     0,0,1,2,0,4,             // Faces
00461     0                        // Interior
00462   };
00463 
00464 
00465 
00466 const unsigned short int Hex::_second_order_vertex_child_index[27] =
00467   {
00468     99,99,99,99,99,99,99,99, // Vertices
00469     1,2,3,3,4,5,6,7,5,6,7,7, // Edges
00470     2,5,6,7,7,6,             // Faces
00471     6                        // Interior
00472   };
00473 
00474 
00475 const unsigned short int Hex::_second_order_adjacent_vertices[12][2] =
00476   {
00477     { 0,  1}, // vertices adjacent to node 8
00478     { 1,  2}, // vertices adjacent to node 9
00479     { 2,  3}, // vertices adjacent to node 10
00480     { 0,  3}, // vertices adjacent to node 11
00481 
00482     { 0,  4}, // vertices adjacent to node 12
00483     { 1,  5}, // vertices adjacent to node 13
00484     { 2,  6}, // vertices adjacent to node 14
00485     { 3,  7}, // vertices adjacent to node 15
00486 
00487     { 4,  5}, // vertices adjacent to node 16
00488     { 5,  6}, // vertices adjacent to node 17
00489     { 6,  7}, // vertices adjacent to node 18
00490     { 4,  7}  // vertices adjacent to node 19
00491   };
00492 
00493 } // namespace libMesh