LCOV - code coverage report
Current view: top level - src/quadrature - quadrature.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 118 148 79.7 %
Date: 2025-08-19 19:27:09 Functions: 9 15 60.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             : // 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    11823642 : QBase::QBase(unsigned int d,
      28    11823642 :              Order o) :
      29    10695853 :   allow_rules_with_negative_weights(true),
      30    10695853 :   allow_nodal_pyramid_quadrature(false),
      31    10695853 :   _dim(d),
      32    10695853 :   _order(o),
      33    10695853 :   _type(INVALID_ELEM),
      34    10695853 :   _elem(nullptr),
      35    11823642 :   _p_level(0)
      36    11823642 : {}
      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   145893607 : void QBase::init(const Elem & elem,
      66             :                  unsigned int p)
      67             : {
      68    12209300 :   libmesh_assert_equal_to(elem.dim(), _dim);
      69             : 
      70             :   // Default to the element p_level() value
      71   145893607 :   if (p == invalid_uint)
      72    19334826 :     p = elem.p_level();
      73             : 
      74   145893607 :   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   145893607 :   if (t == _type && p == _p_level && !elem.runtime_topology())
      84    12129410 :     return;
      85             :   else
      86             :     {
      87     1149438 :       _elem = &elem;
      88     1149438 :       _type = t;
      89     1149438 :       _p_level = p;
      90             :     }
      91             : 
      92     1149438 :   switch(_elem->dim())
      93             :     {
      94       11909 :     case 0:
      95       11909 :       this->init_0D();
      96             : 
      97       11909 :       return;
      98             : 
      99      149339 :     case 1:
     100      149339 :       this->init_1D();
     101             : 
     102      149339 :       return;
     103             : 
     104      661082 :     case 2:
     105      661082 :       this->init_2D();
     106             : 
     107      661082 :       return;
     108             : 
     109      327108 :     case 3:
     110      327108 :       this->init_3D();
     111             : 
     112      327108 :       return;
     113             : 
     114           0 :     default:
     115           0 :       libmesh_error_msg("Invalid dimension _dim = " << _dim);
     116             :     }
     117             : }
     118             : 
     119             : 
     120             : 
     121     5481711 : 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     5481711 :   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      278910 :   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     5481711 :   if (t == _type && p == _p_level)
     141        2306 :     return;
     142             :   else
     143             :     {
     144     5408966 :       _elem = nullptr;
     145     5408966 :       _type = t;
     146     5408966 :       _p_level = p;
     147             :     }
     148             : 
     149     5408966 :   switch(_dim)
     150             :     {
     151           5 :     case 0:
     152           5 :       this->init_0D();
     153             : 
     154           5 :       return;
     155             : 
     156     5371962 :     case 1:
     157     5371962 :       this->init_1D();
     158             : 
     159     5371962 :       return;
     160             : 
     161       36412 :     case 2:
     162       36412 :       this->init_2D();
     163             : 
     164       36412 :       return;
     165             : 
     166         587 :     case 3:
     167         587 :       this->init_3D();
     168             : 
     169         587 :       return;
     170             : 
     171           0 :     default:
     172           0 :       libmesh_error_msg("Invalid dimension _dim = " << _dim);
     173             :     }
     174             : }
     175             : 
     176             : 
     177             : 
     178      144749 : void QBase::init(const QBase & other_rule)
     179             : {
     180      144749 :   if (other_rule._elem)
     181       78195 :     this->init(*other_rule._elem, other_rule._p_level);
     182             :   else
     183       66554 :     this->init(other_rule._type, other_rule._p_level, true);
     184      144749 : }
     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       11914 : void QBase::init_0D()
     199             : {
     200       11914 :   _points.resize(1);
     201       11914 :   _weights.resize(1);
     202       11914 :   _points[0] = Point(0.);
     203       11914 :   _weights[0] = 1.0;
     204       11914 : }
     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        1349 : 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        1349 :     h_new = new_range.second - new_range.first,
     230        1349 :     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        1349 :   Real scfact = h_new/h_old;
     241             : 
     242             :   // We're mapping from old_range -> new_range
     243        4899 :   for (auto i : index_range(_points))
     244             :     {
     245        3550 :       _points[i](0) = new_range.first +
     246        3550 :         (_points[i](0) - old_range.first) * scfact;
     247             : 
     248             :       // Scale the weights
     249        3650 :       _weights[i] *= scfact;
     250             :     }
     251        1349 : }
     252             : 
     253             : 
     254             : 
     255             : 
     256      492480 : void QBase::tensor_product_quad(const QBase & q1D)
     257             : {
     258             : 
     259       35045 :   const unsigned int np = q1D.n_points();
     260             : 
     261      492480 :   _points.resize(np * np);
     262             : 
     263      492480 :   _weights.resize(np * np);
     264             : 
     265       35045 :   unsigned int q=0;
     266             : 
     267     2404651 :   for (unsigned int j=0; j<np; j++)
     268    14551130 :     for (unsigned int i=0; i<np; i++)
     269             :       {
     270    13779954 :         _points[q](0) = q1D.qp(i)(0);
     271    12638959 :         _points[q](1) = q1D.qp(j)(0);
     272             : 
     273    12638959 :         _weights[q] = q1D.w(i)*q1D.w(j);
     274             : 
     275    12638959 :         q++;
     276             :       }
     277      492480 : }
     278             : 
     279             : 
     280             : 
     281             : 
     282             : 
     283       40249 : void QBase::tensor_product_hex(const QBase & q1D)
     284             : {
     285        2085 :   const unsigned int np = q1D.n_points();
     286             : 
     287       40249 :   _points.resize(np * np * np);
     288             : 
     289       40249 :   _weights.resize(np * np * np);
     290             : 
     291        2085 :   unsigned int q=0;
     292             : 
     293      175761 :   for (unsigned int k=0; k<np; k++)
     294      860814 :     for (unsigned int j=0; j<np; j++)
     295     8068404 :       for (unsigned int i=0; i<np; i++)
     296             :         {
     297     7584007 :           _points[q](0) = q1D.qp(i)(0);
     298     7343102 :           _points[q](1) = q1D.qp(j)(0);
     299     7343102 :           _points[q](2) = q1D.qp(k)(0);
     300             : 
     301     7584007 :           _weights[q] = q1D.w(i) * q1D.w(j) * q1D.w(k);
     302             : 
     303     7343102 :           q++;
     304             :         }
     305       40249 : }
     306             : 
     307             : 
     308             : 
     309             : 
     310       28776 : void QBase::tensor_product_prism(const QBase & q1D, const QBase & q2D)
     311             : {
     312        2097 :   const unsigned int n_points1D = q1D.n_points();
     313        2097 :   const unsigned int n_points2D = q2D.n_points();
     314             : 
     315       28776 :   _points.resize  (n_points1D * n_points2D);
     316       28776 :   _weights.resize (n_points1D * n_points2D);
     317             : 
     318        2097 :   unsigned int q=0;
     319             : 
     320      131136 :   for (unsigned int j=0; j<n_points1D; j++)
     321     1669451 :     for (unsigned int i=0; i<n_points2D; i++)
     322             :       {
     323     1668572 :         _points[q](0) = q2D.qp(i)(0);
     324     1567091 :         _points[q](1) = q2D.qp(i)(1);
     325     1567091 :         _points[q](2) = q1D.qp(j)(0);
     326             : 
     327     1567091 :         _weights[q] = q2D.w(i) * q1D.w(j);
     328             : 
     329     1567091 :         q++;
     330             :       }
     331             : 
     332       28776 : }
     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