https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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",
41 Moose::RelationshipManagerType::GEOMETRIC | Moose::RelationshipManagerType::ALGEBRAIC |
42 Moose::RelationshipManagerType::COUPLING,
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<bool>("include_isotropic_viscous_stress",
51 false,
52 "Add the -(2/3) mu div(u) I term (requires specifying the velocity "
53 "components via 'u', 'v', 'w'). Only meaningful for "
54 "weakly-compressible formulations.");
55 params.addParam<MooseFunctorName>("u", "The velocity in the x direction.");
56 params.addParam<MooseFunctorName>("v", "The velocity in the y direction.");
57 params.addParam<MooseFunctorName>("w", "The velocity in the z direction.");
58 params.addParam<bool>(
59 "limit_interpolation", false, "Flag to limit interpolation to positive values.");
60 params.addParam<bool>("newton_solve", false, "Whether a Newton nonlinear solve is being used");
61 params.addParamNamesToGroup("newton_solve", "Advanced");
62 return params;
63}
64
66 : INSFVFluxKernel(params),
68 _mu(getFunctor<ADReal>(NS::mu)),
69 _mu_interp_method(
70 Moose::FV::selectInterpolationMethod(getParam<MooseEnum>("mu_interp_method"))),
71 _u_var(params.isParamValid("u") ? &getFunctor<ADReal>("u") : nullptr),
72 _v_var(params.isParamValid("v") ? &getFunctor<ADReal>("v") : nullptr),
73 _w_var(params.isParamValid("w") ? &getFunctor<ADReal>("w") : nullptr),
74 _complete_expansion(getParam<bool>("complete_expansion")),
75 _include_isotropic_viscous_stress(getParam<bool>("include_isotropic_viscous_stress")),
76 _limit_interpolation(getParam<bool>("limit_interpolation")),
77 _dim(_subproblem.mesh().dimension()),
78 _newton_solve(getParam<bool>("newton_solve"))
79{
81 paramError("u", "The u velocity must be defined when 'complete_expansion=true'.");
82
83 if (_complete_expansion && _dim >= 2 && !_v_var)
84 paramError("v",
85 "The v velocity must be defined when 'complete_expansion=true'"
86 "and problem dimension is larger or equal to 2.");
87
88 if (_complete_expansion && _dim >= 3 && !_w_var)
89 paramError("w",
90 "The w velocity must be defined when 'complete_expansion=true'"
91 "and problem dimension is larger or equal to three.");
92
94 {
96 paramError("include_isotropic_viscous_stress",
97 "Complete expansion needs to be enabled to use the isotropic viscous stress!");
98
99 if (!_u_var)
100 paramError("include_isotropic_viscous_stress",
101 "Velocity components must be provided to use the "
102 "'include_isotropic_viscous_stress' option.");
103 if (_dim >= 2 && !_v_var)
104 paramError("include_isotropic_viscous_stress",
105 "Velocity components must be provided to use the "
106 "'include_isotropic_viscous_stress' option in dimensions >= 2.");
107 if (_dim >= 3 && !_w_var)
108 paramError("include_isotropic_viscous_stress",
109 "Velocity components must be provided to use the "
110 "'include_isotropic_viscous_stress' option in 3D.");
111 }
112}
113
114ADReal
116{
117 const Moose::StateArg state = determineState();
118 const auto dudn = gradUDotNormal(state, _correct_skewness);
119 ADReal face_mu;
120
122 face_mu = _mu(makeCDFace(*_face_info), state);
123 else
125 face_mu,
126 _mu(elemArg(), state),
127 _mu(neighborArg(), state),
128 *_face_info,
129 true);
130
131 // Protecting from negative viscosity at interpolation
132 // to preserve convergence
133 if (face_mu < 0.0)
134 {
136 {
137 mooseDoOnce(mooseWarning(
138 "Negative face viscosity has been encountered. Value ",
139 raw_value(face_mu),
140 " at ",
142 " limiting it to 0!\nFurther warnings for this issue will be silenced, but the "
143 "occurrences will be recorded through the solution invalidity interface."));
144 flagInvalidSolution("Negative face dynamic viscosity has been encountered.");
145 }
146 // Keep face_mu here for sparsity pattern detection
147 face_mu = 0 * face_mu;
148 }
149
150 if (populate_a_coeffs)
151 {
152 if (_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
153 _face_type == FaceInfo::VarFaceNeighbors::BOTH)
154 {
155 const auto dof_number = _face_info->elem().dof_number(_sys.number(), _var.number(), 0);
156 // A gradient is a linear combination of degrees of freedom so it's safe to straight-up index
157 // into the derivatives vector at the dof we care about
158 _ae = dudn.derivatives()[dof_number];
159 _ae *= -face_mu;
160 }
161 if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
162 _face_type == FaceInfo::VarFaceNeighbors::BOTH)
163 {
164 const auto dof_number = _face_info->neighbor().dof_number(_sys.number(), _var.number(), 0);
165 _an = dudn.derivatives()[dof_number];
166 _an *= face_mu;
167 }
168 }
169
170 ADReal dudn_transpose = 0.0;
171 ADReal divergence_term = 0.0;
173 {
174 // Computing the gradient from coupled variables
175 // Normally, we can do this with `_var.gradient(face, state)` but we will need the transpose
176 // gradient. So, we compute all at once
177 Moose::FaceArg face;
179 face = singleSidedFaceArg();
180 else
182
184 if (_dim == 1)
185 {
186 const auto & grad_u = _u_var->gradient(face, state);
188 }
189 else if (_dim == 2)
190 {
191 const auto & grad_u = _u_var->gradient(face, state);
192 const auto & grad_v = _v_var->gradient(face, state);
193 gradient = ADRealTensorValue(grad_u, grad_v, ADRealVectorValue(0, 0, 0));
194 }
195 else // if (_dim == 3)
196 {
197 const auto & grad_u = _u_var->gradient(face, state);
198 const auto & grad_v = _v_var->gradient(face, state);
199 const auto & grad_w = _w_var->gradient(face, state);
200 gradient = ADRealTensorValue(grad_u, grad_v, grad_w);
201 }
202
203 // Getting transpose of the gradient matrix
204 const auto gradient_transpose = gradient.transpose();
205
206 dudn_transpose += gradient_transpose.row(_index) * _face_info->normal();
207
209 {
211 velocity(0) = _u_var ? (*_u_var)(face, state) : ADReal(0);
212 velocity(1) = _v_var ? (*_v_var)(face, state) : ADReal(0);
213 velocity(2) = _w_var ? (*_w_var)(face, state) : ADReal(0);
214
215 const auto coord_sys = _subproblem.getCoordSystem(_face_info->elem().subdomain_id());
216 unsigned int rz_radial_coord =
218 divergence_term =
219 NS::divergence(gradient, velocity, face.getPoint(), coord_sys, rz_radial_coord);
220 }
221 }
222
223 ADReal residual = -face_mu * (dudn + dudn_transpose);
225 residual += (2.0 / 3.0) * face_mu * divergence_term * _face_info->normal()(_index);
226
227 return residual;
228}
229
230void
232{
233 if (skipForBoundary(fi))
234 return;
235
236 _face_info = &fi;
237 _normal = fi.normal();
238 _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
239
241
242 if (_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
243 _face_type == FaceInfo::VarFaceNeighbors::BOTH)
244 _rc_uo.addToA(&fi.elem(), _index, _ae * (fi.faceArea() * fi.faceCoord()));
245 if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
246 _face_type == FaceInfo::VarFaceNeighbors::BOTH)
247 _rc_uo.addToA(fi.neighborPtr(), _index, _an * (fi.faceArea() * fi.faceCoord()));
248}
249
250ADReal
DualNumber< Real, DNDerivativeType, true > ADReal
const double mu
registerMooseObject("NavierStokesApp", INSFVMomentumDiffusion)
static InputParameters validParams()
Moose::ElemArg neighborArg(bool correct_skewness=false) const
Moose::ElemArg elemArg(bool correct_skewness=false) const
RealVectorValue _normal
virtual bool skipForBoundary(const FaceInfo &fi) const
bool onBoundary(const FaceInfo &fi) const
MooseVariableFV< Real > & _var
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
virtual ADReal gradUDotNormal(const Moose::StateArg &time, const bool correct_skewness) const
const FaceInfo * _face_info
FaceInfo::VarFaceNeighbors _face_type
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
const Point & normal() const
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const
const Elem & elem() const
const Elem * neighborPtr() const
Real faceArea() const
Real & faceCoord()
const Point & faceCentroid() const
const Elem & neighbor() const
A flux kernel that momentum residual objects that add non-advection flux terms, or more specifically ...
static InputParameters validParams()
void addResidualAndJacobian(const ADReal &residual)
Process into either the system residual or Jacobian.
ADReal _ae
The a coefficient for the element.
ADReal _an
The a coefficient for the neighbor.
const bool _include_isotropic_viscous_stress
Whether to add the -(2/3) mu div(u) I contribution.
const Moose::Functor< ADReal > *const _v_var
y-velocity
INSFVMomentumDiffusion(const InputParameters &params)
const unsigned int _dim
dimension
const Moose::Functor< ADReal > *const _w_var
z-velocity
const Moose::FV::InterpMethod _mu_interp_method
The face interpolation method for the viscosity.
const Moose::Functor< ADReal > *const _u_var
x-velocity
virtual ADReal computeStrongResidual(const bool populate_a_coeffs)
Routine to compute this object's strong residual (e.g.
static InputParameters validParams()
const bool _limit_interpolation
Boolean parameter to limit interpolation.
virtual ADReal computeSegregatedContribution() override
Compute the contribution which goes into the residual of the segregated system.
const Moose::Functor< ADReal > & _mu
The dynamic viscosity.
void gatherRCData(const FaceInfo &fi) override final
Should be a non-empty implementation if the residual object is a FVFluxKernel and introduces residual...
const bool _complete_expansion
Boolean parameter to include the complete momentum expansion.
const unsigned int _index
index x|y|z
RhieChowInterpolatorBase & _rc_uo
The Rhie Chow user object that is responsible for generating face velocities for advection terms.
void paramError(const std::string &param, Args... args) const
void mooseWarning(Args &&... args) const
SystemBase & sys()
unsigned int number() const
virtual const OutputTools< T >::VariableGradient & gradient()
SubProblem & _subproblem
SystemBase & _sys
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.
unsigned int getAxisymmetricRadialCoord() const
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
unsigned int number() const
Moose::StateArg determineState() const
MeshBase & mesh
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
T divergence(const TensorValue< T > &gradient, const VectorType &value, const PointType &point, const Moose::CoordinateSystemType &coord_sys, const unsigned int rz_radial_coord)
Compute the divergence of a vector given its matrix of derivatives.
static const std::string mu
Definition NS.h:127