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 "NSFVUtils.h"
13 #include "NavierStokesMethods.h"
14 #include "NS.h"
15 
17 
20 {
22  params.addClassDescription("Represents the matrix and right hand side contributions of an "
23  "advection term for a turbulence variable.");
24 
25  params.addRequiredParam<UserObjectName>(
26  "rhie_chow_user_object",
27  "The rhie-chow user-object which is used to determine the face velocity.");
28 
30 
31  params.addParam<std::vector<BoundaryName>>(
32  "walls", {}, "Boundaries that correspond to solid walls.");
33 
34  return params;
35 }
36 
38  : LinearFVFluxKernel(params),
39  _mass_flux_provider(getUserObject<RhieChowMassFlux>("rhie_chow_user_object")),
40  _advected_interp_coeffs(std::make_pair<Real, Real>(0, 0)),
41  _mass_face_flux(0.0),
42  _wall_boundary_names(getParam<std::vector<BoundaryName>>("walls"))
43 {
44  Moose::FV::setInterpolationMethod(*this, _advected_interp_method, "advected_interp_method");
45 }
46 
47 void
49 {
53 }
54 
55 void
57 {
58  // Coumputing bounding map
59  const Elem * elem = _current_face_info->elemPtr();
60  const auto bounded_elem = _wall_bounded.find(elem) != _wall_bounded.end();
61  const Elem * neighbor = _current_face_info->neighborPtr();
62  const auto bounded_neigh = _wall_bounded.find(neighbor) != _wall_bounded.end();
63 
64  // If we are on an internal face, we populate the four entries in the system matrix
65  // which touch the face
67  {
68  // The dof ids of the variable corresponding to the element and neighbor
71 
72  // Compute the entries which will go to the neighbor (offdiagonal) and element
73  // (diagonal).
74  const auto elem_matrix_contribution = computeElemMatrixContribution();
75  const auto neighbor_matrix_contribution = computeNeighborMatrixContribution();
76 
77  // Populate matrix
78  if (hasBlocks(_current_face_info->elemInfo()->subdomain_id()) && !(bounded_elem))
79  {
80  _matrix_contribution(0, 0) = elem_matrix_contribution;
81  _matrix_contribution(0, 1) = neighbor_matrix_contribution;
82  }
83 
84  if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id()) && !(bounded_neigh))
85  {
86  _matrix_contribution(1, 0) = -elem_matrix_contribution;
87  _matrix_contribution(1, 1) = -neighbor_matrix_contribution;
88  }
89  (*_linear_system.matrix).add_matrix(_matrix_contribution, _dof_indices.get_values());
90  }
91  // We are at a block boundary where the variable is not defined on one of the adjacent cells.
92  // We check if we have a boundary condition here
95  {
96  mooseAssert(_current_face_info->boundaryIDs().size() == 1,
97  "We should only have one boundary on every face.");
98 
99  LinearFVBoundaryCondition * bc_pointer =
101 
102  if (bc_pointer || _force_boundary_execution)
103  {
104  if (bc_pointer)
106  const auto matrix_contribution = computeBoundaryMatrixContribution(*bc_pointer);
107 
108  // We allow internal (for the mesh) boundaries too, so we have to check on which side we
109  // are on (assuming that this is a boundary for the variable)
110  if ((_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) && !(bounded_elem))
111  {
112  const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num];
113  (*_linear_system.matrix).add(dof_id_elem, dof_id_elem, matrix_contribution);
114  }
115  else if ((_current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) && !(bounded_neigh))
116  {
117  const auto dof_id_neighbor =
119  (*_linear_system.matrix).add(dof_id_neighbor, dof_id_neighbor, matrix_contribution);
120  }
121  }
122  }
123 }
124 
125 void
127 {
128  // Coumputing bounding map
129  const Elem * elem = _current_face_info->elemPtr();
130  const auto bounded_elem = _wall_bounded.find(elem) != _wall_bounded.end();
131  const Elem * neighbor = _current_face_info->neighborPtr();
132  const auto bounded_neigh = _wall_bounded.find(neighbor) != _wall_bounded.end();
133 
134  // If we are on an internal face, we populate the two entries in the right hand side
135  // which touch the face
137  {
138  // The dof ids of the variable corresponding to the element and neighbor
141 
142  // Compute the entries which will go to the neighbor and element positions.
143  const auto elem_rhs_contribution = computeElemRightHandSideContribution();
144  const auto neighbor_rhs_contribution = computeNeighborRightHandSideContribution();
145 
146  // Populate right hand side
147  if (hasBlocks(_current_face_info->elemInfo()->subdomain_id()) && !(bounded_elem))
148  _rhs_contribution(0) = elem_rhs_contribution;
149  if (hasBlocks(_current_face_info->neighborInfo()->subdomain_id()) && !(bounded_neigh))
150  _rhs_contribution(1) = neighbor_rhs_contribution;
151 
153  .add_vector(_rhs_contribution.get_values().data(), _dof_indices.get_values());
154  }
155  // We are at a block boundary where the variable is not defined on one of the adjacent cells.
156  // We check if we have a boundary condition here
159  {
160  mooseAssert(_current_face_info->boundaryIDs().size() == 1,
161  "We should only have one boundary on every face.");
162  LinearFVBoundaryCondition * bc_pointer =
164 
165  if (bc_pointer || _force_boundary_execution)
166  {
167  if (bc_pointer)
169 
170  const auto rhs_contribution = computeBoundaryRHSContribution(*bc_pointer);
171 
172  // We allow internal (for the mesh) boundaries too, so we have to check on which side we
173  // are on (assuming that this is a boundary for the variable)
174  if ((_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) && !(bounded_elem))
175  {
176  const auto dof_id_elem = _current_face_info->elemInfo()->dofIndices()[_sys_num][_var_num];
177  (*_linear_system.rhs).add(dof_id_elem, rhs_contribution);
178  }
179  else if ((_current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) && !(bounded_neigh))
180  {
181  const auto dof_id_neighbor =
183  (*_linear_system.rhs).add(dof_id_neighbor, rhs_contribution);
184  }
185  }
186  }
187 }
188 
189 Real
191 {
193 }
194 
195 Real
197 {
199 }
200 
201 Real
203 {
204  return 0.0;
205 }
206 
207 Real
209 {
210  return 0.0;
211 }
212 
213 Real
215 {
216  const auto * const adv_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
217  mooseAssert(adv_bc, "This should be a valid BC!");
218 
219  const auto boundary_value_matrix_contrib = adv_bc->computeBoundaryValueMatrixContribution();
220 
221  // We support internal boundaries too so we have to make sure the normal points always outward
222  const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0;
223 
224  return boundary_value_matrix_contrib * factor * _mass_face_flux * _current_face_area;
225 }
226 
227 Real
229 {
230  const auto * const adv_bc = static_cast<const LinearFVAdvectionDiffusionBC *>(&bc);
231  mooseAssert(adv_bc, "This should be a valid BC!");
232 
233  // We support internal boundaries too so we have to make sure the normal points always outward
234  const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0);
235 
236  const auto boundary_value_rhs_contrib = adv_bc->computeBoundaryValueRHSContribution();
237  return -boundary_value_rhs_contrib * factor * _mass_face_flux * _current_face_area;
238 }
239 
240 void
242 {
244 
245  // Caching the mass flux on the face which will be reused in the advection term's matrix and right
246  // hand side contributions
248 
249  // Caching the interpolation coefficients so they will be reused for the matrix and right hand
250  // side terms
253 }
virtual void addRightHandSideContribution() override
const unsigned int _var_num
SubProblem & _subproblem
virtual void addMatrixContribution() override
virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition &bc) override
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
const std::set< BoundaryID > & boundaryIDs() const
libMesh::LinearImplicitSystem & _linear_system
std::pair< Real, Real > interpCoeffs(const InterpMethod m, const FaceInfo &fi, const bool one_is_elem, const T &face_flux=0.0)
Real getMassFlux(const FaceInfo &fi) const
Get the face velocity times density (used in advection terms)
virtual void setupFaceData(const FaceInfo *face_info) override
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
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...
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
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
InputParameters advectedInterpolationParameter()
std::pair< Real, Real > _advected_interp_coeffs
Container for the current advected interpolation coefficients on the face to make sure we don&#39;t compu...
An advection kernel that implements the advection term for the turbulent variables limited for the fi...
const Elem * elemPtr() const
Moose::FV::InterpMethod _advected_interp_method
The interpolation method to use for the advected quantity.
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
SparseMatrix< Number > * matrix
static InputParameters validParams()
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
bool setInterpolationMethod(const MooseObject &obj, Moose::FV::InterpMethod &interp_method, const std::string &param_name)
virtual Real computeElemMatrixContribution() override
SubdomainID subdomain_id() const
DenseMatrix< Real > _matrix_contribution