cell_hex.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 00091 // We'll never get here. 00092 libmesh_error(); 00093 return 0; 00094 } 00095 00096 00097 00098 AutoPtr<Elem> Hex::side (const unsigned int i) const 00099 { 00100 libmesh_assert_less (i, this->n_sides()); 00101 00102 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 00116 AutoPtr<Elem> ap(face); 00117 return ap; 00118 } 00119 case 1: // the face at y = -1 00120 { 00121 face->set_node(0) = this->get_node(0); 00122 face->set_node(1) = this->get_node(1); 00123 face->set_node(2) = this->get_node(5); 00124 face->set_node(3) = this->get_node(4); 00125 00126 AutoPtr<Elem> ap(face); 00127 return ap; 00128 } 00129 case 2: // the face at x = 1 00130 { 00131 face->set_node(0) = this->get_node(1); 00132 face->set_node(1) = this->get_node(2); 00133 face->set_node(2) = this->get_node(6); 00134 face->set_node(3) = this->get_node(5); 00135 00136 AutoPtr<Elem> ap(face); 00137 return ap; 00138 } 00139 case 3: // the face at y = 1 00140 { 00141 face->set_node(0) = this->get_node(2); 00142 face->set_node(1) = this->get_node(3); 00143 face->set_node(2) = this->get_node(7); 00144 face->set_node(3) = this->get_node(6); 00145 00146 AutoPtr<Elem> ap(face); 00147 return ap; 00148 } 00149 case 4: // the face at x = -1 00150 { 00151 face->set_node(0) = this->get_node(3); 00152 face->set_node(1) = this->get_node(0); 00153 face->set_node(2) = this->get_node(4); 00154 face->set_node(3) = this->get_node(7); 00155 00156 AutoPtr<Elem> ap(face); 00157 return ap; 00158 } 00159 case 5: // the face at z = 1 00160 { 00161 face->set_node(0) = this->get_node(4); 00162 face->set_node(1) = this->get_node(5); 00163 face->set_node(2) = this->get_node(6); 00164 face->set_node(3) = this->get_node(7); 00165 00166 AutoPtr<Elem> ap(face); 00167 return ap; 00168 } 00169 default: 00170 { 00171 libmesh_error(); 00172 AutoPtr<Elem> ap(face); 00173 return ap; 00174 } 00175 } 00176 00177 // We'll never get here. 00178 libmesh_error(); 00179 AutoPtr<Elem> ap(face); 00180 return ap; 00181 } 00182 00183 00184 00185 bool Hex::is_child_on_side(const unsigned int c, 00186 const unsigned int s) const 00187 { 00188 libmesh_assert_less (c, this->n_children()); 00189 libmesh_assert_less (s, this->n_sides()); 00190 00191 // This array maps the Hex8 node numbering to the Hex8 child 00192 // numbering. I.e. 00193 // node 6 touches child 7, and 00194 // node 7 touches child 6, etc. 00195 const unsigned int node_child_map[8] = { 0, 1, 3, 2, 4, 5, 7, 6 }; 00196 00197 for (unsigned int i = 0; i != 4; ++i) 00198 if (node_child_map[Hex8::side_nodes_map[s][i]] == c) 00199 return true; 00200 00201 return false; 00202 } 00203 00204 00205 00206 bool Hex::is_edge_on_side(const unsigned int e, 00207 const unsigned int s) const 00208 { 00209 libmesh_assert_less (e, this->n_edges()); 00210 libmesh_assert_less (s, this->n_sides()); 00211 00212 return (is_node_on_side(Hex8::edge_nodes_map[e][0],s) && 00213 is_node_on_side(Hex8::edge_nodes_map[e][1],s)); 00214 } 00215 00216 00217 00218 unsigned int Hex::opposite_side(const unsigned int side_in) const 00219 { 00220 libmesh_assert_less (side_in, 6); 00221 static const unsigned char hex_opposites[6] = {5, 3, 4, 1, 2, 0}; 00222 return hex_opposites[side_in]; 00223 } 00224 00225 00226 00227 unsigned int Hex::opposite_node(const unsigned int node_in, 00228 const unsigned int side_in) const 00229 { 00230 libmesh_assert_less (node_in, 26); 00231 libmesh_assert_less (node_in, this->n_nodes()); 00232 libmesh_assert_less (side_in, this->n_sides()); 00233 libmesh_assert(this->is_node_on_side(node_in, side_in)); 00234 00235 static const unsigned char side05_nodes_map[] = 00236 {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}; 00237 static const unsigned char side13_nodes_map[] = 00238 {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}; 00239 static const unsigned char side24_nodes_map[] = 00240 {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}; 00241 00242 switch (side_in) 00243 { 00244 case 0: 00245 case 5: 00246 return side05_nodes_map[node_in]; 00247 break; 00248 case 1: 00249 case 3: 00250 return side13_nodes_map[node_in]; 00251 break; 00252 case 2: 00253 case 4: 00254 return side24_nodes_map[node_in]; 00255 break; 00256 } 00257 00258 libmesh_error(); 00259 return 255; 00260 } 00261 00262 00263 00264 Real Hex::quality (const ElemQuality q) const 00265 { 00266 switch (q) 00267 { 00268 00273 case DIAGONAL: 00274 { 00275 // Diagonal between node 0 and node 6 00276 const Real d06 = this->length(0,6); 00277 00278 // Diagonal between node 3 and node 5 00279 const Real d35 = this->length(3,5); 00280 00281 // Diagonal between node 1 and node 7 00282 const Real d17 = this->length(1,7); 00283 00284 // Diagonal between node 2 and node 4 00285 const Real d24 = this->length(2,4); 00286 00287 // Find the biggest and smallest diagonals 00288 const Real min = std::min(d06, std::min(d35, std::min(d17, d24))); 00289 const Real max = std::max(d06, std::max(d35, std::max(d17, d24))); 00290 00291 libmesh_assert_not_equal_to (max, 0.0); 00292 00293 return min / max; 00294 00295 break; 00296 } 00297 00302 case TAPER: 00303 { 00304 00308 const Real d01 = this->length(0,1); 00309 const Real d12 = this->length(1,2); 00310 const Real d23 = this->length(2,3); 00311 const Real d03 = this->length(0,3); 00312 const Real d45 = this->length(4,5); 00313 const Real d56 = this->length(5,6); 00314 const Real d67 = this->length(6,7); 00315 const Real d47 = this->length(4,7); 00316 const Real d04 = this->length(0,4); 00317 const Real d15 = this->length(1,5); 00318 const Real d37 = this->length(3,7); 00319 const Real d26 = this->length(2,6); 00320 00321 std::vector<Real> edge_ratios(12); 00322 // Front 00323 edge_ratios[0] = std::min(d01, d45) / std::max(d01, d45); 00324 edge_ratios[1] = std::min(d04, d15) / std::max(d04, d15); 00325 00326 // Right 00327 edge_ratios[2] = std::min(d15, d26) / std::max(d15, d26); 00328 edge_ratios[3] = std::min(d12, d56) / std::max(d12, d56); 00329 00330 // Back 00331 edge_ratios[4] = std::min(d67, d23) / std::max(d67, d23); 00332 edge_ratios[5] = std::min(d26, d37) / std::max(d26, d37); 00333 00334 // Left 00335 edge_ratios[6] = std::min(d04, d37) / std::max(d04, d37); 00336 edge_ratios[7] = std::min(d03, d47) / std::max(d03, d47); 00337 00338 // Bottom 00339 edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23); 00340 edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12); 00341 00342 // Top 00343 edge_ratios[10] = std::min(d45, d67) / std::max(d45, d67); 00344 edge_ratios[11] = std::min(d56, d47) / std::max(d56, d47); 00345 00346 return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ; 00347 00348 break; 00349 } 00350 00351 00356 case STRETCH: 00357 { 00358 const Real sqrt3 = 1.73205080756888; 00359 00363 const Real d06 = this->length(0,6); 00364 const Real d17 = this->length(1,7); 00365 const Real d35 = this->length(3,5); 00366 const Real d24 = this->length(2,4); 00367 const Real max_diag = std::max(d06, std::max(d17, std::max(d35, d24))); 00368 00369 libmesh_assert_not_equal_to ( max_diag, 0.0 ); 00370 00374 std::vector<Real> edges(12); 00375 edges[0] = this->length(0,1); 00376 edges[1] = this->length(1,2); 00377 edges[2] = this->length(2,3); 00378 edges[3] = this->length(0,3); 00379 edges[4] = this->length(4,5); 00380 edges[5] = this->length(5,6); 00381 edges[6] = this->length(6,7); 00382 edges[7] = this->length(4,7); 00383 edges[8] = this->length(0,4); 00384 edges[9] = this->length(1,5); 00385 edges[10] = this->length(2,6); 00386 edges[11] = this->length(3,7); 00387 00388 const Real min_edge = *(std::min_element(edges.begin(), edges.end())); 00389 return sqrt3 * min_edge / max_diag ; 00390 break; 00391 } 00392 00393 00398 default: 00399 { 00400 return Elem::quality(q); 00401 } 00402 } 00403 00404 00405 // Will never get here... 00406 libmesh_error(); 00407 return 0.; 00408 } 00409 00410 00411 00412 std::pair<Real, Real> Hex::qual_bounds (const ElemQuality q) const 00413 { 00414 std::pair<Real, Real> bounds; 00415 00416 switch (q) 00417 { 00418 00419 case ASPECT_RATIO: 00420 bounds.first = 1.; 00421 bounds.second = 4.; 00422 break; 00423 00424 case SKEW: 00425 bounds.first = 0.; 00426 bounds.second = 0.5; 00427 break; 00428 00429 case SHEAR: 00430 case SHAPE: 00431 bounds.first = 0.3; 00432 bounds.second = 1.; 00433 break; 00434 00435 case CONDITION: 00436 bounds.first = 1.; 00437 bounds.second = 8.; 00438 break; 00439 00440 case JACOBIAN: 00441 bounds.first = 0.5; 00442 bounds.second = 1.; 00443 break; 00444 00445 case DISTORTION: 00446 bounds.first = 0.6; 00447 bounds.second = 1.; 00448 break; 00449 00450 case TAPER: 00451 bounds.first = 0.; 00452 bounds.second = 0.4; 00453 break; 00454 00455 case STRETCH: 00456 bounds.first = 0.25; 00457 bounds.second = 1.; 00458 break; 00459 00460 case DIAGONAL: 00461 bounds.first = 0.65; 00462 bounds.second = 1.; 00463 break; 00464 00465 case SIZE: 00466 bounds.first = 0.5; 00467 bounds.second = 1.; 00468 break; 00469 00470 default: 00471 libMesh::out << "Warning: Invalid quality measure chosen." << std::endl; 00472 bounds.first = -1; 00473 bounds.second = -1; 00474 } 00475 00476 return bounds; 00477 } 00478 00479 00480 00481 const unsigned short int Hex::_second_order_vertex_child_number[27] = 00482 { 00483 99,99,99,99,99,99,99,99, // Vertices 00484 0,1,2,0,0,1,2,3,4,5,6,5, // Edges 00485 0,0,1,2,0,4, // Faces 00486 0 // Interior 00487 }; 00488 00489 00490 00491 const unsigned short int Hex::_second_order_vertex_child_index[27] = 00492 { 00493 99,99,99,99,99,99,99,99, // Vertices 00494 1,2,3,3,4,5,6,7,5,6,7,7, // Edges 00495 2,5,6,7,7,6, // Faces 00496 6 // Interior 00497 }; 00498 00499 00500 const unsigned short int Hex::_second_order_adjacent_vertices[12][2] = 00501 { 00502 { 0, 1}, // vertices adjacent to node 8 00503 { 1, 2}, // vertices adjacent to node 9 00504 { 2, 3}, // vertices adjacent to node 10 00505 { 0, 3}, // vertices adjacent to node 11 00506 00507 { 0, 4}, // vertices adjacent to node 12 00508 { 1, 5}, // vertices adjacent to node 13 00509 { 2, 6}, // vertices adjacent to node 14 00510 { 3, 7}, // vertices adjacent to node 15 00511 00512 { 4, 5}, // vertices adjacent to node 16 00513 { 5, 6}, // vertices adjacent to node 17 00514 { 6, 7}, // vertices adjacent to node 18 00515 { 4, 7} // vertices adjacent to node 19 00516 }; 00517 00518 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:45 UTC
Hosted By: