www.mooseframework.org
RichardsPiecewiseLinearSink.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 
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.addParam<std::vector<UserObjectName>>("relperm_UO",
36  "List of names of user objects that "
37  "define relative permeability. Only "
38  "needed if fully_upwind is used");
39  params.addParam<std::vector<UserObjectName>>(
40  "seff_UO",
41  "List of name of user objects that define effective saturation as a function of "
42  "pressure list. Only needed if fully_upwind is used");
43  params.addParam<std::vector<UserObjectName>>("density_UO",
44  "List of names of user objects that "
45  "define the fluid density. Only "
46  "needed if fully_upwind is used");
47  params.addRequiredParam<std::vector<Real>>(
48  "pressures", "Tuple of pressure values. Must be monotonically increasing.");
49  params.addRequiredParam<std::vector<Real>>(
50  "bare_fluxes",
51  "Tuple of flux values (measured in kg.m^-2.s^-1 for use_mobility=false, and "
52  "in Pa.s^-1 if use_mobility=true). This flux is OUT of the medium: hence "
53  "positive values of flux means this will be a SINK, while negative values "
54  "indicate this flux will be a SOURCE. A piecewise-linear fit is performed to "
55  "the (pressure,bare_fluxes) pairs to obtain the flux at any arbitrary "
56  "pressure, and the first or last bare_flux values are used if the quad-point "
57  "pressure falls outside this range.");
58  params.addParam<FunctionName>("multiplying_fcn",
59  1.0,
60  "If this function is provided, the flux "
61  "will be multiplied by this function. "
62  "This is useful for spatially or "
63  "temporally varying sinks");
64  params.addRequiredParam<UserObjectName>(
65  "richardsVarNames_UO", "The UserObject that holds the list of Richards variable names.");
66  params.addParam<bool>("fully_upwind", false, "Use full upwinding");
67  params.addParam<PostprocessorName>(
68  "area_pp",
69  1,
70  "An area postprocessor. If given, the bare_fluxes will be divided by this "
71  "quantity. This means the bare fluxes are measured in kg.s^-1. This is "
72  "useful for the case when you wish to provide the *total* flux, and let MOOSE "
73  "proportion it uniformly across the boundary. In that case you would have "
74  "use_mobility=false=use_relperm, and only one bare flux should be specified");
75  return params;
76 }
77 
79  : IntegratedBC(parameters),
80  _use_mobility(getParam<bool>("use_mobility")),
81  _use_relperm(getParam<bool>("use_relperm")),
82  _fully_upwind(getParam<bool>("fully_upwind")),
83 
84  _sink_func(getParam<std::vector<Real>>("pressures"),
85  getParam<std::vector<Real>>("bare_fluxes")),
86 
87  _m_func(getFunction("multiplying_fcn")),
88 
89  _richards_name_UO(getUserObject<RichardsVarNames>("richardsVarNames_UO")),
90  _num_p(_richards_name_UO.num_v()),
91  _pvar(_richards_name_UO.richards_var_num(_var.number())),
92 
93  // in the following, getUserObjectByName returns a reference (an alias) to a RichardsBLAH user
94  // object, and the & turns it into a pointer
95  _density_UO(_fully_upwind ? &getUserObjectByName<RichardsDensity>(
96  getParam<std::vector<UserObjectName>>("density_UO")[_pvar])
97  : NULL),
98  _seff_UO(_fully_upwind ? &getUserObjectByName<RichardsSeff>(
99  getParam<std::vector<UserObjectName>>("seff_UO")[_pvar])
100  : NULL),
101  _relperm_UO(_fully_upwind ? &getUserObjectByName<RichardsRelPerm>(
102  getParam<std::vector<UserObjectName>>("relperm_UO")[_pvar])
103  : NULL),
104 
105  _area_pp(getPostprocessorValue("area_pp")),
106 
107  _num_nodes(0),
108  _nodal_density(0),
109  _dnodal_density_dv(0),
110  _nodal_relperm(0),
111  _dnodal_relperm_dv(0),
112 
113  _pp(getMaterialProperty<std::vector<Real>>("porepressure")),
114  _dpp_dv(getMaterialProperty<std::vector<std::vector<Real>>>("dporepressure_dv")),
115 
116  _viscosity(getMaterialProperty<std::vector<Real>>("viscosity")),
117  _permeability(getMaterialProperty<RealTensorValue>("permeability")),
118 
119  _dseff_dv(getMaterialProperty<std::vector<std::vector<Real>>>("ds_eff_dv")),
120 
121  _rel_perm(getMaterialProperty<std::vector<Real>>("rel_perm")),
122  _drel_perm_dv(getMaterialProperty<std::vector<std::vector<Real>>>("drel_perm_dv")),
123 
124  _density(getMaterialProperty<std::vector<Real>>("density")),
125  _ddensity_dv(getMaterialProperty<std::vector<std::vector<Real>>>("ddensity_dv"))
126 {
127  _ps_at_nodes.resize(_num_p);
128  for (unsigned int pnum = 0; pnum < _num_p; ++pnum)
130 }
131 
132 void
134 {
135  // NOTE: i'm assuming that all the richards variables are pressure values
136 
137  _num_nodes = (*_ps_at_nodes[_pvar]).size();
138 
139  Real p;
140  Real seff;
141  std::vector<Real> dseff_dp;
142  Real drelperm_ds;
143 
144  _nodal_density.resize(_num_nodes);
146  _nodal_relperm.resize(_num_nodes);
148  dseff_dp.resize(_num_p);
149  for (unsigned int nodenum = 0; nodenum < _num_nodes; ++nodenum)
150  {
151  // retrieve and calculate basic things at the node
152  p = (*_ps_at_nodes[_pvar])[nodenum]; // pressure of fluid _pvar at node nodenum
153 
154  _nodal_density[nodenum] = _density_UO->density(p); // density of fluid _pvar at node nodenum
155  _dnodal_density_dv[nodenum].resize(_num_p);
156  for (unsigned int ph = 0; ph < _num_p; ++ph)
157  _dnodal_density_dv[nodenum][ph] = 0;
158  _dnodal_density_dv[nodenum][_pvar] = _density_UO->ddensity(p); // d(density)/dP
159 
160  seff = _seff_UO->seff(_ps_at_nodes,
161  nodenum); // effective saturation of fluid _pvar at node nodenum
162  _seff_UO->dseff(
163  _ps_at_nodes, nodenum, dseff_dp); // d(seff)/d(P_ph), for ph = 0, ..., _num_p - 1
164 
165  _nodal_relperm[nodenum] =
166  _relperm_UO->relperm(seff); // relative permeability of fluid _pvar at node nodenum
167  drelperm_ds = _relperm_UO->drelperm(seff); // d(relperm)/dseff
168 
169  _dnodal_relperm_dv[nodenum].resize(_num_p);
170  for (unsigned int ph = 0; ph < _num_p; ++ph)
171  _dnodal_relperm_dv[nodenum][ph] = drelperm_ds * dseff_dp[ph];
172  }
173 }
174 
175 void
177 {
178  if (_fully_upwind)
180  IntegratedBC::computeResidual();
181 }
182 
183 Real
185 {
186  Real flux = 0;
187  Real k = 0;
188 
189  if (!_fully_upwind)
190  {
191  flux = _test[_i][_qp] * _sink_func.sample(_pp[_qp][_pvar]);
192  if (_use_mobility)
193  {
194  k = (_permeability[_qp] * _normals[_qp]) * _normals[_qp];
195  flux *= _density[_qp][_pvar] * k / _viscosity[_qp][_pvar];
196  }
197  if (_use_relperm)
198  flux *= _rel_perm[_qp][_pvar];
199  }
200  else
201  {
202  flux = _test[_i][_qp] * _sink_func.sample((*_ps_at_nodes[_pvar])[_i]);
203  if (_use_mobility)
204  {
205  k = (_permeability[0] * _normals[_qp]) * _normals[_qp]; // assume that _permeability is
206  // constant throughout element so
207  // doesn't need to be upwinded
208  flux *= _nodal_density[_i] * k /
209  _viscosity[0][_pvar]; // assume that viscosity is constant throughout element
210  }
211  if (_use_relperm)
212  flux *= _nodal_relperm[_i];
213  }
214 
215  flux *= _m_func.value(_t, _q_point[_qp]);
216 
217  if (_area_pp == 0.0)
218  {
219  if (flux != 0)
220  mooseError("RichardsPiecewiseLinearSink: flux is nonzero, but area is zero!\n");
221  // if flux == 0, then leave it as zero.
222  }
223  else
224  flux /= _area_pp;
225 
226  return flux;
227 }
228 
229 void
231 {
232  if (_fully_upwind)
234  IntegratedBC::computeJacobian();
235 }
236 
237 Real
239 {
240  return jac(_pvar);
241 }
242 
243 void
245 {
246  if (_fully_upwind)
248  IntegratedBC::computeJacobianBlock(jvar);
249 }
250 
251 Real
253 {
255  return 0.0;
256  unsigned int dvar = _richards_name_UO.richards_var_num(jvar);
257  return jac(dvar);
258 }
259 
260 Real
261 RichardsPiecewiseLinearSink::jac(unsigned int wrt_num)
262 {
263  Real flux = 0;
264  Real deriv = 0;
265  Real k = 0;
266  Real mob = 0;
267  Real mobp = 0;
268  Real phi = 0;
269 
270  if (!_fully_upwind)
271  {
272  flux = _sink_func.sample(_pp[_qp][_pvar]);
273  deriv = _sink_func.sampleDerivative(_pp[_qp][_pvar]) * _dpp_dv[_qp][_pvar][wrt_num];
274  phi = _phi[_j][_qp];
275  if (_use_mobility)
276  {
277  k = (_permeability[_qp] * _normals[_qp]) * _normals[_qp];
278  mob = _density[_qp][_pvar] * k / _viscosity[_qp][_pvar];
279  mobp = _ddensity_dv[_qp][_pvar][wrt_num] * k / _viscosity[_qp][_pvar];
280  deriv = mob * deriv + mobp * flux;
281  flux *= mob;
282  }
283  if (_use_relperm)
284  deriv = _rel_perm[_qp][_pvar] * deriv + _drel_perm_dv[_qp][_pvar][wrt_num] * flux;
285  }
286  else
287  {
288  if (_i != _j)
289  return 0.0; // residual at node _i only depends on variables at that node
290  flux = _sink_func.sample((*_ps_at_nodes[_pvar])[_i]);
291  deriv = (_pvar == wrt_num ? _sink_func.sampleDerivative((*_ps_at_nodes[_pvar])[_i])
292  : 0); // NOTE: i'm assuming that the variables are pressure variables
293  phi = 1;
294  if (_use_mobility)
295  {
296  k = (_permeability[0] * _normals[_qp]) * _normals[_qp];
297  mob = _nodal_density[_i] * k / _viscosity[0][_pvar];
298  mobp = _dnodal_density_dv[_i][wrt_num] * k / _viscosity[0][_pvar];
299  deriv = mob * deriv + mobp * flux;
300  flux *= mob;
301  }
302  if (_use_relperm)
303  deriv = _nodal_relperm[_i] * deriv + _dnodal_relperm_dv[_i][wrt_num] * flux;
304  }
305 
306  deriv *= _m_func.value(_t, _q_point[_qp]);
307 
308  if (_area_pp == 0.0)
309  {
310  if (deriv != 0)
311  mooseError("RichardsPiecewiseLinearSink: deriv is nonzero, but area is zero!\n");
312  // if deriv == 0, then leave it as zero.
313  }
314  else
315  deriv /= _area_pp;
316 
317  return _test[_i][_qp] * deriv * phi;
318 }
RichardsPiecewiseLinearSink::_dnodal_density_dv
std::vector< std::vector< Real > > _dnodal_density_dv
d(_nodal_density)/d(variable_ph) (variable_ph is the variable for phase=ph) These are used in the jac...
Definition: RichardsPiecewiseLinearSink.h:107
RichardsPiecewiseLinearSink::_pvar
unsigned int _pvar
the moose internal variable number corresponding to the porepressure of this sink flux
Definition: RichardsPiecewiseLinearSink.h:80
RichardsPiecewiseLinearSink::_density
const MaterialProperty< std::vector< Real > > & _density
fluid density (only the _pvar component is used)
Definition: RichardsPiecewiseLinearSink.h:146
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
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 ...
RichardsPiecewiseLinearSink::_seff_UO
const RichardsSeff * _seff_UO
user object defining the effective saturation. Only used if _fully_upwind = true
Definition: RichardsPiecewiseLinearSink.h:86
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
RichardsSeff
Base class for effective saturation as a function of porepressure(s) The functions seff,...
Definition: RichardsSeff.h:23
RichardsPiecewiseLinearSink::computeQpOffDiagJacobian
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
Definition: RichardsPiecewiseLinearSink.C:252
RichardsPiecewiseLinearSink::_area_pp
const PostprocessorValue & _area_pp
area postprocessor. if given then all bare_fluxes are divided by this quantity
Definition: RichardsPiecewiseLinearSink.h:92
RichardsPiecewiseLinearSink::_dpp_dv
const MaterialProperty< std::vector< std::vector< Real > > > & _dpp_dv
d(porepressure_i)/d(variable_j)
Definition: RichardsPiecewiseLinearSink.h:125
RichardsPiecewiseLinearSink::_use_mobility
bool _use_mobility
whether to multiply the sink flux by permeability*density/viscosity
Definition: RichardsPiecewiseLinearSink.h:59
RichardsPiecewiseLinearSink::prepareNodalValues
void prepareNodalValues()
calculates the nodal values of pressure, mobility, and derivatives thereof
Definition: RichardsPiecewiseLinearSink.C:133
RichardsPiecewiseLinearSink::_pp
const MaterialProperty< std::vector< Real > > & _pp
porepressure values (only the _pvar component is used)
Definition: RichardsPiecewiseLinearSink.h:122
RichardsPiecewiseLinearSink::_dnodal_relperm_dv
std::vector< std::vector< Real > > _dnodal_relperm_dv
d(_nodal_relperm)/d(variable_ph) (variable_ph is the variable for phase=ph) These are used in the jac...
Definition: RichardsPiecewiseLinearSink.h:119
RichardsPiecewiseLinearSink::computeQpResidual
virtual Real computeQpResidual() override
Definition: RichardsPiecewiseLinearSink.C:184
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...
RichardsPiecewiseLinearSink::_num_p
unsigned int _num_p
number of richards variables
Definition: RichardsPiecewiseLinearSink.h:77
RichardsPiecewiseLinearSink::_viscosity
const MaterialProperty< std::vector< Real > > & _viscosity
viscosity (only the _pvar component is used)
Definition: RichardsPiecewiseLinearSink.h:128
RichardsPiecewiseLinearSink::jac
Real jac(unsigned int wrt_num)
derivative of residual wrt the wrt_num Richards variable
Definition: RichardsPiecewiseLinearSink.C:261
RichardsPiecewiseLinearSink::_num_nodes
unsigned int _num_nodes
number of nodes in this element. Only used if _fully_upwind = true
Definition: RichardsPiecewiseLinearSink.h:95
RichardsPiecewiseLinearSink::computeQpJacobian
virtual Real computeQpJacobian() override
Definition: RichardsPiecewiseLinearSink.C:238
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
RichardsPiecewiseLinearSink::_sink_func
LinearInterpolation _sink_func
piecewise-linear function of porepressure (this defines the strength of the sink)
Definition: RichardsPiecewiseLinearSink.h:68
RichardsPiecewiseLinearSink::_drel_perm_dv
const MaterialProperty< std::vector< std::vector< Real > > > & _drel_perm_dv
d(relperm_i)/d(variable_j)
Definition: RichardsPiecewiseLinearSink.h:143
RichardsPiecewiseLinearSink::_nodal_density
std::vector< Real > _nodal_density
nodal values of fluid density These are used if _fully_upwind = true
Definition: RichardsPiecewiseLinearSink.h:101
RichardsPiecewiseLinearSink::computeResidual
virtual void computeResidual() override
Definition: RichardsPiecewiseLinearSink.C:176
RichardsPiecewiseLinearSink::_use_relperm
bool _use_relperm
whether to multiply the sink flux by relative permeability
Definition: RichardsPiecewiseLinearSink.h:62
RichardsPiecewiseLinearSink::_density_UO
const RichardsDensity * _density_UO
user object defining the density. Only used if _fully_upwind = true
Definition: RichardsPiecewiseLinearSink.h:83
registerMooseObject
registerMooseObject("RichardsApp", RichardsPiecewiseLinearSink)
validParams< RichardsPiecewiseLinearSink >
InputParameters validParams< RichardsPiecewiseLinearSink >()
Definition: RichardsPiecewiseLinearSink.C:22
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...
RichardsRelPerm::drelperm
virtual Real drelperm(Real seff) const =0
derivative of relative permeability wrt effective saturation This must be over-ridden in your derived...
RichardsPiecewiseLinearSink::_nodal_relperm
std::vector< Real > _nodal_relperm
nodal values of relative permeability These are used if _fully_upwind = true
Definition: RichardsPiecewiseLinearSink.h:113
RichardsPiecewiseLinearSink::_m_func
const Function & _m_func
sink flux gets multiplied by this function
Definition: RichardsPiecewiseLinearSink.h:71
RichardsPiecewiseLinearSink::_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: RichardsPiecewiseLinearSink.h:159
RichardsPiecewiseLinearSink::_permeability
const MaterialProperty< RealTensorValue > & _permeability
permeability
Definition: RichardsPiecewiseLinearSink.h:131
RichardsPiecewiseLinearSink::computeJacobianBlock
virtual void computeJacobianBlock(MooseVariableFEBase &jvar) override
Definition: RichardsPiecewiseLinearSink.C:244
RichardsPiecewiseLinearSink::_rel_perm
const MaterialProperty< std::vector< Real > > & _rel_perm
relative permeability (only the _pvar component is used)
Definition: RichardsPiecewiseLinearSink.h:140
RichardsPiecewiseLinearSink
Applies a flux sink to a boundary The sink is a piecewise linear function of porepressure (the "varia...
Definition: RichardsPiecewiseLinearSink.h:39
RichardsPiecewiseLinearSink::computeJacobian
virtual void computeJacobian() override
Definition: RichardsPiecewiseLinearSink.C:230
RichardsPiecewiseLinearSink::_ddensity_dv
const MaterialProperty< std::vector< std::vector< Real > > > & _ddensity_dv
d(density_i)/d(variable_j)
Definition: RichardsPiecewiseLinearSink.h:149
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
RichardsPiecewiseLinearSink.h
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
RichardsPiecewiseLinearSink::_relperm_UO
const RichardsRelPerm * _relperm_UO
user object defining the relative permeability. Only used if _fully_upwind = true
Definition: RichardsPiecewiseLinearSink.h:89
RichardsPiecewiseLinearSink::_fully_upwind
bool _fully_upwind
whether to use full upwinding
Definition: RichardsPiecewiseLinearSink.h:65
RichardsPiecewiseLinearSink::_richards_name_UO
const RichardsVarNames & _richards_name_UO
holds info about the names and values of richards variable in the simulation
Definition: RichardsPiecewiseLinearSink.h:74
RichardsPiecewiseLinearSink::RichardsPiecewiseLinearSink
RichardsPiecewiseLinearSink(const InputParameters &parameters)
Definition: RichardsPiecewiseLinearSink.C:78