$extrastylesheet
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 // Local includes 00019 #include "libmesh/libmesh_config.h" 00020 00021 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00022 00023 00024 // C++ includes 00025 #include <algorithm> // for std::min, std::max 00026 00027 // Local includes cont'd 00028 #include "libmesh/cell_inf_hex.h" 00029 #include "libmesh/cell_inf_hex8.h" 00030 #include "libmesh/face_quad4.h" 00031 #include "libmesh/face_inf_quad4.h" 00032 00033 namespace libMesh 00034 { 00035 00036 00037 00038 00039 // ------------------------------------------------------------ 00040 // InfHex class member functions 00041 dof_id_type InfHex::key (const unsigned int s) const 00042 { 00043 libmesh_assert_less (s, this->n_sides()); 00044 00045 switch (s) 00046 { 00047 case 0: // the face at z = -1 00048 00049 return 00050 this->compute_key (this->node(0), 00051 this->node(1), 00052 this->node(2), 00053 this->node(3)); 00054 00055 case 1: // the face at y = -1 00056 00057 return 00058 this->compute_key (this->node(0), 00059 this->node(1), 00060 this->node(5), 00061 this->node(4)); 00062 00063 case 2: // the face at x = 1 00064 00065 return 00066 this->compute_key (this->node(1), 00067 this->node(2), 00068 this->node(6), 00069 this->node(5)); 00070 00071 case 3: // the face at y = 1 00072 00073 return 00074 this->compute_key (this->node(2), 00075 this->node(3), 00076 this->node(7), 00077 this->node(6)); 00078 00079 00080 case 4: // the face at x = -1 00081 00082 return 00083 this->compute_key (this->node(3), 00084 this->node(0), 00085 this->node(4), 00086 this->node(7)); 00087 00088 default: 00089 libmesh_error_msg("Invalid side s = " << s); 00090 } 00091 00092 libmesh_error_msg("We'll never get here!"); 00093 return 0; 00094 } 00095 00096 00097 00098 UniquePtr<Elem> InfHex::side (const unsigned int i) const 00099 { 00100 libmesh_assert_less (i, this->n_sides()); 00101 00102 // To be returned wrapped in an UniquePtr 00103 Elem* face = NULL; 00104 00105 // Think of a unit cube: (-1,1) x (-1,1) x (-1,1), 00106 // with (in general) the normals pointing outwards 00107 switch (i) 00108 { 00109 // the face at z = -1 00110 // the base, where the infinite element couples to conventional 00111 // elements 00112 case 0: 00113 { 00114 // Oops, here we are, claiming the normal of the face 00115 // elements point outwards -- and this is the exception: 00116 // For the side built from the base face, 00117 // the normal is pointing _into_ the element! 00118 // Why is that? - In agreement with build_side(), 00119 // which in turn _has_ to build the face in this 00120 // way as to enable the cool way \p InfFE re-uses \p FE. 00121 face = new Quad4; 00122 face->set_node(0) = this->get_node(0); 00123 face->set_node(1) = this->get_node(1); 00124 face->set_node(2) = this->get_node(2); 00125 face->set_node(3) = this->get_node(3); 00126 break; 00127 } 00128 00129 // the face at y = -1 00130 // this face connects to another infinite element 00131 case 1: 00132 { 00133 face = new InfQuad4; 00134 face->set_node(0) = this->get_node(0); 00135 face->set_node(1) = this->get_node(1); 00136 face->set_node(2) = this->get_node(4); 00137 face->set_node(3) = this->get_node(5); 00138 break; 00139 } 00140 00141 // the face at x = 1 00142 // this face connects to another infinite element 00143 case 2: 00144 { 00145 face = new InfQuad4; 00146 face->set_node(0) = this->get_node(1); 00147 face->set_node(1) = this->get_node(2); 00148 face->set_node(2) = this->get_node(5); 00149 face->set_node(3) = this->get_node(6); 00150 break; 00151 } 00152 00153 // the face at y = 1 00154 // this face connects to another infinite element 00155 case 3: 00156 { 00157 face = new InfQuad4; 00158 face->set_node(0) = this->get_node(2); 00159 face->set_node(1) = this->get_node(3); 00160 face->set_node(2) = this->get_node(6); 00161 face->set_node(3) = this->get_node(7); 00162 break; 00163 } 00164 00165 // the face at x = -1 00166 // this face connects to another infinite element 00167 case 4: 00168 { 00169 face = new InfQuad4; 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(7); 00173 face->set_node(3) = this->get_node(4); 00174 break; 00175 } 00176 00177 default: 00178 libmesh_error_msg("Invalid side i = " << i); 00179 } 00180 00181 return UniquePtr<Elem>(face); 00182 } 00183 00184 00185 00186 bool InfHex::is_child_on_side(const unsigned int c, 00187 const unsigned int s) const 00188 { 00189 libmesh_assert_less (c, this->n_children()); 00190 libmesh_assert_less (s, this->n_sides()); 00191 00192 return (s == 0 || c+1 == s || c == s%4); 00193 } 00194 00195 00196 00197 bool InfHex::is_edge_on_side (const unsigned int e, 00198 const unsigned int s) const 00199 { 00200 libmesh_assert_less (e, this->n_edges()); 00201 libmesh_assert_less (s, this->n_sides()); 00202 00203 return (is_node_on_side(InfHex8::edge_nodes_map[e][0],s) && 00204 is_node_on_side(InfHex8::edge_nodes_map[e][1],s)); 00205 } 00206 00207 00208 00209 00210 Real InfHex::quality (const ElemQuality q) const 00211 { 00212 switch (q) 00213 { 00214 00224 case DIAGONAL: 00225 { 00226 // Diagonal between node 0 and node 2 00227 const Real d02 = this->length(0,2); 00228 00229 // Diagonal between node 1 and node 3 00230 const Real d13 = this->length(1,3); 00231 00232 // Find the biggest and smallest diagonals 00233 const Real min = std::min(d02, d13); 00234 const Real max = std::max(d02, d13); 00235 00236 libmesh_assert_not_equal_to (max, 0.0); 00237 00238 return min / max; 00239 00240 break; 00241 } 00242 00250 case TAPER: 00251 { 00252 00256 const Real d01 = this->length(0,1); 00257 const Real d12 = this->length(1,2); 00258 const Real d23 = this->length(2,3); 00259 const Real d03 = this->length(0,3); 00260 00261 std::vector<Real> edge_ratios(2); 00262 00263 // Bottom 00264 edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23); 00265 edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12); 00266 00267 return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ; 00268 00269 break; 00270 } 00271 00272 00280 case STRETCH: 00281 { 00285 const Real sqrt3 = 1.73205080756888; 00286 00290 const Real d02 = this->length(0,2); 00291 const Real d13 = this->length(1,3); 00292 const Real max_diag = std::max(d02, d13); 00293 00294 libmesh_assert_not_equal_to ( max_diag, 0.0 ); 00295 00299 std::vector<Real> edges(4); 00300 edges[0] = this->length(0,1); 00301 edges[1] = this->length(1,2); 00302 edges[2] = this->length(2,3); 00303 edges[3] = this->length(0,3); 00304 00305 const Real min_edge = *(std::min_element(edges.begin(), edges.end())); 00306 return sqrt3 * min_edge / max_diag ; 00307 } 00308 00309 00314 default: 00315 return Elem::quality(q); 00316 } 00317 00318 libmesh_error_msg("We'll never get here!"); 00319 return 0.; 00320 } 00321 00322 00323 00324 std::pair<Real, Real> InfHex::qual_bounds (const ElemQuality) const 00325 { 00326 libmesh_not_implemented(); 00327 00328 std::pair<Real, Real> bounds; 00329 00330 /* 00331 switch (q) 00332 { 00333 00334 case ASPECT_RATIO: 00335 bounds.first = 1.; 00336 bounds.second = 4.; 00337 break; 00338 00339 case SKEW: 00340 bounds.first = 0.; 00341 bounds.second = 0.5; 00342 break; 00343 00344 case SHEAR: 00345 case SHAPE: 00346 bounds.first = 0.3; 00347 bounds.second = 1.; 00348 break; 00349 00350 case CONDITION: 00351 bounds.first = 1.; 00352 bounds.second = 8.; 00353 break; 00354 00355 case JACOBIAN: 00356 bounds.first = 0.5; 00357 bounds.second = 1.; 00358 break; 00359 00360 case DISTORTION: 00361 bounds.first = 0.6; 00362 bounds.second = 1.; 00363 break; 00364 00365 case TAPER: 00366 bounds.first = 0.; 00367 bounds.second = 0.4; 00368 break; 00369 00370 case STRETCH: 00371 bounds.first = 0.25; 00372 bounds.second = 1.; 00373 break; 00374 00375 case DIAGONAL: 00376 bounds.first = 0.65; 00377 bounds.second = 1.; 00378 break; 00379 00380 case SIZE: 00381 bounds.first = 0.5; 00382 bounds.second = 1.; 00383 break; 00384 00385 default: 00386 libMesh::out << "Warning: Invalid quality measure chosen." << std::endl; 00387 bounds.first = -1; 00388 bounds.second = -1; 00389 } 00390 */ 00391 00392 return bounds; 00393 } 00394 00395 00396 00397 00398 00399 const unsigned short int InfHex::_second_order_adjacent_vertices[8][2] = 00400 { 00401 { 0, 1}, // vertices adjacent to node 8 00402 { 1, 2}, // vertices adjacent to node 9 00403 { 2, 3}, // vertices adjacent to node 10 00404 { 0, 3}, // vertices adjacent to node 11 00405 00406 { 4, 5}, // vertices adjacent to node 12 00407 { 5, 6}, // vertices adjacent to node 13 00408 { 6, 7}, // vertices adjacent to node 14 00409 { 4, 7} // vertices adjacent to node 15 00410 }; 00411 00412 00413 00414 const unsigned short int InfHex::_second_order_vertex_child_number[18] = 00415 { 00416 99,99,99,99,99,99,99,99, // Vertices 00417 0,1,2,0, // Edges 00418 0,1,2,0,0, // Faces 00419 0 // Interior 00420 }; 00421 00422 00423 00424 const unsigned short int InfHex::_second_order_vertex_child_index[18] = 00425 { 00426 99,99,99,99,99,99,99,99, // Vertices 00427 1,2,3,3, // Edges 00428 5,6,7,7,2, // Faces 00429 6 // Interior 00430 }; 00431 00432 } // namespace libMesh 00433 00434 00435 00436 00437 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS