https://mooseframework.inl.gov
LinearFVPressureFluxBC.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "LinearFVPressureFluxBC.h"
11 #include "NS.h"
12 
14 
17 {
19  params.addClassDescription(
20  "Adds a fixed diffusive flux BC which can be used for the assembly of linear "
21  "finite volume system and whose normal face gradient values are determined "
22  "using the H/A flux and a prescribed boundary velocity. This boundary condition is only "
23  "designed to work with advection-diffusion problems.");
24  params.addRequiredParam<MooseFunctorName>("HbyA_flux", "The total HbyA face flux value.");
25  params.addRequiredParam<MooseFunctorName>(
26  "Ainv", "The 1/A where A is the momentum system diagonal vector.");
27  params.addParam<bool>(
28  "use_two_term_expansion",
29  true,
30  "Whether to reconstruct the boundary pressure using the pressure flux and cell gradient. If "
31  "false, the boundary pressure is approximated by the adjacent cell pressure.");
32  params.addRequiredParam<MooseFunctorName>("u", "The x-velocity functor on the boundary.");
33  params.addParam<MooseFunctorName>("v", "The y-velocity functor on the boundary.");
34  params.addParam<MooseFunctorName>("w", "The z-velocity functor on the boundary.");
35  params.addRequiredParam<MooseFunctorName>(
36  NS::density, "The density functor used together with the prescribed boundary velocity.");
37  return params;
38 }
39 
41  : LinearFVAdvectionDiffusionBC(parameters),
42  _HbyA_flux(getFunctor<Real>("HbyA_flux")),
43  _Ainv(getFunctor<RealVectorValue>("Ainv")),
44  _dim(_subproblem.mesh().dimension()),
45  _two_term_expansion(getParam<bool>("use_two_term_expansion")),
46  _u(getFunctor<Real>("u")),
47  _v(parameters.isParamValid("v") ? &getFunctor<Real>("v") : nullptr),
48  _w(parameters.isParamValid("w") ? &getFunctor<Real>("w") : nullptr),
49  _rho(getFunctor<Real>(NS::density))
50 {
51  if (_dim >= 2 && !_v)
52  paramError("v", "The 'v' boundary velocity functor must be provided for 2D and 3D problems.");
53 
54  if (_dim >= 3 && !_w)
55  paramError("w", "The 'w' boundary velocity functor must be provided for 3D problems.");
56 
57  if (_dim < 2 && _v)
58  paramError("v", "The 'v' boundary velocity functor is only valid in 2D and 3D problems.");
59 
60  if (_dim < 3 && _w)
61  paramError("w", "The 'w' boundary velocity functor is only valid in 3D problems.");
62 
65 }
66 
67 Real
69 {
70  const auto face_arg = singleSidedFaceArg(_current_face_info);
71  const auto state = determineState();
72 
73  Real required_pressure_flux = _HbyA_flux(face_arg, state);
74  const auto & normal = _current_face_info->normal();
75  Real boundary_velocity_dot_normal = _u(face_arg, state) * normal(0);
76 
77  if (_dim >= 2)
78  boundary_velocity_dot_normal += (*_v)(face_arg, state) * normal(1);
79 
80  if (_dim >= 3)
81  boundary_velocity_dot_normal += (*_w)(face_arg, state) * normal(2);
82 
83  // FaceInfo normals point from element to neighbor, so reverse the prescribed velocity flux when
84  // this boundary condition acts on the neighbor side of an internal face.
85  const Real boundary_normal_multiplier =
87  required_pressure_flux +=
88  _rho(face_arg, state) * boundary_normal_multiplier * boundary_velocity_dot_normal;
89 
90  return required_pressure_flux;
91 }
92 
93 Real
95 {
96  const auto face_arg = singleSidedFaceArg(_current_face_info);
97  const auto face_ainv = _Ainv(face_arg, determineState());
98  const auto & normal = _current_face_info->normal();
99 
100  // Match the boundary-normal coefficient used by LinearFVAnisotropicDiffusion:
101  // for a diagonal tensor Ainv, the effective normal coefficient is n^T Ainv n.
102  Real normal_ainv = 0.0;
103  for (const auto i : make_range(_dim))
104  normal_ainv += normal(i) * normal(i) * face_ainv(i);
105 
106  if (normal_ainv < 0.0)
107  mooseError("The boundary-normal Ainv coefficient must be nonnegative, but its value is ",
108  normal_ainv,
109  ".");
110 
111  return normal_ainv;
112 }
113 
114 Real
116 {
117  const auto state = determineState();
118  const auto elem_info = _current_face_type == FaceInfo::VarFaceNeighbors::ELEM
121 
122  if (!_two_term_expansion)
123  return _var.getElemValue(*elem_info, state);
124 
125  const Real normal_ainv = computeBoundaryAinv();
126 
127  // Ainv is initialized to zero and is first populated by the momentum assembly. Until then, use
128  // the cell pressure (1 term expansion) for the initial pressure-gradient
129  // calculation.
130  if (normal_ainv == 0.0)
131  return _var.getElemValue(*elem_info, state);
132 
134  const auto d_cf = computeCellToFaceVector();
135  const auto & face_normal = _current_face_info->normal();
136  const auto tangential_cell_to_face = d_cf - (d_cf * face_normal) * face_normal;
137 
138  // Return the 2-term expansion for the boundary value
139  return _var.getElemValue(*elem_info, state) + computeBoundaryNormalGradient() * distance +
140  _var.gradSln(*elem_info, state) * tangential_cell_to_face;
141 }
142 
143 Real
145 {
146  if (!_two_term_expansion)
147  return 0.0;
148 
149  const Real normal_ainv = computeBoundaryAinv();
150  if (normal_ainv == 0.0)
151  return 0.0;
152 
153  const auto state = determineState();
154  const auto face_ainv = _Ainv(singleSidedFaceArg(_current_face_info), state);
155  const auto elem_info = _current_face_type == FaceInfo::VarFaceNeighbors::ELEM
158  const Real boundary_normal_multiplier =
160  const auto boundary_normal = boundary_normal_multiplier * _current_face_info->normal();
161 
162  RealVectorValue normal_scaled_ainv;
163  for (const auto i : make_range(_dim))
164  normal_scaled_ainv(i) = boundary_normal(i) * face_ainv(i);
165 
166  // The prescribed pressure flux is the complete tensor-weighted flux. Subtract its tangential
167  // part only when inverting that flux to reconstruct the boundary-normal pressure gradient.
168  const auto tangential_ainv = normal_scaled_ainv - normal_ainv * boundary_normal;
169  const Real tangential_pressure_flux = tangential_ainv * _var.gradSln(*elem_info, state);
170 
171  return (-computeRequiredPressureFlux() - tangential_pressure_flux) / normal_ainv;
172 }
173 
174 Real
176 {
177  return 1.0;
178 }
179 
180 Real
182 {
183  const auto elem_info = _current_face_type == FaceInfo::VarFaceNeighbors::ELEM
186  return computeBoundaryValue() - _var.getElemValue(*elem_info, determineState());
187 }
188 
189 Real
191 {
192  return 0.0;
193 }
194 
195 Real
197 {
198  return -computeRequiredPressureFlux();
199 }
RealVectorValue computeCellToFaceVector() const
static InputParameters validParams()
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const Moose::Functor< Real > & _rho
Density functor used with the prescribed boundary velocity.
Real computeCellToFaceDistance() const
Moose::StateArg determineState() const
const ElemInfo * neighborInfo() const
virtual Real computeBoundaryNormalGradient() const override
MeshBase & mesh
static const std::string density
Definition: NS.h:34
const ElemInfo * elemInfo() const
Real distance(const Point &p)
void addRequiredParam(const std::string &name, const std::string &doc_string)
const Moose::Functor< Real > *const _v
LinearFVPressureFluxBC(const InputParameters &parameters)
Class constructor.
VectorValue< Real > gradSln(const ElemInfo &elem_info, const StateArg &state) const
const bool _two_term_expansion
Whether to reconstruct the boundary pressure with the pressure flux and cell gradient.
const Moose::Functor< RealVectorValue > & _Ainv
The functor for the 1/A tensor serving as a diffusion coefficient.
FaceInfo::VarFaceNeighbors _current_face_type
Class implementing a flux boundary condition for linear finite volume pressure variables used in the ...
const Point & normal() const
Real computeRequiredPressureFlux() const
Compute the required boundary pressure flux contribution.
Real computeBoundaryAinv() const
Compute the scalar A^{-1} coefficient, which is zero before the first momentum assembly.
MooseLinearVariableFV< Real > & _var
const unsigned short _dim
Spatial dimension of the mesh.
registerMooseObject("NavierStokesApp", LinearFVPressureFluxBC)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real computeBoundaryValueRHSContribution() const override
const Moose::Functor< Real > *const _w
const FaceInfo * _current_face_info
Real getElemValue(const ElemInfo &elem_info, const StateArg &state) const
virtual Real computeBoundaryGradientMatrixContribution() const override
const Moose::Functor< Real > & _u
Velocity functors used to prescribe a boundary mass flux.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
virtual Real computeBoundaryValueMatrixContribution() const override
void addClassDescription(const std::string &doc_string)
Moose::FaceArg singleSidedFaceArg(const FaceInfo *fi, Moose::FV::LimiterType limiter_type=Moose::FV::LimiterType::CentralDifference, bool correct_skewness=false) const
virtual Real computeBoundaryGradientRHSContribution() const override
virtual Real computeBoundaryValue() const override
static InputParameters validParams()
const Moose::Functor< Real > & _HbyA_flux
The H/A flux functor for this BC (can be variable, function, etc)