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"
17
19
22{
24 params.addClassDescription("Represents the matrix and right hand side contributions of the "
25 "stress and advection terms of the momentum equation.");
26 params.addRequiredParam<SolverVariableName>("u", "The velocity in the x direction.");
27 params.addParam<SolverVariableName>("v", "The velocity in the y direction.");
28 params.addParam<SolverVariableName>("w", "The velocity in the z direction.");
29 params.addRequiredParam<UserObjectName>(
30 "rhie_chow_user_object",
31 "The rhie-chow user-object which is used to determine the face velocity.");
32 params.addRequiredParam<MooseFunctorName>(NS::mu, "The diffusion coefficient.");
33 MooseEnum momentum_component("x=0 y=1 z=2");
35 "momentum_component",
36 momentum_component,
37 "The component of the momentum equation that this kernel applies to.");
38 params.addParam<bool>(
39 "use_nonorthogonal_correction",
40 true,
41 "If the nonorthogonal correction should be used when computing the normal gradient.");
42 params.addParam<bool>(
43 "use_deviatoric_terms", false, "If deviatoric terms in the stress terms need to be used.");
44
45 params.addRequiredParam<InterpolationMethodName>(
46 "advected_interp_method_name",
47 "Name of the FVInterpolationMethod to use for the advected velocity.");
48 return params;
49}
50
52 : LinearFVFluxKernel(params),
54 _dim(_subproblem.mesh().dimension()),
55 _mass_flux_provider(getUserObject<RhieChowMassFlux>("rhie_chow_user_object")),
56 _mu(getFunctor<Real>(getParam<MooseFunctorName>(NS::mu))),
57 _use_nonorthogonal_correction(getParam<bool>("use_nonorthogonal_correction")),
58 _use_deviatoric_terms(getParam<bool>("use_deviatoric_terms")),
59 _adv_interp_method(getFVAdvectedInterpolationMethod(
60 getParam<InterpolationMethodName>("advected_interp_method_name"))),
61 _advected_gradient_field(
62 _adv_interp_method.needsGradients()
63 ? &_var.requestCellGradients(_adv_interp_method.gradientMethodName())
64 : nullptr),
65 _face_mass_flux(0.0),
66 _boundary_normal_factor(1.0),
67 _stress_matrix_contribution(0.0),
68 _stress_rhs_contribution(0.0),
69 _index(getParam<MooseEnum>("momentum_component")),
70 _velocity_vars{nullptr, nullptr, nullptr},
71 _gradient_field(_use_nonorthogonal_correction || _use_deviatoric_terms
72 ? &_var.requestCellGradients()
73 : nullptr),
74 _velocity_gradient_fields{nullptr, nullptr, nullptr},
75 _coord_type(getBlockCoordSystem()),
76 _rz_radial_coord(_fe_problem.mesh().getAxisymmetricRadialCoord())
77{
78 auto get_velocity_var = [&](const std::string & param_name)
79 {
80 return dynamic_cast<MooseLinearVariableFVReal *>(
81 &_fe_problem.getVariable(_tid, getParam<SolverVariableName>(param_name)));
82 };
83
84 std::array<MooseLinearVariableFVReal *, 3> velocity_vars{nullptr, nullptr, nullptr};
85
86 velocity_vars[0] = get_velocity_var("u");
87 if (!velocity_vars[0])
88 paramError("u", "the u velocity must be a MooseLinearVariableFVReal.");
89
90 if (_dim >= 2)
91 {
92 if (!params.isParamValid("v"))
93 paramError("v", "In two or more dimensions, the v velocity must be supplied.");
94 velocity_vars[1] = get_velocity_var("v");
95 if (!velocity_vars[1])
96 paramError("v",
97 "In two or more dimensions, the v velocity must be supplied and it must be a "
98 "MooseLinearVariableFVReal.");
99 }
100
101 if (_dim >= 3)
102 {
103 if (!params.isParamValid("w"))
104 paramError("w", "In three-dimensions, the w velocity must be supplied.");
105 velocity_vars[2] = get_velocity_var("w");
106 if (!velocity_vars[2])
107 paramError("w",
108 "In three-dimensions, the w velocity must be supplied and it must be a "
109 "MooseLinearVariableFVReal.");
110 }
111
112 for (const auto dir : make_range(_dim))
113 _velocity_vars[dir] = velocity_vars[dir];
114
116 for (const auto dir : make_range(_dim))
117 _velocity_gradient_fields[dir] = &velocity_vars[dir]->requestCellGradients();
118}
119
120Real
127
128Real
135
136Real
143
144Real
151
152Real
154{
155 const auto * const adv_diff_bc = cast_ptr<const LinearFVAdvectionDiffusionBC *>(&bc);
156
157 mooseAssert(adv_diff_bc, "This should be a valid BC!");
158 return (computeStressBoundaryMatrixContribution(adv_diff_bc) +
161}
162
163Real
165{
166 const auto * const adv_diff_bc = cast_ptr<const LinearFVAdvectionDiffusionBC *>(&bc);
167 mooseAssert(adv_diff_bc, "This should be a valid BC!");
168 return (computeStressBoundaryRHSContribution(adv_diff_bc) +
171}
172
173Real
178
179Real
184
185Real
187{
188 // If we don't have the value yet, we compute it
190 {
191 const auto face_arg = makeCDFace(*_current_face_info);
192
193 // If we requested nonorthogonal correction, we use the normal component of the
194 // cell to face vector.
198
199 // Cache the matrix contribution
202 }
203
205}
206
207Real
209{
210 // We can have contributions to the right hand side in two occasions:
211 // (1) when we use nonorthogonal correction for the normal gradients
212 // (2) when we request the deviatoric parts of the stress tensor. (needed for space-dependent
213 // viscosities for example)
215 {
216 // scenario (1), we need to add the nonorthogonal correction. In 1D, we don't have
217 // any correction so we just skip this part
219 {
220 const auto face_arg = makeCDFace(*_current_face_info);
221 const auto state_arg = determineState();
222 mooseAssert(_gradient_field,
223 "Gradient field should be registered when gradients are needed.");
224
225 // Get the gradients from the adjacent cells
226 const auto grad_elem = _gradient_field->gradient(*_current_face_info->elemInfo());
227 const auto grad_neighbor = _gradient_field->gradient(*_current_face_info->neighborInfo());
228
229 // Interpolate the two gradients to the face
230 const auto interp_coeffs =
231 interpCoeffs(Moose::FV::InterpMethod::Average, *_current_face_info, true);
232
233 const auto correction_vector =
237
238 // Cache the matrix contribution
240 _mu(face_arg, state_arg) *
241 (interp_coeffs.first * grad_elem + interp_coeffs.second * grad_neighbor) *
242 correction_vector;
243 }
244 // scenario (2), we will have to account for the deviatoric parts of the stress tensor.
246 {
247 const auto state_arg = determineState();
248
249 // Interpolate the two gradients to the face
250 const auto interp_coeffs =
251 interpCoeffs(Moose::FV::InterpMethod::Average, *_current_face_info, true);
252
253 RealGradient grad_elem[3];
254 RealGradient grad_neighbor[3];
255 Real trace_elem = 0;
256 Real trace_neighbor = 0;
257 RealVectorValue deviatoric_vector_elem;
258 RealVectorValue deviatoric_vector_neighbor;
259
260 // Loop over every velocity component so we can form the symmetric gradient pieces
261 for (const auto dir : make_range(_dim))
262 {
263 const auto & gradient_field = velocityGradientField(dir);
264 grad_elem[dir] = gradient_field.gradient(*_current_face_info->elemInfo());
265 grad_neighbor[dir] = gradient_field.gradient(*_current_face_info->neighborInfo());
266 trace_elem += grad_elem[dir](dir);
267 trace_neighbor += grad_neighbor[dir](dir);
268 }
269
270 const auto face_arg = makeCDFace(*_current_face_info);
271
272 if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
273 {
274 Real elem_value = 0.0;
275 Real neighbor_value = 0.0;
276 const auto & radial_var = velocityVar(_rz_radial_coord);
277 elem_value = radial_var.getElemValue(*_current_face_info->elemInfo(), state_arg) /
279 neighbor_value = radial_var.getElemValue(*_current_face_info->neighborInfo(), state_arg) /
281
282 trace_elem += elem_value;
283 trace_neighbor += neighbor_value;
284 }
285
286 // Assemble the explicit transpose/trace contribution component by component
287 for (const auto dir : make_range(_dim))
288 {
289 grad_elem[dir](dir) -= 2. / 3 * trace_elem;
290 grad_neighbor[dir](dir) -= 2. / 3 * trace_neighbor;
291
292 deviatoric_vector_elem(dir) = grad_elem[dir](_index);
293 deviatoric_vector_neighbor(dir) = grad_neighbor[dir](_index);
294 }
295
296 _stress_rhs_contribution += _mu(face_arg, state_arg) *
297 (interp_coeffs.first * deviatoric_vector_elem +
298 interp_coeffs.second * deviatoric_vector_neighbor) *
300 }
302 }
303
305}
306
307Real
310{
311 auto grad_contrib = bc->computeBoundaryGradientMatrixContribution();
312 // If the boundary condition does not include the diffusivity contribution then
313 // add it here.
315 {
316 const auto face_arg = singleSidedFaceArg(_current_face_info);
317 grad_contrib *= _mu(face_arg, determineState());
318 }
319
320 return grad_contrib;
321}
322
323Real
326{
327 const auto face_arg = singleSidedFaceArg(_current_face_info);
328 auto grad_contrib = bc->computeBoundaryGradientRHSContribution();
329 // If the boundary condition does not include the diffusivity contribution then
330 // add it here.
332 grad_contrib *= _mu(face_arg, determineState());
333
334 // We add the nonorthogonal corrector for the face here. Potential idea: we could do
335 // this in the boundary condition too. For now, however, we keep it like this.
337 {
338 // We support internal boundaries as well. In that case we have to decide on which side
339 // of the boundary we are on.
340 const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
343
344 // Unit vector to the boundary. Unfortunately, we have to recompute it because the value
345 // stored in the face info is only correct for external boundaries
346 const auto e_Cf = _current_face_info->faceCentroid() - elem_info->centroid();
347 const auto correction_vector =
348 _current_face_info->normal() - 1 / (_current_face_info->normal() * e_Cf) * e_Cf;
349
350 const auto state_arg = determineState();
351 mooseAssert(_gradient_field, "Gradient field should be registered when gradients are needed.");
352 grad_contrib += _mu(face_arg, state_arg) * _gradient_field->gradient(*elem_info) *
353 _boundary_normal_factor * correction_vector;
354 }
355
356 // Complete prescribed fluxes already include all applicable stress contributions.
358 {
359 // We might be on a face which is an internal boundary so we want to make sure we
360 // get the gradient from the right side.
361 const auto elem_info = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM)
364
365 const auto state_arg = determineState();
366
367 RealGradient grad_elem[3];
368 Real trace_elem = 0;
369 RealVectorValue deviatoric_vector_elem;
370
371 for (const auto dir : make_range(_dim))
372 {
373 grad_elem[dir] = velocityGradientField(dir).gradient(*elem_info);
374 trace_elem += grad_elem[dir](dir);
375 }
376
377 if (_coord_type == Moose::CoordinateSystemType::COORD_RZ)
378 {
379 const auto & radial_var = velocityVar(_rz_radial_coord);
380 const Real elem_value =
381 radial_var.getElemValue(*elem_info, state_arg) / elem_info->centroid()(_rz_radial_coord);
382 trace_elem += elem_value;
383 }
384
385 for (const auto dir : make_range(_dim))
386 {
387 grad_elem[dir](dir) -= 2. / 3 * trace_elem;
388 deviatoric_vector_elem(dir) = grad_elem[dir](_index);
389 }
390
391 // We support internal boundaries too so we have to make sure the normal points always outward
392 grad_contrib += _mu(face_arg, state_arg) * deviatoric_vector_elem * _boundary_normal_factor *
394 }
395
396 return grad_contrib;
397}
398
399Real
402{
403 const auto boundary_value_matrix_contrib = bc->computeBoundaryValueMatrixContribution();
404 return boundary_value_matrix_contrib * _face_mass_flux;
405}
406
407Real
410{
411 const auto boundary_value_rhs_contrib = bc->computeBoundaryValueRHSContribution();
412 return -boundary_value_rhs_contrib * _face_mass_flux;
413}
414
415void
417{
419
420 // Multiplier that ensures the normal of the boundary always points outwards, even in cases
421 // when the boundary is within the mesh.
422 _boundary_normal_factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0;
423
424 // Caching the mass flux on the face which will be reused in the advection term's matrix and
425 // right hand side contributions
427
428 if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
429 {
430 const auto state = determineState();
431 const auto & elem_info = *_current_face_info->elemInfo();
432 const auto & neighbor_info = *_current_face_info->neighborInfo();
433
434 const Real elem_value = _var.getElemValue(elem_info, state);
435 const Real neighbor_value = _var.getElemValue(neighbor_info, state);
436
438 {
439 mooseAssert(_advected_gradient_field,
440 "Gradient field should be registered when gradients are needed.");
443 }
444
446 elem_value,
447 neighbor_value,
451 }
452
453 // We'll have to set this to zero to make sure that we don't accumulate values over multiple
454 // faces. The matrix contribution should be fine.
456}
457
460{
461 mooseAssert(dir < _velocity_vars.size() && _velocity_vars[dir],
462 "Velocity variable for requested direction is not available.");
463 return *_velocity_vars[dir];
464}
465
468{
469 mooseAssert(dir < _velocity_gradient_fields.size() && _velocity_gradient_fields[dir],
470 "Velocity gradient field for requested direction is not available.");
471 return *_velocity_gradient_fields[dir];
472}
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 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.
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.
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
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.
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
static const std::string mu
Definition NS.h:127