www.mooseframework.org
PorousFlowUnsaturated.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 "PorousFlowUnsaturated.h"
11 
12 #include "FEProblem.h"
13 #include "Conversion.h"
14 #include "libmesh/string_to_enum.h"
15 
16 registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_user_object");
17 
18 registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_kernel");
19 
20 registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_material");
21 
22 registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_aux_variable");
23 
24 registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_aux_kernel");
25 
28 {
30  params.addParam<bool>("add_saturation_aux", true, "Add an AuxVariable that records saturation");
31  params.addRangeCheckedParam<Real>(
32  "van_genuchten_alpha",
33  1.0E-6,
34  "van_genuchten_alpha > 0.0",
35  "Van Genuchten alpha parameter used to determine saturation from porepressure");
36  params.addRangeCheckedParam<Real>(
37  "van_genuchten_m",
38  0.6,
39  "van_genuchten_m > 0 & van_genuchten_m < 1",
40  "Van Genuchten m parameter used to determine saturation from porepressure");
41  MooseEnum relperm_type_choice("FLAC Corey", "FLAC");
42  params.addParam<MooseEnum>("relative_permeability_type",
43  relperm_type_choice,
44  "Type of relative-permeability function. FLAC relperm = (1+m)S^m - "
45  "mS^(1+m). Corey relperm = S^m. m is the exponent. Here S = "
46  "(saturation - residual)/(1 - residual)");
47  params.addRangeCheckedParam<Real>("relative_permeability_exponent",
48  3.0,
49  "relative_permeability_exponent>=0",
50  "Relative permeability exponent");
51  params.addRangeCheckedParam<Real>(
52  "residual_saturation",
53  0.0,
54  "residual_saturation>=0.0 & residual_saturation<1.0",
55  "Residual saturation to use in the relative permeability expression");
56  params.addClassDescription("Adds Kernels and fluid-property Materials necessary to simulate a "
57  "single-phase saturated-unsaturated flow problem. The saturation is "
58  "computed using van Genuchten's expression. No Kernels for diffusion "
59  "and dispersion of fluid components are added. To run a simulation "
60  "you will also need to provide various other Materials for each mesh "
61  "block, depending on your simulation type, viz: permeability, "
62  "porosity, elasticity tensor, strain calculator, stress calculator, "
63  "matrix internal energy, thermal conductivity, diffusivity");
64  return params;
65 }
66 
68  : PorousFlowSinglePhaseBase(params),
69  _add_saturation_aux(getParam<bool>("add_saturation_aux")),
70  _van_genuchten_alpha(getParam<Real>("van_genuchten_alpha")),
71  _van_genuchten_m(getParam<Real>("van_genuchten_m")),
72  _relperm_type(
73  getParam<MooseEnum>("relative_permeability_type").getEnum<RelpermTypeChoiceEnum>()),
74  _relative_permeability_exponent(getParam<Real>("relative_permeability_exponent")),
75  _s_res(getParam<Real>("residual_saturation")),
76  _capillary_pressure_name("PorousFlowUnsaturated_CapillaryPressureVG")
77 {
79  paramError("stabilization", "Some stabilization must be used in PorousFlowUnsaturated");
80 }
81 
82 void
84 {
86 
87  // Add necessary objects to list of PorousFlow objects added by this action
88  _included_objects.push_back("PorousFlowAdvectiveFlux");
89 
90  if (_transient)
91  _included_objects.push_back("PorousFlowMassTimeDerivative");
92 
93  if (_mechanical && _transient)
94  _included_objects.push_back("PorousFlowMassVolumetricExpansion");
95 
96  if (_thermal)
97  _included_objects.push_back("PorousFlowHeatAdvection");
98 
100  _included_objects.push_back("SaturationAux");
101 
103  _included_objects.push_back("PorousFlowAdvectiveFluxCalculatorUnsaturatedMultiComponent");
104 
106  _included_objects.push_back("PorousFlowAdvectiveFluxCalculatorUnsaturatedHeat");
107 }
108 
109 void
111 {
113 
114  // add the kernels
116  {
117  const std::string kernel_type = "PorousFlowAdvectiveFlux";
118  InputParameters params = _factory.getValidParams(kernel_type);
119  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
120  params.set<RealVectorValue>("gravity") = _gravity;
121 
122  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
123  {
124  const std::string kernel_name = "PorousFlowUnsaturated_AdvectiveFlux" + Moose::stringify(i);
125  params.set<unsigned int>("fluid_component") = i;
126  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
127  _problem->addKernel(kernel_type, kernel_name, params);
128  }
129  const std::string kernel_name =
130  "PorousFlowUnsaturated_AdvectiveFlux" + Moose::stringify(_num_mass_fraction_vars);
131  params.set<unsigned int>("fluid_component") = _num_mass_fraction_vars;
132  params.set<NonlinearVariableName>("variable") = _pp_var;
133  _problem->addKernel(kernel_type, kernel_name, params);
134  }
136  {
137  const std::string kernel_type = "PorousFlowFluxLimitedTVDAdvection";
138  InputParameters params = _factory.getValidParams(kernel_type);
139  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
140 
141  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
142  {
143  const std::string kernel_name = "PorousFlowFluxLimited_DarcyFlow" + Moose::stringify(i);
144  params.set<UserObjectName>("advective_flux_calculator") =
145  "PorousFlowUnsaturated_AC_" + Moose::stringify(i);
146  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
147  _problem->addKernel(kernel_type, kernel_name, params);
148  }
149  const std::string kernel_name =
150  "PorousFlowFluxLimited_DarcyFlow" + Moose::stringify(_num_mass_fraction_vars);
151  params.set<NonlinearVariableName>("variable") = _pp_var;
152  params.set<UserObjectName>("advective_flux_calculator") =
153  "PorousFlowUnsaturated_AC_" + Moose::stringify(_num_mass_fraction_vars);
154  _problem->addKernel(kernel_type, kernel_name, params);
155  }
156 
157  if (_transient)
158  {
159  std::string kernel_name = "PorousFlowUnsaturated_MassTimeDerivative";
160  std::string kernel_type = "PorousFlowMassTimeDerivative";
161  InputParameters params = _factory.getValidParams(kernel_type);
162  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
163  params.set<bool>("strain_at_nearest_qp") = _strain_at_nearest_qp;
164  if (!_base_name.empty())
165  params.set<std::string>("base_name") = _base_name;
166 
167  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
168  {
169  kernel_name = "PorousFlowUnsaturated_MassTimeDerivative" + Moose::stringify(i);
170  params.set<unsigned int>("fluid_component") = i;
171  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
172  if (_save_component_rate_in.size() != 0)
173  params.set<std::vector<AuxVariableName>>("save_in") = {_save_component_rate_in[i]};
174  _problem->addKernel(kernel_type, kernel_name, params);
175  }
176  kernel_name =
177  "PorousFlowUnsaturated_MassTimeDerivative" + Moose::stringify(_num_mass_fraction_vars);
178  params.set<unsigned int>("fluid_component") = _num_mass_fraction_vars;
179  params.set<NonlinearVariableName>("variable") = _pp_var;
180  if (_save_component_rate_in.size() != 0)
181  params.set<std::vector<AuxVariableName>>("save_in") = {
183  _problem->addKernel(kernel_type, kernel_name, params);
184  }
185 
186  if (_mechanical && _transient)
187  {
188  std::string kernel_name = "PorousFlowUnsaturated_MassVolumetricExpansion";
189  std::string kernel_type = "PorousFlowMassVolumetricExpansion";
190  InputParameters params = _factory.getValidParams(kernel_type);
191  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
192  params.set<bool>("strain_at_nearest_qp") = _strain_at_nearest_qp;
193 
194  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
195  {
196  kernel_name = "PorousFlowUnsaturated_MassVolumetricExpansion" + Moose::stringify(i);
197  params.set<unsigned>("fluid_component") = i;
198  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
199  _problem->addKernel(kernel_type, kernel_name, params);
200  }
201  kernel_name =
202  "PorousFlowUnsaturated_MassVolumetricExpansion" + Moose::stringify(_num_mass_fraction_vars);
203  params.set<unsigned>("fluid_component") = _num_mass_fraction_vars;
204  params.set<NonlinearVariableName>("variable") = _pp_var;
205  _problem->addKernel(kernel_type, kernel_name, params);
206  }
207 
208  if (_thermal)
209  {
211  {
212  const std::string kernel_name = "PorousFlowUnsaturated_HeatAdvection";
213  const std::string kernel_type = "PorousFlowHeatAdvection";
214  InputParameters params = _factory.getValidParams(kernel_type);
215  params.set<NonlinearVariableName>("variable") = _temperature_var[0];
216  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
217  params.set<RealVectorValue>("gravity") = _gravity;
218  _problem->addKernel(kernel_type, kernel_name, params);
219  }
221  {
222  const std::string kernel_name = "PorousFlowUnsaturated_HeatAdvection";
223  const std::string kernel_type = "PorousFlowFluxLimitedTVDAdvection";
224  InputParameters params = _factory.getValidParams(kernel_type);
225  params.set<NonlinearVariableName>("variable") = _temperature_var[0];
226  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
227  params.set<UserObjectName>("advective_flux_calculator") = "PorousFlowUnsaturatedHeat_AC";
228  _problem->addKernel(kernel_type, kernel_name, params);
229  }
230  }
231 }
232 
233 void
235 {
237 
238  // Add the capillary pressure UserObject
240 
241  // add Advective Flux calculator UserObjects, if required
243  {
244  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
245  {
246  const std::string userobject_name = "PorousFlowUnsaturated_AC_" + Moose::stringify(i);
247  addAdvectiveFluxCalculatorUnsaturatedMultiComponent(0, i, true, userobject_name);
248  }
249  const std::string userobject_name =
250  "PorousFlowUnsaturated_AC_" + Moose::stringify(_num_mass_fraction_vars);
251  if (_num_mass_fraction_vars == 0)
252  addAdvectiveFluxCalculatorUnsaturated(0, true, userobject_name); // 1 component only
253  else
255  0, _num_mass_fraction_vars, true, userobject_name);
256 
257  if (_thermal)
258  {
259  const std::string userobject_name = "PorousFlowUnsaturatedHeat_AC";
260  addAdvectiveFluxCalculatorUnsaturatedHeat(0, true, userobject_name);
261  }
262  }
263 }
264 
265 void
267 {
269 
270  if (_deps.dependsOn(_included_objects, "pressure_saturation_qp"))
271  {
272  const std::string material_type = "PorousFlow1PhaseP";
273  InputParameters params = _factory.getValidParams(material_type);
274  const std::string material_name = "PorousFlowUnsaturated_1PhaseP_VG_qp";
275  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
276  params.set<std::vector<VariableName>>("porepressure") = {_pp_var};
277  params.set<UserObjectName>("capillary_pressure") = _capillary_pressure_name;
278  params.set<bool>("at_nodes") = false;
279  _problem->addMaterial(material_type, material_name, params);
280  }
281  if (_deps.dependsOn(_included_objects, "pressure_saturation_nodal"))
282  {
283  const std::string material_type = "PorousFlow1PhaseP";
284  InputParameters params = _factory.getValidParams(material_type);
285  const std::string material_name = "PorousFlowUnsaturated_1PhaseP_VG_nodal";
286  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
287  params.set<std::vector<VariableName>>("porepressure") = {_pp_var};
288  params.set<UserObjectName>("capillary_pressure") = _capillary_pressure_name;
289  params.set<bool>("at_nodes") = true;
290  _problem->addMaterial(material_type, material_name, params);
291  }
292 
293  if (_deps.dependsOn(_included_objects, "relative_permeability_qp"))
294  {
297  else
299  }
300 
301  if (_deps.dependsOn(_included_objects, "relative_permeability_nodal"))
302  {
305  else
307  }
308 
309  if (_deps.dependsOn(_included_objects, "volumetric_strain_qp") ||
310  _deps.dependsOn(_included_objects, "volumetric_strain_nodal"))
312 }
313 
314 void
316 {
318 
320  addSaturationAux(0);
321 }
virtual void addMaterials() override
Add all Materials.
void addSaturationAux(unsigned phase)
Add an AuxVariable and AuxKernel to calculate saturation.
Action for simulation involving a single phase, partially or fully saturated fluid.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addRelativePermeabilityCorey(bool at_nodes, unsigned phase, Real n, Real s_res, Real sum_s_res)
Adds a relative-permeability Material of the Corey variety.
const Real _van_genuchten_m
Van Genuchten m parameter.
T & set(const std::string &name, bool quiet_mode=false)
InputParameters getValidParams(const std::string &name) const
bool dependsOn(const std::string &key, const std::string &value)
const VariableName _pp_var
Porepressure NonlinearVariable name.
const bool _add_saturation_aux
Add an Aux Variable to record saturation.
std::vector< VariableName > _coupled_displacements
Displacement Variable names.
RelpermTypeChoiceEnum
Fluid relative permeability type (FLAC or Corey)
std::vector< std::string > _included_objects
List of Kernels, AuxKernels, Materials, etc, that are added in this input file.
const Real _van_genuchten_alpha
Van Genuchten alpha parameter.
virtual void addKernels() override
Add all Kernels.
const std::vector< AuxVariableName > _save_component_rate_in
Name of the variables (if any) that will record the fluid-components&#39; rate of change.
const bool _thermal
Flags to indicate whether thermal or mechanical effects are included.
static InputParameters validParams()
Factory & _factory
const Real _s_res
Residual saturation to use in the relative permeability expressions.
void addCapillaryPressureVG(Real m, Real alpha, std::string userobject_name)
Adds a van Genuchten capillary pressure UserObject.
registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_user_object")
virtual void addAuxObjects() override
Add all AuxVariables and AuxKernels.
Base class for actions involving a single fluid phase.
virtual void addMaterials() override
Add all Materials.
void addAdvectiveFluxCalculatorUnsaturated(unsigned phase, bool multiply_by_density, std::string userobject_name)
virtual void addKernels() override
Add all Kernels.
void paramError(const std::string &param, Args... args) const
static InputParameters validParams()
std::string stringify(const T &t)
const RealVectorValue _gravity
Gravity.
const std::vector< VariableName > _temperature_var
Name of the temperature variable (if any)
bool _transient
Flag to denote if the simulation is transient.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Real _relative_permeability_exponent
Relative permeability exponent.
enum PorousFlowUnsaturated::RelpermTypeChoiceEnum _relperm_type
PorousFlowUnsaturated(const InputParameters &params)
virtual void addMaterialDependencies() override
Add all material dependencies so that the correct version of each material can be added...
const std::string _capillary_pressure_name
Name of the capillary pressure UserObject.
virtual void addAuxObjects() override
Add all AuxVariables and AuxKernels.
const std::string _dictator_name
The name of the PorousFlowDictator object to be added.
const bool _strain_at_nearest_qp
Evaluate strain at the nearest quadpoint for porosity that depends on strain.
void addVolumetricStrainMaterial(const std::vector< VariableName > &displacements, const std::string &base_name)
Adds a quadpoint volumetric strain material.
const unsigned _num_mass_fraction_vars
Number of mass-fraction variables.
void addRelativePermeabilityFLAC(bool at_nodes, unsigned phase, Real m, Real s_res, Real sum_s_res)
Adds a relative-permeability Material of the FLAC variety.
void addClassDescription(const std::string &doc_string)
std::shared_ptr< FEProblemBase > & _problem
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
virtual void addUserObjects()
Add all other UserObjects.
void addAdvectiveFluxCalculatorUnsaturatedMultiComponent(unsigned phase, unsigned fluid_component, bool multiply_by_density, std::string userobject_name)
virtual void addMaterialDependencies() override
Add all material dependencies so that the correct version of each material can be added...
const std::string _base_name
base_name used in the TensorMechanics strain calculator
enum PorousFlowActionBase::StabilizationEnum _stabilization
const std::vector< VariableName > _mass_fraction_vars
Name of the mass-fraction variables (if any)
virtual void addUserObjects() override
Add all other UserObjects.
DependencyResolver< std::string > _deps
All dependencies of kernels, auxkernels, materials, etc, are stored in _dependencies.
void addAdvectiveFluxCalculatorUnsaturatedHeat(unsigned phase, bool multiply_by_density, std::string userobject_name)