14 #include "MooseVariable.h"
15 #include "SystemBase.h"
17 #include "libmesh/quadrature.h"
28 InputParameters params = validParams<Kernel>();
29 params.addRequiredParam<UserObjectName>(
31 "A RichardsDensity UserObject that defines the fluid density as a function of pressure.");
32 params.addRequiredCoupledVar(
"porepressure_variable",
33 "The variable representing the porepressure");
34 params.addRequiredParam<UserObjectName>(
36 "A RichardsRelPerm UserObject (eg RichardsRelPermPowerGas) that defines the "
37 "fluid relative permeability as a function of the saturation Variable.");
38 params.addRequiredParam<Real>(
"fluid_viscosity",
"The fluid dynamic viscosity");
39 params.addClassDescription(
40 "Flux according to Darcy-Richards flow. The Variable of this Kernel must be the saturation");
47 _pp(coupledValue(
"porepressure_variable")),
48 _grad_pp(coupledGradient(
"porepressure_variable")),
49 _pp_nodal(coupledDofValues(
"porepressure_variable")),
50 _pp_var(coupled(
"porepressure_variable")),
52 _viscosity(getParam<Real>(
"fluid_viscosity")),
53 _gravity(getMaterialProperty<RealVectorValue>(
"gravity")),
54 _permeability(getMaterialProperty<RealTensorValue>(
"permeability")),
76 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
81 _var.dofValues()[nodenum]);
96 return _grad_test[_i][_qp] *
109 upwind(
false,
true, _var.number());
115 upwind(
false,
true, jvar.number());
124 return _grad_test[_i][_qp] *
134 if (compute_jac && !(jvar == _var.number() || jvar ==
_pp_var))
143 DenseVector<Number> & re = _assembly.residualBlock(_var.number());
144 _local_re.resize(re.size());
147 for (_i = 0; _i < _test.size(); _i++)
148 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
151 DenseMatrix<Number> & ke = _assembly.jacobianBlock(_var.number(), jvar);
154 _local_ke.resize(ke.m(), ke.n());
157 for (_i = 0; _i < _test.size(); _i++)
158 for (_j = 0; _j < _phi.size(); _j++)
159 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
160 _local_ke(_i, _j) += _JxW[_qp] * _coord[_qp] *
computeQpJac(jvar);
193 bool reached_steady =
true;
194 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
196 if (_local_re(nodenum) >= 1E-20)
198 reached_steady =
false;
202 reached_steady =
false;
206 Real total_mass_out = 0;
211 std::vector<Real> dtotal_mass_out;
212 std::vector<Real> dtotal_in;
220 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
222 if (_local_re(nodenum) >= 0 || reached_steady)
226 for (_j = 0; _j < _phi.size(); _j++)
227 _local_ke(nodenum, _j) *=
_mobility[nodenum];
228 if (jvar == _var.number())
230 _local_ke(nodenum, nodenum) +=
_dmobility_ds[nodenum] * _local_re(nodenum);
233 _local_ke(nodenum, nodenum) +=
_dmobility_dp[nodenum] * _local_re(nodenum);
234 for (_j = 0; _j < _phi.size(); _j++)
235 dtotal_mass_out[_j] += _local_ke(nodenum, _j);
237 _local_re(nodenum) *=
_mobility[nodenum];
238 total_mass_out += _local_re(nodenum);
242 total_in -= _local_re(nodenum);
244 for (_j = 0; _j < _phi.size(); _j++)
245 dtotal_in[_j] -= _local_ke(nodenum, _j);
252 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
253 if (_local_re(nodenum) < 0)
256 for (_j = 0; _j < _phi.size(); _j++)
258 _local_ke(nodenum, _j) *= total_mass_out / total_in;
259 _local_ke(nodenum, _j) +=
260 _local_re(nodenum) * (dtotal_mass_out[_j] / total_in -
261 dtotal_in[_j] * total_mass_out / total_in / total_in);
263 _local_re(nodenum) *= total_mass_out / total_in;
273 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
274 for (
unsigned int i = 0; i < _save_in.size(); i++)
275 _save_in[i]->sys().solution().add_vector(_local_re, _save_in[i]->dofIndices());
283 if (_has_diag_save_in && jvar == _var.number())
285 const unsigned int rows = ke.m();
286 DenseVector<Number> diag(rows);
287 for (
unsigned int i = 0; i < rows; i++)
288 diag(i) = _local_ke(i, i);
290 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
291 for (
unsigned int i = 0; i < _diag_save_in.size(); i++)
292 _diag_save_in[i]->sys().solution().add_vector(diag, _diag_save_in[i]->dofIndices());