https://mooseframework.inl.gov
Loading...
Searching...
No Matches
INSFVTKESourceSink.C
Go to the documentation of this file.
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 "INSFVTKESourceSink.h"
11#include "NonlinearSystemBase.h"
12#include "NavierStokesMethods.h"
13#include "libmesh/nonlinear_solver.h"
14
16
19{
21 params.addClassDescription("Elemental kernel to compute the production and destruction "
22 " terms of turbulent kinetic energy (TKE).");
23 params.addRequiredParam<MooseFunctorName>("u", "The velocity in the x direction.");
24 params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
25 params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
26 params.addRequiredParam<MooseFunctorName>(NS::TKED,
27 "Coupled turbulent kinetic energy dissipation rate.");
28 params.addRequiredParam<MooseFunctorName>(NS::density, "fluid density");
29 params.addRequiredParam<MooseFunctorName>(NS::mu, "Dynamic viscosity.");
30 params.addRequiredParam<MooseFunctorName>(NS::mu_t, "Turbulent viscosity.");
31 params.addParam<std::vector<BoundaryName>>(
32 "walls", {}, "Boundaries that correspond to solid walls.");
33 params.addParam<bool>(
34 "linearized_model",
35 true,
36 "Boolean to determine if the problem should be use in a linear or nonlinear solve.");
37 MooseEnum wall_treatment("eq_newton eq_incremental eq_linearized neq", "neq");
38 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 params.addParam<Real>("C_mu", 0.09, "Coupled turbulent kinetic energy closure.");
43 params.addParam<Real>("C_pl", 10.0, "Production Limiter Constant Multiplier.");
44 params.set<unsigned short>("ghost_layers") = 2;
45 params.addParam<bool>("newton_solve", false, "Whether a Newton nonlinear solve is being used");
46 params.addParamNamesToGroup("newton_solve", "Advanced");
47
48 return params;
49}
50
52 : FVElementalKernel(params),
53 _dim(_subproblem.mesh().dimension()),
54 _u_var(getFunctor<ADReal>("u")),
55 _v_var(params.isParamValid("v") ? &(getFunctor<ADReal>("v")) : nullptr),
56 _w_var(params.isParamValid("w") ? &(getFunctor<ADReal>("w")) : nullptr),
57 _epsilon(getFunctor<ADReal>(NS::TKED)),
58 _rho(getFunctor<ADReal>(NS::density)),
59 _mu(getFunctor<ADReal>(NS::mu)),
60 _mu_t(getFunctor<ADReal>(NS::mu_t)),
61 _wall_boundary_names(getParam<std::vector<BoundaryName>>("walls")),
62 _linearized_model(getParam<bool>("linearized_model")),
63 _wall_treatment(getParam<MooseEnum>("wall_treatment").getEnum<NS::WallTreatmentEnum>()),
64 _C_mu(getParam<Real>("C_mu")),
65 _C_pl(getParam<Real>("C_pl")),
66 _newton_solve(getParam<bool>("newton_solve"))
67{
68 if (_dim >= 2 && !_v_var)
69 paramError("v", "In two or more dimensions, the v velocity must be supplied!");
70
71 if (_dim >= 3 && !_w_var)
72 paramError("w", "In three or more dimensions, the w velocity must be supplied!");
73}
74
75void
83
86{
87 using std::max, std::sqrt, std::pow, std::min;
88
89 ADReal residual = 0.0;
90 ADReal production = 0.0;
91 ADReal destruction = 0.0;
92
93 const auto state = determineState();
94 const auto elem_arg = makeElemArg(_current_elem);
95 const auto old_state =
96 _linearized_model ? Moose::StateArg(1, Moose::SolutionIterationType::Nonlinear) : state;
97 const auto rho = _rho(elem_arg, state);
98 const auto mu = _mu(elem_arg, state);
99 // To prevent negative values & preserve sparsity pattern
100 auto TKE = _newton_solve ? max(_var(elem_arg, old_state), ADReal(0) * _var(elem_arg, old_state))
101 : _var(elem_arg, old_state);
102 // Prevent computation of sqrt(0) with undefined automatic derivatives
103 // This is not needed for segregated solves, as TKE has minimum bound in the solver
104 if (_newton_solve)
105 TKE = max(TKE, 1e-10);
106
107 if (_wall_bounded.find(_current_elem) != _wall_bounded.end())
108 {
109 std::vector<ADReal> y_plus_vec, velocity_grad_norm_vec;
110
111 Real tot_weight = 0.0;
112
113 ADRealVectorValue velocity(_u_var(elem_arg, state));
114 if (_v_var)
115 velocity(1) = (*_v_var)(elem_arg, state);
116 if (_w_var)
117 velocity(2) = (*_w_var)(elem_arg, state);
118
119 const auto & face_info_vec = libmesh_map_find(_face_infos, _current_elem);
120 const auto & distance_vec = libmesh_map_find(_dist, _current_elem);
121
122 for (unsigned int i = 0; i < distance_vec.size(); i++)
123 {
124 const auto parallel_speed = NS::computeSpeed<ADReal>(
125 velocity - velocity * face_info_vec[i]->normal() * face_info_vec[i]->normal());
126 const auto distance = distance_vec[i];
127
128 ADReal y_plus;
129 if (_wall_treatment == NS::WallTreatmentEnum::NEQ) // Non-equilibrium / Non-iterative
130 y_plus = distance * sqrt(sqrt(_C_mu) * TKE) * rho / mu;
131 else // Equilibrium / Iterative
132 y_plus = NS::findyPlus<ADReal>(mu, rho, max(parallel_speed, 1e-10), distance);
133
134 y_plus_vec.push_back(y_plus);
135
136 const ADReal velocity_grad_norm = parallel_speed / distance;
137
139 // More complete expansion for velocity gradient. Leave commented for now.
140 // Will be useful later when doing two-phase or compressible flow
141 // ADReal velocity_grad_norm_sq =
142 // Utility::pow<2>(_u_var->gradient(elem_arg, state) *
143 // _normal[_current_elem][i]);
144 // if (_dim >= 2)
145 // velocity_grad_norm_sq +=
146 // Utility::pow<2>(_v_var->gradient(elem_arg, state) *
147 // _normal[_current_elem][i]);
148 // if (_dim >= 3)
149 // velocity_grad_norm_sq +=
150 // Utility::pow<2>(_w_var->gradient(elem_arg, state) *
151 // _normal[_current_elem][i]);
152 // ADReal velocity_grad_norm = sqrt(velocity_grad_norm_sq);
153
154 velocity_grad_norm_vec.push_back(velocity_grad_norm);
155
156 tot_weight += 1.0;
157 }
158
159 for (unsigned int i = 0; i < y_plus_vec.size(); i++)
160 {
161 const auto y_plus = y_plus_vec[i];
162
163 const auto fi = face_info_vec[i];
164 const bool defined_on_elem_side = _var.hasFaceSide(*fi, true);
165 const Elem * const loc_elem = defined_on_elem_side ? &fi->elem() : fi->neighborPtr();
166 const Moose::FaceArg facearg = {
167 fi, Moose::FV::LimiterType::CentralDifference, false, false, loc_elem, nullptr};
168 const ADReal wall_mut = _mu_t(facearg, state);
169 const ADReal wall_mu = _mu(facearg, state);
170
171 const auto destruction_visc = 2.0 * wall_mu / Utility::pow<2>(distance_vec[i]) / tot_weight;
172 const auto destruction_log = pow(_C_mu, 0.75) * rho * pow(TKE, 0.5) /
173 (NS::von_karman_constant * distance_vec[i]) / tot_weight;
174 const auto tau_w = (wall_mut + wall_mu) * velocity_grad_norm_vec[i];
175
176 // Additional 0-value terms to make sure new derivative entries are not added during the solve
177 if (y_plus < 11.25)
178 {
179 destruction += destruction_visc;
180 if (_newton_solve)
181 destruction += 0 * destruction_log + 0 * tau_w;
182 }
183 else
184 {
185 destruction += destruction_log;
186 if (_newton_solve)
187 destruction += 0 * destruction_visc;
188 production += tau_w * pow(_C_mu, 0.25) / sqrt(TKE) /
189 (NS::von_karman_constant * distance_vec[i]) / tot_weight;
190 }
191 }
192
193 residual = (destruction - production) * _var(elem_arg, state);
194 // Additional 0-value term to make sure new derivative entries are not added during the solve
195 if (_newton_solve)
196 residual += 0 * _epsilon(elem_arg, old_state);
197 }
198 else
199 {
200 const auto subdomain_id = _current_elem->subdomain_id();
201 const auto coord_sys = _subproblem.getCoordSystem(subdomain_id);
202 const auto rz_radial_coord =
204 const auto symmetric_strain_tensor_sq_norm = NS::computeShearStrainRateNormSquared<ADReal>(
205 _u_var, _v_var, _w_var, elem_arg, state, coord_sys, rz_radial_coord);
206
207 production = _mu_t(elem_arg, state) * symmetric_strain_tensor_sq_norm;
208
209 const auto tke_old_raw = raw_value(TKE);
210 const auto epsilon_old = _epsilon(elem_arg, old_state);
211
212 if (MooseUtils::absoluteFuzzyEqual(tke_old_raw, 0))
213 destruction = rho * epsilon_old;
214 else
215 destruction = rho * _var(elem_arg, state) / tke_old_raw * raw_value(epsilon_old);
216
217 // k-Production limiter (needed for flows with stagnation zones)
218 const ADReal production_limit =
219 _C_pl * rho * (_newton_solve ? max(epsilon_old, ADReal(0)) : epsilon_old);
220
221 // Apply production limiter
222 production = min(production, production_limit);
223
224 residual = destruction - production;
225
226 // Additional 0-value terms to make sure new derivative entries are not added during the solve
227 if (_newton_solve)
228 residual += 0 * _epsilon(elem_arg, state);
229 }
230
231 return residual;
232}
DualNumber< Real, DNDerivativeType, true > ADReal
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double mu
const double rho
registerMooseObject("NavierStokesApp", INSFVTKESourceSink)
virtual const std::set< SubdomainID > & blockIDs() const
static InputParameters validParams()
MooseVariableFV< Real > & _var
const Elem *const & _current_elem
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
Computes source the sink terms for the turbulent kinetic energy.
const Real _C_mu
C_mu constant.
std::map< const Elem *, std::vector< Real > > _dist
const bool _newton_solve
For Newton solves we want to add extra zero-valued terms regardless of y-plus to avoid sparsity patte...
virtual void initialSetup() override
INSFVTKESourceSink(const InputParameters &parameters)
const bool _linearized_model
Linearized model?
static InputParameters validParams()
const std::vector< BoundaryName > & _wall_boundary_names
Wall boundaries.
std::unordered_set< const Elem * > _wall_bounded
const unsigned int _dim
The dimension of the domain.
const Moose::Functor< ADReal > & _u_var
x-velocity
const Moose::Functor< ADReal > * _w_var
z-velocity
const Moose::Functor< ADReal > & _rho
Density.
std::map< const Elem *, std::vector< const FaceInfo * > > _face_infos
const Moose::Functor< ADReal > & _mu_t
Turbulent dynamic viscosity.
const Moose::Functor< ADReal > & _mu
Dynamic viscosity.
ADReal computeQpResidual() override
NS::WallTreatmentEnum _wall_treatment
Method used for wall treatment.
const Moose::Functor< ADReal > & _epsilon
epsilon - dissipation rate of TKE
const Moose::Functor< ADReal > * _v_var
y-velocity
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void paramError(const std::string &param, Args... args) const
virtual bool hasFaceSide(const FaceInfo &fi, const bool fi_elem_side) const override
SubProblem & _subproblem
FEProblemBase & _fe_problem
unsigned int getAxisymmetricRadialCoord() const
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
Moose::StateArg determineState() const
MeshBase & mesh
void getWallBoundedElements(const std::vector< BoundaryName > &wall_boundary_name, const FEProblemBase &fe_problem, const SubProblem &subproblem, const std::set< SubdomainID > &block_ids, std::unordered_set< const Elem * > &wall_bounded)
Map marking wall bounded elements The map passed in wall_bounded_map gets cleared and re-populated.
void getWallDistance(const std::vector< BoundaryName > &wall_boundary_name, const FEProblemBase &fe_problem, const SubProblem &subproblem, const std::set< SubdomainID > &block_ids, std::map< const Elem *, std::vector< Real > > &dist_map)
Map storing wall ditance for near-wall marked elements The map passed in dist_map gets cleared and re...
template ADReal findyPlus< ADReal >(const ADReal &mu, const ADReal &rho, const ADReal &u, Real dist)
static const std::string density
Definition NS.h:34
static constexpr Real von_karman_constant
Definition NS.h:205
static const std::string TKED
Definition NS.h:181
static const std::string mu_t
Definition NS.h:129
template ADReal computeSpeed< ADReal >(const libMesh::VectorValue< ADReal > &velocity)
static const std::string mu
Definition NS.h:127
template ADReal computeShearStrainRateNormSquared< ADReal >(const Moose::Functor< ADReal > &u, const Moose::Functor< ADReal > *v, const Moose::Functor< ADReal > *w, const Moose::ElemArg &elem_arg, const Moose::StateArg &state, const Moose::CoordinateSystemType coord_sys, const unsigned int rz_radial_coord)
void getElementFaceArgs(const std::vector< BoundaryName > &wall_boundary_name, const FEProblemBase &fe_problem, const SubProblem &subproblem, const std::set< SubdomainID > &block_ids, std::map< const Elem *, std::vector< const FaceInfo * > > &face_info_map)
Map storing face arguments to wall bounded faces The map passed in face_info_map gets cleared and re-...
Real distance(const Point &p)