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),
63  _mu(getFunctor<ADReal>(NS::mu)),
64  _mu_interp_method(
65  Moose::FV::selectInterpolationMethod(getParam<MooseEnum>("mu_interp_method"))),
66  _u_var(params.isParamValid("u") ? &getFunctor<ADReal>("u") : nullptr),
67  _v_var(params.isParamValid("v") ? &getFunctor<ADReal>("v") : nullptr),
68  _w_var(params.isParamValid("w") ? &getFunctor<ADReal>("w") : nullptr),
69  _complete_expansion(getParam<bool>("complete_expansion")),
70  _limit_interpolation(getParam<bool>("limit_interpolation")),
71  _dim(_subproblem.mesh().dimension()),
72  _newton_solve(getParam<bool>("newton_solve"))
73 {
75  paramError("u", "The u velocity must be defined when 'complete_expansion=true'.");
76 
77  if (_complete_expansion && _dim >= 2 && !_v_var)
78  paramError("v",
79  "The v velocity must be defined when 'complete_expansion=true'"
80  "and problem dimension is larger or equal to 2.");
81 
82  if (_complete_expansion && _dim >= 3 && !_w_var)
83  paramError("w",
84  "The w velocity must be defined when 'complete_expansion=true'"
85  "and problem dimension is larger or equal to three.");
86 }
87 
88 ADReal
89 INSFVMomentumDiffusion::computeStrongResidual(const bool populate_a_coeffs)
90 {
91  const Moose::StateArg state = determineState();
92  const auto dudn = gradUDotNormal(state, _correct_skewness);
93  ADReal face_mu;
94 
95  if (onBoundary(*_face_info))
96  face_mu = _mu(makeCDFace(*_face_info), state);
97  else
99  face_mu,
100  _mu(elemArg(), state),
101  _mu(neighborArg(), state),
102  *_face_info,
103  true);
104 
105  // Protecting from negative viscosity at interpolation
106  // to preserve convergence
107  if (face_mu < 0.0)
108  {
109  if (!(_limit_interpolation))
110  {
111  mooseDoOnce(mooseWarning(
112  "Negative face viscosity has been encountered. Value ",
113  raw_value(face_mu),
114  " at ",
116  " limiting it to 0!\nFurther warnings for this issue will be silenced, but the "
117  "occurrences will be recorded through the solution invalidity interface."));
118  flagInvalidSolution("Negative face dynamic viscosity has been encountered.");
119  }
120  // Keep face_mu here for sparsity pattern detection
121  face_mu = 0 * face_mu;
122  }
123 
124  if (populate_a_coeffs)
125  {
128  {
129  const auto dof_number = _face_info->elem().dof_number(_sys.number(), _var.number(), 0);
130  // A gradient is a linear combination of degrees of freedom so it's safe to straight-up index
131  // into the derivatives vector at the dof we care about
132  _ae = dudn.derivatives()[dof_number];
133  _ae *= -face_mu;
134  }
137  {
138  const auto dof_number = _face_info->neighbor().dof_number(_sys.number(), _var.number(), 0);
139  _an = dudn.derivatives()[dof_number];
140  _an *= face_mu;
141  }
142  }
143 
144  ADReal dudn_transpose = 0.0;
146  {
147  // Computing the gradient from coupled variables
148  // Normally, we can do this with `_var.gradient(face, state)` but we will need the transpose
149  // gradient. So, we compute all at once
150  Moose::FaceArg face;
151  if (onBoundary(*_face_info))
152  face = singleSidedFaceArg();
153  else
155 
157  if (_dim == 1)
158  {
159  const auto & grad_u = _u_var->gradient(face, state);
160  gradient = ADRealTensorValue(grad_u, ADRealVectorValue(0, 0, 0), ADRealVectorValue(0, 0, 0));
161  }
162  else if (_dim == 2)
163  {
164  const auto & grad_u = _u_var->gradient(face, state);
165  const auto & grad_v = _v_var->gradient(face, state);
166  gradient = ADRealTensorValue(grad_u, grad_v, ADRealVectorValue(0, 0, 0));
167  }
168  else // if (_dim == 3)
169  {
170  const auto & grad_u = _u_var->gradient(face, state);
171  const auto & grad_v = _v_var->gradient(face, state);
172  const auto & grad_w = _w_var->gradient(face, state);
173  gradient = ADRealTensorValue(grad_u, grad_v, grad_w);
174  }
175 
176  // Getting transpose of the gradient matrix
177  const auto gradient_transpose = gradient.transpose();
178 
179  dudn_transpose += gradient_transpose.row(_index) * _face_info->normal();
180  }
181 
182  return -face_mu * (dudn + dudn_transpose);
183 }
184 
185 void
187 {
188  if (skipForBoundary(fi))
189  return;
190 
191  _face_info = &fi;
192  _normal = fi.normal();
193  _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
194 
196 
199  _rc_uo.addToA(&fi.elem(), _index, _ae * (fi.faceArea() * fi.faceCoord()));
202  _rc_uo.addToA(fi.neighborPtr(), _index, _an * (fi.faceArea() * fi.faceCoord()));
203 }
204 
205 ADReal
207 {
208  return computeStrongResidual(false);
209 }
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
void paramError(const std::string &param, Args... args) const
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
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
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...
void mooseWarning(Args &&... args) const
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