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 "INSFVTurbulentTemperatureWallFunction.h"
11 : #include "NavierStokesMethods.h"
12 : #include "NS.h"
13 :
14 : registerADMooseObject("NavierStokesApp", INSFVTurbulentTemperatureWallFunction);
15 :
16 : InputParameters
17 366 : INSFVTurbulentTemperatureWallFunction::validParams()
18 : {
19 366 : InputParameters params = FVFluxBC::validParams();
20 :
21 366 : params.addClassDescription("Adds turbulent temperature wall function.");
22 732 : params.addRequiredParam<MooseFunctorName>("T_w", "The wall temperature.");
23 732 : params.addRequiredParam<MooseFunctorName>("u", "The velocity in the x direction.");
24 732 : params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
25 732 : params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
26 366 : params.addRequiredParam<MooseFunctorName>(NS::density, "Density");
27 366 : params.addRequiredParam<MooseFunctorName>(NS::mu, "Dynamic viscosity.");
28 366 : params.addRequiredParam<MooseFunctorName>(NS::cp, "The specific heat at constant pressure.");
29 366 : params.addParam<MooseFunctorName>(NS::kappa, "The thermal conductivity.");
30 732 : params.addParam<MooseFunctorName>("Pr_t", 0.58, "The turbulent Prandtl number.");
31 732 : params.addParam<MooseFunctorName>("k", "Turbulent kinetic energy functor.");
32 732 : params.deprecateParam("k", NS::TKE, "01/01/2025");
33 732 : params.addParam<Real>("C_mu", 0.09, "Coupled turbulent kinetic energy closure.");
34 732 : MooseEnum wall_treatment("eq_newton eq_incremental eq_linearized neq", "neq");
35 732 : params.addParam<MooseEnum>(
36 : "wall_treatment", wall_treatment, "The method used for computing the wall functions");
37 :
38 732 : params.addParam<bool>("newton_solve", false, "Whether a Newton nonlinear solve is being used");
39 732 : params.addParamNamesToGroup("newton_solve", "Advanced");
40 366 : return params;
41 366 : }
42 :
43 198 : INSFVTurbulentTemperatureWallFunction::INSFVTurbulentTemperatureWallFunction(
44 198 : const InputParameters & parameters)
45 : : FVFluxBC(parameters),
46 198 : _dim(_subproblem.mesh().dimension()),
47 396 : _T_w(getFunctor<ADReal>("T_w")),
48 396 : _u_var(getFunctor<ADReal>("u")),
49 594 : _v_var(parameters.isParamValid("v") ? &(getFunctor<ADReal>("v")) : nullptr),
50 198 : _w_var(parameters.isParamValid("w") ? &(getFunctor<ADReal>("w")) : nullptr),
51 198 : _rho(getFunctor<ADReal>(NS::density)),
52 198 : _mu(getFunctor<ADReal>(NS::mu)),
53 198 : _cp(getFunctor<ADReal>(NS::cp)),
54 198 : _kappa(getFunctor<ADReal>(NS::kappa)),
55 396 : _Pr_t(getFunctor<ADReal>("Pr_t")),
56 198 : _k(getFunctor<ADReal>(NS::TKE)),
57 396 : _C_mu(getParam<Real>("C_mu")),
58 396 : _wall_treatment(getParam<MooseEnum>("wall_treatment")),
59 594 : _newton_solve(getParam<bool>("newton_solve"))
60 : {
61 198 : }
62 :
63 : ADReal
64 16984 : INSFVTurbulentTemperatureWallFunction::computeQpResidual()
65 : {
66 : // Useful parameters
67 16984 : const FaceInfo & fi = *_face_info;
68 : // if on an internal face (internal to the mesh, but an external boundary of the flow area),
69 : // we have to select the element on which the flow variables / temperature are defined
70 16984 : const bool use_elem = (_face_type == FaceInfo::VarFaceNeighbors::ELEM);
71 : const Real wall_dist = std::abs(
72 16984 : ((use_elem ? fi.elemCentroid() : fi.neighborCentroid()) - fi.faceCentroid()) * fi.normal());
73 16984 : const Elem * const elem_ptr = use_elem ? fi.elemPtr() : fi.neighborPtr();
74 16984 : const auto elem_arg = makeElemArg(elem_ptr);
75 16984 : const auto state = determineState();
76 : const auto old_state = Moose::StateArg(1, Moose::SolutionIterationType::Nonlinear);
77 16984 : const auto mu = _mu(elem_arg, state);
78 16984 : const auto rho = _rho(elem_arg, state);
79 16984 : const auto cp = _cp(elem_arg, state);
80 16984 : const auto kappa = _kappa(elem_arg, state);
81 :
82 : // Get the velocity vector
83 33968 : ADRealVectorValue velocity(_u_var(elem_arg, state));
84 16984 : if (_v_var)
85 16984 : velocity(1) = (*_v_var)(elem_arg, state);
86 16984 : if (_w_var)
87 0 : velocity(2) = (*_w_var)(elem_arg, state);
88 :
89 : // Compute the velocity and direction of the velocity component that is parallel to the wall
90 : const ADReal parallel_speed =
91 50952 : NS::computeSpeed<ADReal>(velocity - velocity * (fi.normal()) * (fi.normal()));
92 :
93 : // Computing friction velocity and y+
94 : ADReal u_tau, y_plus;
95 :
96 16984 : if (_wall_treatment == "eq_newton")
97 : {
98 : // Full Newton-Raphson solve to find the wall quantities from the law of the wall
99 0 : u_tau = NS::findUStar<ADReal>(mu, rho, parallel_speed, wall_dist);
100 0 : y_plus = wall_dist * u_tau * rho / mu;
101 : }
102 16984 : else if (_wall_treatment == "eq_incremental")
103 : {
104 : // Incremental solve on y_plus to get the near-wall quantities
105 0 : y_plus = NS::findyPlus<ADReal>(mu, rho, std::max(parallel_speed, 1e-10), wall_dist);
106 0 : u_tau = parallel_speed / (std::log(std::max(NS::E_turb_constant * y_plus, 1.0 + 1e-4)) /
107 0 : NS::von_karman_constant);
108 : }
109 16984 : else if (_wall_treatment == "eq_linearized")
110 : {
111 : // Linearized approximation to the wall function to find the near-wall quantities faster
112 16984 : const ADReal a_c = 1 / NS::von_karman_constant;
113 33968 : const ADReal b_c = 1.0 / NS::von_karman_constant *
114 50952 : (std::log(NS::E_turb_constant * std::max(wall_dist, 1.0) / mu) + 1.0);
115 16984 : const ADReal c_c = parallel_speed;
116 :
117 84920 : u_tau = (-b_c + std::sqrt(std::pow(b_c, 2) + 4.0 * a_c * c_c)) / (2.0 * a_c);
118 16984 : y_plus = wall_dist * u_tau * rho / mu;
119 : }
120 0 : else if (_wall_treatment == "neq")
121 : {
122 : // Assign non-equilibrium wall function value
123 0 : y_plus = wall_dist * std::sqrt(std::sqrt(_C_mu) * _k(elem_arg, old_state)) * rho / mu;
124 0 : u_tau = parallel_speed / (std::log(std::max(NS::E_turb_constant * y_plus, 1.0 + 1e-4)) /
125 0 : NS::von_karman_constant);
126 : }
127 :
128 : ADReal alpha;
129 16984 : if (y_plus <= 5.0) // sub-laminar layer
130 : {
131 16723 : alpha = kappa / (rho * cp);
132 : }
133 261 : else if (y_plus >= 30.0) // log-layer
134 : {
135 0 : const auto Pr = cp * mu / kappa;
136 0 : const auto Pr_ratio = Pr / _Pr_t(elem_arg, state);
137 : const auto jayatilleke_P =
138 0 : 9.24 * (std::pow(Pr_ratio, 0.75) - 1.0) * (1.0 + 0.28 * std::exp(-0.007 * Pr_ratio));
139 : const auto wall_scaling =
140 0 : 1.0 / NS::von_karman_constant * std::log(NS::E_turb_constant * y_plus) + jayatilleke_P;
141 0 : alpha = u_tau * wall_dist / (_Pr_t(elem_arg, state) * wall_scaling);
142 : }
143 : else // buffer layer
144 : {
145 261 : const auto alpha_lam = kappa / (rho * cp);
146 261 : const auto Pr = cp * mu / kappa;
147 261 : const auto Pr_t = _Pr_t(elem_arg, state);
148 : const auto Pr_ratio = Pr / Pr_t;
149 : const auto jayatilleke_P =
150 1566 : 9.24 * (std::pow(Pr_ratio, 0.75) - 1.0) * (1.0 + 0.28 * std::exp(-0.007 * Pr_ratio));
151 : const auto wall_scaling =
152 522 : 1.0 / NS::von_karman_constant * std::log(NS::E_turb_constant * y_plus) + jayatilleke_P;
153 261 : const auto alpha_turb = u_tau * wall_dist / (Pr_t * wall_scaling);
154 261 : const auto blending_function = (y_plus - 5.0) / 25.0;
155 522 : alpha = blending_function * alpha_turb + (1.0 - blending_function) * alpha_lam;
156 : }
157 :
158 : // To make sure new derivatives are not introduced as the solve progresses
159 16984 : if (_newton_solve)
160 33672 : alpha += 0 * kappa * (rho * cp) + 0 * u_tau * _Pr_t(elem_arg, state) * y_plus;
161 :
162 16984 : const auto face_arg = singleSidedFaceArg();
163 50952 : return -rho * cp * alpha * (_T_w(face_arg, state) - _var(elem_arg, state)) / wall_dist;
164 : }
|