https://mooseframework.inl.gov
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 
11 #include "MooseLinearVariableFV.h"
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 
51 void
53 {
57 }
58 
59 void
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
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  }
93  (*_linear_system.matrix).add_matrix(_matrix_contribution, _dof_indices.get_values());
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
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 
129 void
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
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
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 
193 Real
195 {
196  const auto & coeffs = _adv_interp_result.weights_matrix;
197  return coeffs.first * _mass_face_flux * _current_face_area;
198 }
199 
200 Real
202 {
203  const auto & coeffs = _adv_interp_result.weights_matrix;
204  return coeffs.second * _mass_face_flux * _current_face_area;
205 }
206 
207 Real
209 {
211 }
212 
213 Real
215 {
217 }
218 
219 Real
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 
233 Real
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 
246 void
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.
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 }
virtual void addRightHandSideContribution() override
const unsigned int _var_num
SubProblem & _subproblem
virtual void addMatrixContribution() override
virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition &bc) override
VectorValue< Real > _neighbor_grad_storage
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
const std::set< BoundaryID > & boundaryIDs() const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
libMesh::LinearImplicitSystem & _linear_system
Real getMassFlux(const FaceInfo &fi) const
Get the face velocity times density (used in advection terms)
virtual void setupFaceData(const FaceInfo *face_info) override
Moose::StateArg determineState() const
const ElemInfo * neighborInfo() const
void setupFaceData(const FaceInfo *face_info, const FaceInfo::VarFaceNeighbors face_type)
MooseLinearVariableFV< Real > & _var
virtual void setupFaceData(const FaceInfo *face_info)
NumericVector< Number > * rhs
const ElemInfo * elemInfo() const
virtual Moose::FV::GradientLimiterType gradientLimiter() const
LinearFVBoundaryCondition * getBoundaryCondition(const BoundaryID bd_id) const
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...
const FVAdvectedInterpolationMethod & _adv_interp_method
The interpolation method to use for the advected quantity.
virtual const std::set< SubdomainID > & blockIDs() const
virtual void initialSetup() override
Real _mass_face_flux
Container for the mass flux on the face which will be reused in the advection term&#39;s matrix and right...
FaceInfo::VarFaceNeighbors _current_face_type
void addRequiredParam(const std::string &name, const std::string &doc_string)
const bool _force_boundary_execution
DenseVector< Real > _rhs_contribution
VectorValue< Real > gradSln(const ElemInfo &elem_info, const StateArg &state) const
const std::vector< BoundaryName > & _wall_boundary_names
Wall boundaries.
virtual Real computeNeighborMatrixContribution() override
virtual Real computeBoundaryRHSContribution(const LinearFVBoundaryCondition &bc) override
static InputParameters validParams()
const FaceInfo * _current_face_info
const Elem * neighborPtr() 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
An advection kernel that implements the advection term for the turbulent variables limited for the fi...
const Elem * elemPtr() const
FVAdvectedInterpolationMethod::AdvectedSystemContribution _adv_interp_result
Cached weights/correction for the current face (refreshed in setupFaceData)
DenseVector< dof_id_type > _dof_indices
const std::vector< std::vector< dof_id_type > > & dofIndices() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual bool needsGradients() const
SparseMatrix< Number > * matrix
static InputParameters validParams()
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
VectorValue< Real > _elem_grad_storage
Reusable gradient storage used when advected interpolation requires gradients.
LinearFVTurbulentAdvection(const InputParameters &params)
void addClassDescription(const std::string &doc_string)
virtual Real computeNeighborRightHandSideContribution() override
registerMooseObject("NavierStokesApp", LinearFVTurbulentAdvection)
FEProblemBase & _fe_problem
const RhieChowMassFlux & _mass_flux_provider
The Rhie-Chow user object that provides us with the face velocity.
virtual Real computeElemRightHandSideContribution() override
bool hasBlocks(const SubdomainName &name) const
virtual void initialSetup()
std::unordered_set< const Elem * > _wall_bounded
List for wall bounded elements.
const unsigned int _sys_num
virtual Real computeElemMatrixContribution() override
SubdomainID subdomain_id() const
DenseMatrix< Real > _matrix_contribution