www.mooseframework.org
Q2PPiecewiseLinearSink.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 "Q2PPiecewiseLinearSink.h"
11 
12 // MOOSE includes
13 #include "MooseVariable.h"
14 
15 // C++ includes
16 #include <iostream>
17 
19 
20 template <>
21 InputParameters
23 {
24  InputParameters params = validParams<IntegratedBC>();
25  params.addRequiredParam<bool>(
26  "use_mobility",
27  "If true, then fluxes are multiplied by (density*permeability_nn/viscosity), "
28  "where the '_nn' indicates the component normal to the boundary. In this "
29  "case bare_flux is measured in Pa.s^-1. This can be used in conjunction "
30  "with use_relperm.");
31  params.addRequiredParam<bool>("use_relperm",
32  "If true, then fluxes are multiplied by relative "
33  "permeability. This can be used in conjunction "
34  "with use_mobility");
35  params.addRequiredParam<std::vector<Real>>(
36  "pressures", "Tuple of pressure values. Must be monotonically increasing.");
37  params.addRequiredParam<std::vector<Real>>(
38  "bare_fluxes",
39  "Tuple of flux values (measured in kg.m^-2.s^-1 for use_mobility=false, and "
40  "in Pa.s^-1 if use_mobility=true). This flux is OUT of the medium: hence "
41  "positive values of flux means this will be a SINK, while negative values "
42  "indicate this flux will be a SOURCE. A piecewise-linear fit is performed to "
43  "the (pressure,bare_fluxes) pairs to obtain the flux at any arbitrary "
44  "pressure, and the first or last bare_flux values are used if the quad-point "
45  "pressure falls outside this range.");
46  params.addParam<FunctionName>("multiplying_fcn",
47  1.0,
48  "If this function is provided, the flux "
49  "will be multiplied by this function. "
50  "This is useful for spatially or "
51  "temporally varying sinks");
52  params.addRequiredParam<UserObjectName>(
53  "fluid_density",
54  "A RichardsDensity UserObject that defines the fluid density as a function of pressure.");
55  params.addRequiredParam<UserObjectName>(
56  "fluid_relperm",
57  "A RichardsRelPerm UserObject (eg RichardsRelPermPower) that defines the "
58  "fluid relative permeability as a function of the saturation Variable.");
59  params.addRequiredCoupledVar("other_var",
60  "The other variable in the 2-phase system. If "
61  "Variable=porepressure, the other_var=saturation, and "
62  "vice-versa.");
63  params.addRequiredParam<bool>("var_is_porepressure",
64  "This flag is needed to correctly calculate the Jacobian entries. "
65  "If set to true, this Sink will extract fluid from the phase with "
66  "porepressure as its Variable (usually the liquid phase). If set "
67  "to false, this Sink will extract fluid from the phase with "
68  "saturation as its variable (usually the gas phase)");
69  params.addRequiredParam<Real>("fluid_viscosity", "The fluid dynamic viscosity");
70  params.addClassDescription("Sink of fluid, controlled by (pressure, bare_fluxes) interpolation. "
71  "This is for use in Q2P models");
72  return params;
73 }
74 
75 Q2PPiecewiseLinearSink::Q2PPiecewiseLinearSink(const InputParameters & parameters)
76  : IntegratedBC(parameters),
77  _use_mobility(getParam<bool>("use_mobility")),
78  _use_relperm(getParam<bool>("use_relperm")),
79  _sink_func(getParam<std::vector<Real>>("pressures"),
80  getParam<std::vector<Real>>("bare_fluxes")),
81  _m_func(getFunction("multiplying_fcn")),
82  _density(getUserObject<RichardsDensity>("fluid_density")),
83  _relperm(getUserObject<RichardsRelPerm>("fluid_relperm")),
84  _other_var_nodal(coupledDofValues("other_var")),
85  _other_var_num(coupled("other_var")),
86  _var_is_pp(getParam<bool>("var_is_porepressure")),
87  _viscosity(getParam<Real>("fluid_viscosity")),
88  _permeability(getMaterialProperty<RealTensorValue>("permeability")),
89  _num_nodes(0),
90  _pp(0),
91  _sat(0),
92  _nodal_density(0),
93  _dnodal_density_dp(0),
94  _nodal_relperm(0),
95  _dnodal_relperm_ds(0)
96 {
97 }
98 
99 void
101 {
102  _num_nodes = _other_var_nodal.size();
103 
104  // set _pp and _sat variables
105  _pp.resize(_num_nodes);
106  _sat.resize(_num_nodes);
107  if (_var_is_pp)
108  {
109  for (unsigned int nodenum = 0; nodenum < _num_nodes; ++nodenum)
110  {
111  _pp[nodenum] = _var.dofValues()[nodenum];
112  _sat[nodenum] = _other_var_nodal[nodenum];
113  }
114  }
115  else
116  {
117  for (unsigned int nodenum = 0; nodenum < _num_nodes; ++nodenum)
118  {
119  _pp[nodenum] = _other_var_nodal[nodenum];
120  _sat[nodenum] = _var.dofValues()[nodenum];
121  }
122  }
123 
124  // calculate derived things
125  if (_use_mobility)
126  {
127  _nodal_density.resize(_num_nodes);
129  for (unsigned int nodenum = 0; nodenum < _num_nodes; ++nodenum)
130  {
131  _nodal_density[nodenum] = _density.density(_pp[nodenum]);
132  _dnodal_density_dp[nodenum] = _density.ddensity(_pp[nodenum]);
133  }
134  }
135 
136  if (_use_relperm)
137  {
138  _nodal_relperm.resize(_num_nodes);
140  for (unsigned int nodenum = 0; nodenum < _num_nodes; ++nodenum)
141  {
142  _nodal_relperm[nodenum] = _relperm.relperm(_sat[nodenum]);
143  _dnodal_relperm_ds[nodenum] = _relperm.drelperm(_sat[nodenum]);
144  }
145  }
146 }
147 
148 void
150 {
152  IntegratedBC::computeResidual();
153 }
154 
155 Real
157 {
158  Real flux = 0;
159  Real k = 0;
160 
161  flux = _test[_i][_qp] * _sink_func.sample(_pp[_i]);
162  if (_use_mobility)
163  {
164  k = (_permeability[0] * _normals[_qp]) * _normals[_qp]; // assume that _permeability is constant
165  // throughout element so doesn't need to
166  // be upwinded
167  flux *= _nodal_density[_i] * k / _viscosity;
168  }
169  if (_use_relperm)
170  flux *= _nodal_relperm[_i];
171 
172  flux *= _m_func.value(_t, _q_point[_qp]);
173 
174  return flux;
175 }
176 
177 void
179 {
181  IntegratedBC::computeJacobian();
182 }
183 
184 Real
186 {
187  return jac(_var.number());
188 }
189 
190 void
192 {
194  IntegratedBC::computeJacobianBlock(jvar);
195 }
196 
197 Real
199 {
200  if (jvar == _var.number() || jvar == _other_var_num)
201  return jac(jvar);
202 
203  return 0.0;
204 }
205 
206 Real
207 Q2PPiecewiseLinearSink::jac(unsigned int wrt_num)
208 {
209  Real flux = 0;
210  Real deriv = 0;
211  Real k = 0;
212  Real mob = 0;
213  Real mobp = 0;
214  Real phi = 1;
215 
216  if (_i != _j)
217  return 0.0; // residual at node _i only depends on variables at that node
218 
219  flux = _sink_func.sample(_pp[_i]);
220 
221  if (_var_is_pp)
222  {
223  // derivative of the _sink_func
224  if (wrt_num == _var.number())
225  deriv = _sink_func.sampleDerivative(_pp[_i]);
226  else
227  deriv = 0;
228 
229  // add derivative of the mobility
230  if (_use_mobility)
231  {
232  k = (_permeability[0] * _normals[_qp]) * _normals[_qp];
233  mob = _nodal_density[_i] * k / _viscosity;
234  if (wrt_num == _var.number())
235  mobp = _dnodal_density_dp[_i] * k / _viscosity; // else mobp = 0
236  deriv = mob * deriv + mobp * flux;
237  flux *= mob;
238  }
239 
240  // add derivative of the relperm
241  if (_use_relperm)
242  {
243  if (wrt_num == _other_var_num)
244  deriv = _nodal_relperm[_i] * deriv + _dnodal_relperm_ds[_i] * flux;
245  else
246  deriv = _nodal_relperm[_i] * deriv;
247  }
248  }
249  else
250  {
251  // derivative of the _sink_func
252  if (wrt_num == _other_var_num)
253  deriv = _sink_func.sampleDerivative(_pp[_i]);
254  else
255  deriv = 0;
256 
257  // add derivative of the mobility
258  if (_use_mobility)
259  {
260  k = (_permeability[0] * _normals[_qp]) * _normals[_qp];
261  mob = _nodal_density[_i] * k / _viscosity;
262  if (wrt_num == _other_var_num)
263  mobp = _dnodal_density_dp[_i] * k / _viscosity; // else mobp = 0
264  deriv = mob * deriv + mobp * flux;
265  flux *= mob;
266  }
267 
268  // add derivative of the relperm
269  if (_use_relperm)
270  {
271  if (wrt_num == _var.number())
272  deriv = _nodal_relperm[_i] * deriv + _dnodal_relperm_ds[_i] * flux;
273  else
274  deriv = _nodal_relperm[_i] * deriv;
275  }
276  }
277 
278  deriv *= _m_func.value(_t, _q_point[_qp]);
279 
280  return _test[_i][_qp] * deriv * phi;
281 }
Q2PPiecewiseLinearSink::_permeability
const MaterialProperty< RealTensorValue > & _permeability
permeability
Definition: Q2PPiecewiseLinearSink.h:86
Q2PPiecewiseLinearSink::_nodal_relperm
std::vector< Real > _nodal_relperm
nodal values of relative permeability
Definition: Q2PPiecewiseLinearSink.h:104
RichardsRelPerm
Base class for Richards relative permeability classes that provide relative permeability as a functio...
Definition: RichardsRelPerm.h:23
Q2PPiecewiseLinearSink::computeQpJacobian
virtual Real computeQpJacobian() override
Definition: Q2PPiecewiseLinearSink.C:185
RichardsRelPerm::relperm
virtual Real relperm(Real seff) const =0
relative permeability as a function of effective saturation This must be over-ridden in your derived ...
Q2PPiecewiseLinearSink
Applies a fully-upwinded flux sink to a boundary The sink is a piecewise linear function of porepress...
Definition: Q2PPiecewiseLinearSink.h:36
Q2PPiecewiseLinearSink::_pp
std::vector< Real > _pp
nodal values of porepressure
Definition: Q2PPiecewiseLinearSink.h:92
Q2PPiecewiseLinearSink::_other_var_nodal
const VariableValue & _other_var_nodal
the other variable in the 2-phase system (this is saturation if Variable=porepressure,...
Definition: Q2PPiecewiseLinearSink.h:74
Q2PPiecewiseLinearSink::_dnodal_relperm_ds
std::vector< Real > _dnodal_relperm_ds
d(_nodal_relperm)/d(saturation)
Definition: Q2PPiecewiseLinearSink.h:107
Q2PPiecewiseLinearSink::_use_mobility
bool _use_mobility
whether to multiply the sink flux by permeability*density/viscosity
Definition: Q2PPiecewiseLinearSink.h:56
Q2PPiecewiseLinearSink::prepareNodalValues
void prepareNodalValues()
calculates the nodal values of pressure, mobility, and derivatives thereof
Definition: Q2PPiecewiseLinearSink.C:100
Q2PPiecewiseLinearSink::Q2PPiecewiseLinearSink
Q2PPiecewiseLinearSink(const InputParameters &parameters)
Definition: Q2PPiecewiseLinearSink.C:75
Q2PPiecewiseLinearSink::_relperm
const RichardsRelPerm & _relperm
fluid relative permeability
Definition: Q2PPiecewiseLinearSink.h:71
RichardsDensity::density
virtual Real density(Real p) const =0
fluid density as a function of porepressure This must be over-ridden in derived classes to provide an...
Q2PPiecewiseLinearSink::_num_nodes
unsigned int _num_nodes
number of nodes in this element.
Definition: Q2PPiecewiseLinearSink.h:89
Q2PPiecewiseLinearSink::_density
const RichardsDensity & _density
fluid density
Definition: Q2PPiecewiseLinearSink.h:68
Q2PPiecewiseLinearSink::_sat
std::vector< Real > _sat
nodal values of saturation
Definition: Q2PPiecewiseLinearSink.h:95
Q2PPiecewiseLinearSink::computeResidual
virtual void computeResidual() override
Definition: Q2PPiecewiseLinearSink.C:149
Q2PPiecewiseLinearSink::computeJacobianBlock
virtual void computeJacobianBlock(MooseVariableFEBase &jvar) override
Definition: Q2PPiecewiseLinearSink.C:191
validParams< Q2PPiecewiseLinearSink >
InputParameters validParams< Q2PPiecewiseLinearSink >()
Definition: Q2PPiecewiseLinearSink.C:22
Q2PPiecewiseLinearSink::_viscosity
Real _viscosity
viscosity
Definition: Q2PPiecewiseLinearSink.h:83
Q2PPiecewiseLinearSink::_var_is_pp
bool _var_is_pp
whether the Variable for this BC is porepressure or not
Definition: Q2PPiecewiseLinearSink.h:80
Q2PPiecewiseLinearSink::_use_relperm
bool _use_relperm
whether to multiply the sink flux by relative permeability
Definition: Q2PPiecewiseLinearSink.h:59
Q2PPiecewiseLinearSink::jac
Real jac(unsigned int wrt_num)
derivative of residual wrt the wrt_num variable
Definition: Q2PPiecewiseLinearSink.C:207
RichardsDensity
Base class for fluid density as a function of porepressure The functions density, ddensity and d2dens...
Definition: RichardsDensity.h:24
RichardsDensity::ddensity
virtual Real ddensity(Real p) const =0
derivative of fluid density wrt porepressure This must be over-ridden in derived classes to provide a...
Q2PPiecewiseLinearSink::computeQpOffDiagJacobian
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
Definition: Q2PPiecewiseLinearSink.C:198
registerMooseObject
registerMooseObject("RichardsApp", Q2PPiecewiseLinearSink)
RichardsRelPerm::drelperm
virtual Real drelperm(Real seff) const =0
derivative of relative permeability wrt effective saturation This must be over-ridden in your derived...
Q2PPiecewiseLinearSink::_m_func
const Function & _m_func
sink flux gets multiplied by this function
Definition: Q2PPiecewiseLinearSink.h:65
Q2PPiecewiseLinearSink::_other_var_num
unsigned int _other_var_num
the variable number of the other variable
Definition: Q2PPiecewiseLinearSink.h:77
Q2PPiecewiseLinearSink::_nodal_density
std::vector< Real > _nodal_density
nodal values of fluid density
Definition: Q2PPiecewiseLinearSink.h:98
Q2PPiecewiseLinearSink::_dnodal_density_dp
std::vector< Real > _dnodal_density_dp
d(_nodal_density)/d(porepressure)
Definition: Q2PPiecewiseLinearSink.h:101
Q2PPiecewiseLinearSink.h
Q2PPiecewiseLinearSink::computeJacobian
virtual void computeJacobian() override
Definition: Q2PPiecewiseLinearSink.C:178
Q2PPiecewiseLinearSink::computeQpResidual
virtual Real computeQpResidual() override
Definition: Q2PPiecewiseLinearSink.C:156
Q2PPiecewiseLinearSink::_sink_func
LinearInterpolation _sink_func
piecewise-linear function of porepressure (this defines the strength of the sink)
Definition: Q2PPiecewiseLinearSink.h:62