LCOV - code coverage report
Current view: top level - src/bcs - ADConvectiveHeatFluxBC.C (source / functions) Hit Total Coverage
Test: idaholab/moose heat_transfer: #31405 (292dce) with base fef103 Lines: 67 76 88.2 %
Date: 2025-09-04 07:53:51 Functions: 6 6 100.0 %
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 "ADConvectiveHeatFluxBC.h"
      11             : 
      12             : registerMooseObject("HeatTransferApp", ADConvectiveHeatFluxBC);
      13             : 
      14             : InputParameters
      15         321 : ADConvectiveHeatFluxBC::validParams()
      16             : {
      17         321 :   InputParameters params = ADIntegratedBC::validParams();
      18         321 :   params.addClassDescription(
      19             :       "Convective heat transfer boundary condition with temperature and heat "
      20             :       "transfer coefficient given by material properties.");
      21             :   // Using material properties
      22         642 :   params.addParam<MaterialPropertyName>("T_infinity",
      23             :                                         "Material property for far-field temperature");
      24         642 :   params.addParam<MaterialPropertyName>("heat_transfer_coefficient",
      25             :                                         "Material property for heat transfer coefficient");
      26             :   // Using functors
      27         642 :   params.addParam<MooseFunctorName>("T_infinity_functor", "Functor for far-field temperature");
      28         642 :   params.addParam<MooseFunctorName>("heat_transfer_coefficient_functor",
      29             :                                     "Functor for heat transfer coefficient");
      30             :   // In the case where we are coupling a FV variable (via functors) that are block restricted on the
      31             :   // neighboring side of boundary, we need to have two layers of ghosting to do the face
      32             :   // interpolation.
      33         642 :   params.addRelationshipManager("ElementSideNeighborLayers",
      34             :                                 Moose::RelationshipManagerType::GEOMETRIC |
      35             :                                     Moose::RelationshipManagerType::ALGEBRAIC,
      36         279 :                                 [](const InputParameters & obj_params, InputParameters & rm_params)
      37             :                                 {
      38         495 :                                   rm_params.set<unsigned short>("layers") =
      39         279 :                                       obj_params.isParamValid("T_infinity_functor") ? 2 : 1;
      40         279 :                                 });
      41         321 :   return params;
      42           0 : }
      43             : 
      44         152 : ADConvectiveHeatFluxBC::ADConvectiveHeatFluxBC(const InputParameters & parameters)
      45             :   : ADIntegratedBC(parameters),
      46         318 :     _T_infinity(isParamValid("T_infinity") ? &getADMaterialProperty<Real>("T_infinity") : nullptr),
      47         152 :     _htc(isParamValid("heat_transfer_coefficient")
      48         318 :              ? &getADMaterialProperty<Real>("heat_transfer_coefficient")
      49             :              : nullptr),
      50         152 :     _T_infinity_functor(
      51         442 :         isParamValid("T_infinity_functor") ? &getFunctor<ADReal>("T_infinity_functor") : nullptr),
      52         152 :     _htc_functor(isParamValid("heat_transfer_coefficient_functor")
      53         290 :                      ? &getFunctor<ADReal>("heat_transfer_coefficient_functor")
      54         152 :                      : nullptr)
      55             : {
      56         152 :   if (_T_infinity || _htc)
      57             :   {
      58          83 :     if (_T_infinity_functor)
      59           0 :       paramError("T_infinity_functor",
      60             :                  "Either material properties or functors should be specified for both T_infinity "
      61             :                  "and the heat transfer coefficient.");
      62          83 :     if (_htc_functor)
      63           0 :       paramError("heat_transfer_coefficient_functor",
      64             :                  "Either material properties or functors should be specified for both T_infinity "
      65             :                  "and the heat transfer coefficient");
      66          83 :     if (!_htc)
      67           0 :       paramError("heat_transfer_coefficient",
      68             :                  "Heat transfer coefficient material property must be specified");
      69          83 :     if (!_T_infinity)
      70           0 :       paramError("T_infinity", "Far field temperature material property must be specified");
      71             :   }
      72          69 :   else if (_T_infinity_functor || _htc_functor)
      73             :   {
      74          69 :     if (!_htc_functor)
      75           0 :       paramError("heat_transfer_coefficient_functor",
      76             :                  "Heat transfer coefficient functor must be specified");
      77          69 :     if (!_T_infinity_functor)
      78           0 :       paramError("T_infinity_functor", "Far field temperature functor must be specified");
      79             :   }
      80             :   else
      81           0 :     paramError("T_infinity",
      82             :                "Far field temperature and heat transfer coefficients must be specified");
      83         152 : }
      84             : 
      85             : void
      86         151 : ADConvectiveHeatFluxBC::initialSetup()
      87             : {
      88         151 :   if (_T_infinity)
      89          83 :     return;
      90             : 
      91             :   bool T_inf_can_use_neighbor = true;
      92             :   bool htc_can_use_neighbor = true;
      93             :   // Loop over elements on the primary side of all boundaries
      94        1484 :   for (const auto & bnd_elem : *_mesh.getBoundaryElementRange())
      95             :   {
      96        1416 :     const auto & [elem, side, bid] = *bnd_elem;
      97             :     // Skip if this boundary is not part of the restriction
      98        1416 :     if (!hasBoundary(bid) || (elem->processor_id() != this->processor_id()))
      99        1228 :       continue;
     100             : 
     101             :     // Use neighbors if the functor is not defined on all primary blocks
     102         188 :     _T_infinity_use_neighbor =
     103         188 :         _T_infinity_use_neighbor || !_T_infinity_functor->hasBlocks(elem->subdomain_id());
     104         188 :     _htc_use_neighbor = _htc_use_neighbor || !_htc_functor->hasBlocks(elem->subdomain_id());
     105             : 
     106             :     // Determine if neighbor can be used, just in case
     107         188 :     const auto neighbor = elem->neighbor_ptr(side);
     108             :     if (neighbor)
     109             :       mooseAssert(
     110             :           !neighbor->is_remote(),
     111             :           "The neighbor best not be remote because we request at least one layer of ghosting");
     112         330 :     T_inf_can_use_neighbor = T_inf_can_use_neighbor && neighbor &&
     113         142 :                              _T_infinity_functor->hasBlocks(neighbor->subdomain_id());
     114             :     htc_can_use_neighbor =
     115         188 :         htc_can_use_neighbor && neighbor && _htc_functor->hasBlocks(neighbor->subdomain_id());
     116             :   }
     117             : 
     118          68 :   _communicator.max(_T_infinity_use_neighbor);
     119          68 :   _communicator.max(_htc_use_neighbor);
     120             : 
     121             :   const std::string error_msg =
     122             :       "Functor must either be defined on all of the primary side of the boundary or on all "
     123          68 :       "of the secondary side.";
     124          68 :   if (_T_infinity_use_neighbor && !T_inf_can_use_neighbor)
     125           2 :     paramError("T_infinity_functor", error_msg);
     126          66 :   if (_htc_use_neighbor && !htc_can_use_neighbor)
     127           0 :     paramError("heat_transfer_coefficient_functor", error_msg);
     128             : }
     129             : 
     130             : ADReal
     131      295440 : ADConvectiveHeatFluxBC::computeQpResidual()
     132             : {
     133      295440 :   if (_T_infinity)
     134      822768 :     return -_test[_i][_qp] * (*_htc)[_qp] * ((*_T_infinity)[_qp] - _u[_qp]);
     135             :   else
     136             :   {
     137             :     // Populate neighbor information, if necessary (optimization on first qp)
     138       21184 :     if ((_T_infinity_use_neighbor || _htc_use_neighbor) && _qp == 0)
     139             :     {
     140        9800 :       _current_neighbor_elem = _current_elem->neighbor_ptr(_current_side);
     141             :       mooseAssert(_current_neighbor_elem, "Neighbor element should exist at this point.");
     142        9800 :       _current_neighbor_side = _current_neighbor_elem->which_neighbor_am_i(_current_elem);
     143             :     }
     144             : 
     145             :     // Convenience lambda for getting space argument on either element or neighbor
     146       42368 :     const auto get_space_arg = [this](bool use_neighbor) -> Moose::ElemSideQpArg
     147             :     {
     148       42368 :       if (!use_neighbor)
     149       22768 :         return {_current_elem, _current_side, _qp, _qrule, _q_point[_qp]};
     150             :       else
     151       19600 :         return {_current_neighbor_elem, _current_neighbor_side, _qp, _qrule, _q_point[_qp]};
     152       21184 :     };
     153             : 
     154       21184 :     const auto Tinf_space_arg = get_space_arg(_T_infinity_use_neighbor);
     155       21184 :     const auto htc_space_arg = get_space_arg(_htc_use_neighbor);
     156       21184 :     const auto time_arg = Moose::currentState();
     157       21184 :     return -_test[_i][_qp] * (*_htc_functor)(htc_space_arg, time_arg) *
     158       42368 :            ((*_T_infinity_functor)(Tinf_space_arg, time_arg) - _u[_qp]);
     159             :   }
     160             : }

Generated by: LCOV version 1.14