LCOV - code coverage report
Current view: top level - src/geom - face_inf_quad6.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 62 109 56.9 %
Date: 2025-08-19 19:27:09 Functions: 9 13 69.2 %
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             : 
      20             : #include "libmesh/libmesh_config.h"
      21             : 
      22             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
      23             : 
      24             : // Local includes
      25             : #include "libmesh/face_inf_quad6.h"
      26             : #include "libmesh/edge_edge3.h"
      27             : #include "libmesh/edge_inf_edge2.h"
      28             : #include "libmesh/enum_io_package.h"
      29             : #include "libmesh/enum_order.h"
      30             : 
      31             : namespace libMesh
      32             : {
      33             : 
      34             : 
      35             : 
      36             : 
      37             : // ------------------------------------------------------------
      38             : // InfQuad6 class static member initializations
      39             : const int InfQuad6::num_nodes;
      40             : const int InfQuad6::nodes_per_side;
      41             : 
      42             : const unsigned int InfQuad6::side_nodes_map[InfQuad6::num_sides][InfQuad6::nodes_per_side] =
      43             :   {
      44             :     {0, 1, 4},  // Side 0
      45             :     {1, 3, 99}, // Side 1
      46             :     {0, 2, 99}  // Side 2
      47             :   };
      48             : 
      49             : 
      50             : // ------------------------------------------------------------
      51             : // InfQuad6 class member functions
      52             : 
      53         243 : bool InfQuad6::is_node_on_side(const unsigned int n,
      54             :                                const unsigned int s) const
      55             : {
      56          93 :   libmesh_assert_less (s, n_sides());
      57          93 :   return std::find(std::begin(side_nodes_map[s]),
      58         243 :                    std::end(side_nodes_map[s]),
      59         243 :                    n) != std::end(side_nodes_map[s]);
      60             : }
      61             : 
      62             : std::vector<unsigned>
      63          78 : InfQuad6::nodes_on_side(const unsigned int s) const
      64             : {
      65          28 :   libmesh_assert_less(s, n_sides());
      66          78 :   auto trim = (s == 0) ? 0 : 1;
      67          78 :   return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
      68             : }
      69             : 
      70             : std::vector<unsigned>
      71          54 : InfQuad6::nodes_on_edge(const unsigned int e) const
      72             : {
      73          54 :   return nodes_on_side(e);
      74             : }
      75             : 
      76             : #ifdef LIBMESH_ENABLE_AMR
      77             : 
      78             : const Real InfQuad6::_embedding_matrix[InfQuad6::num_children][InfQuad6::num_nodes][InfQuad6::num_nodes] =
      79             :   {
      80             :     // embedding matrix for child 0
      81             :     {
      82             :       //     0       1       2       3       4       5th parent node
      83             :       {    1.0,    0.0,    0.0,    0.0,    0.0,    0.0 }, // 0th child node
      84             :       {    0.0,    0.0,    0.0,    0.0,    1.0,    0.0 }, // 1
      85             :       {    0.0,    0.0,    1.0,    0.0,    0.0,    0.0 }, // 2
      86             :       {    0.0,    0.0,    0.0,    0.0,    0.0,    1.0 }, // 3
      87             :       {  0.375, -0.125,    0.0,    0.0,   0.75,    0.0 }, // 4
      88             :       {    0.0,    0.0,  0.375, -0.125,    0.0,   0.75 }  // 5
      89             :     },
      90             : 
      91             :     // embedding matrix for child 1
      92             :     {
      93             :       //     0       1       2       3       4       5th parent node
      94             :       {    0.0,    0.0,    0.0,    0.0,    1.0,    0.0 }, // 0th child node
      95             :       {    0.0,    1.0,    0.0,    0.0,    0.0,    0.0 }, // 1
      96             :       {    0.0,    0.0,    0.0,    0.0,    0.0,    1.0 }, // 2
      97             :       {    0.0,    0.0,    0.0,    1.0,    0.0,    0.0 }, // 3
      98             :       { -0.125,  0.375,    0.0,    0.0,   0.75,    0.0 }, // 4
      99             :       {    0.0,    0.0, -0.125,  0.375,    0.0,   0.75 }  // 5
     100             :     }
     101             :   };
     102             : 
     103             : #endif
     104             : 
     105             : 
     106             : 
     107             : 
     108         438 : Order InfQuad6::default_order() const
     109             : {
     110         438 :   return SECOND;
     111             : }
     112             : 
     113             : 
     114             : 
     115           0 : dof_id_type InfQuad6::key (const unsigned int s) const
     116             : {
     117           0 :   libmesh_assert_less (s, this->n_sides());
     118             : 
     119           0 :   switch (s)
     120             :     {
     121             :       // Edge3 side
     122           0 :     case 0:
     123           0 :       return this->compute_key (this->node_id(4));
     124             : 
     125             :       // InfEdge
     126           0 :     case 1:
     127             :     case 2:
     128           0 :       return InfQuad::key(s);
     129             : 
     130           0 :     default:
     131           0 :       libmesh_error_msg("Invalid side s = " << s);
     132             :     }
     133             : }
     134             : 
     135             : 
     136             : 
     137         114 : unsigned int InfQuad6::local_side_node(unsigned int side,
     138             :                                        unsigned int side_node) const
     139             : {
     140          38 :   libmesh_assert_less (side, this->n_sides());
     141          38 :   libmesh_assert ((side == 0 && side_node < InfQuad6::nodes_per_side) || (side_node < 2));
     142             : 
     143         114 :   return InfQuad6::side_nodes_map[side][side_node];
     144             : }
     145             : 
     146             : 
     147             : 
     148         679 : std::unique_ptr<Elem> InfQuad6::build_side_ptr (const unsigned int i)
     149             : {
     150             :   // libmesh_assert_less (i, this->n_sides());
     151             : 
     152         679 :   std::unique_ptr<Elem> edge;
     153             : 
     154         679 :   switch (i)
     155             :     {
     156         238 :     case 0:
     157             :       {
     158         238 :         edge = std::make_unique<Edge3>();
     159         238 :         break;
     160             :       }
     161             : 
     162             :       // adjacent to another infinite element
     163         441 :     case 1:
     164             :     case 2:
     165             :       {
     166         441 :         edge = std::make_unique<InfEdge2>();
     167         441 :         break;
     168             :       }
     169             : 
     170           0 :     default:
     171           0 :       libmesh_error_msg("Invalid side i = " << i);
     172             :     }
     173             : 
     174             :   // Set the nodes
     175        2275 :   for (auto n : edge->node_index_range())
     176        2150 :     edge->set_node(n, this->node_ptr(InfQuad6::side_nodes_map[i][n]));
     177             : 
     178         679 :   edge->set_interior_parent(this);
     179         449 :   edge->inherit_data_from(*this);
     180             : 
     181         679 :   return edge;
     182           0 : }
     183             : 
     184             : 
     185             : 
     186          42 : void InfQuad6::build_side_ptr (std::unique_ptr<Elem> & side,
     187             :                                const unsigned int i)
     188             : {
     189          15 :   libmesh_assert_less (i, this->n_sides());
     190             : 
     191             :   // Think of a unit cube: (-1,1) x (-1,1) x (1,1)
     192          42 :   switch (i)
     193             :     {
     194             :       // the base face
     195           5 :     case 0:
     196             :       {
     197          14 :         if (!side.get() || side->type() != EDGE3)
     198             :           {
     199          14 :             side = this->build_side_ptr(i);
     200          11 :             return;
     201             :           }
     202           1 :         break;
     203             :       }
     204             : 
     205             :       // connecting to another infinite element
     206          10 :     case 1:
     207             :     case 2:
     208             :       {
     209          28 :         if (!side.get() || side->type() != INFEDGE2)
     210             :           {
     211          14 :             side = this->build_side_ptr(i);
     212          11 :             return;
     213             :           }
     214           6 :         break;
     215             :       }
     216             : 
     217           0 :     default:
     218           0 :       libmesh_error_msg("Invalid side i = " << i);
     219             :     }
     220             : 
     221          20 :   side->subdomain_id() = this->subdomain_id();
     222          14 :   side->set_mapping_type(this->mapping_type());
     223             : #ifdef LIBMESH_ENABLE_AMR
     224          27 :   side->set_p_level(this->p_level());
     225             : #endif
     226             :   // Set the nodes
     227          63 :   for (auto n : side->node_index_range())
     228          58 :     side->set_node(n, this->node_ptr(InfQuad6::side_nodes_map[i][n]));
     229             : }
     230             : 
     231             : 
     232             : 
     233           0 : void InfQuad6::connectivity(const unsigned int sf,
     234             :                             const IOPackage iop,
     235             :                             std::vector<dof_id_type> & conn) const
     236             : {
     237           0 :   libmesh_assert_less (sf, this->n_sub_elem());
     238           0 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
     239             : 
     240           0 :   conn.resize(4);
     241             : 
     242           0 :   switch (iop)
     243             :     {
     244           0 :     case TECPLOT:
     245             :       {
     246           0 :         switch(sf)
     247             :           {
     248           0 :           case 0:
     249             :             // linear sub-quad 0
     250           0 :             conn[0] = this->node_id(0)+1;
     251           0 :             conn[1] = this->node_id(4)+1;
     252           0 :             conn[2] = this->node_id(5)+1;
     253           0 :             conn[3] = this->node_id(2)+1;
     254             : 
     255           0 :             return;
     256             : 
     257           0 :           case 1:
     258             :             // linear sub-quad 1
     259           0 :             conn[0] = this->node_id(4)+1;
     260           0 :             conn[1] = this->node_id(1)+1;
     261           0 :             conn[2] = this->node_id(3)+1;
     262           0 :             conn[3] = this->node_id(5)+1;
     263             : 
     264           0 :             return;
     265             : 
     266           0 :           default:
     267           0 :             libmesh_error_msg("Invalid sf = " << sf);
     268             :           }
     269             :       }
     270             : 
     271           0 :     default:
     272           0 :       libmesh_error_msg("Unsupported IO package " << iop);
     273             :     }
     274             : }
     275             : 
     276             : 
     277             : 
     278             : 
     279           0 : unsigned short int InfQuad6::second_order_adjacent_vertex (const unsigned int n,
     280             :                                                            const unsigned int v) const
     281             : {
     282           0 :   libmesh_assert_greater_equal (n, this->n_vertices());
     283           0 :   libmesh_assert_less (n, this->n_nodes());
     284           0 :   libmesh_assert_less (v, 2);
     285           0 :   return _second_order_adjacent_vertices[n-this->n_vertices()][v];
     286             : }
     287             : 
     288             : 
     289             : 
     290             : const unsigned short int InfQuad6::_second_order_adjacent_vertices[2][2] =
     291             :   {
     292             :     {0, 1}, // vertices adjacent to node 4
     293             :     {2, 3}  // vertices adjacent to node 5
     294             :   };
     295             : 
     296             : 
     297             : 
     298             : std::pair<unsigned short int, unsigned short int>
     299           0 : InfQuad6::second_order_child_vertex (const unsigned int n) const
     300             : {
     301           0 :   libmesh_assert_greater_equal (n, this->n_vertices());
     302           0 :   libmesh_assert_less (n, this->n_nodes());
     303             : 
     304           0 :   return std::pair<unsigned short int, unsigned short int>
     305           0 :     (0, 2*n-7);
     306             : }
     307             : 
     308             : 
     309             : ElemType
     310          27 : InfQuad6::side_type (const unsigned int s) const
     311             : {
     312           9 :   libmesh_assert_less (s, 3);
     313          27 :   if (s == 0)
     314           9 :     return EDGE3;
     315           6 :   return INFEDGE2;
     316             : }
     317             : 
     318             : 
     319           5 : void InfQuad6::flip(BoundaryInfo * boundary_info)
     320             : {
     321           2 :   libmesh_assert(boundary_info);
     322             : 
     323           5 :   swap2nodes(0,1);
     324           5 :   swap2nodes(2,3);
     325           2 :   swap2neighbors(1,2);
     326           5 :   swap2boundarysides(1,2,boundary_info);
     327           5 :   swap2boundaryedges(1,2,boundary_info);
     328           5 : }
     329             : 
     330             : 
     331             : } // namespace libMesh
     332             : 
     333             : 
     334             : #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

Generated by: LCOV version 1.14