$extrastylesheet
face_inf_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 
00019 
00020 // Local includes
00021 #include "libmesh/libmesh_config.h"
00022 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00023 
00024 
00025 // Local includes cont'd
00026 #include "libmesh/face_inf_quad4.h"
00027 #include "libmesh/fe_interface.h"
00028 #include "libmesh/fe_type.h"
00029 #include "libmesh/side.h"
00030 #include "libmesh/edge_edge2.h"
00031 #include "libmesh/edge_inf_edge2.h"
00032 
00033 namespace libMesh
00034 {
00035 
00036 
00037 
00038 // ------------------------------------------------------------
00039 // InfQuad4 class static member initializations
00040 const unsigned int InfQuad4::side_nodes_map[3][2] =
00041   {
00042     {0, 1}, // Side 0
00043     {1, 3}, // Side 1
00044     {0, 2}  // Side 2
00045   };
00046 
00047 
00048 
00049 #ifdef LIBMESH_ENABLE_AMR
00050 
00051 const float InfQuad4::_embedding_matrix[2][4][4] =
00052   {
00053     // embedding matrix for child 0
00054     {
00055       // 0    1    2    3rd parent node
00056       {1.0, 0.0, 0.0, 0.0}, // 0th child node
00057       {0.5, 0.5, 0.0, 0.0}, // 1
00058       {0.0, 0.0, 1.0, 0.0}, // 2
00059       {0.0, 0.0, 0.5, 0.5}  // 3
00060     },
00061 
00062     // embedding matrix for child 1
00063     {
00064       // 0    1    2    3
00065       {0.5, 0.5, 0.0, 0.0}, // 0
00066       {0.0, 1.0, 0.0, 0.0}, // 1
00067       {0.0, 0.0, 0.5, 0.5}, // 2
00068       {0.0, 0.0, 0.0, 1.0}  // 3
00069     }
00070   };
00071 
00072 #endif
00073 
00074 
00075 // ------------------------------------------------------------
00076 // InfQuad4 class member functions
00077 
00078 bool InfQuad4::is_vertex(const unsigned int i) const
00079 {
00080   if (i < 2)
00081     return true;
00082   return false;
00083 }
00084 
00085 bool InfQuad4::is_edge(const unsigned int i) const
00086 {
00087   if (i < 2)
00088     return false;
00089   return true;
00090 }
00091 
00092 bool InfQuad4::is_face(const unsigned int) const
00093 {
00094   return false;
00095 }
00096 
00097 bool InfQuad4::is_node_on_side(const unsigned int n,
00098                                const unsigned int s) const
00099 {
00100   libmesh_assert_less (s, n_sides());
00101   for (unsigned int i = 0; i != 2; ++i)
00102     if (side_nodes_map[s][i] == n)
00103       return true;
00104   return false;
00105 }
00106 
00107 bool InfQuad4::contains_point (const Point& p, Real tol) const
00108 {
00109   /*
00110    * make use of the fact that infinite elements do not
00111    * live inside the envelope.  Use a fast scheme to
00112    * check whether point \p p is inside or outside
00113    * our relevant part of the envelope.  Note that
00114    * this is not exclusive: the point may be outside
00115    * the envelope, but contained in another infinite element.
00116    * Therefore, if the distance is greater, do fall back
00117    * to the scheme of using FEInterface::inverse_map().
00118    */
00119   const Point my_origin (this->origin());
00120 
00121   /*
00122    * determine the minimal distance of the base from the origin
00123    * use size_sq() instead of size(), it is slightly faster
00124    */
00125   const Real min_distance_sq = std::min((Point(this->point(0)-my_origin)).size_sq(),
00126                                         (Point(this->point(1)-my_origin)).size_sq());
00127 
00128   /*
00129    * work with 1% allowable deviation.  Can still fall
00130    * back to the InfFE::inverse_map()
00131    */
00132   const Real conservative_p_dist_sq = 1.01 * (Point(p-my_origin).size_sq());
00133 
00134   if (conservative_p_dist_sq < min_distance_sq)
00135     {
00136       /*
00137        * the physical point is definitely not contained
00138        * in the element, return false.
00139        */
00140       return false;
00141     }
00142   else
00143     {
00144       /*
00145        * cannot say anything, fall back to the FEInterface::inverse_map()
00146        *
00147        * Declare a basic FEType.  Will use default in the base,
00148        * and something else (not important) in radial direction.
00149        */
00150       FEType fe_type(default_order());
00151 
00152       const Point mapped_point = FEInterface::inverse_map(dim(),
00153                                                           fe_type,
00154                                                           this,
00155                                                           p,
00156                                                           tol,
00157                                                           false);
00158 
00159       return FEInterface::on_reference_element(mapped_point, this->type(), tol);
00160     }
00161 }
00162 
00163 
00164 
00165 
00166 UniquePtr<Elem> InfQuad4::build_side (const unsigned int i,
00167                                       bool proxy) const
00168 {
00169   // libmesh_assert_less (i, this->n_sides());
00170 
00171   if (proxy)
00172     {
00173       switch (i)
00174         {
00175           // base
00176         case 0:
00177           return UniquePtr<Elem>(new Side<Edge2,InfQuad4>(this,i));
00178 
00179           // ifem edges
00180         case 1:
00181         case 2:
00182           return UniquePtr<Elem>(new Side<InfEdge2,InfQuad4>(this,i));
00183 
00184         default:
00185           libmesh_error_msg("Invalid side i = " << i);
00186         }
00187     }
00188 
00189   else
00190     {
00191       // Create NULL pointer to be initialized, returned later.
00192       Elem* edge = NULL;
00193 
00194       switch (i)
00195         {
00196         case 0:
00197           {
00198             edge = new Edge2;
00199             edge->set_node(0) = this->get_node(0);
00200             edge->set_node(1) = this->get_node(1);
00201             break;
00202           }
00203 
00204         case 1:
00205           {
00206             // adjacent to another infinite element
00207             edge = new InfEdge2;
00208             edge->set_node(0) = this->get_node(1);
00209             edge->set_node(1) = this->get_node(3);
00210             break;
00211           }
00212 
00213         case 2:
00214           {
00215             // adjacent to another infinite element
00216             edge = new InfEdge2;
00217             edge->set_node(0) = this->get_node(0);
00218             edge->set_node(1) = this->get_node(2);
00219             break;
00220           }
00221         default:
00222           libmesh_error_msg("Invalid side i = " << i);
00223         }
00224 
00225       edge->subdomain_id() = this->subdomain_id();
00226       return UniquePtr<Elem>(edge);
00227     }
00228 
00229   libmesh_error_msg("We'll never get here!");
00230   return UniquePtr<Elem>();
00231 }
00232 
00233 
00234 void InfQuad4::connectivity(const unsigned int libmesh_dbg_var(sf),
00235                             const IOPackage iop,
00236                             std::vector<dof_id_type>& conn) const
00237 {
00238   libmesh_assert_less (sf, this->n_sub_elem());
00239   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
00240 
00241   conn.resize(4);
00242 
00243   switch (iop)
00244     {
00245     case TECPLOT:
00246       {
00247         conn[0] = this->node(0)+1;
00248         conn[1] = this->node(1)+1;
00249         conn[2] = this->node(3)+1;
00250         conn[3] = this->node(2)+1;
00251         return;
00252       }
00253     case VTK:
00254       {
00255         conn[0] = this->node(0);
00256         conn[1] = this->node(1);
00257         conn[2] = this->node(3);
00258         conn[3] = this->node(2);
00259       }
00260     default:
00261       libmesh_error_msg("Unsupported IO package " << iop);
00262     }
00263 }
00264 
00265 } // namespace libMesh
00266 
00267 
00268 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS