https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
12#include "NSFVUtils.h"
13#include "MathFVUtils.h"
14#include "NS.h"
15#include "RhieChowMassFlux.h"
19
21
24{
26 params.addClassDescription("Represents the matrix and right hand side contributions of the "
27 "stress and advection terms of the momentum equation.");
28 params.addRequiredParam<SolverVariableName>("u", "The velocity in the x direction.");
29 params.addParam<SolverVariableName>("v", "The velocity in the y direction.");
30 params.addParam<SolverVariableName>("w", "The velocity in the z direction.");
31 params.addRequiredParam<UserObjectName>(
32 "rhie_chow_user_object",
33 "The rhie-chow user-object which is used to determine the face velocity.");
34 params.addRequiredParam<MooseFunctorName>(NS::mu, "The diffusion coefficient.");
35 MooseEnum momentum_component("x=0 y=1 z=2");
37 "momentum_component",
38 momentum_component,
39 "The component of the momentum equation that this kernel applies to.");
40 params.addParam<bool>(
41 "use_nonorthogonal_correction",
42 true,
43 "If the nonorthogonal correction should be used when computing the normal gradient.");
44 params.addParam<bool>(
45 "use_deviatoric_terms", false, "If deviatoric terms in the stress terms need to be used.");
46
47 params.addRequiredParam<InterpolationMethodName>(
48 "advected_interp_method_name",
49 "Name of the FVInterpolationMethod to use for the advected velocity.");
50 return params;
51}
52
54 : LinearFVFluxKernel(params),
56 _dim(_subproblem.mesh().dimension()),
57 _mass_flux_provider(getUserObject<RhieChowMassFlux>("rhie_chow_user_object")),
58 _mu(getFunctor<Real>(getParam<MooseFunctorName>(NS::mu))),
59 _use_nonorthogonal_correction(getParam<bool>("use_nonorthogonal_correction")),
60 _use_deviatoric_terms(getParam<bool>("use_deviatoric_terms")),
61 _adv_interp_method(getFVAdvectedInterpolationMethod(
62 getParam<InterpolationMethodName>("advected_interp_method_name"))),
63 _advected_gradient_field(
64 _adv_interp_method.needsGradients()
65 ? &_var.requestCellGradients(_adv_interp_method.gradientMethodName())
66 : nullptr),
67 _face_mass_flux(0.0),
68 _boundary_normal_factor(1.0),
69 _stress_matrix_contribution(0.0),
70 _stress_rhs_contribution(0.0),
71 _index(getParam<MooseEnum>("momentum_component")),
72 _velocity_vars{nullptr, nullptr, nullptr},
73 _gradient_field(_use_nonorthogonal_correction || _use_deviatoric_terms
74 ? &_var.requestCellGradients()
75 : nullptr),
76 _velocity_gradient_fields{nullptr, nullptr, nullptr},
77 _coord_type(getBlockCoordSystem()),
78 _rz_radial_coord(_fe_problem.mesh().getAxisymmetricRadialCoord())
79{
80 // A face where this kernel's variable is defined on both sides but the kernel itself is not
81 // (VarFaceNeighbors::BOTH with the kernel restricted to only one side) would need boundary-like
82 // treatment that this kernel does not implement.
83 if (blockIDs() != _var.blockIDs())
84 paramError("block",
85 "Must match the block restriction of variable '",
86 _var.name(),
87 "' (",
89 "). This kernel's blocks are ",
91 ".");
92
93 auto get_velocity_var = [&](const std::string & param_name)
94 {
95 return dynamic_cast<MooseLinearVariableFVReal *>(
96 &_fe_problem.getVariable(_tid, getParam<SolverVariableName>(param_name)));
97 };
98
99 std::array<MooseLinearVariableFVReal *, 3> velocity_vars{nullptr, nullptr, nullptr};
100
101 velocity_vars[0] = get_velocity_var("u");
102 if (!velocity_vars[0])
103 paramError("u", "the u velocity must be a MooseLinearVariableFVReal.");
104
105 if (_dim >= 2)
106 {
107 if (!params.isParamValid("v"))
108 paramError("v", "In two or more dimensions, the v velocity must be supplied.");
109 velocity_vars[1] = get_velocity_var("v");
110 if (!velocity_vars[1])
111 paramError("v",
112 "In two or more dimensions, the v velocity must be supplied and it must be a "
113 "MooseLinearVariableFVReal.");
114 }
115
116 if (_dim >= 3)
117 {
118 if (!params.isParamValid("w"))
119 paramError("w", "In three-dimensions, the w velocity must be supplied.");
120 velocity_vars[2] = get_velocity_var("w");
121 if (!velocity_vars[2])
122 paramError("w",
123 "In three-dimensions, the w velocity must be supplied and it must be a "
124 "MooseLinearVariableFVReal.");
125 }
126
127 for (const auto dir : make_range(_dim))
128 _velocity_vars[dir] = velocity_vars[dir];
129
131 for (const auto dir : make_range(_dim))
132 _velocity_gradient_fields[dir] = &velocity_vars[dir]->requestCellGradients();
133}
134
135Real
142
143Real
150
151Real
158
159Real
166
167Real
169{
170 const auto * const adv_diff_bc = cast_ptr<const LinearFVAdvectionDiffusionBC *>(&bc);
171
172 mooseAssert(adv_diff_bc, "This should be a valid BC!");
173 return (computeStressBoundaryMatrixContribution(adv_diff_bc) +
176}
177
178Real
180{
181 const auto * const adv_diff_bc = cast_ptr<const LinearFVAdvectionDiffusionBC *>(&bc);
182 mooseAssert(adv_diff_bc, "This should be a valid BC!");
183 return (computeStressBoundaryRHSContribution(adv_diff_bc) +
186}
187
188Real
193
194Real
199
200Real
212
213Real
224
225Real
227{
228 const auto face_arg = makeCDFace(*_current_face_info);
229
230 // A nonorthogonal correction uses the normal component of the cell-to-cell vector.
234
235 return _mu(face_arg, determineState()) / d;
236}
237
238Real
240{
241 // We can have contributions to the right hand side in two occasions:
242 // (1) when we use nonorthogonal correction for the normal gradients
243 // (2) when we request the deviatoric parts of the stress tensor. (needed for space-dependent
244 // viscosities for example)
246 return 0.0;
247
248 // Scenario (1), add the nonorthogonal correction. In 1D, there is no correction.
249 RealVectorValue correction_vector;
251 correction_vector =
254
255 // Interpolate the two cell corrections to the face.
256 const auto interp_coeffs =
257 interpCoeffs(Moose::FV::InterpMethod::Average, *_current_face_info, true);
258 const Real elem_correction =
260 const Real neighbor_correction =
262
263 const auto face_arg = makeCDFace(*_current_face_info);
264 return _mu(face_arg, determineState()) *
265 (interp_coeffs.first * elem_correction + interp_coeffs.second * neighbor_correction);
266}
267
268Real
270 const ElemInfo & cell_info, const RealVectorValue & nonorthogonal_correction_vector) const
271{
272 Real correction = 0.0;
273
275 {
276 mooseAssert(_gradient_field, "Gradient field should be registered when gradients are needed.");
277 // Get the kernel variable gradient from this cell.
278 correction += _gradient_field->gradient(cell_info) * nonorthogonal_correction_vector;
279 }
280
281 // Scenario (2), account for the deviatoric parts of the stress tensor.
283 {
284 std::array<RealGradient, 3> gradients;
285 Real trace = 0.0;
286 RealVectorValue deviatoric_vector;
287
288 // Loop over every velocity component to form the symmetric gradient pieces.
289 for (const auto dir : make_range(_dim))
290 {
291 gradients[dir] = velocityGradientField(dir).gradient(cell_info);
292 trace += gradients[dir](dir);
293 }
294
295 if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
297 cell_info.centroid()(_rz_radial_coord);
298
299 // Assemble the explicit transpose/trace contribution component by component.
300 for (const auto dir : make_range(_dim))
301 {
302 gradients[dir](dir) -= 2.0 / 3.0 * trace;
303 deviatoric_vector(dir) = gradients[dir](_index);
304 }
305
306 correction += deviatoric_vector * _current_face_info->normal();
307 }
308
309 return correction;
310}
311
312Real
315{
316 auto grad_contrib = bc->computeBoundaryGradientMatrixContribution();
317 // If the boundary condition does not include the diffusivity contribution then
318 // add it here.
320 {
321 const auto face_arg = singleSidedFaceArg(_current_face_info);
322 grad_contrib *= _mu(face_arg, determineState());
323 }
324
325 return grad_contrib;
326}
327
328Real
331{
332 const auto face_arg = singleSidedFaceArg(_current_face_info);
333 auto grad_contrib = bc->computeBoundaryGradientRHSContribution();
334 // If the boundary condition does not include the diffusivity contribution then
335 // add it here.
337 grad_contrib *= _mu(face_arg, determineState());
338
339 // We add the nonorthogonal corrector for the face here. Potential idea: we could do
340 // this in the boundary condition too. For now, however, we keep it like this.
342 {
343 // We support internal boundaries as well. In that case we have to decide on which side
344 // of the boundary we are on.
345 const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
348
349 // Unit vector to the boundary. Unfortunately, we have to recompute it because the value
350 // stored in the face info is only correct for external boundaries
351 const auto e_Cf = _current_face_info->faceCentroid() - elem_info->centroid();
352 const auto correction_vector =
353 _current_face_info->normal() - 1 / (_current_face_info->normal() * e_Cf) * e_Cf;
354
355 const auto state_arg = determineState();
356 mooseAssert(_gradient_field, "Gradient field should be registered when gradients are needed.");
357 grad_contrib += _mu(face_arg, state_arg) * _gradient_field->gradient(*elem_info) *
358 _boundary_normal_factor * correction_vector;
359 }
360
361 // Complete prescribed fluxes already include all applicable stress contributions.
363 {
364 // We might be on a face which is an internal boundary so we want to make sure we
365 // get the gradient from the right side.
366 const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
369
370 // A zero correction vector restricts the cell correction to its deviatoric part; the
371 // boundary nonorthogonal correction is added above. We support internal boundaries too so
372 // we have to make sure the normal points always outward.
373 grad_contrib += _mu(face_arg, determineState()) * _boundary_normal_factor *
374 computeCellStressExplicitCorrection(*elem_info, RealVectorValue());
375 }
376
377 return grad_contrib;
378}
379
380Real
383{
384 const auto boundary_value_matrix_contrib = bc->computeBoundaryValueMatrixContribution();
385 return boundary_value_matrix_contrib * _face_mass_flux;
386}
387
388Real
391{
392 const auto boundary_value_rhs_contrib = bc->computeBoundaryValueRHSContribution();
393 return -boundary_value_rhs_contrib * _face_mass_flux;
394}
395
396void
398{
400
401 // Multiplier that ensures the normal of the boundary always points outwards, even in cases
402 // when the boundary is within the mesh.
403 _boundary_normal_factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0;
404
405 // Caching the mass flux on the face which will be reused in the advection term's matrix and
406 // right hand side contributions
408
409 if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
410 {
411 const auto state = determineState();
412 const auto & elem_info = *_current_face_info->elemInfo();
413 const auto & neighbor_info = *_current_face_info->neighborInfo();
414
415 const Real elem_value = _var.getElemValue(elem_info, state);
416 const Real neighbor_value = _var.getElemValue(neighbor_info, state);
417
419 {
420 mooseAssert(_advected_gradient_field,
421 "Gradient field should be registered when gradients are needed.");
424 }
425
427 elem_value,
428 neighbor_value,
432 }
433
434 // We'll have to set this to zero to make sure that we don't accumulate values over multiple
435 // faces. The matrix contribution should be fine.
437}
438
441{
442 mooseAssert(dir < _velocity_vars.size() && _velocity_vars[dir],
443 "Velocity variable for requested direction is not available.");
444 return *_velocity_vars[dir];
445}
446
449{
450 mooseAssert(dir < _velocity_gradient_fields.size() && _velocity_gradient_fields[dir],
451 "Velocity gradient field for requested direction is not available.");
452 return *_velocity_gradient_fields[dir];
453}
const double mu
registerMooseObject("NavierStokesApp", LinearWCNSFVMomentumFlux)
virtual const std::set< SubdomainID > & blockIDs() const
const Point & centroid() const
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
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
virtual bool needsGradients() const
Moose::FaceArg makeCDFace(const FaceInfo &fi, const bool correct_skewness=false) const
const Point & normal() const
const Point & eCN() const
const ElemInfo * elemInfo() const
Real dCNMag() const
const ElemInfo * neighborInfo() const
const Point & dCN() const
const Point & faceCentroid() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
bool isParamValid(const std::string &name) const
virtual Real computeBoundaryValueMatrixContribution() const=0
virtual bool providesCompleteBoundaryFlux() const
virtual Real computeBoundaryValueRHSContribution() const=0
virtual Real computeBoundaryGradientMatrixContribution() const=0
virtual Real computeBoundaryGradientRHSContribution() const=0
virtual bool includesMaterialPropertyMultiplier() const
virtual bool needsBoundaryNonorthogonalCorrection() const
bool _cached_matrix_contribution
FaceInfo::VarFaceNeighbors _current_face_type
Moose::FaceArg singleSidedFaceArg(const FaceInfo *fi, Moose::FV::LimiterType limiter_type=Moose::FV::LimiterType::CentralDifference, bool correct_skewness=false) const
virtual void setupFaceData(const FaceInfo *face_info)
const FaceInfo * _current_face_info
static InputParameters validParams()
RealVectorValue gradient(const ElemInfo &elem_info) const
MooseLinearVariableFV< Real > & _var
const THREAD_ID _tid
FEProblemBase & _fe_problem
Kernel that implements the stress tensor and advection terms for the momentum equation.
const LinearFVGradientReader *const _advected_gradient_field
Gradient field used by advected interpolations that require gradients.
virtual void setupFaceData(const FaceInfo *face_info) override
Set the current FaceInfo object.
Real computeInternalStressMatrixContribution()
Computes the matrix contribution of the stress term on the current face when the face is an internal ...
virtual Real computeNeighborMatrixContribution() override
VectorValue< Real > _elem_grad_storage
Reusable gradient storage used when advected interpolation requires gradients.
const MooseLinearVariableFVReal & velocityVar(unsigned int dir) const
Helper to access the velocity variable for a given direction.
Real _face_mass_flux
Container for the mass flux on the face which will be reused in the advection term's matrix and right...
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.
Real computeInternalAdvectionElemMatrixContribution()
Computes the matrix contribution of the advective flux on the element side of current face when the f...
FVAdvectedInterpolationMethod::AdvectedSystemContribution _adv_interp_result
Current advected interpolation contribution on the face.
virtual Real computeNeighborRightHandSideContribution() override
const Moose::CoordinateSystemType _coord_type
Coordinate system of the blocks this kernel operates on.
virtual Real computeElemMatrixContribution() override
Real _stress_matrix_contribution
The cached matrix contribution.
const Moose::Functor< Real > & _mu
The functor for the dynamic viscosity.
virtual Real computeElemRightHandSideContribution() override
Real _boundary_normal_factor
Multiplier that ensures the normal of the boundary always points outwards, even in cases when the bou...
Real _stress_rhs_contribution
The cached right hand side contribution.
Real computeInternalStressExplicitCorrection() const
Computes the explicit internal-face stress correction.
Real computeInternalStressTransmissibility() const
Computes the implicit internal-face stress transmissibility.
Real computeCellStressExplicitCorrection(const ElemInfo &cell_info, const RealVectorValue &nonorthogonal_correction_vector) const
Compute the explicit stress correction reconstructed from one adjacent cell.
const LinearFVGradientReader & velocityGradientField(unsigned int dir) const
Helper to access the velocity gradient field for a given direction.
virtual Real computeBoundaryRHSContribution(const LinearFVBoundaryCondition &bc) override
const unsigned int _index
Index x|y|z, this is mainly to handle the deviatoric parts correctly in in the stress term.
virtual Real computeAdvectionBoundaryMatrixContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the matrix contributions of the boundary conditions resulting from the advection term.
const bool _use_deviatoric_terms
Switch to enable/disable deviatoric parts in the stress term.
virtual Real computeAdvectionBoundaryRHSContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the right hand side contributions of the boundary conditions resulting from the advection te...
Real computeInternalStressRHSContribution()
Computes the right hand side contribution of the stress term on the current face when the face is an ...
VectorValue< Real > _neighbor_grad_storage
std::array< const LinearFVGradientReader *, 3 > _velocity_gradient_fields
Gradient fields used for velocity variables in deviatoric stress terms.
Real computeInternalAdvectionNeighborMatrixContribution()
Computes the matrix contribution of the advective flux on the neighbor side of current face when the ...
std::array< const MooseLinearVariableFVReal *, 3 > _velocity_vars
Velocity variables for each coordinate direction.
const unsigned int _dim
The dimension of the mesh.
const bool _use_nonorthogonal_correction
Switch to enable/disable nonorthogonal correction in the stress term.
Real computeStressBoundaryMatrixContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the matrix contributions of the boundary conditions resulting from the stress tensor.
const RhieChowMassFlux & _mass_flux_provider
The Rhie-Chow user object that provides us with the face velocity.
const LinearFVGradientReader * _gradient_field
Gradient field used for the kernel variable nonorthogonal correction.
Real computeStressBoundaryRHSContribution(const LinearFVAdvectionDiffusionBC *bc)
Computes the right hand side contributions of the boundary conditions resulting from the stress tenso...
static InputParameters validParams()
virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition &bc) override
LinearWCNSFVMomentumFlux(const InputParameters &params)
Class constructor.
const std::string & name() const
void paramError(const std::string &param, Args... args) const
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
Real getMassFlux(const FaceInfo &fi) const
Get the face velocity times density (used in advection terms)
Moose::StateArg determineState() const
MeshBase & mesh
std::string stringify(const T &t)
static const std::string mu
Definition NS.h:127