https://mooseframework.inl.gov
LinearWCNSFVMomentumFlux.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 
11 #include "MooseLinearVariableFV.h"
12 #include "NSFVUtils.h"
13 #include "NS.h"
14 #include "RhieChowMassFlux.h"
17 
19 
22 {
24  params.addClassDescription("Represents the matrix and right hand side contributions of the "
25  "stress and advection terms of the momentum equation.");
26  params.addRequiredParam<SolverVariableName>("u", "The velocity in the x direction.");
27  params.addParam<SolverVariableName>("v", "The velocity in the y direction.");
28  params.addParam<SolverVariableName>("w", "The velocity in the z direction.");
29  params.addRequiredParam<UserObjectName>(
30  "rhie_chow_user_object",
31  "The rhie-chow user-object which is used to determine the face velocity.");
32  params.addRequiredParam<MooseFunctorName>(NS::mu, "The diffusion coefficient.");
33  MooseEnum momentum_component("x=0 y=1 z=2");
35  "momentum_component",
36  momentum_component,
37  "The component of the momentum equation that this kernel applies to.");
38  params.addParam<bool>(
39  "use_nonorthogonal_correction",
40  true,
41  "If the nonorthogonal correction should be used when computing the normal gradient.");
42  params.addParam<bool>(
43  "use_deviatoric_terms", false, "If deviatoric terms in the stress terms need to be used.");
44 
46  return params;
47 }
48 
50  : LinearFVFluxKernel(params),
51  _dim(_subproblem.mesh().dimension()),
52  _mass_flux_provider(getUserObject<RhieChowMassFlux>("rhie_chow_user_object")),
53  _mu(getFunctor<Real>(getParam<MooseFunctorName>(NS::mu))),
54  _use_nonorthogonal_correction(getParam<bool>("use_nonorthogonal_correction")),
55  _use_deviatoric_terms(getParam<bool>("use_deviatoric_terms")),
56  _advected_interp_coeffs(std::make_pair<Real, Real>(0, 0)),
57  _face_mass_flux(0.0),
58  _boundary_normal_factor(1.0),
59  _stress_matrix_contribution(0.0),
60  _stress_rhs_contribution(0.0),
61  _index(getParam<MooseEnum>("momentum_component")),
62  _velocity_vars{nullptr, nullptr, nullptr},
63  _coord_type(getBlockCoordSystem()),
64  _rz_radial_coord(_fe_problem.mesh().getAxisymmetricRadialCoord())
65 {
66  // We only need gradients if the nonorthogonal correction is enabled or when we request the
67  // computation of the deviatoric parts of the stress tensor.
68  if (_use_nonorthogonal_correction || _use_deviatoric_terms)
69  _var.computeCellGradients();
70 
71  Moose::FV::setInterpolationMethod(*this, _advected_interp_method, "advected_interp_method");
72 
73  auto get_velocity_var = [&](const std::string & param_name)
74  {
75  return dynamic_cast<const MooseLinearVariableFVReal *>(
76  &_fe_problem.getVariable(_tid, getParam<SolverVariableName>(param_name)));
77  };
78 
79  _velocity_vars[0] = get_velocity_var("u");
80  if (!_velocity_vars[0])
81  paramError("u", "the u velocity must be a MooseLinearVariableFVReal.");
82 
83  if (_dim >= 2)
84  {
85  if (!params.isParamValid("v"))
86  paramError("v", "In two or more dimensions, the v velocity must be supplied.");
87  _velocity_vars[1] = get_velocity_var("v");
88  if (!_velocity_vars[1])
89  paramError("v",
90  "In two or more dimensions, the v velocity must be supplied and it must be a "
91  "MooseLinearVariableFVReal.");
92  }
93 
94  if (_dim >= 3)
95  {
96  if (!params.isParamValid("w"))
97  paramError("w", "In three-dimensions, the w velocity must be supplied.");
98  _velocity_vars[2] = get_velocity_var("w");
99  if (!_velocity_vars[2])
100  paramError("w",
101  "In three-dimensions, the w velocity must be supplied and it must be a "
102  "MooseLinearVariableFVReal.");
103  }
104 }
105 
106 Real
108 {
112 }
113 
114 Real
116 {
120 }
121 
122 Real
124 {
126 }
127 
128 Real
130 {
132 }
133 
134 Real
136 {
137  const auto * const adv_diff_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
138 
139  mooseAssert(adv_diff_bc, "This should be a valid BC!");
140  return (computeStressBoundaryMatrixContribution(adv_diff_bc) +
143 }
144 
145 Real
147 {
148  const auto * const adv_diff_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
149  mooseAssert(adv_diff_bc, "This should be a valid BC!");
150  return (computeStressBoundaryRHSContribution(adv_diff_bc) +
153 }
154 
155 Real
157 {
159 }
160 
161 Real
163 {
165 }
166 
167 Real
169 {
170  // If we don't have the value yet, we compute it
172  {
173  const auto face_arg = makeCDFace(*_current_face_info);
174 
175  // If we requested nonorthogonal correction, we use the normal component of the
176  // cell to face vector.
177  const auto d = _use_nonorthogonal_correction
178  ? std::abs(_current_face_info->dCN() * _current_face_info->normal())
180 
181  // Cache the matrix contribution
184  }
185 
187 }
188 
189 Real
191 {
192  // We can have contributions to the right hand side in two occasions:
193  // (1) when we use nonorthogonal correction for the normal gradients
194  // (2) when we request the deviatoric parts of the stress tensor. (needed for space-dependent
195  // viscosities for example)
197  {
198  // scenario (1), we need to add the nonorthogonal correction. In 1D, we don't have
199  // any correction so we just skip this part
201  {
202  const auto face_arg = makeCDFace(*_current_face_info);
203  const auto state_arg = determineState();
204 
205  // Get the gradients from the adjacent cells
206  const auto grad_elem = _var.gradSln(*_current_face_info->elemInfo(), state_arg);
207  const auto & grad_neighbor = _var.gradSln(*_current_face_info->neighborInfo(), state_arg);
208 
209  // Interpolate the two gradients to the face
210  const auto interp_coeffs =
212 
213  const auto correction_vector =
217 
218  // Cache the matrix contribution
220  _mu(face_arg, state_arg) *
221  (interp_coeffs.first * grad_elem + interp_coeffs.second * grad_neighbor) *
222  correction_vector;
223  }
224  // scenario (2), we will have to account for the deviatoric parts of the stress tensor.
226  {
227  const auto state_arg = determineState();
228 
229  // Interpolate the two gradients to the face
230  const auto interp_coeffs =
232 
233  RealGradient grad_elem[3];
234  RealGradient grad_neighbor[3];
235  Real trace_elem = 0;
236  Real trace_neighbor = 0;
237  RealVectorValue deviatoric_vector_elem;
238  RealVectorValue deviatoric_vector_neighbor;
239 
240  // Loop over every velocity component so we can form the symmetric gradient pieces
241  for (const auto dir : make_range(_dim))
242  {
243  grad_elem[dir] = velocityVar(dir).gradSln(*_current_face_info->elemInfo(), state_arg);
244  grad_neighbor[dir] =
245  velocityVar(dir).gradSln(*_current_face_info->neighborInfo(), state_arg);
246  trace_elem += grad_elem[dir](dir);
247  trace_neighbor += grad_neighbor[dir](dir);
248  }
249 
250  const auto face_arg = makeCDFace(*_current_face_info);
251 
252  if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
253  {
254  Real elem_value = 0.0;
255  Real neighbor_value = 0.0;
256  const auto & radial_var = velocityVar(_rz_radial_coord);
257  elem_value = radial_var.getElemValue(*_current_face_info->elemInfo(), state_arg) /
259  neighbor_value = radial_var.getElemValue(*_current_face_info->neighborInfo(), state_arg) /
261 
262  trace_elem += elem_value;
263  trace_neighbor += neighbor_value;
264  }
265 
266  // Assemble the explicit transpose/trace contribution component by component
267  for (const auto dir : make_range(_dim))
268  {
269  grad_elem[dir](dir) -= 2. / 3 * trace_elem;
270  grad_neighbor[dir](dir) -= 2. / 3 * trace_neighbor;
271 
272  deviatoric_vector_elem(dir) = grad_elem[dir](_index);
273  deviatoric_vector_neighbor(dir) = grad_neighbor[dir](_index);
274  }
275 
276  _stress_rhs_contribution += _mu(face_arg, state_arg) *
277  (interp_coeffs.first * deviatoric_vector_elem +
278  interp_coeffs.second * deviatoric_vector_neighbor) *
280  }
282  }
283 
285 }
286 
287 Real
289  const LinearFVAdvectionDiffusionBC * bc)
290 {
291  auto grad_contrib = bc->computeBoundaryGradientMatrixContribution();
292  // If the boundary condition does not include the diffusivity contribution then
293  // add it here.
295  {
296  const auto face_arg = singleSidedFaceArg(_current_face_info);
297  grad_contrib *= _mu(face_arg, determineState());
298  }
299 
300  return grad_contrib;
301 }
302 
303 Real
305  const LinearFVAdvectionDiffusionBC * bc)
306 {
307  const auto face_arg = singleSidedFaceArg(_current_face_info);
308  auto grad_contrib = bc->computeBoundaryGradientRHSContribution();
309  // If the boundary condition does not include the diffusivity contribution then
310  // add it here.
312  grad_contrib *= _mu(face_arg, determineState());
313 
314  // We add the nonorthogonal corrector for the face here. Potential idea: we could do
315  // this in the boundary condition too. For now, however, we keep it like this.
317  {
318  // We support internal boundaries as well. In that case we have to decide on which side
319  // of the boundary we are on.
320  const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
323 
324  // Unit vector to the boundary. Unfortunately, we have to recompute it because the value
325  // stored in the face info is only correct for external boundaries
326  const auto e_Cf = _current_face_info->faceCentroid() - elem_info->centroid();
327  const auto correction_vector =
328  _current_face_info->normal() - 1 / (_current_face_info->normal() * e_Cf) * e_Cf;
329 
330  const auto state_arg = determineState();
331  grad_contrib += _mu(face_arg, state_arg) * _var.gradSln(*elem_info, state_arg) *
332  _boundary_normal_factor * correction_vector;
333  }
334 
336  {
337  // We might be on a face which is an internal boundary so we want to make sure we
338  // get the gradient from the right side.
339  const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
342 
343  const auto state_arg = determineState();
344 
345  RealGradient grad_elem[3];
346  Real trace_elem = 0;
347  RealVectorValue deviatoric_vector_elem;
348 
349  for (const auto dir : make_range(_dim))
350  {
351  grad_elem[dir] = velocityVar(dir).gradSln(*elem_info, state_arg);
352  trace_elem += grad_elem[dir](dir);
353  }
354 
355  if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
356  {
357  const auto & radial_var = velocityVar(_rz_radial_coord);
358  const Real elem_value =
359  radial_var.getElemValue(*elem_info, state_arg) / elem_info->centroid()(_rz_radial_coord);
360  trace_elem += elem_value;
361  }
362 
363  for (const auto dir : make_range(_dim))
364  {
365  grad_elem[dir](dir) -= 2. / 3 * trace_elem;
366  deviatoric_vector_elem(dir) = grad_elem[dir](_index);
367  }
368 
369  // We support internal boundaries too so we have to make sure the normal points always outward
370  grad_contrib += _mu(face_arg, state_arg) * deviatoric_vector_elem * _boundary_normal_factor *
372  }
373 
374  return grad_contrib;
375 }
376 
377 Real
379  const LinearFVAdvectionDiffusionBC * bc)
380 {
381  const auto boundary_value_matrix_contrib = bc->computeBoundaryValueMatrixContribution();
382  return boundary_value_matrix_contrib * _face_mass_flux;
383 }
384 
385 Real
387  const LinearFVAdvectionDiffusionBC * bc)
388 {
389  const auto boundary_value_rhs_contrib = bc->computeBoundaryValueRHSContribution();
390  return -boundary_value_rhs_contrib * _face_mass_flux;
391 }
392 
393 void
395 {
397 
398  // Multiplier that ensures the normal of the boundary always points outwards, even in cases
399  // when the boundary is within the mesh.
401 
402  // Caching the mass flux on the face which will be reused in the advection term's matrix and
403  // right hand side contributions
405 
406  // Caching the interpolation coefficients so they will be reused for the matrix and right hand
407  // side terms
410 
411  // We'll have to set this to zero to make sure that we don't accumulate values over multiple
412  // faces. The matrix contribution should be fine.
414 }
415 
418 {
419  mooseAssert(dir < _velocity_vars.size() && _velocity_vars[dir],
420  "Velocity variable for requested direction is not available.");
421  return *_velocity_vars[dir];
422 }
virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition &bc) override
Real computeInternalAdvectionNeighborMatrixContribution()
Computes the matrix contribution of the advective flux on the neighbor side of current face when the ...
const unsigned int _index
Index x|y|z, this is mainly to handle the deviatoric parts correctly in in the stress term...
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
virtual Real computeBoundaryGradientRHSContribution() const=0
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
Real computeInternalAdvectionElemMatrixContribution()
Computes the matrix contribution of the advective flux on the element side of current face when the f...
virtual Real computeNeighborRightHandSideContribution() override
std::pair< Real, Real > interpCoeffs(const InterpMethod m, const FaceInfo &fi, const bool one_is_elem, const T &face_flux=0.0)
Real getMassFlux(const FaceInfo &fi) const
Get the face velocity times density (used in advection terms)
Real computeStressBoundaryRHSContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the right hand side contributions of the boundary conditions resulting from the stress tenso...
Moose::FaceArg singleSidedFaceArg(const FaceInfo *fi, Moose::FV::LimiterType limiter_type=Moose::FV::LimiterType::CentralDifference, bool correct_skewness=false) const
Moose::StateArg determineState() const
const ElemInfo * neighborInfo() const
const Point & faceCentroid() const
Real computeInternalStressMatrixContribution()
Computes the matrix contribution of the stress term on the current face when the face is an internal ...
MooseLinearVariableFV< Real > & _var
MeshBase & mesh
virtual void setupFaceData(const FaceInfo *face_info)
virtual Real computeBoundaryGradientMatrixContribution() const=0
const bool _use_nonorthogonal_correction
Switch to enable/disable nonorthogonal correction in the stress term.
const ElemInfo * elemInfo() const
const RhieChowMassFlux & _mass_flux_provider
The Rhie-Chow user object that provides us with the face velocity.
registerMooseObject("NavierStokesApp", LinearWCNSFVMomentumFlux)
std::array< const MooseLinearVariableFVReal *, 3 > _velocity_vars
Velocity variables for each coordinate direction.
const unsigned int _rz_radial_coord
Axisymmetric radial coordinate index (only used when in RZ)
const Moose::CoordinateSystemType _coord_type
Coordinate system of the blocks this kernel operates on.
FaceInfo::VarFaceNeighbors _current_face_type
void addRequiredParam(const std::string &name, const std::string &doc_string)
Real _boundary_normal_factor
Multiplier that ensures the normal of the boundary always points outwards, even in cases when the bou...
const Moose::Functor< Real > & _mu
The functor for the dynamic viscosity.
VectorValue< Real > gradSln(const ElemInfo &elem_info, const StateArg &state) const
virtual bool useBoundaryGradientExtrapolation() const
static InputParameters validParams()
const MooseLinearVariableFVReal & velocityVar(unsigned int dir) const
Helper to access the velocity variable for a given direction.
const Point & centroid() const
static InputParameters validParams()
const FaceInfo * _current_face_info
InputParameters advectedInterpolationParameter()
virtual void setupFaceData(const FaceInfo *face_info) override
Set the current FaceInfo object.
Real computeAdvectionBoundaryMatrixContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the matrix contributions of the boundary conditions resulting from the advection term...
static const std::string mu
Definition: NS.h:127
Kernel that implements the stress tensor and advection terms for the momentum equation.
std::pair< Real, Real > _advected_interp_coeffs
Container for the current advected interpolation coefficients on the face to make sure we don&#39;t compu...
Real computeAdvectionBoundaryRHSContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the right hand side contributions of the boundary conditions resulting from the advection te...
Real _stress_rhs_contribution
The cached right hand side contribution.
const Point & normal() const
virtual Real computeElemRightHandSideContribution() override
virtual bool includesMaterialPropertyMultiplier() const
const unsigned int _dim
The dimension of the mesh.
Real dCNMag() const
Real _stress_matrix_contribution
The cached matrix contribution.
Real computeStressBoundaryMatrixContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the matrix contributions of the boundary conditions resulting from the stress tensor...
virtual Real computeBoundaryValueMatrixContribution() const=0
virtual Real computeNeighborMatrixContribution() override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Point & eCN() const
Real _face_mass_flux
Container for the mass flux on the face which will be reused in the advection term&#39;s matrix and right...
virtual Real computeElemMatrixContribution() override
IntRange< T > make_range(T beg, T end)
virtual Real computeBoundaryValueRHSContribution() const=0
Moose::FV::InterpMethod _advected_interp_method
The interpolation method to use for the advected quantity.
void addClassDescription(const std::string &doc_string)
bool _cached_matrix_contribution
LinearWCNSFVMomentumFlux(const InputParameters &params)
Class constructor.
Moose::FaceArg makeCDFace(const FaceInfo &fi, const bool correct_skewness=false) const
Real computeInternalStressRHSContribution()
Computes the right hand side contribution of the stress term on the current face when the face is an ...
const double mu
bool setInterpolationMethod(const MooseObject &obj, Moose::FV::InterpMethod &interp_method, const std::string &param_name)
const Point & dCN() const
const bool _use_deviatoric_terms
Switch to enable/disable deviatoric parts in the stress term.
virtual Real computeBoundaryRHSContribution(const LinearFVBoundaryCondition &bc) override