www.mooseframework.org
RichardsBorehole.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 "RichardsBorehole.h"
11 #include "RotationMatrix.h"
12 
14 
15 template <>
16 InputParameters
18 {
19  InputParameters params = validParams<PeacemanBorehole>();
20  params.addRequiredParam<UserObjectName>(
21  "richardsVarNames_UO", "The UserObject that holds the list of Richards variable names.");
22  params.addParam<std::vector<UserObjectName>>("relperm_UO",
23  "List of names of user objects that "
24  "define relative permeability. Only "
25  "needed if fully_upwind is used");
26  params.addParam<std::vector<UserObjectName>>(
27  "seff_UO",
28  "List of name of user objects that define effective saturation as a function of "
29  "pressure list. Only needed if fully_upwind is used");
30  params.addParam<std::vector<UserObjectName>>("density_UO",
31  "List of names of user objects that "
32  "define the fluid density. Only "
33  "needed if fully_upwind is used");
34  params.addParam<bool>("fully_upwind", false, "Fully upwind the flux");
35  params.addClassDescription("Approximates a borehole in the mesh with given bottomhole pressure, "
36  "and radii using a number of point sinks whose positions are read "
37  "from a file");
38  return params;
39 }
40 
41 RichardsBorehole::RichardsBorehole(const InputParameters & parameters)
42  : PeacemanBorehole(parameters),
43  _fully_upwind(getParam<bool>("fully_upwind")),
44  _richards_name_UO(getUserObject<RichardsVarNames>("richardsVarNames_UO")),
45  _num_p(_richards_name_UO.num_v()),
46  _pvar(_richards_name_UO.richards_var_num(_var.number())),
47 
48  // in the following, getUserObjectByName returns a reference (an alias) to a RichardsBLAH user
49  // object, and the & turns it into a pointer
50  _density_UO(_fully_upwind
51  ? &getUserObjectByName<RichardsDensity>(
52  getParam<std::vector<UserObjectName>>("density_UO")[_pvar])
53  : NULL),
54  _seff_UO(_fully_upwind
55  ? &getUserObjectByName<RichardsSeff>(
56  getParam<std::vector<UserObjectName>>("seff_UO")[_pvar])
57  : NULL),
58  _relperm_UO(_fully_upwind
59  ? &getUserObjectByName<RichardsRelPerm>(
60  getParam<std::vector<UserObjectName>>("relperm_UO")[_pvar])
61  : NULL),
62 
63  _num_nodes(0),
64  _mobility(0),
65  _dmobility_dv(0),
66  _pp(getMaterialProperty<std::vector<Real>>("porepressure")),
67  _dpp_dv(getMaterialProperty<std::vector<std::vector<Real>>>("dporepressure_dv")),
68  _viscosity(getMaterialProperty<std::vector<Real>>("viscosity")),
69  _permeability(getMaterialProperty<RealTensorValue>("permeability")),
70  _dseff_dv(getMaterialProperty<std::vector<std::vector<Real>>>("ds_eff_dv")),
71  _rel_perm(getMaterialProperty<std::vector<Real>>("rel_perm")),
72  _drel_perm_dv(getMaterialProperty<std::vector<std::vector<Real>>>("drel_perm_dv")),
73  _density(getMaterialProperty<std::vector<Real>>("density")),
74  _ddensity_dv(getMaterialProperty<std::vector<std::vector<Real>>>("ddensity_dv"))
75 {
76  _ps_at_nodes.resize(_num_p);
77  for (unsigned int pnum = 0; pnum < _num_p; ++pnum)
79 
80  // To correctly compute the Jacobian terms,
81  // tell MOOSE that this DiracKernel depends on all the Richards Vars
82  const std::vector<MooseVariableFEBase *> & coupled_vars = _richards_name_UO.getCoupledMooseVars();
83  for (unsigned int i = 0; i < coupled_vars.size(); i++)
84  addMooseVariableDependency(coupled_vars[i]);
85 }
86 
87 void
89 {
90  // NOTE: i'm assuming that all the richards variables are pressure values
91 
92  _num_nodes = (*_ps_at_nodes[_pvar]).size();
93 
94  Real p;
95  Real density;
96  Real ddensity_dp;
97  Real seff;
98  std::vector<Real> dseff_dp;
99  Real relperm;
100  Real drelperm_ds;
101  _mobility.resize(_num_nodes);
102  _dmobility_dv.resize(_num_nodes);
103  dseff_dp.resize(_num_p);
104  for (unsigned int nodenum = 0; nodenum < _num_nodes; ++nodenum)
105  {
106  // retrieve and calculate basic things at the node
107  p = (*_ps_at_nodes[_pvar])[nodenum]; // pressure of fluid _pvar at node nodenum
108  density = _density_UO->density(p); // density of fluid _pvar at node nodenum
109  ddensity_dp = _density_UO->ddensity(p); // d(density)/dP
110  seff = _seff_UO->seff(_ps_at_nodes,
111  nodenum); // effective saturation of fluid _pvar at node nodenum
112  _seff_UO->dseff(
113  _ps_at_nodes, nodenum, dseff_dp); // d(seff)/d(P_ph), for ph = 0, ..., _num_p - 1
114  relperm = _relperm_UO->relperm(seff); // relative permeability of fluid _pvar at node nodenum
115  drelperm_ds = _relperm_UO->drelperm(seff); // d(relperm)/dseff
116 
117  // calculate the mobility and its derivatives wrt (variable_ph = porepressure_ph)
118  _mobility[nodenum] =
119  density * relperm / _viscosity[0][_pvar]; // assume viscosity is constant throughout element
120  _dmobility_dv[nodenum].resize(_num_p);
121  for (unsigned int ph = 0; ph < _num_p; ++ph)
122  _dmobility_dv[nodenum][ph] = density * drelperm_ds * dseff_dp[ph] / _viscosity[0][_pvar];
123  _dmobility_dv[nodenum][_pvar] += ddensity_dp * relperm / _viscosity[0][_pvar];
124  }
125 }
126 
127 void
129 {
130  if (_fully_upwind)
132  DiracKernel::computeResidual();
133 }
134 
135 Real
137 {
138  const Real character = _character.value(_t, _q_point[_qp]);
139  if (character == 0.0)
140  return 0.0;
141 
142  const Real bh_pressure =
143  _p_bot +
144  _unit_weight *
145  (_q_point[_qp] -
146  _bottom_point); // really want to use _q_point instaed of _current_point, i think?!
147 
148  Real pp;
149  Real mob;
150  if (!_fully_upwind)
151  {
152  pp = _pp[_qp][_pvar];
153  mob = _rel_perm[_qp][_pvar] * _density[_qp][_pvar] / _viscosity[_qp][_pvar];
154  }
155  else
156  {
157  pp = (*_ps_at_nodes[_pvar])[_i];
158  mob = _mobility[_i];
159  }
160 
161  // Get the ID we initially assigned to this point
162  const unsigned current_dirac_ptid = currentPointCachedID();
163 
164  // If getting the ID failed, fall back to the old bodge!
165  // if (current_dirac_ptid == libMesh::invalid_uint)
166  // current_dirac_ptid = (_zs.size() > 2) ? 1 : 0;
167 
168  Real outflow(0.0); // this is the flow rate from porespace out of the system
169 
170  Real wc(0.0);
171  if (current_dirac_ptid > 0)
172  // contribution from half-segment "behind" this point (must have >1 point for
173  // current_dirac_ptid>0)
174  {
175  wc = wellConstant(_permeability[_qp],
176  _rot_matrix[current_dirac_ptid - 1],
177  _half_seg_len[current_dirac_ptid - 1],
178  _current_elem,
179  _rs[current_dirac_ptid]);
180  if ((character < 0.0 && pp < bh_pressure) || (character > 0.0 && pp > bh_pressure))
181  // injection, so outflow<0 || // production, so outflow>0
182  outflow += _test[_i][_qp] * std::abs(character) * wc * mob * (pp - bh_pressure);
183  }
184 
185  if (current_dirac_ptid + 1 < _zs.size() || _zs.size() == 1)
186  // contribution from half-segment "ahead of" this point, or we only have one point
187  {
188  wc = wellConstant(_permeability[_qp],
189  _rot_matrix[current_dirac_ptid],
190  _half_seg_len[current_dirac_ptid],
191  _current_elem,
192  _rs[current_dirac_ptid]);
193  if ((character < 0.0 && pp < bh_pressure) || (character > 0.0 && pp > bh_pressure))
194  // injection, so outflow<0 || // production, so outflow>0
195  outflow += _test[_i][_qp] * std::abs(character) * wc * mob * (pp - bh_pressure);
196  }
197 
199  outflow * _dt); // this is not thread safe, but DiracKernel's aren't currently threaded
200  return outflow;
201 }
202 
203 void
205 {
206  if (_fully_upwind)
208  DiracKernel::computeJacobian();
209 }
210 
211 Real
213 {
214  const Real character = _character.value(_t, _q_point[_qp]);
215  if (character == 0.0)
216  return 0.0;
217  return jac(_pvar);
218 }
219 
220 Real
222 {
224  return 0.0;
225  const unsigned int dvar = _richards_name_UO.richards_var_num(jvar);
226  return jac(dvar);
227 }
228 
229 Real
230 RichardsBorehole::jac(unsigned int wrt_num)
231 {
232  const Real character = _character.value(_t, _q_point[_qp]);
233  if (character == 0.0)
234  return 0.0;
235 
236  const Real bh_pressure =
237  _p_bot +
238  _unit_weight *
239  (_q_point[_qp] -
240  _bottom_point); // really want to use _q_point instaed of _current_point, i think?!
241 
242  Real pp;
243  Real dpp_dv;
244  Real mob;
245  Real dmob_dv;
246  Real phi;
247  if (!_fully_upwind)
248  {
249  pp = _pp[_qp][_pvar];
250  dpp_dv = _dpp_dv[_qp][_pvar][wrt_num];
251  mob = _rel_perm[_qp][_pvar] * _density[_qp][_pvar] / _viscosity[_qp][_pvar];
252  dmob_dv = (_drel_perm_dv[_qp][_pvar][wrt_num] * _density[_qp][_pvar] +
253  _rel_perm[_qp][_pvar] * _ddensity_dv[_qp][_pvar][wrt_num]) /
254  _viscosity[_qp][_pvar];
255  phi = _phi[_j][_qp];
256  }
257  else
258  {
259  if (_i != _j)
260  return 0.0; // residual at node _i only depends on variables at that node
261  pp = (*_ps_at_nodes[_pvar])[_i];
262  dpp_dv =
263  (_pvar == wrt_num ? 1 : 0); // NOTE: i'm assuming that the variables are pressure variables
264  mob = _mobility[_i];
265  dmob_dv = _dmobility_dv[_i][wrt_num];
266  phi = 1;
267  }
268 
269  // Get the ID we initially assigned to this point
270  const unsigned current_dirac_ptid = currentPointCachedID();
271 
272  // If getting the ID failed, fall back to the old bodge!
273  // if (current_dirac_ptid == libMesh::invalid_uint)
274  // current_dirac_ptid = (_zs.size() > 2) ? 1 : 0;
275 
276  Real outflowp(0.0);
277 
278  Real wc(0.0);
279  if (current_dirac_ptid > 0)
280  // contribution from half-segment "behind" this point
281  {
282  wc = wellConstant(_permeability[_qp],
283  _rot_matrix[current_dirac_ptid - 1],
284  _half_seg_len[current_dirac_ptid - 1],
285  _current_elem,
286  _rs[current_dirac_ptid]);
287  if ((character < 0.0 && pp < bh_pressure) || (character > 0.0 && pp > bh_pressure))
288  // injection, so outflow<0 || // production, so outflow>0
289  outflowp += _test[_i][_qp] * std::abs(character) * wc *
290  (mob * phi * dpp_dv + dmob_dv * phi * (pp - bh_pressure));
291  }
292 
293  if (current_dirac_ptid < _zs.size() - 1 || _zs.size() == 1)
294  // contribution from half-segment "ahead of" this point
295  {
296  wc = wellConstant(_permeability[_qp],
297  _rot_matrix[current_dirac_ptid],
298  _half_seg_len[current_dirac_ptid],
299  _current_elem,
300  _rs[current_dirac_ptid]);
301  if ((character < 0.0 && pp < bh_pressure) || (character > 0.0 && pp > bh_pressure))
302  // injection, so outflow<0 || // production, so outflow>0
303  outflowp += _test[_i][_qp] * std::abs(character) * wc *
304  (mob * phi * dpp_dv + dmob_dv * phi * (pp - bh_pressure));
305  }
306 
307  return outflowp;
308 }
RichardsBorehole
Approximates a borehole by a sequence of Dirac Points.
Definition: RichardsBorehole.h:27
RichardsBorehole::_ps_at_nodes
std::vector< const VariableValue * > _ps_at_nodes
Holds the values of pressures at all the nodes of the element Only used if _fully_upwind = true Eg: _...
Definition: RichardsBorehole.h:145
PeacemanBorehole::_zs
std::vector< Real > _zs
z points of borehole
Definition: PeacemanBorehole.h:91
RichardsBorehole::computeResidual
virtual void computeResidual()
Computes the residual.
Definition: RichardsBorehole.C:128
RichardsVarNames::richards_var_num
unsigned int richards_var_num(unsigned int moose_var_num) const
the richards variable number
Definition: RichardsVarNames.C:99
RichardsRelPerm
Base class for Richards relative permeability classes that provide relative permeability as a functio...
Definition: RichardsRelPerm.h:23
RichardsBorehole::_pp
const MaterialProperty< std::vector< Real > > & _pp
fluid porepressure (or porepressures in case of multiphase)
Definition: RichardsBorehole.h:111
RichardsBorehole::_dpp_dv
const MaterialProperty< std::vector< std::vector< Real > > > & _dpp_dv
d(porepressure_i)/d(variable_j)
Definition: RichardsBorehole.h:114
PeacemanBorehole::_rs
std::vector< Real > _rs
radii of the borehole
Definition: PeacemanBorehole.h:82
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 ...
RichardsBorehole::_num_p
const unsigned int _num_p
number of richards variables
Definition: RichardsBorehole.h:81
PeacemanBorehole::_p_bot
const Real _p_bot
bottomhole pressure of borehole
Definition: PeacemanBorehole.h:69
RichardsSeff::dseff
virtual void dseff(std::vector< const VariableValue * > p, unsigned int qp, std::vector< Real > &result) const =0
derivative(s) of effective saturation as a function of porepressure(s) at given quadpoint of the elem...
RichardsVarNames
This holds maps between pressure_var or pressure_var, sat_var used in RichardsMaterial and kernels,...
Definition: RichardsVarNames.h:25
RichardsBorehole::_permeability
const MaterialProperty< RealTensorValue > & _permeability
material permeability
Definition: RichardsBorehole.h:120
RichardsSeff
Base class for effective saturation as a function of porepressure(s) The functions seff,...
Definition: RichardsSeff.h:23
RichardsBorehole::_drel_perm_dv
const MaterialProperty< std::vector< std::vector< Real > > > & _drel_perm_dv
d(relperm_i)/d(variable_j)
Definition: RichardsBorehole.h:129
RichardsBorehole::computeJacobian
virtual void computeJacobian()
Computes the Jacobian.
Definition: RichardsBorehole.C:204
PeacemanBorehole::wellConstant
Real wellConstant(const RealTensorValue &perm, const RealTensorValue &rot, const Real &half_len, const Elem *ele, const Real &rad)
Calculates Peaceman's form of the borehole well constant Z Chen, Y Zhang, Well flow models for variou...
Definition: PeacemanBorehole.C:194
RichardsBorehole::RichardsBorehole
RichardsBorehole(const InputParameters &parameters)
Creates a new RichardsBorehole This sets all the variables, but also reads the file containing the li...
Definition: RichardsBorehole.C:41
RichardsBorehole::_density
const MaterialProperty< std::vector< Real > > & _density
fluid density
Definition: RichardsBorehole.h:132
RichardsBorehole::_density_UO
const RichardsDensity * _density_UO
user object defining the density. Only used if _fully_upwind = true
Definition: RichardsBorehole.h:87
PeacemanBorehole::_rot_matrix
std::vector< RealTensorValue > _rot_matrix
rotation matrix used in well_constant calculation
Definition: PeacemanBorehole.h:100
RichardsBorehole::_pvar
const unsigned int _pvar
The moose internal variable number of the richards variable of this Dirac Kernel.
Definition: RichardsBorehole.h:84
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...
RichardsBorehole::_dmobility_dv
std::vector< std::vector< Real > > _dmobility_dv
d(_mobility)/d(variable_ph) (variable_ph is the variable for phase=ph) These are used in the jacobian...
Definition: RichardsBorehole.h:108
PeacemanBorehole::_bottom_point
Point _bottom_point
the bottom point of the borehole (where bottom_pressure is defined)
Definition: PeacemanBorehole.h:94
validParams< PeacemanBorehole >
InputParameters validParams< PeacemanBorehole >()
Definition: PeacemanBorehole.C:17
NS::density
const std::string density
Definition: NS.h:16
RichardsBorehole::computeQpJacobian
virtual Real computeQpJacobian()
Computes the diagonal part of the jacobian.
Definition: RichardsBorehole.C:212
RichardsBorehole::_richards_name_UO
const RichardsVarNames & _richards_name_UO
Defines the richards variables in the simulation.
Definition: RichardsBorehole.h:78
PeacemanBorehole
Approximates a borehole by a sequence of Dirac Points.
Definition: PeacemanBorehole.h:25
registerMooseObject
registerMooseObject("RichardsApp", RichardsBorehole)
RichardsVarNames::nodal_var
const VariableValue * nodal_var(unsigned int richards_var_num) const
The nodal variable values for the given richards_var_num To extract a the value of pressure variable ...
Definition: RichardsVarNames.C:142
RichardsBorehole::computeQpResidual
virtual Real computeQpResidual()
Computes the Qp residual.
Definition: RichardsBorehole.C:136
RichardsBorehole::_seff_UO
const RichardsSeff * _seff_UO
user object defining the effective saturation. Only used if _fully_upwind = true
Definition: RichardsBorehole.h:90
RichardsBorehole::_mobility
std::vector< Real > _mobility
nodal values of mobility = density*relperm/viscosity These are used if _fully_upwind = true
Definition: RichardsBorehole.h:102
RichardsBorehole.h
PeacemanBorehole::_half_seg_len
std::vector< Real > _half_seg_len
0.5*(length of polyline segments between points)
Definition: PeacemanBorehole.h:97
RichardsDensity
Base class for fluid density as a function of porepressure The functions density, ddensity and d2dens...
Definition: RichardsDensity.h:24
RichardsBorehole::prepareNodalValues
void prepareNodalValues()
calculates the nodal values of pressure, mobility, and derivatives thereof
Definition: RichardsBorehole.C:88
RichardsBorehole::_ddensity_dv
const MaterialProperty< std::vector< std::vector< Real > > > & _ddensity_dv
d(density_i)/d(variable_j)
Definition: RichardsBorehole.h:135
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...
RichardsRelPerm::drelperm
virtual Real drelperm(Real seff) const =0
derivative of relative permeability wrt effective saturation This must be over-ridden in your derived...
RichardsSumQuantity::add
void add(Real contrib)
adds contrib to _total
Definition: RichardsSumQuantity.C:37
RichardsBorehole::_fully_upwind
const bool _fully_upwind
Whether to use full upwinding.
Definition: RichardsBorehole.h:75
PeacemanBorehole::_total_outflow_mass
RichardsSumQuantity & _total_outflow_mass
This is used to hold the total fluid flowing into the borehole Hence, it is positive for production w...
Definition: PeacemanBorehole.h:79
RichardsBorehole::_relperm_UO
const RichardsRelPerm * _relperm_UO
user object defining the relative permeability. Only used if _fully_upwind = true
Definition: RichardsBorehole.h:93
RichardsBorehole::jac
Real jac(unsigned int wrt_num)
Calculates Jacobian.
Definition: RichardsBorehole.C:230
RichardsBorehole::_viscosity
const MaterialProperty< std::vector< Real > > & _viscosity
fluid viscosity
Definition: RichardsBorehole.h:117
validParams< RichardsBorehole >
InputParameters validParams< RichardsBorehole >()
Definition: RichardsBorehole.C:17
PeacemanBorehole::_character
const Function & _character
If positive then the borehole acts as a sink (producion well) for porepressure > borehole pressure,...
Definition: PeacemanBorehole.h:66
RichardsBorehole::computeQpOffDiagJacobian
virtual Real computeQpOffDiagJacobian(unsigned int jvar)
Computes the off-diagonal part of the jacobian Note: at March2014 this is never called since moose do...
Definition: RichardsBorehole.C:221
RichardsBorehole::_rel_perm
const MaterialProperty< std::vector< Real > > & _rel_perm
relative permeability
Definition: RichardsBorehole.h:126
RichardsSeff::seff
virtual Real seff(std::vector< const VariableValue * > p, unsigned int qp) const =0
effective saturation as a function of porepressure(s) at given quadpoint of the element
PeacemanBorehole::_unit_weight
const RealVectorValue _unit_weight
unit weight of fluid in borehole (for calculating bottomhole pressure at each Dirac Point)
Definition: PeacemanBorehole.h:72
RichardsVarNames::not_richards_var
bool not_richards_var(unsigned int moose_var_num) const
returns true if moose_var_num is not a richards var
Definition: RichardsVarNames.C:109
RichardsBorehole::_num_nodes
unsigned int _num_nodes
number of nodes in this element. Only used if _fully_upwind = true
Definition: RichardsBorehole.h:96