$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 00019 // C++ includes 00020 00021 // Local includes 00022 #include "libmesh/side.h" 00023 #include "libmesh/cell_pyramid5.h" 00024 #include "libmesh/edge_edge2.h" 00025 #include "libmesh/face_tri3.h" 00026 #include "libmesh/face_quad4.h" 00027 00028 namespace libMesh 00029 { 00030 00031 00032 00033 00034 // ------------------------------------------------------------ 00035 // Pyramid5 class static member initializations 00036 const unsigned int Pyramid5::side_nodes_map[5][4] = 00037 { 00038 {0, 1, 4, 99}, // Side 0 00039 {1, 2, 4, 99}, // Side 1 00040 {2, 3, 4, 99}, // Side 2 00041 {3, 0, 4, 99}, // Side 3 00042 {0, 3, 2, 1} // Side 4 00043 }; 00044 00045 const unsigned int Pyramid5::edge_nodes_map[8][2] = 00046 { 00047 {0, 1}, // Side 0 00048 {1, 2}, // Side 1 00049 {2, 3}, // Side 2 00050 {0, 3}, // Side 3 00051 {0, 4}, // Side 4 00052 {1, 4}, // Side 5 00053 {2, 4}, // Side 6 00054 {3, 4} // Side 7 00055 }; 00056 00057 00058 00059 // ------------------------------------------------------------ 00060 // Pyramid5 class member functions 00061 00062 bool Pyramid5::is_vertex(const unsigned int) const 00063 { 00064 return true; 00065 } 00066 00067 bool Pyramid5::is_edge(const unsigned int) const 00068 { 00069 return false; 00070 } 00071 00072 bool Pyramid5::is_face(const unsigned int) const 00073 { 00074 return false; 00075 } 00076 00077 bool Pyramid5::is_node_on_side(const unsigned int n, 00078 const unsigned int s) const 00079 { 00080 libmesh_assert_less (s, n_sides()); 00081 for (unsigned int i = 0; i != 4; ++i) 00082 if (side_nodes_map[s][i] == n) 00083 return true; 00084 return false; 00085 } 00086 00087 bool Pyramid5::is_node_on_edge(const unsigned int n, 00088 const unsigned int e) const 00089 { 00090 libmesh_assert_less (e, n_edges()); 00091 for (unsigned int i = 0; i != 2; ++i) 00092 if (edge_nodes_map[e][i] == n) 00093 return true; 00094 return false; 00095 } 00096 00097 00098 00099 bool Pyramid5::has_affine_map() const 00100 { 00101 // Point v = this->point(3) - this->point(0); 00102 // return (v.relative_fuzzy_equals(this->point(2) - this->point(1))); 00103 return false; 00104 } 00105 00106 00107 00108 UniquePtr<Elem> Pyramid5::build_side (const unsigned int i, 00109 bool proxy) const 00110 { 00111 libmesh_assert_less (i, this->n_sides()); 00112 00113 if (proxy) 00114 { 00115 switch (i) 00116 { 00117 case 0: 00118 case 1: 00119 case 2: 00120 case 3: 00121 return UniquePtr<Elem>(new Side<Tri3,Pyramid5>(this,i)); 00122 00123 case 4: 00124 return UniquePtr<Elem>(new Side<Quad4,Pyramid5>(this,i)); 00125 00126 default: 00127 libmesh_error_msg("Invalid side i = " << i); 00128 } 00129 } 00130 00131 else 00132 { 00133 // Create NULL pointer to be initialized, returned later. 00134 Elem* face = NULL; 00135 00136 switch (i) 00137 { 00138 case 0: // triangular face 1 00139 { 00140 face = new Tri3; 00141 00142 face->set_node(0) = this->get_node(0); 00143 face->set_node(1) = this->get_node(1); 00144 face->set_node(2) = this->get_node(4); 00145 00146 break; 00147 } 00148 case 1: // triangular face 2 00149 { 00150 face = new Tri3; 00151 00152 face->set_node(0) = this->get_node(1); 00153 face->set_node(1) = this->get_node(2); 00154 face->set_node(2) = this->get_node(4); 00155 00156 break; 00157 } 00158 case 2: // triangular face 3 00159 { 00160 face = new Tri3; 00161 00162 face->set_node(0) = this->get_node(2); 00163 face->set_node(1) = this->get_node(3); 00164 face->set_node(2) = this->get_node(4); 00165 00166 break; 00167 } 00168 case 3: // triangular face 4 00169 { 00170 face = new Tri3; 00171 00172 face->set_node(0) = this->get_node(3); 00173 face->set_node(1) = this->get_node(0); 00174 face->set_node(2) = this->get_node(4); 00175 00176 break; 00177 } 00178 case 4: // the quad face at z=0 00179 { 00180 face = new Quad4; 00181 00182 face->set_node(0) = this->get_node(0); 00183 face->set_node(1) = this->get_node(3); 00184 face->set_node(2) = this->get_node(2); 00185 face->set_node(3) = this->get_node(1); 00186 00187 break; 00188 } 00189 default: 00190 libmesh_error_msg("Invalid side i = " << i); 00191 } 00192 00193 face->subdomain_id() = this->subdomain_id(); 00194 return UniquePtr<Elem>(face); 00195 } 00196 00197 libmesh_error_msg("We'll never get here!"); 00198 return UniquePtr<Elem>(); 00199 } 00200 00201 00202 00203 UniquePtr<Elem> Pyramid5::build_edge (const unsigned int i) const 00204 { 00205 libmesh_assert_less (i, this->n_edges()); 00206 00207 return UniquePtr<Elem>(new SideEdge<Edge2,Pyramid5>(this,i)); 00208 } 00209 00210 00211 00212 void Pyramid5::connectivity(const unsigned int libmesh_dbg_var(sc), 00213 const IOPackage iop, 00214 std::vector<dof_id_type>& conn) const 00215 { 00216 libmesh_assert(_nodes); 00217 libmesh_assert_less (sc, this->n_sub_elem()); 00218 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); 00219 00220 switch (iop) 00221 { 00222 case TECPLOT: 00223 { 00224 conn.resize(8); 00225 conn[0] = this->node(0)+1; 00226 conn[1] = this->node(1)+1; 00227 conn[2] = this->node(2)+1; 00228 conn[3] = this->node(3)+1; 00229 conn[4] = this->node(4)+1; 00230 conn[5] = this->node(4)+1; 00231 conn[6] = this->node(4)+1; 00232 conn[7] = this->node(4)+1; 00233 return; 00234 } 00235 00236 case VTK: 00237 { 00238 conn.resize(5); 00239 conn[0] = this->node(3); 00240 conn[1] = this->node(2); 00241 conn[2] = this->node(1); 00242 conn[3] = this->node(0); 00243 conn[4] = this->node(4); 00244 return; 00245 } 00246 00247 default: 00248 libmesh_error_msg("Unsupported IO package " << iop); 00249 } 00250 } 00251 00252 00253 Real Pyramid5::volume () const 00254 { 00255 // The pyramid with a bilinear base has volume given by the 00256 // formula in: "Calculation of the Volume of a General Hexahedron 00257 // for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954- 00258 Node* node0 = this->get_node(0); 00259 Node* node1 = this->get_node(1); 00260 Node* node2 = this->get_node(2); 00261 Node* node3 = this->get_node(3); 00262 Node* node4 = this->get_node(4); 00263 00264 // Construct Various edge and diagonal vectors 00265 Point v40 ( *node0 - *node4 ); 00266 Point v13 ( *node3 - *node1 ); 00267 Point v02 ( *node2 - *node0 ); 00268 Point v03 ( *node3 - *node0 ); 00269 Point v01 ( *node1 - *node0 ); 00270 00271 // Finally, ready to return the volume! 00272 return (1./6.)*(v40*(v13.cross(v02))) + (1./12.)*(v02*(v01.cross(v03))); 00273 } 00274 00275 } // namespace libMesh