https://mooseframework.inl.gov
WCNSFV2PMomentumAdvectionSlip.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 "FVUtils.h"
14 #include "SystemBase.h"
15 #include "NSFVUtils.h"
16 
18 
21 {
23  params.addClassDescription(
24  "Computes the slip velocity advection kernel for two-phase mixture model.");
25  params.addRequiredParam<MooseFunctorName>("u_slip", "The slip velocity in the x direction.");
26  params.addParam<MooseFunctorName>("v_slip", "The slip velocity in the y direction.");
27  params.addParam<MooseFunctorName>("w_slip", "The slip velocity in the z direction.");
28  params.addRequiredParam<MooseFunctorName>("rho_d", "Dispersed phase density.");
29  params.addParam<MooseFunctorName>("fd", 0.0, "Fraction dispersed phase.");
30  params.renameParam("fd", "fraction_dispersed", "");
31  params.setDocString(NS::density, "Main phase (not dispersed) density functor");
32 
33  return params;
34 }
35 
37  : INSFVMomentumAdvection(params),
38  _rho_d(getFunctor<ADReal>("rho_d")),
39  _dim(_subproblem.mesh().dimension()),
40  _u_slip(getFunctor<ADReal>("u_slip")),
41  _v_slip(isParamValid("v_slip") ? &getFunctor<ADReal>("v_slip") : nullptr),
42  _w_slip(isParamValid("w_slip") ? &getFunctor<ADReal>("w_slip") : nullptr),
43  _fd(getFunctor<ADReal>("fd"))
44 {
45  if (_dim >= 2 && !_v_slip)
46  mooseError("In two or more dimensions, the v_slip velocity must be supplied using the 'v_slip' "
47  "parameter");
48  if (_dim >= 3 && !_w_slip)
49  mooseError(
50  "In three dimensions, the w_slip velocity must be supplied using the 'w_slip' parameter");
51 }
52 
53 void
55 {
56  mooseAssert(!skipForBoundary(fi),
57  "We shouldn't get in here if we're supposed to skip for a boundary");
58 
59  constexpr Real offset = 1e-15;
60  _face_info = &fi;
61  _normal = fi.normal();
62  _face_type = fi.faceType(std::make_pair(_var.number(), _var.sys().number()));
63  const auto state = determineState();
64 
65  using namespace Moose::FV;
66 
67  const bool correct_skewness = _advected_interp_method == InterpMethod::SkewCorrectedAverage;
68  const bool on_boundary = onBoundary(fi);
69 
70  _elem_residual = 0, _neighbor_residual = 0, _ae = 0, _an = 0;
71 
72  Moose::FaceArg face_arg;
73  if (on_boundary)
74  face_arg = singleSidedFaceArg();
75  else
76  face_arg = Moose::FaceArg{
77  &fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
78 
79  ADRealVectorValue u_slip_vel_vec;
80  if (_dim == 1)
81  u_slip_vel_vec(0) = _u_slip(face_arg, state);
82  if (_dim == 2)
83  u_slip_vel_vec = ADRealVectorValue(_u_slip(face_arg, state), (*_v_slip)(face_arg, state), 0.0);
84  if (_dim == 3)
85  u_slip_vel_vec = ADRealVectorValue(
86  _u_slip(face_arg, state), (*_v_slip)(face_arg, state), (*_w_slip)(face_arg, state));
87 
88  const auto rho_mix = _rho(face_arg, state) +
89  (_rho_d(face_arg, state) - _rho(face_arg, state)) * _fd(face_arg, state);
90 
91  const auto vdotn = _normal * u_slip_vel_vec;
92 
93  if (on_boundary)
94  {
95  const auto ssf = singleSidedFaceArg();
96  const Elem * const sided_elem = ssf.face_side;
97  const auto dof_number = sided_elem->dof_number(_sys.number(), _var.number(), 0);
98  const auto rho_face = rho_mix;
99  const auto eps_face = epsilon()(ssf, state);
100  const auto u_face = _var(ssf, state);
101  const Real d_u_face_d_dof = u_face.derivatives()[dof_number];
102  const auto coeff = vdotn * rho_face / eps_face;
103 
104  if (sided_elem == fi.elemPtr())
105  {
106  _ae = coeff * d_u_face_d_dof;
107  _elem_residual = coeff * u_face;
108  if (_approximate_as)
109  _ae = _cs / fi.elem().n_sides() * rho_face / eps_face;
110  }
111  else
112  {
113  _an = -coeff * d_u_face_d_dof;
114  _neighbor_residual = -coeff * u_face;
115  if (_approximate_as)
116  _an = _cs / fi.neighborPtr()->n_sides() * rho_face / eps_face;
117  }
118  }
119  else // we are an internal fluid flow face
120  {
121  const bool elem_is_upwind = MetaPhysicL::raw_value(u_slip_vel_vec) * _normal > 0;
122  const Moose::FaceArg advected_face_arg{&fi,
124  elem_is_upwind,
125  correct_skewness,
126  nullptr,
127  nullptr};
128  if (const auto [is_jump, eps_elem_face, eps_neighbor_face] =
129  NS::isPorosityJumpFace(epsilon(), fi, state);
130  is_jump)
131  {
132  // For a weakly compressible formulation, the density should not depend on pressure and
133  // consequently the density should not be impacted by the pressure jump that occurs at a
134  // porosity jump. Consequently we will allow evaluation of the density using both upstream and
135  // downstream information
136  const auto rho_face =
137  _rho_d(advected_face_arg, state) - _rho(advected_face_arg, state) + offset;
138 
139  // We set the + and - sides of the superficial velocity equal to the interpolated value
140  const auto & var_elem_face = u_slip_vel_vec(_index);
141  const auto & var_neighbor_face = u_slip_vel_vec(_index);
142 
143  const auto elem_dof_number = fi.elem().dof_number(_sys.number(), _var.number(), 0);
144  const auto neighbor_dof_number = fi.neighbor().dof_number(_sys.number(), _var.number(), 0);
145 
146  const auto d_var_elem_face_d_elem_dof = var_elem_face.derivatives()[elem_dof_number];
147  const auto d_var_neighbor_face_d_neighbor_dof =
148  var_neighbor_face.derivatives()[neighbor_dof_number];
149 
150  // We allow a discontintuity in the advective momentum flux at the jump face. Mainly the
151  // advective flux is:
152  // elem side:
153  // rho * v_superficial / eps_elem * v_superficial = rho * v_interstitial_elem * v_superficial
154  // neighbor side:
155  // rho * v_superficial / eps_neigh * v_superficial = rho * v_interstitial_neigh *
156  // v_superficial
157  const auto elem_coeff = vdotn * rho_face / eps_elem_face;
158  const auto neighbor_coeff = vdotn * rho_face / eps_neighbor_face;
159  _ae = elem_coeff * d_var_elem_face_d_elem_dof;
160  _elem_residual = elem_coeff * var_elem_face;
161  _an = -neighbor_coeff * d_var_neighbor_face_d_neighbor_dof;
162  _neighbor_residual = -neighbor_coeff * var_neighbor_face;
163  if (_approximate_as)
164  {
165  _ae = _cs / fi.elem().n_sides() * rho_face / eps_elem_face;
166  _an = _cs / fi.neighborPtr()->n_sides() * rho_face / eps_elem_face;
167  }
168  }
169  else
170  {
171  const auto [interp_coeffs, advected] =
172  interpCoeffsAndAdvected(*_rho_u, advected_face_arg, state);
173 
174  const auto elem_arg = elemArg();
175  const auto neighbor_arg = neighborArg();
176 
177  const auto rho_elem = _rho_d(elem_arg, state) - _rho(elem_arg, state) + offset;
178  const auto rho_neighbor = _rho_d(neighbor_arg, state) - _rho(neighbor_arg, state) + offset;
179  const auto eps_elem = epsilon()(elem_arg, state),
180  eps_neighbor = epsilon()(neighbor_arg, state);
181  const auto var_elem = advected.first / rho_elem * eps_elem,
182  var_neighbor = advected.second / rho_neighbor * eps_neighbor;
183 
184  _ae = vdotn * rho_elem / eps_elem * interp_coeffs.first;
185  // Minus sign because we apply a minus sign to the residual in computeResidual
186  _an = -vdotn * rho_neighbor / eps_neighbor * interp_coeffs.second;
187 
188  _elem_residual = _ae * var_elem - _an * var_neighbor;
190 
191  if (_approximate_as)
192  {
193  _ae = _cs / fi.elem().n_sides() * rho_elem / eps_elem;
194  _an = _cs / fi.neighborPtr()->n_sides() * rho_neighbor / eps_neighbor;
195  }
196  }
197  }
198 
199  _ae *= fi.faceArea() * fi.faceCoord();
200  _an *= fi.faceArea() * fi.faceCoord();
201  _elem_residual *= fi.faceArea() * fi.faceCoord();
202  _neighbor_residual *= fi.faceArea() * fi.faceCoord();
203 }
ADReal _neighbor_residual
The neighbor residual.
void renameParam(const std::string &old_name, const std::string &new_name, const std::string &new_docstring)
Moose::FV::InterpMethod _advected_interp_method
The interpolation method to use for the advected quantity.
const Moose::Functor< ADReal > *const _v_slip
slip velocity in direction y
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void setDocString(const std::string &name, const std::string &doc)
Moose::ElemArg elemArg(bool correct_skewness=false) const
unsigned int number() const
std::unique_ptr< PiecewiseByBlockLambdaFunctor< ADReal > > _rho_u
Our local momentum functor.
const Elem & elem() const
const FaceInfo * _face_info
Moose::StateArg determineState() 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
const unsigned int _index
index x|y|z
MeshBase & mesh
static const std::string density
Definition: NS.h:33
auto raw_value(const Eigen::Map< T > &in)
Real & faceCoord()
RealVectorValue _normal
static InputParameters validParams()
Real faceArea() const
ADReal _ae
The a coefficient for the element.
void addRequiredParam(const std::string &name, const std::string &doc_string)
SystemBase & _sys
bool onBoundary(const FaceInfo &fi) const
LimiterType limiterType(InterpMethod interp_method)
const Elem * neighborPtr() const
const Real _cs
Characteristic speed.
const Moose::Functor< ADReal > & _u_slip
slip velocity in direction x
const bool _approximate_as
Whether to approximately calculate the &#39;a&#39; coefficients.
bool skipForBoundary(const FaceInfo &fi) const override
const Moose::Functor< ADReal > & _rho
Density.
virtual const Moose::FunctorBase< ADReal > & epsilon() const
A virtual method that allows us to reuse all the code from free-flow for porous.
const Moose::Functor< ADReal > & _rho_d
Dispersed phase density.
An advection kernel that implements interpolation schemes specific to Navier-Stokes flow physics...
const Elem & neighbor() const
const Point & normal() const
unsigned int number() const
virtual void computeResidualsAndAData(const FaceInfo &fi) override
Helper method that computes the &#39;a&#39; coefficients and AD residuals.
FaceInfo::VarFaceNeighbors _face_type
const Elem * elemPtr() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
WCNSFV2PMomentumAdvectionSlip(const InputParameters &params)
Moose::ElemArg neighborArg(bool correct_skewness=false) const
ADReal _an
The a coefficient for the neighbor.
const Moose::Functor< ADReal > & _fd
Particle diameter in the dispersed phase.
registerMooseObject("NavierStokesApp", WCNSFV2PMomentumAdvectionSlip)
void mooseError(Args &&... args) const
Adds momentum kernel coming from the slip velocity in two-phase mixture model.
ADReal _elem_residual
The element residual.
void addClassDescription(const std::string &doc_string)
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
MooseVariableFV< Real > & _var
const Moose::Functor< ADReal > *const _w_slip
slip velocity in direction z
std::pair< std::pair< T, T >, std::pair< T, T > > interpCoeffsAndAdvected(const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
const unsigned int _dim
the dimension of the simulation
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const