$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 // C++ includes 00019 00020 // Local includes 00021 #include "libmesh/side.h" 00022 #include "libmesh/edge_edge3.h" 00023 #include "libmesh/face_quad8.h" 00024 00025 namespace libMesh 00026 { 00027 00028 00029 00030 00031 // ------------------------------------------------------------ 00032 // Quad8 class static member initializations 00033 const unsigned int Quad8::side_nodes_map[4][3] = 00034 { 00035 {0, 1, 4}, // Side 0 00036 {1, 2, 5}, // Side 1 00037 {2, 3, 6}, // Side 2 00038 {3, 0, 7} // Side 3 00039 }; 00040 00041 00042 #ifdef LIBMESH_ENABLE_AMR 00043 00044 const float Quad8::_embedding_matrix[4][8][8] = 00045 { 00046 // embedding matrix for child 0 00047 { 00048 // 0 1 2 3 4 5 6 7 00049 { 1.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000 }, // 0 00050 { 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.00000, 0.00000 }, // 1 00051 { -0.250000, -0.250000, -0.250000, -0.250000, 0.500000, 0.500000, 0.500000, 0.500000 }, // 2 00052 { 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000 }, // 3 00053 { 0.375000, -0.125000, 0.00000, 0.00000, 0.750000, 0.00000, 0.00000, 0.00000 }, // 4 00054 { -0.187500, -0.187500, -0.187500, -0.187500, 0.750000, 0.375000, 0.250000, 0.375000 }, // 5 00055 { -0.187500, -0.187500, -0.187500, -0.187500, 0.375000, 0.250000, 0.375000, 0.750000 }, // 6 00056 { 0.375000, 0.00000, 0.00000, -0.125000, 0.00000, 0.00000, 0.00000, 0.750000 } // 7 00057 }, 00058 00059 // embedding matrix for child 1 00060 { 00061 // 0 1 2 3 4 5 6 7 00062 { 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.00000, 0.00000 }, // 0 00063 { 0.00000, 1.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000 }, // 1 00064 { 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.00000 }, // 2 00065 { -0.250000, -0.250000, -0.250000, -0.250000, 0.500000, 0.500000, 0.500000, 0.500000 }, // 3 00066 { -0.125000, 0.375000, 0.00000, 0.00000, 0.750000, 0.00000, 0.00000, 0.00000 }, // 4 00067 { 0.00000, 0.375000, -0.125000, 0.00000, 0.00000, 0.750000, 0.00000, 0.00000 }, // 5 00068 { -0.187500, -0.187500, -0.187500, -0.187500, 0.375000, 0.750000, 0.375000, 0.250000 }, // 6 00069 { -0.187500, -0.187500, -0.187500, -0.187500, 0.750000, 0.375000, 0.250000, 0.375000 } // 7 00070 }, 00071 00072 // embedding matrix for child 2 00073 { 00074 // 0 1 2 3 4 5 6 7 00075 { 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000 }, // 0 00076 { -0.250000, -0.250000, -0.250000, -0.250000, 0.500000, 0.500000, 0.500000, 0.500000 }, // 1 00077 { 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000 }, // 2 00078 { 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.00000, 0.00000, 0.00000 }, // 3 00079 { -0.187500, -0.187500, -0.187500, -0.187500, 0.375000, 0.250000, 0.375000, 0.750000 }, // 4 00080 { -0.187500, -0.187500, -0.187500, -0.187500, 0.250000, 0.375000, 0.750000, 0.375000 }, // 5 00081 { 0.00000, 0.00000, -0.125000, 0.375000, 0.00000, 0.00000, 0.750000, 0.00000 }, // 6 00082 { -0.125000, 0.00000, 0.00000, 0.375000, 0.00000, 0.00000, 0.00000, 0.750000 } // 7 00083 }, 00084 00085 // embedding matrix for child 3 00086 { 00087 // 0 1 2 3 4 5 6 7 00088 { -0.250000, -0.250000, -0.250000, -0.250000, 0.500000, 0.500000, 0.500000, 0.500000 }, // 0 00089 { 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000, 0.00000 }, // 1 00090 { 0.00000, 0.00000, 1.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000 }, // 2 00091 { 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000, 0.00000 }, // 3 00092 { -0.187500, -0.187500, -0.187500, -0.187500, 0.375000, 0.750000, 0.375000, 0.250000 }, // 4 00093 { 0.00000, -0.125000, 0.375000, 0.00000, 0.00000, 0.750000, 0.00000, 0.00000 }, // 5 00094 { 0.00000, 0.00000, 0.375000, -0.125000, 0.00000, 0.00000, 0.750000, 0.00000 }, // 6 00095 { -0.187500, -0.187500, -0.187500, -0.187500, 0.250000, 0.375000, 0.750000, 0.375000 } // 7 00096 } 00097 }; 00098 00099 00100 #endif 00101 00102 00103 // ------------------------------------------------------------ 00104 // Quad8 class member functions 00105 00106 bool Quad8::is_vertex(const unsigned int i) const 00107 { 00108 if (i < 4) 00109 return true; 00110 return false; 00111 } 00112 00113 bool Quad8::is_edge(const unsigned int i) const 00114 { 00115 if (i < 4) 00116 return false; 00117 return true; 00118 } 00119 00120 bool Quad8::is_face(const unsigned int) const 00121 { 00122 return false; 00123 } 00124 00125 bool Quad8::is_node_on_side(const unsigned int n, 00126 const unsigned int s) const 00127 { 00128 libmesh_assert_less (s, n_sides()); 00129 for (unsigned int i = 0; i != 3; ++i) 00130 if (side_nodes_map[s][i] == n) 00131 return true; 00132 return false; 00133 } 00134 00135 00136 00137 bool Quad8::has_affine_map() const 00138 { 00139 // make sure corners form a parallelogram 00140 Point v = this->point(1) - this->point(0); 00141 if (!v.relative_fuzzy_equals(this->point(2) - this->point(3))) 00142 return false; 00143 // make sure sides are straight 00144 v /= 2; 00145 if (!v.relative_fuzzy_equals(this->point(4) - this->point(0)) || 00146 !v.relative_fuzzy_equals(this->point(6) - this->point(3))) 00147 return false; 00148 v = (this->point(3) - this->point(0))/2; 00149 if (!v.relative_fuzzy_equals(this->point(7) - this->point(0)) || 00150 !v.relative_fuzzy_equals(this->point(5) - this->point(1))) 00151 return false; 00152 return true; 00153 } 00154 00155 00156 00157 dof_id_type Quad8::key (const unsigned int s) const 00158 { 00159 libmesh_assert_less (s, this->n_sides()); 00160 00161 switch (s) 00162 { 00163 case 0: 00164 00165 return 00166 this->compute_key (this->node(4)); 00167 00168 case 1: 00169 00170 return 00171 this->compute_key (this->node(5)); 00172 00173 case 2: 00174 00175 return 00176 this->compute_key (this->node(6)); 00177 00178 case 3: 00179 00180 return 00181 this->compute_key (this->node(7)); 00182 00183 default: 00184 libmesh_error_msg("Invalid side s = " << s); 00185 } 00186 00187 libmesh_error_msg("We'll never get here!"); 00188 return 0; 00189 } 00190 00191 00192 00193 UniquePtr<Elem> Quad8::build_side (const unsigned int i, 00194 bool proxy) const 00195 { 00196 libmesh_assert_less (i, this->n_sides()); 00197 00198 if (proxy) 00199 return UniquePtr<Elem>(new Side<Edge3,Quad8>(this,i)); 00200 00201 else 00202 { 00203 Elem* edge = new Edge3; 00204 edge->subdomain_id() = this->subdomain_id(); 00205 00206 switch (i) 00207 { 00208 case 0: 00209 { 00210 edge->set_node(0) = this->get_node(0); 00211 edge->set_node(1) = this->get_node(1); 00212 edge->set_node(2) = this->get_node(4); 00213 break; 00214 } 00215 case 1: 00216 { 00217 edge->set_node(0) = this->get_node(1); 00218 edge->set_node(1) = this->get_node(2); 00219 edge->set_node(2) = this->get_node(5); 00220 break; 00221 } 00222 case 2: 00223 { 00224 edge->set_node(0) = this->get_node(2); 00225 edge->set_node(1) = this->get_node(3); 00226 edge->set_node(2) = this->get_node(6); 00227 break; 00228 } 00229 case 3: 00230 { 00231 edge->set_node(0) = this->get_node(3); 00232 edge->set_node(1) = this->get_node(0); 00233 edge->set_node(2) = this->get_node(7); 00234 break; 00235 } 00236 default: 00237 libmesh_error_msg("Invalid side i = " << i); 00238 } 00239 00240 return UniquePtr<Elem>(edge); 00241 } 00242 00243 libmesh_error_msg("We'll never get here!"); 00244 return UniquePtr<Elem>(); 00245 } 00246 00247 00248 00249 00250 00251 00252 void Quad8::connectivity(const unsigned int sf, 00253 const IOPackage iop, 00254 std::vector<dof_id_type>& conn) const 00255 { 00256 libmesh_assert_less (sf, this->n_sub_elem()); 00257 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); 00258 00259 switch (iop) 00260 { 00261 // Note: TECPLOT connectivity is output as four triangles with 00262 // a central quadrilateral. Therefore, the first four connectivity 00263 // arrays are degenerate quads (triangles in Tecplot). 00264 case TECPLOT: 00265 { 00266 // Create storage 00267 conn.resize(4); 00268 00269 switch(sf) 00270 { 00271 case 0: 00272 // linear sub-tri 0 00273 conn[0] = this->node(0)+1; 00274 conn[1] = this->node(4)+1; 00275 conn[2] = this->node(7)+1; 00276 conn[3] = this->node(7)+1; 00277 00278 return; 00279 00280 case 1: 00281 // linear sub-tri 1 00282 conn[0] = this->node(4)+1; 00283 conn[1] = this->node(1)+1; 00284 conn[2] = this->node(5)+1; 00285 conn[3] = this->node(5)+1; 00286 00287 return; 00288 00289 case 2: 00290 // linear sub-tri 2 00291 conn[0] = this->node(5)+1; 00292 conn[1] = this->node(2)+1; 00293 conn[2] = this->node(6)+1; 00294 conn[3] = this->node(6)+1; 00295 00296 return; 00297 00298 case 3: 00299 // linear sub-tri 3 00300 conn[0] = this->node(7)+1; 00301 conn[1] = this->node(6)+1; 00302 conn[2] = this->node(3)+1; 00303 conn[3] = this->node(3)+1; 00304 00305 return; 00306 00307 case 4: 00308 // linear sub-quad 00309 conn[0] = this->node(4)+1; 00310 conn[1] = this->node(5)+1; 00311 conn[2] = this->node(6)+1; 00312 conn[3] = this->node(7)+1; 00313 00314 return; 00315 00316 default: 00317 libmesh_error_msg("Invalid sf = " << sf); 00318 } 00319 } 00320 00321 00322 // Note: VTK connectivity is output as four triangles with 00323 // a central quadrilateral. Therefore most of the connectivity 00324 // arrays have length three. 00325 case VTK: 00326 { 00327 // Create storage 00328 conn.resize(8); 00329 conn[0] = this->node(0); 00330 conn[1] = this->node(1); 00331 conn[2] = this->node(2); 00332 conn[3] = this->node(3); 00333 conn[4] = this->node(4); 00334 conn[5] = this->node(5); 00335 conn[6] = this->node(6); 00336 conn[7] = this->node(7); 00337 return; 00338 /* 00339 conn.resize(3); 00340 00341 switch (sf) 00342 { 00343 case 0: 00344 // linear sub-tri 0 00345 conn[0] = this->node(0); 00346 conn[1] = this->node(4); 00347 conn[2] = this->node(7); 00348 00349 return; 00350 00351 case 1: 00352 // linear sub-tri 1 00353 conn[0] = this->node(4); 00354 conn[1] = this->node(1); 00355 conn[2] = this->node(5); 00356 00357 return; 00358 00359 case 2: 00360 // linear sub-tri 2 00361 conn[0] = this->node(5); 00362 conn[1] = this->node(2); 00363 conn[2] = this->node(6); 00364 00365 return; 00366 00367 case 3: 00368 // linear sub-tri 3 00369 conn[0] = this->node(7); 00370 conn[1] = this->node(6); 00371 conn[2] = this->node(3); 00372 00373 return; 00374 00375 case 4: 00376 conn.resize(4); 00377 00378 // linear sub-quad 00379 conn[0] = this->node(4); 00380 conn[1] = this->node(5); 00381 conn[2] = this->node(6); 00382 conn[3] = this->node(7); 00383 */ 00384 // return; 00385 00386 // default: 00387 // libmesh_error_msg("Invalid sf = " << sf); 00388 // } 00389 } 00390 00391 default: 00392 libmesh_error_msg("Unsupported IO package " << iop); 00393 } 00394 } 00395 00396 00397 00398 00399 unsigned short int Quad8::second_order_adjacent_vertex (const unsigned int n, 00400 const unsigned int v) const 00401 { 00402 libmesh_assert_greater_equal (n, this->n_vertices()); 00403 libmesh_assert_less (n, this->n_nodes()); 00404 libmesh_assert_less (v, 2); 00405 // use the matrix from \p face_quad.C 00406 return _second_order_adjacent_vertices[n-this->n_vertices()][v]; 00407 } 00408 00409 00410 00411 std::pair<unsigned short int, unsigned short int> 00412 Quad8::second_order_child_vertex (const unsigned int n) const 00413 { 00414 libmesh_assert_greater_equal (n, this->n_vertices()); 00415 libmesh_assert_less (n, this->n_nodes()); 00416 /* 00417 * the _second_order_vertex_child_* vectors are 00418 * stored in face_quad.C, since they are identical 00419 * for Quad8 and Quad9 (for the first 4 higher-order nodes) 00420 */ 00421 return std::pair<unsigned short int, unsigned short int> 00422 (_second_order_vertex_child_number[n], 00423 _second_order_vertex_child_index[n]); 00424 } 00425 00426 } // namespace libMesh