https://mooseframework.inl.gov
INSFVMomentumDiffusion.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 "INSFVMomentumDiffusion.h"
12 #include "NS.h"
13 #include "NavierStokesMethods.h"
14 #include "SystemBase.h"
15 #include "NonlinearSystemBase.h"
16 #include "RelationshipManager.h"
17 #include "Factory.h"
18 #include "libmesh/nonlinear_solver.h"
19 
21 
24 {
25  auto params = INSFVFluxKernel::validParams();
27  params.addRequiredParam<MooseFunctorName>(NS::mu, "The viscosity");
28  params.addClassDescription(
29  "Implements the Laplace form of the viscous stress in the Navier-Stokes equation.");
30 
31  MooseEnum coeff_interp_method("average harmonic", "harmonic");
32  params.addParam<MooseEnum>("mu_interp_method",
33  coeff_interp_method,
34  "Switch that can select face interpolation method for the viscosity.");
35  params.set<unsigned short>("ghost_layers") = 2;
36 
37  // We add the relationship manager here, this will select the right number of
38  // ghosting layers depending on the chosen interpolation method
39  params.addRelationshipManager(
40  "ElementSideNeighborLayers",
43  [](const InputParameters & obj_params, InputParameters & rm_params)
44  { FVRelationshipManagerInterface::setRMParamsDiffusion(obj_params, rm_params, 3); });
45 
46  params.addParam<bool>(
47  "complete_expansion",
48  false,
49  "Boolean parameter to use complete momentum expansion is the diffusion term.");
50  params.addParam<MooseFunctorName>("u", "The velocity in the x direction.");
51  params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
52  params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
53  params.addParam<bool>(
54  "limit_interpolation", false, "Flag to limit interpolation to positive values.");
55  params.addParam<bool>("newton_solve", false, "Whether a Newton nonlinear solve is being used");
56  params.addParamNamesToGroup("newton_solve", "Advanced");
57  return params;
58 }
59 
61  : INSFVFluxKernel(params),
64  _mu(getFunctor<ADReal>(NS::mu)),
65  _mu_interp_method(
66  Moose::FV::selectInterpolationMethod(getParam<MooseEnum>("mu_interp_method"))),
67  _u_var(params.isParamValid("u") ? &getFunctor<ADReal>("u") : nullptr),
68  _v_var(params.isParamValid("v") ? &getFunctor<ADReal>("v") : nullptr),
69  _w_var(params.isParamValid("w") ? &getFunctor<ADReal>("w") : nullptr),
70  _complete_expansion(getParam<bool>("complete_expansion")),
71  _limit_interpolation(getParam<bool>("limit_interpolation")),
72  _dim(_subproblem.mesh().dimension()),
73  _newton_solve(getParam<bool>("newton_solve"))
74 {
76  paramError("u", "The u velocity must be defined when 'complete_expansion=true'.");
77 
78  if (_complete_expansion && _dim >= 2 && !_v_var)
79  paramError("v",
80  "The v velocity must be defined when 'complete_expansion=true'"
81  "and problem dimension is larger or equal to 2.");
82 
83  if (_complete_expansion && _dim >= 3 && !_w_var)
84  paramError("w",
85  "The w velocity must be defined when 'complete_expansion=true'"
86  "and problem dimension is larger or equal to three.");
87 }
88 
89 ADReal
90 INSFVMomentumDiffusion::computeStrongResidual(const bool populate_a_coeffs)
91 {
92  const Moose::StateArg state = determineState();
93  const auto dudn = gradUDotNormal(state, _correct_skewness);
94  ADReal face_mu;
95 
96  if (onBoundary(*_face_info))
97  face_mu = _mu(makeCDFace(*_face_info), state);
98  else
100  face_mu,
101  _mu(elemArg(), state),
102  _mu(neighborArg(), state),
103  *_face_info,
104  true);
105 
106  // Protecting from negative viscosity at interpolation
107  // to preserve convergence
108  if (face_mu < 0.0)
109  {
110  if (!(_limit_interpolation))
111  {
112  mooseDoOnce(mooseWarning(
113  "Negative face viscosity has been encountered. Value ",
114  raw_value(face_mu),
115  " at ",
117  " limiting it to 0!\nFurther warnings for this issue will be silenced, but the "
118  "occurrences will be recorded through the solution invalidity interface."));
119  flagInvalidSolution("Negative face dynamic viscosity has been encountered.");
120  }
121  // Keep face_mu here for sparsity pattern detection
122  face_mu = 0 * face_mu;
123  }
124 
125  if (populate_a_coeffs)
126  {
129  {
130  const auto dof_number = _face_info->elem().dof_number(_sys.number(), _var.number(), 0);
131  // A gradient is a linear combination of degrees of freedom so it's safe to straight-up index
132  // into the derivatives vector at the dof we care about
133  _ae = dudn.derivatives()[dof_number];
134  _ae *= -face_mu;
135  }
138  {
139  const auto dof_number = _face_info->neighbor().dof_number(_sys.number(), _var.number(), 0);
140  _an = dudn.derivatives()[dof_number];
141  _an *= face_mu;
142  }
143  }
144 
145  ADReal dudn_transpose = 0.0;
147  {
148  // Computing the gradient from coupled variables
149  // Normally, we can do this with `_var.gradient(face, state)` but we will need the transpose
150  // gradient. So, we compute all at once
151  Moose::FaceArg face;
152  if (onBoundary(*_face_info))
153  face = singleSidedFaceArg();
154  else
156 
158  if (_dim == 1)
159  {
160  const auto & grad_u = _u_var->gradient(face, state);
161  gradient = ADRealTensorValue(grad_u, ADRealVectorValue(0, 0, 0), ADRealVectorValue(0, 0, 0));
162  }
163  else if (_dim == 2)
164  {
165  const auto & grad_u = _u_var->gradient(face, state);
166  const auto & grad_v = _v_var->gradient(face, state);
167  gradient = ADRealTensorValue(grad_u, grad_v, ADRealVectorValue(0, 0, 0));
168  }
169  else // if (_dim == 3)
170  {
171  const auto & grad_u = _u_var->gradient(face, state);
172  const auto & grad_v = _v_var->gradient(face, state);
173  const auto & grad_w = _w_var->gradient(face, state);
174  gradient = ADRealTensorValue(grad_u, grad_v, grad_w);
175  }
176 
177  // Getting transpose of the gradient matrix
178  const auto gradient_transpose = gradient.transpose();
179 
180  dudn_transpose += gradient_transpose.row(_index) * _face_info->normal();
181  }
182 
183  return -face_mu * (dudn + dudn_transpose);
184 }
185 
186 void
188 {
189  if (skipForBoundary(fi))
190  return;
191 
192  _face_info = &fi;
193  _normal = fi.normal();
194  _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
195 
197 
200  _rc_uo.addToA(&fi.elem(), _index, _ae * (fi.faceArea() * fi.faceCoord()));
203  _rc_uo.addToA(fi.neighborPtr(), _index, _an * (fi.faceArea() * fi.faceCoord()));
204 }
205 
206 ADReal
208 {
209  return computeStrongResidual(false);
210 }
ADReal _ae
The a coefficient for the element.
virtual ADReal gradUDotNormal(const Moose::StateArg &time, const bool correct_skewness) const
ADReal _an
The a coefficient for the neighbor.
const unsigned int _dim
dimension
A flux kernel that momentum residual objects that add non-advection flux terms, or more specifically ...
const bool _limit_interpolation
Boolean parameter to limit interpolation.
Moose::ElemArg elemArg(bool correct_skewness=false) const
unsigned int number() const
const Elem & elem() const
const Moose::Functor< ADReal > *const _v_var
y-velocity
const FaceInfo * _face_info
Moose::StateArg determineState() const
const Point & faceCentroid() const
virtual ADReal computeStrongResidual(const bool populate_a_coeffs)
Routine to compute this object&#39;s strong residual (e.g.
virtual ADReal computeSegregatedContribution() override
Compute the contribution which goes into the residual of the segregated system.
const unsigned int _index
index x|y|z
MeshBase & mesh
auto raw_value(const Eigen::Map< T > &in)
Real & faceCoord()
RealVectorValue _normal
DualNumber< Real, DNDerivativeType, true > ADReal
const Moose::FV::InterpMethod _mu_interp_method
The face interpolation method for the viscosity.
Real faceArea() const
void mooseWarning(Args &&... args) const
registerMooseObject("NavierStokesApp", INSFVMomentumDiffusion)
RhieChowInterpolatorBase & _rc_uo
The Rhie Chow user object that is responsible for generating face velocities for advection terms...
SystemBase & _sys
virtual bool skipForBoundary(const FaceInfo &fi) const
bool onBoundary(const FaceInfo &fi) const
const Elem * neighborPtr() const
static const std::string mu
Definition: NS.h:123
static InputParameters validParams()
const Moose::Functor< ADReal > & _mu
The dynamic viscosity.
const Elem & neighbor() const
const Point & normal() const
void paramError(const std::string &param, Args... args) const
unsigned int number() const
const Moose::Functor< ADReal > *const _u_var
x-velocity
FaceInfo::VarFaceNeighbors _face_type
void addResidualAndJacobian(const ADReal &residual)
Process into either the system residual or Jacobian.
virtual void addToA(const libMesh::Elem *elem, unsigned int component, const ADReal &value)=0
API for momentum residual objects that have on-diagonals for velocity call.
Moose::ElemArg neighborArg(bool correct_skewness=false) const
static InputParameters validParams()
virtual const OutputTools< Real >::VariableGradient & gradient()
static InputParameters validParams()
void gatherRCData(const FaceInfo &fi) override final
Should be a non-empty implementation if the residual object is a FVFluxKernel and introduces residual...
Moose::FaceArg singleSidedFaceArg(const FaceInfo *fi=nullptr, Moose::FV::LimiterType limiter_type=Moose::FV::LimiterType::CentralDifference, bool correct_skewness=false, const Moose::StateArg *state_limiter=nullptr) const
InterpMethod selectInterpolationMethod(const std::string &interp_method)
MooseVariableFV< Real > & _var
const Moose::Functor< ADReal > *const _w_var
z-velocity
static void setRMParamsDiffusion(const InputParameters &obj_params, InputParameters &rm_params, const unsigned short conditional_extended_layers)
Moose::FaceArg makeCDFace(const FaceInfo &fi, const bool correct_skewness=false) const
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
INSFVMomentumDiffusion(const InputParameters &params)
const bool _complete_expansion
Boolean parameter to include the complete momentum expansion.
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const