https://mooseframework.inl.gov
INSFVTurbulentDiffusion.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 
11 #include "NavierStokesMethods.h"
12 
14 
17 {
19  params.addClassDescription(
20  "Computes residual for the turbulent scaled diffusion operator for finite volume method.");
21  params.addParam<MooseFunctorName>(
22  "scaling_coef", 1.0, "Scaling factor to divide the diffusion coefficient with");
23  params.addParam<std::vector<BoundaryName>>(
24  "walls", {}, "Boundaries that correspond to solid walls.");
25 
26  return params;
27 }
28 
30  : FVDiffusion(params),
31  _scaling_coef(getFunctor<ADReal>("scaling_coef")),
32  _wall_boundary_names(getParam<std::vector<BoundaryName>>("walls")),
33  _preserve_sparsity_pattern(_fe_problem.preserveMatrixSparsityPattern())
34 {
35 }
36 
37 void
39 {
43 }
44 
45 ADReal
47 {
48  using namespace Moose::FV;
49  const auto state = determineState();
50 
51  const auto dudn = gradUDotNormal(state, _correct_skewness);
52  ADReal coeff;
53  ADReal scaling_coef;
54 
55  // If we are on internal faces, we interpolate the diffusivity as usual
57  {
58  // If the diffusion coefficients are zero, then we can early return 0 (and avoid warnings if we
59  // have a harmonic interpolation)
60  const auto coeff_elem = _coeff(elemArg(), state);
61  const auto coeff_neighbor = _coeff(neighborArg(), state);
62  if (!coeff_elem.value() && !coeff_neighbor.value())
63  {
65  return 0;
66  else
67  // we return 0 but preserve the sparsity pattern of the Jacobian for Newton's method
68  return 0 * (coeff_elem + coeff_neighbor) *
69  (_scaling_coef(elemArg(), state) + _scaling_coef(neighborArg(), state)) * dudn;
70  }
71 
72  interpolate(_coeff_interp_method, coeff, coeff_elem, coeff_neighbor, *_face_info, true);
74  scaling_coef,
75  _scaling_coef(elemArg(), state),
76  _scaling_coef(neighborArg(), state),
77  *_face_info,
78  true);
79  }
80  // Else we just use the boundary values (which depend on how the diffusion
81  // coefficient is constructed)
82  else
83  {
84  const auto face = singleSidedFaceArg();
85  coeff = _coeff(face, state);
86  scaling_coef = _scaling_coef(face, state);
87  }
88 
89  return -1 * coeff / scaling_coef * dudn;
90 }
91 
92 void
94 {
95  if (skipForBoundary(fi))
96  return;
97 
98  _face_info = &fi;
99  _normal = fi.normal();
100  _face_type = _face_info->faceType(std::make_pair(_var.number(), _var.sys().number()));
102 
103  const Elem * elem = fi.elemPtr();
104  const Elem * neighbor = fi.neighborPtr();
105  const auto bounded_elem = _wall_bounded.find(elem) != _wall_bounded.end();
106  const auto bounded_neigh = _wall_bounded.find(neighbor) != _wall_bounded.end();
107 
110  (!bounded_elem))
111  {
112  // residual contribution of this kernel to the elem element
114  _local_re(0) = r;
116  }
119  (!bounded_neigh))
120  {
121  // residual contribution of this kernel to the neighbor element
123  _local_re(0) = -r;
125  }
126 }
127 
128 void
130 {
131  if (skipForBoundary(fi))
132  return;
133 
134  _face_info = &fi;
135  _normal = fi.normal();
136  _face_type = _face_info->faceType(std::make_pair(_var.number(), _var.sys().number()));
137  const ADReal r = fi.faceArea() * fi.faceCoord() * computeQpResidual();
138 
139  const Elem * elem = fi.elemPtr();
140  const Elem * neighbor = fi.neighborPtr();
141  const auto bounded_elem = _wall_bounded.find(elem) != _wall_bounded.end();
142  const auto bounded_neigh = _wall_bounded.find(neighbor) != _wall_bounded.end();
143 
146  (!bounded_elem))
147  {
148  mooseAssert(_var.dofIndices().size() == 1, "We're currently built to use CONSTANT MONOMIALS");
149 
151  _assembly, std::array<ADReal, 1>{{r}}, _var.dofIndices(), _var.scalingFactor());
152  }
153 
156  (!bounded_neigh))
157  {
159  (_var.dofIndices().size() == 0),
160  "If the variable is only defined on the neighbor hand side of the face, then that "
161  "means it should have no dof indices on the elem element. Conversely if "
162  "the variable is defined on both sides of the face, then it should have a non-zero "
163  "number of degrees of freedom on the elem element");
164 
165  // We switch the sign for the neighbor residual
166  ADReal neighbor_r = -r;
167 
168  mooseAssert(_var.dofIndicesNeighbor().size() == 1,
169  "We're currently built to use CONSTANT MONOMIALS");
170 
172  std::array<ADReal, 1>{{neighbor_r}},
174  _var.scalingFactor());
175  }
176 }
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const final
static InputParameters validParams()
virtual ADReal gradUDotNormal(const Moose::StateArg &time, const bool correct_skewness) const
void addResidualsAndJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
void accumulateTaggedLocalResidual()
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
INSFVTurbulentDiffusion implements a standard diffusion term for a turbulent problem: ...
Moose::ElemArg elemArg(bool correct_skewness=false) const
unsigned int number() const
void getWallBoundedElements(const std::vector< BoundaryName > &wall_boundary_name, const FEProblemBase &fe_problem, const SubProblem &subproblem, const std::set< SubdomainID > &block_ids, std::map< const Elem *, bool > &wall_bounded_map)
Map marking wall bounded elements The map passed in wall_bounded_map gets cleared and re-populated...
const FaceInfo * _face_info
Moose::StateArg determineState() const
auto raw_value(const Eigen::Map< T > &in)
const Moose::FV::InterpMethod _coeff_interp_method
Real & faceCoord()
virtual const std::set< SubdomainID > & blockIDs() const
RealVectorValue _normal
DualNumber< Real, DNDerivativeType, true > ADReal
Real faceArea() const
const bool _preserve_sparsity_pattern
Whether a Newton&#39;s method is being used (and we need to preserve the sparsity pattern in edge cases) ...
void computeJacobian() override
virtual bool skipForBoundary(const FaceInfo &fi) const
registerMooseObject("NavierStokesApp", INSFVTurbulentDiffusion)
bool isInternalFace(const FaceInfo &) const
virtual ADReal computeQpResidual() override final
const Elem * neighborPtr() const
const Moose::Functor< ADReal > & _scaling_coef
const bool _correct_skewness
INSFVTurbulentDiffusion(const InputParameters &params)
SubProblem & _subproblem
static InputParameters validParams()
const std::vector< BoundaryName > & _wall_boundary_names
Wall boundaries.
FEProblemBase & _fe_problem
const Point & normal() const
unsigned int number() const
virtual void initialSetup() override
std::map< const Elem *, bool > _wall_bounded
Maps for wall treatment.
FaceInfo::VarFaceNeighbors _face_type
Assembly & _assembly
const Elem * elemPtr() const
const Moose::Functor< ADReal > & _coeff
void prepareVectorTagNeighbor(Assembly &assembly, unsigned int ivar)
Moose::ElemArg neighborArg(bool correct_skewness=false) const
DenseVector< Number > _local_re
void addClassDescription(const std::string &doc_string)
Moose::FaceArg singleSidedFaceArg(const FaceInfo *fi=nullptr, Moose::FV::LimiterType limiter_type=Moose::FV::LimiterType::CentralDifference, bool correct_skewness=false, const Moose::StateArg *state_limiter=nullptr) const
MooseVariableFV< Real > & _var
void prepareVectorTag(Assembly &assembly, unsigned int ivar)
virtual void initialSetup()
void computeResidual() override
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
void scalingFactor(const std::vector< Real > &factor)
virtual const std::vector< dof_id_type > & dofIndices() const final
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const