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