LCOV - code coverage report
Current view: top level - src/quadrature - quadrature_gauss_3D.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 157 166 94.6 %
Date: 2025-08-19 19:27:09 Functions: 1 1 100.0 %
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             : 
      20             : // Local includes
      21             : #include "libmesh/quadrature_gauss.h"
      22             : #include "libmesh/quadrature_conical.h"
      23             : #include "libmesh/quadrature_gm.h"
      24             : #include "libmesh/enum_to_string.h"
      25             : #include "libmesh/cell_c0polyhedron.h"
      26             : 
      27             : namespace libMesh
      28             : {
      29             : 
      30      171105 : void QGauss::init_3D()
      31             : {
      32             : #if LIBMESH_DIM == 3
      33             : 
      34             :   //-----------------------------------------------------------------------
      35             :   // 3D quadrature rules
      36      171105 :   switch (_type)
      37             :     {
      38             :       //---------------------------------------------
      39             :       // Hex quadrature rules
      40       32730 :     case HEX8:
      41             :     case HEX20:
      42             :     case HEX27:
      43             :       {
      44             :         // We compute the 3D quadrature rule as a tensor
      45             :         // product of the 1D quadrature rule.
      46       35968 :         QGauss q1D(1, get_order());
      47       32730 :         tensor_product_hex( q1D );
      48        1619 :         return;
      49             :       }
      50             : 
      51             : 
      52             : 
      53             :       //---------------------------------------------
      54             :       // Tetrahedral quadrature rules
      55       92923 :     case TET4:
      56             :     case TET10:
      57             :     case TET14:
      58             :       {
      59       99291 :         switch(get_order())
      60             :           {
      61             :             // Taken from pg. 222 of "The finite element method," vol. 1
      62             :             // ed. 5 by Zienkiewicz & Taylor
      63         437 :           case CONSTANT:
      64             :           case FIRST:
      65             :             {
      66             :               // Exact for linears
      67         437 :               _points.resize(1);
      68         437 :               _weights.resize(1);
      69             : 
      70             : 
      71         437 :               _points[0](0) = .25;
      72         437 :               _points[0](1) = .25;
      73         437 :               _points[0](2) = .25;
      74             : 
      75         437 :               _weights[0] = Real(1)/6;
      76             : 
      77         437 :               return;
      78             :             }
      79         284 :           case SECOND:
      80             :             {
      81             :               // Exact for quadratics
      82         284 :               _points.resize(4);
      83         284 :               _weights.resize(4);
      84             : 
      85             : 
      86             :               // Can't be constexpr with my version of Boost quad
      87             :               // precision
      88           8 :               const Real b = 0.25*(1-std::sqrt(Real(5))/5);
      89           8 :               const Real a = 1-3*b;
      90             : 
      91         284 :               _points[0](0) = a;
      92         284 :               _points[0](1) = b;
      93         284 :               _points[0](2) = b;
      94             : 
      95         284 :               _points[1](0) = b;
      96         284 :               _points[1](1) = a;
      97         284 :               _points[1](2) = b;
      98             : 
      99         284 :               _points[2](0) = b;
     100         284 :               _points[2](1) = b;
     101         284 :               _points[2](2) = a;
     102             : 
     103         284 :               _points[3](0) = b;
     104         284 :               _points[3](1) = b;
     105         284 :               _points[3](2) = b;
     106             : 
     107             : 
     108             : 
     109         284 :               _weights[0] = Real(1)/24;
     110         284 :               _weights[1] = _weights[0];
     111         284 :               _weights[2] = _weights[0];
     112         284 :               _weights[3] = _weights[0];
     113             : 
     114         284 :               return;
     115             :             }
     116             : 
     117             : 
     118             : 
     119             :             // Can be found in the class notes
     120             :             // http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps
     121             :             // by Flaherty.
     122             :             //
     123             :             // Caution: this rule has a negative weight and may be
     124             :             // unsuitable for some problems.
     125             :             // Exact for cubics.
     126             :             //
     127             :             // Note: Keast (see ref. elsewhere in this file) also gives
     128             :             // a third-order rule with positive weights, but it contains points
     129             :             // on the ref. elt. boundary, making it less suitable for FEM calculations.
     130        8550 :           case THIRD:
     131             :             {
     132        8550 :               if (allow_rules_with_negative_weights)
     133             :                 {
     134        8408 :                   _points.resize(5);
     135        8408 :                   _weights.resize(5);
     136             : 
     137             : 
     138        8408 :                   _points[0](0) = .25;
     139        8408 :                   _points[0](1) = .25;
     140        8408 :                   _points[0](2) = .25;
     141             : 
     142        8408 :                   _points[1](0) = .5;
     143        8408 :                   _points[1](1) = Real(1)/6;
     144        8408 :                   _points[1](2) = Real(1)/6;
     145             : 
     146        8408 :                   _points[2](0) = Real(1)/6;
     147        8408 :                   _points[2](1) = .5;
     148        8408 :                   _points[2](2) = Real(1)/6;
     149             : 
     150        8408 :                   _points[3](0) = Real(1)/6;
     151        8408 :                   _points[3](1) = Real(1)/6;
     152        8408 :                   _points[3](2) = .5;
     153             : 
     154        8408 :                   _points[4](0) = Real(1)/6;
     155        8408 :                   _points[4](1) = Real(1)/6;
     156        8408 :                   _points[4](2) = Real(1)/6;
     157             : 
     158             : 
     159        8408 :                   _weights[0] = Real(-2)/15;
     160        8408 :                   _weights[1] = .075;
     161        8408 :                   _weights[2] = _weights[1];
     162        8408 :                   _weights[3] = _weights[1];
     163        8408 :                   _weights[4] = _weights[1];
     164             : 
     165        8408 :                   return;
     166             :                 } // end if (allow_rules_with_negative_weights)
     167             :               else
     168             :                 {
     169             :                   // If a rule with positive weights is required, the 2x2x2 conical
     170             :                   // product rule is third-order accurate and has less points than
     171             :                   // the next-available positive-weight rule at FIFTH order.
     172           4 :                   QConical conical_rule(3, _order);
     173         142 :                   conical_rule.init(*this);
     174             : 
     175             :                   // Swap points and weights with the about-to-be destroyed rule.
     176           4 :                   _points.swap (conical_rule.get_points() );
     177           4 :                   _weights.swap(conical_rule.get_weights());
     178             : 
     179           4 :                   return;
     180             :                 }
     181             :               // Note: if !allow_rules_with_negative_weights, fall through to next case.
     182             :             }
     183             : 
     184             : 
     185             : 
     186             :             // Originally a Keast rule,
     187             :             //    Patrick Keast,
     188             :             //    Moderate Degree Tetrahedral Quadrature Formulas,
     189             :             //    Computer Methods in Applied Mechanics and Engineering,
     190             :             //    Volume 55, Number 3, May 1986, pages 339-348.
     191             :             //
     192             :             // Can also be found the class notes
     193             :             // http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps
     194             :             // by Flaherty.
     195             :             //
     196             :             // Caution: this rule has a negative weight and may be
     197             :             // unsuitable for some problems.
     198        1207 :           case FOURTH:
     199             :             {
     200        1207 :               if (allow_rules_with_negative_weights)
     201             :                 {
     202         213 :                   _points.resize(11);
     203         213 :                   _weights.resize(11);
     204             : 
     205             :                   // The raw data for the quadrature rule.
     206         213 :                   const Real rule_data[3][4] = {
     207             :                     {0.250000000000000000e+00_R,                         0._R,                            0._R,  -0.131555555555555556e-01_R},  // 1
     208             :                     {0.785714285714285714e+00_R,   0.714285714285714285e-01_R,                            0._R,   0.762222222222222222e-02_R},  // 4
     209             :                     {0.399403576166799219e+00_R,                         0._R,      0.100596423833200785e+00_R,   0.248888888888888889e-01_R}   // 6
     210             :                   };
     211             : 
     212             : 
     213             :                   // Now call the keast routine to generate _points and _weights
     214         213 :                   keast_rule(rule_data, 3);
     215             : 
     216           6 :                   return;
     217          56 :                 } // end if (allow_rules_with_negative_weights)
     218             :               // Note: if !allow_rules_with_negative_weights, fall through to next case.
     219             :             }
     220             : 
     221             :             libmesh_fallthrough();
     222             : 
     223             : 
     224             :             // Walkington's fifth-order 14-point rule from
     225             :             // "Quadrature on Simplices of Arbitrary Dimension"
     226             :             //
     227             :             // We originally had a Keast rule here, but this rule had
     228             :             // more points than an equivalent rule by Walkington and
     229             :             // also contained points on the boundary of the ref. elt,
     230             :             // making it less suitable for FEM calculations.
     231             :           case FIFTH:
     232             :             {
     233       40308 :               _points.resize(14);
     234       40308 :               _weights.resize(14);
     235             : 
     236             :               // permutations of these points and suitably-modified versions of
     237             :               // these points are the quadrature point locations
     238       40308 :               const Real a[3] = {0.31088591926330060980_R,    // a1 from the paper
     239             :                                  0.092735250310891226402_R,   // a2 from the paper
     240             :                                  0.045503704125649649492_R};  // a3 from the paper
     241             : 
     242             :               // weights.  a[] and wt[] are the only floating-point inputs required
     243             :               // for this rule.
     244       40308 :               const Real wt[3] = {0.018781320953002641800_R,    // w1 from the paper
     245             :                                   0.012248840519393658257_R,    // w2 from the paper
     246             :                                   0.0070910034628469110730_R};  // w3 from the paper
     247             : 
     248             :               // The first two sets of 4 points are formed in a similar manner
     249      120924 :               for (unsigned int i=0; i<2; ++i)
     250             :                 {
     251             :                   // Where we will insert values into _points and _weights
     252       80616 :                   const unsigned int offset=4*i;
     253             : 
     254             :                   // Stuff points and weights values into their arrays
     255       80616 :                   const Real b = 1. - 3.*a[i];
     256             : 
     257             :                   // Here are the permutations.  Order of these is not important,
     258             :                   // all have the same weight
     259       80616 :                   _points[offset + 0] = Point(a[i], a[i], a[i]);
     260       80616 :                   _points[offset + 1] = Point(a[i],    b, a[i]);
     261       80616 :                   _points[offset + 2] = Point(   b, a[i], a[i]);
     262       86426 :                   _points[offset + 3] = Point(a[i], a[i],    b);
     263             : 
     264             :                   // These 4 points all have the same weights
     265      403080 :                   for (unsigned int j=0; j<4; ++j)
     266      345704 :                     _weights[offset + j] = wt[i];
     267             :                 } // end for
     268             : 
     269             : 
     270             :               {
     271             :                 // The third set contains 6 points and is formed a little differently
     272        2905 :                 const unsigned int offset = 8;
     273        2905 :                 const Real b = 0.5*(1. - 2.*a[2]);
     274             : 
     275             :                 // Here are the permutations.  Order of these is not important,
     276             :                 // all have the same weight
     277       40308 :                 _points[offset + 0] = Point(b   ,    b, a[2]);
     278       40308 :                 _points[offset + 1] = Point(b   , a[2], a[2]);
     279       40308 :                 _points[offset + 2] = Point(a[2], a[2],    b);
     280       40308 :                 _points[offset + 3] = Point(a[2],    b, a[2]);
     281       40308 :                 _points[offset + 4] = Point(   b, a[2],    b);
     282       40308 :                 _points[offset + 5] = Point(a[2],    b,    b);
     283             : 
     284             :                 // These 6 points all have the same weights
     285      282156 :                 for (unsigned int j=0; j<6; ++j)
     286      259278 :                   _weights[offset + j] = wt[2];
     287             :               }
     288             : 
     289             : 
     290             :               // Original rule by Keast, unsuitable because it has points on the
     291             :               // reference element boundary!
     292             :               //       _points.resize(15);
     293             :               //       _weights.resize(15);
     294             : 
     295             :               //       _points[0](0) = 0.25;
     296             :               //       _points[0](1) = 0.25;
     297             :               //       _points[0](2) = 0.25;
     298             : 
     299             :               //       {
     300             :               // const Real a = 0.;
     301             :               // const Real b = Real(1)/3;
     302             : 
     303             :               // _points[1](0) = a;
     304             :               // _points[1](1) = b;
     305             :               // _points[1](2) = b;
     306             : 
     307             :               // _points[2](0) = b;
     308             :               // _points[2](1) = a;
     309             :               // _points[2](2) = b;
     310             : 
     311             :               // _points[3](0) = b;
     312             :               // _points[3](1) = b;
     313             :               // _points[3](2) = a;
     314             : 
     315             :               // _points[4](0) = b;
     316             :               // _points[4](1) = b;
     317             :               // _points[4](2) = b;
     318             :               //       }
     319             :               //       {
     320             :               // const Real a = Real(8)/11;
     321             :               // const Real b = Real(1)/11;
     322             : 
     323             :               // _points[5](0) = a;
     324             :               // _points[5](1) = b;
     325             :               // _points[5](2) = b;
     326             : 
     327             :               // _points[6](0) = b;
     328             :               // _points[6](1) = a;
     329             :               // _points[6](2) = b;
     330             : 
     331             :               // _points[7](0) = b;
     332             :               // _points[7](1) = b;
     333             :               // _points[7](2) = a;
     334             : 
     335             :               // _points[8](0) = b;
     336             :               // _points[8](1) = b;
     337             :               // _points[8](2) = b;
     338             :               //       }
     339             :               //       {
     340             :               // const Real a = 0.066550153573664;
     341             :               // const Real b = 0.433449846426336;
     342             : 
     343             :               // _points[9](0) = b;
     344             :               // _points[9](1) = a;
     345             :               // _points[9](2) = a;
     346             : 
     347             :               // _points[10](0) = a;
     348             :               // _points[10](1) = a;
     349             :               // _points[10](2) = b;
     350             : 
     351             :               // _points[11](0) = a;
     352             :               // _points[11](1) = b;
     353             :               // _points[11](2) = b;
     354             : 
     355             :               // _points[12](0) = b;
     356             :               // _points[12](1) = a;
     357             :               // _points[12](2) = b;
     358             : 
     359             :               // _points[13](0) = b;
     360             :               // _points[13](1) = b;
     361             :               // _points[13](2) = a;
     362             : 
     363             :               // _points[14](0) = a;
     364             :               // _points[14](1) = b;
     365             :               // _points[14](2) = a;
     366             :               //       }
     367             : 
     368             :               //       _weights[0]  = 0.030283678097089;
     369             :               //       _weights[1]  = 0.006026785714286;
     370             :               //       _weights[2]  = _weights[1];
     371             :               //       _weights[3]  = _weights[1];
     372             :               //       _weights[4]  = _weights[1];
     373             :               //       _weights[5]  = 0.011645249086029;
     374             :               //       _weights[6]  = _weights[5];
     375             :               //       _weights[7]  = _weights[5];
     376             :               //       _weights[8]  = _weights[5];
     377             :               //       _weights[9]  = 0.010949141561386;
     378             :               //       _weights[10] = _weights[9];
     379             :               //       _weights[11] = _weights[9];
     380             :               //       _weights[12] = _weights[9];
     381             :               //       _weights[13] = _weights[9];
     382             :               //       _weights[14] = _weights[9];
     383             : 
     384        2905 :               return;
     385             :             }
     386             : 
     387             : 
     388             : 
     389             : 
     390             :             // This rule is originally from Keast:
     391             :             //    Patrick Keast,
     392             :             //    Moderate Degree Tetrahedral Quadrature Formulas,
     393             :             //    Computer Methods in Applied Mechanics and Engineering,
     394             :             //    Volume 55, Number 3, May 1986, pages 339-348.
     395             :             //
     396             :             // It is accurate on 6th-degree polynomials and has 24 points
     397             :             // vs. 64 for the comparable conical product rule.
     398             :             //
     399             :             // Values copied 24th June 2008 from:
     400             :             // http://people.scs.fsu.edu/~burkardt/f_src/keast/keast.f90
     401         639 :           case SIXTH:
     402             :             {
     403         639 :               _points.resize (24);
     404         639 :               _weights.resize(24);
     405             : 
     406             :               // The raw data for the quadrature rule.
     407         639 :               const Real rule_data[4][4] = {
     408             :                 {0.356191386222544953e+00_R , 0.214602871259151684e+00_R ,                       0._R, 0.00665379170969464506e+00_R}, // 4
     409             :                 {0.877978124396165982e+00_R , 0.0406739585346113397e+00_R,                       0._R, 0.00167953517588677620e+00_R}, // 4
     410             :                 {0.0329863295731730594e+00_R, 0.322337890142275646e+00_R ,                       0._R, 0.00922619692394239843e+00_R}, // 4
     411             :                 {0.0636610018750175299e+00_R, 0.269672331458315867e+00_R , 0.603005664791649076e+00_R, 0.00803571428571428248e+00_R}  // 12
     412             :               };
     413             : 
     414             : 
     415             :               // Now call the keast routine to generate _points and _weights
     416         639 :               keast_rule(rule_data, 4);
     417             : 
     418          18 :               return;
     419             :             }
     420             : 
     421             : 
     422             :             // Keast's 31 point, 7th-order rule contains points on the reference
     423             :             // element boundary, so we've decided not to include it here.
     424             :             //
     425             :             // Keast's 8th-order rule has 45 points.  and a negative
     426             :             // weight, so if you've explicitly disallowed such rules
     427             :             // you will fall through to the conical product rules
     428             :             // below.
     429       36382 :           case SEVENTH:
     430             :           case EIGHTH:
     431             :             {
     432       36382 :               if (allow_rules_with_negative_weights)
     433             :                 {
     434       36382 :                   _points.resize (45);
     435       36382 :                   _weights.resize(45);
     436             : 
     437             :                   // The raw data for the quadrature rule.
     438       36382 :                   const Real rule_data[7][4] = {
     439             :                     {0.250000000000000000e+00_R,                        0._R,                        0._R,   -0.393270066412926145e-01_R},  // 1
     440             :                     {0.617587190300082967e+00_R,  0.127470936566639015e+00_R,                        0._R,    0.408131605934270525e-02_R},  // 4
     441             :                     {0.903763508822103123e+00_R,  0.320788303926322960e-01_R,                        0._R,    0.658086773304341943e-03_R},  // 4
     442             :                     {0.497770956432810185e-01_R,                        0._R,  0.450222904356718978e+00_R,    0.438425882512284693e-02_R},  // 6
     443             :                     {0.183730447398549945e+00_R,                        0._R,  0.316269552601450060e+00_R,    0.138300638425098166e-01_R},  // 6
     444             :                     {0.231901089397150906e+00_R,  0.229177878448171174e-01_R,  0.513280033360881072e+00_R,    0.424043742468372453e-02_R},  // 12
     445             :                     {0.379700484718286102e-01_R,  0.730313427807538396e+00_R,  0.193746475248804382e+00_R,    0.223873973961420164e-02_R}   // 12
     446             :                   };
     447             : 
     448             : 
     449             :                   // Now call the keast routine to generate _points and _weights
     450       36382 :                   keast_rule(rule_data, 7);
     451             : 
     452        2784 :                   return;
     453           0 :                 } // end if (allow_rules_with_negative_weights)
     454             :               // Note: if !allow_rules_with_negative_weights, fall through to next case.
     455             :             }
     456             : 
     457             :             libmesh_fallthrough();
     458             : 
     459             : 
     460             :             // Fall back on Grundmann-Moller or Conical Product rules at high orders.
     461             :           default:
     462             :             {
     463        6110 :               if ((allow_rules_with_negative_weights) && (get_order() < 34))
     464             :                 {
     465             :                   // The Grundmann-Moller rules are defined to arbitrary order and
     466             :                   // can have significantly fewer evaluation points than conical product
     467             :                   // rules.  If you allow rules with negative weights, the GM rules
     468             :                   // will be more efficient for degree up to 33 (for degree 34 and
     469             :                   // higher, CP is more efficient!) but may be more susceptible
     470             :                   // to round-off error.  Safest is to disallow rules with negative
     471             :                   // weights, but this decision should be made on a case-by-case basis.
     472         260 :                   QGrundmann_Moller gm_rule(3, _order);
     473        6110 :                   gm_rule.init(*this);
     474             : 
     475             :                   // Swap points and weights with the about-to-be destroyed rule.
     476         260 :                   _points.swap (gm_rule.get_points() );
     477         260 :                   _weights.swap(gm_rule.get_weights());
     478             : 
     479         260 :                   return;
     480             :                 }
     481             : 
     482             :               else
     483             :                 {
     484             :                   // The following quadrature rules are generated as
     485             :                   // conical products.  These tend to be non-optimal
     486             :                   // (use too many points, cluster points in certain
     487             :                   // regions of the domain) but they are quite easy to
     488             :                   // automatically generate using a 1D Gauss rule on
     489             :                   // [0,1] and two 1D Jacobi-Gauss rules on [0,1].
     490           0 :                   QConical conical_rule(3, _order);
     491           0 :                   conical_rule.init(*this);
     492             : 
     493             :                   // Swap points and weights with the about-to-be destroyed rule.
     494           0 :                   _points.swap (conical_rule.get_points() );
     495           0 :                   _weights.swap(conical_rule.get_weights());
     496             : 
     497           0 :                   return;
     498             :                 }
     499             :             }
     500             :           }
     501             :       } // end case TET
     502             : 
     503             : 
     504             : 
     505             :       //---------------------------------------------
     506             :       // Prism quadrature rules
     507       26046 :     case PRISM6:
     508             :     case PRISM15:
     509             :     case PRISM18:
     510             :     case PRISM20:
     511             :     case PRISM21:
     512             :       {
     513             :         // We compute the 3D quadrature rule as a tensor
     514             :         // product of the 1D quadrature rule and a 2D
     515             :         // triangle quadrature rule
     516             : 
     517       29832 :         QGauss q1D(1,get_order());
     518       27939 :         QGauss q2D(2,_order);
     519             : 
     520             :         // Initialize the 2D rule (1D is pre-initialized)
     521       26046 :         q2D.init(TRI3, _p_level, /*simple_type_only=*/true);
     522             : 
     523       26046 :         tensor_product_prism(q1D, q2D);
     524             : 
     525        1893 :         return;
     526             :       }
     527             : 
     528             : 
     529             : 
     530             :       //---------------------------------------------
     531             :       // Pyramid
     532       18819 :     case PYRAMID5:
     533             :     case PYRAMID13:
     534             :     case PYRAMID14:
     535             :     case PYRAMID18:
     536             :       {
     537             :         // We compute the Pyramid rule as a conical product of a
     538             :         // Jacobi rule with alpha==2 on the interval [0,1] two 1D
     539             :         // Gauss rules with suitably modified points.  The idea comes
     540             :         // from: Stroud, A.H. "Approximate Calculation of Multiple
     541             :         // Integrals."
     542       19837 :         QConical conical_rule(3, _order);
     543       18819 :         conical_rule.init(*this);
     544             : 
     545             :         // Swap points and weights with the about-to-be destroyed rule.
     546        1018 :         _points.swap (conical_rule.get_points() );
     547        1018 :         _weights.swap(conical_rule.get_weights());
     548             : 
     549        1018 :         return;
     550             : 
     551             :       }
     552             : 
     553             : 
     554             :       //---------------------------------------------
     555             :       // Arbitrary polyhedron quadrature rules
     556         587 :     case C0POLYHEDRON:
     557             :       {
     558         632 :         QGauss tet_rule(3, _order);
     559         587 :         tet_rule.init(TET4, _p_level, true);
     560             : 
     561          45 :         std::vector<Point> & tetpoints = tet_rule.get_points();
     562          45 :         std::vector<Real> & tetweights = tet_rule.get_weights();
     563             : 
     564          90 :         std::size_t numtetpts = tetpoints.size();
     565             : 
     566             :         // C0Polyhedron requires the newer Quadrature API
     567         587 :         if (!_elem)
     568           0 :           libmesh_error();
     569             : 
     570          45 :         libmesh_assert(_elem->type() == C0POLYHEDRON);
     571             : 
     572          45 :         const C0Polyhedron & poly = *cast_ptr<const C0Polyhedron *>(_elem);
     573             : 
     574         587 :         std::size_t numtets = poly.n_subelements();
     575         587 :         _points.resize(numtetpts*numtets);
     576         587 :         _weights.resize(numtetpts*numtets);
     577             : 
     578        3522 :         for (std::size_t t = 0; t != numtets; ++t)
     579             :           {
     580        2935 :             auto master_points = poly.master_subelement(t);
     581             : 
     582         225 :             const Point v01 = master_points[1] - master_points[0];
     583         225 :             const Point v02 = master_points[2] - master_points[0];
     584         225 :             const Point v03 = master_points[3] - master_points[0];
     585             : 
     586             :             // The factor of one sixth from the tetweights cancels out
     587             :             // the factor of six here, so we don't need to do so
     588             :             // ourselves.
     589             :             const Real six_master_tet_vol =
     590        2710 :               triple_product(v01, v02, v03);
     591             : 
     592       24630 :             for (std::size_t i = 0; i != numtetpts; ++i)
     593             :               {
     594       21695 :                 _points[numtetpts*t+i] =
     595        1710 :                   master_points[0] +
     596        5130 :                     v01 * tetpoints[i](0) +
     597        5130 :                     v02 * tetpoints[i](1) +
     598        6840 :                     v03 * tetpoints[i](2);
     599       25115 :                 _weights[numtetpts*t+i] = tetweights[i] *
     600             :                                           six_master_tet_vol;
     601             :               }
     602             :           }
     603          45 :         return;
     604             :       }
     605             : 
     606             :       //---------------------------------------------
     607             :       // Unsupported type
     608           0 :     default:
     609           0 :       libmesh_error_msg("ERROR: Unsupported type: " << Utility::enum_to_string(_type));
     610             :     }
     611             : #endif
     612             : }
     613             : 
     614             : } // namespace libMesh

Generated by: LCOV version 1.14