https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PorousFlowOutflowBC.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 "PorousFlowOutflowBC.h"
11
12#include "MooseVariable.h"
13#include "libmesh/string_to_enum.h"
14#include "libmesh/quadrature.h"
15
17
20{
22 params.addRequiredParam<UserObjectName>(
23 "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
24 params.addRequiredParam<RealVectorValue>("gravity",
25 "Gravitational acceleration vector downwards (m/s^2)");
26 MooseEnum flux_type_enum("fluid heat", "fluid");
27 params.addParam<MooseEnum>(
28 "flux_type",
29 flux_type_enum,
30 "The type of boundary condition to apply. 'fluid' means this boundary condition will allow "
31 "a fluid component to flow freely from the boundary. 'heat' means this boundary condition "
32 "will allow heat energy to flow freely from the boundary");
33 params.addParam<unsigned int>(
34 "mass_fraction_component",
35 0,
36 "The index corresponding to a fluid "
37 "component. If supplied, the residual contribution will be "
38 "multiplied by the mass fraction, corresponding to allowing the "
39 "given mass fraction to flow freely from the boundary. This is ignored if flux_type = heat");
40 params.addParam<bool>("multiply_by_density",
41 true,
42 "If true, this BC represents mass flux. If false, it represents volume "
43 "flux. User input of this flag is ignored if flux_type = heat as "
44 "multiply_by_density should always be true in that case");
45 params.addParam<bool>(
46 "include_relperm",
47 true,
48 "If true, the Darcy flux will include the relative permeability. If false, the relative "
49 "permeability will not be used, which must only be used for fully-saturated situations "
50 "where there is no notion of relative permeability");
51 params.addParam<Real>(
52 "multiplier",
53 1.0,
54 "Multiply the flux by this number. This is mainly used for testing purposes");
55 params.addParamNamesToGroup("multiplier", "Advanced");
57 "Applies an 'outflow' boundary condition, which allows fluid components or heat energy to "
58 "flow freely out of the boundary as if it weren't there. This is fully upwinded");
59 return params;
60}
61
63 : IntegratedBC(parameters),
64 _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
65 _num_phases(_dictator.numPhases()),
66 _perm_derivs(_dictator.usePermDerivs()),
67 _flux_type(getParam<MooseEnum>("flux_type").getEnum<FluxTypeChoiceEnum>()),
68 _sp(getParam<unsigned>("mass_fraction_component")),
69 _multiply_by_density(
70 _flux_type == FluxTypeChoiceEnum::FLUID ? getParam<bool>("multiply_by_density") : true),
71 _include_relperm(getParam<bool>("include_relperm")),
72 _gravity(getParam<RealVectorValue>("gravity")),
73 _multiplier(getParam<Real>("multiplier")),
74 _grad_p(getMaterialProperty<std::vector<RealGradient>>("PorousFlow_grad_porepressure_qp")),
75 _dgrad_p_dgrad_var(getMaterialProperty<std::vector<std::vector<Real>>>(
76 "dPorousFlow_grad_porepressure_qp_dgradvar")),
77 _dgrad_p_dvar(getMaterialProperty<std::vector<std::vector<RealGradient>>>(
78 "dPorousFlow_grad_porepressure_qp_dvar")),
79 _fluid_density_qp(getMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_qp")),
80 _dfluid_density_qp_dvar(getMaterialProperty<std::vector<std::vector<Real>>>(
81 "dPorousFlow_fluid_phase_density_qp_dvar")),
82 _permeability(getMaterialProperty<RealTensorValue>("PorousFlow_permeability_qp")),
83 _dpermeability_dvar(
84 getMaterialProperty<std::vector<RealTensorValue>>("dPorousFlow_permeability_qp_dvar")),
85 _dpermeability_dgradvar(getMaterialProperty<std::vector<std::vector<RealTensorValue>>>(
86 "dPorousFlow_permeability_qp_dgradvar")),
87 _fluid_viscosity(getMaterialProperty<std::vector<Real>>("PorousFlow_viscosity_nodal")),
88 _dfluid_viscosity_dvar(
89 getMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_viscosity_nodal_dvar")),
90
91 _has_density(hasMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal") &&
92 hasMaterialProperty<std::vector<std::vector<Real>>>(
93 "dPorousFlow_fluid_phase_density_nodal_dvar")),
94 _has_mass_fraction(
95 hasMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal") &&
96 hasMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
97 "dPorousFlow_mass_frac_nodal_dvar")),
98 _has_relperm(hasMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_nodal") &&
99 hasMaterialProperty<std::vector<std::vector<Real>>>(
100 "dPorousFlow_relative_permeability_nodal_dvar")),
101 _has_enthalpy(hasMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_enthalpy_nodal") &&
102 hasMaterialProperty<std::vector<std::vector<Real>>>(
103 "dPorousFlow_fluid_phase_enthalpy_nodal_dvar")),
104 _has_thermal_conductivity(
105 hasMaterialProperty<RealTensorValue>("PorousFlow_thermal_conductivity_qp") &&
106 hasMaterialProperty<std::vector<RealTensorValue>>(
107 "dPorousFlow_thermal_conductivity_qp_dvar")),
108 _has_t(hasMaterialProperty<RealGradient>("PorousFlow_grad_temperature_qp") &&
109 hasMaterialProperty<std::vector<RealGradient>>("dPorousFlow_grad_temperature_qp_dvar") &&
110 hasMaterialProperty<std::vector<Real>>("dPorousFlow_grad_temperature_qp_dgradvar")),
111
112 _fluid_density_node(_has_density ? &getMaterialProperty<std::vector<Real>>(
113 "PorousFlow_fluid_phase_density_nodal")
114 : nullptr),
115 _dfluid_density_node_dvar(_has_density ? &getMaterialProperty<std::vector<std::vector<Real>>>(
116 "dPorousFlow_fluid_phase_density_nodal_dvar")
117 : nullptr),
118 _relative_permeability(_has_relperm ? &getMaterialProperty<std::vector<Real>>(
119 "PorousFlow_relative_permeability_nodal")
120 : nullptr),
121 _drelative_permeability_dvar(_has_relperm
122 ? &getMaterialProperty<std::vector<std::vector<Real>>>(
123 "dPorousFlow_relative_permeability_nodal_dvar")
124 : nullptr),
125 _mass_fractions(_has_mass_fraction ? &getMaterialProperty<std::vector<std::vector<Real>>>(
126 "PorousFlow_mass_frac_nodal")
127 : nullptr),
128 _dmass_fractions_dvar(_has_mass_fraction
129 ? &getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
130 "dPorousFlow_mass_frac_nodal_dvar")
131 : nullptr),
132 _enthalpy(_has_enthalpy ? &getMaterialPropertyByName<std::vector<Real>>(
133 "PorousFlow_fluid_phase_enthalpy_nodal")
134 : nullptr),
135 _denthalpy_dvar(_has_enthalpy ? &getMaterialPropertyByName<std::vector<std::vector<Real>>>(
136 "dPorousFlow_fluid_phase_enthalpy_nodal_dvar")
137 : nullptr),
138 _thermal_conductivity(_has_thermal_conductivity ? &getMaterialProperty<RealTensorValue>(
139 "PorousFlow_thermal_conductivity_qp")
140 : nullptr),
141 _dthermal_conductivity_dvar(_has_thermal_conductivity
142 ? &getMaterialProperty<std::vector<RealTensorValue>>(
143 "dPorousFlow_thermal_conductivity_qp_dvar")
144 : nullptr),
145 _grad_t(_has_t ? &getMaterialProperty<RealGradient>("PorousFlow_grad_temperature_qp")
146 : nullptr),
147 _dgrad_t_dvar(_has_t ? &getMaterialProperty<std::vector<RealGradient>>(
148 "dPorousFlow_grad_temperature_qp_dvar")
149 : nullptr),
150 _dgrad_t_dgradvar(
151 _has_t ? &getMaterialProperty<std::vector<Real>>("dPorousFlow_grad_temperature_qp_dgradvar")
152 : nullptr)
153{
155 paramError("mass_fraction_component",
156 "The Dictator declares that the maximum fluid component index is ",
158 ", but you have set mass_fraction_component to ",
159 _sp,
160 ". Remember that indexing starts at 0. Please be assured that the Dictator has "
161 "noted your error.");
162
164 mooseError("PorousFlowOutflowBC: You requested to multiply_by_density, but you have no nodal "
165 "fluid density Material");
167 mooseError("PorousFlowOutflowBC: You requested to include the relative permeability, but you "
168 "have no nodal relative permeability Material");
171 "PorousFlowOutflowBC: For flux_type = fluid, you need a nodal mass-fraction Material");
174 "PorousFlowOutflowBC: For flux_type = heat, you need a nodal fluid enthalpy Material");
177 "PorousFlowOutflowBC: For flux_type = heat, you need a thermal conductivity Material");
179 mooseError("PorousFlowOutflowBC: For flux_type = heat, you need a temperature Material");
180}
181
182Real
184{
185 Real advective_term = 0.0;
186 for (unsigned ph = 0; ph < _num_phases; ++ph)
187 advective_term -= darcy(ph) * mobility(ph) * prefactor(ph);
188
190 return _test[_i][_qp] * advective_term * _multiplier;
191
192 const Real conduction_term = -_normals[_qp] * ((*_thermal_conductivity)[_qp] * (*_grad_t)[_qp]);
193 return _test[_i][_qp] * (conduction_term + advective_term) * _multiplier;
194}
195
196Real
201
202Real
204{
205 return jac(jvar);
206}
207
208Real
209PorousFlowOutflowBC::jac(unsigned int jvar) const
210{
212 return 0.0;
213 const unsigned int pvar = _dictator.porousFlowVariableNum(jvar);
214
215 // For _i != _j, note:
216 // since the only non-upwinded contribution to the residual is
217 // from Darcy and thermal_conductivity, the only contribution
218 // of the residual at node _i from changing jvar at node _j is through
219 // the derivative of Darcy or thermal_conductivity
220
221 Real advective_term_prime = 0.0;
222 for (unsigned ph = 0; ph < _num_phases; ++ph)
223 {
224 Real darcyprime =
225 _normals[_qp] *
227 _dgrad_p_dvar[_qp][ph][pvar] * _phi[_j][_qp] -
228 _dfluid_density_qp_dvar[_qp][ph][pvar] * _phi[_j][_qp] * _gravity));
229 if (_perm_derivs)
230 {
231 darcyprime += _normals[_qp] * (_dpermeability_dvar[_qp][pvar] * _phi[_j][_qp] *
232 (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity));
233 for (const auto i : make_range(Moose::dim))
234 darcyprime +=
235 _normals[_qp] * (_dpermeability_dgradvar[_qp][i][pvar] * _grad_phi[_j][_qp](i) *
236 (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity));
237 }
238 if (_i != _j)
239 advective_term_prime -= prefactor(ph) * mobility(ph) * darcyprime;
240 else
241 {
242 const Real dar = darcy(ph);
243
244 Real mob = 1.0 / _fluid_viscosity[_i][ph];
245 Real mobprime =
246 -_dfluid_viscosity_dvar[_i][ph][pvar] / Utility::pow<2>(_fluid_viscosity[_i][ph]);
248 {
249 const Real densityprime = (*_dfluid_density_node_dvar)[_i][ph][pvar];
250 mobprime = densityprime * mob + (*_fluid_density_node)[_i][ph] * mobprime;
251 mob *= (*_fluid_density_node)[_i][ph];
252 }
254 {
255 const Real relpermprime = (*_drelative_permeability_dvar)[_i][ph][pvar];
256 mobprime = relpermprime * mob + (*_relative_permeability)[_i][ph] * mobprime;
257 mob *= (*_relative_permeability)[_i][ph];
258 }
259
260 const Real pre = prefactor(ph);
261 const Real preprime =
262 (_flux_type == FluxTypeChoiceEnum::FLUID ? (*_dmass_fractions_dvar)[_i][ph][_sp][pvar]
263 : (*_denthalpy_dvar)[_i][ph][pvar]);
264
265 advective_term_prime -= preprime * mob * dar + pre * mobprime * dar + pre * mob * darcyprime;
266 }
267 }
269 return _test[_i][_qp] * advective_term_prime * _multiplier;
270
271 const Real conduction_term_prime =
272 -_normals[_qp] *
273 ((*_dthermal_conductivity_dvar)[_qp][pvar] * (*_grad_t)[_qp] +
274 (*_thermal_conductivity)[_qp] * (*_dgrad_t_dvar)[_qp][pvar]) *
275 _phi[_j][_qp] -
276 _normals[_qp] *
277 ((*_thermal_conductivity)[_qp] * (*_dgrad_t_dgradvar)[_qp][pvar] * _grad_phi[_j][_qp]);
278 return _test[_i][_qp] * (conduction_term_prime + advective_term_prime) * _multiplier;
279}
280
281Real
283{
284 return _normals[_qp] *
286}
287
288Real
290{
291 return (_multiply_by_density ? (*_fluid_density_node)[_i][ph] : 1.0) *
293}
294
295Real
297{
299 : (*_enthalpy)[_i][ph]);
300}
registerMooseObject("PorousFlowApp", PorousFlowOutflowBC)
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
unsigned int _qp
unsigned int _i
unsigned int _j
const VariablePhiGradient & _grad_phi
MooseVariable & _var
static InputParameters validParams()
const VariablePhiValue & _phi
const MooseArray< Point > & _normals
const VariableTestValue & _test
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
unsigned int number() const
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
unsigned int numComponents() const
The number of fluid components.
unsigned int porousFlowVariableNum(unsigned int moose_var_num) const
The PorousFlow variable number.
bool notPorousFlowVariable(unsigned int moose_var_num) const
Returns true if moose_var_num is not a porous flow variabe.
Applies a flux to a boundary such that fluid or heat will flow freely out of the boundary.
const MaterialProperty< std::vector< Real > > *const _fluid_density_node
Fluid density for each phase (at the node)
PorousFlowOutflowBC(const InputParameters &parameters)
const bool _perm_derivs
Flag indicating whether to include derivatives of the permeability in the Jacobian.
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
const Real _multiplier
Multiply the flux by this quantity. This is mainly used for testing purposes, for instance,...
Real prefactor(unsigned ph) const
Either mass_fraction or enthalpy, depending on _flux_type.
static InputParameters validParams()
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_viscosity_dvar
Derivative of the fluid viscosity for each phase wrt PorousFlow variables.
const MaterialProperty< std::vector< Real > > *const _relative_permeability
Relative permeability of each phase.
const MaterialProperty< RealTensorValue > & _permeability
Permeability of porous material.
const unsigned _num_phases
Number of phases in the simulation.
const MaterialProperty< std::vector< RealGradient > > & _grad_p
Gradient of the pore pressure in each phase.
const bool _has_enthalpy
Whether there is an enthalpy Material.
Real jac(unsigned int jvar) const
Derivative of residual with respect to the jvar variable.
const bool _has_t
Whether there is a grad_temp Material.
const bool _include_relperm
Whether to multiply the Darcy flux by the relative permeability.
const bool _has_mass_fraction
Whether there is a mass_frac_nodal Material.
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_density_qp_dvar
Derivative of the fluid density for each phase wrt PorousFlow variables (at the qp)
const MaterialProperty< RealTensorValue > *const _thermal_conductivity
Thermal_Conductivity of porous material.
Real mobility(unsigned ph) const
Mobility contribution to the outflowBC.
const RealVectorValue _gravity
Gravitational acceleration.
virtual Real computeQpJacobian() override
Real darcy(unsigned ph) const
Darcy contribution to the outflowBC.
const unsigned int _sp
The fluid component number (only used if _flux_type==FLUID))
FluxTypeChoiceEnum
Indicates the type of flux that this BC will apply.
const MaterialProperty< std::vector< std::vector< RealGradient > > > & _dgrad_p_dvar
Derivative of Grad porepressure in each phase wrt PorousFlow variables.
const MaterialProperty< std::vector< std::vector< Real > > > *const _mass_fractions
Mass fraction of each component in each phase.
const MaterialProperty< std::vector< std::vector< RealTensorValue > > > & _dpermeability_dgradvar
d(permeabiity)/d(grad(PorousFlow variable))
const MaterialProperty< std::vector< Real > > & _fluid_density_qp
Fluid density for each phase (at the qp)
const bool _has_thermal_conductivity
Whether there is a thermal_conductivity_qp Material.
const MaterialProperty< std::vector< RealTensorValue > > & _dpermeability_dvar
d(permeabiity)/d(PorousFlow variable)
virtual Real computeQpResidual() override
const MaterialProperty< std::vector< std::vector< Real > > > & _dgrad_p_dgrad_var
Derivative of Grad porepressure in each phase wrt grad(PorousFlow variables)
const bool _has_relperm
Whether there is a relative_permeability_nodal Material.
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
const MaterialProperty< std::vector< Real > > & _fluid_viscosity
Viscosity of each phase.
const bool _has_density
Whether there is a fluid_phase_density_nodal Material.
const bool _multiply_by_density
Whether to multiply the Darcy flux by the fluid density. This is automatically set to true if _flux_t...
enum PorousFlowOutflowBC::FluxTypeChoiceEnum _flux_type
static constexpr std::size_t dim