LCOV - code coverage report
Current view: top level - src/geom - cell_prism6.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 153 178 86.0 %
Date: 2025-08-19 19:27:09 Functions: 24 27 88.9 %
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             : // Local includes
      20             : #include "libmesh/cell_prism6.h"
      21             : #include "libmesh/edge_edge2.h"
      22             : #include "libmesh/face_quad4.h"
      23             : #include "libmesh/face_tri3.h"
      24             : #include "libmesh/enum_io_package.h"
      25             : #include "libmesh/enum_order.h"
      26             : #include "libmesh/fe_lagrange_shape_1D.h"
      27             : 
      28             : // C++ includes
      29             : #include <array>
      30             : 
      31             : // Helper functions for computing volume() and true_centroid()
      32             : namespace {
      33             : 
      34             : using namespace libMesh;
      35             : 
      36             : // Templated numerical quadrature implementation function used by both
      37             : // Prism6::volume() and Prism6::true_centroid() routines.
      38             : template <typename T>
      39             : void cell_integral(const Elem * elem, T & t);
      40             : 
      41             : /**
      42             :  * Object passed to cell_integral() routine for computing the cell volume.
      43             :  */
      44             : struct VolumeIntegral
      45             : {
      46             :   // API
      47         256 :   void accumulate_qp(Real /*xi*/, Real /*eta*/, Real /*zeta*/, Real JxW)
      48             :   {
      49        9088 :     vol += JxW;
      50         256 :   };
      51             : 
      52             :   Real vol = 0.;
      53             : };
      54             : 
      55             : /**
      56             :  * Object passed to cell_integral() routine for computing the nodal
      57             :  * volumes (one value per node)
      58             :  */
      59             : struct NodalVolumeIntegral
      60             : {
      61             :   // API
      62       19840 :   void accumulate_qp(Real xi, Real eta, Real zeta, Real JxW)
      63             :   {
      64             :     // Copied from fe_lagrange_shape_3D.C
      65             :     static const unsigned int i0[] = {0, 0, 0, 1, 1, 1};
      66             :     static const unsigned int i1[] = {0, 1, 2, 0, 1, 2};
      67             : 
      68             :     // Copied from fe_lagrange_shape_2D.C
      69      119040 :     auto tri3_phi = [](int i, Real x, Real y)
      70             :     {
      71      119040 :       switch(i)
      72             :       {
      73       39680 :         case 0:
      74       39680 :           return 1 - x - y;
      75             : 
      76        2304 :         case 1:
      77        2304 :           return x;
      78             : 
      79       39680 :         case 2:
      80       37376 :           return y;
      81             : 
      82           0 :         default:
      83           0 :           libmesh_error_msg("Invalid shape function index i = " << i);
      84             :       }
      85             :     };
      86             : 
      87      138880 :     for (int i=0; i<6; ++i)
      88             :       {
      89             :         Real phi =
      90      119040 :           tri3_phi(i1[i], xi, eta) * fe_lagrange_1D_linear_shape(i0[i], zeta);
      91             : 
      92      119040 :         V[i] += phi * JxW;
      93             :       }
      94       19840 :   };
      95             : 
      96             :   // nodal volumes
      97             :   std::array<Real, 6> V {};
      98             : };
      99             : 
     100             : }
     101             : 
     102             : namespace libMesh
     103             : {
     104             : 
     105             : 
     106             : 
     107             : // ------------------------------------------------------------
     108             : // Prism6 class static member initializations
     109             : const int Prism6::num_nodes;
     110             : const int Prism6::nodes_per_side;
     111             : const int Prism6::nodes_per_edge;
     112             : 
     113             : const unsigned int Prism6::side_nodes_map[Prism6::num_sides][Prism6::nodes_per_side] =
     114             :   {
     115             :     {0, 2, 1, 99}, // Side 0
     116             :     {0, 1, 4,  3}, // Side 1
     117             :     {1, 2, 5,  4}, // Side 2
     118             :     {2, 0, 3,  5}, // Side 3
     119             :     {3, 4, 5, 99}  // Side 4
     120             :   };
     121             : 
     122             : const unsigned int Prism6::side_elems_map[Prism6::num_sides][Prism6::nodes_per_side] =
     123             :   {
     124             :     {0, 1, 2, 3}, // Side 0
     125             :     {0, 1, 4, 5}, // Side 1
     126             :     {1, 2, 5, 6}, // Side 2
     127             :     {0, 2, 4, 6}, // Side 3
     128             :     {4, 5, 6, 7}  // Side 4
     129             :   };
     130             : 
     131             : const unsigned int Prism6::edge_nodes_map[Prism6::num_edges][Prism6::nodes_per_edge] =
     132             :   {
     133             :     {0, 1}, // Edge 0
     134             :     {1, 2}, // Edge 1
     135             :     {0, 2}, // Edge 2
     136             :     {0, 3}, // Edge 3
     137             :     {1, 4}, // Edge 4
     138             :     {2, 5}, // Edge 5
     139             :     {3, 4}, // Edge 6
     140             :     {4, 5}, // Edge 7
     141             :     {3, 5}  // Edge 8
     142             :   };
     143             : 
     144             : // ------------------------------------------------------------
     145             : // Prism6 class member functions
     146             : 
     147     1071502 : bool Prism6::is_vertex(const unsigned int libmesh_dbg_var(n)) const
     148             : {
     149       61836 :   libmesh_assert_not_equal_to (n, invalid_uint);
     150     1071502 :   return true;
     151             : }
     152             : 
     153           0 : bool Prism6::is_edge(const unsigned int) const
     154             : {
     155           0 :   return false;
     156             : }
     157             : 
     158             : 
     159           0 : bool Prism6::is_face(const unsigned int) const
     160             : {
     161           0 :   return false;
     162             : }
     163             : 
     164       20706 : bool Prism6::is_node_on_side(const unsigned int n,
     165             :                              const unsigned int s) const
     166             : {
     167        1608 :   libmesh_assert_less (s, n_sides());
     168        1608 :   return std::find(std::begin(side_nodes_map[s]),
     169       20706 :                    std::end(side_nodes_map[s]),
     170       20706 :                    n) != std::end(side_nodes_map[s]);
     171             : }
     172             : 
     173             : std::vector<unsigned>
     174    40170851 : Prism6::nodes_on_side(const unsigned int s) const
     175             : {
     176     3583908 :   libmesh_assert_less(s, n_sides());
     177    40170851 :   auto trim = (s > 0 && s < 4) ? 0 : 1;
     178    40170851 :   return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
     179             : }
     180             : 
     181             : std::vector<unsigned>
     182        9279 : Prism6::nodes_on_edge(const unsigned int e) const
     183             : {
     184         738 :   libmesh_assert_less(e, n_edges());
     185       10017 :   return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
     186             : }
     187             : 
     188        7290 : bool Prism6::is_node_on_edge(const unsigned int n,
     189             :                              const unsigned int e) const
     190             : {
     191         396 :   libmesh_assert_less (e, n_edges());
     192         396 :   return std::find(std::begin(edge_nodes_map[e]),
     193        7290 :                    std::end(edge_nodes_map[e]),
     194        7290 :                    n) != std::end(edge_nodes_map[e]);
     195             : }
     196             : 
     197             : 
     198             : 
     199      475377 : bool Prism6::has_affine_map() const
     200             : {
     201             :   // Make sure z edges are affine
     202       95384 :   Point v = this->point(3) - this->point(0);
     203      570681 :   if (!v.relative_fuzzy_equals(this->point(4) - this->point(1), affine_tol) ||
     204      568893 :       !v.relative_fuzzy_equals(this->point(5) - this->point(2), affine_tol))
     205        1848 :     return false;
     206       47632 :   return true;
     207             : }
     208             : 
     209             : 
     210             : 
     211    11892466 : Order Prism6::default_order() const
     212             : {
     213    11892466 :   return FIRST;
     214             : }
     215             : 
     216             : 
     217             : 
     218      175186 : std::unique_ptr<Elem> Prism6::build_side_ptr (const unsigned int i)
     219             : {
     220       13965 :   libmesh_assert_less (i, this->n_sides());
     221             : 
     222      175186 :   std::unique_ptr<Elem> face;
     223             : 
     224      175186 :   switch (i)
     225             :     {
     226       68394 :     case 0: // the triangular face at z=-1
     227             :     case 4: // the triangular face at z=1
     228             :       {
     229       68394 :         face = std::make_unique<Tri3>();
     230       68394 :         break;
     231             :       }
     232      106792 :     case 1: // the quad face at y=0
     233             :     case 2: // the other quad face
     234             :     case 3: // the quad face at x=0
     235             :       {
     236      106792 :         face = std::make_unique<Quad4>();
     237      106792 :         break;
     238             :       }
     239           0 :     default:
     240           0 :       libmesh_error_msg("Invalid side i = " << i);
     241             :     }
     242             : 
     243             :   // Set the nodes
     244      807536 :   for (auto n : face->node_index_range())
     245      682762 :     face->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
     246             : 
     247      175186 :   face->set_interior_parent(this);
     248      161221 :   face->inherit_data_from(*this);
     249             : 
     250      175186 :   return face;
     251           0 : }
     252             : 
     253             : 
     254             : 
     255        7835 : void Prism6::build_side_ptr (std::unique_ptr<Elem> & side,
     256             :                              const unsigned int i)
     257             : {
     258        7835 :   this->side_ptr(side, i);
     259        7835 :   side->set_interior_parent(this);
     260        6993 :   side->inherit_data_from(*this);
     261        7835 : }
     262             : 
     263             : 
     264             : 
     265     1612815 : std::unique_ptr<Elem> Prism6::build_edge_ptr (const unsigned int i)
     266             : {
     267     1612815 :   return this->simple_build_edge_ptr<Edge2,Prism6>(i);
     268             : }
     269             : 
     270             : 
     271             : 
     272           0 : void Prism6::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
     273             : {
     274           0 :   this->simple_build_edge_ptr<Prism6>(edge, i, EDGE2);
     275           0 : }
     276             : 
     277             : 
     278             : 
     279       23040 : void Prism6::connectivity(const unsigned int libmesh_dbg_var(sc),
     280             :                           const IOPackage iop,
     281             :                           std::vector<dof_id_type> & conn) const
     282             : {
     283        1920 :   libmesh_assert(_nodes);
     284        1920 :   libmesh_assert_less (sc, this->n_sub_elem());
     285        1920 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
     286             : 
     287       23040 :   switch (iop)
     288             :     {
     289       23040 :     case TECPLOT:
     290             :       {
     291       23040 :         conn.resize(8);
     292       24960 :         conn[0] = this->node_id(0)+1;
     293       23040 :         conn[1] = this->node_id(1)+1;
     294       23040 :         conn[2] = this->node_id(2)+1;
     295       23040 :         conn[3] = this->node_id(2)+1;
     296       23040 :         conn[4] = this->node_id(3)+1;
     297       23040 :         conn[5] = this->node_id(4)+1;
     298       23040 :         conn[6] = this->node_id(5)+1;
     299       23040 :         conn[7] = this->node_id(5)+1;
     300       23040 :         return;
     301             :       }
     302             : 
     303           0 :     case VTK:
     304             :       {
     305           0 :         conn.resize(6);
     306           0 :         conn[0] = this->node_id(0);
     307           0 :         conn[1] = this->node_id(2);
     308           0 :         conn[2] = this->node_id(1);
     309           0 :         conn[3] = this->node_id(3);
     310           0 :         conn[4] = this->node_id(5);
     311           0 :         conn[5] = this->node_id(4);
     312           0 :         return;
     313             :       }
     314             : 
     315           0 :     default:
     316           0 :       libmesh_error_msg("Unsupported IO package " << iop);
     317             :     }
     318             : }
     319             : 
     320             : 
     321             : 
     322             : #ifdef LIBMESH_ENABLE_AMR
     323             : 
     324             : const Real Prism6::_embedding_matrix[Prism6::num_children][Prism6::num_nodes][Prism6::num_nodes] =
     325             :   {
     326             :     // embedding matrix for child 0
     327             :     {
     328             :       //  0     1     2     3     4     5
     329             :       { 1.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 0
     330             :       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 1
     331             :       { 0.5,  0.0,  0.5,  0.0,  0.0,  0.0}, // 2
     332             :       { 0.5,  0.0,  0.0,  0.5,  0.0,  0.0}, // 3
     333             :       { .25,  .25,  0.0,  .25,  .25,  0.0}, // 4
     334             :       { .25,  0.0,  .25,  .25,  0.0,  .25}  // 5
     335             :     },
     336             : 
     337             :     // embedding matrix for child 1
     338             :     {
     339             :       //  0     1     2     3     4     5
     340             :       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 0
     341             :       { 0.0,  1.0,  0.0,  0.0,  0.0,  0.0}, // 1
     342             :       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0}, // 2
     343             :       { .25,  .25,  0.0,  .25,  .25,  0.0}, // 3
     344             :       { 0.0,  0.5,  0.0,  0.0,  0.5,  0.0}, // 4
     345             :       { 0.0,  .25,  .25,  0.0,  .25,  .25}  // 5
     346             :     },
     347             : 
     348             :     // embedding matrix for child 2
     349             :     {
     350             :       //  0     1     2     3     4     5
     351             :       { 0.5,  0.0,  0.5,  0.0,  0.0,  0.0}, // 0
     352             :       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0}, // 1
     353             :       { 0.0,  0.0,  1.0,  0.0,  0.0,  0.0}, // 2
     354             :       { .25,  0.0,  .25,  .25,  0.0,  .25}, // 3
     355             :       { 0.0,  .25,  .25,  0.0,  .25,  .25}, // 4
     356             :       { 0.0,  0.0,  0.5,  0.0,  0.0,  0.5}  // 5
     357             :     },
     358             : 
     359             :     // embedding matrix for child 3
     360             :     {
     361             :       //  0     1     2     3     4     5
     362             :       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 0
     363             :       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0}, // 1
     364             :       { 0.5,  0.0,  0.5,  0.0,  0.0,  0.0}, // 2
     365             :       { .25,  .25,  0.0,  .25,  .25,  0.0}, // 3
     366             :       { 0.0,  .25,  .25,  0.0,  .25,  .25}, // 4
     367             :       { .25,  0.0,  .25,  .25,  0.0,  .25}  // 5
     368             :     },
     369             : 
     370             :     // embedding matrix for child 4
     371             :     {
     372             :       //  0     1     2     3     4     5
     373             :       { 0.5,  0.0,  0.0,  0.5,  0.0,  0.0}, // 0
     374             :       { .25,  .25,  0.0,  .25,  .25,  0.0}, // 1
     375             :       { .25,  0.0,  .25,  .25,  0.0,  .25}, // 2
     376             :       { 0.0,  0.0,  0.0,  1.0,  0.0,  0.0}, // 3
     377             :       { 0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 4
     378             :       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.5}  // 5
     379             :     },
     380             : 
     381             :     // embedding matrix for child 5
     382             :     {
     383             :       //  0     1     2     3     4     5
     384             :       { .25,  .25,  0.0,  .25,  .25,  0.0}, // 0
     385             :       { 0.0,  0.5,  0.0,  0.0,  0.5,  0.0}, // 1
     386             :       { 0.0,  .25,  .25,  0.0,  .25,  .25}, // 2
     387             :       { 0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 3
     388             :       { 0.0,  0.0,  0.0,  0.0,  1.0,  0.0}, // 4
     389             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5}  // 5
     390             :     },
     391             : 
     392             :     // embedding matrix for child 6
     393             :     {
     394             :       //  0     1     2     3     4     5
     395             :       { .25,  0.0,  .25,  .25,  0.0,  .25}, // 0
     396             :       { 0.0,  .25,  .25,  0.0,  .25,  .25}, // 1
     397             :       { 0.0,  0.0,  0.5,  0.0,  0.0,  0.5}, // 2
     398             :       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.5}, // 3
     399             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5}, // 4
     400             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  1.0}  // 5
     401             :     },
     402             : 
     403             :     // embedding matrix for child 7
     404             :     {
     405             :       //  0     1     2     3     4     5
     406             :       { .25,  .25,  0.0,  .25,  .25,  0.0}, // 0
     407             :       { 0.0,  .25,  .25,  0.0,  .25,  .25}, // 1
     408             :       { .25,  0.0,  .25,  .25,  0.0,  .25}, // 2
     409             :       { 0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 3
     410             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5}, // 4
     411             :       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.5}  // 5
     412             :     }
     413             :   };
     414             : 
     415             : #endif
     416             : 
     417             : 
     418             : 
     419        2480 : Point Prism6::true_centroid () const
     420             : {
     421        2480 :   NodalVolumeIntegral nvi;
     422        2480 :   cell_integral(this, nvi);
     423             : 
     424             :   // Compute centroid
     425         144 :   Point cp;
     426         144 :   Real vol = 0.;
     427             : 
     428       17360 :   for (int i=0; i<6; ++i)
     429             :     {
     430       15744 :       cp += this->point(i) * nvi.V[i];
     431       14880 :       vol += nvi.V[i];
     432             :     }
     433             : 
     434        2480 :   return cp / vol;
     435             : }
     436             : 
     437        1136 : Real Prism6::volume () const
     438             : {
     439        1136 :   VolumeIntegral vi;
     440        1136 :   cell_integral(this, vi);
     441        1136 :   return vi.vol;
     442             : }
     443             : 
     444             : BoundingBox
     445      193721 : Prism6::loose_bounding_box () const
     446             : {
     447      193721 :   return Elem::loose_bounding_box();
     448             : }
     449             : 
     450             : 
     451             : void
     452        4716 : Prism6::permute(unsigned int perm_num)
     453             : {
     454         420 :   libmesh_assert_less (perm_num, 6);
     455        4716 :   const unsigned int side = perm_num % 2;
     456        4716 :   const unsigned int rotate = perm_num / 2;
     457             : 
     458       11214 :   for (unsigned int i = 0; i != rotate; ++i)
     459             :     {
     460        6498 :       swap3nodes(0,1,2);
     461        5916 :       swap3nodes(3,4,5);
     462        5916 :       swap3neighbors(1,2,3);
     463             :     }
     464             : 
     465        4716 :   switch (side) {
     466          48 :   case 0:
     467          48 :     break;
     468        4140 :   case 1:
     469        4140 :     swap2nodes(1,3);
     470        4140 :     swap2nodes(0,4);
     471        4140 :     swap2nodes(2,5);
     472         372 :     swap2neighbors(0,4);
     473         372 :     swap2neighbors(2,3);
     474         372 :     break;
     475           0 :   default:
     476           0 :     libmesh_error();
     477             :   }
     478             : 
     479        4716 : }
     480             : 
     481             : 
     482             : void
     483         576 : Prism6::flip(BoundaryInfo * boundary_info)
     484             : {
     485          48 :   libmesh_assert(boundary_info);
     486             : 
     487         576 :   swap2nodes(0,1);
     488         576 :   swap2nodes(3,4);
     489          48 :   swap2neighbors(2,3);
     490         576 :   swap2boundarysides(2,3,boundary_info);
     491         576 :   swap2boundaryedges(0,1,boundary_info);
     492         576 :   swap2boundaryedges(3,4,boundary_info);
     493         576 :   swap2boundaryedges(7,8,boundary_info);
     494         576 : }
     495             : 
     496             : 
     497             : ElemType
     498        2880 : Prism6::side_type (const unsigned int s) const
     499             : {
     500         240 :   libmesh_assert_less (s, 5);
     501        2880 :   if (s == 0 || s == 4)
     502        1152 :     return TRI3;
     503         144 :   return QUAD4;
     504             : }
     505             : 
     506             : } // namespace libMesh
     507             : 
     508             : namespace // anonymous
     509             : {
     510             : 
     511             : template <typename T>
     512        3616 : void cell_integral(const Elem * elem, T & t)
     513             : {
     514             :   // Conveient references to our points.
     515             :   const Point
     516         352 :     &x0 = elem->point(0), &x1 = elem->point(1), &x2 = elem->point(2),
     517         176 :     &x3 = elem->point(3), &x4 = elem->point(4), &x5 = elem->point(5);
     518             : 
     519             :   // constant and zeta terms only.  These are copied directly from a
     520             :   // Python script.
     521         352 :   Point dx_dxi[2] =
     522             :     {
     523         176 :       -x0/2 + x1/2 - x3/2 + x4/2, // constant
     524         176 :       x0/2 - x1/2 - x3/2 + x4/2,  // zeta
     525             :     };
     526             : 
     527             :   // constant and zeta terms only.  These are copied directly from a
     528             :   // Python script.
     529         352 :   Point dx_deta[2] =
     530             :     {
     531         176 :       -x0/2 + x2/2 - x3/2 + x5/2, // constant
     532         176 :       x0/2 - x2/2 - x3/2 + x5/2,  // zeta
     533             :     };
     534             : 
     535             :   // Constant, xi, and eta terms
     536         528 :   Point dx_dzeta[3] =
     537             :     {
     538         176 :       -x0/2 + x3/2,              // constant
     539         176 :       x0/2 - x2/2 - x3/2 + x5/2, // eta
     540         176 :       x0/2 - x1/2 - x3/2 + x4/2  // xi
     541             :     };
     542             : 
     543             :   // The quadrature rule for the Prism6 is a tensor product between a
     544             :   // four-point TRI3 rule (in xi, eta) and a two-point EDGE2 rule (in
     545             :   // zeta) which is capable of integrating cubics exactly.
     546             : 
     547             :   // Number of points in the 2D quadrature rule.
     548         176 :   const int N2D = 4;
     549             : 
     550             :   static const Real w2D[N2D] =
     551             :     {
     552             :       1.5902069087198858469718450103758e-01_R,
     553             :       9.0979309128011415302815498962418e-02_R,
     554             :       1.5902069087198858469718450103758e-01_R,
     555             :       9.0979309128011415302815498962418e-02_R
     556             :     };
     557             : 
     558             :   static const Real xi[N2D] =
     559             :     {
     560             :       1.5505102572168219018027159252941e-01_R,
     561             :       6.4494897427831780981972840747059e-01_R,
     562             :       1.5505102572168219018027159252941e-01_R,
     563             :       6.4494897427831780981972840747059e-01_R
     564             :     };
     565             : 
     566             :   static const Real eta[N2D] =
     567             :     {
     568             :       1.7855872826361642311703513337422e-01_R,
     569             :       7.5031110222608118177475598324603e-02_R,
     570             :       6.6639024601470138670269327409637e-01_R,
     571             :       2.8001991549907407200279599420481e-01_R
     572             :     };
     573             : 
     574             :   // Number of points in the 1D quadrature rule.  The weights of the
     575             :   // 1D quadrature rule are equal to 1.
     576         176 :   const int N1D = 2;
     577             : 
     578             :   // Points of the 1D quadrature rule
     579             :   static const Real zeta[N1D] =
     580             :     {
     581             :       -std::sqrt(Real(3))/3,
     582             :       std::sqrt(Real(3))/3.
     583             :     };
     584             : 
     585       18080 :   for (int i=0; i<N2D; ++i)
     586             :     {
     587             :       // dx_dzeta depends only on the 2D quadrature rule points.
     588        2112 :       Point dx_dzeta_q = dx_dzeta[0] + eta[i]*dx_dzeta[1] + xi[i]*dx_dzeta[2];
     589             : 
     590       43392 :       for (int j=0; j<N1D; ++j)
     591             :         {
     592             :           // dx_dxi and dx_deta only depend on the 1D quadrature rule points.
     593             :           Point
     594        2816 :             dx_dxi_q  = dx_dxi[0]  + zeta[j]*dx_dxi[1],
     595        1408 :             dx_deta_q = dx_deta[0] + zeta[j]*dx_deta[1];
     596             : 
     597             :           // Compute t-specific contributions at current qp
     598       30336 :           t.accumulate_qp(xi[i], eta[i], zeta[j], w2D[i] * triple_product(dx_dxi_q, dx_deta_q, dx_dzeta_q));
     599             :         }
     600             :     }
     601        3616 : }
     602             : 
     603             : }

Generated by: LCOV version 1.14