https://mooseframework.inl.gov
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 {
19  auto params = INSFVPressureVariable::validParams();
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",
47  [](const InputParameters & /*obj_params*/, InputParameters & rm_params)
48  { rm_params.set<unsigned short>("layers") = 3; });
49  return params;
50 }
51 
53  : INSFVPressureVariable(params),
54  ADFunctorInterface(this),
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 {
68  paramError(
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 
77 void
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 
89 std::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 
104 bool
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 
125 bool
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 
146 ADReal
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 }
const Moose::Functor< ADReal > * _eps
The porosity.
const std::vector< BoundaryID > _pressure_drop_sideset_ids
The boundary IDs corresponding to the form loss sidesets.
Moose::FV::InterpMethod _face_interp_method
BernoulliPressureVariable(const InputParameters &params)
const Moose::Functor< ADReal > * _rho
The density.
const std::set< BoundaryID > & boundaryIDs() const
const Elem & elem() const
std::tuple< bool, ADReal, ADReal > isPorosityJumpFace(const Moose::Functor< ADReal > &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:58
T & set(const std::string &name, bool quiet_mode=false)
static InputParameters validParams()
static const std::string density
Definition: NS.h:33
bool isDirichletBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
static InputParameters validParams()
const Moose::Functor< ADReal > * _v
The y-component of velocity.
std::vector< Real > _pressure_drop_form_factors
The form loss coefficients corresponding to the sidesets.
DualNumber< Real, DNDerivativeType, true > ADReal
bool isSeparatorBoundary(const FaceInfo &fi) const
Definition: INSFVVariable.C:82
bool isExtrapolatedBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
virtual bool isDirichletBoundaryFace(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &state) const
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
static const std::string porosity
Definition: NS.h:104
bool isInternalFace(const FaceInfo &) const
void libmesh_ignore(const Args &...)
const Moose::Functor< ADReal > * _u
The x-component of velocity.
virtual void initialSetup() override
Definition: INSFVVariable.C:75
const Elem * neighborPtr() const
SubProblem & _subproblem
ADReal getDirichletBoundaryFaceValue(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &time) const override
const Moose::Functor< ADReal > * _w
The z-component of velocity.
registerMooseObject("NavierStokesApp", BernoulliPressureVariable)
const bool _allow_two_term_expansion_on_bernoulli_faces
Switch to enable the two-term extrapolation on porosity jump faces.
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
const Point & normal() const
void paramError(const std::string &param, Args... args) const
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.
const Elem * elemPtr() const
A special variable class for pressure which flags faces at which porosity jumps occur as extrapolated...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual ADReal getDirichletBoundaryFaceValue(const FaceInfo &fi, const Elem *elem, const Moose::StateArg &state) const
std::vector< BoundaryName > _pressure_drop_sidesets
The names of the sidesets which will have associated form loss coefficients.
static InputParameters validParams()
auto index_range(const T &sizable)