LCOV - code coverage report
Current view: top level - src/geom - cell_pyramid.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 83 111 74.8 %
Date: 2026-10-13 21:47:33 Functions: 12 14 85.7 %
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             : // C++ includes
      20             : 
      21             : // Local includes
      22             : #include "libmesh/cell_pyramid.h"
      23             : #include "libmesh/cell_pyramid5.h"
      24             : #include "libmesh/enum_elem_quality.h"
      25             : #include "libmesh/face_tri3.h"
      26             : #include "libmesh/face_quad4.h"
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : // ------------------------------------------------------------
      32             : // Pyramid class static member initializations
      33             : const int Pyramid::num_sides;
      34             : const int Pyramid::num_edges;
      35             : const int Pyramid::num_children;
      36             : 
      37             : const Real Pyramid::_master_points[18][3] =
      38             :   {
      39             :     {-1, -1, 0},
      40             :     {1, -1, 0},
      41             :     {1, 1, 0},
      42             :     {-1, 1, 0},
      43             :     {0, 0, 1},
      44             :     {0, -1, 0},
      45             :     {1, 0, 0},
      46             :     {0, 1, 0},
      47             :     {-1, 0, 0},
      48             :     {-0.5, -0.5, 0.5},
      49             :     {0.5, -0.5, 0.5},
      50             :     {0.5, 0.5, 0.5},
      51             :     {-0.5, 0.5, 0.5},
      52             :     {0, 0, 0},
      53             :     {0, -Real(2)/3, Real(1)/3},
      54             :     { Real(2)/3, 0, Real(1)/3},
      55             :     {0,  Real(2)/3, Real(1)/3},
      56             :     {-Real(2)/3, 0, Real(1)/3}
      57             :   };
      58             : 
      59             : const unsigned int Pyramid::edge_sides_map[8][2] =
      60             :   {
      61             :     {0, 4}, // Edge 0
      62             :     {1, 4}, // Edge 1
      63             :     {2, 4}, // Edge 2
      64             :     {3, 4}, // Edge 3
      65             :     {0, 3}, // Edge 4
      66             :     {0, 1}, // Edge 5
      67             :     {1, 2}, // Edge 6
      68             :     {2, 3}  // Edge 7
      69             :   };
      70             : 
      71             : const unsigned int Pyramid::adjacent_edges_map[/*num_vertices*/5][/*max_adjacent_edges*/4] =
      72             :   {
      73             :     {0, 3, 4, 99},  // Edges adjacent to node 0
      74             :     {0, 1, 5, 99},  // Edges adjacent to node 1
      75             :     {1, 2, 6, 99},  // Edges adjacent to node 2
      76             :     {2, 3, 7, 99},  // Edges adjacent to node 3
      77             :     {4, 5, 6,  7}   // Edges adjacent to node 4
      78             :   };
      79             : 
      80             : // ------------------------------------------------------------
      81             : // Pyramid class member functions
      82           0 : dof_id_type Pyramid::key (const unsigned int s) const
      83             : {
      84           0 :   libmesh_assert_less (s, this->n_sides());
      85             : 
      86           0 :   switch (s)
      87             :     {
      88           0 :     case 0: // triangular face 1
      89             :     case 1: // triangular face 2
      90             :     case 2: // triangular face 3
      91             :     case 3: // triangular face 4
      92           0 :       return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
      93           0 :                                 this->node_id(Pyramid5::side_nodes_map[s][1]),
      94           0 :                                 this->node_id(Pyramid5::side_nodes_map[s][2]));
      95             : 
      96           0 :     case 4:  // the quad face at z=0
      97           0 :       return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
      98           0 :                                 this->node_id(Pyramid5::side_nodes_map[s][1]),
      99           0 :                                 this->node_id(Pyramid5::side_nodes_map[s][2]),
     100           0 :                                 this->node_id(Pyramid5::side_nodes_map[s][3]));
     101             : 
     102           0 :     default:
     103           0 :       libmesh_error_msg("Invalid side s = " << s);
     104             :     }
     105             : }
     106             : 
     107             : 
     108             : 
     109     6270484 : dof_id_type Pyramid::low_order_key (const unsigned int s) const
     110             : {
     111      139468 :   libmesh_assert_less (s, this->n_sides());
     112             : 
     113     6270484 :   switch (s)
     114             :     {
     115     5052488 :     case 0: // triangular face 1
     116             :     case 1: // triangular face 2
     117             :     case 2: // triangular face 3
     118             :     case 3: // triangular face 4
     119     5164088 :       return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
     120     5052488 :                                 this->node_id(Pyramid5::side_nodes_map[s][1]),
     121     5164088 :                                 this->node_id(Pyramid5::side_nodes_map[s][2]));
     122             : 
     123     1217996 :     case 4:  // the quad face at z=0
     124     1245864 :       return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
     125     1217996 :                                 this->node_id(Pyramid5::side_nodes_map[s][1]),
     126     1217996 :                                 this->node_id(Pyramid5::side_nodes_map[s][2]),
     127     1245864 :                                 this->node_id(Pyramid5::side_nodes_map[s][3]));
     128             : 
     129           0 :     default:
     130           0 :       libmesh_error_msg("Invalid side s = " << s);
     131             :     }
     132             : }
     133             : 
     134             : 
     135             : 
     136       25486 : unsigned int Pyramid::local_side_node(unsigned int side,
     137             :                                       unsigned int side_node) const
     138             : {
     139        2116 :   libmesh_assert_less (side, this->n_sides());
     140             : 
     141             :   // Never more than 4 nodes per side.
     142        2116 :   libmesh_assert_less(side_node, Pyramid5::nodes_per_side);
     143             : 
     144             :   // Some sides have 3 nodes.
     145        2116 :   libmesh_assert(side == 4 || side_node < 3);
     146             : 
     147       25484 :   return Pyramid5::side_nodes_map[side][side_node];
     148             : }
     149             : 
     150             : 
     151             : 
     152      665379 : unsigned int Pyramid::local_edge_node(unsigned int edge,
     153             :                                       unsigned int edge_node) const
     154             : {
     155       55370 :   libmesh_assert_less(edge, this->n_edges());
     156       55370 :   libmesh_assert_less(edge_node, Pyramid5::nodes_per_edge);
     157             : 
     158      665379 :   return Pyramid5::edge_nodes_map[edge][edge_node];
     159             : }
     160             : 
     161             : 
     162             : 
     163     1286756 : std::unique_ptr<Elem> Pyramid::side_ptr (const unsigned int i)
     164             : {
     165       29132 :   libmesh_assert_less (i, this->n_sides());
     166             : 
     167             :   // Return value
     168     1286756 :   std::unique_ptr<Elem> face;
     169             : 
     170             :   // Set up the type of element
     171     1286756 :   switch (i)
     172             :     {
     173      665599 :     case 0: // triangular face 1
     174             :     case 1: // triangular face 2
     175             :     case 2: // triangular face 3
     176             :     case 3: // triangular face 4
     177             :       {
     178      665599 :         face = std::make_unique<Tri3>();
     179      665599 :         break;
     180             :       }
     181      621157 :     case 4:  // the quad face at z=0
     182             :       {
     183      621157 :         face = std::make_unique<Quad4>();
     184      621157 :         break;
     185             :       }
     186           0 :     default:
     187           0 :       libmesh_error_msg("Invalid side i = " << i);
     188             :     }
     189             : 
     190             :   // Set the nodes
     191     5768181 :   for (auto n : face->node_index_range())
     192     4582663 :     face->set_node(n, this->node_ptr(Pyramid5::side_nodes_map[i][n]));
     193             : 
     194     1286756 :   return face;
     195           0 : }
     196             : 
     197             : 
     198             : 
     199     5317032 : void Pyramid::side_ptr (std::unique_ptr<Elem> & side,
     200             :                         const unsigned int i)
     201             : {
     202      125892 :   libmesh_assert_less (i, this->n_sides());
     203             : 
     204     5317032 :   switch (i)
     205             :     {
     206      111952 :     case 0: // triangular face 1
     207             :     case 1: // triangular face 2
     208             :     case 2: // triangular face 3
     209             :     case 3: // triangular face 4
     210             :       {
     211     4683828 :         if (!side.get() || side->type() != TRI3)
     212             :           {
     213     1298962 :             side = this->side_ptr(i);
     214      664747 :             return;
     215             :           }
     216       96686 :         break;
     217             :       }
     218             : 
     219       13940 :     case 4:  // the quad face at z=0
     220             :       {
     221      633204 :         if (!side.get() || side->type() != QUAD4)
     222             :           {
     223     1214216 :             side = this->side_ptr(i);
     224      620944 :             return;
     225             :           }
     226         104 :         break;
     227             :       }
     228             : 
     229           0 :     default:
     230           0 :       libmesh_error_msg("Invalid side i = " << i);
     231             :     }
     232             : 
     233     4128131 :   side->subdomain_id() = this->subdomain_id();
     234             : 
     235             :   // Set the nodes
     236    16137624 :   for (auto n : side->node_index_range())
     237    12396757 :     side->set_node(n, this->node_ptr(Pyramid5::side_nodes_map[i][n]));
     238             : }
     239             : 
     240             : 
     241             : 
     242           0 : bool Pyramid::is_child_on_side(const unsigned int c,
     243             :                                const unsigned int s) const
     244             : {
     245           0 :   libmesh_assert_less (c, this->n_children());
     246           0 :   libmesh_assert_less (s, this->n_sides());
     247             : 
     248           0 :   for (unsigned int i = 0; i != 4; ++i)
     249           0 :     if (Pyramid5::side_nodes_map[s][i] == c)
     250           0 :       return true;
     251           0 :   return false;
     252             : }
     253             : 
     254             : 
     255             : 
     256       36864 : bool Pyramid::is_edge_on_side(const unsigned int e,
     257             :                               const unsigned int s) const
     258             : {
     259        3072 :   libmesh_assert_less (e, this->n_edges());
     260        3072 :   libmesh_assert_less (s, this->n_sides());
     261             : 
     262       36864 :   return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
     263             : }
     264             : 
     265             : 
     266             : 
     267      258048 : std::vector<unsigned int> Pyramid::sides_on_edge(const unsigned int e) const
     268             : {
     269       21504 :   libmesh_assert_less (e, this->n_edges());
     270      258048 :   return {edge_sides_map[e][0], edge_sides_map[e][1]};
     271             : }
     272             : 
     273             : 
     274             : bool
     275       22431 : Pyramid::is_flipped() const
     276             : {
     277       21087 :   return (triple_product(this->point(1)-this->point(0),
     278       21087 :                          this->point(3)-this->point(0),
     279       25119 :                          this->point(4)-this->point(0)) < 0);
     280             : }
     281             : 
     282             : std::vector<unsigned int>
     283      432000 : Pyramid::edges_adjacent_to_node(const unsigned int n) const
     284             : {
     285       36000 :   libmesh_assert_less(n, this->n_nodes());
     286      432000 :   if (this->is_vertex(n))
     287             :     {
     288      172800 :       auto trim = (n < 4) ? 1 : 0;
     289      172800 :       return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n]) - trim};
     290             :     }
     291      259200 :   else if (this->is_edge(n))
     292      207360 :     return {n - this->n_vertices()};
     293             : 
     294             :   // Not a vertex or edge node, so must be one of the face nodes.
     295        4320 :   libmesh_assert(this->is_face(n));
     296       47520 :   return {};
     297             : }
     298             : 
     299      675138 : unsigned int Pyramid::local_singular_node(const Point & p, const Real tol) const
     300             : {
     301      675138 :   return this->node_ref(4).absolute_fuzzy_equals(p, tol) ? 4 : invalid_uint;
     302             : }
     303             : 
     304             : 
     305     4766180 : bool Pyramid::on_reference_element(const Point & p,
     306             :                                    const Real eps) const
     307             : {
     308      131100 :   const Real & xi = p(0);
     309      131100 :   const Real & eta = p(1);
     310      131100 :   const Real & zeta = p(2);
     311             : 
     312             :   // Check that the point is on the same side of all the faces
     313             :   // by testing whether:
     314             :   //
     315             :   // n_i.(x - x_i) <= 0
     316             :   //
     317             :   // for each i, where:
     318             :   //   n_i is the outward normal of face i,
     319             :   //   x_i is a point on face i.
     320     7920228 :   return ((-eta - 1. + zeta <= 0.+eps) &&
     321     3154048 :           (  xi - 1. + zeta <= 0.+eps) &&
     322     1712699 :           ( eta - 1. + zeta <= 0.+eps) &&
     323     6178471 :           ( -xi - 1. + zeta <= 0.+eps) &&
     324     1310900 :           (            zeta >= 0.-eps));
     325             : }
     326             : 
     327             : 
     328             : 
     329       11520 : std::pair<Real, Real> Pyramid::qual_bounds (const ElemQuality) const
     330             : {
     331             :   // No suggested ranges have yet been established for any of the
     332             :   // metrics Quality::valid() lists for pyramids, so we always return
     333             :   // the (-1, -1) sentinel.
     334             :   libmesh_warning("Invalid quality measure chosen.");
     335       11520 :   return std::make_pair(Real(-1), Real(-1));
     336             : }
     337             : 
     338             : 
     339             : } // namespace libMesh

Generated by: LCOV version 1.14