Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://www.mooseframework.org
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 "LinearFVTKEDSourceSink.h"
11 : #include "Assembly.h"
12 : #include "SubProblem.h"
13 : #include "NavierStokesMethods.h"
14 :
15 : registerMooseObject("NavierStokesApp", LinearFVTKEDSourceSink);
16 :
17 : InputParameters
18 88 : LinearFVTKEDSourceSink::validParams()
19 : {
20 88 : InputParameters params = LinearFVElementalKernel::validParams();
21 88 : params.addClassDescription("Elemental kernel to compute the production and destruction "
22 : " terms of turbulent kinetic energy dissipation (TKED).");
23 176 : params.addRequiredParam<MooseFunctorName>("u", "The velocity in the x direction.");
24 176 : params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
25 176 : params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
26 88 : params.addRequiredParam<MooseFunctorName>(NS::TKE, "Coupled turbulent kinetic energy.");
27 88 : params.addRequiredParam<MooseFunctorName>(NS::density, "fluid density");
28 88 : params.addRequiredParam<MooseFunctorName>(NS::mu, "Dynamic viscosity.");
29 88 : params.addRequiredParam<MooseFunctorName>(NS::mu_t, "Turbulent viscosity.");
30 :
31 176 : params.addParam<std::vector<BoundaryName>>(
32 : "walls", {}, "Boundaries that correspond to solid walls.");
33 176 : params.addParam<bool>(
34 : "linearized_model",
35 176 : true,
36 : "Boolean to determine if the problem should be used in a linear or nonlinear solve");
37 176 : MooseEnum wall_treatment("eq_newton eq_incremental eq_linearized neq", "neq");
38 176 : params.addParam<MooseEnum>("wall_treatment",
39 : wall_treatment,
40 : "The method used for computing the wall functions "
41 : "'eq_newton', 'eq_incremental', 'eq_linearized', 'neq'");
42 :
43 176 : params.addParam<Real>("C1_eps", 1.44, "First epsilon coefficient");
44 176 : params.addParam<Real>("C2_eps", 1.92, "Second epsilon coefficient");
45 176 : params.addParam<Real>("C_mu", 0.09, "Coupled turbulent kinetic energy closure.");
46 176 : params.addParam<Real>("C_pl", 10.0, "Production limiter constant multiplier.");
47 :
48 88 : return params;
49 88 : }
50 :
51 44 : LinearFVTKEDSourceSink::LinearFVTKEDSourceSink(const InputParameters & params)
52 : : LinearFVElementalKernel(params),
53 44 : _dim(_subproblem.mesh().dimension()),
54 88 : _u_var(getFunctor<Real>("u")),
55 132 : _v_var(params.isParamValid("v") ? &(getFunctor<Real>("v")) : nullptr),
56 44 : _w_var(params.isParamValid("w") ? &(getFunctor<Real>("w")) : nullptr),
57 44 : _k(getFunctor<Real>(NS::TKE)),
58 44 : _rho(getFunctor<Real>(NS::density)),
59 44 : _mu(getFunctor<Real>(NS::mu)),
60 44 : _mu_t(getFunctor<Real>(NS::mu_t)),
61 88 : _wall_boundary_names(getParam<std::vector<BoundaryName>>("walls")),
62 88 : _linearized_model(getParam<bool>("linearized_model")),
63 88 : _wall_treatment(getParam<MooseEnum>("wall_treatment").getEnum<NS::WallTreatmentEnum>()),
64 88 : _C1_eps(getParam<Real>("C1_eps")),
65 88 : _C2_eps(getParam<Real>("C2_eps")),
66 88 : _C_mu(getParam<Real>("C_mu")),
67 132 : _C_pl(getParam<Real>("C_pl"))
68 : {
69 44 : if (_dim >= 2 && !_v_var)
70 0 : paramError("v", "In two or more dimensions, the v velocity must be supplied!");
71 :
72 44 : if (_dim >= 3 && !_w_var)
73 0 : paramError("w", "In three or more dimensions, the w velocity must be supplied!");
74 :
75 : // Strain tensor term requires velocity gradients;
76 44 : if (dynamic_cast<const MooseLinearVariableFV<Real> *>(&_u_var))
77 0 : requestVariableCellGradient(getParam<MooseFunctorName>("u"));
78 44 : if (dynamic_cast<const MooseLinearVariableFV<Real> *>(_v_var))
79 0 : requestVariableCellGradient(getParam<MooseFunctorName>("v"));
80 44 : if (dynamic_cast<const MooseLinearVariableFV<Real> *>(_w_var))
81 0 : requestVariableCellGradient(getParam<MooseFunctorName>("w"));
82 44 : }
83 :
84 : void
85 220 : LinearFVTKEDSourceSink::initialSetup()
86 : {
87 220 : LinearFVElementalKernel::initialSetup();
88 440 : NS::getWallBoundedElements(
89 220 : _wall_boundary_names, _fe_problem, _subproblem, blockIDs(), _wall_bounded);
90 220 : NS::getWallDistance(_wall_boundary_names, _fe_problem, _subproblem, blockIDs(), _dist);
91 220 : NS::getElementFaceArgs(_wall_boundary_names, _fe_problem, _subproblem, blockIDs(), _face_infos);
92 220 : }
93 :
94 : Real
95 548992 : LinearFVTKEDSourceSink::computeMatrixContribution()
96 : {
97 548992 : if (_wall_bounded.find(_current_elem_info->elem()) != _wall_bounded.end())
98 : // TKED value for near wall element will be directly assigned for this cell
99 : return 1.0;
100 : else
101 : {
102 : // Convenient definitions
103 403940 : const auto state = determineState();
104 403940 : const auto elem_arg = makeElemArg(_current_elem_info->elem());
105 403940 : const Real rho = _rho(elem_arg, state);
106 403940 : const Real TKE = _k(elem_arg, state);
107 403940 : const auto epsilon = _var.getElemValue(*_current_elem_info, state);
108 :
109 : // Compute destruction
110 403940 : const auto destruction = _C2_eps * rho * epsilon / TKE;
111 :
112 : // Assign to matrix (term gets multiplied by TKED)
113 403940 : return destruction * _current_elem_volume;
114 : }
115 : }
116 :
117 : Real
118 548992 : LinearFVTKEDSourceSink::computeRightHandSideContribution()
119 : {
120 548992 : if (_wall_bounded.find(_current_elem_info->elem()) != _wall_bounded.end())
121 : {
122 : // Convenient definitions
123 145052 : const auto state = determineState();
124 145052 : const auto elem_arg = makeElemArg(_current_elem_info->elem());
125 145052 : const Real rho = _rho(elem_arg, state);
126 145052 : const Real mu = _mu(elem_arg, state);
127 145052 : const Real TKE = _k(elem_arg, state);
128 :
129 : // Convenient variables
130 : Real destruction = 0.0;
131 : std::vector<Real> y_plus_vec, velocity_grad_norm_vec;
132 : Real tot_weight = 0.0;
133 :
134 : // Get velocity vector
135 145052 : RealVectorValue velocity(_u_var(elem_arg, state));
136 145052 : if (_v_var)
137 145052 : velocity(1) = (*_v_var)(elem_arg, state);
138 145052 : if (_w_var)
139 0 : velocity(2) = (*_w_var)(elem_arg, state);
140 :
141 : // Get near wall faceInfo and distances from cell center to every wall
142 145052 : const auto & face_info_vec = libmesh_map_find(_face_infos, _current_elem_info->elem());
143 145052 : const auto & distance_vec = libmesh_map_find(_dist, _current_elem_info->elem());
144 : mooseAssert(distance_vec.size(), "Should have found a distance vector");
145 : mooseAssert(distance_vec.size() == face_info_vec.size(),
146 : "Should be as many distance vectors as face info vectors");
147 :
148 : // Update y+ and wall face cell
149 291164 : for (unsigned int i = 0; i < distance_vec.size(); i++)
150 : {
151 146112 : const auto distance = distance_vec[i];
152 : mooseAssert(distance > 0, "Should be at a non-zero distance");
153 :
154 : Real y_plus;
155 146112 : if (_wall_treatment == NS::WallTreatmentEnum::NEQ) // Non-equilibrium / Non-iterative
156 50000 : y_plus = distance * std::sqrt(std::sqrt(_C_mu) * TKE) * rho / mu;
157 : else // Equilibrium / Iterative
158 : {
159 96112 : const auto parallel_speed = NS::computeSpeed<Real>(
160 96112 : velocity - velocity * face_info_vec[i]->normal() * face_info_vec[i]->normal());
161 96112 : y_plus = NS::findyPlus<Real>(mu, rho, std::max(parallel_speed, 1e-10), distance);
162 : }
163 :
164 146112 : y_plus_vec.push_back(y_plus);
165 146112 : tot_weight += 1.0;
166 : }
167 :
168 : // Compute near wall epsilon value
169 291164 : for (const auto i : index_range(y_plus_vec))
170 : {
171 146112 : const auto y_plus = y_plus_vec[i];
172 :
173 146112 : if (y_plus < 11.25)
174 32379 : destruction += 2.0 * TKE * mu / rho / Utility::pow<2>(distance_vec[i]) / tot_weight;
175 : else
176 113733 : destruction += std::pow(_C_mu, 0.75) * std::pow(TKE, 1.5) /
177 113733 : (NS::von_karman_constant * distance_vec[i]) / tot_weight;
178 : }
179 :
180 : // Assign the computed value of TKED for element near the wall
181 : return destruction;
182 145052 : }
183 : else
184 : {
185 : // Convenient definitions
186 403940 : const auto state = determineState();
187 403940 : const auto elem_arg = makeElemArg(_current_elem_info->elem());
188 403940 : const Real rho = _rho(elem_arg, state);
189 403940 : const Real TKE = _k(elem_arg, state);
190 403940 : const Real TKED = _var.getElemValue(*_current_elem_info, state);
191 :
192 : // Compute production of TKE
193 : const auto symmetric_strain_tensor_sq_norm =
194 403940 : NS::computeShearStrainRateNormSquared<Real>(_u_var, _v_var, _w_var, elem_arg, state);
195 403940 : Real production = _mu_t(elem_arg, state) * symmetric_strain_tensor_sq_norm;
196 :
197 : // Limit TKE production (needed for flows with stagnation zones)
198 403940 : const Real production_limit = _C_pl * rho * TKED;
199 403940 : production = std::min(production, production_limit);
200 :
201 : // Compute production - recasted with mu_t definition to avoid division by epsilon
202 403940 : const auto production_epsilon = _C1_eps * production * TKED / TKE;
203 :
204 : // Assign to matrix (term gets multiplied by TKED)
205 403940 : return production_epsilon * _current_elem_volume;
206 : }
207 : }
|