https://mooseframework.inl.gov
Loading...
Searching...
No Matches
LinearFVTurbulentAdvection.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://www.mooseframework.org
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 "NavierStokesMethods.h"
13#include "NS.h"
14
16
19{
21 params.addClassDescription("Represents the matrix and right hand side contributions of an "
22 "advection term for a turbulence variable.");
23
24 params.addRequiredParam<UserObjectName>(
25 "rhie_chow_user_object",
26 "The rhie-chow user-object which is used to determine the face velocity.");
27
28 params.addRequiredParam<InterpolationMethodName>(
29 "advected_interp_method_name",
30 "Name of the FVInterpolationMethod to use for the advected quantity.");
31
32 params.addParam<std::vector<BoundaryName>>(
33 "walls", {}, "Boundaries that correspond to solid walls.");
34
35 return params;
36}
37
39 : LinearFVFluxKernel(params),
41 _mass_flux_provider(getUserObject<RhieChowMassFlux>("rhie_chow_user_object")),
42 _adv_interp_method(getFVAdvectedInterpolationMethod(
43 getParam<InterpolationMethodName>("advected_interp_method_name"))),
44 _mass_face_flux(0.0),
45 _wall_boundary_names(getParam<std::vector<BoundaryName>>("walls"))
46{
49}
50
51void
58
59void
61{
62 // Coumputing bounding map
63 const Elem * elem = _current_face_info->elemPtr();
64 const auto bounded_elem = _wall_bounded.find(elem) != _wall_bounded.end();
65 const Elem * neighbor = _current_face_info->neighborPtr();
66 const auto bounded_neigh = _wall_bounded.find(neighbor) != _wall_bounded.end();
67
68 // If we are on an internal face, we populate the four entries in the system matrix
69 // which touch the face
70 if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
71 {
72 // The dof ids of the variable corresponding to the element and neighbor
75
76 // Compute the entries which will go to the neighbor (offdiagonal) and element
77 // (diagonal).
78 const auto elem_matrix_contribution = computeElemMatrixContribution();
79 const auto neighbor_matrix_contribution = computeNeighborMatrixContribution();
80
81 // Populate matrix
82 if (hasBlocks(_current_face_info->elemInfo()->subdomain_id()) && !(bounded_elem))
83 {
84 _matrix_contribution(0, 0) = elem_matrix_contribution;
85 _matrix_contribution(0, 1) = neighbor_matrix_contribution;
86 }
87
88 if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id()) && !(bounded_neigh))
89 {
90 _matrix_contribution(1, 0) = -elem_matrix_contribution;
91 _matrix_contribution(1, 1) = -neighbor_matrix_contribution;
92 }
94 }
95 // We are at a block boundary where the variable is not defined on one of the adjacent cells.
96 // We check if we have a boundary condition here
97 else if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
98 _current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR)
99 {
100 mooseAssert(_current_face_info->boundaryIDs().size() == 1,
101 "We should only have one boundary on every face.");
102
103 LinearFVBoundaryCondition * bc_pointer =
105
106 if (bc_pointer || _force_boundary_execution)
107 {
108 if (bc_pointer)
110 const auto matrix_contribution = computeBoundaryMatrixContribution(*bc_pointer);
111
112 // We allow internal (for the mesh) boundaries too, so we have to check on which side we
113 // are on (assuming that this is a boundary for the variable)
114 if ((_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) && !(bounded_elem))
115 {
116 const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num];
117 (*_linear_system.matrix).add(dof_id_elem, dof_id_elem, matrix_contribution);
118 }
119 else if ((_current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) && !(bounded_neigh))
120 {
121 const auto dof_id_neighbor =
123 (*_linear_system.matrix).add(dof_id_neighbor, dof_id_neighbor, matrix_contribution);
124 }
125 }
126 }
127}
128
129void
131{
132 // Coumputing bounding map
133 const Elem * elem = _current_face_info->elemPtr();
134 const auto bounded_elem = _wall_bounded.find(elem) != _wall_bounded.end();
135 const Elem * neighbor = _current_face_info->neighborPtr();
136 const auto bounded_neigh = _wall_bounded.find(neighbor) != _wall_bounded.end();
137
138 // If we are on an internal face, we populate the two entries in the right hand side
139 // which touch the face
140 if (_current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
141 {
142 // The dof ids of the variable corresponding to the element and neighbor
145
146 // Compute the entries which will go to the neighbor and element positions.
147 const auto elem_rhs_contribution = computeElemRightHandSideContribution();
148 const auto neighbor_rhs_contribution = computeNeighborRightHandSideContribution();
149
150 // Populate right hand side
151 if (hasBlocks(_current_face_info->elemInfo()->subdomain_id()) && !(bounded_elem))
152 _rhs_contribution(0) = elem_rhs_contribution;
153 if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id()) && !(bounded_neigh))
154 _rhs_contribution(1) = neighbor_rhs_contribution;
155
157 .add_vector(_rhs_contribution.get_values().data(), _dof_indices.get_values());
158 }
159 // We are at a block boundary where the variable is not defined on one of the adjacent cells.
160 // We check if we have a boundary condition here
161 else if (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
162 _current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR)
163 {
164 mooseAssert(_current_face_info->boundaryIDs().size() == 1,
165 "We should only have one boundary on every face.");
166 LinearFVBoundaryCondition * bc_pointer =
168
169 if (bc_pointer || _force_boundary_execution)
170 {
171 if (bc_pointer)
173
174 const auto rhs_contribution = computeBoundaryRHSContribution(*bc_pointer);
175
176 // We allow internal (for the mesh) boundaries too, so we have to check on which side we
177 // are on (assuming that this is a boundary for the variable)
178 if ((_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) && !(bounded_elem))
179 {
180 const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num];
181 (*_linear_system.rhs).add(dof_id_elem, rhs_contribution);
182 }
183 else if ((_current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) && !(bounded_neigh))
184 {
185 const auto dof_id_neighbor =
187 (*_linear_system.rhs).add(dof_id_neighbor, rhs_contribution);
188 }
189 }
190 }
191}
192
193Real
199
200Real
206
207Real
212
213Real
218
219Real
221{
222 const auto * const adv_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
223 mooseAssert(adv_bc, "This should be a valid BC!");
224
225 const auto boundary_value_matrix_contrib = adv_bc->computeBoundaryValueMatrixContribution();
226
227 // We support internal boundaries too so we have to make sure the normal points always outward
228 const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0;
229
230 return boundary_value_matrix_contrib * factor * _mass_face_flux * _current_face_area;
231}
232
233Real
235{
236 const auto * const adv_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
237 mooseAssert(adv_bc, "This should be a valid BC!");
238
239 // We support internal boundaries too so we have to make sure the normal points always outward
240 const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0);
241
242 const auto boundary_value_rhs_contrib = adv_bc->computeBoundaryValueRHSContribution();
243 return -boundary_value_rhs_contrib * factor * _mass_face_flux * _current_face_area;
244}
245
246void
248{
250
251 // Caching the mass flux on the face which will be reused in the advection term's matrix and right
252 // hand side contributions
254
255 // Only internal faces need advected interpolation results; boundary contributions are handled
256 // through the linear FV boundary conditions.
257 if (_current_face_type != FaceInfo::VarFaceNeighbors::BOTH)
258 return;
259
260 const auto state = determineState();
261 const auto & elem_info = *_current_face_info->elemInfo();
262 const auto & neighbor_info = *_current_face_info->neighborInfo();
263
264 const Real elem_value = _var.getElemValue(elem_info, state);
265 const Real neighbor_value = _var.getElemValue(neighbor_info, state);
267 {
268 const auto limiter_type = _adv_interp_method.gradientLimiter();
269 _elem_grad_storage = _var.gradSln(elem_info, state, limiter_type);
270 _neighbor_grad_storage = _var.gradSln(neighbor_info, state, limiter_type);
271 }
272
274 elem_value,
275 neighbor_value,
279}
registerMooseObject("NavierStokesApp", LinearFVTurbulentAdvection)
bool hasBlocks(const SubdomainName &name) const
virtual const std::set< SubdomainID > & blockIDs() const
SubdomainID subdomain_id() const
const std::vector< std::vector< dof_id_type > > & dofIndices() const
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
const std::set< BoundaryID > & boundaryIDs() const
const Elem * neighborPtr() const
const ElemInfo * elemInfo() const
const ElemInfo * neighborInfo() const
const Elem * elemPtr() 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)
void setupFaceData(const FaceInfo *face_info, const FaceInfo::VarFaceNeighbors face_type)
FaceInfo::VarFaceNeighbors _current_face_type
DenseMatrix< Real > _matrix_contribution
virtual void setupFaceData(const FaceInfo *face_info)
DenseVector< Real > _rhs_contribution
DenseVector< dof_id_type > _dof_indices
const bool _force_boundary_execution
const FaceInfo * _current_face_info
static InputParameters validParams()
MooseLinearVariableFV< Real > & _var
const unsigned int _sys_num
const unsigned int _var_num
An advection kernel that implements the advection term for the turbulent variables limited for the fi...
virtual Real computeNeighborRightHandSideContribution() override
virtual Real computeElemRightHandSideContribution() override
const RhieChowMassFlux & _mass_flux_provider
The Rhie-Chow user object that provides us with the face velocity.
virtual Real computeNeighborMatrixContribution() override
virtual void addRightHandSideContribution() override
VectorValue< Real > _elem_grad_storage
Reusable gradient storage used when advected interpolation requires gradients.
const std::vector< BoundaryName > & _wall_boundary_names
Wall boundaries.
virtual Real computeBoundaryRHSContribution(const LinearFVBoundaryCondition &bc) override
virtual void addMatrixContribution() override
const FVAdvectedInterpolationMethod & _adv_interp_method
The interpolation method to use for the advected quantity.
virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition &bc) override
virtual Real computeElemMatrixContribution() override
FVAdvectedInterpolationMethod::AdvectedSystemContribution _adv_interp_result
Cached weights/correction for the current face (refreshed in setupFaceData)
LinearFVTurbulentAdvection(const InputParameters &params)
std::unordered_set< const Elem * > _wall_bounded
List for wall bounded elements.
Real _mass_face_flux
Container for the mass flux on the face which will be reused in the advection term's matrix and right...
virtual void setupFaceData(const FaceInfo *face_info) override
static InputParameters validParams()
FEProblemBase & _fe_problem
libMesh::LinearImplicitSystem & _linear_system
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
LinearFVBoundaryCondition * getBoundaryCondition(const BoundaryID bd_id) 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)
virtual void initialSetup()
SubProblem & _subproblem
Moose::StateArg determineState() const
std::vector< T > & get_values()
NumericVector< Number > * rhs
SparseMatrix< Number > * matrix
void getWallBoundedElements(const std::vector< BoundaryName > &wall_boundary_name, const FEProblemBase &fe_problem, const SubProblem &subproblem, const std::set< SubdomainID > &block_ids, std::unordered_set< const Elem * > &wall_bounded)
Map marking wall bounded elements The map passed in wall_bounded_map gets cleared and re-populated.