LCOV - code coverage report
Current view: top level - src/postprocessors - SideIntegralFunctorPostprocessor.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 39 44 88.6 %
Date: 2025-07-17 01:28:37 Functions: 14 18 77.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "SideIntegralFunctorPostprocessor.h"
      11             : 
      12             : #include "metaphysicl/raw_type.h"
      13             : 
      14             : registerMooseObject("MooseApp", SideIntegralFunctorPostprocessor);
      15             : registerMooseObject("MooseApp", ADSideIntegralFunctorPostprocessor);
      16             : 
      17             : template <bool is_ad>
      18             : InputParameters
      19       44404 : SideIntegralFunctorPostprocessorTempl<is_ad>::validParams()
      20             : {
      21       44404 :   InputParameters params = SideIntegralPostprocessor::validParams();
      22       44404 :   params.addRequiredParam<MooseFunctorName>(
      23             :       "functor", "The name of the functor that this postprocessor integrates");
      24       44404 :   params.addParam<MooseFunctorName>("prefactor", 1, "Factor multiplying the integrand");
      25      133212 :   params.addParam<bool>("restrict_to_functors_domain",
      26       88808 :                         false,
      27             :                         "If the functor (and the prefactor) is only defined only along part of "
      28             :                         "the sideset, allows to skip the parts where it is not defined. Please "
      29             :                         "keep in mind that if the sideset is defined with the wrong normal, this "
      30             :                         "may allow to skip the entire integral.");
      31       44404 :   MooseEnum functor_args("qp face", "face");
      32       44404 :   params.addParam<MooseEnum>(
      33             :       "functor_argument", functor_args, "Location to evaluate the functors at");
      34       44404 :   params.addClassDescription(
      35             :       "Computes a surface integral of the specified functor, using the "
      36             :       "single-sided face argument, which usually means that the functor will be"
      37             :       " evaluated from a single side of the surface, not interpolated between "
      38             :       "both sides.");
      39       88808 :   return params;
      40       44404 : }
      41             : 
      42             : template <bool is_ad>
      43         837 : SideIntegralFunctorPostprocessorTempl<is_ad>::SideIntegralFunctorPostprocessorTempl(
      44             :     const InputParameters & parameters)
      45             :   : SideIntegralPostprocessor(parameters),
      46         837 :     _functor(getFunctor<GenericReal<is_ad>>("functor")),
      47         837 :     _prefactor(getFunctor<GenericReal<is_ad>>("prefactor")),
      48        1674 :     _partial_integral(getParam<bool>("restrict_to_functors_domain"))
      49             : {
      50         837 :   _qp_integration = (getParam<MooseEnum>("functor_argument") == "qp");
      51             : 
      52         837 :   checkFunctorSupportsSideIntegration<GenericReal<is_ad>>("functor", _qp_integration);
      53         837 :   checkFunctorSupportsSideIntegration<GenericReal<is_ad>>("prefactor", _qp_integration);
      54         837 : }
      55             : 
      56             : template <bool is_ad>
      57             : Real
      58       23552 : SideIntegralFunctorPostprocessorTempl<is_ad>::computeFaceInfoIntegral(const FaceInfo * fi)
      59             : {
      60             :   mooseAssert(fi, "We should have a FaceInfo");
      61       23552 :   const auto face = makeCDFace(*fi);
      62       47104 :   return computeLocalContribution(face);
      63             : }
      64             : 
      65             : template <bool is_ad>
      66             : template <typename T>
      67             : Real
      68       27048 : SideIntegralFunctorPostprocessorTempl<is_ad>::computeLocalContribution(const T & functor_arg) const
      69             : {
      70             :   // It's possible the functor is not defined on that side of the boundary
      71             :   // We wont allow that case, unless explicitly requested by the user,
      72             :   // as this means the sideset is reversed, but we will allow the case where
      73             :   // both sides are defined
      74       27048 :   const bool has_elem = checkFunctorDefinedOnSideBlock();
      75             : 
      76       27048 :   if (has_elem)
      77       49000 :     return MetaPhysicL::raw_value(_prefactor(functor_arg, determineState()) *
      78       71624 :                                   _functor(functor_arg, determineState()));
      79             :   else
      80             :   {
      81         672 :     if (!_partial_integral)
      82           0 :       errorFunctorNotDefinedOnSideBlock();
      83         672 :     return 0;
      84             :   }
      85             : }
      86             : 
      87             : template <bool is_ad>
      88             : Real
      89        3496 : SideIntegralFunctorPostprocessorTempl<is_ad>::computeQpIntegral()
      90             : {
      91        3496 :   Moose::ElemSideQpArg elem_side_qp = {_current_elem, _current_side, _qp, _qrule, _q_point[_qp]};
      92        6992 :   return computeLocalContribution(elem_side_qp);
      93             : }
      94             : 
      95             : template <bool is_ad>
      96             : bool
      97       27048 : SideIntegralFunctorPostprocessorTempl<is_ad>::checkFunctorDefinedOnSideBlock() const
      98             : {
      99       53424 :   if (_functor.hasBlocks(_current_elem->subdomain_id()) &&
     100       26376 :       _prefactor.hasBlocks(_current_elem->subdomain_id()))
     101       26376 :     return true;
     102             :   else
     103             :   {
     104             : #ifndef NDEBUG
     105             :     const auto neighbor_ptr = _current_elem->neighbor_ptr(_current_side);
     106             :     if (neighbor_ptr)
     107             :     {
     108             :       mooseAssert(_functor.hasBlocks(_current_elem->subdomain_id()) ||
     109             :                       _functor.hasBlocks(neighbor_ptr->subdomain_id()),
     110             :                   "Functor should be defined on at least one side of the boundary");
     111             :       mooseAssert(_prefactor.hasBlocks(_current_elem->subdomain_id()) ||
     112             :                       _prefactor.hasBlocks(neighbor_ptr->subdomain_id()),
     113             :                   "Prefactor should be defined on at least one side of the boundary");
     114             :     }
     115             : #endif
     116         672 :     return false;
     117             :   }
     118             : }
     119             : 
     120             : template <bool is_ad>
     121             : void
     122           0 : SideIntegralFunctorPostprocessorTempl<is_ad>::errorFunctorNotDefinedOnSideBlock() const
     123             : {
     124           0 :   paramError("boundary",
     125           0 :              "Functor " + _functor.functorName() + " (or prefactor " + _prefactor.functorName() +
     126           0 :                  ") is not defined on block " + std::to_string(_current_elem->subdomain_id()) +
     127             :                  ". Is the functor defined along the whole sideset? "
     128             :                  "Are the sidesets in 'boundary' all oriented correctly?");
     129             : }
     130             : 
     131             : template <bool is_ad>
     132             : bool
     133       47104 : SideIntegralFunctorPostprocessorTempl<is_ad>::hasFaceSide(const FaceInfo & fi,
     134             :                                                           const bool fi_elem_side) const
     135             : {
     136       47104 :   return _current_elem == (fi_elem_side ? &fi.elem() : fi.neighborPtr());
     137             : }
     138             : 
     139             : template class SideIntegralFunctorPostprocessorTempl<false>;
     140             : template class SideIntegralFunctorPostprocessorTempl<true>;

Generated by: LCOV version 1.14