$extrastylesheet
cell_inf_hex.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 
00024 // C++ includes
00025 #include <algorithm> // for std::min, std::max
00026 
00027 // Local includes cont'd
00028 #include "libmesh/cell_inf_hex.h"
00029 #include "libmesh/cell_inf_hex8.h"
00030 #include "libmesh/face_quad4.h"
00031 #include "libmesh/face_inf_quad4.h"
00032 
00033 namespace libMesh
00034 {
00035 
00036 
00037 
00038 
00039 // ------------------------------------------------------------
00040 // InfHex class member functions
00041 dof_id_type InfHex::key (const unsigned int s) const
00042 {
00043   libmesh_assert_less (s, this->n_sides());
00044 
00045   switch (s)
00046     {
00047     case 0:  // the face at z = -1
00048 
00049       return
00050         this->compute_key (this->node(0),
00051                            this->node(1),
00052                            this->node(2),
00053                            this->node(3));
00054 
00055     case 1:  // the face at y = -1
00056 
00057       return
00058         this->compute_key (this->node(0),
00059                            this->node(1),
00060                            this->node(5),
00061                            this->node(4));
00062 
00063     case 2:  // the face at x = 1
00064 
00065       return
00066         this->compute_key (this->node(1),
00067                            this->node(2),
00068                            this->node(6),
00069                            this->node(5));
00070 
00071     case 3: // the face at y = 1
00072 
00073       return
00074         this->compute_key (this->node(2),
00075                            this->node(3),
00076                            this->node(7),
00077                            this->node(6));
00078 
00079 
00080     case 4: // the face at x = -1
00081 
00082       return
00083         this->compute_key (this->node(3),
00084                            this->node(0),
00085                            this->node(4),
00086                            this->node(7));
00087 
00088     default:
00089       libmesh_error_msg("Invalid side s = " << s);
00090     }
00091 
00092   libmesh_error_msg("We'll never get here!");
00093   return 0;
00094 }
00095 
00096 
00097 
00098 UniquePtr<Elem> InfHex::side (const unsigned int i) const
00099 {
00100   libmesh_assert_less (i, this->n_sides());
00101 
00102   // To be returned wrapped in an UniquePtr
00103   Elem* face = NULL;
00104 
00105   // Think of a unit cube: (-1,1) x (-1,1) x (-1,1),
00106   // with (in general) the normals pointing outwards
00107   switch (i)
00108     {
00109       // the face at z = -1
00110       // the base, where the infinite element couples to conventional
00111       // elements
00112     case 0:
00113       {
00114         // Oops, here we are, claiming the normal of the face
00115         // elements point outwards -- and this is the exception:
00116         // For the side built from the base face,
00117         // the normal is pointing _into_ the element!
00118         // Why is that? - In agreement with build_side(),
00119         // which in turn _has_ to build the face in this
00120         // way as to enable the cool way \p InfFE re-uses \p FE.
00121         face = new Quad4;
00122         face->set_node(0) = this->get_node(0);
00123         face->set_node(1) = this->get_node(1);
00124         face->set_node(2) = this->get_node(2);
00125         face->set_node(3) = this->get_node(3);
00126         break;
00127       }
00128 
00129       // the face at y = -1
00130       // this face connects to another infinite element
00131     case 1:
00132       {
00133         face = new InfQuad4;
00134         face->set_node(0) = this->get_node(0);
00135         face->set_node(1) = this->get_node(1);
00136         face->set_node(2) = this->get_node(4);
00137         face->set_node(3) = this->get_node(5);
00138         break;
00139       }
00140 
00141       // the face at x = 1
00142       // this face connects to another infinite element
00143     case 2:
00144       {
00145         face = new InfQuad4;
00146         face->set_node(0) = this->get_node(1);
00147         face->set_node(1) = this->get_node(2);
00148         face->set_node(2) = this->get_node(5);
00149         face->set_node(3) = this->get_node(6);
00150         break;
00151       }
00152 
00153       // the face at y = 1
00154       // this face connects to another infinite element
00155     case 3:
00156       {
00157         face = new InfQuad4;
00158         face->set_node(0) = this->get_node(2);
00159         face->set_node(1) = this->get_node(3);
00160         face->set_node(2) = this->get_node(6);
00161         face->set_node(3) = this->get_node(7);
00162         break;
00163       }
00164 
00165       // the face at x = -1
00166       // this face connects to another infinite element
00167     case 4:
00168       {
00169         face = new InfQuad4;
00170         face->set_node(0) = this->get_node(3);
00171         face->set_node(1) = this->get_node(0);
00172         face->set_node(2) = this->get_node(7);
00173         face->set_node(3) = this->get_node(4);
00174         break;
00175       }
00176 
00177     default:
00178       libmesh_error_msg("Invalid side i = " << i);
00179     }
00180 
00181   return UniquePtr<Elem>(face);
00182 }
00183 
00184 
00185 
00186 bool InfHex::is_child_on_side(const unsigned int c,
00187                               const unsigned int s) const
00188 {
00189   libmesh_assert_less (c, this->n_children());
00190   libmesh_assert_less (s, this->n_sides());
00191 
00192   return (s == 0 || c+1 == s || c == s%4);
00193 }
00194 
00195 
00196 
00197 bool InfHex::is_edge_on_side (const unsigned int e,
00198                               const unsigned int s) const
00199 {
00200   libmesh_assert_less (e, this->n_edges());
00201   libmesh_assert_less (s, this->n_sides());
00202 
00203   return (is_node_on_side(InfHex8::edge_nodes_map[e][0],s) &&
00204           is_node_on_side(InfHex8::edge_nodes_map[e][1],s));
00205 }
00206 
00207 
00208 
00209 
00210 Real InfHex::quality (const ElemQuality q) const
00211 {
00212   switch (q)
00213     {
00214 
00224     case DIAGONAL:
00225       {
00226         // Diagonal between node 0 and node 2
00227         const Real d02 = this->length(0,2);
00228 
00229         // Diagonal between node 1 and node 3
00230         const Real d13 = this->length(1,3);
00231 
00232         // Find the biggest and smallest diagonals
00233         const Real min = std::min(d02, d13);
00234         const Real max = std::max(d02, d13);
00235 
00236         libmesh_assert_not_equal_to (max, 0.0);
00237 
00238         return min / max;
00239 
00240         break;
00241       }
00242 
00250     case TAPER:
00251       {
00252 
00256         const Real d01 = this->length(0,1);
00257         const Real d12 = this->length(1,2);
00258         const Real d23 = this->length(2,3);
00259         const Real d03 = this->length(0,3);
00260 
00261         std::vector<Real> edge_ratios(2);
00262 
00263         // Bottom
00264         edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23);
00265         edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12);
00266 
00267         return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ;
00268 
00269         break;
00270       }
00271 
00272 
00280     case STRETCH:
00281       {
00285         const Real sqrt3 = 1.73205080756888;
00286 
00290         const Real d02 = this->length(0,2);
00291         const Real d13 = this->length(1,3);
00292         const Real max_diag = std::max(d02, d13);
00293 
00294         libmesh_assert_not_equal_to ( max_diag, 0.0 );
00295 
00299         std::vector<Real> edges(4);
00300         edges[0]  = this->length(0,1);
00301         edges[1]  = this->length(1,2);
00302         edges[2]  = this->length(2,3);
00303         edges[3]  = this->length(0,3);
00304 
00305         const Real min_edge = *(std::min_element(edges.begin(), edges.end()));
00306         return sqrt3 * min_edge / max_diag ;
00307       }
00308 
00309 
00314     default:
00315       return Elem::quality(q);
00316     }
00317 
00318   libmesh_error_msg("We'll never get here!");
00319   return 0.;
00320 }
00321 
00322 
00323 
00324 std::pair<Real, Real> InfHex::qual_bounds (const ElemQuality) const
00325 {
00326   libmesh_not_implemented();
00327 
00328   std::pair<Real, Real> bounds;
00329 
00330   /*
00331     switch (q)
00332     {
00333 
00334     case ASPECT_RATIO:
00335     bounds.first  = 1.;
00336     bounds.second = 4.;
00337     break;
00338 
00339     case SKEW:
00340     bounds.first  = 0.;
00341     bounds.second = 0.5;
00342     break;
00343 
00344     case SHEAR:
00345     case SHAPE:
00346     bounds.first  = 0.3;
00347     bounds.second = 1.;
00348     break;
00349 
00350     case CONDITION:
00351     bounds.first  = 1.;
00352     bounds.second = 8.;
00353     break;
00354 
00355     case JACOBIAN:
00356     bounds.first  = 0.5;
00357     bounds.second = 1.;
00358     break;
00359 
00360     case DISTORTION:
00361     bounds.first  = 0.6;
00362     bounds.second = 1.;
00363     break;
00364 
00365     case TAPER:
00366     bounds.first  = 0.;
00367     bounds.second = 0.4;
00368     break;
00369 
00370     case STRETCH:
00371     bounds.first  = 0.25;
00372     bounds.second = 1.;
00373     break;
00374 
00375     case DIAGONAL:
00376     bounds.first  = 0.65;
00377     bounds.second = 1.;
00378     break;
00379 
00380     case SIZE:
00381     bounds.first  = 0.5;
00382     bounds.second = 1.;
00383     break;
00384 
00385     default:
00386     libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
00387     bounds.first  = -1;
00388     bounds.second = -1;
00389     }
00390   */
00391 
00392   return bounds;
00393 }
00394 
00395 
00396 
00397 
00398 
00399 const unsigned short int InfHex::_second_order_adjacent_vertices[8][2] =
00400   {
00401     { 0,  1}, // vertices adjacent to node 8
00402     { 1,  2}, // vertices adjacent to node 9
00403     { 2,  3}, // vertices adjacent to node 10
00404     { 0,  3}, // vertices adjacent to node 11
00405 
00406     { 4,  5}, // vertices adjacent to node 12
00407     { 5,  6}, // vertices adjacent to node 13
00408     { 6,  7}, // vertices adjacent to node 14
00409     { 4,  7}  // vertices adjacent to node 15
00410   };
00411 
00412 
00413 
00414 const unsigned short int InfHex::_second_order_vertex_child_number[18] =
00415   {
00416     99,99,99,99,99,99,99,99, // Vertices
00417     0,1,2,0,                 // Edges
00418     0,1,2,0,0,               // Faces
00419     0                        // Interior
00420   };
00421 
00422 
00423 
00424 const unsigned short int InfHex::_second_order_vertex_child_index[18] =
00425   {
00426     99,99,99,99,99,99,99,99, // Vertices
00427     1,2,3,3,                 // Edges
00428     5,6,7,7,2,               // Faces
00429     6                        // Interior
00430   };
00431 
00432 } // namespace libMesh
00433 
00434 
00435 
00436 
00437 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS