https://mooseframework.inl.gov
Loading...
Searching...
No Matches
BernoulliPressureVariable.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 "NS.h"
12#include "NSFVUtils.h"
13
15
18{
21 params.addRequiredParam<MooseFunctorName>("u", "The x-component of velocity");
22 params.addParam<MooseFunctorName>("v", 0, "The y-component of velocity");
23 params.addParam<MooseFunctorName>("w", 0, "The z-component of velocity");
24 params.addRequiredParam<MooseFunctorName>(NS::porosity, "The porosity");
25 params.addRequiredParam<MooseFunctorName>(NS::density, "The density");
26 params.addParam<std::vector<BoundaryName>>(
27 "pressure_drop_sidesets", {}, "Sidesets over which form loss coefficients are to be applied");
28 params.addParam<std::vector<Real>>(
29 "pressure_drop_form_factors",
30 {},
31 "User-supplied form loss coefficients to be applied over the sidesets listed above");
32 params.addParam<bool>(
33 "allow_two_term_expansion_on_bernoulli_faces",
34 false,
35 "Switch to enable the two-term extrapolation on porosity jump faces. "
36 "WARNING: This might lead to crushes in parallel runs if porosity jump faces are connected "
37 "with one cell (usually corners) due to the insufficient number of ghosted "
38 "layers.");
39
40 // Assuming that this variable is used for advection problems, due to the
41 // utilization of the pressure gradient in the advecting velocity
42 // through the Rhie-Chow interpolation, we have to extend the ghosted layers.
43 params.addRelationshipManager(
44 "ElementSideNeighborLayers",
45 Moose::RelationshipManagerType::GEOMETRIC | Moose::RelationshipManagerType::ALGEBRAIC |
46 Moose::RelationshipManagerType::COUPLING,
47 [](const InputParameters & /*obj_params*/, InputParameters & rm_params)
48 { rm_params.set<unsigned short>("layers") = 3; });
49 return params;
50}
51
53 : INSFVPressureVariable(params),
55 _u(nullptr),
56 _v(nullptr),
57 _w(nullptr),
58 _eps(nullptr),
59 _rho(nullptr),
60 _pressure_drop_sidesets(getParam<std::vector<BoundaryName>>("pressure_drop_sidesets")),
61 _pressure_drop_sideset_ids(this->_mesh.getBoundaryIDs(_pressure_drop_sidesets)),
62 _pressure_drop_form_factors(getParam<std::vector<Real>>("pressure_drop_form_factors")),
63 _allow_two_term_expansion_on_bernoulli_faces(
64 getParam<bool>("allow_two_term_expansion_on_bernoulli_faces"))
65{
67 _face_interp_method == Moose::FV::InterpMethod::SkewCorrectedAverage)
69 "allow_two_term_expansion_on_bernoulli_faces",
70 "Skewness correction with two term extrapolation on Bernoulli faces is not supported!");
71
73 paramError("pressure_drop_sidesets",
74 "The number of sidesets and the number of supplied form losses are not equal!");
75}
76
77void
79{
80 _u = &getFunctor<ADReal>("u", _subproblem);
81 _v = &getFunctor<ADReal>("v", _subproblem);
82 _w = &getFunctor<ADReal>("w", _subproblem);
83 _eps = &getFunctor<ADReal>(NS::porosity, _subproblem);
84 _rho = &getFunctor<ADReal>(NS::density, _subproblem);
85
87}
88
89std::pair<bool, ADRealVectorValue>
91 const FaceInfo & fi,
92 const Moose::StateArg & time) const
93{
94 const Moose::FaceArg face{
95 &fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
96
97 const VectorValue<ADReal> vel_face{(*_u)(face, time), (*_v)(face, time), (*_w)(face, time)};
98 const bool fi_elem_is_upwind = vel_face * fi.normal() > 0;
99 const bool elem_is_upwind = &elem == &fi.elem() ? fi_elem_is_upwind : !fi_elem_is_upwind;
100
101 return {elem_is_upwind, vel_face};
102}
103
104bool
106 const Elem * const elem,
107 const Moose::StateArg & time) const
108{
109 if (isDirichletBoundaryFace(fi, elem, time))
110 return false;
111 if (!isInternalFace(fi))
112 // We are neither a Dirichlet nor an internal face
113 return true;
114
115 if (isSeparatorBoundary(fi))
116 return true;
117
118 if (std::get<0>(NS::isPorosityJumpFace(*_eps, fi, time)))
119 // We choose to extrapolate for the element that is downwind
120 return !std::get<0>(elemIsUpwind(*elem, fi, time));
121
122 return false;
123}
124
125bool
127 const Elem * const elem,
128 const Moose::StateArg & time) const
129{
131 return true;
132
133 if (isInternalFace(fi))
134 {
135 if (isSeparatorBoundary(fi))
136 return false;
137
138 if (std::get<0>(NS::isPorosityJumpFace(*_eps, fi, time)))
139 // We choose to apply the Dirichlet condition for the upwind element
140 return std::get<0>(elemIsUpwind(*elem, fi, time));
141 }
142
143 return false;
144}
145
146ADReal
148 const Elem * const elem,
149 const Moose::StateArg & time) const
150{
151 mooseAssert(isDirichletBoundaryFace(fi, elem, time), "This better be a Dirichlet face");
152
155
156 const auto [is_jump_face, eps_elem, eps_neighbor] = NS::isPorosityJumpFace(*_eps, fi, time);
157#ifndef NDEBUG
158 mooseAssert(is_jump_face,
159 "If we are not a traditional Dirichlet face, then we must be a jump face");
160#else
161 libmesh_ignore(is_jump_face);
162#endif
163
164 const Moose::FaceArg face_elem{
165 &fi, Moose::FV::LimiterType::CentralDifference, true, false, &fi.elem(), nullptr};
166 const Moose::FaceArg face_neighbor{
167 &fi, Moose::FV::LimiterType::CentralDifference, true, false, fi.neighborPtr(), nullptr};
168
169 const auto [elem_is_upwind, vel_face] = elemIsUpwind(*elem, fi, time);
170
171 const bool fi_elem_is_upwind = elem == &fi.elem() ? elem_is_upwind : !elem_is_upwind;
172 const auto & downwind_face = fi_elem_is_upwind ? face_neighbor : face_elem;
173
174 const auto & upwind_elem = makeElemArg(fi_elem_is_upwind ? fi.elemPtr() : fi.neighborPtr());
175 const auto & downwind_elem = makeElemArg(fi_elem_is_upwind ? fi.neighborPtr() : fi.elemPtr());
176
177 const auto & vel_upwind = vel_face;
178 const auto & vel_downwind = vel_face;
179
180 const auto & eps_upwind = fi_elem_is_upwind ? eps_elem : eps_neighbor;
181 const auto & eps_downwind = fi_elem_is_upwind ? eps_neighbor : eps_elem;
182
183 /*
184 If a weakly compressible material is used where the density slightly
185 depends on pressure. Given that the two-term expansion on Bernoulli faces is
186 enabled, we take use the downwind face assuming the continuity (minimal jump) of the
187 density. This protects against an infinite recursion between pressure and
188 density.
189 */
190 const auto & rho_upwind = (*_rho)(upwind_elem, time);
191 const auto & rho_downwind = (*_rho)(downwind_elem, time);
192
193 const VectorValue<ADReal> interstitial_vel_upwind = vel_upwind * (1 / eps_upwind);
194 const VectorValue<ADReal> interstitial_vel_downwind = vel_downwind * (1 / eps_downwind);
195
196 const auto v_dot_n_upwind = interstitial_vel_upwind * fi.normal();
197 const auto v_dot_n_downwind = interstitial_vel_downwind * fi.normal();
198
199 // Iterate through sidesets to see if we have associated irreversible pressure losses
200 // or not.
201 ADReal factor = 0.0;
202 for (const auto & bd_id : fi.boundaryIDs())
203 for (const auto i : index_range(_pressure_drop_sideset_ids))
204 if (_pressure_drop_sideset_ids[i] == bd_id)
205 factor += _pressure_drop_form_factors[i];
206
207 auto upwind_bernoulli_vel_chunk = 0.5 * rho_upwind * v_dot_n_upwind * v_dot_n_upwind;
208 auto downwind_bernoulli_vel_chunk = 0.5 * rho_downwind * v_dot_n_downwind * v_dot_n_downwind;
209
210 // We add the additional, irreversible pressure loss here.
211 // If it is a contraction we have to use the downwind values, otherwise the upwind values.
212 if (eps_downwind < eps_upwind)
213 downwind_bernoulli_vel_chunk +=
214 0.5 * factor * rho_downwind * v_dot_n_downwind * v_dot_n_downwind;
215 else
216 upwind_bernoulli_vel_chunk += -0.5 * factor * rho_upwind * v_dot_n_upwind * v_dot_n_upwind;
217
218 ADReal p_downwind;
220 p_downwind = (*this)(downwind_face, time);
221 else
222 p_downwind = (*this)(downwind_elem, time);
223
224 return p_downwind + downwind_bernoulli_vel_chunk - upwind_bernoulli_vel_chunk;
225}
DualNumber< Real, DNDerivativeType, true > ADReal
registerMooseObject("NavierStokesApp", BernoulliPressureVariable)
static InputParameters validParams()
A special variable class for pressure which flags faces at which porosity jumps occur as extrapolated...
ADReal getDirichletBoundaryFaceValue(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
const Moose::Functor< ADReal > * _eps
The porosity.
bool isDirichletBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
const Moose::Functor< ADReal > * _rho
The density.
std::vector< Real > _pressure_drop_form_factors
The form loss coefficients corresponding to the sidesets.
std::pair< bool, ADRealVectorValue > elemIsUpwind(const Elem &elem, const FaceInfo &fi, const Moose::StateArg &time) const
Checks to see whether the provided element is upwind of the provided face.
std::vector< BoundaryName > _pressure_drop_sidesets
The names of the sidesets which will have associated form loss coefficients.
const Moose::Functor< ADReal > * _v
The y-component of velocity.
const Moose::Functor< ADReal > * _w
The z-component of velocity.
const bool _allow_two_term_expansion_on_bernoulli_faces
Switch to enable the two-term extrapolation on porosity jump faces.
BernoulliPressureVariable(const InputParameters &params)
static InputParameters validParams()
const Moose::Functor< ADReal > * _u
The x-component of velocity.
const std::vector< BoundaryID > _pressure_drop_sideset_ids
The boundary IDs corresponding to the form loss sidesets.
bool isExtrapolatedBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
const Point & normal() const
const std::set< BoundaryID > & boundaryIDs() const
const Elem & elem() const
const Elem * neighborPtr() const
const Elem * elemPtr() const
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
static InputParameters validParams()
bool isSeparatorBoundary(const FaceInfo &fi) const
T & set(const std::string &name, bool quiet_mode=false)
void paramError(const std::string &param, Args... args) const
SubProblem & _subproblem
void initialSetup() override
Moose::FV::InterpMethod _face_interp_method
virtual bool isDirichletBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &state) const
virtual ADReal getDirichletBoundaryFaceValue(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &state) const
bool isInternalFace(const FaceInfo &) const
static const std::string density
Definition NS.h:34
std::tuple< bool, T, T > isPorosityJumpFace(const Moose::FunctorBase< T > &porosity, const FaceInfo &fi, const Moose::StateArg &time)
Checks to see whether the porosity value jumps from one side to the other of the provided face.
Definition NSFVUtils.C:119
static const std::string porosity
Definition NS.h:108