$extrastylesheet
face_quad4.C
Go to the documentation of this file.
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_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 UniquePtr<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     return UniquePtr<Elem>(new Side<Edge2,Quad4>(this,i));
00134 
00135   else
00136     {
00137       Elem * edge = new Edge2;
00138       edge->subdomain_id() = this->subdomain_id();
00139 
00140       switch (i)
00141         {
00142         case 0:
00143           {
00144             edge->set_node(0) = this->get_node(0);
00145             edge->set_node(1) = this->get_node(1);
00146             break;
00147           }
00148         case 1:
00149           {
00150             edge->set_node(0) = this->get_node(1);
00151             edge->set_node(1) = this->get_node(2);
00152             break;
00153           }
00154         case 2:
00155           {
00156             edge->set_node(0) = this->get_node(2);
00157             edge->set_node(1) = this->get_node(3);
00158             break;
00159           }
00160         case 3:
00161           {
00162             edge->set_node(0) = this->get_node(3);
00163             edge->set_node(1) = this->get_node(0);
00164             break;
00165           }
00166         default:
00167           libmesh_error_msg("Invalid side i = " << i);
00168         }
00169 
00170       return UniquePtr<Elem>(edge);
00171     }
00172 
00173   libmesh_error_msg("We'll never get here!");
00174   return UniquePtr<Elem>();
00175 }
00176 
00177 
00178 
00179 
00180 
00181 void Quad4::connectivity(const unsigned int libmesh_dbg_var(sf),
00182                          const IOPackage iop,
00183                          std::vector<dof_id_type>& conn) const
00184 {
00185   libmesh_assert_less (sf, this->n_sub_elem());
00186   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
00187 
00188   // Create storage.
00189   conn.resize(4);
00190 
00191   switch (iop)
00192     {
00193     case TECPLOT:
00194       {
00195         conn[0] = this->node(0)+1;
00196         conn[1] = this->node(1)+1;
00197         conn[2] = this->node(2)+1;
00198         conn[3] = this->node(3)+1;
00199         return;
00200       }
00201 
00202     case VTK:
00203       {
00204         conn[0] = this->node(0);
00205         conn[1] = this->node(1);
00206         conn[2] = this->node(2);
00207         conn[3] = this->node(3);
00208         return;
00209       }
00210 
00211     default:
00212       libmesh_error_msg("Unsupported IO package " << iop);
00213     }
00214 }
00215 
00216 
00217 
00218 Real Quad4::volume () const
00219 {
00220   // The A,B,C,D naming scheme here corresponds exactly to the
00221   // libmesh counter-clockwise numbering scheme.
00222 
00223   //        3           2        D           C
00224   // QUAD4: o-----------o        o-----------o
00225   //        |           |        |           |
00226   //        |           |        |           |
00227   //        |           |        |           |
00228   //        |           |        |           |
00229   //        |           |        |           |
00230   //        o-----------o        o-----------o
00231   //        0           1        A           B
00232 
00233   // Vector pointing from A to C
00234   Point AC ( this->point(2) - this->point(0) );
00235 
00236   // Vector pointing from A to B
00237   Point AB ( this->point(1) - this->point(0) );
00238 
00239   // Vector pointing from A to D
00240   Point AD ( this->point(3) - this->point(0) );
00241 
00242   // The diagonal vector minus the side vectors
00243   Point AC_AB_AD (AC - AB - AD);
00244 
00245   // Check for quick return for planar QUAD4.  This will
00246   // be the most common case, occuring for all purely 2D meshes.
00247   if (AC_AB_AD == Point(0.,0.,0.))
00248     return AB.cross(AD).size();
00249 
00250   else
00251     {
00252       // Use 2x2 quadrature to approximate the surface area.  (The
00253       // true integral is too difficult to compute analytically.)  The
00254       // accuracy here is exactly the same as would be obtained via a
00255       // call to Elem::volume(), however it is a bit more optimized to
00256       // do it this way.  The technique used is to integrate the magnitude
00257       // of the normal vector over the whole area.  See for example,
00258       //
00259       // Y. Zhang, C. Bajaj, G. Xu. Surface Smoothing and Quality
00260       // Improvement of Quadrilateral/Hexahedral Meshes with Geometric
00261       // Flow. The special issue of the Journal Communications in
00262       // Numerical Methods in Engineering (CNME), submitted as an
00263       // invited paper, 2006.
00264       // http://www.ices.utexas.edu/~jessica/paper/quadhexgf/quadhex_geomflow_CNM.pdf
00265 
00266       // 4-point rule
00267       const Real q[2] = {0.5 - std::sqrt(3.) / 6.,
00268                          0.5 + std::sqrt(3.) / 6.};
00269 
00270       Real vol=0.;
00271       for (unsigned int i=0; i<2; ++i)
00272         for (unsigned int j=0; j<2; ++j)
00273           vol += (AB + q[i]*AC_AB_AD).cross(AD + q[j]*AC_AB_AD).size();
00274 
00275       return 0.25*vol;
00276     }
00277 }
00278 
00279 } // namespace libMesh