https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PorousFlowLineSink.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 "PorousFlowLineSink.h"
11#include "libmesh/utility.h"
12
15{
17 MooseEnum p_or_t_choice("pressure=0 temperature=1", "pressure");
18 params.addParam<MooseEnum>("function_of",
19 p_or_t_choice,
20 "Modifying functions will be a function of either pressure and "
21 "permeability (eg, for boreholes that pump fluids) or "
22 "temperature and thermal conductivity (eg, for boreholes that "
23 "pump pure heat with no fluid flow)");
24 params.addRequiredParam<UserObjectName>(
25 "SumQuantityUO",
26 "User Object of type=PorousFlowSumQuantity in which to place the total "
27 "outflow from the line sink for each time step.");
28 params.addParam<UserObjectName>(
29 "PointFluxUO",
30 "Optional UserObject of type=PorousFlowPointFluxQuantity in which to record the "
31 "instantaneous flux (eg kg.s^-1 for fluid, J.s^-1 for heat) at each individual Dirac "
32 "point of this line sink, as computed during the most recent residual evaluation. Use a "
33 "PorousFlowPlotPointFluxQuantity VectorPostprocessor to output the recorded values. "
34 "Unlike SumQuantityUO, this is not multiplied by the timestep size. Use a separate "
35 "UserObject for each line sink.");
36 params.addRequiredParam<UserObjectName>(
37 "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
38 params.addParam<unsigned int>(
39 "fluid_phase",
40 0,
41 "The fluid phase whose pressure (and potentially mobility, enthalpy, etc) "
42 "controls the flux to the line sink. For p_or_t=temperature, and without "
43 "any use_*, this parameter is irrelevant");
44 params.addParam<unsigned int>("mass_fraction_component",
45 "The index corresponding to a fluid "
46 "component. If supplied, the flux will "
47 "be multiplied by the nodal mass "
48 "fraction for the component");
49 params.addParam<bool>(
50 "use_relative_permeability", false, "Multiply the flux by the fluid relative permeability");
51 params.addParam<bool>("use_mobility", false, "Multiply the flux by the fluid mobility");
52 params.addParam<bool>("use_enthalpy", false, "Multiply the flux by the fluid enthalpy");
53 params.addParam<bool>(
54 "use_internal_energy", false, "Multiply the flux by the fluid internal energy");
55 params.addCoupledVar("multiplying_var", 1.0, "Fluxes will be moultiplied by this variable");
56 params.addClassDescription("Approximates a line sink in the mesh by a sequence of weighted Dirac "
57 "points whose positions are read from a file");
58 return params;
59}
60
62 : PorousFlowLineGeometry(parameters),
63 _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
64 _total_outflow_mass(
65 const_cast<PorousFlowSumQuantity &>(getUserObject<PorousFlowSumQuantity>("SumQuantityUO"))),
66 _point_fluxes(isParamValid("PointFluxUO")
67 ? &const_cast<PorousFlowPointFluxQuantity &>(
68 getUserObject<PorousFlowPointFluxQuantity>("PointFluxUO"))
69 : nullptr),
70
71 _has_porepressure(
72 hasMaterialProperty<std::vector<Real>>("PorousFlow_porepressure_qp") &&
73 hasMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_porepressure_qp_dvar")),
74 _has_temperature(hasMaterialProperty<Real>("PorousFlow_temperature_qp") &&
75 hasMaterialProperty<std::vector<Real>>("dPorousFlow_temperature_qp_dvar")),
76 _has_mass_fraction(
77 hasMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal") &&
78 hasMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
79 "dPorousFlow_mass_frac_nodal_dvar")),
80 _has_relative_permeability(
81 hasMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_nodal") &&
82 hasMaterialProperty<std::vector<std::vector<Real>>>(
83 "dPorousFlow_relative_permeability_nodal_dvar")),
84 _has_mobility(
85 hasMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_nodal") &&
86 hasMaterialProperty<std::vector<std::vector<Real>>>(
87 "dPorousFlow_relative_permeability_nodal_dvar") &&
88 hasMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal") &&
89 hasMaterialProperty<std::vector<std::vector<Real>>>(
90 "dPorousFlow_fluid_phase_density_nodal_dvar") &&
91 hasMaterialProperty<std::vector<Real>>("PorousFlow_viscosity_nodal") &&
92 hasMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_viscosity_nodal_dvar")),
93 _has_enthalpy(hasMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_enthalpy_nodal") &&
94 hasMaterialProperty<std::vector<std::vector<Real>>>(
95 "dPorousFlow_fluid_phase_enthalpy_nodal_dvar")),
96 _has_internal_energy(
97 hasMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_internal_energy_nodal") &&
98 hasMaterialProperty<std::vector<std::vector<Real>>>(
99 "dPorousFlow_fluid_phase_internal_energy_nodal_dvar")),
100
101 _p_or_t(getParam<MooseEnum>("function_of").getEnum<PorTchoice>()),
102 _use_mass_fraction(isParamValid("mass_fraction_component")),
103 _use_relative_permeability(getParam<bool>("use_relative_permeability")),
104 _use_mobility(getParam<bool>("use_mobility")),
105 _use_enthalpy(getParam<bool>("use_enthalpy")),
106 _use_internal_energy(getParam<bool>("use_internal_energy")),
107
108 _ph(getParam<unsigned int>("fluid_phase")),
109 _sp(_use_mass_fraction ? getParam<unsigned int>("mass_fraction_component") : 0),
110
111 _pp((_p_or_t == PorTchoice::pressure && _has_porepressure)
112 ? &getMaterialProperty<std::vector<Real>>("PorousFlow_porepressure_qp")
113 : nullptr),
114 _dpp_dvar((_p_or_t == PorTchoice::pressure && _has_porepressure)
115 ? &getMaterialProperty<std::vector<std::vector<Real>>>(
116 "dPorousFlow_porepressure_qp_dvar")
117 : nullptr),
118 _temperature((_p_or_t == PorTchoice::temperature && _has_temperature)
119 ? &getMaterialProperty<Real>("PorousFlow_temperature_qp")
120 : nullptr),
121 _dtemperature_dvar(
122 (_p_or_t == PorTchoice::temperature && _has_temperature)
123 ? &getMaterialProperty<std::vector<Real>>("dPorousFlow_temperature_qp_dvar")
124 : nullptr),
125 _fluid_density_node(
126 (_use_mobility && _has_mobility)
127 ? &getMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal")
128 : nullptr),
129 _dfluid_density_node_dvar((_use_mobility && _has_mobility)
130 ? &getMaterialProperty<std::vector<std::vector<Real>>>(
131 "dPorousFlow_fluid_phase_density_nodal_dvar")
132 : nullptr),
133 _fluid_viscosity((_use_mobility && _has_mobility)
134 ? &getMaterialProperty<std::vector<Real>>("PorousFlow_viscosity_nodal")
135 : nullptr),
136 _dfluid_viscosity_dvar((_use_mobility && _has_mobility)
137 ? &getMaterialProperty<std::vector<std::vector<Real>>>(
138 "dPorousFlow_viscosity_nodal_dvar")
139 : nullptr),
140 _relative_permeability(
141 ((_use_mobility && _has_mobility) ||
142 (_use_relative_permeability && _has_relative_permeability))
143 ? &getMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_nodal")
144 : nullptr),
145 _drelative_permeability_dvar(((_use_mobility && _has_mobility) ||
146 (_use_relative_permeability && _has_relative_permeability))
147 ? &getMaterialProperty<std::vector<std::vector<Real>>>(
148 "dPorousFlow_relative_permeability_nodal_dvar")
149 : nullptr),
150 _mass_fractions(
151 (_use_mass_fraction && _has_mass_fraction)
152 ? &getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal")
153 : nullptr),
154 _dmass_fractions_dvar((_use_mass_fraction && _has_mass_fraction)
155 ? &getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
156 "dPorousFlow_mass_frac_nodal_dvar")
157 : nullptr),
158 _enthalpy(_has_enthalpy ? &getMaterialPropertyByName<std::vector<Real>>(
159 "PorousFlow_fluid_phase_enthalpy_nodal")
160 : nullptr),
161 _denthalpy_dvar(_has_enthalpy ? &getMaterialPropertyByName<std::vector<std::vector<Real>>>(
162 "dPorousFlow_fluid_phase_enthalpy_nodal_dvar")
163 : nullptr),
164 _internal_energy(_has_internal_energy ? &getMaterialPropertyByName<std::vector<Real>>(
165 "PorousFlow_fluid_phase_internal_energy_nodal")
166 : nullptr),
167 _dinternal_energy_dvar(_has_internal_energy
168 ? &getMaterialPropertyByName<std::vector<std::vector<Real>>>(
169 "dPorousFlow_fluid_phase_internal_energy_nodal_dvar")
170 : nullptr),
171 _multiplying_var(coupledValue("multiplying_var"))
172{
173 // zero the outflow mass
175
176 if (_ph >= _dictator.numPhases())
177 paramError("fluid_phase",
178 "The Dictator proclaims that the maximum phase index in this simulation is ",
179 _dictator.numPhases() - 1,
180 " whereas you have used ",
181 _ph,
182 ". Remember that indexing starts at 0. You must try harder.");
183
186 "mass_fraction_component",
187 "The Dictator proclaims that the maximum fluid component index in this simulation is ",
189 " whereas you have used ",
190 _sp,
191 ". Remember that indexing starts at 0. Please be assured that the Dictator has noted your "
192 "error.");
193
195 mooseError("PorousFlowLineSink: You have specified function_of=porepressure, but you do not "
196 "have a quadpoint porepressure material");
197
199 mooseError("PorousFlowLineSink: You have specified function_of=temperature, but you do not "
200 "have a quadpoint temperature material");
201
203 mooseError("PorousFlowLineSink: You have specified a fluid component, but do not have a nodal "
204 "mass-fraction material");
205
207 mooseError("PorousFlowLineSink: You have set use_relative_permeability=true, but do not have a "
208 "nodal relative permeability material");
209
211 mooseError("PorousFlowLineSink: You have set use_mobility=true, but do not have nodal density, "
212 "relative permeability or viscosity material");
213
215 mooseError("PorousFlowLineSink: You have set use_enthalpy=true, but do not have a nodal "
216 "enthalpy material");
217
219 mooseError("PorousFlowLineSink: You have set use_internal_energy=true, but do not have a nodal "
220 "internal-energy material");
221
222 // To correctly compute the Jacobian terms,
223 // tell MOOSE that this DiracKernel depends on all the PorousFlow Variables
224 const std::vector<MooseVariableFEBase *> & coupled_vars = _dictator.getCoupledMooseVars();
225 for (unsigned int i = 0; i < coupled_vars.size(); i++)
226 addMooseVariableDependency(coupled_vars[i]);
227}
228
229void
231{
232 // This function gets called just before the DiracKernel is evaluated
233 // so this is a handy place to zero this out.
235 if (_point_fluxes)
237
239}
240
241Real
243{
244 // Get the ID we initially assigned to this point
245 const unsigned current_dirac_ptid = currentPointCachedID();
246 Real outflow = computeQpBaseOutflow(current_dirac_ptid);
247 if (outflow == 0.0)
248 return 0.0;
249
250 outflow *= _multiplying_var[_qp];
251
253 outflow *= (*_relative_permeability)[_i][_ph];
254
255 if (_use_mobility)
256 outflow *= (*_relative_permeability)[_i][_ph] * (*_fluid_density_node)[_i][_ph] /
257 (*_fluid_viscosity)[_i][_ph];
258
260 outflow *= (*_mass_fractions)[_i][_ph][_sp];
261
262 if (_use_enthalpy)
263 outflow *= (*_enthalpy)[_i][_ph];
264
266 outflow *= (*_internal_energy)[_i][_ph];
267
269 outflow * _dt); // this is not thread safe, but DiracKernel's aren't currently threaded
270 if (_point_fluxes)
271 _point_fluxes->add(current_dirac_ptid, outflow);
272
273 return outflow;
274}
275
276Real
281
282Real
284{
285 return jac(jvar);
286}
287
288Real
289PorousFlowLineSink::jac(unsigned int jvar)
290{
292 return 0.0;
293 const unsigned pvar = _dictator.porousFlowVariableNum(jvar);
294
295 Real outflow;
296 Real outflowp;
297 const unsigned current_dirac_ptid = currentPointCachedID();
298 computeQpBaseOutflowJacobian(jvar, current_dirac_ptid, outflow, outflowp);
299 if (outflow == 0.0 && outflowp == 0.0)
300 return 0.0;
301
302 outflow *= _multiplying_var[_qp];
303 outflowp *= _multiplying_var[_qp];
304
306 {
307 const Real relperm_prime = (_i != _j ? 0.0 : (*_drelative_permeability_dvar)[_i][_ph][pvar]);
308 outflowp = (*_relative_permeability)[_i][_ph] * outflowp + relperm_prime * outflow;
309 outflow *= (*_relative_permeability)[_i][_ph];
310 }
311
312 if (_use_mobility)
313 {
314 const Real mob = (*_relative_permeability)[_i][_ph] * (*_fluid_density_node)[_i][_ph] /
315 (*_fluid_viscosity)[_i][_ph];
316 const Real mob_prime =
317 (_i != _j
318 ? 0.0
319 : (*_drelative_permeability_dvar)[_i][_ph][pvar] * (*_fluid_density_node)[_i][_ph] /
320 (*_fluid_viscosity)[_i][_ph] +
321 (*_relative_permeability)[_i][_ph] *
322 (*_dfluid_density_node_dvar)[_i][_ph][pvar] / (*_fluid_viscosity)[_i][_ph] -
323 (*_relative_permeability)[_i][_ph] * (*_fluid_density_node)[_i][_ph] *
324 (*_dfluid_viscosity_dvar)[_i][_ph][pvar] /
325 Utility::pow<2>((*_fluid_viscosity)[_i][_ph]));
326 outflowp = mob * outflowp + mob_prime * outflow;
327 outflow *= mob;
328 }
329
331 {
332 const Real mass_fractions_prime =
333 (_i != _j ? 0.0 : (*_dmass_fractions_dvar)[_i][_ph][_sp][pvar]);
334 outflowp = (*_mass_fractions)[_i][_ph][_sp] * outflowp + mass_fractions_prime * outflow;
335 outflow *= (*_mass_fractions)[_i][_ph][_sp];
336 }
337
338 if (_use_enthalpy)
339 {
340 const Real enthalpy_prime = (_i != _j ? 0.0 : (*_denthalpy_dvar)[_i][_ph][pvar]);
341 outflowp = (*_enthalpy)[_i][_ph] * outflowp + enthalpy_prime * outflow;
342 outflow *= (*_enthalpy)[_i][_ph];
343 }
344
346 {
347 const Real internal_energy_prime = (_i != _j ? 0.0 : (*_dinternal_energy_dvar)[_i][_ph][pvar]);
348 outflowp = (*_internal_energy)[_i][_ph] * outflowp + internal_energy_prime * outflow;
349 // this multiplication was performed, but the code does not need to know: outflow *=
350 // (*_internal_energy)[_i][_ph];
351 }
352
353 return outflowp;
354}
355
356Real
358{
359 return (_p_or_t == PorTchoice::pressure ? (*_pp)[_qp][_ph] : (*_temperature)[_qp]);
360}
361
362Real
363PorousFlowLineSink::dptqp(unsigned pvar) const
364{
365 return (_p_or_t == PorTchoice::pressure ? (*_dpp_dvar)[_qp][_ph][pvar]
366 : (*_dtemperature_dvar)[_qp][pvar]);
367}
void ErrorVector unsigned int
const std::vector< MooseVariableFieldBase * > & getCoupledMooseVars() const
unsigned int _i
unsigned int _qp
unsigned int _j
unsigned currentPointCachedID()
MooseVariableField< T > & _var
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)
void addCoupledVar(const std::string &name, const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
unsigned int number() const
void addMooseVariableDependency(MooseVariableFieldBase *var)
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
unsigned int numPhases() const
The number of fluid phases.
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.
Approximates a borehole by a sequence of Dirac Points.
static InputParameters validParams()
Creates a new PorousFlowLineGeometry This reads the file containing the lines of the form weight x y ...
const std::vector< Real > *const _z_coord
const std::vector< Real > *const _y_coord
const std::vector< Real > *const _x_coord
virtual void addPoints() override
Add Dirac Points to the line sink.
Real dptqp(unsigned pvar) const
If _p_or_t==0, then returns d(quadpoint porepressure)/d(PorousFlow variable), else returns d(quadpoin...
const bool _has_temperature
Whether a quadpoint temperature material exists (for error checking)
const MaterialProperty< std::vector< Real > > *const _pp
Quadpoint pore pressure in each phase.
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
const VariableValue & _multiplying_var
mass flux is multiplied by this variable evaluated at quadpoints
virtual Real computeQpResidual() override
PorTchoice
whether the flux is a function of pressure or temperature
virtual Real computeQpBaseOutflow(unsigned current_dirac_ptid) const =0
Returns the flux from the line sink (before modification by mobility, etc). Derived classes should ov...
Real jac(unsigned int jvar)
Jacobian contribution for the derivative wrt the variable jvar.
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
PorousFlowPointFluxQuantity *const _point_fluxes
Optional recorder of the instantaneous flux at each Dirac point of this line sink.
const bool _use_mobility
Whether the flux will be multiplied by the mobility.
const bool _has_porepressure
Whether a quadpoint porepressure material exists (for error checking)
const bool _has_relative_permeability
Whether a relative permeability material exists (for error checking)
enum PorousFlowLineSink::PorTchoice _p_or_t
PorousFlowSumQuantity & _total_outflow_mass
This is used to hold the total fluid flowing into the line sink for each time step.
const bool _has_mass_fraction
Whether a mass_fraction material exists (for error checking)
const MaterialProperty< std::vector< Real > > *const _fluid_viscosity
Viscosity of each component in each phase.
const bool _use_mass_fraction
Whether the flux will be multiplied by the mass fraction.
static InputParameters validParams()
PorousFlowLineSink(const InputParameters &parameters)
const bool _has_enthalpy
Whether an enthalpy material exists (for error checking)
const MaterialProperty< std::vector< std::vector< Real > > > *const _dpp_dvar
d(quadpoint pore pressure in each phase)/d(PorousFlow variable)
virtual void addPoints() override
Add Dirac Points to the borehole.
Real ptqp() const
If _p_or_t==0, then returns the quadpoint porepressure, else returns the quadpoint temperature.
virtual Real computeQpJacobian() override
const unsigned int _sp
The component number (only used if _use_mass_fraction==true)
virtual void computeQpBaseOutflowJacobian(unsigned jvar, unsigned current_dirac_ptid, Real &outflow, Real &outflowp) const =0
Calculates the BaseOutflow as well as its derivative wrt jvar. Derived classes should override this.
const unsigned int _ph
The phase number.
const bool _use_enthalpy
Whether the flux will be multiplied by the enthalpy.
const bool _has_internal_energy
Whether an internal-energy material exists (for error checking)
const bool _use_relative_permeability
Whether the flux will be multiplied by the relative permeability.
const bool _use_internal_energy
Whether the flux will be multiplied by the internal-energy.
const bool _has_mobility
Whether enough materials exist to form the mobility (for error checking)
Records the instantaneous flux at each Dirac point of a PorousFlow line sink (such as PorousFlowPeace...
void zero(const std::vector< Real > &xs, const std::vector< Real > &ys, const std::vector< Real > &zs)
Resets the flux recorded at every point to zero, and records the current point coordinates.
void add(std::size_t i, Real contrib)
Adds contrib to the flux recorded at point i.
Sums into _total This is used, for instance, to record the total mass flowing into a borehole.
void add(Real contrib)
Adds contrib to _total.
void zero()
Sets _total = 0.