https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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{
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
37void
44
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);
73 interpolate(_coeff_interp_method,
74 scaling_coef,
75 _scaling_coef(elemArg(), state),
76 _scaling_coef(neighborArg(), state),
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
92void
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
108 if ((_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
109 _face_type == FaceInfo::VarFaceNeighbors::BOTH) &&
110 (!bounded_elem))
111 {
112 // residual contribution of this kernel to the elem element
114 _local_re(0) = r;
116 }
117 if ((_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
118 _face_type == FaceInfo::VarFaceNeighbors::BOTH) &&
119 (!bounded_neigh))
120 {
121 // residual contribution of this kernel to the neighbor element
123 _local_re(0) = -r;
125 }
126}
127
128void
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
144 if ((_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
145 _face_type == FaceInfo::VarFaceNeighbors::BOTH) &&
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
154 if ((_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
155 _face_type == FaceInfo::VarFaceNeighbors::BOTH) &&
156 (!bounded_neigh))
157 {
158 mooseAssert((_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR) ==
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}},
175 }
176}
DualNumber< Real, DNDerivativeType, true > ADReal
registerMooseObject("NavierStokesApp", INSFVTurbulentDiffusion)
virtual const std::set< SubdomainID > & blockIDs() const
const bool _correct_skewness
static InputParameters validParams()
const Moose::FV::InterpMethod _coeff_interp_method
const Moose::Functor< ADReal > & _coeff
Moose::ElemArg neighborArg(bool correct_skewness=false) const
Moose::ElemArg elemArg(bool correct_skewness=false) const
RealVectorValue _normal
virtual bool skipForBoundary(const FaceInfo &fi) const
MooseVariableFV< Real > & _var
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
virtual ADReal gradUDotNormal(const Moose::StateArg &time, const bool correct_skewness) const
const FaceInfo * _face_info
FaceInfo::VarFaceNeighbors _face_type
const Point & normal() const
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const
const Elem * neighborPtr() const
Real faceArea() const
Real & faceCoord()
const Elem * elemPtr() const
INSFVTurbulentDiffusion implements a standard diffusion term for a turbulent problem:
static InputParameters validParams()
const std::vector< BoundaryName > & _wall_boundary_names
Wall boundaries.
const bool _preserve_sparsity_pattern
Whether a Newton's method is being used (and we need to preserve the sparsity pattern in edge cases)
void computeResidual() override
void computeJacobian() override
std::unordered_set< const Elem * > _wall_bounded
List for wall treatment.
const Moose::Functor< ADReal > & _scaling_coef
virtual ADReal computeQpResidual() override final
INSFVTurbulentDiffusion(const InputParameters &params)
virtual void initialSetup() override
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 scalingFactor(const std::vector< Real > &factor)
SystemBase & sys()
unsigned int number() const
virtual const std::vector< dof_id_type > & dofIndices() const final
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const final
bool isInternalFace(const FaceInfo &) const
Assembly & _assembly
SubProblem & _subproblem
FEProblemBase & _fe_problem
virtual void initialSetup()
unsigned int number() const
void accumulateTaggedLocalResidual()
void addResidualsAndJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
void prepareVectorTagNeighbor(Assembly &assembly, unsigned int ivar)
void prepareVectorTag(Assembly &assembly, unsigned int ivar)
DenseVector< Number > _local_re
Moose::StateArg determineState() const
auto raw_value(const Eigen::Map< T > &in)
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.