LCOV - code coverage report
Current view: top level - src/linearfvkernels - LinearFVAnisotropicDiffusion.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 101 106 95.3 %
Date: 2026-05-29 20:35:17 Functions: 11 11 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 "LinearFVAnisotropicDiffusion.h"
      11             : #include "Assembly.h"
      12             : #include "SubProblem.h"
      13             : #include "LinearFVAdvectionDiffusionBC.h"
      14             : 
      15             : registerMooseObject("MooseApp", LinearFVAnisotropicDiffusion);
      16             : 
      17             : InputParameters
      18        3121 : LinearFVAnisotropicDiffusion::validParams()
      19             : {
      20        3121 :   InputParameters params = LinearFVFluxKernel::validParams();
      21        6242 :   params.addClassDescription("Represents the matrix and right hand side contributions of a "
      22             :                              "diffusion term in a partial differential equation.");
      23        9363 :   params.addParam<bool>(
      24             :       "use_nonorthogonal_correction",
      25        6242 :       true,
      26             :       "If the nonorthogonal correction should be used when computing the normal gradient.");
      27       12484 :   params.addParam<bool>(
      28             :       "use_nonorthogonal_correction_on_boundary",
      29             :       "If the nonorthogonal correction should be used when computing the normal gradient.");
      30        9363 :   params.addRequiredParam<MooseFunctorName>("diffusion_tensor",
      31             :                                             "Functor describing a diagonal diffusion tensor.");
      32        3121 :   return params;
      33           0 : }
      34             : 
      35          30 : LinearFVAnisotropicDiffusion::LinearFVAnisotropicDiffusion(const InputParameters & params)
      36             :   : LinearFVFluxKernel(params),
      37          30 :     _diffusion_tensor(getFunctor<RealVectorValue>("diffusion_tensor")),
      38          60 :     _use_nonorthogonal_correction(getParam<bool>("use_nonorthogonal_correction")),
      39          30 :     _use_nonorthogonal_correction_on_boundary(
      40          60 :         isParamValid("use_nonorthogonal_correction_on_boundary")
      41          60 :             ? getParam<bool>("use_nonorthogonal_correction_on_boundary")
      42          30 :             : _use_nonorthogonal_correction),
      43          30 :     _flux_matrix_contribution(0.0),
      44          30 :     _flux_rhs_contribution(0.0)
      45             : {
      46          30 :   _var.computeCellGradients();
      47          30 : }
      48             : 
      49             : void
      50          30 : LinearFVAnisotropicDiffusion::initialSetup()
      51             : {
      52         150 :   for (const auto bc : _var.getBoundaryConditionMap())
      53         120 :     if (!dynamic_cast<const LinearFVAdvectionDiffusionBC *>(bc.second))
      54           0 :       mooseError(
      55           0 :           bc.second->type(), " is not a compatible boundary condition with ", this->type(), "!");
      56          30 : }
      57             : 
      58             : Real
      59       72075 : LinearFVAnisotropicDiffusion::computeElemMatrixContribution()
      60             : {
      61       72075 :   return computeFluxMatrixContribution();
      62             : }
      63             : 
      64             : Real
      65       72075 : LinearFVAnisotropicDiffusion::computeNeighborMatrixContribution()
      66             : {
      67       72075 :   return -computeFluxMatrixContribution();
      68             : }
      69             : 
      70             : Real
      71       72075 : LinearFVAnisotropicDiffusion::computeElemRightHandSideContribution()
      72             : {
      73       72075 :   return computeFluxRHSContribution();
      74             : }
      75             : 
      76             : Real
      77       72075 : LinearFVAnisotropicDiffusion::computeNeighborRightHandSideContribution()
      78             : {
      79       72075 :   return -computeFluxRHSContribution();
      80             : }
      81             : 
      82             : Real
      83      144150 : LinearFVAnisotropicDiffusion::computeFluxMatrixContribution()
      84             : {
      85             :   // If we don't have the value yet, we compute it
      86      144150 :   if (!_cached_matrix_contribution)
      87             :   {
      88       72075 :     const auto face_arg = makeCDFace(*_current_face_info);
      89             : 
      90             :     // If we requested nonorthogonal correction, we use the normal component of the
      91             :     // cell to face vector.
      92       72075 :     const auto d = _use_nonorthogonal_correction
      93       72075 :                        ? std::abs(_current_face_info->dCN() * _current_face_info->normal())
      94        7626 :                        : _current_face_info->dCNMag();
      95             : 
      96       72075 :     auto scaled_diff_tensor = _diffusion_tensor(face_arg, determineState());
      97             : 
      98      288300 :     for (const auto i : make_range(Moose::dim))
      99      216225 :       scaled_diff_tensor(i) = _current_face_info->normal()(i) * scaled_diff_tensor(i);
     100             : 
     101       72075 :     auto normal_scaled_diff_tensor = scaled_diff_tensor * _current_face_info->normal();
     102             : 
     103             :     // Cache the matrix contribution
     104       72075 :     _flux_matrix_contribution = normal_scaled_diff_tensor / d * _current_face_area;
     105       72075 :     _cached_matrix_contribution = true;
     106             :   }
     107             : 
     108      144150 :   return _flux_matrix_contribution;
     109             : }
     110             : 
     111             : Real
     112      144150 : LinearFVAnisotropicDiffusion::computeFluxRHSContribution()
     113             : {
     114             :   // Cache the RHS contribution
     115      144150 :   if (!_cached_rhs_contribution)
     116             :   {
     117       72075 :     const auto face_arg = makeCDFace(*_current_face_info);
     118       72075 :     const auto state_arg = determineState();
     119             : 
     120             :     // Get the gradients from the adjacent cells
     121       72075 :     const auto grad_elem = _var.gradSln(*_current_face_info->elemInfo(), state_arg);
     122       72075 :     const auto grad_neighbor = _var.gradSln(*_current_face_info->neighborInfo(), state_arg);
     123             : 
     124             :     // Interpolate the two gradients to the face
     125             :     const auto interp_coeffs =
     126       72075 :         interpCoeffs(Moose::FV::InterpMethod::Average, *_current_face_info, true);
     127             : 
     128             :     const auto interpolated_gradient =
     129       72075 :         (interp_coeffs.first * grad_elem + interp_coeffs.second * grad_neighbor);
     130             : 
     131       72075 :     auto scaled_diff_tensor = _diffusion_tensor(face_arg, state_arg);
     132             : 
     133      288300 :     for (const auto i : make_range(Moose::dim))
     134      216225 :       scaled_diff_tensor(i) = _current_face_info->normal()(i) * scaled_diff_tensor(i);
     135             : 
     136       72075 :     auto normal_scaled_diff_tensor = scaled_diff_tensor * _current_face_info->normal();
     137             : 
     138       72075 :     _flux_rhs_contribution =
     139       72075 :         (scaled_diff_tensor - normal_scaled_diff_tensor * _current_face_info->normal()) *
     140             :         interpolated_gradient;
     141             : 
     142       72075 :     if (_use_nonorthogonal_correction)
     143             :     {
     144             :       // Compute correction vector. Potential optimization: this only depends on the geometry
     145             :       // so we can cache it in FaceInfo at some point.
     146             :       const auto correction_vector =
     147       64449 :           _current_face_info->normal() -
     148       64449 :           1 / (_current_face_info->normal() * _current_face_info->eCN()) *
     149      193347 :               _current_face_info->eCN();
     150             : 
     151       64449 :       _flux_rhs_contribution +=
     152       64449 :           normal_scaled_diff_tensor * interpolated_gradient * correction_vector;
     153             :     }
     154       72075 :     _flux_rhs_contribution *= _current_face_area;
     155       72075 :     _cached_rhs_contribution = true;
     156             :   }
     157             : 
     158      144150 :   return _flux_rhs_contribution;
     159             : }
     160             : 
     161             : Real
     162        7254 : LinearFVAnisotropicDiffusion::computeBoundaryMatrixContribution(
     163             :     const LinearFVBoundaryCondition & bc)
     164             : {
     165        7254 :   const auto * const diff_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
     166             :   mooseAssert(diff_bc, "This should be a valid BC!");
     167             : 
     168        7254 :   auto grad_contrib = diff_bc->computeBoundaryGradientMatrixContribution() * _current_face_area;
     169             :   // If the boundary condition does not include the diffusivity contribution then
     170             :   // add it here.
     171        7254 :   if (!diff_bc->includesMaterialPropertyMultiplier())
     172             :   {
     173        7254 :     const auto face_arg = singleSidedFaceArg(_current_face_info);
     174             : 
     175        7254 :     auto scaled_diff_tensor = _diffusion_tensor(face_arg, determineState());
     176             : 
     177       29016 :     for (const auto i : make_range(Moose::dim))
     178       21762 :       scaled_diff_tensor(i) = _current_face_info->normal()(i) * scaled_diff_tensor(i);
     179             : 
     180        7254 :     auto normal_scaled_diff_tensor = scaled_diff_tensor * _current_face_info->normal();
     181             : 
     182        7254 :     grad_contrib *= normal_scaled_diff_tensor;
     183             :   }
     184             : 
     185        7254 :   return grad_contrib;
     186             : }
     187             : 
     188             : Real
     189        7254 : LinearFVAnisotropicDiffusion::computeBoundaryRHSContribution(const LinearFVBoundaryCondition & bc)
     190             : {
     191        7254 :   const auto * const diff_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
     192             :   mooseAssert(diff_bc, "This should be a valid BC!");
     193             : 
     194        7254 :   const auto face_arg = singleSidedFaceArg(_current_face_info);
     195        7254 :   const auto state_arg = determineState();
     196        7254 :   auto grad_contrib = diff_bc->computeBoundaryGradientRHSContribution();
     197             : 
     198        7254 :   auto scaled_diff_tensor = _diffusion_tensor(face_arg, state_arg);
     199             : 
     200       29016 :   for (const auto i : make_range(Moose::dim))
     201       21762 :     scaled_diff_tensor(i) = _current_face_info->normal()(i) * scaled_diff_tensor(i);
     202             : 
     203        7254 :   auto normal_scaled_diff_tensor = scaled_diff_tensor * _current_face_info->normal();
     204        7254 :   const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
     205        7254 :                              ? _current_face_info->elemInfo()
     206           0 :                              : _current_face_info->neighborInfo();
     207             :   mooseAssert(elem_info, "We should always have an element info for the current face");
     208             : 
     209        7254 :   auto boundary_grad = _var.gradSln(*elem_info, state_arg);
     210             : 
     211             :   // If the boundary condition does not include the diffusivity contribution then
     212             :   // add it here.
     213        7254 :   if (!diff_bc->includesMaterialPropertyMultiplier())
     214        7254 :     grad_contrib *= normal_scaled_diff_tensor;
     215             : 
     216             :   // We allow internal boundaries as well, in that case we have to make sure the normals point in
     217             :   // the right direction
     218        7254 :   const Real boundary_normal_multiplier =
     219        7254 :       (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0;
     220             : 
     221           0 :   grad_contrib += (scaled_diff_tensor - normal_scaled_diff_tensor * boundary_normal_multiplier *
     222        7254 :                                             _current_face_info->normal()) *
     223             :                   boundary_grad;
     224             : 
     225             :   // We add the nonorthogonal corrector for the face here. Potential idea: we could do
     226             :   // this in the boundary condition too. For now, however, we keep it like this.
     227        7254 :   if (diff_bc->useBoundaryGradientExtrapolation() && _use_nonorthogonal_correction_on_boundary)
     228             :   {
     229        6138 :     const auto e_Cf = _current_face_info->faceCentroid() - elem_info->centroid();
     230             :     const auto correction_vector =
     231        6138 :         _current_face_info->normal() - 1 / (_current_face_info->normal() * e_Cf) * e_Cf;
     232             : 
     233        6138 :     grad_contrib +=
     234        6138 :         normal_scaled_diff_tensor * boundary_grad * boundary_normal_multiplier * correction_vector;
     235             :   }
     236             : 
     237        7254 :   return grad_contrib * _current_face_area;
     238             : }

Generated by: LCOV version 1.14