https://mooseframework.inl.gov
INSFVTKEDSourceSink.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 "INSFVTKEDSourceSink.h"
11 #include "NonlinearSystemBase.h"
12 #include "NavierStokesMethods.h"
13 #include "libmesh/nonlinear_solver.h"
14 
15 registerMooseObject("NavierStokesApp", INSFVTKEDSourceSink);
16 
19 {
21  params.addClassDescription("Elemental kernel to compute the production and destruction "
22  " terms of turbulent kinetic energy dissipation (TKED).");
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::TKE, "Coupled turbulent kinetic energy.");
27  params.addRequiredParam<MooseFunctorName>(NS::density, "fluid density");
28  params.addRequiredParam<MooseFunctorName>(NS::mu, "Dynamic viscosity.");
29  params.addRequiredParam<MooseFunctorName>(NS::mu_t, "Turbulent viscosity.");
30  params.addParam<std::vector<BoundaryName>>(
31  "walls", {}, "Boundaries that correspond to solid walls.");
32  params.addParam<bool>(
33  "linearized_model",
34  true,
35  "Boolean to determine if the problem should be used in a linear or nonlinear solve");
36  MooseEnum wall_treatment("eq_newton eq_incremental eq_linearized neq", "neq");
37  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  params.addParam<Real>("C1_eps", 1.44, "First epsilon coefficient");
42  params.addParam<Real>("C2_eps", 1.92, "Second epsilon coefficient");
43  params.addParam<Real>("C_mu", 0.09, "Coupled turbulent kinetic energy closure.");
44  params.addParam<Real>("C_pl", 10.0, "Production limiter constant multiplier.");
45  params.set<unsigned short>("ghost_layers") = 2;
46  params.addParam<bool>("newton_solve", false, "Whether a Newton nonlinear solve is being used");
47  params.addParamNamesToGroup("newton_solve", "Advanced");
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  _k(getFunctor<ADReal>(NS::TKE)),
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  _C1_eps(getParam<Real>("C1_eps")),
65  _C2_eps(getParam<Real>("C2_eps")),
66  _C_mu(getParam<Real>("C_mu")),
67  _C_pl(getParam<Real>("C_pl")),
68  _newton_solve(getParam<bool>("newton_solve"))
69 {
70  if (_dim >= 2 && !_v_var)
71  paramError("v", "In two or more dimensions, the v velocity must be supplied!");
72 
73  if (_dim >= 3 && !_w_var)
74  paramError("w", "In three or more dimensions, the w velocity must be supplied!");
75 }
76 
77 void
79 {
84 }
85 
86 ADReal
88 {
89  using std::max, std::sqrt, std::pow, std::min;
90 
91  ADReal residual = 0.0;
92  ADReal production = 0.0;
93  ADReal destruction = 0.0;
94  const auto elem_arg = makeElemArg(_current_elem);
95  const auto state = determineState();
96  const auto old_state =
98  const auto mu = _mu(elem_arg, state);
99  const auto rho = _rho(elem_arg, state);
100  const auto TKE_old =
101  _newton_solve ? max(_k(elem_arg, old_state), 1e-10) : _k(elem_arg, old_state);
102  ADReal y_plus;
103 
104  if (_wall_bounded.find(_current_elem) != _wall_bounded.end())
105  {
106  std::vector<ADReal> y_plus_vec;
107 
108  Real tot_weight = 0.0;
109 
110  ADRealVectorValue velocity(_u_var(elem_arg, state));
111  if (_v_var)
112  velocity(1) = (*_v_var)(elem_arg, state);
113  if (_w_var)
114  velocity(2) = (*_w_var)(elem_arg, state);
115 
116  const auto & face_info_vec = libmesh_map_find(_face_infos, _current_elem);
117  const auto & distance_vec = libmesh_map_find(_dist, _current_elem);
118  mooseAssert(distance_vec.size(), "Should have found a distance vector");
119  mooseAssert(distance_vec.size() == face_info_vec.size(),
120  "Should be as many distance vectors as face info vectors");
121 
122  for (unsigned int i = 0; i < distance_vec.size(); i++)
123  {
124  const auto distance = distance_vec[i];
125  mooseAssert(distance > 0, "Should be at a non-zero distance");
126 
127  if (_wall_treatment == NS::WallTreatmentEnum::NEQ) // Non-equilibrium / Non-iterative
128  y_plus = distance * sqrt(sqrt(_C_mu) * TKE_old) * rho / mu;
129  else
130  {
131  // Equilibrium / Iterative
132  const auto parallel_speed = NS::computeSpeed<ADReal>(
133  velocity - velocity * face_info_vec[i]->normal() * face_info_vec[i]->normal());
134 
135  y_plus = NS::findyPlus<ADReal>(mu, rho, max(parallel_speed, 1e-10), distance);
136  }
137 
138  y_plus_vec.push_back(y_plus);
139 
140  tot_weight += 1.0;
141  }
142 
143  for (const auto i : index_range(y_plus_vec))
144  {
145  const auto y_plus = y_plus_vec[i];
146 
147  if (y_plus < 11.25)
148  {
149  const auto fi = face_info_vec[i];
150  const bool defined_on_elem_side = _var.hasFaceSide(*fi, true);
151  const Elem * const loc_elem = defined_on_elem_side ? &fi->elem() : fi->neighborPtr();
152  const Moose::FaceArg facearg = {
153  fi, Moose::FV::LimiterType::CentralDifference, false, false, loc_elem, nullptr};
154  destruction += 2.0 * TKE_old * _mu(facearg, state) / rho /
155  Utility::pow<2>(distance_vec[i]) / tot_weight;
156  }
157  else
158  destruction += pow(_C_mu, 0.75) * pow(TKE_old, 1.5) /
159  (NS::von_karman_constant * distance_vec[i]) / tot_weight;
160  }
161 
162  residual = _var(makeElemArg(_current_elem), state) - destruction;
163  }
164  else
165  {
166  const auto & grad_u = _u_var.gradient(elem_arg, state);
167  const auto Sij_xx = 2.0 * grad_u(0);
168  ADReal Sij_xy = 0.0;
169  ADReal Sij_xz = 0.0;
170  ADReal Sij_yy = 0.0;
171  ADReal Sij_yz = 0.0;
172  ADReal Sij_zz = 0.0;
173 
174  const auto grad_xx = grad_u(0);
175  ADReal grad_xy = 0.0;
176  ADReal grad_xz = 0.0;
177  ADReal grad_yx = 0.0;
178  ADReal grad_yy = 0.0;
179  ADReal grad_yz = 0.0;
180  ADReal grad_zx = 0.0;
181  ADReal grad_zy = 0.0;
182  ADReal grad_zz = 0.0;
183 
184  auto trace = Sij_xx / 3.0;
185 
186  if (_dim >= 2)
187  {
188  const auto & grad_v = (*_v_var).gradient(elem_arg, state);
189  Sij_xy = grad_u(1) + grad_v(0);
190  Sij_yy = 2.0 * grad_v(1);
191 
192  grad_xy = grad_u(1);
193  grad_yx = grad_v(0);
194  grad_yy = grad_v(1);
195 
196  trace += Sij_yy / 3.0;
197 
198  if (_dim >= 3)
199  {
200  const auto & grad_w = (*_w_var).gradient(elem_arg, state);
201 
202  Sij_xz = grad_u(2) + grad_w(0);
203  Sij_yz = grad_v(2) + grad_w(1);
204  Sij_zz = 2.0 * grad_w(2);
205 
206  grad_xz = grad_u(2);
207  grad_yz = grad_v(2);
208  grad_zx = grad_w(0);
209  grad_zy = grad_w(1);
210  grad_zz = grad_w(2);
211 
212  trace += Sij_zz / 3.0;
213  }
214  }
215 
216  const auto symmetric_strain_tensor_sq_norm =
217  (Sij_xx - trace) * grad_xx + Sij_xy * grad_xy + Sij_xz * grad_xz + Sij_xy * grad_yx +
218  (Sij_yy - trace) * grad_yy + Sij_yz * grad_yz + Sij_xz * grad_zx + Sij_yz * grad_zy +
219  (Sij_zz - trace) * grad_zz;
220 
221  ADReal production_k = _mu_t(elem_arg, state) * symmetric_strain_tensor_sq_norm;
222  // Compute production limiter (needed for flows with stagnation zones)
223  const auto eps_old =
224  _newton_solve ? max(_var(elem_arg, old_state), 1e-10) : _var(elem_arg, old_state);
225  const ADReal production_limit = _C_pl * rho * eps_old;
226  // Apply production limiter
227  production_k = min(production_k, production_limit);
228 
229  const auto time_scale = raw_value(TKE_old) / raw_value(eps_old);
230  production = _C1_eps * production_k / time_scale;
231  destruction = _C2_eps * rho * _var(elem_arg, state) / time_scale;
232 
233  residual = destruction - production;
234  }
235 
236  return residual;
237 }
const Moose::Functor< ADReal > * _w_var
z-velocity
static constexpr Real von_karman_constant
Definition: NS.h:201
static const std::string mu_t
Definition: NS.h:125
const std::vector< BoundaryName > & _wall_boundary_names
Wall boundaries.
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static InputParameters validParams()
Moose::StateArg determineState() const
const Moose::Functor< ADReal > & _k
Turbulent kinetic energy.
T & set(const std::string &name, bool quiet_mode=false)
Real trace(const RealTensor &A, const unsigned int &dim)
NS::WallTreatmentEnum _wall_treatment
Method used for wall treatment.
MeshBase & mesh
static const std::string density
Definition: NS.h:33
auto raw_value(const Eigen::Map< T > &in)
static const std::string TKE
Definition: NS.h:176
WallTreatmentEnum
Wall treatment options.
Definition: NS.h:182
const Moose::Functor< ADReal > * _v_var
y-velocity
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...
virtual const std::set< SubdomainID > & blockIDs() const
Computes the source and sink terms for the turbulent kinetic energy dissipation rate.
DualNumber< Real, DNDerivativeType, true > ADReal
ADReal computeQpResidual() override
Real distance(const Point &p)
void addRequiredParam(const std::string &name, const std::string &doc_string)
auto max(const L &left, const R &right)
const Real _C2_eps
Value of the second epsilon closure coefficient.
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
const Real _C1_eps
Value of the first epsilon closure coefficient.
const Moose::Functor< ADReal > & _rho
Density.
std::unordered_set< const Elem * > _wall_bounded
Maps for wall treatment.
registerMooseObject("NavierStokesApp", INSFVTKEDSourceSink)
const Elem *const & _current_elem
static const std::string mu
Definition: NS.h:123
SubProblem & _subproblem
INSFVTKEDSourceSink(const InputParameters &parameters)
static InputParameters validParams()
std::map< const Elem *, std::vector< Real > > _dist
FEProblemBase & _fe_problem
std::map< const Elem *, std::vector< const FaceInfo * > > _face_infos
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...
const bool _newton_solve
Whether a nonlinear Newton-like solver is being used (as opposed to a linearized solver) ...
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
template ADReal computeSpeed< ADReal >(const libMesh::VectorValue< ADReal > &velocity)
const unsigned int _dim
The dimension of the simulation.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
const Real _C_mu
C_mu constant.
template ADReal findyPlus< ADReal >(const ADReal &mu, const ADReal &rho, const ADReal &u, Real dist)
const bool _linearized_model
If the user wants to use the linearized model.
const Moose::Functor< ADReal > & _mu
Dynamic viscosity.
void addClassDescription(const std::string &doc_string)
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-...
const Moose::Functor< ADReal > & _mu_t
Turbulent dynamic viscosity.
static const std::string velocity
Definition: NS.h:45
virtual void initialSetup() override
auto min(const L &left, const R &right)
MooseUnits pow(const MooseUnits &, int)
auto index_range(const T &sizable)
const Moose::Functor< ADReal > & _u_var
x-velocity
MooseVariableFV< Real > & _var
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
virtual bool hasFaceSide(const FaceInfo &fi, const bool fi_elem_side) const override