LCOV - code coverage report
Current view: top level - src/geom - face_tri7.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 98 162 60.5 %
Date: 2026-10-13 21:47:33 Functions: 19 23 82.6 %
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             : // Local includes
      19             : #include "libmesh/edge_edge3.h"
      20             : #include "libmesh/face_tri7.h"
      21             : #include "libmesh/enum_io_package.h"
      22             : #include "libmesh/enum_order.h"
      23             : 
      24             : #ifdef LIBMESH_ENABLE_AMR
      25             : namespace {
      26             :   constexpr libMesh::Real r18 = 18;
      27             : }
      28             : #endif
      29             : 
      30             : namespace libMesh
      31             : {
      32             : 
      33             : 
      34             : 
      35             : 
      36             : // ------------------------------------------------------------
      37             : // Tri7 class static member initializations
      38             : const int Tri7::num_nodes;
      39             : const int Tri7::nodes_per_side;
      40             : 
      41             : 
      42             : #ifdef LIBMESH_ENABLE_AMR
      43             : 
      44             : const Real Tri7::_embedding_matrix[Tri7::num_children][Tri7::num_nodes][Tri7::num_nodes] =
      45             :   {
      46             :     // embedding matrix for child 0
      47             :     {
      48             :       //  0      1      2     3      4     5      6
      49             :       {   1.0,   0.0,   0.0,  0.0,   0.0,  0.0,   0.0}, // 0
      50             :       {   0.0,   0.0,   0.0,  1.0,   0.0,  0.0,   0.0}, // 1
      51             :       {   0.0,   0.0,   0.0,  0.0,   0.0,  1.0,   0.0}, // 2
      52             :       {  .375, -.125,   0.0,  .75,   0.0,  0.0,   0.0}, // 3
      53             :       {.09375,-.03125,-.03125, .125, -.125, .125,.84375}, // 4
      54             :       {  .375,   0.0, -.125,  0.0,   0.0,  .75,   0.0}, // 5
      55             :       { 5/r18,-1/r18,-1/r18,4/r18,-2/r18,4/r18,   0.5}  // 6
      56             :     },
      57             : 
      58             :     // embedding matrix for child 1
      59             :     {
      60             :       //  0      1      2     3     4      5      6
      61             :       {   0.0,   0.0,   0.0,  1.0,  0.0,   0.0,   0.0}, // 0
      62             :       {   0.0,   1.0,   0.0,  0.0,  0.0,   0.0,   0.0}, // 1
      63             :       {   0.0,   0.0,   0.0,  0.0,  1.0,   0.0,   0.0}, // 2
      64             :       { -.125,  .375,   0.0,  .75,  0.0,   0.0,   0.0}, // 3
      65             :       {   0.0,  .375, -.125,  0.0,  .75,   0.0,   0.0}, // 4
      66             :       {-.03125,.09375,-.03125, .125, .125, -.125,.84375}, // 5
      67             :       {-1/r18, 5/r18,-1/r18,4/r18,4/r18,-2/r18,   0.5}  // 6
      68             :     },
      69             : 
      70             :     // embedding matrix for child 2
      71             :     {
      72             :       //  0       1     2      3     4     5    6
      73             :       {   0.0,   0.0,   0.0,   0.0,  0.0,  1.0,   0.0}, // 0
      74             :       {   0.0,   0.0,   0.0,   0.0,  1.0,  0.0,   0.0}, // 1
      75             :       {   0.0,   0.0,   1.0,   0.0,  0.0,  0.0,   0.0}, // 2
      76             :       {-.03125,-.03125,.09375, -.125, .125, .125,.84375}, // 3
      77             :       {   0.0, -.125,  .375,   0.0,  .75,  0.0,   0.0}, // 4
      78             :       { -.125,   0.0,  .375,   0.0,  0.0,  .75,   0.0}, // 5
      79             :       {-1/r18,-1/r18, 5/r18,-2/r18,4/r18,4/r18,   0.5}  // 6
      80             :     },
      81             : 
      82             :     // embedding matrix for child 3
      83             :     {
      84             :       //  0      1      2     3     4     5      6
      85             :       {   0.0,   0.0,   0.0,  1.0,  0.0,  0.0,   0.0}, // 0
      86             :       {   0.0,   0.0,   0.0,  0.0,  1.0,  0.0,   0.0}, // 1
      87             :       {   0.0,   0.0,   0.0,  0.0,  0.0,  1.0,   0.0}, // 2
      88             :       {-.03125,.09375,-.03125, .125, .125,-.125,.84375}, // 3
      89             :       {-.03125,-.03125,.09375,-.125, .125, .125,.84375}, // 4
      90             :       {.09375,-.03125,-.03125, .125,-.125, .125,.84375}, // 5
      91             :       {   0.0,   0.0,   0.0,  0.0,  0.0,  0.0,   1.0}  // 6
      92             :     }
      93             :   };
      94             : 
      95             : const std::vector<std::pair<unsigned char, unsigned char>>
      96             :   Tri7::_parent_bracketing_nodes[Tri7::num_children][Tri7::num_nodes] =
      97             :   {
      98             :     // Child 0
      99             :     {      {},{{0,1}},{{0,2}},{{0,3}},{{3,5}},{{0,5}},{{0,6}} },
     100             :     // Child 1
     101             :     { {{0,1}},     {},{{1,2}},{{1,3}},{{1,4}},{{3,4}},{{1,6}} },
     102             :     // Child 2
     103             :     { {{0,2}},{{1,2}},     {},{{4,5}},{{2,4}},{{2,5}},{{2,6}} },
     104             :     // Child 3
     105             :     { {{0,1}},{{1,2}},{{0,2}},{{3,4}},{{4,5}},{{3,5}},{{0,4},{1,5},{2,3}} }
     106             :   };
     107             : #endif
     108             : 
     109             : 
     110             : 
     111             : // ------------------------------------------------------------
     112             : // Tri7 class member functions
     113             : 
     114     5235677 : bool Tri7::is_vertex(const unsigned int i) const
     115             : {
     116     5235677 :   if (i < 3)
     117     2244005 :     return true;
     118      244100 :   return false;
     119             : }
     120             : 
     121       16512 : bool Tri7::is_edge(const unsigned int i) const
     122             : {
     123       16512 :   if (i < 3 || i == 6)
     124        4128 :     return false;
     125        1032 :   return true;
     126             : }
     127             : 
     128         336 : bool Tri7::is_face(const unsigned int i) const
     129             : {
     130         336 :   if (i > 5)
     131         336 :     return true;
     132           0 :   return false;
     133             : }
     134             : 
     135      147156 : bool Tri7::is_node_on_side(const unsigned int n,
     136             :                            const unsigned int s) const
     137             : {
     138       11066 :   libmesh_assert_less (s, n_sides());
     139       11066 :   return std::find(std::begin(side_nodes_map[s]),
     140      147156 :                    std::end(side_nodes_map[s]),
     141      147156 :                    n) != std::end(side_nodes_map[s]);
     142             : }
     143             : 
     144             : std::vector<unsigned>
     145      102522 : Tri7::nodes_on_side(const unsigned int s) const
     146             : {
     147        8520 :   libmesh_assert_less(s, n_sides());
     148      111042 :   return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s])};
     149             : }
     150             : 
     151             : std::vector<unsigned>
     152        3093 : Tri7::nodes_on_edge(const unsigned int e) const
     153             : {
     154        3093 :   return nodes_on_side(e);
     155             : }
     156             : 
     157     2404693 : bool Tri7::has_affine_map() const
     158             : {
     159             :   // Make sure edges are straight
     160      392530 :   Point v = this->point(2) - this->point(1);
     161     2600998 :   if (!v.relative_fuzzy_equals
     162     2404693 :       ((this->point(4) - this->point(1))*2))
     163           0 :     return false;
     164     2600918 :   v = this->point(1) - this->point(0);
     165     2600998 :   if (!v.relative_fuzzy_equals
     166     2404693 :       ((this->point(3) - this->point(0))*2))
     167           0 :     return false;
     168      392530 :   Point v20 = this->point(2) - this->point(0);
     169     2600998 :   if (!v20.relative_fuzzy_equals
     170     2404693 :       ((this->point(5) - this->point(0))*2))
     171           0 :     return false;
     172             : 
     173             :   // Make sure center node is centered
     174      196305 :   v += v20;
     175     2600998 :   if (!v.relative_fuzzy_equals
     176     2404693 :       ((this->point(6) - this->point(0))*3))
     177           0 :     return false;
     178             : 
     179      196305 :   return true;
     180             : }
     181             : 
     182             : 
     183             : 
     184    89876826 : Order Tri7::default_order() const
     185             : {
     186    89876826 :   return THIRD;
     187             : }
     188             : 
     189             : 
     190             : 
     191       13496 : Order Tri7::default_side_order() const
     192             : {
     193       13496 :   return SECOND;
     194             : }
     195             : 
     196             : 
     197             : 
     198           0 : dof_id_type Tri7::key (const unsigned int s) const
     199             : {
     200           0 :   libmesh_assert_less (s, this->n_sides());
     201             : 
     202           0 :   switch (s)
     203             :     {
     204           0 :     case 0:
     205             : 
     206             :       return
     207           0 :         this->compute_key (this->node_id(3));
     208             : 
     209           0 :     case 1:
     210             : 
     211             :       return
     212           0 :         this->compute_key (this->node_id(4));
     213             : 
     214           0 :     case 2:
     215             : 
     216             :       return
     217           0 :         this->compute_key (this->node_id(5));
     218             : 
     219           0 :     default:
     220           0 :       libmesh_error_msg("Invalid side s = " << s);
     221             :     }
     222             : }
     223             : 
     224             : 
     225             : 
     226    56081595 : unsigned int Tri7::local_side_node(unsigned int side,
     227             :                                    unsigned int side_node) const
     228             : {
     229     4379391 :   libmesh_assert_less (side, this->n_sides());
     230     4379391 :   libmesh_assert_less (side_node, Tri7::nodes_per_side);
     231             : 
     232    56081595 :   return Tri7::side_nodes_map[side][side_node];
     233             : }
     234             : 
     235             : 
     236             : 
     237     1485019 : std::unique_ptr<Elem> Tri7::build_side_ptr (const unsigned int i)
     238             : {
     239     1485019 :   return this->simple_build_side_ptr<Edge3, Tri7>(i);
     240             : }
     241             : 
     242             : 
     243             : 
     244        1661 : void Tri7::build_side_ptr (std::unique_ptr<Elem> & side,
     245             :                            const unsigned int i)
     246             : {
     247        1661 :   this->simple_build_side_ptr<Tri7>(side, i, EDGE3);
     248        1661 : }
     249             : 
     250             : 
     251             : 
     252           0 : void Tri7::connectivity(const unsigned int sf,
     253             :                         const IOPackage iop,
     254             :                         std::vector<dof_id_type> & conn) const
     255             : {
     256           0 :   libmesh_assert_less (sf, this->n_sub_elem());
     257           0 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
     258             : 
     259           0 :   switch (iop)
     260             :     {
     261           0 :     case TECPLOT:
     262             :       {
     263           0 :         conn.resize(4);
     264           0 :         switch(sf)
     265             :           {
     266           0 :           case 0:
     267             :             // linear sub-triangle 0
     268           0 :             conn[0] = this->node_id(0)+1;
     269           0 :             conn[1] = this->node_id(3)+1;
     270           0 :             conn[2] = this->node_id(5)+1;
     271           0 :             conn[3] = this->node_id(5)+1;
     272             : 
     273           0 :             return;
     274             : 
     275           0 :           case 1:
     276             :             // linear sub-triangle 1
     277           0 :             conn[0] = this->node_id(3)+1;
     278           0 :             conn[1] = this->node_id(1)+1;
     279           0 :             conn[2] = this->node_id(4)+1;
     280           0 :             conn[3] = this->node_id(4)+1;
     281             : 
     282           0 :             return;
     283             : 
     284           0 :           case 2:
     285             :             // linear sub-triangle 2
     286           0 :             conn[0] = this->node_id(5)+1;
     287           0 :             conn[1] = this->node_id(4)+1;
     288           0 :             conn[2] = this->node_id(2)+1;
     289           0 :             conn[3] = this->node_id(2)+1;
     290             : 
     291           0 :             return;
     292             : 
     293           0 :           case 3:
     294             :             // linear sub-triangle 3
     295           0 :             conn[0] = this->node_id(3)+1;
     296           0 :             conn[1] = this->node_id(4)+1;
     297           0 :             conn[2] = this->node_id(5)+1;
     298           0 :             conn[3] = this->node_id(5)+1;
     299             : 
     300           0 :             return;
     301             : 
     302           0 :           default:
     303           0 :             libmesh_error_msg("Invalid sf = " << sf);
     304             :           }
     305             :       }
     306             : 
     307           0 :     case VTK:
     308             :       {
     309             :         // VTK has a vtkBiQuadraticTriangle class whose connectivity matches libMesh's
     310           0 :         conn.resize(Tri7::num_nodes);
     311           0 :         for (auto i : index_range(conn))
     312           0 :           conn[i] = this->node_id(i);
     313           0 :         return;
     314             :       }
     315             : 
     316           0 :     default:
     317           0 :       libmesh_error_msg("Unsupported IO package " << iop);
     318             :     }
     319             : }
     320             : 
     321             : 
     322             : 
     323    21531913 : BoundingBox Tri7::loose_bounding_box () const
     324             : {
     325             :   // This might have curved edges, or might be a curved surface in
     326             :   // 3-space, in which case the full bounding box can be larger than
     327             :   // the bounding box of just the nodes.
     328             :   //
     329             :   //
     330             :   // FIXME - I haven't yet proven the formula below to be correct for
     331             :   // quadratics in 2D - RHS
     332             :   //
     333             :   // FIXME - This doesn't take into account curvature caused by the
     334             :   // center node in 3D - RHS
     335      389809 :   Point pmin, pmax;
     336             : 
     337    86127652 :   for (unsigned d=0; d<LIBMESH_DIM; ++d)
     338             :     {
     339    65765166 :       Real center = this->point(0)(d);
     340   387574434 :       for (unsigned int p=1; p != 6; ++p)
     341   322978695 :         center += this->point(p)(d);
     342    64595739 :       center /= 6;
     343             : 
     344    65765166 :       Real hd = std::abs(center - this->point(0)(d));
     345   387574434 :       for (unsigned int p=1; p != 6; ++p)
     346   366792506 :         hd = std::max(hd, std::abs(center - this->point(p)(d)));
     347             : 
     348    64595739 :       pmin(d) = center - hd;
     349    64595739 :       pmax(d) = center + hd;
     350             :     }
     351             : 
     352    21921722 :   return BoundingBox(pmin, pmax);
     353             : }
     354             : 
     355             : 
     356             : 
     357       12572 : unsigned int Tri7::n_second_order_adjacent_vertices (const unsigned int n) const
     358             : {
     359       12572 :   switch (n)
     360             :     {
     361         522 :     case 3:
     362             :     case 4:
     363             :     case 5:
     364         522 :       return 2;
     365             : 
     366        3143 :     case 6:
     367        3143 :       return 3;
     368             : 
     369           0 :     default:
     370           0 :       libmesh_error_msg("Invalid n = " << n);
     371             :     }
     372             : }
     373             : 
     374             : 
     375             : 
     376       28287 : unsigned short int Tri7::second_order_adjacent_vertex (const unsigned int n,
     377             :                                                        const unsigned int v) const
     378             : {
     379        1566 :   libmesh_assert_greater_equal (n, this->n_vertices());
     380        1566 :   libmesh_assert_less (n, this->n_nodes());
     381             : 
     382       28287 :   switch (n)
     383             :     {
     384        9429 :     case 6:
     385             :       {
     386         522 :         libmesh_assert_less (v, 3);
     387        9429 :         return static_cast<unsigned short int>(v);
     388             :       }
     389             : 
     390       18858 :     default:
     391             :       {
     392        1044 :         libmesh_assert_less (v, 2);
     393       18858 :         return _second_order_adjacent_vertices[n-this->n_vertices()][v];
     394             :       }
     395             :     }
     396             : }
     397             : 
     398             : 
     399             : 
     400             : const unsigned short int Tri7::_second_order_adjacent_vertices[Tri7::num_sides][2] =
     401             :   {
     402             :     {0, 1}, // vertices adjacent to node 3
     403             :     {1, 2}, // vertices adjacent to node 4
     404             :     {0, 2}  // vertices adjacent to node 5
     405             :   };
     406             : 
     407             : 
     408             : 
     409             : std::pair<unsigned short int, unsigned short int>
     410           0 : Tri7::second_order_child_vertex (const unsigned int n) const
     411             : {
     412           0 :   libmesh_assert_greater_equal (n, this->n_vertices());
     413           0 :   libmesh_assert_less (n, this->n_nodes());
     414           0 :   return std::pair<unsigned short int, unsigned short int>
     415           0 :     (_second_order_vertex_child_number[n],
     416           0 :      _second_order_vertex_child_index[n]);
     417             : }
     418             : 
     419             : 
     420             : 
     421             : const unsigned short int Tri7::_second_order_vertex_child_number[Tri7::num_nodes] =
     422             :   {
     423             :     99,99,99, // Vertices
     424             :     0,1,0,    // Edges
     425             :     3         // Interior
     426             :   };
     427             : 
     428             : 
     429             : 
     430             : const unsigned short int Tri7::_second_order_vertex_child_index[Tri7::num_nodes] =
     431             :   {
     432             :     99,99,99, // Vertices
     433             :     1,2,2,    // Edges
     434             :     6         // Interior
     435             :   };
     436             : 
     437             : 
     438      129834 : void Tri7::permute(unsigned int perm_num)
     439             : {
     440       10520 :   libmesh_assert_less (perm_num, 3);
     441             : 
     442      255665 :   for (unsigned int i = 0; i != perm_num; ++i)
     443             :     {
     444      125831 :       swap3nodes(0,1,2);
     445      115609 :       swap3nodes(3,4,5);
     446      115609 :       swap3neighbors(0,1,2);
     447             :     }
     448      129834 : }
     449             : 
     450             : 
     451        3713 : void Tri7::flip(BoundaryInfo * boundary_info)
     452             : {
     453         174 :   libmesh_assert(boundary_info);
     454             : 
     455        3713 :   swap2nodes(0,1);
     456        3713 :   swap2nodes(4,5);
     457         174 :   swap2neighbors(1,2);
     458        3713 :   swap2boundarysides(1,2,boundary_info);
     459        3713 :   swap2boundaryedges(1,2,boundary_info);
     460        3713 : }
     461             : 
     462             : 
     463         288 : unsigned int Tri7::center_node_on_side(const unsigned short side) const
     464             : {
     465          24 :   libmesh_assert_less (side, Tri7::num_sides);
     466         288 :   return side + 3;
     467             : }
     468             : 
     469             : 
     470             : ElemType
     471        1152 : Tri7::side_type (const unsigned int libmesh_dbg_var(s)) const
     472             : {
     473          96 :   libmesh_assert_less (s, 3);
     474        1152 :   return EDGE3;
     475             : }
     476             : 
     477             : 
     478             : } // namespace libMesh

Generated by: LCOV version 1.14