LCOV - code coverage report
Current view: top level - src/fvbcs - NSFVHeatFluxBC.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: #32971 (54bef8) with base c6cf66 Lines: 77 79 97.5 %
Date: 2026-05-29 20:37:52 Functions: 3 3 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 "NSFVHeatFluxBC.h"
      11             : #include "NS.h"
      12             : #include "NSEnums.h"
      13             : 
      14             : registerADMooseObject("NavierStokesApp", NSFVHeatFluxBC);
      15             : 
      16             : InputParameters
      17         228 : NSFVHeatFluxBC::validParams()
      18             : {
      19         228 :   InputParameters params = FVFluxBC::validParams();
      20             : 
      21         456 :   params.addRequiredParam<Real>("value", "total heat flux");
      22         456 :   params.addRequiredParam<MooseEnum>(
      23         456 :       "phase", getPhaseEnum(), "'fluid' or 'solid' phase to which this BC is applied.");
      24             : 
      25         456 :   params.addRequiredParam<MooseEnum>("splitting", getSplittingEnum(), "type of splitting");
      26             : 
      27         456 :   params.addRequiredParam<MooseEnum>(
      28             :       "locality",
      29         456 :       getLocalityEnum(),
      30             :       "whether to use local (at the boundary) or global (domain-averaged) "
      31             :       "parameter values");
      32             : 
      33         228 :   params.addCoupledVar(NS::porosity, "porosity");
      34         456 :   params.addParam<PostprocessorName>("average_porosity",
      35             :                                      "postprocessor that provides domain-averaged porosity");
      36         456 :   params.addParam<PostprocessorName>(
      37             :       "average_k_fluid", "postprocessor that provides domain-averaged fluid thermal conductivity");
      38         456 :   params.addParam<PostprocessorName>(
      39             :       "average_kappa", "postprocessor that provides domain-averaged fluid thermal dispersion");
      40         456 :   params.addParam<PostprocessorName>(
      41             :       "average_k_solid", "postprocessor that provides domain-averaged solid thermal conductivity");
      42         456 :   params.addParam<PostprocessorName>(
      43             :       "average_kappa_solid",
      44             :       "postprocessor that provides domain-averaged solid effective thermal "
      45             :       "conductivity");
      46         228 :   params.addClassDescription("Constant heat flux boundary condition with phase splitting "
      47             :                              "for fluid and solid energy equations");
      48         228 :   return params;
      49           0 : }
      50             : 
      51         120 : NSFVHeatFluxBC::NSFVHeatFluxBC(const InputParameters & parameters)
      52             :   : FVFluxBC(parameters),
      53         120 :     _value(getParam<Real>("value")),
      54         240 :     _phase(getParam<MooseEnum>("phase").getEnum<NS::phase::PhaseEnum>()),
      55         240 :     _split_type(getParam<MooseEnum>("splitting").getEnum<NS::splitting::SplittingEnum>()),
      56         240 :     _locality(getParam<MooseEnum>("locality").getEnum<NS::settings::LocalityEnum>()),
      57             :     // quantities needed for global evaluations
      58         300 :     _average_eps(_locality == NS::settings::global &&
      59          60 :                          _split_type != NS::splitting::thermal_conductivity
      60         180 :                      ? &getPostprocessorValue("average_porosity")
      61             :                      : nullptr),
      62          60 :     _average_k_f(_locality == NS::settings::global && _split_type != NS::splitting::porosity
      63         180 :                      ? &getPostprocessorValue("average_k_fluid")
      64             :                      : nullptr),
      65         300 :     _average_k_s(_locality == NS::settings::global &&
      66          60 :                          _split_type == NS::splitting::thermal_conductivity
      67         180 :                      ? &getPostprocessorValue("average_k_solid")
      68             :                      : nullptr),
      69         300 :     _average_kappa_s(_locality == NS::settings::global &&
      70          60 :                              _split_type == NS::splitting::effective_thermal_conductivity
      71         180 :                          ? &getPostprocessorValue("average_kappa_solid")
      72             :                          : nullptr),
      73         300 :     _average_kappa(_locality == NS::settings::global &&
      74          60 :                            _split_type == NS::splitting::effective_thermal_conductivity
      75         180 :                        ? &getPostprocessorValue("average_kappa")
      76             :                        : nullptr),
      77             :     // quantities needed for local evaluations
      78          60 :     _eps(_locality == NS::settings::local && _split_type != NS::splitting::thermal_conductivity
      79         180 :              ? coupledValue(NS::porosity)
      80             :              : _zero),
      81          60 :     _k_f(_locality == NS::settings::local && _split_type != NS::splitting::porosity
      82         160 :              ? &getADMaterialProperty<Real>(NS::k)
      83             :              : nullptr),
      84          60 :     _k_s(_locality == NS::settings::local && _split_type == NS::splitting::thermal_conductivity
      85         140 :              ? &getADMaterialProperty<Real>(NS::k_s)
      86             :              : nullptr),
      87         300 :     _kappa(_locality == NS::settings::local &&
      88          60 :                    _split_type == NS::splitting::effective_thermal_conductivity
      89         140 :                ? &getADMaterialProperty<RealVectorValue>(NS::kappa)
      90             :                : nullptr),
      91         300 :     _kappa_s(_locality == NS::settings::local &&
      92          60 :                      _split_type == NS::splitting::effective_thermal_conductivity
      93         140 :                  ? &getADMaterialProperty<Real>(NS::kappa_s)
      94         120 :                  : nullptr)
      95             : {
      96         120 : }
      97             : 
      98             : ADReal
      99       36240 : NSFVHeatFluxBC::computeQpResidual()
     100             : {
     101             :   // we don't need default statements in the switch-case statements for
     102             :   // the SplittingEnum because we by default set the fraction to zero such that
     103             :   // all of the heat flux enters the solid phase (though this default is never
     104             :   // reached since the InputParameters class requires the MooseEnum to be
     105             :   // one of 'porosity', 'thermal_conductivity', or 'effective_thermal_conductivity'
     106       36240 :   ADReal fraction = 0.0;
     107       36240 :   ADReal tol = NS_DEFAULT_VALUES::k_epsilon;
     108             : 
     109       36240 :   if (_locality == NS::settings::local)
     110             :   {
     111       18120 :     switch (_split_type)
     112             :     {
     113        6040 :       case NS::splitting::porosity:
     114             :       {
     115        6040 :         fraction = _eps[_qp];
     116             :         break;
     117             :       }
     118        6040 :       case NS::splitting::thermal_conductivity:
     119             :       {
     120        6040 :         ADReal d = (*_k_f)[_qp] + (*_k_s)[_qp];
     121       12080 :         fraction = d > tol ? (*_k_f)[_qp] / d : 0.5;
     122             :         break;
     123             :       }
     124             :       case NS::splitting::effective_thermal_conductivity:
     125             :       {
     126             :         // TODO: for the case of an anisotropic conductivity, we technically should
     127             :         // grab the component of kappa perpendicular to the boundary.
     128             : 
     129             :         // Need this logic to avoid AD failures when taking norms of zero. The
     130             :         // division by sqrt(3) ensures equivalence with a non-vector form of kappa with
     131             :         // 3 components
     132             :         ADReal kappa;
     133       12080 :         if ((MooseUtils::absoluteFuzzyEqual((*_kappa)[_qp](0), 0)) &&
     134       12080 :             (MooseUtils::absoluteFuzzyEqual((*_kappa)[_qp](1), 0)) &&
     135        6040 :             (MooseUtils::absoluteFuzzyEqual((*_kappa)[_qp](2), 0)))
     136           0 :           kappa = 1e-42;
     137             :         else
     138       12080 :           kappa = (*_kappa)[_qp].norm() / std::sqrt(3.0);
     139             : 
     140       12080 :         ADReal d = _eps[_qp] * kappa + (*_kappa_s)[_qp];
     141       18120 :         fraction = d > tol ? _eps[_qp] * kappa / d : 0.5;
     142             :         break;
     143             :       }
     144             :     }
     145             :   }
     146             :   else
     147             :   {
     148       18120 :     switch (_split_type)
     149             :     {
     150        6040 :       case NS::splitting::porosity:
     151             :       {
     152        6040 :         fraction = *_average_eps;
     153             :         break;
     154             :       }
     155        6040 :       case NS::splitting::thermal_conductivity:
     156             :       {
     157        6040 :         ADReal d = *_average_k_f + *_average_k_s;
     158        6040 :         fraction = d > tol ? *_average_k_f / d : 0.5;
     159             :         break;
     160             :       }
     161        6040 :       case NS::splitting::effective_thermal_conductivity:
     162             :       {
     163        6040 :         ADReal d = (*_average_eps) * (*_average_kappa) + (*_average_kappa_s);
     164        6040 :         fraction = d > tol ? (*_average_eps) * (*_average_kappa) / d : 0.5;
     165             :         break;
     166             :       }
     167             :     }
     168             :   }
     169             : 
     170       36240 :   if (_phase == NS::phase::solid)
     171       36240 :     return (1.0 - fraction) * -_value;
     172             :   else
     173       36240 :     return fraction * -_value;
     174             : }

Generated by: LCOV version 1.14