$extrastylesheet
face_quad8.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_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