LCOV - code coverage report
Current view: top level - src/quadrature - quadrature.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4481 (67a8c4) with base cc8438 Lines: 118 148 79.7 %
Date: 2026-06-12 15:24:28 Functions: 9 15 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : // Local includes
      20             : #include "libmesh/elem.h"
      21             : #include "libmesh/quadrature.h"
      22             : #include "libmesh/int_range.h"
      23             : 
      24             : namespace libMesh
      25             : {
      26             : 
      27     1784128 : QBase::QBase(unsigned int d,
      28     1784128 :              Order o) :
      29      731569 :   allow_rules_with_negative_weights(true),
      30      731569 :   allow_nodal_pyramid_quadrature(false),
      31      731569 :   _dim(d),
      32      731569 :   _order(o),
      33      731569 :   _type(INVALID_ELEM),
      34      731569 :   _elem(nullptr),
      35     1784128 :   _p_level(0)
      36     1784128 : {}
      37             : 
      38           0 : std::unique_ptr<QBase> QBase::clone() const
      39             : {
      40           0 :   return QBase::build(this->type(), this->get_dim(), this->get_order());
      41             : }
      42             : 
      43           0 : void QBase::print_info(std::ostream & os) const
      44             : {
      45           0 :   libmesh_assert(!_points.empty());
      46           0 :   libmesh_assert(!_weights.empty());
      47             : 
      48           0 :   Real summed_weights=0;
      49           0 :   os << "N_Q_Points=" << this->n_points() << std::endl << std::endl;
      50           0 :   for (auto qpoint: index_range(_points))
      51             :     {
      52           0 :       os << " Point " << qpoint << ":\n"
      53           0 :          << "  "
      54           0 :          << _points[qpoint]
      55             :          << "\n Weight:\n "
      56           0 :          << "  w=" << _weights[qpoint] << "\n" << std::endl;
      57             : 
      58           0 :       summed_weights += _weights[qpoint];
      59             :     }
      60           0 :   os << "Summed Weights: " << summed_weights << std::endl;
      61           0 : }
      62             : 
      63             : 
      64             : 
      65    42726542 : void QBase::init(const Elem & elem,
      66             :                  unsigned int p)
      67             : {
      68    12406182 :   libmesh_assert_equal_to(elem.dim(), _dim);
      69             : 
      70             :   // Default to the element p_level() value
      71    42726542 :   if (p == invalid_uint)
      72    19506214 :     p = elem.p_level();
      73             : 
      74    42726542 :   ElemType t = elem.type();
      75             : 
      76             :   // check to see if we have already
      77             :   // done the work for this quadrature rule
      78             :   //
      79             :   // If we have something like a Polygon subclass then we're going to
      80             :   // need to recompute to be safe; even if we're using the same
      81             :   // element, it might have been distorted enough that its subtriangle
      82             :   // triangulation has been changed.
      83    42726542 :   if (t == _type && p == _p_level && !elem.runtime_topology())
      84    12315640 :     return;
      85             :   else
      86             :     {
      87      314454 :       _elem = &elem;
      88      314454 :       _type = t;
      89      314454 :       _p_level = p;
      90             :     }
      91             : 
      92      314454 :   switch(_elem->dim())
      93             :     {
      94        2531 :     case 0:
      95        2531 :       this->init_0D();
      96             : 
      97        2531 :       return;
      98             : 
      99       59901 :     case 1:
     100       59901 :       this->init_1D();
     101             : 
     102       59901 :       return;
     103             : 
     104      161405 :     case 2:
     105      161405 :       this->init_2D();
     106             : 
     107      161405 :       return;
     108             : 
     109       90617 :     case 3:
     110       90617 :       this->init_3D();
     111             : 
     112       90617 :       return;
     113             : 
     114           0 :     default:
     115           0 :       libmesh_error_msg("Invalid dimension _dim = " << _dim);
     116             :     }
     117             : }
     118             : 
     119             : 
     120             : 
     121      902088 : void QBase::init(const ElemType t,
     122             :                  unsigned int p,
     123             :                  bool simple_type_only)
     124             : {
     125             :   // Some element types require data from a specific element, so can
     126             :   // only be used with newer APIs.
     127      902088 :   if (t == C0POLYGON || t == C0POLYHEDRON)
     128           0 :     libmesh_error_msg("Code (see stack trace) used an outdated quadrature function overload.\n"
     129             :                       "Quadrature rules on a C0Polygon are not defined by its ElemType alone.");
     130             : 
     131             :   // This API is dangerous to use on general meshes, which may include
     132             :   // element types where the desired quadrature depends on the
     133             :   // physical element, but we still want to be able to initialize
     134             :   // based on only a type for certain simple cases
     135      271641 :   if (t != EDGE2 && !simple_type_only)
     136             :     libmesh_deprecated();
     137             : 
     138             :   // check to see if we have already
     139             :   // done the work for this quadrature rule
     140      902088 :   if (t == _type && p == _p_level)
     141        2086 :     return;
     142             :   else
     143             :     {
     144      894803 :       _elem = nullptr;
     145      894803 :       _type = t;
     146      894803 :       _p_level = p;
     147             :     }
     148             : 
     149      894803 :   switch(_dim)
     150             :     {
     151           5 :     case 0:
     152           5 :       this->init_0D();
     153             : 
     154           5 :       return;
     155             : 
     156      884896 :     case 1:
     157      884896 :       this->init_1D();
     158             : 
     159      884896 :       return;
     160             : 
     161        9560 :     case 2:
     162        9560 :       this->init_2D();
     163             : 
     164        9560 :       return;
     165             : 
     166         342 :     case 3:
     167         342 :       this->init_3D();
     168             : 
     169         342 :       return;
     170             : 
     171           0 :     default:
     172           0 :       libmesh_error_msg("Invalid dimension _dim = " << _dim);
     173             :     }
     174             : }
     175             : 
     176             : 
     177             : 
     178       27287 : void QBase::init(const QBase & other_rule)
     179             : {
     180       27287 :   if (other_rule._elem)
     181       20689 :     this->init(*other_rule._elem, other_rule._p_level);
     182             :   else
     183        6598 :     this->init(other_rule._type, other_rule._p_level, true);
     184       27287 : }
     185             : 
     186             : 
     187             : 
     188           0 : void QBase::init (const Elem & elem,
     189             :                   const std::vector<Real> & /* vertex_distance_func */,
     190             :                   unsigned int p_level)
     191             : {
     192             :   // dispatch generic implementation
     193           0 :   this->init(elem.type(), p_level);
     194           0 : }
     195             : 
     196             : 
     197             : 
     198        2536 : void QBase::init_0D()
     199             : {
     200        2536 :   _points.resize(1);
     201        2536 :   _weights.resize(1);
     202        2536 :   _points[0] = Point(0.);
     203        2536 :   _weights[0] = 1.0;
     204        2536 : }
     205             : 
     206             : 
     207             : 
     208           0 : void QBase::init_2D ()
     209             : {
     210           0 :   libmesh_not_implemented();
     211             : }
     212             : 
     213             : 
     214             : 
     215           0 : void QBase::init_3D ()
     216             : {
     217           0 :   libmesh_not_implemented();
     218             : }
     219             : 
     220             : 
     221             : 
     222         133 : void QBase::scale(std::pair<Real, Real> old_range,
     223             :                   std::pair<Real, Real> new_range)
     224             : {
     225             :   // Make sure we are in 1D
     226          38 :   libmesh_assert_equal_to (_dim, 1);
     227             : 
     228             :   Real
     229         133 :     h_new = new_range.second - new_range.first,
     230         133 :     h_old = old_range.second - old_range.first;
     231             : 
     232             :   // Make sure that we have sane ranges
     233          38 :   libmesh_assert_greater (h_new, 0.);
     234          38 :   libmesh_assert_greater (h_old, 0.);
     235             : 
     236             :   // Make sure there are some points
     237          38 :   libmesh_assert_greater (_points.size(), 0);
     238             : 
     239             :   // Compute the scale factor
     240         133 :   Real scfact = h_new/h_old;
     241             : 
     242             :   // We're mapping from old_range -> new_range
     243         483 :   for (auto i : index_range(_points))
     244             :     {
     245         350 :       _points[i](0) = new_range.first +
     246         350 :         (_points[i](0) - old_range.first) * scfact;
     247             : 
     248             :       // Scale the weights
     249         450 :       _weights[i] *= scfact;
     250             :     }
     251         133 : }
     252             : 
     253             : 
     254             : 
     255             : 
     256      108460 : void QBase::tensor_product_quad(const QBase & q1D)
     257             : {
     258             : 
     259       33028 :   const unsigned int np = q1D.n_points();
     260             : 
     261      108460 :   _points.resize(np * np);
     262             : 
     263      108460 :   _weights.resize(np * np);
     264             : 
     265       33028 :   unsigned int q=0;
     266             : 
     267      502147 :   for (unsigned int j=0; j<np; j++)
     268     2647644 :     for (unsigned int i=0; i<np; i++)
     269             :       {
     270     2977798 :         _points[q](0) = q1D.qp(i)(0);
     271     2253957 :         _points[q](1) = q1D.qp(j)(0);
     272             : 
     273     2253957 :         _weights[q] = q1D.w(i)*q1D.w(j);
     274             : 
     275     2253957 :         q++;
     276             :       }
     277      108460 : }
     278             : 
     279             : 
     280             : 
     281             : 
     282             : 
     283        8557 : void QBase::tensor_product_hex(const QBase & q1D)
     284             : {
     285        2243 :   const unsigned int np = q1D.n_points();
     286             : 
     287        8557 :   _points.resize(np * np * np);
     288             : 
     289        8557 :   _weights.resize(np * np * np);
     290             : 
     291        2243 :   unsigned int q=0;
     292             : 
     293       35772 :   for (unsigned int k=0; k<np; k++)
     294      143408 :     for (unsigned int j=0; j<np; j++)
     295      995522 :       for (unsigned int i=0; i<np; i++)
     296             :         {
     297     1123382 :           _points[q](0) = q1D.qp(i)(0);
     298      879329 :           _points[q](1) = q1D.qp(j)(0);
     299      879329 :           _points[q](2) = q1D.qp(k)(0);
     300             : 
     301     1123382 :           _weights[q] = q1D.w(i) * q1D.w(j) * q1D.w(k);
     302             : 
     303      879329 :           q++;
     304             :         }
     305        8557 : }
     306             : 
     307             : 
     308             : 
     309             : 
     310        8653 : void QBase::tensor_product_prism(const QBase & q1D, const QBase & q2D)
     311             : {
     312        2403 :   const unsigned int n_points1D = q1D.n_points();
     313        2403 :   const unsigned int n_points2D = q2D.n_points();
     314             : 
     315        8653 :   _points.resize  (n_points1D * n_points2D);
     316        8653 :   _weights.resize (n_points1D * n_points2D);
     317             : 
     318        2403 :   unsigned int q=0;
     319             : 
     320       38928 :   for (unsigned int j=0; j<n_points1D; j++)
     321      424089 :     for (unsigned int i=0; i<n_points2D; i++)
     322             :       {
     323      503799 :         _points[q](0) = q2D.qp(i)(0);
     324      393814 :         _points[q](1) = q2D.qp(i)(1);
     325      393814 :         _points[q](2) = q1D.qp(j)(0);
     326             : 
     327      393814 :         _weights[q] = q2D.w(i) * q1D.w(j);
     328             : 
     329      393814 :         q++;
     330             :       }
     331             : 
     332        8653 : }
     333             : 
     334             : 
     335             : 
     336             : 
     337           0 : std::ostream & operator << (std::ostream & os, const QBase & q)
     338             : {
     339           0 :   q.print_info(os);
     340           0 :   return os;
     341             : }
     342             : 
     343             : } // namespace libMesh

Generated by: LCOV version 1.14