LCOV - code coverage report
Current view: top level - src/geom - cell_pyramid18.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4554 (5a536d) with base 54e0d5 Lines: 128 163 78.5 %
Date: 2026-09-16 12:37:14 Functions: 19 24 79.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 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/cell_pyramid18.h"
      21             : #include "libmesh/fe_reference_element_traits.h"
      22             : #include "libmesh/edge_edge3.h"
      23             : #include "libmesh/face_tri7.h"
      24             : #include "libmesh/face_quad9.h"
      25             : #include "libmesh/enum_io_package.h"
      26             : #include "libmesh/enum_order.h"
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : 
      32             : 
      33             : 
      34             : // ------------------------------------------------------------
      35             : // Pyramid18 class static member initializations
      36             : const int Pyramid18::num_nodes;
      37             : const int Pyramid18::nodes_per_side;
      38             : const int Pyramid18::nodes_per_edge;
      39             : 
      40             : const ReferenceElementTable<Pyramid18::num_sides, Pyramid18::nodes_per_side>
      41             : Pyramid18::side_nodes_map = build_side_nodes<Pyramid18::num_sides, Pyramid18::nodes_per_side>(PYRAMID18);
      42             : 
      43             : const ReferenceElementTable<Pyramid18::num_edges, Pyramid18::nodes_per_edge>
      44             : Pyramid18::edge_nodes_map = pyramid_edge_nodes();
      45             : 
      46             : // ------------------------------------------------------------
      47             : // Pyramid18 class member functions
      48             : 
      49      106704 : bool Pyramid18::is_vertex(const unsigned int i) const
      50             : {
      51      106704 :   if (i < 5)
      52       46680 :     return true;
      53       16002 :   return false;
      54             : }
      55             : 
      56             : 
      57             : 
      58       14976 : bool Pyramid18::is_edge(const unsigned int i) const
      59             : {
      60       14976 :   if (i < 5)
      61           0 :     return false;
      62       14976 :   if (i > 12)
      63        5760 :     return false;
      64        2304 :   return true;
      65             : }
      66             : 
      67             : 
      68             : 
      69       39130 : bool Pyramid18::is_face(const unsigned int i) const
      70             : {
      71       39130 :   if (i > 12)
      72        8710 :     return true;
      73        7800 :   return false;
      74             : }
      75             : 
      76             : 
      77             : 
      78       30694 : bool Pyramid18::is_node_on_side(const unsigned int n,
      79             :                                 const unsigned int s) const
      80             : {
      81        7736 :   libmesh_assert_less (s, n_sides());
      82        7736 :   return std::find(std::begin(side_nodes_map[s]),
      83        7736 :                    std::end(side_nodes_map[s]),
      84       30694 :                    n) != std::end(side_nodes_map[s]);
      85             : }
      86             : 
      87             : std::vector<unsigned>
      88       16156 : Pyramid18::nodes_on_side(const unsigned int s) const
      89             : {
      90        4045 :   libmesh_assert_less(s, n_sides());
      91       16156 :   auto trim = (s == 4) ? 0 : 2;
      92       16156 :   return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
      93             : }
      94             : 
      95             : std::vector<unsigned>
      96       10752 : Pyramid18::nodes_on_edge(const unsigned int e) const
      97             : {
      98        2688 :   libmesh_assert_less(e, n_edges());
      99       10752 :   return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
     100             : }
     101             : 
     102       55968 : bool Pyramid18::is_node_on_edge(const unsigned int n,
     103             :                                 const unsigned int e) const
     104             : {
     105       14856 :   libmesh_assert_less (e, n_edges());
     106       14856 :   return std::find(std::begin(edge_nodes_map[e]),
     107       14856 :                    std::end(edge_nodes_map[e]),
     108       55968 :                    n) != std::end(edge_nodes_map[e]);
     109             : }
     110             : 
     111             : 
     112             : 
     113       18705 : bool Pyramid18::has_affine_map() const
     114             : {
     115             :   // TODO: If the base is a parallelogram and all the triangular faces are planar,
     116             :   // the map should be linear, but I need to test this theory...
     117       18705 :   return false;
     118             : }
     119             : 
     120             : 
     121             : 
     122     2110665 : Order Pyramid18::default_order() const
     123             : {
     124     2110665 :   return THIRD;
     125             : }
     126             : 
     127             : 
     128             : 
     129           0 : dof_id_type Pyramid18::key (const unsigned int s) const
     130             : {
     131           0 :   libmesh_assert_less (s, this->n_sides());
     132             : 
     133           0 :   switch (s)
     134             :     {
     135           0 :     case 0: // triangular face 1
     136             :     case 1: // triangular face 2
     137             :     case 2: // triangular face 3
     138             :     case 3: // triangular face 4
     139           0 :       return this->compute_key (this->node_id(s+14));
     140             : 
     141           0 :     case 4:  // the quad face at z=0
     142           0 :       return this->compute_key (this->node_id(13));
     143             : 
     144           0 :     default:
     145           0 :       libmesh_error_msg("Invalid side s = " << s);
     146             :     }
     147             : }
     148             : 
     149             : 
     150             : 
     151        7398 : unsigned int Pyramid18::local_side_node(unsigned int side,
     152             :                                         unsigned int side_node) const
     153             : {
     154        1860 :   libmesh_assert_less (side, this->n_sides());
     155             : 
     156             :   // Never more than 9 nodes per side.
     157        1860 :   libmesh_assert_less(side_node, Pyramid18::nodes_per_side);
     158             : 
     159             :   // Some sides have 7 nodes.
     160        1860 :   libmesh_assert(side == 4 || side_node < 7);
     161             : 
     162        7398 :   return Pyramid18::side_nodes_map[side][side_node];
     163             : }
     164             : 
     165             : 
     166             : 
     167       44572 : unsigned int Pyramid18::local_edge_node(unsigned int edge,
     168             :                                         unsigned int edge_node) const
     169             : {
     170       11144 :   libmesh_assert_less(edge, this->n_edges());
     171       11144 :   libmesh_assert_less(edge_node, Pyramid18::nodes_per_edge);
     172             : 
     173       44572 :   return Pyramid18::edge_nodes_map[edge][edge_node];
     174             : }
     175             : 
     176             : 
     177             : 
     178       43620 : std::unique_ptr<Elem> Pyramid18::build_side_ptr (const unsigned int i)
     179             : {
     180       13848 :   libmesh_assert_less (i, this->n_sides());
     181             : 
     182       43620 :   std::unique_ptr<Elem> face;
     183             : 
     184       43620 :   switch (i)
     185             :     {
     186       22695 :     case 0: // triangular face 1
     187             :     case 1: // triangular face 2
     188             :     case 2: // triangular face 3
     189             :     case 3: // triangular face 4
     190             :       {
     191       22695 :         face = std::make_unique<Tri7>();
     192       22695 :         break;
     193             :       }
     194       20925 :     case 4: // the quad face at z=0
     195             :       {
     196       20925 :         face = std::make_unique<Quad9>();
     197       20925 :         break;
     198             :       }
     199           0 :     default:
     200           0 :       libmesh_error_msg("Invalid side i = " << i);
     201             :     }
     202             : 
     203             :   // Set the nodes
     204      390810 :   for (auto n : face->node_index_range())
     205      457530 :     face->set_node(n, this->node_ptr(Pyramid18::side_nodes_map[i][n]));
     206             : 
     207       43620 :   face->set_interior_parent(this);
     208       29772 :   face->inherit_data_from(*this);
     209             : 
     210       43620 :   return face;
     211           0 : }
     212             : 
     213             : 
     214             : 
     215       83424 : void Pyramid18::build_side_ptr (std::unique_ptr<Elem> & side,
     216             :                                 const unsigned int i)
     217             : {
     218       26736 :   libmesh_assert_less (i, this->n_sides());
     219             : 
     220       83424 :   switch (i)
     221             :     {
     222       20088 :     case 0: // triangular face 1
     223             :     case 1: // triangular face 2
     224             :     case 2: // triangular face 3
     225             :     case 3: // triangular face 4
     226             :       {
     227       62712 :         if (!side.get() || side->type() != TRI7)
     228             :           {
     229         298 :             side = this->build_side_ptr(i);
     230         199 :             return;
     231             :           }
     232       20038 :         break;
     233             :       }
     234        6648 :     case 4:  // the quad face at z=0
     235             :       {
     236       20712 :         if (!side.get() || side->type() != QUAD9)
     237             :           {
     238       27562 :             side = this->build_side_ptr(i);
     239       20335 :             return;
     240             :           }
     241          94 :         break;
     242             :       }
     243           0 :     default:
     244           0 :       libmesh_error_msg("Invalid side i = " << i);
     245             :     }
     246             : 
     247       42758 :   side->inherit_data_from(*this);
     248             : 
     249             :   // Set the nodes
     250      503874 :   for (auto n : side->node_index_range())
     251      582096 :     side->set_node(n, this->node_ptr(Pyramid18::side_nodes_map[i][n]));
     252             : }
     253             : 
     254             : 
     255             : 
     256           0 : std::unique_ptr<Elem> Pyramid18::build_edge_ptr (const unsigned int i)
     257             : {
     258           0 :   return this->simple_build_edge_ptr<Edge3,Pyramid18>(i);
     259             : }
     260             : 
     261             : 
     262             : 
     263           0 : void Pyramid18::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
     264             : {
     265           0 :   this->simple_build_edge_ptr<Pyramid18>(edge, i, EDGE3);
     266           0 : }
     267             : 
     268             : 
     269             : 
     270           0 : void Pyramid18::connectivity(const unsigned int libmesh_dbg_var(sc),
     271             :                              const IOPackage iop,
     272             :                              std::vector<dof_id_type> & /*conn*/) const
     273             : {
     274           0 :   libmesh_assert(_nodes);
     275           0 :   libmesh_assert_less (sc, this->n_sub_elem());
     276           0 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
     277             : 
     278           0 :   switch (iop)
     279             :     {
     280           0 :     case TECPLOT:
     281             :       {
     282             :         // TODO
     283           0 :         libmesh_not_implemented();
     284             :       }
     285             : 
     286           0 :     case VTK:
     287             :       {
     288             :         // TODO
     289           0 :         libmesh_not_implemented();
     290             :       }
     291             : 
     292           0 :     default:
     293           0 :       libmesh_error_msg("Unsupported IO package " << iop);
     294             :     }
     295             : }
     296             : 
     297             : 
     298             : 
     299      116298 : unsigned int Pyramid18::n_second_order_adjacent_vertices (const unsigned int n) const
     300             : {
     301       33228 :   switch (n)
     302             :     {
     303       20448 :     case 5:
     304             :     case 6:
     305             :     case 7:
     306             :     case 8:
     307             :     case 9:
     308             :     case 10:
     309             :     case 11:
     310             :     case 12:
     311       20448 :       return 2;
     312             : 
     313        2556 :     case 13:
     314        2556 :       return 4;
     315             : 
     316       10224 :     case 14:
     317             :     case 15:
     318             :     case 16:
     319             :     case 17:
     320       10224 :       return 3;
     321             : 
     322           0 :     default:
     323           0 :       libmesh_error_msg("Invalid node n = " << n);
     324             :     }
     325             : }
     326             : 
     327             : 
     328      286272 : unsigned short int Pyramid18::second_order_adjacent_vertex (const unsigned int n,
     329             :                                                             const unsigned int v) const
     330             : {
     331       81792 :   libmesh_assert_greater_equal (n, this->n_vertices());
     332       81792 :   libmesh_assert_less (n, this->n_nodes());
     333             : 
     334      286272 :   switch (n)
     335             :     {
     336      143136 :     case 5:
     337             :     case 6:
     338             :     case 7:
     339             :     case 8:
     340             :     case 9:
     341             :     case 10:
     342             :     case 11:
     343             :     case 12:
     344             :       {
     345       40896 :         libmesh_assert_less (v, 2);
     346             : 
     347             :         // This is the analog of the static, const arrays
     348             :         // {Hex,Prism,Tet10}::_second_order_adjacent_vertices
     349             :         // defined in the respective source files... possibly treat
     350             :         // this similarly once the Pyramid13 has been added?
     351      143136 :         constexpr unsigned short node_list[8][2] =
     352             :           {
     353             :             {0,1},
     354             :             {1,2},
     355             :             {2,3},
     356             :             {0,3},
     357             :             {0,4},
     358             :             {1,4},
     359             :             {2,4},
     360             :             {3,4}
     361             :           };
     362             : 
     363      143136 :         return node_list[n-5][v];
     364             :       }
     365             : 
     366             :       // mid-face node on bottom
     367       10224 :     case 13:
     368             :       {
     369       10224 :         libmesh_assert_less (v, 4);
     370             : 
     371             :         // The vertex nodes surrounding node 13 are 0, 1, 2, and 3.
     372             :         // Thus, the v'th node is simply = v.
     373       35784 :         return cast_int<unsigned short>(v);
     374             :       }
     375             : 
     376             :       // mid-face nodes on triangles
     377      107352 :     case 14:
     378             :     case 15:
     379             :     case 16:
     380             :     case 17:
     381             :       {
     382       30672 :         libmesh_assert_less (v, 3);
     383             : 
     384      107352 :         constexpr unsigned short node_list[4][3] =
     385             :           {
     386             :             {0,1,4},
     387             :             {1,2,4},
     388             :             {2,3,4},
     389             :             {0,3,4}
     390             :           };
     391             : 
     392      107352 :         return node_list[n-14][v];
     393             :       }
     394             : 
     395           0 :     default:
     396           0 :       libmesh_error_msg("Invalid n = " << n);
     397             : 
     398             :     }
     399             : }
     400             : 
     401             : 
     402             : 
     403        1188 : void Pyramid18::permute(unsigned int perm_num)
     404             : {
     405         312 :   libmesh_assert_less (perm_num, 4);
     406             : 
     407        2900 :   for (unsigned int i = 0; i != perm_num; ++i)
     408             :     {
     409        1712 :       swap4nodes(0,1,2,3);
     410        1712 :       swap4nodes(5,6,7,8);
     411        1712 :       swap4nodes(9,10,11,12);
     412        1712 :       swap4nodes(14,15,16,17);
     413        1264 :       swap4neighbors(0,1,2,3);
     414             :     }
     415        1188 : }
     416             : 
     417             : 
     418         576 : void Pyramid18::flip(BoundaryInfo * boundary_info)
     419             : {
     420         144 :   libmesh_assert(boundary_info);
     421             : 
     422         576 :   swap2nodes(0,1);
     423         576 :   swap2nodes(2,3);
     424         576 :   swap2nodes(6,8);
     425         576 :   swap2nodes(9,10);
     426         576 :   swap2nodes(11,12);
     427         576 :   swap2nodes(15,17);
     428         144 :   swap2neighbors(1,3);
     429         576 :   swap2boundarysides(1,3,boundary_info);
     430         576 :   swap2boundaryedges(1,3,boundary_info);
     431         576 :   swap2boundaryedges(4,5,boundary_info);
     432         576 :   swap2boundaryedges(6,7,boundary_info);
     433         576 : }
     434             : 
     435             : 
     436         960 : unsigned int Pyramid18::center_node_on_side(const unsigned short side) const
     437             : {
     438         240 :   libmesh_assert_less (side, Pyramid18::num_sides);
     439         960 :   return side == 4 ? 13 : side+14;
     440             : }
     441             : 
     442             : 
     443        2880 : ElemType Pyramid18::side_type (const unsigned int s) const
     444             : {
     445         720 :   libmesh_assert_less (s, 5);
     446        2880 :   if (s < 4)
     447        2304 :     return TRI7;
     448         144 :   return QUAD9;
     449             : }
     450             : 
     451             : 
     452             : } // namespace libMesh

Generated by: LCOV version 1.14