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(
"saturation_variable",
"The variable representing fluid saturation");
33 params.addRequiredParam<UserObjectName>(
35 "A RichardsRelPerm UserObject (eg RichardsRelPermPower) that defines the "
36 "fluid relative permeability as a function of the saturation variable");
37 params.addRequiredParam<Real>(
"fluid_viscosity",
"The fluid dynamic viscosity");
38 params.addClassDescription(
"Flux according to Darcy-Richards flow. The Variable for this Kernel "
39 "should be the porepressure.");
46 _sat(coupledDofValues(
"saturation_variable")),
47 _sat_var(coupled(
"saturation_variable")),
49 _viscosity(getParam<Real>(
"fluid_viscosity")),
50 _gravity(getMaterialProperty<RealVectorValue>(
"gravity")),
51 _permeability(getMaterialProperty<RealTensorValue>(
"permeability")),
73 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
92 return _grad_test[_i][_qp] *
105 upwind(
false,
true, _var.number());
111 upwind(
false,
true, jvar.number());
119 if (dvar == _var.number())
120 return _grad_test[_i][_qp] *
130 if (compute_jac && !(jvar == _var.number() || jvar ==
_sat_var))
139 DenseVector<Number> & re = _assembly.residualBlock(_var.number());
140 _local_re.resize(re.size());
143 for (_i = 0; _i < _test.size(); _i++)
144 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
147 DenseMatrix<Number> & ke = _assembly.jacobianBlock(_var.number(), jvar);
150 _local_ke.resize(ke.m(), ke.n());
153 for (_i = 0; _i < _test.size(); _i++)
154 for (_j = 0; _j < _phi.size(); _j++)
155 for (_qp = 0; _qp < _qrule->n_points(); _qp++)
156 _local_ke(_i, _j) += _JxW[_qp] * _coord[_qp] *
computeQpJac(jvar);
189 bool reached_steady =
true;
190 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
192 if (_local_re(nodenum) >= 1E-20)
194 reached_steady =
false;
198 reached_steady =
false;
202 Real total_mass_out = 0;
207 std::vector<Real> dtotal_mass_out;
208 std::vector<Real> dtotal_in;
216 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
218 if (_local_re(nodenum) >= 0 || reached_steady)
222 for (_j = 0; _j < _phi.size(); _j++)
223 _local_ke(nodenum, _j) *=
_mobility[nodenum];
224 if (jvar == _var.number())
226 _local_ke(nodenum, nodenum) +=
_dmobility_dp[nodenum] * _local_re(nodenum);
229 _local_ke(nodenum, nodenum) +=
_dmobility_ds[nodenum] * _local_re(nodenum);
230 for (_j = 0; _j < _phi.size(); _j++)
231 dtotal_mass_out[_j] += _local_ke(nodenum, _j);
233 _local_re(nodenum) *=
_mobility[nodenum];
234 total_mass_out += _local_re(nodenum);
238 total_in -= _local_re(nodenum);
240 for (_j = 0; _j < _phi.size(); _j++)
241 dtotal_in[_j] -= _local_ke(nodenum, _j);
248 for (
unsigned int nodenum = 0; nodenum <
_num_nodes; ++nodenum)
249 if (_local_re(nodenum) < 0)
252 for (_j = 0; _j < _phi.size(); _j++)
254 _local_ke(nodenum, _j) *= total_mass_out / total_in;
255 _local_ke(nodenum, _j) +=
256 _local_re(nodenum) * (dtotal_mass_out[_j] / total_in -
257 dtotal_in[_j] * total_mass_out / total_in / total_in);
259 _local_re(nodenum) *= total_mass_out / total_in;
269 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
270 for (
unsigned int i = 0; i < _save_in.size(); i++)
271 _save_in[i]->sys().solution().add_vector(_local_re, _save_in[i]->dofIndices());
279 if (_has_diag_save_in && jvar == _var.number())
281 const unsigned int rows = ke.m();
282 DenseVector<Number> diag(rows);
283 for (
unsigned int i = 0; i < rows; i++)
284 diag(i) = _local_ke(i, i);
286 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
287 for (
unsigned int i = 0; i < _diag_save_in.size(); i++)
288 _diag_save_in[i]->sys().solution().add_vector(diag, _diag_save_in[i]->dofIndices());