face_quad4.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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_edge2.h" 00023 #include "libmesh/face_quad4.h" 00024 00025 namespace libMesh 00026 { 00027 00028 00029 00030 00031 // ------------------------------------------------------------ 00032 // Quad class static member initialization 00033 const unsigned int Quad4::side_nodes_map[4][2] = 00034 { 00035 {0, 1}, // Side 0 00036 {1, 2}, // Side 1 00037 {2, 3}, // Side 2 00038 {3, 0} // Side 3 00039 }; 00040 00041 00042 #ifdef LIBMESH_ENABLE_AMR 00043 00044 const float Quad4::_embedding_matrix[4][4][4] = 00045 { 00046 // embedding matrix for child 0 00047 { 00048 // 0 1 2 3 00049 {1.0, 0.0, 0.0, 0.0}, // 0 00050 {0.5, 0.5, 0.0, 0.0}, // 1 00051 {.25, .25, .25, .25}, // 2 00052 {0.5, 0.0, 0.0, 0.5} // 3 00053 }, 00054 00055 // embedding matrix for child 1 00056 { 00057 // 0 1 2 3 00058 {0.5, 0.5, 0.0, 0.0}, // 0 00059 {0.0, 1.0, 0.0, 0.0}, // 1 00060 {0.0, 0.5, 0.5, 0.0}, // 2 00061 {.25, .25, .25, .25} // 3 00062 }, 00063 00064 // embedding matrix for child 2 00065 { 00066 // 0 1 2 3 00067 {0.5, 0.0, 0.0, 0.5}, // 0 00068 {.25, .25, .25, .25}, // 1 00069 {0.0, 0.0, 0.5, 0.5}, // 2 00070 {0.0, 0.0, 0.0, 1.0} // 3 00071 }, 00072 00073 // embedding matrix for child 3 00074 { 00075 // 0 1 2 3 00076 {.25, .25, .25, .25}, // 0 00077 {0.0, 0.5, 0.5, 0.0}, // 1 00078 {0.0, 0.0, 1.0, 0.0}, // 2 00079 {0.0, 0.0, 0.5, 0.5} // 3 00080 } 00081 }; 00082 00083 #endif 00084 00085 00086 00087 00088 00089 // ------------------------------------------------------------ 00090 // Quad4 class member functions 00091 00092 bool Quad4::is_vertex(const unsigned int) const 00093 { 00094 return true; 00095 } 00096 00097 bool Quad4::is_edge(const unsigned int) const 00098 { 00099 return false; 00100 } 00101 00102 bool Quad4::is_face(const unsigned int) const 00103 { 00104 return false; 00105 } 00106 00107 bool Quad4::is_node_on_side(const unsigned int n, 00108 const unsigned int s) const 00109 { 00110 libmesh_assert_less (s, n_sides()); 00111 for (unsigned int i = 0; i != 2; ++i) 00112 if (side_nodes_map[s][i] == n) 00113 return true; 00114 return false; 00115 } 00116 00117 00118 00119 bool Quad4::has_affine_map() const 00120 { 00121 Point v = this->point(3) - this->point(0); 00122 return (v.relative_fuzzy_equals(this->point(2) - this->point(1))); 00123 } 00124 00125 00126 00127 AutoPtr<Elem> Quad4::build_side (const unsigned int i, 00128 bool proxy) const 00129 { 00130 libmesh_assert_less (i, this->n_sides()); 00131 00132 if (proxy) 00133 { 00134 AutoPtr<Elem> ap(new Side<Edge2,Quad4>(this,i)); 00135 return ap; 00136 } 00137 00138 else 00139 { 00140 00141 switch (i) 00142 { 00143 case 0: 00144 { 00145 Edge2* edge = new Edge2; 00146 00147 edge->set_node(0) = this->get_node(0); 00148 edge->set_node(1) = this->get_node(1); 00149 00150 AutoPtr<Elem> ap(edge); return ap; 00151 } 00152 case 1: 00153 { 00154 Edge2* edge = new Edge2; 00155 00156 edge->set_node(0) = this->get_node(1); 00157 edge->set_node(1) = this->get_node(2); 00158 00159 AutoPtr<Elem> ap(edge); return ap; 00160 } 00161 case 2: 00162 { 00163 Edge2* edge = new Edge2; 00164 00165 edge->set_node(0) = this->get_node(2); 00166 edge->set_node(1) = this->get_node(3); 00167 00168 AutoPtr<Elem> ap(edge); return ap; 00169 } 00170 case 3: 00171 { 00172 Edge2* edge = new Edge2; 00173 00174 edge->set_node(0) = this->get_node(3); 00175 edge->set_node(1) = this->get_node(0); 00176 00177 AutoPtr<Elem> ap(edge); return ap; 00178 } 00179 default: 00180 { 00181 libmesh_error(); 00182 } 00183 } 00184 } 00185 00186 // We will never get here... 00187 AutoPtr<Elem> ap(NULL); return ap; 00188 } 00189 00190 00191 00192 00193 00194 void Quad4::connectivity(const unsigned int libmesh_dbg_var(sf), 00195 const IOPackage iop, 00196 std::vector<dof_id_type>& conn) const 00197 { 00198 libmesh_assert_less (sf, this->n_sub_elem()); 00199 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); 00200 00201 // Create storage. 00202 conn.resize(4); 00203 00204 switch (iop) 00205 { 00206 case TECPLOT: 00207 { 00208 conn[0] = this->node(0)+1; 00209 conn[1] = this->node(1)+1; 00210 conn[2] = this->node(2)+1; 00211 conn[3] = this->node(3)+1; 00212 return; 00213 } 00214 00215 case VTK: 00216 { 00217 conn[0] = this->node(0); 00218 conn[1] = this->node(1); 00219 conn[2] = this->node(2); 00220 conn[3] = this->node(3); 00221 return; 00222 } 00223 00224 default: 00225 libmesh_error(); 00226 } 00227 00228 libmesh_error(); 00229 } 00230 00231 00232 00233 Real Quad4::volume () const 00234 { 00235 // The A,B,C,D naming scheme here corresponds exactly to the 00236 // libmesh counter-clockwise numbering scheme. 00237 00238 // 3 2 D C 00239 // QUAD4: o-----------o o-----------o 00240 // | | | | 00241 // | | | | 00242 // | | | | 00243 // | | | | 00244 // | | | | 00245 // o-----------o o-----------o 00246 // 0 1 A B 00247 00248 // Vector pointing from A to C 00249 Point AC ( this->point(2) - this->point(0) ); 00250 00251 // Vector pointing from A to B 00252 Point AB ( this->point(1) - this->point(0) ); 00253 00254 // Vector pointing from A to D 00255 Point AD ( this->point(3) - this->point(0) ); 00256 00257 // The diagonal vector minus the side vectors 00258 Point AC_AB_AD (AC - AB - AD); 00259 00260 // Check for quick return for planar QUAD4. This will 00261 // be the most common case, occuring for all purely 2D meshes. 00262 if (AC_AB_AD == Point(0.,0.,0.)) 00263 return AB.cross(AD).size(); 00264 00265 else 00266 { 00267 // Use 2x2 quadrature to approximate the surface area. (The 00268 // true integral is too difficult to compute analytically.) The 00269 // accuracy here is exactly the same as would be obtained via a 00270 // call to Elem::volume(), however it is a bit more optimized to 00271 // do it this way. The technique used is to integrate the magnitude 00272 // of the normal vector over the whole area. See for example, 00273 // 00274 // Y. Zhang, C. Bajaj, G. Xu. Surface Smoothing and Quality 00275 // Improvement of Quadrilateral/Hexahedral Meshes with Geometric 00276 // Flow. The special issue of the Journal Communications in 00277 // Numerical Methods in Engineering (CNME), submitted as an 00278 // invited paper, 2006. 00279 // http://www.ices.utexas.edu/~jessica/paper/quadhexgf/quadhex_geomflow_CNM.pdf 00280 00281 // 4-point rule 00282 const Real q[2] = {0.5 - std::sqrt(3.) / 6., 00283 0.5 + std::sqrt(3.) / 6.}; 00284 00285 Real vol=0.; 00286 for (unsigned int i=0; i<2; ++i) 00287 for (unsigned int j=0; j<2; ++j) 00288 vol += (AB + q[i]*AC_AB_AD).cross(AD + q[j]*AC_AB_AD).size(); 00289 00290 return 0.25*vol; 00291 } 00292 } 00293 00294 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: