$extrastylesheet
cell_inf_hex8.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 // Local includes
00019 #include "libmesh/libmesh_config.h"
00020 
00021 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00022 
00023 // C++ includes
00024 
00025 // Local includes cont'd
00026 #include "libmesh/cell_inf_hex8.h"
00027 #include "libmesh/edge_edge2.h"
00028 #include "libmesh/edge_inf_edge2.h"
00029 #include "libmesh/face_quad4.h"
00030 #include "libmesh/face_inf_quad4.h"
00031 #include "libmesh/fe_interface.h"
00032 #include "libmesh/fe_type.h"
00033 #include "libmesh/side.h"
00034 
00035 namespace libMesh
00036 {
00037 
00038 
00039 // ------------------------------------------------------------
00040 // InfHex8 class member functions
00041 const unsigned int InfHex8::side_nodes_map[5][4] =
00042   {
00043     { 0, 1, 2, 3}, // Side 0
00044     { 0, 1, 4, 5}, // Side 1
00045     { 1, 2, 5, 6}, // Side 2
00046     { 2, 3, 6, 7}, // Side 3
00047     { 3, 0, 7, 4}  // Side 4
00048   };
00049 
00050 const unsigned int InfHex8::edge_nodes_map[8][2] =
00051   {
00052     { 0, 1}, // Side 0
00053     { 1, 2}, // Side 1
00054     { 2, 3}, // Side 2
00055     { 0, 3}, // Side 3
00056     { 0, 4}, // Side 4
00057     { 1, 5}, // Side 5
00058     { 2, 6}, // Side 6
00059     { 3, 7}  // Side 7
00060   };
00061 
00062 
00063 // ------------------------------------------------------------
00064 // InfHex8 class member functions
00065 
00066 bool InfHex8::is_vertex(const unsigned int i) const
00067 {
00068   if (i < 4)
00069     return true;
00070   return false;
00071 }
00072 
00073 bool InfHex8::is_edge(const unsigned int i) const
00074 {
00075   if (i < 4)
00076     return false;
00077   return true;
00078 }
00079 
00080 bool InfHex8::is_face(const unsigned int) const
00081 {
00082   return false;
00083 }
00084 
00085 bool InfHex8::is_node_on_side(const unsigned int n,
00086                               const unsigned int s) const
00087 {
00088   libmesh_assert_less (s, n_sides());
00089   for (unsigned int i = 0; i != 4; ++i)
00090     if (side_nodes_map[s][i] == n)
00091       return true;
00092   return false;
00093 }
00094 
00095 bool InfHex8::is_node_on_edge(const unsigned int n,
00096                               const unsigned int e) const
00097 {
00098   libmesh_assert_less (e, n_edges());
00099   for (unsigned int i = 0; i != 2; ++i)
00100     if (edge_nodes_map[e][i] == n)
00101       return true;
00102   return false;
00103 }
00104 
00105 UniquePtr<Elem> InfHex8::build_side (const unsigned int i,
00106                                      bool proxy) const
00107 {
00108   libmesh_assert_less (i, this->n_sides());
00109 
00110   if (proxy)
00111     {
00112       switch (i)
00113         {
00114           // base
00115         case 0:
00116           return UniquePtr<Elem>(new Side<Quad4,InfHex8>(this,i));
00117 
00118           // ifem sides
00119         case 1:
00120         case 2:
00121         case 3:
00122         case 4:
00123           return UniquePtr<Elem>(new Side<InfQuad4,InfHex8>(this,i));
00124 
00125         default:
00126           libmesh_error_msg("Invalid side i = " << i);
00127         }
00128     }
00129 
00130   else
00131     {
00132       // Create NULL pointer to be initialized, returned later.
00133       Elem* face = NULL;
00134 
00135       // Think of a unit cube: (-1,1) x (-1,1) x (1,1)
00136       switch (i)
00137         {
00138         case 0: // the base face
00139           {
00140             face = new Quad4;
00141 
00142             // Only here, the face element's normal points inward
00143             face->set_node(0) = this->get_node(0);
00144             face->set_node(1) = this->get_node(1);
00145             face->set_node(2) = this->get_node(2);
00146             face->set_node(3) = this->get_node(3);
00147 
00148             break;
00149           }
00150 
00151         case 1:  // connecting to another infinite element
00152           {
00153             face = new InfQuad4;
00154 
00155             face->set_node(0) = this->get_node(0);
00156             face->set_node(1) = this->get_node(1);
00157             face->set_node(2) = this->get_node(4);
00158             face->set_node(3) = this->get_node(5);
00159 
00160             break;
00161           }
00162 
00163         case 2:  // connecting to another infinite element
00164           {
00165             face = new InfQuad4;
00166 
00167             face->set_node(0) = this->get_node(1);
00168             face->set_node(1) = this->get_node(2);
00169             face->set_node(2) = this->get_node(5);
00170             face->set_node(3) = this->get_node(6);
00171 
00172             break;
00173           }
00174 
00175         case 3:  // connecting to another infinite element
00176           {
00177             face = new InfQuad4;
00178 
00179             face->set_node(0) = this->get_node(2);
00180             face->set_node(1) = this->get_node(3);
00181             face->set_node(2) = this->get_node(6);
00182             face->set_node(3) = this->get_node(7);
00183 
00184             break;
00185           }
00186 
00187         case 4:  // connecting to another infinite element
00188           {
00189             face = new InfQuad4;
00190 
00191             face->set_node(0) = this->get_node(3);
00192             face->set_node(1) = this->get_node(0);
00193             face->set_node(2) = this->get_node(7);
00194             face->set_node(3) = this->get_node(4);
00195 
00196             break;
00197           }
00198 
00199         default:
00200           libmesh_error_msg("Invalid side i = " << i);
00201         }
00202 
00203       face->subdomain_id() = this->subdomain_id();
00204       return UniquePtr<Elem>(face);
00205     }
00206 
00207   libmesh_error_msg("We'll never get here!");
00208   return UniquePtr<Elem>();
00209 }
00210 
00211 
00212 UniquePtr<Elem> InfHex8::build_edge (const unsigned int i) const
00213 {
00214   libmesh_assert_less (i, this->n_edges());
00215 
00216   if (i < 4) // base edges
00217     return UniquePtr<Elem>(new SideEdge<Edge2,InfHex8>(this,i));
00218   // infinite edges
00219   return UniquePtr<Elem>(new SideEdge<InfEdge2,InfHex8>(this,i));
00220 }
00221 
00222 bool InfHex8::contains_point (const Point& p, Real tol) const
00223 {
00224   /*
00225    * For infinite elements with linear base interpolation:
00226    *
00227    * make use of the fact that infinite elements do not
00228    * live inside the envelope.  Use a fast scheme to
00229    * check whether point \p p is inside or outside
00230    * our relevant part of the envelope.  Note that
00231    * this is not exclusive: only when the distance is less,
00232    * we are safe.  Otherwise, we cannot say anything. The
00233    * envelope may be non-spherical, the physical point may lie
00234    * inside the envelope, outside the envelope, or even inside
00235    * this infinite element.  Therefore if this fails,
00236    * fall back to the FEInterface::inverse_map()
00237    */
00238   const Point my_origin (this->origin());
00239 
00240   /*
00241    * determine the minimal distance of the base from the origin
00242    * Use size_sq() instead of size(), it is faster
00243    */
00244   const Real min_distance_sq = std::min((Point(this->point(0)-my_origin)).size_sq(),
00245                                         std::min((Point(this->point(1)-my_origin)).size_sq(),
00246                                                  std::min((Point(this->point(2)-my_origin)).size_sq(),
00247                                                           (Point(this->point(3)-my_origin)).size_sq())));
00248 
00249   /*
00250    * work with 1% allowable deviation.  We can still fall
00251    * back to the InfFE::inverse_map()
00252    */
00253   const Real conservative_p_dist_sq = 1.01 * (Point(p-my_origin).size_sq());
00254 
00255 
00256 
00257   if (conservative_p_dist_sq < min_distance_sq)
00258     {
00259       /*
00260        * the physical point is definitely not contained in the element
00261        */
00262       return false;
00263     }
00264   else
00265     {
00266       /*
00267        * Declare a basic FEType.  Will use default in the base,
00268        * and something else (not important) in radial direction.
00269        */
00270       FEType fe_type(default_order());
00271 
00272       const Point mapped_point = FEInterface::inverse_map(dim(),
00273                                                           fe_type,
00274                                                           this,
00275                                                           p,
00276                                                           tol,
00277                                                           false);
00278 
00279       return FEInterface::on_reference_element(mapped_point, this->type(), tol);
00280     }
00281 }
00282 
00283 
00284 void InfHex8::connectivity(const unsigned int libmesh_dbg_var(sc),
00285                            const IOPackage iop,
00286                            std::vector<dof_id_type>& conn) const
00287 {
00288   libmesh_assert(_nodes);
00289   libmesh_assert_less (sc, this->n_sub_elem());
00290   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
00291 
00292   switch (iop)
00293     {
00294     case TECPLOT:
00295       {
00296         conn.resize(8);
00297         conn[0] = this->node(0)+1;
00298         conn[1] = this->node(1)+1;
00299         conn[2] = this->node(2)+1;
00300         conn[3] = this->node(3)+1;
00301         conn[4] = this->node(4)+1;
00302         conn[5] = this->node(5)+1;
00303         conn[6] = this->node(6)+1;
00304         conn[7] = this->node(7)+1;
00305         return;
00306       }
00307 
00308     default:
00309       libmesh_error_msg("Unsupported IO package " << iop);
00310     }
00311 }
00312 
00313 
00314 
00315 #ifdef LIBMESH_ENABLE_AMR
00316 
00317 const float InfHex8::_embedding_matrix[4][8][8] =
00318   {
00319     // embedding matrix for child 0
00320     {
00321       //     0      1      2      3      4      5      6      7 th parent N.(ode)
00322       {    1.0,   0.0,   0.0,   0.0,   0.0,   0.0,   0.0,   0.0}, // 0th child N.
00323       {    0.5,   0.5,   0.0,   0.0,   0.0,   0.0,   0.0,   0.0}, // 1
00324       {   0.25,  0.25,  0.25,  0.25,   0.0,   0.0,   0.0,   0.0}, // 2
00325       {    0.5,   0.0,   0.0,   0.5,   0.0,   0.0,   0.0,   0.0}, // 3
00326       {    0.0,   0.0,   0.0,   0.0,   1.0,   0.0,   0.0,   0.0}, // 4
00327       {    0.0,   0.0,   0.0,   0.0,   0.5,   0.5,   0.0,   0.0}, // 5
00328       {    0.0,   0.0,   0.0,   0.0,  0.25,  0.25,  0.25,  0.25}, // 6
00329       {    0.0,   0.0,   0.0,   0.0,   0.5,   0.0,   0.0,   0.5}  // 7
00330     },
00331 
00332     // embedding matrix for child 1
00333     {
00334       //     0      1      2      3      4      5      6      7 th parent N.(ode)
00335       {    0.5,   0.5,   0.0,   0.0,   0.0,   0.0,   0.0,   0.0}, // 0th child N.
00336       {    0.0,   1.0,   0.0,   0.0,   0.0,   0.0,   0.0,   0.0}, // 1
00337       {    0.0,   0.5,   0.5,   0.0,   0.0,   0.0,   0.0,   0.0}, // 2
00338       {   0.25,  0.25,  0.25,  0.25,   0.0,   0.0,   0.0,   0.0}, // 3
00339       {    0.0,   0.0,   0.0,   0.0,   0.5,   0.5,   0.0,   0.0}, // 4
00340       {    0.0,   0.0,   0.0,   0.0,   0.0,   1.0,   0.0,   0.0}, // 5
00341       {    0.0,   0.0,   0.0,   0.0,   0.0,   0.5,   0.5,   0.0}, // 6
00342       {    0.0,   0.0,   0.0,   0.0,  0.25,  0.25,  0.25,  0.25}  // 7
00343     },
00344 
00345     // embedding matrix for child 2
00346     {
00347       //     0      1      2      3      4      5      6      7 th parent N.(ode)
00348       {    0.5,   0.0,   0.0,   0.5,   0.0,   0.0,   0.0,   0.0}, // 0th child N.
00349       {   0.25,  0.25,  0.25,  0.25,   0.0,   0.0,   0.0,   0.0}, // 1
00350       {    0.0,   0.0,   0.5,   0.5,   0.0,   0.0,   0.0,   0.0}, // 2
00351       {    0.0,   0.0,   0.0,   1.0,   0.0,   0.0,   0.0,   0.0}, // 3
00352       {    0.0,   0.0,   0.0,   0.0,   0.5,   0.0,   0.0,   0.5}, // 4
00353       {    0.0,   0.0,   0.0,   0.0,  0.25,  0.25,  0.25,  0.25}, // 5
00354       {    0.0,   0.0,   0.0,   0.0,   0.0,   0.0,   0.5,   0.5}, // 6
00355       {    0.0,   0.0,   0.0,   0.0,   0.0,   0.0,   0.0,   1.0}  // 7
00356     },
00357 
00358     // embedding matrix for child 3
00359     {
00360       //     0      1      2      3      4      5      6      7 th parent N.(ode)
00361       {   0.25,  0.25,  0.25,  0.25,   0.0,   0.0,   0.0,   0.0}, // 0th child N.
00362       {    0.0,   0.5,   0.5,   0.0,   0.0,   0.0,   0.0,   0.0}, // 1
00363       {    0.0,   0.0,   1.0,   0.0,   0.0,   0.0,   0.0,   0.0}, // 2
00364       {    0.0,   0.0,   0.5,   0.5,   0.0,   0.0,   0.0,   0.0}, // 3
00365       {    0.0,   0.0,   0.0,   0.0,  0.25,  0.25,  0.25,  0.25}, // 4
00366       {    0.0,   0.0,   0.0,   0.0,   0.0,   0.5,   0.5,   0.0}, // 5
00367       {    0.0,   0.0,   0.0,   0.0,   0.0,   0.0,   1.0,   0.0}, // 6
00368       {    0.0,   0.0,   0.0,   0.0,   0.0,   0.0,   0.5,   0.5}  // 7
00369     }
00370   };
00371 
00372 
00373 
00374 #endif
00375 
00376 } // namespace libMesh
00377 
00378 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS