LCOV - code coverage report
Current view: top level - src/geom - cell_pyramid5.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 106 145 73.1 %
Date: 2026-10-13 21:47:33 Functions: 17 22 77.3 %
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_pyramid5.h"
      21             : #include "libmesh/edge_edge2.h"
      22             : #include "libmesh/face_tri3.h"
      23             : #include "libmesh/face_quad4.h"
      24             : #include "libmesh/enum_io_package.h"
      25             : #include "libmesh/enum_order.h"
      26             : #include "libmesh/cell_hex8.h"
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : 
      32             : 
      33             : 
      34             : // ------------------------------------------------------------
      35             : // Pyramid5 class static member initializations
      36             : const int Pyramid5::num_nodes;
      37             : const int Pyramid5::nodes_per_side;
      38             : const int Pyramid5::nodes_per_edge;
      39             : 
      40             : // ------------------------------------------------------------
      41             : // Pyramid5 class member functions
      42             : 
      43     4888860 : bool Pyramid5::is_vertex(const unsigned int libmesh_dbg_var(n)) const
      44             : {
      45      162720 :   libmesh_assert_not_equal_to (n, invalid_uint);
      46     4888860 :   return true;
      47             : }
      48             : 
      49           0 : bool Pyramid5::is_edge(const unsigned int) const
      50             : {
      51           0 :   return false;
      52             : }
      53             : 
      54           0 : bool Pyramid5::is_face(const unsigned int) const
      55             : {
      56           0 :   return false;
      57             : }
      58             : 
      59      158447 : bool Pyramid5::is_node_on_side(const unsigned int n,
      60             :                                const unsigned int s) const
      61             : {
      62       13106 :   libmesh_assert_less (s, n_sides());
      63       13106 :   return std::find(std::begin(side_nodes_map[s]),
      64      158447 :                    std::end(side_nodes_map[s]),
      65      158447 :                    n) != std::end(side_nodes_map[s]);
      66             : }
      67             : 
      68             : std::vector<unsigned>
      69      181412 : Pyramid5::nodes_on_side(const unsigned int s) const
      70             : {
      71       14986 :   libmesh_assert_less(s, n_sides());
      72      181412 :   auto trim = (s == 4) ? 0 : 1;
      73      181412 :   return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
      74             : }
      75             : 
      76             : std::vector<unsigned>
      77       28216 : Pyramid5::nodes_on_edge(const unsigned int e) const
      78             : {
      79        2320 :   libmesh_assert_less(e, n_edges());
      80       30536 :   return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
      81             : }
      82             : 
      83     3528824 : bool Pyramid5::is_node_on_edge(const unsigned int n,
      84             :                                const unsigned int e) const
      85             : {
      86      113432 :   libmesh_assert_less (e, n_edges());
      87      113432 :   return std::find(std::begin(edge_nodes_map[e]),
      88     3528824 :                    std::end(edge_nodes_map[e]),
      89     3528824 :                    n) != std::end(edge_nodes_map[e]);
      90             : }
      91             : 
      92             : 
      93             : 
      94      148937 : bool Pyramid5::has_affine_map() const
      95             : {
      96             :   //  Point v = this->point(3) - this->point(0);
      97             :   //  return (v.relative_fuzzy_equals(this->point(2) - this->point(1)));
      98      148937 :   return false;
      99             : }
     100             : 
     101             : 
     102             : 
     103     3720160 : Order Pyramid5::default_order() const
     104             : {
     105     3720160 :   return FIRST;
     106             : }
     107             : 
     108             : 
     109             : 
     110       10060 : std::unique_ptr<Elem> Pyramid5::build_side_ptr (const unsigned int i)
     111             : {
     112         760 :   libmesh_assert_less (i, this->n_sides());
     113             : 
     114       10060 :   std::unique_ptr<Elem> face;
     115             : 
     116       10060 :   switch (i)
     117             :     {
     118        8048 :     case 0: // triangular face 1
     119             :     case 1: // triangular face 2
     120             :     case 2: // triangular face 3
     121             :     case 3: // triangular face 4
     122             :       {
     123        8048 :         face = std::make_unique<Tri3>();
     124        8048 :         break;
     125             :       }
     126        2012 :     case 4: // the quad face at z=0
     127             :       {
     128        2012 :         face = std::make_unique<Quad4>();
     129        2012 :         break;
     130             :       }
     131           0 :     default:
     132           0 :       libmesh_error_msg("Invalid side i = " << i);
     133             :     }
     134             : 
     135             :   // Set the nodes
     136       42252 :   for (auto n : face->node_index_range())
     137       34624 :     face->set_node(n, this->node_ptr(Pyramid5::side_nodes_map[i][n]));
     138             : 
     139       10060 :   face->set_interior_parent(this);
     140        9300 :   face->inherit_data_from(*this);
     141             : 
     142       10060 :   return face;
     143           0 : }
     144             : 
     145             : 
     146             : 
     147        9421 : void Pyramid5::build_side_ptr (std::unique_ptr<Elem> & side,
     148             :                                const unsigned int i)
     149             : {
     150        9421 :   this->side_ptr(side, i);
     151        9421 :   side->set_interior_parent(this);
     152        8679 :   side->inherit_data_from(*this);
     153        9421 : }
     154             : 
     155             : 
     156             : 
     157        6312 : std::unique_ptr<Elem> Pyramid5::build_edge_ptr (const unsigned int i)
     158             : {
     159        6312 :   return this->simple_build_edge_ptr<Edge2,Pyramid5>(i);
     160             : }
     161             : 
     162             : 
     163             : 
     164           0 : void Pyramid5::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
     165             : {
     166           0 :   this->simple_build_edge_ptr<Pyramid5>(edge, i, EDGE2);
     167           0 : }
     168             : 
     169             : 
     170             : 
     171           0 : void Pyramid5::connectivity(const unsigned int libmesh_dbg_var(sc),
     172             :                             const IOPackage iop,
     173             :                             std::vector<dof_id_type> & conn) const
     174             : {
     175           0 :   libmesh_assert(_nodes);
     176           0 :   libmesh_assert_less (sc, this->n_sub_elem());
     177           0 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
     178             : 
     179           0 :   switch (iop)
     180             :     {
     181           0 :     case TECPLOT:
     182             :       {
     183           0 :         conn.resize(8);
     184           0 :         conn[0] = this->node_id(0)+1;
     185           0 :         conn[1] = this->node_id(1)+1;
     186           0 :         conn[2] = this->node_id(2)+1;
     187           0 :         conn[3] = this->node_id(3)+1;
     188           0 :         conn[4] = this->node_id(4)+1;
     189           0 :         conn[5] = this->node_id(4)+1;
     190           0 :         conn[6] = this->node_id(4)+1;
     191           0 :         conn[7] = this->node_id(4)+1;
     192           0 :         return;
     193             :       }
     194             : 
     195           0 :     case VTK:
     196             :       {
     197           0 :         conn.resize(5);
     198           0 :         conn[0] = this->node_id(3);
     199           0 :         conn[1] = this->node_id(2);
     200           0 :         conn[2] = this->node_id(1);
     201           0 :         conn[3] = this->node_id(0);
     202           0 :         conn[4] = this->node_id(4);
     203           0 :         return;
     204             :       }
     205             : 
     206           0 :     default:
     207           0 :       libmesh_error_msg("Unsupported IO package " << iop);
     208             :     }
     209             : }
     210             : 
     211             : 
     212        6359 : Point Pyramid5::true_centroid () const
     213             : {
     214             :   // Call Hex8 static helper function, passing 4 copies of the final
     215             :   // vertex point, effectively treating the Pyramid as a degenerate
     216             :   // hexahedron.  In my testing, this still seems to give correct
     217             :   // results.
     218        5683 :   return Hex8::centroid_from_points(
     219             :     point(0), point(1), point(2), point(3),
     220        6697 :     point(4), point(4), point(4), point(4));
     221             : }
     222             : 
     223             : 
     224             : 
     225        8089 : Real Pyramid5::volume () const
     226             : {
     227             :   // This specialization is good for Lagrange mappings only in general
     228        8089 :   if (this->mapping_type() != LAGRANGE_MAP)
     229           0 :     return this->Elem::volume();
     230             : 
     231             :   // The pyramid with a bilinear base has volume given by the
     232             :   // formula in: "Calculation of the Volume of a General Hexahedron
     233             :   // for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954-
     234             :   Point
     235        9535 :     x0 = point(0), x1 = point(1), x2 = point(2),
     236        8571 :     x3 = point(3), x4 = point(4);
     237             : 
     238             :   // Construct various edge and diagonal vectors.
     239         484 :   Point v40 = x0 - x4;
     240         484 :   Point v13 = x3 - x1;
     241         484 :   Point v02 = x2 - x0;
     242         484 :   Point v03 = x3 - x0;
     243         484 :   Point v01 = x1 - x0;
     244             : 
     245             :   // Finally, ready to return the volume!
     246             :   return
     247        8089 :     triple_product(v40, v13, v02) / 6. +
     248        8089 :     triple_product(v02, v01, v03) / 12.;
     249             : }
     250             : 
     251             : BoundingBox
     252      224652 : Pyramid5::loose_bounding_box () const
     253             : {
     254      224652 :   return Elem::loose_bounding_box();
     255             : }
     256             : 
     257       10224 : void Pyramid5::permute(unsigned int perm_num)
     258             : {
     259         720 :   libmesh_assert_less (perm_num, 4);
     260             : 
     261       25008 :   for (unsigned int i = 0; i != perm_num; ++i)
     262             :     {
     263       14784 :       swap4nodes(0,1,2,3);
     264       13728 :       swap4neighbors(0,1,2,3);
     265             :     }
     266       10224 : }
     267             : 
     268             : 
     269        1728 : void Pyramid5::flip(BoundaryInfo * boundary_info)
     270             : {
     271         144 :   libmesh_assert(boundary_info);
     272             : 
     273        1728 :   swap2nodes(0,1);
     274        1728 :   swap2nodes(2,3);
     275         144 :   swap2neighbors(1,3);
     276        1728 :   swap2boundarysides(1,3,boundary_info);
     277        1728 :   swap2boundaryedges(1,3,boundary_info);
     278        1728 :   swap2boundaryedges(4,5,boundary_info);
     279        1728 :   swap2boundaryedges(6,7,boundary_info);
     280        1728 : }
     281             : 
     282             : 
     283       56448 : ElemType Pyramid5::side_type (const unsigned int s) const
     284             : {
     285        4704 :   libmesh_assert_less (s, 5);
     286       56448 :   if (s < 4)
     287       46080 :     return TRI3;
     288         864 :   return QUAD4;
     289             : }
     290             : 
     291             : 
     292             : Point
     293         355 : Pyramid5::side_vertex_average_normal(const unsigned int s) const
     294             : {
     295          10 :   libmesh_assert_less (s, 5);
     296          10 :   libmesh_assert_equal_to(this->mapping_type(), LAGRANGE_MAP);
     297             : 
     298         355 :   switch (s)
     299             :     {
     300         284 :     case 0: // triangular face 1
     301             :     case 1: // triangular face 2
     302             :     case 2: // triangular face 3
     303             :     case 3: // triangular face 4
     304             :       {
     305         300 :         const Point n1 = this->point(side_nodes_map[s][1]) -
     306         284 :                          this->point(side_nodes_map[s][0]);
     307         300 :         const Point n2 = this->point(side_nodes_map[s][2]) -
     308           8 :                          this->point(side_nodes_map[s][1]);
     309         276 :         const Point pointing_out = n1.cross(n2);
     310         284 :         return pointing_out.unit();
     311             :       }
     312           2 :     case 4: // the quad face at z=0
     313             :       {
     314             :         // At the side vertex average, things simplify a bit
     315             :         // We get the side "plane" normal at all vertices, then average them
     316           2 :         Point normal;
     317          75 :         Point current_edge = this->point(side_nodes_map[s][1]) -
     318          71 :                              this->point(side_nodes_map[s][0]);
     319         355 :         for (auto i : make_range(4))
     320             :         {
     321         300 :           const Point next_edge = this->point(side_nodes_map[s][(i + 2) % 4]) -
     322         284 :                                   this->point(side_nodes_map[s][(i + 1) % 4]);
     323         276 :           const Point normal_at_vertex = current_edge.cross(next_edge);
     324           8 :           normal += normal_at_vertex;
     325         276 :           current_edge = next_edge;
     326             :         }
     327           2 :         normal /= 4;
     328          71 :         return normal.unit();
     329             :       }
     330           0 :     default:
     331           0 :       libmesh_error_msg("Invalid side s = " << s);
     332             :     }
     333             : }
     334             : 
     335             : 
     336             : } // namespace libMesh

Generated by: LCOV version 1.14