LCOV - code coverage report
Current view: top level - src/fvkernels - INSFVMixingLengthReynoldsStress.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: ba1ead Lines: 63 72 87.5 %
Date: 2025-08-13 06:50:25 Functions: 4 5 80.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 "INSFVMixingLengthReynoldsStress.h"
      11             : #include "INSFVVelocityVariable.h"
      12             : #include "NS.h"
      13             : #include "SystemBase.h"
      14             : 
      15             : registerMooseObject("NavierStokesApp", INSFVMixingLengthReynoldsStress);
      16             : 
      17             : InputParameters
      18       16544 : INSFVMixingLengthReynoldsStress::validParams()
      19             : {
      20       16544 :   InputParameters params = INSFVFluxKernel::validParams();
      21       16544 :   params.addClassDescription(
      22             :       "Computes the force due to the Reynolds stress term in the incompressible"
      23             :       " Reynolds-averaged Navier-Stokes equations.");
      24       33088 :   params.addRequiredParam<MooseFunctorName>("u", "The velocity in the x direction.");
      25       33088 :   params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
      26       33088 :   params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
      27       16544 :   params.addRequiredParam<MooseFunctorName>(NS::density, "fluid density");
      28       33088 :   params.addRequiredParam<MooseFunctorName>("mixing_length", "Turbulent eddy mixing length.");
      29       33088 :   MooseEnum momentum_component("x=0 y=1 z=2");
      30       33088 :   params.addRequiredParam<MooseEnum>(
      31             :       "momentum_component",
      32             :       momentum_component,
      33             :       "The component of the momentum equation that this kernel applies to.");
      34             :   // We assume the worst, e.g. we are doing Rhie-Chow. In that case we need three layers. An 'a'
      35             :   // coefficient evaluation at a face will necessitate evaluation of *this* object at every face of
      36             :   // the adjoining element, necessitating a face gradient evaluation at those faces, necessitating a
      37             :   // cell gradient evaluation in neighboring elements, necessitating cell value evaluations in
      38             :   // neighbors of those neighbor elements
      39       16544 :   params.set<unsigned short>("ghost_layers") = 3;
      40       16544 :   return params;
      41       16544 : }
      42             : 
      43         212 : INSFVMixingLengthReynoldsStress::INSFVMixingLengthReynoldsStress(const InputParameters & params)
      44             :   : INSFVFluxKernel(params),
      45         424 :     _dim(blocksMaxDimension()),
      46         424 :     _axis_index(getParam<MooseEnum>("momentum_component")),
      47         424 :     _u(getFunctor<ADReal>("u")),
      48         636 :     _v(params.isParamValid("v") ? &getFunctor<ADReal>("v") : nullptr),
      49         212 :     _w(params.isParamValid("w") ? &getFunctor<ADReal>("w") : nullptr),
      50         212 :     _rho(getFunctor<ADReal>(NS::density)),
      51         636 :     _mixing_len(getFunctor<ADReal>("mixing_length"))
      52             : {
      53         212 :   if (_dim >= 2 && !_v)
      54           0 :     mooseError(
      55             :         "In two or more dimensions, the v velocity must be supplied using the 'v' parameter");
      56         212 :   if (_dim >= 3 && !_w)
      57           0 :     mooseError("In three dimensions, the w velocity must be supplied using the 'w' parameter");
      58         212 : }
      59             : 
      60             : ADReal
      61     5175768 : INSFVMixingLengthReynoldsStress::computeStrongResidual(const bool populate_a_coeffs)
      62             : {
      63             :   constexpr Real offset = 1e-15; // prevents explosion of sqrt(x) derivative to infinity
      64             : 
      65     5175768 :   const auto face = makeCDFace(*_face_info);
      66     5175768 :   const auto state = determineState();
      67             : 
      68     5175768 :   const auto grad_u = _u.gradient(face, state);
      69             :   // Compute the dot product of the strain rate tensor and the normal vector
      70             :   // aka (grad_v + grad_v^T) * n_hat
      71     5175768 :   ADReal norm_strain_rate = grad_u(_axis_index) * _normal(0);
      72             :   ADRealVectorValue grad_v;
      73             :   ADRealVectorValue grad_w;
      74     5175768 :   if (_dim >= 2)
      75             :   {
      76    10351536 :     grad_v = _v->gradient(face, state);
      77    10351536 :     norm_strain_rate += grad_v(_axis_index) * _normal(1);
      78     5175768 :     if (_dim >= 3)
      79             :     {
      80           0 :       grad_w = _w->gradient(face, state);
      81           0 :       norm_strain_rate += grad_w(_axis_index) * _normal(2);
      82             :     }
      83             :   }
      84     5175768 :   const ADRealVectorValue & var_grad = _index == 0 ? grad_u : (_index == 1 ? grad_v : grad_w);
      85     5175768 :   norm_strain_rate += var_grad * _normal;
      86             : 
      87    10351536 :   ADReal symmetric_strain_tensor_norm = 2.0 * Utility::pow<2>(grad_u(0));
      88     5175768 :   if (_dim >= 2)
      89             :   {
      90             :     symmetric_strain_tensor_norm +=
      91    10351536 :         2.0 * Utility::pow<2>(grad_v(1)) + Utility::pow<2>(grad_v(0) + grad_u(1));
      92     5175768 :     if (_dim >= 3)
      93           0 :       symmetric_strain_tensor_norm += 2.0 * Utility::pow<2>(grad_w(2)) +
      94           0 :                                       Utility::pow<2>(grad_u(2) + grad_w(0)) +
      95           0 :                                       Utility::pow<2>(grad_v(2) + grad_w(1));
      96             :   }
      97             : 
      98     5175768 :   symmetric_strain_tensor_norm = std::sqrt(symmetric_strain_tensor_norm + offset);
      99             : 
     100             :   // Interpolate the mixing length to the face
     101     5175768 :   const ADReal mixing_len = _mixing_len(face, state);
     102             : 
     103             :   // Compute the eddy diffusivity
     104     5175768 :   ADReal eddy_diff = symmetric_strain_tensor_norm * mixing_len * mixing_len;
     105             : 
     106     5175768 :   const ADReal rho = _rho(face, state);
     107             : 
     108     5175768 :   if (populate_a_coeffs)
     109             :   {
     110     5175768 :     if (_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
     111             :         _face_type == FaceInfo::VarFaceNeighbors::BOTH)
     112             :     {
     113     5175768 :       const auto dof_number = _face_info->elem().dof_number(_sys.number(), _var.number(), 0);
     114             :       // norm_strain_rate is a linear combination of degrees of freedom so it's safe to straight-up
     115             :       // index into the derivatives vector at the dof we care about
     116     5175768 :       _ae = norm_strain_rate.derivatives()[dof_number];
     117    10351536 :       _ae *= -rho * eddy_diff;
     118             :     }
     119     5175768 :     if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
     120             :         _face_type == FaceInfo::VarFaceNeighbors::BOTH)
     121             :     {
     122     5016520 :       const auto dof_number = _face_info->neighbor().dof_number(_sys.number(), _var.number(), 0);
     123     5016520 :       _an = norm_strain_rate.derivatives()[dof_number];
     124     5016520 :       _an *= rho * eddy_diff;
     125             :     }
     126             :   }
     127             : 
     128             :   // Return the turbulent stress contribution to the momentum equation
     129    10351536 :   return -1 * rho * eddy_diff * norm_strain_rate;
     130             : }
     131             : 
     132             : ADReal
     133           0 : INSFVMixingLengthReynoldsStress::computeSegregatedContribution()
     134             : {
     135           0 :   return computeStrongResidual(false);
     136             : }
     137             : 
     138             : void
     139     5623128 : INSFVMixingLengthReynoldsStress::gatherRCData(const FaceInfo & fi)
     140             : {
     141     5623128 :   if (skipForBoundary(fi))
     142             :     return;
     143             : 
     144     5175768 :   _face_info = &fi;
     145     5175768 :   _normal = fi.normal();
     146     5175768 :   _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
     147             : 
     148    10351536 :   addResidualAndJacobian(computeStrongResidual(true) * (fi.faceArea() * fi.faceCoord()));
     149             : 
     150     5175768 :   if (_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
     151             :       _face_type == FaceInfo::VarFaceNeighbors::BOTH)
     152    10351536 :     _rc_uo.addToA(&fi.elem(), _index, _ae * (fi.faceArea() * fi.faceCoord()));
     153     5175768 :   if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
     154             :       _face_type == FaceInfo::VarFaceNeighbors::BOTH)
     155    15049560 :     _rc_uo.addToA(fi.neighborPtr(), _index, _an * (fi.faceArea() * fi.faceCoord()));
     156             : }

Generated by: LCOV version 1.14