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