https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FVFluxKernel.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
10#include "FVFluxKernel.h"
11
12#include "MooseVariableFV.h"
13#include "SystemBase.h"
14#include "MooseMesh.h"
15#include "ADUtils.h"
16#include "RelationshipManager.h"
17
18#include "libmesh/elem.h"
19#include "libmesh/system.h"
20
23{
26 params.registerSystemAttributeName("FVFluxKernel");
27 params.addParam<bool>("force_boundary_execution",
28 false,
29 "Whether to force execution of this object on all external boundaries.");
30 params.addParam<std::vector<BoundaryName>>(
31 "boundaries_to_force",
32 std::vector<BoundaryName>(),
33 "The set of sidesets to force execution of this FVFluxKernel on. "
34 "Setting force_boundary_execution to true is equivalent to listing all external "
35 "mesh boundaries in this parameter.");
36 params.addParam<std::vector<BoundaryName>>(
37 "boundaries_to_avoid",
38 std::vector<BoundaryName>(),
39 "The set of sidesets to not execute this FVFluxKernel on. "
40 "This takes precedence over force_boundary_execution to restrict to less external boundaries."
41 " By default flux kernels are executed on all internal boundaries and Dirichlet boundary "
42 "conditions.");
43
44 params.addParamNamesToGroup("force_boundary_execution boundaries_to_force boundaries_to_avoid",
45 "Boundary execution modification");
46 return params;
47}
48
50 : FVKernel(params),
51 TwoMaterialPropertyInterface(this, blockIDs(), {}),
55 this, false, false, /*is_fv=*/true),
56 _var(*mooseVariableFV()),
57 _force_boundary_execution(getParam<bool>("force_boundary_execution"))
58{
59 addMooseVariableDependency(&_var);
60
61 const auto & vec = getParam<std::vector<BoundaryName>>("boundaries_to_force");
62 for (const auto & name : vec)
63 _boundaries_to_force.insert(_mesh.getBoundaryID(name));
64
65 const auto & avoid_vec = getParam<std::vector<BoundaryName>>("boundaries_to_avoid");
66 for (const auto & name : avoid_vec)
67 {
68 const auto bid = _mesh.getBoundaryID(name);
69 _boundaries_to_avoid.insert(bid);
70 if (_boundaries_to_force.find(bid) != _boundaries_to_force.end())
71 paramError(
72 "boundaries_to_avoid",
73 "A boundary may not be specified in both boundaries_to_avoid and boundaries_to_force");
74 }
75}
76
77bool
79{
80 return Moose::FV::onBoundary(*this, fi);
81}
82
83// Note the lack of quadrature point loops in the residual/jacobian compute
84// functions. This is because finite volumes currently only works with
85// constant monomial elements. We only have one quadrature point regardless of
86// problem dimension and just multiply by the face area.
87
88bool
90{
91 // Boundaries to avoid come first, since they are always obeyed
92 if (avoidBoundary(fi))
93 return true;
94
95 // We get this to check if we are on a kernel boundary or not
96 const bool on_boundary = onBoundary(fi);
97
98 // We are either on a kernel boundary or on an internal sideset
99 // which is handled as a boundary
100 if (on_boundary || !fi.boundaryIDs().empty())
101 {
102 // Blanket forcing on boundary
104 return false;
105
106 // Selected boundaries to force
107 for (const auto bnd_to_force : _boundaries_to_force)
108 if (fi.boundaryIDs().count(bnd_to_force))
109 return false;
110
111 // If we have a flux boundary on this face, we skip. This
112 // should be relatively easy to check with the cached maps.
113 if (_var.getFluxBCs(fi).first)
114 return true;
115
116 // If we have a dirichlet BC, we are not skipping
117 if (_var.getDirichletBC(fi).first)
118 return false;
119 }
120
121 // The last question is: are we on the inside or on the outside? If we are on an internal
122 // face we dont skip, otherwise we assume a natural BC and skip
123 return on_boundary;
124}
125
126void
128{
129 if (skipForBoundary(fi))
130 return;
131
132 _face_info = &fi;
133 _normal = fi.normal();
134 _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
136
137 // residual contributions for a flux kernel go to both neighboring faces.
138 // They are equal in magnitude but opposite in direction due to the outward
139 // facing unit normals of the face for each neighboring elements being
140 // oriented oppositely. We calculate the residual contribution once using
141 // the lower-id-elem-oriented _normal and just use the resulting residual's
142 // negative for the contribution to the neighbor element.
143
144 // The fancy face type if condition checks here are because we might
145 // currently be running on a face for which this kernel's variable is only
146 // defined on one side. If this is the case, we need to only calculate+add
147 // the residual contribution if there is a dirichlet bc for the active
148 // face+variable. We always need to add the residual contribution when the
149 // variable is defined on both sides of the face. If the variable is only
150 // defined on one side and there is NOT a dirichlet BC, then there is either
151 // a flux BC or a natural BC - in either of those cases we don't want to add
152 // any residual contributions from regular flux kernels.
155 {
156 // residual contribution of this kernel to the elem element
158 _local_re(0) = r;
160 }
163 {
164 // residual contribution of this kernel to the neighbor element
166 _local_re(0) = -r;
168 }
169}
170
171void
173{
174 if (skipForBoundary(fi))
175 return;
176
177 _face_info = &fi;
178 _normal = fi.normal();
179 _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
180 const ADReal r = fi.faceArea() * fi.faceCoord() * computeQpResidual();
181
182 // The fancy face type if condition checks here are because we might
183 // currently be running on a face for which this kernel's variable is only
184 // defined on one side. If this is the case, we need to only calculate+add
185 // the jacobian contribution if there is a dirichlet bc for the active
186 // face+variable. We always need to add the jacobian contribution when the
187 // variable is defined on both sides of the face. If the variable is only
188 // defined on one side and there is NOT a dirichlet BC, then there is either
189 // a flux BC or a natural BC - in either of those cases we don't want to add
190 // any jacobian contributions from regular flux kernels.
193 {
194 mooseAssert(_var.dofIndices().size() == 1, "We're currently built to use CONSTANT MONOMIALS");
195
197 _assembly, std::array<ADReal, 1>{{r}}, _var.dofIndices(), _var.scalingFactor());
198 }
199
202 {
204 (_var.dofIndices().size() == 0),
205 "If the variable is only defined on the neighbor hand side of the face, then that "
206 "means it should have no dof indices on the elem element. Conversely if "
207 "the variable is defined on both sides of the face, then it should have a non-zero "
208 "number of degrees of freedom on the elem element");
209
210 // We switch the sign for the neighbor residual
211 ADReal neighbor_r = -r;
212
213 mooseAssert(_var.dofIndicesNeighbor().size() == 1,
214 "We're currently built to use CONSTANT MONOMIALS");
215
217 std::array<ADReal, 1>{{neighbor_r}},
220 }
221}
222
223void
228
229ADReal
230FVFluxKernel::gradUDotNormal(const Moose::StateArg & time, const bool correct_skewness) const
231{
232 mooseAssert(_face_info, "the face info should be non-null");
233 return Moose::FV::gradUDotNormal(*_face_info, _var, time, correct_skewness);
234}
235
237FVFluxKernel::elemArg(const bool correct_skewness) const
238{
239 mooseAssert(_face_info, "the face info should be non-null");
240 return {_face_info->elemPtr(), correct_skewness};
241}
242
244FVFluxKernel::neighborArg(const bool correct_skewness) const
245{
246 mooseAssert(_face_info, "the face info should be non-null");
247 return {_face_info->neighborPtr(), correct_skewness};
248}
249
252 const Moose::FV::LimiterType limiter_type,
253 const bool correct_skewness,
254 const Moose::StateArg * state_limiter) const
255{
256 if (!fi)
257 fi = _face_info;
258
259 return makeFace(*fi, limiter_type, true, correct_skewness, state_limiter);
260}
261
262bool
264{
265 for (const auto bnd_id : fi.boundaryIDs())
266 if (_boundaries_to_avoid.count(bnd_id))
267 return true;
268 return false;
269}
270
271void
273{
274 mooseError("FVFluxKernel residual/Jacobian evaluation requires a face information object");
275}
276
277void
279{
280 mooseError("FVFluxKernel residual/Jacobian evaluation requires a face information object");
281}
282
283void
285{
286 mooseError("FVFluxKernel residual/Jacobian evaluation requires a face information object");
287}
288
289bool
290FVFluxKernel::hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const
291{
292 if (fi_elem_side)
293 return hasBlocks(fi.elem().subdomain_id());
294 else
295 return fi.neighborPtr() && hasBlocks(fi.neighbor().subdomain_id());
296}
DualNumber< Real, DNDerivativeType, true > ADReal
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
bool hasBlocks(const SubdomainName &name) const
Test if the supplied block name is valid for this object.
Moose::ElemArg neighborArg(bool correct_skewness=false) const
bool hasFaceSide(const FaceInfo &fi, const bool fi_elem_side) const override
virtual ADReal computeQpResidual()=0
This is the primary function that must be implemented for flux kernel terms.
const bool _force_boundary_execution
Whether to force execution of flux kernels on all external boundaries.
Moose::ElemArg elemArg(bool correct_skewness=false) const
static InputParameters validParams()
RealVectorValue _normal
This is the outward unit normal vector for the face the kernel is currently operating on.
void computeJacobian() override
Compute this object's contribution to the diagonal Jacobian entries.
virtual bool skipForBoundary(const FaceInfo &fi) const
Kernels are called even on boundaries in case one is for a variable with a dirichlet BC - in which ca...
FVFluxKernel(const InputParameters &params)
bool onBoundary(const FaceInfo &fi) const
Return whether the supplied face is on a boundary of this object's execution.
MooseVariableFV< Real > & _var
bool avoidBoundary(const FaceInfo &fi) const
Returns whether to avoid execution on a boundary.
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
Determine the single sided face argument when evaluating a functor on a face.
virtual ADReal gradUDotNormal(const Moose::StateArg &time, const bool correct_skewness) const
Calculates and returns "grad_u dot normal" on the face to be used for diffusive terms.
void computeResidual() override
Compute this object's contribution to the residual.
std::unordered_set< BoundaryID > _boundaries_to_avoid
Which boundaries/sidesets to prevent the execution of flux kernels on.
void computeResidualAndJacobian() override
Compute this object's contribution to the residual and Jacobian simultaneously.
const FaceInfo * _face_info
This is holds meta-data for geometric information relevant to the current face including elem+neighbo...
std::unordered_set< BoundaryID > _boundaries_to_force
Which boundaries/sidesets to force the execution of flux kernels on.
FaceInfo::VarFaceNeighbors _face_type
The face type.
FVKernel is a base class for all finite volume method kernels.
Definition FVKernel.h:36
static InputParameters validParams()
Definition FVKernel.C:15
Moose::FaceArg makeFace(const FaceInfo &fi, const Moose::FV::LimiterType limiter_type, const bool elem_is_upwind, const bool correct_skewness=false, const Moose::StateArg *state_limiter=nullptr) const
Create a functor face argument from provided component arguments.
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition FaceInfo.h:38
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face's elem element.
Definition FaceInfo.h:72
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const
Returns which side(s) the given variable-system number pair is defined on for this face.
Definition FaceInfo.h:229
const std::set< BoundaryID > & boundaryIDs() const
Const getter for every associated boundary ID.
Definition FaceInfo.h:124
const Elem & elem() const
Definition FaceInfo.h:85
const Elem * neighborPtr() const
Definition FaceInfo.h:88
Real faceArea() const
Returns the face area of face id.
Definition FaceInfo.h:64
Real & faceCoord()
Sets/gets the coordinate transformation factor (for e.g.
Definition FaceInfo.h:68
const Elem * elemPtr() const
Definition FaceInfo.h:86
const Elem & neighbor() const
Definition FaceInfo.h:220
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void registerSystemAttributeName(const std::string &value)
This method is used to define the MOOSE system name that is used by the TheWarehouse object for stori...
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void scalingFactor(const std::vector< Real > &factor)
Set the scaling factor for this variable.
SystemBase & sys()
Get the system this variable is part of.
unsigned int number() const
Get variable number coming from libMesh.
virtual const std::vector< dof_id_type > & dofIndices() const final
Get local DoF indices.
std::pair< bool, std::vector< const FVFluxBC * > > getFluxBCs(const FaceInfo &fi) const
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const final
Get neighbor DOF indices for currently selected element.
std::pair< bool, const FVDirichletBCBase * > getDirichletBC(const FaceInfo &fi) const
Intermediate base class that ties together all the interfaces for getting MooseVariables with the Moo...
Enhances MooseVariableInterface interface provide values from neighbor elements.
Assembly & _assembly
Reference to this Kernel's assembly object.
unsigned int number() const
Gets the number of this system.
void accumulateTaggedLocalResidual()
Local residual blocks will be appended by adding the current local kernel residual.
void addResidualsAndJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
Add the provided incoming residuals and derivatives for the Jacobian, corresponding to the provided d...
void prepareVectorTagNeighbor(Assembly &assembly, unsigned int ivar)
Prepare data for computing element residual the according to active tags for DG and interface kernels...
void prepareVectorTag(Assembly &assembly, unsigned int ivar)
Prepare data for computing element residual according to active tags.
DenseVector< Number > _local_re
Holds local residual entries as they are accumulated by this Kernel.
This interface is designed for DGKernel, InternalSideUserObject, InterfaceUserObject,...
auto raw_value(const Eigen::Map< T > &in)
ADReal gradUDotNormal(const FaceInfo &face_info, const MooseVariableFV< Real > &fv_var, const Moose::StateArg &time, bool correct_skewness=false)
Calculates and returns "grad_u dot normal" on the face to be used for diffusive terms.
Definition MathFVUtils.C:18
bool onBoundary(const SubdomainRestrictable &obj, const FaceInfo &fi)
Return whether the supplied face is on a boundary of the object's execution.
@ VAR_FIELD_STANDARD
Definition MooseTypes.h:777
@ VAR_SOLVER
Definition MooseTypes.h:770
A structure that is used to evaluate Moose functors logically at an element/cell center.
A structure defining a "face" evaluation calling argument for Moose functors.
State argument for evaluating functors.