LCOV - code coverage report
Current view: top level - src/error_estimation - fourth_error_estimators.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 51 55 92.7 %
Date: 2025-08-19 19:27:09 Functions: 3 4 75.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             : #include "libmesh/libmesh_config.h"
      20             : 
      21             : #include "libmesh/fourth_error_estimators.h"
      22             : 
      23             : #include "libmesh/enum_error_estimator_type.h"
      24             : 
      25             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      26             : 
      27             : // Local Includes
      28             : #include "libmesh/libmesh_common.h"
      29             : #include "libmesh/error_vector.h"
      30             : #include "libmesh/fe_base.h"
      31             : #include "libmesh/libmesh_logging.h"
      32             : #include "libmesh/elem.h"
      33             : #include "libmesh/system.h"
      34             : #include "libmesh/dense_vector.h"
      35             : #include "libmesh/tensor_tools.h"
      36             : #include "libmesh/enum_norm_type.h"
      37             : 
      38             : // C++ includes
      39             : #include <algorithm> // for std::fill
      40             : #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
      41             : #include <cmath>    // for sqrt
      42             : 
      43             : namespace libMesh
      44             : {
      45             : 
      46             : 
      47        2982 : LaplacianErrorEstimator::LaplacianErrorEstimator() :
      48        2982 :   JumpErrorEstimator()
      49             : {
      50        2982 :   error_norm = H2_SEMINORM;
      51        2982 : }
      52             : 
      53             : 
      54             : 
      55             : ErrorEstimatorType
      56           0 : LaplacianErrorEstimator::type() const
      57             : {
      58           0 :   return LAPLACIAN;
      59             : }
      60             : 
      61             : 
      62             : 
      63             : void
      64        5964 : LaplacianErrorEstimator::init_context(FEMContext & c)
      65             : {
      66         168 :   const unsigned int n_vars = c.n_vars();
      67       11928 :   for (unsigned int v=0; v<n_vars; v++)
      68             :     {
      69             :       // Possibly skip this variable
      70        5964 :       if (error_norm.weight(v) == 0.0) continue;
      71             : 
      72             :       // FIXME: Need to generalize this to vector-valued elements. [PB]
      73         168 :       FEBase * side_fe = nullptr;
      74             : 
      75             :       const std::set<unsigned char> & elem_dims =
      76         168 :         c.elem_dimensions();
      77             : 
      78       11928 :       for (const auto & dim : elem_dims)
      79             :         {
      80        5964 :           c.get_side_fe( v, side_fe, dim );
      81             : 
      82             :           // We'll need hessians on both sides for flux jump computation
      83         168 :           side_fe->get_d2phi();
      84             :         }
      85             :     }
      86        5964 : }
      87             : 
      88             : 
      89             : 
      90             : void
      91       36809 : LaplacianErrorEstimator::internal_side_integration ()
      92             : {
      93        6108 :   const Elem & coarse_elem = coarse_context->get_elem();
      94        6108 :   const Elem & fine_elem   = fine_context->get_elem();
      95             : 
      96        3054 :   const DenseVector<Number> & Ucoarse = coarse_context->get_elem_solution();
      97        3054 :   const DenseVector<Number> & Ufine   = fine_context->get_elem_solution();
      98             : 
      99       36809 :   unsigned short dim = fine_elem.dim();
     100             : 
     101        3054 :   FEBase * fe_fine = nullptr;
     102       36809 :   fine_context->get_side_fe( var, fe_fine, dim );
     103             : 
     104        3054 :   FEBase * fe_coarse = nullptr;
     105        3054 :   coarse_context->get_side_fe( var, fe_coarse, dim );
     106             : 
     107        3054 :   Real error = 1.e-30;
     108       36809 :   unsigned int n_qp = fe_fine->n_quadrature_points();
     109             : 
     110        3054 :   const std::vector<std::vector<RealTensor>> & d2phi_coarse = fe_coarse->get_d2phi();
     111        3054 :   const std::vector<std::vector<RealTensor>> & d2phi_fine = fe_fine->get_d2phi();
     112        9359 :   const std::vector<Real> & JxW_face = fe_fine->get_JxW();
     113             : 
     114      110259 :   for (unsigned int qp=0; qp != n_qp; ++qp)
     115             :     {
     116             :       // Calculate solution gradients on fine and coarse elements
     117             :       // at this quadrature point
     118        6094 :       Number laplacian_fine = 0., laplacian_coarse = 0.;
     119             : 
     120        6094 :       const unsigned int n_coarse_dofs = Ucoarse.size();
     121     1070162 :       for (unsigned int i=0; i != n_coarse_dofs; ++i)
     122             :         {
     123     1161972 :           laplacian_coarse += d2phi_coarse[i][qp](0,0) * Ucoarse(i);
     124      996712 :           if (dim > 1)
     125      907008 :             laplacian_coarse += d2phi_coarse[i][qp](1,1) * Ucoarse(i);
     126      996012 :           if (dim > 2)
     127           0 :             laplacian_coarse += d2phi_coarse[i][qp](2,2) * Ucoarse(i);
     128             :         }
     129             : 
     130        6094 :       const unsigned int n_fine_dofs = Ufine.size();
     131     1070162 :       for (unsigned int i=0; i != n_fine_dofs; ++i)
     132             :         {
     133     1161972 :           laplacian_fine += d2phi_fine[i][qp](0,0) * Ufine(i);
     134      996712 :           if (dim > 1)
     135      907008 :             laplacian_fine += d2phi_fine[i][qp](1,1) * Ufine(i);
     136      996012 :           if (dim > 2)
     137           0 :             laplacian_fine += d2phi_fine[i][qp](2,2) * Ufine(i);
     138             :         }
     139             : 
     140             : 
     141             :       // Find the jump in the Laplacian
     142             :       // at this quadrature point
     143       66962 :       const Number jump = laplacian_fine - laplacian_coarse;
     144        6094 :       const Real jump2 = TensorTools::norm_sq(jump);
     145             : 
     146             :       // Accumulate the jump integral
     147       79544 :       error += JxW_face[qp] * jump2;
     148             :     }
     149             : 
     150             :   // Add the h-weighted jump integral to each error term
     151       36809 :   fine_error =
     152       36809 :     error * fine_elem.hmax() * error_norm.weight(var);
     153       36809 :   coarse_error =
     154       36809 :     error * coarse_elem.hmax() * error_norm.weight(var);
     155       36809 : }
     156             : 
     157             : } // namespace libMesh
     158             : 
     159             : #else // defined (LIBMESH_ENABLE_SECOND_DERIVATIVES)
     160             : 
     161             : namespace libMesh
     162             : {
     163             : 
     164             : LaplacianErrorEstimator::LaplacianErrorEstimator() :
     165             :   JumpErrorEstimator()
     166             : {
     167             :   libmesh_error_msg("Error: LaplacianErrorEstimator requires second " \
     168             :                     << "derivative support; try configuring libmesh with " \
     169             :                     << "--enable-second");
     170             : }
     171             : 
     172             : ErrorEstimatorType
     173             : LaplacianErrorEstimator::type() const
     174             : {
     175             :   return LAPLACIAN;
     176             : }
     177             : 
     178             : 
     179             : 
     180             : void LaplacianErrorEstimator::init_context (FEMContext &) {}
     181             : 
     182             : void LaplacianErrorEstimator::internal_side_integration () {}
     183             : 
     184             : } // namespace libMesh
     185             : 
     186             : #endif // defined (LIBMESH_ENABLE_SECOND_DERIVATIVES)

Generated by: LCOV version 1.14