LCOV - code coverage report
Current view: top level - src/auxkernels - kEpsilonViscosityAux.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: 2bd28b Lines: 83 106 78.3 %
Date: 2025-10-23 22:11:45 Functions: 4 4 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 "kEpsilonViscosityAux.h"
      11             : #include "NavierStokesMethods.h"
      12             : #include "NonlinearSystemBase.h"
      13             : #include "libmesh/nonlinear_solver.h"
      14             : 
      15             : registerMooseObject("NavierStokesApp", kEpsilonViscosityAux);
      16             : 
      17             : InputParameters
      18         925 : kEpsilonViscosityAux::validParams()
      19             : {
      20         925 :   InputParameters params = AuxKernel::validParams();
      21         925 :   params.addClassDescription(
      22             :       "Calculates the turbulent viscosity according to the k-epsilon model.");
      23        1850 :   params.addRequiredParam<MooseFunctorName>("u", "The velocity in the x direction.");
      24        1850 :   params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
      25        1850 :   params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
      26         925 :   params.addRequiredParam<MooseFunctorName>(NS::TKE, "Coupled turbulent kinetic energy.");
      27         925 :   params.addRequiredParam<MooseFunctorName>(NS::TKED,
      28             :                                             "Coupled turbulent kinetic energy dissipation rate.");
      29         925 :   params.addRequiredParam<MooseFunctorName>(NS::density, "Density");
      30         925 :   params.addRequiredParam<MooseFunctorName>(NS::mu, "Dynamic viscosity.");
      31        1850 :   params.addParam<Real>("C_mu", "Coupled turbulent kinetic energy closure.");
      32        1850 :   params.addParam<Real>("mu_t_ratio_max", 1e5, "Maximum allowable mu_t_ratio : mu/mu_t.");
      33        1850 :   params.addParam<std::vector<BoundaryName>>(
      34             :       "walls", {}, "Boundaries that correspond to solid walls.");
      35        1850 :   params.addParam<bool>("bulk_wall_treatment", false, "Activate bulk wall treatment.");
      36        1850 :   MooseEnum wall_treatment("eq_newton eq_incremental eq_linearized neq", "eq_newton");
      37        1850 :   params.addParam<MooseEnum>("wall_treatment",
      38             :                              wall_treatment,
      39             :                              "The method used for computing the wall functions."
      40             :                              "'eq_newton', 'eq_incremental', 'eq_linearized', 'neq'");
      41        1850 :   MooseEnum scale_limiter("none standard", "standard");
      42        1850 :   params.addParam<MooseEnum>("scale_limiter",
      43             :                              scale_limiter,
      44             :                              "The method used to limit the k-epsilon time scale."
      45             :                              "'none', 'standard'");
      46        1850 :   params.addParam<bool>("newton_solve", false, "Whether a Newton nonlinear solve is being used");
      47        1850 :   params.addParamNamesToGroup("newton_solve", "Advanced");
      48             : 
      49         925 :   return params;
      50         925 : }
      51             : 
      52         494 : kEpsilonViscosityAux::kEpsilonViscosityAux(const InputParameters & params)
      53             :   : AuxKernel(params),
      54         494 :     _dim(_subproblem.mesh().dimension()),
      55         988 :     _u_var(getFunctor<Real>("u")),
      56        1482 :     _v_var(params.isParamValid("v") ? &(getFunctor<Real>("v")) : nullptr),
      57         494 :     _w_var(params.isParamValid("w") ? &(getFunctor<Real>("w")) : nullptr),
      58         494 :     _k(getFunctor<Real>(NS::TKE)),
      59         494 :     _epsilon(getFunctor<Real>(NS::TKED)),
      60         494 :     _rho(getFunctor<Real>(NS::density)),
      61         494 :     _mu(getFunctor<Real>(NS::mu)),
      62         988 :     _C_mu(getParam<Real>("C_mu")),
      63         988 :     _mu_t_ratio_max(getParam<Real>("mu_t_ratio_max")),
      64         988 :     _wall_boundary_names(getParam<std::vector<BoundaryName>>("walls")),
      65         988 :     _bulk_wall_treatment(getParam<bool>("bulk_wall_treatment")),
      66         988 :     _wall_treatment(getParam<MooseEnum>("wall_treatment").getEnum<NS::WallTreatmentEnum>()),
      67         988 :     _scale_limiter(getParam<MooseEnum>("scale_limiter")),
      68        1482 :     _newton_solve(getParam<bool>("newton_solve"))
      69             : {
      70         494 : }
      71             : 
      72             : void
      73         494 : kEpsilonViscosityAux::initialSetup()
      74             : {
      75         494 :   if (!_wall_boundary_names.empty())
      76             :   {
      77         900 :     NS::getWallBoundedElements(
      78         450 :         _wall_boundary_names, _c_fe_problem, _subproblem, blockIDs(), _wall_bounded);
      79         450 :     NS::getWallDistance(_wall_boundary_names, _c_fe_problem, _subproblem, blockIDs(), _dist);
      80         900 :     NS::getElementFaceArgs(
      81         450 :         _wall_boundary_names, _c_fe_problem, _subproblem, blockIDs(), _face_infos);
      82             :   }
      83         494 : }
      84             : 
      85             : Real
      86     4442748 : kEpsilonViscosityAux::computeValue()
      87             : {
      88             :   // Convenient Arguments
      89     4442748 :   const Elem & elem = *_current_elem;
      90     4442748 :   const auto elem_arg = makeElemArg(_current_elem);
      91     4442748 :   const Moose::StateArg state = determineState();
      92     4442748 :   const auto rho = _rho(makeElemArg(_current_elem), state);
      93     4442748 :   const auto mu = _mu(makeElemArg(_current_elem), state);
      94     4442748 :   const auto nu = mu / rho;
      95             : 
      96             :   // Determine if the element is wall bounded
      97             :   // and if bulk wall treatment needs to be activated
      98     4442748 :   const bool wall_bounded = _wall_bounded.find(_current_elem) != _wall_bounded.end();
      99             :   Real mu_t;
     100             : 
     101             :   // Computing wall value for near-wall elements if bulk wall treatment is activated
     102             :   // bulk_wall_treatment should only be used for very coarse mesh problems
     103     4442748 :   if (wall_bounded && _bulk_wall_treatment)
     104             :   {
     105             :     // Computing wall value for turbulent dynamic viscosity
     106        3960 :     const auto & elem_distances = _dist[&elem];
     107             :     const auto min_wall_distance_iterator =
     108             :         (std::min_element(elem_distances.begin(), elem_distances.end()));
     109        3960 :     const auto min_wall_dist = *min_wall_distance_iterator;
     110             :     const size_t minIndex = std::distance(elem_distances.begin(), min_wall_distance_iterator);
     111        3960 :     const auto loc_normal = _face_infos[&elem][minIndex]->normal();
     112             : 
     113             :     // Getting y_plus
     114        3960 :     RealVectorValue velocity(_u_var(elem_arg, state));
     115        3960 :     if (_v_var)
     116        3960 :       velocity(1) = (*_v_var)(elem_arg, state);
     117        3960 :     if (_w_var)
     118           0 :       velocity(2) = (*_w_var)(elem_arg, state);
     119             : 
     120             :     // Compute the velocity and direction of the velocity component that is parallel to the wall
     121             :     const auto parallel_speed =
     122        3960 :         NS::computeSpeed<Real>(velocity - velocity * loc_normal * loc_normal);
     123             : 
     124             :     // Switch for determining the near wall quantities
     125             :     // wall_treatment can be: "eq_newton eq_incremental eq_linearized neq"
     126             :     Real y_plus = 0;
     127             :     Real mut_log; // turbulent log-layer viscosity
     128             :     Real mu_wall; // total wall viscosity to obtain the shear stress at the wall
     129             : 
     130        3960 :     if (_wall_treatment == NS::WallTreatmentEnum::EQ_NEWTON)
     131             :     {
     132             :       // Full Newton-Raphson solve to find the wall quantities from the law of the wall
     133        3960 :       const auto u_tau = NS::findUStar<Real>(mu, rho, parallel_speed, min_wall_dist);
     134        3960 :       y_plus = min_wall_dist * u_tau * rho / mu;
     135        3960 :       mu_wall = rho * Utility::pow<2>(u_tau) * min_wall_dist / parallel_speed;
     136        3960 :       mut_log = mu_wall - mu;
     137             :     }
     138           0 :     else if (_wall_treatment == NS::WallTreatmentEnum::EQ_INCREMENTAL)
     139             :     {
     140             :       // Incremental solve on y_plus to get the near-wall quantities
     141           0 :       y_plus = NS::findyPlus<Real>(mu, rho, std::max(parallel_speed, 1e-10), min_wall_dist);
     142           0 :       mu_wall = mu * (NS::von_karman_constant * y_plus /
     143           0 :                       std::log(std::max(NS::E_turb_constant * y_plus, 1 + 1e-4)));
     144           0 :       mut_log = mu_wall - mu;
     145             :     }
     146           0 :     else if (_wall_treatment == NS::WallTreatmentEnum::EQ_LINEARIZED)
     147             :     {
     148             :       // Linearized approximation to the wall function to find the near-wall quantities faster
     149             :       const Real a_c = 1 / NS::von_karman_constant;
     150             :       const Real b_c = 1 / NS::von_karman_constant *
     151           0 :                        (std::log(NS::E_turb_constant * std::max(min_wall_dist, 1.0) / mu) + 1.0);
     152             :       const Real c_c = parallel_speed;
     153             : 
     154           0 :       const auto u_tau = (-b_c + std::sqrt(std::pow(b_c, 2) + 4.0 * a_c * c_c)) / (2.0 * a_c);
     155           0 :       y_plus = min_wall_dist * u_tau * rho / mu;
     156           0 :       mu_wall = rho * Utility::pow<2>(u_tau) * min_wall_dist / parallel_speed;
     157           0 :       mut_log = mu_wall - mu;
     158             :     }
     159           0 :     else if (_wall_treatment == NS::WallTreatmentEnum::NEQ)
     160             :     {
     161             :       // Assign non-equilibrium wall function value
     162           0 :       y_plus = min_wall_dist * std::sqrt(std::sqrt(_C_mu) * _k(elem_arg, state)) * rho / mu;
     163           0 :       mu_wall = mu * (NS::von_karman_constant * y_plus /
     164           0 :                       std::log(std::max(NS::E_turb_constant * y_plus, 1 + 1e-4)));
     165           0 :       mut_log = mu_wall - mu;
     166             :     }
     167             :     else
     168             :       mooseAssert(false, "For `kEpsilonViscosityAux` , wall treatment should not reach here");
     169             : 
     170        3960 :     if (y_plus <= 5.0)
     171             :       // sub-laminar layer
     172        3960 :       mu_t = 0.0;
     173           0 :     else if (y_plus >= 30.0)
     174             :       // log-layer
     175           0 :       mu_t = std::max(mut_log, NS::mu_t_low_limit);
     176             :     else
     177             :     {
     178             :       // buffer layer
     179           0 :       const auto blending_function = (y_plus - 5.0) / 25.0;
     180             :       // the blending depends on the mut_log at y+=30
     181           0 :       const auto mut_log = mu * (NS::von_karman_constant * 30.0 /
     182             :                                      std::log(std::max(NS::E_turb_constant * 30.0, 1 + 1e-4)) -
     183           0 :                                  1.0);
     184           0 :       mu_t = std::max(blending_function * mut_log, NS::mu_t_low_limit);
     185             :     }
     186        3960 :   }
     187             :   else
     188             :   {
     189             :     Real time_scale;
     190     4438788 :     if (_scale_limiter == "standard")
     191             :     {
     192     4425828 :       time_scale = std::max(_k(elem_arg, state) / _epsilon(elem_arg, state),
     193     8851656 :                             std::sqrt(nu / _epsilon(elem_arg, state)));
     194             :     }
     195             :     else
     196             :     {
     197       12960 :       time_scale = _k(elem_arg, state) / _epsilon(elem_arg, state);
     198             :     }
     199             :     // For newton solvers, epsilon might not be bounded
     200     4438788 :     if (_newton_solve)
     201       46309 :       time_scale = _k(elem_arg, state) / std::max(NS::epsilon_low_limit, _epsilon(elem_arg, state));
     202             : 
     203     4438788 :     const Real mu_t_nl = _rho(elem_arg, state) * _C_mu * _k(elem_arg, state) * time_scale;
     204     4438788 :     mu_t = mu_t_nl;
     205     4438788 :     if (_newton_solve)
     206       25940 :       mu_t = std::max(mu_t, NS::mu_t_low_limit);
     207             :   }
     208             :   // Turbulent viscosity limiter
     209     4442748 :   return std::min(mu_t, _mu_t_ratio_max * mu);
     210             : }

Generated by: LCOV version 1.14