$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 // C++ includes 00024 00025 // Local includes cont'd 00026 #include "libmesh/cell_inf_hex8.h" 00027 #include "libmesh/edge_edge2.h" 00028 #include "libmesh/edge_inf_edge2.h" 00029 #include "libmesh/face_quad4.h" 00030 #include "libmesh/face_inf_quad4.h" 00031 #include "libmesh/fe_interface.h" 00032 #include "libmesh/fe_type.h" 00033 #include "libmesh/side.h" 00034 00035 namespace libMesh 00036 { 00037 00038 00039 // ------------------------------------------------------------ 00040 // InfHex8 class member functions 00041 const unsigned int InfHex8::side_nodes_map[5][4] = 00042 { 00043 { 0, 1, 2, 3}, // Side 0 00044 { 0, 1, 4, 5}, // Side 1 00045 { 1, 2, 5, 6}, // Side 2 00046 { 2, 3, 6, 7}, // Side 3 00047 { 3, 0, 7, 4} // Side 4 00048 }; 00049 00050 const unsigned int InfHex8::edge_nodes_map[8][2] = 00051 { 00052 { 0, 1}, // Side 0 00053 { 1, 2}, // Side 1 00054 { 2, 3}, // Side 2 00055 { 0, 3}, // Side 3 00056 { 0, 4}, // Side 4 00057 { 1, 5}, // Side 5 00058 { 2, 6}, // Side 6 00059 { 3, 7} // Side 7 00060 }; 00061 00062 00063 // ------------------------------------------------------------ 00064 // InfHex8 class member functions 00065 00066 bool InfHex8::is_vertex(const unsigned int i) const 00067 { 00068 if (i < 4) 00069 return true; 00070 return false; 00071 } 00072 00073 bool InfHex8::is_edge(const unsigned int i) const 00074 { 00075 if (i < 4) 00076 return false; 00077 return true; 00078 } 00079 00080 bool InfHex8::is_face(const unsigned int) const 00081 { 00082 return false; 00083 } 00084 00085 bool InfHex8::is_node_on_side(const unsigned int n, 00086 const unsigned int s) const 00087 { 00088 libmesh_assert_less (s, n_sides()); 00089 for (unsigned int i = 0; i != 4; ++i) 00090 if (side_nodes_map[s][i] == n) 00091 return true; 00092 return false; 00093 } 00094 00095 bool InfHex8::is_node_on_edge(const unsigned int n, 00096 const unsigned int e) const 00097 { 00098 libmesh_assert_less (e, n_edges()); 00099 for (unsigned int i = 0; i != 2; ++i) 00100 if (edge_nodes_map[e][i] == n) 00101 return true; 00102 return false; 00103 } 00104 00105 UniquePtr<Elem> InfHex8::build_side (const unsigned int i, 00106 bool proxy) const 00107 { 00108 libmesh_assert_less (i, this->n_sides()); 00109 00110 if (proxy) 00111 { 00112 switch (i) 00113 { 00114 // base 00115 case 0: 00116 return UniquePtr<Elem>(new Side<Quad4,InfHex8>(this,i)); 00117 00118 // ifem sides 00119 case 1: 00120 case 2: 00121 case 3: 00122 case 4: 00123 return UniquePtr<Elem>(new Side<InfQuad4,InfHex8>(this,i)); 00124 00125 default: 00126 libmesh_error_msg("Invalid side i = " << i); 00127 } 00128 } 00129 00130 else 00131 { 00132 // Create NULL pointer to be initialized, returned later. 00133 Elem* face = NULL; 00134 00135 // Think of a unit cube: (-1,1) x (-1,1) x (1,1) 00136 switch (i) 00137 { 00138 case 0: // the base face 00139 { 00140 face = new Quad4; 00141 00142 // Only here, the face element's normal points inward 00143 face->set_node(0) = this->get_node(0); 00144 face->set_node(1) = this->get_node(1); 00145 face->set_node(2) = this->get_node(2); 00146 face->set_node(3) = this->get_node(3); 00147 00148 break; 00149 } 00150 00151 case 1: // connecting to another infinite element 00152 { 00153 face = new InfQuad4; 00154 00155 face->set_node(0) = this->get_node(0); 00156 face->set_node(1) = this->get_node(1); 00157 face->set_node(2) = this->get_node(4); 00158 face->set_node(3) = this->get_node(5); 00159 00160 break; 00161 } 00162 00163 case 2: // connecting to another infinite element 00164 { 00165 face = new InfQuad4; 00166 00167 face->set_node(0) = this->get_node(1); 00168 face->set_node(1) = this->get_node(2); 00169 face->set_node(2) = this->get_node(5); 00170 face->set_node(3) = this->get_node(6); 00171 00172 break; 00173 } 00174 00175 case 3: // connecting to another infinite element 00176 { 00177 face = new InfQuad4; 00178 00179 face->set_node(0) = this->get_node(2); 00180 face->set_node(1) = this->get_node(3); 00181 face->set_node(2) = this->get_node(6); 00182 face->set_node(3) = this->get_node(7); 00183 00184 break; 00185 } 00186 00187 case 4: // connecting to another infinite element 00188 { 00189 face = new InfQuad4; 00190 00191 face->set_node(0) = this->get_node(3); 00192 face->set_node(1) = this->get_node(0); 00193 face->set_node(2) = this->get_node(7); 00194 face->set_node(3) = this->get_node(4); 00195 00196 break; 00197 } 00198 00199 default: 00200 libmesh_error_msg("Invalid side i = " << i); 00201 } 00202 00203 face->subdomain_id() = this->subdomain_id(); 00204 return UniquePtr<Elem>(face); 00205 } 00206 00207 libmesh_error_msg("We'll never get here!"); 00208 return UniquePtr<Elem>(); 00209 } 00210 00211 00212 UniquePtr<Elem> InfHex8::build_edge (const unsigned int i) const 00213 { 00214 libmesh_assert_less (i, this->n_edges()); 00215 00216 if (i < 4) // base edges 00217 return UniquePtr<Elem>(new SideEdge<Edge2,InfHex8>(this,i)); 00218 // infinite edges 00219 return UniquePtr<Elem>(new SideEdge<InfEdge2,InfHex8>(this,i)); 00220 } 00221 00222 bool InfHex8::contains_point (const Point& p, Real tol) const 00223 { 00224 /* 00225 * For infinite elements with linear base interpolation: 00226 * 00227 * make use of the fact that infinite elements do not 00228 * live inside the envelope. Use a fast scheme to 00229 * check whether point \p p is inside or outside 00230 * our relevant part of the envelope. Note that 00231 * this is not exclusive: only when the distance is less, 00232 * we are safe. Otherwise, we cannot say anything. The 00233 * envelope may be non-spherical, the physical point may lie 00234 * inside the envelope, outside the envelope, or even inside 00235 * this infinite element. Therefore if this fails, 00236 * fall back to the FEInterface::inverse_map() 00237 */ 00238 const Point my_origin (this->origin()); 00239 00240 /* 00241 * determine the minimal distance of the base from the origin 00242 * Use size_sq() instead of size(), it is faster 00243 */ 00244 const Real min_distance_sq = std::min((Point(this->point(0)-my_origin)).size_sq(), 00245 std::min((Point(this->point(1)-my_origin)).size_sq(), 00246 std::min((Point(this->point(2)-my_origin)).size_sq(), 00247 (Point(this->point(3)-my_origin)).size_sq()))); 00248 00249 /* 00250 * work with 1% allowable deviation. We can still fall 00251 * back to the InfFE::inverse_map() 00252 */ 00253 const Real conservative_p_dist_sq = 1.01 * (Point(p-my_origin).size_sq()); 00254 00255 00256 00257 if (conservative_p_dist_sq < min_distance_sq) 00258 { 00259 /* 00260 * the physical point is definitely not contained in the element 00261 */ 00262 return false; 00263 } 00264 else 00265 { 00266 /* 00267 * Declare a basic FEType. Will use default in the base, 00268 * and something else (not important) in radial direction. 00269 */ 00270 FEType fe_type(default_order()); 00271 00272 const Point mapped_point = FEInterface::inverse_map(dim(), 00273 fe_type, 00274 this, 00275 p, 00276 tol, 00277 false); 00278 00279 return FEInterface::on_reference_element(mapped_point, this->type(), tol); 00280 } 00281 } 00282 00283 00284 void InfHex8::connectivity(const unsigned int libmesh_dbg_var(sc), 00285 const IOPackage iop, 00286 std::vector<dof_id_type>& conn) const 00287 { 00288 libmesh_assert(_nodes); 00289 libmesh_assert_less (sc, this->n_sub_elem()); 00290 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); 00291 00292 switch (iop) 00293 { 00294 case TECPLOT: 00295 { 00296 conn.resize(8); 00297 conn[0] = this->node(0)+1; 00298 conn[1] = this->node(1)+1; 00299 conn[2] = this->node(2)+1; 00300 conn[3] = this->node(3)+1; 00301 conn[4] = this->node(4)+1; 00302 conn[5] = this->node(5)+1; 00303 conn[6] = this->node(6)+1; 00304 conn[7] = this->node(7)+1; 00305 return; 00306 } 00307 00308 default: 00309 libmesh_error_msg("Unsupported IO package " << iop); 00310 } 00311 } 00312 00313 00314 00315 #ifdef LIBMESH_ENABLE_AMR 00316 00317 const float InfHex8::_embedding_matrix[4][8][8] = 00318 { 00319 // embedding matrix for child 0 00320 { 00321 // 0 1 2 3 4 5 6 7 th parent N.(ode) 00322 { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0th child N. 00323 { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1 00324 { 0.25, 0.25, 0.25, 0.25, 0.0, 0.0, 0.0, 0.0}, // 2 00325 { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0}, // 3 00326 { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 4 00327 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0}, // 5 00328 { 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 0.25}, // 6 00329 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5} // 7 00330 }, 00331 00332 // embedding matrix for child 1 00333 { 00334 // 0 1 2 3 4 5 6 7 th parent N.(ode) 00335 { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0th child N. 00336 { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1 00337 { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2 00338 { 0.25, 0.25, 0.25, 0.25, 0.0, 0.0, 0.0, 0.0}, // 3 00339 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0}, // 4 00340 { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 5 00341 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 6 00342 { 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 0.25} // 7 00343 }, 00344 00345 // embedding matrix for child 2 00346 { 00347 // 0 1 2 3 4 5 6 7 th parent N.(ode) 00348 { 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0th child N. 00349 { 0.25, 0.25, 0.25, 0.25, 0.0, 0.0, 0.0, 0.0}, // 1 00350 { 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 2 00351 { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 3 00352 { 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5}, // 4 00353 { 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 0.25}, // 5 00354 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 6 00355 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0} // 7 00356 }, 00357 00358 // embedding matrix for child 3 00359 { 00360 // 0 1 2 3 4 5 6 7 th parent N.(ode) 00361 { 0.25, 0.25, 0.25, 0.25, 0.0, 0.0, 0.0, 0.0}, // 0th child N. 00362 { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1 00363 { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2 00364 { 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 3 00365 { 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 0.25}, // 4 00366 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 5 00367 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 6 00368 { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5} // 7 00369 } 00370 }; 00371 00372 00373 00374 #endif 00375 00376 } // namespace libMesh 00377 00378 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS