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 "NS.h"
13 #include "RhieChowMassFlux.h"
16 
18 
21 {
23  params.addClassDescription("Represents the matrix and right hand side contributions of the "
24  "stress and advection terms of the momentum equation.");
25  params.addRequiredParam<SolverVariableName>("u", "The velocity in the x direction.");
26  params.addParam<SolverVariableName>("v", "The velocity in the y direction.");
27  params.addParam<SolverVariableName>("w", "The velocity in the z direction.");
28  params.addRequiredParam<UserObjectName>(
29  "rhie_chow_user_object",
30  "The rhie-chow user-object which is used to determine the face velocity.");
31  params.addRequiredParam<MooseFunctorName>(NS::mu, "The diffusion coefficient.");
32  MooseEnum momentum_component("x=0 y=1 z=2");
34  "momentum_component",
35  momentum_component,
36  "The component of the momentum equation that this kernel applies to.");
37  params.addParam<bool>(
38  "use_nonorthogonal_correction",
39  true,
40  "If the nonorthogonal correction should be used when computing the normal gradient.");
41  params.addParam<bool>(
42  "use_deviatoric_terms", false, "If deviatoric terms in the stress terms need to be used.");
43 
44  params.addRequiredParam<InterpolationMethodName>(
45  "advected_interp_method_name",
46  "Name of the FVInterpolationMethod to use for the advected velocity.");
47  return params;
48 }
49 
51  : LinearFVFluxKernel(params),
53  _dim(_subproblem.mesh().dimension()),
54  _mass_flux_provider(getUserObject<RhieChowMassFlux>("rhie_chow_user_object")),
55  _mu(getFunctor<Real>(getParam<MooseFunctorName>(NS::mu))),
56  _use_nonorthogonal_correction(getParam<bool>("use_nonorthogonal_correction")),
57  _use_deviatoric_terms(getParam<bool>("use_deviatoric_terms")),
58  _adv_interp_method(getFVAdvectedInterpolationMethod(
59  getParam<InterpolationMethodName>("advected_interp_method_name"))),
60  _face_mass_flux(0.0),
61  _boundary_normal_factor(1.0),
62  _stress_matrix_contribution(0.0),
63  _stress_rhs_contribution(0.0),
64  _index(getParam<MooseEnum>("momentum_component")),
65  _velocity_vars{nullptr, nullptr, nullptr},
66  _coord_type(getBlockCoordSystem()),
67  _rz_radial_coord(_fe_problem.mesh().getAxisymmetricRadialCoord())
68 {
69  // We only need gradients if the nonorthogonal correction is enabled or when we request the
70  // computation of the deviatoric parts of the stress tensor.
71  if (_use_nonorthogonal_correction || _use_deviatoric_terms)
72  _var.computeCellGradients();
73 
74  if (_adv_interp_method.needsGradients())
75  _var.computeCellGradients(_adv_interp_method.gradientLimiter());
76 
77  auto get_velocity_var = [&](const std::string & param_name)
78  {
79  return dynamic_cast<const MooseLinearVariableFVReal *>(
80  &_fe_problem.getVariable(_tid, getParam<SolverVariableName>(param_name)));
81  };
82 
83  _velocity_vars[0] = get_velocity_var("u");
84  if (!_velocity_vars[0])
85  paramError("u", "the u velocity must be a MooseLinearVariableFVReal.");
86 
87  if (_dim >= 2)
88  {
89  if (!params.isParamValid("v"))
90  paramError("v", "In two or more dimensions, the v velocity must be supplied.");
91  _velocity_vars[1] = get_velocity_var("v");
92  if (!_velocity_vars[1])
93  paramError("v",
94  "In two or more dimensions, the v velocity must be supplied and it must be a "
95  "MooseLinearVariableFVReal.");
96  }
97 
98  if (_dim >= 3)
99  {
100  if (!params.isParamValid("w"))
101  paramError("w", "In three-dimensions, the w velocity must be supplied.");
102  _velocity_vars[2] = get_velocity_var("w");
103  if (!_velocity_vars[2])
104  paramError("w",
105  "In three-dimensions, the w velocity must be supplied and it must be a "
106  "MooseLinearVariableFVReal.");
107  }
108 }
109 
110 Real
112 {
116 }
117 
118 Real
120 {
124 }
125 
126 Real
128 {
132 }
133 
134 Real
136 {
140 }
141 
142 Real
144 {
145  const auto * const adv_diff_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
146 
147  mooseAssert(adv_diff_bc, "This should be a valid BC!");
148  return (computeStressBoundaryMatrixContribution(adv_diff_bc) +
151 }
152 
153 Real
155 {
156  const auto * const adv_diff_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
157  mooseAssert(adv_diff_bc, "This should be a valid BC!");
158  return (computeStressBoundaryRHSContribution(adv_diff_bc) +
161 }
162 
163 Real
165 {
167 }
168 
169 Real
171 {
173 }
174 
175 Real
177 {
178  // If we don't have the value yet, we compute it
180  {
181  const auto face_arg = makeCDFace(*_current_face_info);
182 
183  // If we requested nonorthogonal correction, we use the normal component of the
184  // cell to face vector.
185  const auto d = _use_nonorthogonal_correction
186  ? std::abs(_current_face_info->dCN() * _current_face_info->normal())
188 
189  // Cache the matrix contribution
192  }
193 
195 }
196 
197 Real
199 {
200  // We can have contributions to the right hand side in two occasions:
201  // (1) when we use nonorthogonal correction for the normal gradients
202  // (2) when we request the deviatoric parts of the stress tensor. (needed for space-dependent
203  // viscosities for example)
205  {
206  // scenario (1), we need to add the nonorthogonal correction. In 1D, we don't have
207  // any correction so we just skip this part
209  {
210  const auto face_arg = makeCDFace(*_current_face_info);
211  const auto state_arg = determineState();
212 
213  // Get the gradients from the adjacent cells
214  const auto grad_elem = _var.gradSln(*_current_face_info->elemInfo(), state_arg);
215  const auto & grad_neighbor = _var.gradSln(*_current_face_info->neighborInfo(), state_arg);
216 
217  // Interpolate the two gradients to the face
218  const auto interp_coeffs =
220 
221  const auto correction_vector =
225 
226  // Cache the matrix contribution
228  _mu(face_arg, state_arg) *
229  (interp_coeffs.first * grad_elem + interp_coeffs.second * grad_neighbor) *
230  correction_vector;
231  }
232  // scenario (2), we will have to account for the deviatoric parts of the stress tensor.
234  {
235  const auto state_arg = determineState();
236 
237  // Interpolate the two gradients to the face
238  const auto interp_coeffs =
240 
241  RealGradient grad_elem[3];
242  RealGradient grad_neighbor[3];
243  Real trace_elem = 0;
244  Real trace_neighbor = 0;
245  RealVectorValue deviatoric_vector_elem;
246  RealVectorValue deviatoric_vector_neighbor;
247 
248  // Loop over every velocity component so we can form the symmetric gradient pieces
249  for (const auto dir : make_range(_dim))
250  {
251  grad_elem[dir] = velocityVar(dir).gradSln(*_current_face_info->elemInfo(), state_arg);
252  grad_neighbor[dir] =
253  velocityVar(dir).gradSln(*_current_face_info->neighborInfo(), state_arg);
254  trace_elem += grad_elem[dir](dir);
255  trace_neighbor += grad_neighbor[dir](dir);
256  }
257 
258  const auto face_arg = makeCDFace(*_current_face_info);
259 
260  if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
261  {
262  Real elem_value = 0.0;
263  Real neighbor_value = 0.0;
264  const auto & radial_var = velocityVar(_rz_radial_coord);
265  elem_value = radial_var.getElemValue(*_current_face_info->elemInfo(), state_arg) /
267  neighbor_value = radial_var.getElemValue(*_current_face_info->neighborInfo(), state_arg) /
269 
270  trace_elem += elem_value;
271  trace_neighbor += neighbor_value;
272  }
273 
274  // Assemble the explicit transpose/trace contribution component by component
275  for (const auto dir : make_range(_dim))
276  {
277  grad_elem[dir](dir) -= 2. / 3 * trace_elem;
278  grad_neighbor[dir](dir) -= 2. / 3 * trace_neighbor;
279 
280  deviatoric_vector_elem(dir) = grad_elem[dir](_index);
281  deviatoric_vector_neighbor(dir) = grad_neighbor[dir](_index);
282  }
283 
284  _stress_rhs_contribution += _mu(face_arg, state_arg) *
285  (interp_coeffs.first * deviatoric_vector_elem +
286  interp_coeffs.second * deviatoric_vector_neighbor) *
288  }
290  }
291 
293 }
294 
295 Real
297  const LinearFVAdvectionDiffusionBC * bc)
298 {
299  auto grad_contrib = bc->computeBoundaryGradientMatrixContribution();
300  // If the boundary condition does not include the diffusivity contribution then
301  // add it here.
303  {
304  const auto face_arg = singleSidedFaceArg(_current_face_info);
305  grad_contrib *= _mu(face_arg, determineState());
306  }
307 
308  return grad_contrib;
309 }
310 
311 Real
313  const LinearFVAdvectionDiffusionBC * bc)
314 {
315  const auto face_arg = singleSidedFaceArg(_current_face_info);
316  auto grad_contrib = bc->computeBoundaryGradientRHSContribution();
317  // If the boundary condition does not include the diffusivity contribution then
318  // add it here.
320  grad_contrib *= _mu(face_arg, determineState());
321 
322  // We add the nonorthogonal corrector for the face here. Potential idea: we could do
323  // this in the boundary condition too. For now, however, we keep it like this.
325  {
326  // We support internal boundaries as well. In that case we have to decide on which side
327  // of the boundary we are on.
328  const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
331 
332  // Unit vector to the boundary. Unfortunately, we have to recompute it because the value
333  // stored in the face info is only correct for external boundaries
334  const auto e_Cf = _current_face_info->faceCentroid() - elem_info->centroid();
335  const auto correction_vector =
336  _current_face_info->normal() - 1 / (_current_face_info->normal() * e_Cf) * e_Cf;
337 
338  const auto state_arg = determineState();
339  grad_contrib += _mu(face_arg, state_arg) * _var.gradSln(*elem_info, state_arg) *
340  _boundary_normal_factor * correction_vector;
341  }
342 
344  {
345  // We might be on a face which is an internal boundary so we want to make sure we
346  // get the gradient from the right side.
347  const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
350 
351  const auto state_arg = determineState();
352 
353  RealGradient grad_elem[3];
354  Real trace_elem = 0;
355  RealVectorValue deviatoric_vector_elem;
356 
357  for (const auto dir : make_range(_dim))
358  {
359  grad_elem[dir] = velocityVar(dir).gradSln(*elem_info, state_arg);
360  trace_elem += grad_elem[dir](dir);
361  }
362 
363  if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
364  {
365  const auto & radial_var = velocityVar(_rz_radial_coord);
366  const Real elem_value =
367  radial_var.getElemValue(*elem_info, state_arg) / elem_info->centroid()(_rz_radial_coord);
368  trace_elem += elem_value;
369  }
370 
371  for (const auto dir : make_range(_dim))
372  {
373  grad_elem[dir](dir) -= 2. / 3 * trace_elem;
374  deviatoric_vector_elem(dir) = grad_elem[dir](_index);
375  }
376 
377  // We support internal boundaries too so we have to make sure the normal points always outward
378  grad_contrib += _mu(face_arg, state_arg) * deviatoric_vector_elem * _boundary_normal_factor *
380  }
381 
382  return grad_contrib;
383 }
384 
385 Real
387  const LinearFVAdvectionDiffusionBC * bc)
388 {
389  const auto boundary_value_matrix_contrib = bc->computeBoundaryValueMatrixContribution();
390  return boundary_value_matrix_contrib * _face_mass_flux;
391 }
392 
393 Real
395  const LinearFVAdvectionDiffusionBC * bc)
396 {
397  const auto boundary_value_rhs_contrib = bc->computeBoundaryValueRHSContribution();
398  return -boundary_value_rhs_contrib * _face_mass_flux;
399 }
400 
401 void
403 {
405 
406  // Multiplier that ensures the normal of the boundary always points outwards, even in cases
407  // when the boundary is within the mesh.
409 
410  // Caching the mass flux on the face which will be reused in the advection term's matrix and
411  // right hand side contributions
413 
415  {
416  const auto state = determineState();
417  const auto & elem_info = *_current_face_info->elemInfo();
418  const auto & neighbor_info = *_current_face_info->neighborInfo();
419 
420  const Real elem_value = _var.getElemValue(elem_info, state);
421  const Real neighbor_value = _var.getElemValue(neighbor_info, state);
422 
424  {
425  const auto limiter_type = _adv_interp_method.gradientLimiter();
426  _elem_grad_storage = _var.gradSln(elem_info, state, limiter_type);
427  _neighbor_grad_storage = _var.gradSln(neighbor_info, state, limiter_type);
428  }
429 
431  elem_value,
432  neighbor_value,
436  }
437 
438  // We'll have to set this to zero to make sure that we don't accumulate values over multiple
439  // faces. The matrix contribution should be fine.
441 }
442 
445 {
446  mooseAssert(dir < _velocity_vars.size() && _velocity_vars[dir],
447  "Velocity variable for requested direction is not available.");
448  return *_velocity_vars[dir];
449 }
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.
virtual Moose::FV::GradientLimiterType gradientLimiter() const
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 FVAdvectedInterpolationMethod & _adv_interp_method
The interpolation method to use for the advected quantity.
const Moose::CoordinateSystemType _coord_type
Coordinate system of the blocks this kernel operates on.
FaceInfo::VarFaceNeighbors _current_face_type
VectorValue< Real > _neighbor_grad_storage
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
FVAdvectedInterpolationMethod::AdvectedSystemContribution _adv_interp_result
Current advected interpolation contribution on the face.
static InputParameters validParams()
const FaceInfo * _current_face_info
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...
virtual AdvectedSystemContribution advectedInterpolate(const FaceInfo &face, Real elem_value, Real neighbor_value, const VectorValue< Real > *elem_grad, const VectorValue< Real > *neighbor_grad, Real mass_flux) const=0
static const std::string mu
Definition: NS.h:127
Kernel that implements the stress tensor and advection terms for the momentum equation.
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
virtual bool needsGradients() const
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
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
IntRange< T > make_range(T beg, T end)
virtual Real computeBoundaryValueRHSContribution() const=0
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 ...
VectorValue< Real > _elem_grad_storage
Reusable gradient storage used when advected interpolation requires gradients.
const double mu
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