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 "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.
73
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
110Real
117
118Real
125
126Real
133
134Real
141
142Real
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
153Real
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
163Real
168
169Real
174
175Real
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.
188
189 // Cache the matrix contribution
192 }
193
195}
196
197Real
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 =
219 interpCoeffs(Moose::FV::InterpMethod::Average, *_current_face_info, true);
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 =
239 interpCoeffs(Moose::FV::InterpMethod::Average, *_current_face_info, true);
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] =
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
295Real
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
311Real
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
343 // Complete prescribed fluxes already include all applicable stress contributions.
345 {
346 // We might be on a face which is an internal boundary so we want to make sure we
347 // get the gradient from the right side.
348 const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
351
352 const auto state_arg = determineState();
353
354 RealGradient grad_elem[3];
355 Real trace_elem = 0;
356 RealVectorValue deviatoric_vector_elem;
357
358 for (const auto dir : make_range(_dim))
359 {
360 grad_elem[dir] = velocityVar(dir).gradSln(*elem_info, state_arg);
361 trace_elem += grad_elem[dir](dir);
362 }
363
364 if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
365 {
366 const auto & radial_var = velocityVar(_rz_radial_coord);
367 const Real elem_value =
368 radial_var.getElemValue(*elem_info, state_arg) / elem_info->centroid()(_rz_radial_coord);
369 trace_elem += elem_value;
370 }
371
372 for (const auto dir : make_range(_dim))
373 {
374 grad_elem[dir](dir) -= 2. / 3 * trace_elem;
375 deviatoric_vector_elem(dir) = grad_elem[dir](_index);
376 }
377
378 // We support internal boundaries too so we have to make sure the normal points always outward
379 grad_contrib += _mu(face_arg, state_arg) * deviatoric_vector_elem * _boundary_normal_factor *
381 }
382
383 return grad_contrib;
384}
385
386Real
389{
390 const auto boundary_value_matrix_contrib = bc->computeBoundaryValueMatrixContribution();
391 return boundary_value_matrix_contrib * _face_mass_flux;
392}
393
394Real
397{
398 const auto boundary_value_rhs_contrib = bc->computeBoundaryValueRHSContribution();
399 return -boundary_value_rhs_contrib * _face_mass_flux;
400}
401
402void
404{
406
407 // Multiplier that ensures the normal of the boundary always points outwards, even in cases
408 // when the boundary is within the mesh.
409 _boundary_normal_factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0;
410
411 // Caching the mass flux on the face which will be reused in the advection term's matrix and
412 // right hand side contributions
414
415 if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
416 {
417 const auto state = determineState();
418 const auto & elem_info = *_current_face_info->elemInfo();
419 const auto & neighbor_info = *_current_face_info->neighborInfo();
420
421 const Real elem_value = _var.getElemValue(elem_info, state);
422 const Real neighbor_value = _var.getElemValue(neighbor_info, state);
423
425 {
426 const auto limiter_type = _adv_interp_method.gradientLimiter();
427 _elem_grad_storage = _var.gradSln(elem_info, state, limiter_type);
428 _neighbor_grad_storage = _var.gradSln(neighbor_info, state, limiter_type);
429 }
430
432 elem_value,
433 neighbor_value,
437 }
438
439 // We'll have to set this to zero to make sure that we don't accumulate values over multiple
440 // faces. The matrix contribution should be fine.
442}
443
446{
447 mooseAssert(dir < _velocity_vars.size() && _velocity_vars[dir],
448 "Velocity variable for requested direction is not available.");
449 return *_velocity_vars[dir];
450}
const double mu
registerMooseObject("NavierStokesApp", LinearWCNSFVMomentumFlux)
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 Moose::FV::GradientLimiterType gradientLimiter() const
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()
MooseLinearVariableFV< Real > & _var
const THREAD_ID _tid
FEProblemBase & _fe_problem
Kernel that implements the stress tensor and advection terms for the momentum equation.
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.
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.
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.
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
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.
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.
void paramError(const std::string &param, Args... args) const
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
VectorValue< Real > gradSln(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
static const std::string mu
Definition NS.h:127