LCOV - code coverage report
Current view: top level - src/geom - cell_prism.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 85 109 78.0 %
Date: 2025-08-19 19:27:09 Functions: 11 13 84.6 %
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             : // C++ includes
      20             : 
      21             : // Local includes
      22             : #include "libmesh/cell_prism.h"
      23             : #include "libmesh/cell_prism6.h"
      24             : #include "libmesh/face_quad4.h"
      25             : #include "libmesh/face_tri3.h"
      26             : 
      27             : namespace libMesh
      28             : {
      29             : 
      30             : 
      31             : // ------------------------------------------------------------
      32             : // Prism class static member initializations
      33             : const int Prism::num_sides;
      34             : const int Prism::num_edges;
      35             : const int Prism::num_children;
      36             : 
      37             : const Real Prism::_master_points[18][3] =
      38             :   {
      39             :     {0, 0, -1},
      40             :     {1, 0, -1},
      41             :     {0, 1, -1},
      42             :     {0, 0, 1},
      43             :     {1, 0, 1},
      44             :     {0, 1, 1},
      45             :     {0.5, 0, -1},
      46             :     {0.5, 0.5, -1},
      47             :     {0, 0.5, -1},
      48             :     {0, 0, 0},
      49             :     {1, 0, 0},
      50             :     {0, 1, 0},
      51             :     {0.5, 0, 1},
      52             :     {0.5, 0.5, 1},
      53             :     {0, 0.5, 1},
      54             :     {0.5, 0, 0},
      55             :     {0.5, 0.5, 0},
      56             :     {0, 0.5, 0}
      57             :   };
      58             : 
      59             : const unsigned int Prism::edge_sides_map[9][2] =
      60             :   {
      61             :     {0, 1}, // Edge 0
      62             :     {0, 2}, // Edge 1
      63             :     {0, 3}, // Edge 2
      64             :     {1, 3}, // Edge 3
      65             :     {1, 2}, // Edge 4
      66             :     {2, 3}, // Edge 5
      67             :     {1, 4}, // Edge 6
      68             :     {2, 4}, // Edge 7
      69             :     {3, 4}  // Edge 8
      70             :   };
      71             : 
      72             : const unsigned int Prism::adjacent_edges_map[/*num_vertices*/6][/*n_adjacent_edges*/3] =
      73             :   {
      74             :     {0, 2, 3},  // Edges adjacent to node 0
      75             :     {0, 1, 4},  // Edges adjacent to node 1
      76             :     {1, 2, 5},  // Edges adjacent to node 2
      77             :     {3, 6, 8},  // Edges adjacent to node 3
      78             :     {4, 6, 7},  // Edges adjacent to node 4
      79             :     {5, 7, 8},  // Edges adjacent to node 5
      80             :   };
      81             : 
      82             : 
      83             : // ------------------------------------------------------------
      84             : // Prism class member functions
      85           0 : dof_id_type Prism::key (const unsigned int s) const
      86             : {
      87           0 :   libmesh_assert_less (s, this->n_sides());
      88             : 
      89           0 :   switch (s)
      90             :     {
      91           0 :     case 0: // the triangular face at z=0
      92             :     case 4: // the triangular face at z=1
      93           0 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
      94           0 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
      95           0 :                                 this->node_id(Prism6::side_nodes_map[s][2]));
      96             : 
      97           0 :     case 1: // the quad face at y=0
      98             :     case 2: // the other quad face
      99             :     case 3: // the quad face at x=0
     100           0 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
     101           0 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
     102           0 :                                 this->node_id(Prism6::side_nodes_map[s][2]),
     103           0 :                                 this->node_id(Prism6::side_nodes_map[s][3]));
     104             : 
     105           0 :     default:
     106           0 :       libmesh_error_msg("Invalid side " << s);
     107             :     }
     108             : }
     109             : 
     110             : 
     111             : 
     112     4348745 : dof_id_type Prism::low_order_key (const unsigned int s) const
     113             : {
     114      217220 :   libmesh_assert_less (s, this->n_sides());
     115             : 
     116     4348745 :   switch (s)
     117             :     {
     118     1739498 :     case 0: // the triangular face at z=0
     119             :     case 4: // the triangular face at z=1
     120     1826386 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
     121     1739498 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
     122     1826386 :                                 this->node_id(Prism6::side_nodes_map[s][2]));
     123             : 
     124     2609247 :     case 1: // the quad face at y=0
     125             :     case 2: // the other quad face
     126             :     case 3: // the quad face at x=0
     127     2739579 :       return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
     128     2609247 :                                 this->node_id(Prism6::side_nodes_map[s][1]),
     129     2609247 :                                 this->node_id(Prism6::side_nodes_map[s][2]),
     130     2739579 :                                 this->node_id(Prism6::side_nodes_map[s][3]));
     131             : 
     132           0 :     default:
     133           0 :       libmesh_error_msg("Invalid side " << s);
     134             :     }
     135             : }
     136             : 
     137             : 
     138             : 
     139       91870 : unsigned int Prism::local_side_node(unsigned int side,
     140             :                                     unsigned int side_node) const
     141             : {
     142        7648 :   libmesh_assert_less (side, this->n_sides());
     143             : 
     144             :   // Never more than 4 nodes per side.
     145        7648 :   libmesh_assert_less(side_node, Prism6::nodes_per_side);
     146             : 
     147             :   // Some sides have 3 nodes.
     148        7648 :   libmesh_assert(!(side==0 || side==4) || side_node < 3);
     149             : 
     150       91868 :   return Prism6::side_nodes_map[side][side_node];
     151             : }
     152             : 
     153             : 
     154             : 
     155    31575726 : unsigned int Prism::local_edge_node(unsigned int edge,
     156             :                                     unsigned int edge_node) const
     157             : {
     158     2816280 :   libmesh_assert_less(edge, this->n_edges());
     159     2816280 :   libmesh_assert_less(edge_node, Prism6::nodes_per_edge);
     160             : 
     161    31575726 :   return Prism6::edge_nodes_map[edge][edge_node];
     162             : }
     163             : 
     164             : 
     165             : 
     166   264791983 : std::unique_ptr<Elem> Prism::side_ptr (const unsigned int i)
     167             : {
     168    23560998 :   libmesh_assert_less (i, this->n_sides());
     169             : 
     170   264791983 :   std::unique_ptr<Elem> face;
     171             : 
     172             :   // Set up the type of element
     173   264791983 :   switch (i)
     174             :     {
     175      819381 :     case 0: // the triangular face at z=0
     176             :     case 4: // the triangular face at z=1
     177             :       {
     178      819381 :         face = std::make_unique<Tri3>();
     179      819381 :         break;
     180             :       }
     181   263972602 :     case 1: // the quad face at y=0
     182             :     case 2: // the other quad face
     183             :     case 3: // the quad face at x=0
     184             :       {
     185   263972602 :         face = std::make_unique<Quad4>();
     186   263972602 :         break;
     187             :       }
     188           0 :     default:
     189           0 :       libmesh_error_msg("Invalid side i = " << i);
     190             :     }
     191             : 
     192             :   // Set the nodes
     193  1323140534 :   for (auto n : face->node_index_range())
     194  1152542949 :     face->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
     195             : 
     196   264791983 :   return face;
     197           0 : }
     198             : 
     199             : 
     200             : 
     201     3123892 : void Prism::side_ptr (std::unique_ptr<Elem> & side,
     202             :                       const unsigned int i)
     203             : {
     204      180456 :   libmesh_assert_less (i, this->n_sides());
     205             : 
     206     3123892 :   switch (i)
     207             :     {
     208             :       // the base face
     209       69128 :     case 0: // the triangular face at z=0
     210             :     case 4: // the triangular face at z=1
     211             :       {
     212     1141932 :         if (!side.get() || side->type() != TRI3)
     213             :           {
     214     1523572 :             side = this->side_ptr(i);
     215      810674 :             return;
     216             :           }
     217       20240 :         break;
     218             :       }
     219             : 
     220      111328 :     case 1: // the quad face at y=0
     221             :     case 2: // the other quad face
     222             :     case 3: // the quad face at x=0
     223             :       {
     224     1981960 :         if (!side.get() || side->type() != QUAD4)
     225             :           {
     226     1646890 :             side = this->side_ptr(i);
     227      873979 :             return;
     228             :           }
     229       60794 :         break;
     230             :       }
     231             : 
     232           0 :     default:
     233           0 :       libmesh_error_msg("Invalid side i = " << i);
     234             :     }
     235             : 
     236     1520273 :   side->subdomain_id() = this->subdomain_id();
     237             : 
     238             :   // Set the nodes
     239     6864937 :   for (auto n : side->node_index_range())
     240     5729594 :     side->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
     241             : }
     242             : 
     243             : 
     244             : 
     245     1248672 : bool Prism::is_child_on_side(const unsigned int c,
     246             :                              const unsigned int s) const
     247             : {
     248      550492 :   libmesh_assert_less (c, this->n_children());
     249      550492 :   libmesh_assert_less (s, this->n_sides());
     250             : 
     251     4770226 :   for (unsigned int i = 0; i != 4; ++i)
     252     4110115 :     if (Prism6::side_elems_map[s][i] == c)
     253      243224 :       return true;
     254      307268 :   return false;
     255             : }
     256             : 
     257             : 
     258             : 
     259     3390736 : bool Prism::is_edge_on_side(const unsigned int e,
     260             :                             const unsigned int s) const
     261             : {
     262     2912302 :   libmesh_assert_less (e, this->n_edges());
     263     2912302 :   libmesh_assert_less (s, this->n_sides());
     264             : 
     265     3390736 :   return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
     266             : }
     267             : 
     268             : 
     269             : 
     270       34560 : std::vector<unsigned int> Prism::sides_on_edge(const unsigned int e) const
     271             : {
     272        2880 :   libmesh_assert_less(e, this->n_edges());
     273             : 
     274       34560 :   return {edge_sides_map[e][0], edge_sides_map[e][1]};
     275             : }
     276             : 
     277             : 
     278             : 
     279           0 : unsigned int Prism::opposite_side(const unsigned int side_in) const
     280             : {
     281           0 :   libmesh_assert_less (side_in, 5);
     282             :   static const unsigned int prism_opposites[5] =
     283             :     {4, invalid_uint, invalid_uint, invalid_uint, 0};
     284           0 :   return prism_opposites[side_in];
     285             : }
     286             : 
     287             : 
     288             : 
     289             : bool
     290        9428 : Prism::is_flipped() const
     291             : {
     292        8868 :   return (triple_product(this->point(1)-this->point(0),
     293        8868 :                         this->point(2)-this->point(0),
     294       10548 :                         this->point(3)-this->point(0)) < 0);
     295             : }
     296             : 
     297             : 
     298             : std::vector<unsigned int>
     299       76800 : Prism::edges_adjacent_to_node(const unsigned int n) const
     300             : {
     301        6400 :   libmesh_assert_less(n, this->n_nodes());
     302             : 
     303             :   // For vertices, we use the Prism::adjacent_sides_map, otherwise each
     304             :   // of the mid-edge nodes is adjacent only to the edge it is on, and
     305             :   // face/internal nodes are not adjacent to any edge.
     306       76800 :   if (this->is_vertex(n))
     307       31200 :     return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n])};
     308       48000 :   else if (this->is_edge(n))
     309       34560 :     return {n - this->n_vertices()};
     310             : 
     311        1120 :   libmesh_assert(this->is_face(n) || this->is_internal(n));
     312       12320 :   return {};
     313             : }
     314             : 
     315             : 
     316             : 
     317     7028703 : bool Prism::on_reference_element(const Point & p,
     318             :                                  const Real eps) const
     319             : {
     320      720231 :   const Real & xi = p(0);
     321      720231 :   const Real & eta = p(1);
     322      720231 :   const Real & zeta = p(2);
     323             : 
     324             :   // inside the reference triangle with zeta in [-1,1]
     325    12818967 :   return ((xi   >=  0.-eps) &&
     326     5790264 :           (eta  >=  0.-eps) &&
     327     3752311 :           (zeta >= -1.-eps) &&
     328    11111463 :           (zeta <=  1.+eps) &&
     329     3981476 :           ((xi + eta) <= 1.+eps));
     330             : }
     331             : 
     332             : 
     333             : 
     334             : const unsigned short int Prism::_second_order_vertex_child_number[18] =
     335             :   {
     336             :     99,99,99,99,99,99, // Vertices
     337             :     0,1,0,0,1,2,3,4,3, // Edges
     338             :     0,1,0              // Faces
     339             :   };
     340             : 
     341             : 
     342             : 
     343             : const unsigned short int Prism::_second_order_vertex_child_index[18] =
     344             :   {
     345             :     99,99,99,99,99,99, // Vertices
     346             :     1,2,2,3,4,5,4,5,5, // Edges
     347             :     4,5,5              // Faces
     348             :   };
     349             : 
     350             : 
     351             : const unsigned short int Prism::_second_order_adjacent_vertices[9][2] =
     352             :   {
     353             :     { 0,  1}, // vertices adjacent to node 6
     354             :     { 1,  2}, // vertices adjacent to node 7
     355             :     { 0,  2}, // vertices adjacent to node 8
     356             : 
     357             :     { 0,  3}, // vertices adjacent to node 9
     358             :     { 1,  4}, // vertices adjacent to node 10
     359             :     { 2,  5}, // vertices adjacent to node 11
     360             : 
     361             :     { 3,  4}, // vertices adjacent to node 12
     362             :     { 4,  5}, // vertices adjacent to node 13
     363             :     { 3,  5}  // vertices adjacent to node 14
     364             :   };
     365             : 
     366             : } // namespace libMesh

Generated by: LCOV version 1.14