LCOV - code coverage report
Current view: top level - src/geom - cell_prism.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 87 111 78.4 %
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_prism.h"
      23             : #include "libmesh/cell_prism6.h"
      24             : #include "libmesh/enum_elem_quality.h"
      25             : #include "libmesh/face_quad4.h"
      26             : #include "libmesh/face_tri3.h"
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : 
      32             : // ------------------------------------------------------------
      33             : // Prism class static member initializations
      34             : const int Prism::num_sides;
      35             : const int Prism::num_edges;
      36             : const int Prism::num_children;
      37             : 
      38             : const Real Prism::_master_points[21][3] =
      39             :   {
      40             :     {0, 0, -1},
      41             :     {1, 0, -1},
      42             :     {0, 1, -1},
      43             :     {0, 0, 1},
      44             :     {1, 0, 1},
      45             :     {0, 1, 1},
      46             :     {0.5, 0, -1},
      47             :     {0.5, 0.5, -1},
      48             :     {0, 0.5, -1},
      49             :     {0, 0, 0},
      50             :     {1, 0, 0},
      51             :     {0, 1, 0},
      52             :     {0.5, 0, 1},
      53             :     {0.5, 0.5, 1},
      54             :     {0, 0.5, 1},
      55             :     {0.5, 0, 0},
      56             :     {0.5, 0.5, 0},
      57             :     {0, 0.5, 0},
      58             :     {Real(1)/3, Real(1)/3, -1},
      59             :     {Real(1)/3, Real(1)/3, 1},
      60             :     {Real(1)/3, Real(1)/3, 0}
      61             :   };
      62             : 
      63             : const unsigned int Prism::edge_sides_map[9][2] =
      64             :   {
      65             :     {0, 1}, // Edge 0
      66             :     {0, 2}, // Edge 1
      67             :     {0, 3}, // Edge 2
      68             :     {1, 3}, // Edge 3
      69             :     {1, 2}, // Edge 4
      70             :     {2, 3}, // Edge 5
      71             :     {1, 4}, // Edge 6
      72             :     {2, 4}, // Edge 7
      73             :     {3, 4}  // Edge 8
      74             :   };
      75             : 
      76             : const unsigned int Prism::adjacent_edges_map[/*num_vertices*/6][/*n_adjacent_edges*/3] =
      77             :   {
      78             :     {0, 2, 3},  // Edges adjacent to node 0
      79             :     {0, 1, 4},  // Edges adjacent to node 1
      80             :     {1, 2, 5},  // Edges adjacent to node 2
      81             :     {3, 6, 8},  // Edges adjacent to node 3
      82             :     {4, 6, 7},  // Edges adjacent to node 4
      83             :     {5, 7, 8},  // Edges adjacent to node 5
      84             :   };
      85             : 
      86             : 
      87             : // ------------------------------------------------------------
      88             : // Prism class member functions
      89           0 : dof_id_type Prism::key (const unsigned int s) const
      90             : {
      91           0 :   libmesh_assert_less (s, this->n_sides());
      92             : 
      93           0 :   switch (s)
      94             :     {
      95           0 :     case 0: // the triangular face at z=0
      96             :     case 4: // the triangular face at z=1
      97           0 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
      98           0 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
      99           0 :                                 this->node_id(Prism6::side_nodes_map[s][2]));
     100             : 
     101           0 :     case 1: // the quad face at y=0
     102             :     case 2: // the other quad face
     103             :     case 3: // the quad face at x=0
     104           0 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
     105           0 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
     106           0 :                                 this->node_id(Prism6::side_nodes_map[s][2]),
     107           0 :                                 this->node_id(Prism6::side_nodes_map[s][3]));
     108             : 
     109           0 :     default:
     110           0 :       libmesh_error_msg("Invalid side " << s);
     111             :     }
     112             : }
     113             : 
     114             : 
     115             : 
     116     5327330 : dof_id_type Prism::low_order_key (const unsigned int s) const
     117             : {
     118      237760 :   libmesh_assert_less (s, this->n_sides());
     119             : 
     120     5327330 :   switch (s)
     121             :     {
     122     2119343 :     case 0: // the triangular face at z=0
     123             :     case 4: // the triangular face at z=1
     124     2214447 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
     125     2119343 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
     126     2214447 :                                 this->node_id(Prism6::side_nodes_map[s][2]));
     127             : 
     128     3207987 :     case 1: // the quad face at y=0
     129             :     case 2: // the other quad face
     130             :     case 3: // the quad face at x=0
     131     3350643 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
     132     3207987 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
     133     3207987 :                                 this->node_id(Prism6::side_nodes_map[s][2]),
     134     3350643 :                                 this->node_id(Prism6::side_nodes_map[s][3]));
     135             : 
     136           0 :     default:
     137           0 :       libmesh_error_msg("Invalid side " << s);
     138             :     }
     139             : }
     140             : 
     141             : 
     142             : 
     143   295832854 : unsigned int Prism::local_side_node(unsigned int side,
     144             :                                     unsigned int side_node) const
     145             : {
     146    26436500 :   libmesh_assert_less (side, this->n_sides());
     147             : 
     148             :   // Never more than 4 nodes per side.
     149    26436500 :   libmesh_assert_less(side_node, Prism6::nodes_per_side);
     150             : 
     151             :   // Some sides have 3 nodes.
     152    26436500 :   libmesh_assert(!(side==0 || side==4) || side_node < 3);
     153             : 
     154   295832852 :   return Prism6::side_nodes_map[side][side_node];
     155             : }
     156             : 
     157             : 
     158             : 
     159    35517078 : unsigned int Prism::local_edge_node(unsigned int edge,
     160             :                                     unsigned int edge_node) const
     161             : {
     162     3171564 :   libmesh_assert_less(edge, this->n_edges());
     163     3171564 :   libmesh_assert_less(edge_node, Prism6::nodes_per_edge);
     164             : 
     165    35517078 :   return Prism6::edge_nodes_map[edge][edge_node];
     166             : }
     167             : 
     168             : 
     169             : 
     170     2035233 : std::unique_ptr<Elem> Prism::side_ptr (const unsigned int i)
     171             : {
     172      107354 :   libmesh_assert_less (i, this->n_sides());
     173             : 
     174     2035233 :   std::unique_ptr<Elem> face;
     175             : 
     176             :   // Set up the type of element
     177     2035233 :   switch (i)
     178             :     {
     179      968773 :     case 0: // the triangular face at z=0
     180             :     case 4: // the triangular face at z=1
     181             :       {
     182      968773 :         face = std::make_unique<Tri3>();
     183      968773 :         break;
     184             :       }
     185     1066460 :     case 1: // the quad face at y=0
     186             :     case 2: // the other quad face
     187             :     case 3: // the quad face at x=0
     188             :       {
     189     1066460 :         face = std::make_unique<Quad4>();
     190     1066460 :         break;
     191             :       }
     192           0 :     default:
     193           0 :       libmesh_error_msg("Invalid side i = " << i);
     194             :     }
     195             : 
     196             :   // Set the nodes
     197     9207392 :   for (auto n : face->node_index_range())
     198     7549217 :     face->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
     199             : 
     200     2035233 :   return face;
     201           0 : }
     202             : 
     203             : 
     204             : 
     205     3666521 : void Prism::side_ptr (std::unique_ptr<Elem> & side,
     206             :                       const unsigned int i)
     207             : {
     208      192334 :   libmesh_assert_less (i, this->n_sides());
     209             : 
     210     3666521 :   switch (i)
     211             :     {
     212             :       // the base face
     213       73008 :     case 0: // the triangular face at z=0
     214             :     case 4: // the triangular face at z=1
     215             :       {
     216     1319992 :         if (!side.get() || side->type() != TRI3)
     217             :           {
     218     1831444 :             side = this->side_ptr(i);
     219      968058 :             return;
     220             :           }
     221       20672 :         break;
     222             :       }
     223             : 
     224      119326 :     case 1: // the quad face at y=0
     225             :     case 2: // the other quad face
     226             :     case 3: // the quad face at x=0
     227             :       {
     228     2346529 :         if (!side.get() || side->type() != QUAD4)
     229             :           {
     230     2020858 :             side = this->side_ptr(i);
     231     1065395 :             return;
     232             :           }
     233       64360 :         break;
     234             :       }
     235             : 
     236           0 :     default:
     237           0 :       libmesh_error_msg("Invalid side i = " << i);
     238             :     }
     239             : 
     240     1718100 :   side->subdomain_id() = this->subdomain_id();
     241             : 
     242             :   // Set the nodes
     243     7813406 :   for (auto n : side->node_index_range())
     244     6499794 :     side->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
     245             : }
     246             : 
     247             : 
     248             : 
     249     9077437 : bool Prism::is_child_on_side(const unsigned int c,
     250             :                              const unsigned int s) const
     251             : {
     252      547932 :   libmesh_assert_less (c, this->n_children());
     253      547932 :   libmesh_assert_less (s, this->n_sides());
     254             : 
     255    34008071 :   for (unsigned int i = 0; i != 4; ++i)
     256    29480391 :     if (Prism6::side_elems_map[s][i] == c)
     257      242584 :       return true;
     258      305348 :   return false;
     259             : }
     260             : 
     261             : 
     262             : 
     263     3364720 : bool Prism::is_edge_on_side(const unsigned int e,
     264             :                             const unsigned int s) const
     265             : {
     266     2886286 :   libmesh_assert_less (e, this->n_edges());
     267     2886286 :   libmesh_assert_less (s, this->n_sides());
     268             : 
     269     3364720 :   return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
     270             : }
     271             : 
     272             : 
     273             : 
     274      155520 : std::vector<unsigned int> Prism::sides_on_edge(const unsigned int e) const
     275             : {
     276       12960 :   libmesh_assert_less(e, this->n_edges());
     277             : 
     278      155520 :   return {edge_sides_map[e][0], edge_sides_map[e][1]};
     279             : }
     280             : 
     281             : 
     282             : 
     283           0 : unsigned int Prism::opposite_side(const unsigned int side_in) const
     284             : {
     285           0 :   libmesh_assert_less (side_in, 5);
     286             :   static const unsigned int prism_opposites[5] =
     287             :     {4, invalid_uint, invalid_uint, invalid_uint, 0};
     288           0 :   return prism_opposites[side_in];
     289             : }
     290             : 
     291             : 
     292             : 
     293             : bool
     294        9428 : Prism::is_flipped() const
     295             : {
     296        8868 :   return (triple_product(this->point(1)-this->point(0),
     297        8868 :                         this->point(2)-this->point(0),
     298       10548 :                         this->point(3)-this->point(0)) < 0);
     299             : }
     300             : 
     301             : 
     302             : std::vector<unsigned int>
     303      291840 : Prism::edges_adjacent_to_node(const unsigned int n) const
     304             : {
     305       24320 :   libmesh_assert_less(n, this->n_nodes());
     306             : 
     307             :   // For vertices, we use the Prism::adjacent_sides_map, otherwise each
     308             :   // of the mid-edge nodes is adjacent only to the edge it is on, and
     309             :   // face/internal nodes are not adjacent to any edge.
     310      291840 :   if (this->is_vertex(n))
     311      118560 :     return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n])};
     312      182400 :   else if (this->is_edge(n))
     313      131328 :     return {n - this->n_vertices()};
     314             : 
     315        4256 :   libmesh_assert(this->is_face(n) || this->is_internal(n));
     316       46816 :   return {};
     317             : }
     318             : 
     319             : 
     320             : 
     321     7568002 : bool Prism::on_reference_element(const Point & p,
     322             :                                  const Real eps) const
     323             : {
     324      744121 :   const Real & xi = p(0);
     325      744121 :   const Real & eta = p(1);
     326      744121 :   const Real & zeta = p(2);
     327             : 
     328             :   // inside the reference triangle with zeta in [-1,1]
     329    13695153 :   return ((xi   >=  0.-eps) &&
     330     6127151 :           (eta  >=  0.-eps) &&
     331     4044507 :           (zeta >= -1.-eps) &&
     332    11945364 :           (zeta <=  1.+eps) &&
     333     4242538 :           ((xi + eta) <= 1.+eps));
     334             : }
     335             : 
     336             : 
     337             : 
     338        4800 : std::pair<Real, Real> Prism::qual_bounds (const ElemQuality) const
     339             : {
     340             :   // No suggested ranges have yet been established for any of the
     341             :   // metrics Quality::valid() lists for prisms, so we always return
     342             :   // the (-1, -1) sentinel.
     343             :   libmesh_warning("Invalid quality measure chosen.");
     344        4800 :   return std::make_pair(Real(-1), Real(-1));
     345             : }
     346             : 
     347             : 
     348             : 
     349             : const unsigned short int Prism::_second_order_vertex_child_number[18] =
     350             :   {
     351             :     99,99,99,99,99,99, // Vertices
     352             :     0,1,0,0,1,2,3,4,3, // Edges
     353             :     0,1,0              // Faces
     354             :   };
     355             : 
     356             : 
     357             : 
     358             : const unsigned short int Prism::_second_order_vertex_child_index[18] =
     359             :   {
     360             :     99,99,99,99,99,99, // Vertices
     361             :     1,2,2,3,4,5,4,5,5, // Edges
     362             :     4,5,5              // Faces
     363             :   };
     364             : 
     365             : 
     366             : const unsigned short int Prism::_second_order_adjacent_vertices[9][2] =
     367             :   {
     368             :     { 0,  1}, // vertices adjacent to node 6
     369             :     { 1,  2}, // vertices adjacent to node 7
     370             :     { 0,  2}, // vertices adjacent to node 8
     371             : 
     372             :     { 0,  3}, // vertices adjacent to node 9
     373             :     { 1,  4}, // vertices adjacent to node 10
     374             :     { 2,  5}, // vertices adjacent to node 11
     375             : 
     376             :     { 3,  4}, // vertices adjacent to node 12
     377             :     { 4,  5}, // vertices adjacent to node 13
     378             :     { 3,  5}  // vertices adjacent to node 14
     379             :   };
     380             : 
     381             : } // namespace libMesh

Generated by: LCOV version 1.14