https://mooseframework.inl.gov
NavierStokesMethods.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 "NavierStokesMethods.h"
11 #include "MooseError.h"
12 #include "libmesh/vector_value.h"
13 #include "NS.h"
14 
15 namespace NS
16 {
17 int
18 delta(unsigned int i, unsigned int j)
19 {
20  if (i == j)
21  return 1;
22  else
23  return 0;
24 }
25 
26 int
27 computeSign(const Real & a)
28 {
29  return a > 0 ? 1 : (a < 0 ? -1 : 0);
30 }
31 
32 unsigned int
33 getIndex(const Real & p, const std::vector<Real> & bounds)
34 {
35  if (p < bounds.front() || p > bounds.back())
36  mooseError("Point exceeds bounds of domain!");
37 
38  for (unsigned int i = 1; i < bounds.size(); ++i)
39  if (p <= bounds[i])
40  return i - 1;
41 
42  return bounds.size() - 2;
43 }
44 
45 Real
47  const Real & Re, const Real & rho, const Real & mu, const Real & drho, const Real & dmu)
48 {
49  return Re * (drho / std::max(rho, 1e-6) - dmu / std::max(mu, 1e-8));
50 }
51 
52 Real
54  const Real & cp,
55  const Real & k,
56  const Real & dmu,
57  const Real & dcp,
58  const Real & dk)
59 {
60  return (k * (mu * dcp + cp * dmu) - mu * cp * dk) / std::max(k * k, 1e-8);
61 }
62 
63 ADReal
64 findUStar(const ADReal & mu, const ADReal & rho, const ADReal & u, const Real dist)
65 {
66  // usually takes about 3-4 iterations
67  constexpr int MAX_ITERS{50};
68  constexpr Real REL_TOLERANCE{1e-6};
69 
70  // Check inputs
71  mooseAssert(mu > 0, "Need a strictly positive viscosity");
72  mooseAssert(rho > 0, "Need a strictly positive density");
73  mooseAssert(u > 0, "Need a strictly positive velocity");
74  mooseAssert(dist > 0, "Need a strictly positive wall distance");
75 
76  const ADReal nu = mu / rho;
77 
78  // Wall-function linearized guess
79  const Real a_c = 1 / NS::von_karman_constant;
80  const ADReal b_c =
81  1.0 / NS::von_karman_constant * (std::log(NS::E_turb_constant * dist / mu) + 1.0);
82  const ADReal & c_c = u;
83 
85  ADReal u_star =
86  std::max(1e-20, (-b_c + std::sqrt(std::pow(b_c, 2) + 4.0 * a_c * c_c)) / (2.0 * a_c));
87 
88  // Newton-Raphson method to solve for u_star (friction velocity).
89  for (int i = 0; i < MAX_ITERS; ++i)
90  {
91  ADReal residual =
92  u_star / NS::von_karman_constant * std::log(NS::E_turb_constant * u_star * dist / nu) - u;
93  ADReal deriv =
94  (1.0 + std::log(NS::E_turb_constant * u_star * dist / nu)) / NS::von_karman_constant;
95  ADReal new_u_star = std::max(1e-20, u_star - residual / deriv);
96 
97  Real rel_err = std::abs((new_u_star.value() - u_star.value()) / new_u_star.value());
98 
99  u_star = new_u_star;
100  if (rel_err < REL_TOLERANCE)
101  return u_star;
102  }
103 
104  mooseException("Could not find the wall friction velocity (mu: ",
105  mu,
106  " rho: ",
107  rho,
108  " velocity: ",
109  u,
110  " wall distance: ",
111  dist,
112  ")");
113 }
114 
115 ADReal
116 findyPlus(const ADReal & mu, const ADReal & rho, const ADReal & u, const Real dist)
117 {
118  // Fixed point iteration method to find y_plus
119  // It should take 3 or 4 iterations
120  constexpr int MAX_ITERS{10};
121  constexpr Real REL_TOLERANCE{1e-2};
122 
123  // Check inputs
124  mooseAssert(mu > 0, "Need a strictly positive viscosity");
125  mooseAssert(u > 0, "Need a strictly positive velocity");
126  mooseAssert(rho > 0, "Need a strictly positive density");
127  mooseAssert(dist > 0, "Need a strictly positive wall distance");
128 
129  Real yPlusLast = 0.0;
130  ADReal yPlus = dist * u * rho / mu; // Assign initial value to laminar
131  const Real rev_yPlusLam = 1.0 / yPlus.value();
132  const ADReal kappa_time_Re = NS::von_karman_constant * u * dist / (mu / rho);
133  unsigned int iters = 0;
134 
135  do
136  {
137  yPlusLast = yPlus.value();
138  // Negative y plus does not make sense
139  yPlus = std::max(NS::min_y_plus, yPlus);
140  yPlus = (kappa_time_Re + yPlus) / (1.0 + std::log(NS::E_turb_constant * yPlus));
141  } while (std::abs(rev_yPlusLam * (yPlus.value() - yPlusLast)) > REL_TOLERANCE &&
142  ++iters < MAX_ITERS);
143 
144  return std::max(NS::min_y_plus, yPlus);
145 }
146 
147 ADReal
149 {
150  // if the velocity is zero, then the norm function call fails because AD tries to calculate the
151  // derivatives which causes a divide by zero - because d/dx(sqrt(f(x))) = 1/2/sqrt(f(x))*df/dx.
152  // So add a bit of noise (based on hitchhiker's guide to the galaxy's meaning of life number) to
153  // avoid this failure mode.
154  return isZero(velocity) ? 1e-42 : velocity.norm();
155 }
156 
158 void
159 getWallBoundedElements(const std::vector<BoundaryName> & wall_boundary_names,
160  const FEProblemBase & fe_problem,
161  const SubProblem & subproblem,
162  const std::set<SubdomainID> & block_ids,
163  std::map<const Elem *, bool> & wall_bounded_map)
164 {
165 
166  wall_bounded_map.clear();
167  const auto wall_boundary_ids = subproblem.mesh().getBoundaryIDs(wall_boundary_names);
168 
169  for (const auto & elem : fe_problem.mesh().getMesh().active_element_ptr_range())
170  {
171  if (block_ids.find(elem->subdomain_id()) != block_ids.end())
172  for (const auto i_side : elem->side_index_range())
173  {
174  const auto & side_bnds = subproblem.mesh().getBoundaryIDs(elem, i_side);
175  for (const auto & wall_id : wall_boundary_ids)
176  {
177  for (const auto side_id : side_bnds)
178  if (side_id == wall_id)
179  wall_bounded_map[elem] = true;
180  }
181  }
182  }
183 }
184 
186 void
187 getWallDistance(const std::vector<BoundaryName> & wall_boundary_name,
188  const FEProblemBase & fe_problem,
189  const SubProblem & subproblem,
190  const std::set<SubdomainID> & block_ids,
191  std::map<const Elem *, std::vector<Real>> & dist_map)
192 {
193 
194  dist_map.clear();
195 
196  for (const auto & elem : fe_problem.mesh().getMesh().active_element_ptr_range())
197  if (block_ids.find(elem->subdomain_id()) != block_ids.end())
198  for (const auto i_side : elem->side_index_range())
199  {
200  const auto & side_bnds = subproblem.mesh().getBoundaryIDs(elem, i_side);
201  for (const auto & name : wall_boundary_name)
202  {
203  const auto wall_id = subproblem.mesh().getBoundaryID(name);
204  for (const auto side_id : side_bnds)
205  if (side_id == wall_id)
206  {
207  const FaceInfo * const fi = subproblem.mesh().faceInfo(elem, i_side);
208  const Real dist = std::abs((fi->elemCentroid() - fi->faceCentroid()) * fi->normal());
209  dist_map[elem].push_back(dist);
210  }
211  }
212  }
213 }
214 
216 void
217 getElementFaceArgs(const std::vector<BoundaryName> & wall_boundary_name,
218  const FEProblemBase & fe_problem,
219  const SubProblem & subproblem,
220  const std::set<SubdomainID> & block_ids,
221  std::map<const Elem *, std::vector<const FaceInfo *>> & face_info_map)
222 {
223 
224  face_info_map.clear();
225 
226  for (const auto & elem : fe_problem.mesh().getMesh().active_element_ptr_range())
227  if (block_ids.find(elem->subdomain_id()) != block_ids.end())
228  for (const auto i_side : elem->side_index_range())
229  {
230  const auto & side_bnds = subproblem.mesh().getBoundaryIDs(elem, i_side);
231  for (const auto & name : wall_boundary_name)
232  {
233  const auto wall_id = subproblem.mesh().getBoundaryID(name);
234  for (const auto side_id : side_bnds)
235  if (side_id == wall_id)
236  {
237  const FaceInfo * fi = subproblem.mesh().faceInfo(elem, i_side);
238  face_info_map[elem].push_back(fi);
239  }
240  }
241  }
242 }
243 }
virtual MooseMesh & mesh()=0
int computeSign(const Real &a)
Sign function, returns $+1$ if $a$ is positive and $-1$ if $a$ is negative.
static constexpr Real von_karman_constant
Definition: NS.h:191
static constexpr Real min_y_plus
Definition: NS.h:198
void mooseError(Args &&... args)
Real prandtlPropertyDerivative(const Real &mu, const Real &cp, const Real &k, const Real &dmu, const Real &dcp, const Real &dk)
Computes the derivative of the Prandtl number, $Pr{ C_p}{k}$, with respect to an arbitrary variale $$...
bool isZero(const T &value, const Real tolerance=TOLERANCE *TOLERANCE *TOLERANCE)
void getWallBoundedElements(const std::vector< BoundaryName > &wall_boundary_name, const FEProblemBase &fe_problem, const SubProblem &subproblem, const std::set< SubdomainID > &block_ids, std::map< const Elem *, bool > &wall_bounded_map)
Map marking wall bounded elements The map passed in wall_bounded_map gets cleared and re-populated...
const boundary_id_type side_id
const Point & faceCentroid() const
int delta(unsigned int i, unsigned int j)
Delta function, which returns zero if $i j$ and unity if $i=j$.
DualNumber< Real, DNDerivativeType, true > ADReal
static const std::string cp
Definition: NS.h:121
const std::vector< const FaceInfo *> & faceInfo() const
const Point & elemCentroid() const
MeshBase & getMesh()
Real deriv(unsigned n, unsigned alpha, unsigned beta, Real x)
static const std::string mu
Definition: NS.h:123
const std::string name
Definition: Setup.h:20
ADReal findyPlus(const ADReal &mu, const ADReal &rho, const ADReal &u, Real dist)
Finds the non-dimensional wall distance normalized with the friction velocity Implements a fixed-poin...
Real reynoldsPropertyDerivative(const Real &Re, const Real &rho, const Real &mu, const Real &drho, const Real &dmu)
Computes the derivative of the Reynolds number, $Re { Vd}{}$, with respect to an arbitrary variable $...
const Point & normal() const
unsigned int getIndex(const Real &p, const std::vector< Real > &bounds)
Determines the index $i$ in a sorted array such that the input point is within the $i$-th and $i+1$-t...
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...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static constexpr Real E_turb_constant
Definition: NS.h:192
virtual MooseMesh & mesh() override
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-...
static const std::string velocity
Definition: NS.h:45
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
ADReal findUStar(const ADReal &mu, const ADReal &rho, const ADReal &u, Real dist)
Finds the friction velocity using standard velocity wall functions formulation.
std::vector< BoundaryID > getBoundaryIDs(const Elem *const elem, const unsigned short int side) const
ADReal computeSpeed(const ADRealVectorValue &velocity)
Compute the speed (velocity norm) given the supplied velocity.
MooseUnits pow(const MooseUnits &, int)
static const std::string k
Definition: NS.h:130
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const