LCOV - code coverage report
Current view: top level - src/geom - face_inf_quad.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 60 128 46.9 %
Date: 2025-08-19 19:27:09 Functions: 9 12 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : // Local includes
      20             : #include "libmesh/libmesh_config.h"
      21             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
      22             : 
      23             : // Local includes cont'd
      24             : #include "libmesh/face_inf_quad.h"
      25             : #include "libmesh/edge_edge2.h"
      26             : #include "libmesh/edge_inf_edge2.h"
      27             : #include "libmesh/face_inf_quad4.h"
      28             : #include "libmesh/enum_elem_quality.h"
      29             : 
      30             : namespace libMesh
      31             : {
      32             : 
      33             : 
      34             : // ------------------------------------------------------------
      35             : // InfQuad class static member initializations
      36             : const int InfQuad::num_sides;
      37             : const int InfQuad::num_children;
      38             : 
      39             : // Note: we can omit initialization of the third entry of each row because
      40             : // static variables are automatically zero-initialized.
      41             : const Real InfQuad::_master_points[6][3] =
      42             :   {
      43             :     {-1, 0},
      44             :     {1, 0},
      45             :     {-1, 1},
      46             :     {1, 1},
      47             :     {0, 0},
      48             :     {0, 1}
      49             :   };
      50             : 
      51             : const unsigned int InfQuad::adjacent_sides_map[/*num_vertices*/4][/*max_adjacent_sides*/2] =
      52             :   {
      53             :     {0,  2}, // Sides adjacent to node 0
      54             :     {0,  1}, // Sides adjacent to node 1
      55             :     {2, 99}, // Sides adjacent to node 2
      56             :     {1, 99}  // Sides adjacent to node 3
      57             :   };
      58             : 
      59             : // ------------------------------------------------------------
      60             : // InfQuad class member functions
      61           0 : dof_id_type InfQuad::key (const unsigned int s) const
      62             : {
      63           0 :   libmesh_assert_less (s, this->n_sides());
      64             : 
      65             :   // The order of the node ids does not matter, they are sorted by the
      66             :   // compute_key() function.
      67           0 :   return this->compute_key(this->node_id(InfQuad4::side_nodes_map[s][0]),
      68           0 :                            this->node_id(InfQuad4::side_nodes_map[s][1]));
      69             : }
      70             : 
      71             : 
      72             : 
      73         810 : dof_id_type InfQuad::low_order_key (const unsigned int s) const
      74             : {
      75         324 :   libmesh_assert_less (s, this->n_sides());
      76             : 
      77             :   // The order of the node ids does not matter, they are sorted by the
      78             :   // compute_key() function.
      79        1134 :   return this->compute_key(this->node_id(InfQuad4::side_nodes_map[s][0]),
      80        1134 :                            this->node_id(InfQuad4::side_nodes_map[s][1]));
      81             : }
      82             : 
      83             : 
      84             : 
      85         114 : unsigned int InfQuad::local_side_node(unsigned int side,
      86             :                                       unsigned int side_node) const
      87             : {
      88          38 :   libmesh_assert_less (side, this->n_sides());
      89          38 :   libmesh_assert_less (side_node, 2);
      90             : 
      91         114 :   return InfQuad4::side_nodes_map[side][side_node];
      92             : }
      93             : 
      94             : 
      95             : 
      96         228 : unsigned int InfQuad::local_edge_node(unsigned int edge,
      97             :                                       unsigned int edge_node) const
      98             : {
      99         228 :   return local_side_node(edge, edge_node);
     100             : }
     101             : 
     102             : 
     103             : 
     104         112 : std::unique_ptr<Elem> InfQuad::side_ptr (const unsigned int i)
     105             : {
     106          44 :   libmesh_assert_less (i, this->n_sides());
     107             : 
     108             :   // Return value
     109         112 :   std::unique_ptr<Elem> edge;
     110             : 
     111         112 :   switch (i)
     112             :     {
     113          31 :     case 0: // base face
     114             :       {
     115          31 :         edge = std::make_unique<Edge2>();
     116          31 :         break;
     117             :       }
     118             : 
     119          81 :     case 1: // adjacent to another infinite element
     120             :     case 2: // adjacent to another infinite element
     121             :       {
     122          81 :         edge = std::make_unique<InfEdge2>();
     123          81 :         break;
     124             :       }
     125             : 
     126           0 :     default:
     127           0 :       libmesh_error_msg("Invalid side i = " << i);
     128             :     }
     129             : 
     130             :   // Set the nodes
     131         336 :   for (auto n : edge->node_index_range())
     132         312 :     edge->set_node(n, this->node_ptr(InfQuad4::side_nodes_map[i][n]));
     133             : 
     134         112 :   return edge;
     135           0 : }
     136             : 
     137             : 
     138             : 
     139         312 : void InfQuad::side_ptr (std::unique_ptr<Elem> & side,
     140             :                         const unsigned int i)
     141             : {
     142         123 :   libmesh_assert_less (i, this->n_sides());
     143             : 
     144         312 :   switch (i)
     145             :     {
     146             :       // the base face
     147           9 :     case 0:
     148             :       {
     149          24 :         if (!side.get() || side->type() != EDGE2)
     150             :           {
     151          26 :             side = this->side_ptr(i);
     152          21 :             return;
     153             :           }
     154           1 :         break;
     155             :       }
     156             : 
     157             :       // connecting to another infinite element
     158         114 :     case 1:
     159             :     case 2:
     160             :       {
     161         288 :         if (!side.get() || side->type() != INFEDGE2)
     162             :           {
     163          74 :             side = this->side_ptr(i);
     164          61 :             return;
     165             :           }
     166          90 :         break;
     167             :       }
     168             : 
     169           0 :     default:
     170           0 :       libmesh_error_msg("Invalid side i = " << i);
     171             :     }
     172             : 
     173         321 :   side->subdomain_id() = this->subdomain_id();
     174             : 
     175             :   // Set the nodes
     176         690 :   for (auto n : side->node_index_range())
     177         642 :     side->set_node(n, this->node_ptr(InfQuad4::side_nodes_map[i][n]));
     178             : }
     179             : 
     180             : 
     181         352 : bool InfQuad::is_child_on_side(const unsigned int c,
     182             :                                const unsigned int s) const
     183             : {
     184         204 :   libmesh_assert_less (c, this->n_children());
     185         204 :   libmesh_assert_less (s, this->n_sides());
     186             : 
     187         352 :   return (s == 0 || s == c+1);
     188             : }
     189             : 
     190             : 
     191             : bool
     192          16 : InfQuad::is_flipped() const
     193             : {
     194             :   return (
     195             : #if LIBMESH_DIM > 2
     196             :           // Don't bother outside the XY plane
     197          22 :           this->point(0)(2) && this->point(1)(2) &&
     198          38 :           this->point(2)(2) && this->point(3)(2) &&
     199             : #endif
     200          22 :           ((this->point(1)(0)-this->point(0)(0))*
     201          16 :            (this->point(2)(1)-this->point(0)(1)) >
     202          22 :            (this->point(2)(0)-this->point(0)(0))*
     203          22 :            (this->point(1)(1)-this->point(0)(1))));
     204             : }
     205             : 
     206             : 
     207             : std::vector<unsigned int>
     208         150 : InfQuad::edges_adjacent_to_node(const unsigned int n) const
     209             : {
     210          50 :   libmesh_assert_less(n, this->n_nodes());
     211             : 
     212             :   // For vertices, we use the adjacent_sides_map, otherwise node
     213             :   // 4 is on side 0 and node 5 is not any any side.
     214         150 :   if (this->is_vertex(n))
     215             :     {
     216          80 :       auto trim = (n < 2) ? 0 : 1;
     217         120 :       return {std::begin(adjacent_sides_map[n]), std::end(adjacent_sides_map[n]) - trim};
     218             :     }
     219          30 :   else if (n == 4)
     220          15 :     return {0};
     221             :   else
     222          10 :     return {};
     223             : }
     224             : 
     225             : 
     226          30 : Real InfQuad::quality (const ElemQuality q) const
     227             : {
     228          30 :   return Elem::quality(q); // Not implemented
     229             : }
     230             : 
     231             : 
     232             : 
     233             : 
     234           0 : std::pair<Real, Real> InfQuad::qual_bounds (const ElemQuality q) const
     235             : {
     236           0 :   std::pair<Real, Real> bounds;
     237             : 
     238           0 :   switch (q)
     239             :     {
     240             : 
     241           0 :     case ASPECT_RATIO:
     242           0 :       bounds.first  = 1.;
     243           0 :       bounds.second = 4.;
     244           0 :       break;
     245             : 
     246           0 :     case SKEW:
     247           0 :       bounds.first  = 0.;
     248           0 :       bounds.second = 0.5;
     249           0 :       break;
     250             : 
     251           0 :     case TAPER:
     252           0 :       bounds.first  = 0.;
     253           0 :       bounds.second = 0.7;
     254           0 :       break;
     255             : 
     256           0 :     case WARP:
     257           0 :       bounds.first  = 0.9;
     258           0 :       bounds.second = 1.;
     259           0 :       break;
     260             : 
     261           0 :     case STRETCH:
     262           0 :       bounds.first  = 0.25;
     263           0 :       bounds.second = 1.;
     264           0 :       break;
     265             : 
     266           0 :     case MIN_ANGLE:
     267           0 :       bounds.first  = 45.;
     268           0 :       bounds.second = 90.;
     269           0 :       break;
     270             : 
     271           0 :     case MAX_ANGLE:
     272           0 :       bounds.first  = 90.;
     273           0 :       bounds.second = 135.;
     274           0 :       break;
     275             : 
     276           0 :     case CONDITION:
     277           0 :       bounds.first  = 1.;
     278           0 :       bounds.second = 4.;
     279           0 :       break;
     280             : 
     281           0 :     case JACOBIAN:
     282             :     case SCALED_JACOBIAN:
     283           0 :       bounds.first  = 0.5;
     284           0 :       bounds.second = 1.;
     285           0 :       break;
     286             : 
     287           0 :     case SHEAR:
     288             :     case SHAPE:
     289             :     case SIZE:
     290           0 :       bounds.first  = 0.3;
     291           0 :       bounds.second = 1.;
     292           0 :       break;
     293             : 
     294           0 :     case DISTORTION:
     295           0 :       bounds.first  = 0.6;
     296           0 :       bounds.second = 1.;
     297           0 :       break;
     298             : 
     299           0 :     default:
     300           0 :       libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
     301           0 :       bounds.first  = -1;
     302           0 :       bounds.second = -1;
     303             :     }
     304             : 
     305           0 :   return bounds;
     306             : }
     307             : 
     308             : 
     309             : 
     310           0 : bool InfQuad::on_reference_element(const Point & p,
     311             :                                    const Real eps) const
     312             : {
     313           0 :   const Real & xi = p(0);
     314           0 :   const Real & eta = p(1);
     315             : 
     316             :   // The reference infquad is [-1,1]^2.
     317           0 :   return ((xi  >= -1.-eps) &&
     318           0 :           (xi  <=  1.+eps) &&
     319           0 :           (eta >= -1.-eps) &&
     320           0 :           (eta <=  1.+eps));
     321             : }
     322             : 
     323             : 
     324             : 
     325             : } // namespace libMesh
     326             : 
     327             : 
     328             : 
     329             : #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

Generated by: LCOV version 1.14