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>;