https://mooseframework.inl.gov
PorousFlowUnsaturated.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
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);
120  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
121  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
122  params.set<RealVectorValue>("gravity") = _gravity;
123 
124  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
125  {
126  const std::string kernel_name = "PorousFlowUnsaturated_AdvectiveFlux" + Moose::stringify(i);
127  params.set<unsigned int>("fluid_component") = i;
128  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
129  _problem->addKernel(kernel_type, kernel_name, params);
130  }
131  const std::string kernel_name =
132  "PorousFlowUnsaturated_AdvectiveFlux" + Moose::stringify(_num_mass_fraction_vars);
133  params.set<unsigned int>("fluid_component") = _num_mass_fraction_vars;
134  params.set<NonlinearVariableName>("variable") = _pp_var;
135  _problem->addKernel(kernel_type, kernel_name, params);
136  }
138  {
139  const std::string kernel_type = "PorousFlowFluxLimitedTVDAdvection";
140  InputParameters params = _factory.getValidParams(kernel_type);
142  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
143  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
144 
145  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
146  {
147  const std::string kernel_name = "PorousFlowFluxLimited_DarcyFlow" + Moose::stringify(i);
148  params.set<UserObjectName>("advective_flux_calculator") =
149  "PorousFlowUnsaturated_AC_" + Moose::stringify(i);
150  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
151  _problem->addKernel(kernel_type, kernel_name, params);
152  }
153  const std::string kernel_name =
154  "PorousFlowFluxLimited_DarcyFlow" + Moose::stringify(_num_mass_fraction_vars);
155  params.set<NonlinearVariableName>("variable") = _pp_var;
156  params.set<UserObjectName>("advective_flux_calculator") =
157  "PorousFlowUnsaturated_AC_" + Moose::stringify(_num_mass_fraction_vars);
158  _problem->addKernel(kernel_type, kernel_name, params);
159  }
160 
161  if (_transient)
162  {
163  std::string kernel_name = "PorousFlowUnsaturated_MassTimeDerivative";
164  std::string kernel_type = "PorousFlowMassTimeDerivative";
165  InputParameters params = _factory.getValidParams(kernel_type);
167  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
168  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
169  params.set<bool>("strain_at_nearest_qp") = _strain_at_nearest_qp;
170  if (!_base_name.empty())
171  params.set<std::string>("base_name") = _base_name;
172 
173  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
174  {
175  kernel_name = "PorousFlowUnsaturated_MassTimeDerivative" + Moose::stringify(i);
176  params.set<unsigned int>("fluid_component") = i;
177  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
178  if (_save_component_rate_in.size() != 0)
179  params.set<std::vector<AuxVariableName>>("save_in") = {_save_component_rate_in[i]};
180  _problem->addKernel(kernel_type, kernel_name, params);
181  }
182  kernel_name =
183  "PorousFlowUnsaturated_MassTimeDerivative" + Moose::stringify(_num_mass_fraction_vars);
184  params.set<unsigned int>("fluid_component") = _num_mass_fraction_vars;
185  params.set<NonlinearVariableName>("variable") = _pp_var;
186  if (_save_component_rate_in.size() != 0)
187  params.set<std::vector<AuxVariableName>>("save_in") = {
189  _problem->addKernel(kernel_type, kernel_name, params);
190  }
191 
192  if (_mechanical && _transient)
193  {
194  std::string kernel_name = "PorousFlowUnsaturated_MassVolumetricExpansion";
195  std::string kernel_type = "PorousFlowMassVolumetricExpansion";
196  InputParameters params = _factory.getValidParams(kernel_type);
198  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
199  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
200  params.set<bool>("strain_at_nearest_qp") = _strain_at_nearest_qp;
201 
202  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
203  {
204  kernel_name = "PorousFlowUnsaturated_MassVolumetricExpansion" + Moose::stringify(i);
205  params.set<unsigned>("fluid_component") = i;
206  params.set<NonlinearVariableName>("variable") = _mass_fraction_vars[i];
207  _problem->addKernel(kernel_type, kernel_name, params);
208  }
209  kernel_name =
210  "PorousFlowUnsaturated_MassVolumetricExpansion" + Moose::stringify(_num_mass_fraction_vars);
211  params.set<unsigned>("fluid_component") = _num_mass_fraction_vars;
212  params.set<NonlinearVariableName>("variable") = _pp_var;
213  _problem->addKernel(kernel_type, kernel_name, params);
214  }
215 
216  if (_thermal)
217  {
219  {
220  const std::string kernel_name = "PorousFlowUnsaturated_HeatAdvection";
221  const std::string kernel_type = "PorousFlowHeatAdvection";
222  InputParameters params = _factory.getValidParams(kernel_type);
224  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
225  params.set<NonlinearVariableName>("variable") = _temperature_var[0];
226  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
227  params.set<RealVectorValue>("gravity") = _gravity;
228  _problem->addKernel(kernel_type, kernel_name, params);
229  }
231  {
232  const std::string kernel_name = "PorousFlowUnsaturated_HeatAdvection";
233  const std::string kernel_type = "PorousFlowFluxLimitedTVDAdvection";
234  InputParameters params = _factory.getValidParams(kernel_type);
236  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
237  params.set<NonlinearVariableName>("variable") = _temperature_var[0];
238  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
239  params.set<UserObjectName>("advective_flux_calculator") = "PorousFlowUnsaturatedHeat_AC";
240  _problem->addKernel(kernel_type, kernel_name, params);
241  }
242  }
243 }
244 
245 void
247 {
249 
250  // Add the capillary pressure UserObject
252 
253  // add Advective Flux calculator UserObjects, if required
255  {
256  for (unsigned i = 0; i < _num_mass_fraction_vars; ++i)
257  {
258  const std::string userobject_name = "PorousFlowUnsaturated_AC_" + Moose::stringify(i);
259  addAdvectiveFluxCalculatorUnsaturatedMultiComponent(0, i, true, userobject_name);
260  }
261  const std::string userobject_name =
262  "PorousFlowUnsaturated_AC_" + Moose::stringify(_num_mass_fraction_vars);
263  if (_num_mass_fraction_vars == 0)
264  addAdvectiveFluxCalculatorUnsaturated(0, true, userobject_name); // 1 component only
265  else
267  0, _num_mass_fraction_vars, true, userobject_name);
268 
269  if (_thermal)
270  {
271  const std::string userobject_name = "PorousFlowUnsaturatedHeat_AC";
272  addAdvectiveFluxCalculatorUnsaturatedHeat(0, true, userobject_name);
273  }
274  }
275 }
276 
277 void
279 {
281 
282  if (_deps.dependsOn(_included_objects, "pressure_saturation_qp"))
283  {
284  const std::string material_type = "PorousFlow1PhaseP";
285  const std::string material_name = "PorousFlowUnsaturated_1PhaseP_VG_qp";
286  InputParameters params = _factory.getValidParams(material_type);
288  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
289  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
290  params.set<std::vector<VariableName>>("porepressure") = {_pp_var};
291  params.set<UserObjectName>("capillary_pressure") = _capillary_pressure_name;
292  params.set<bool>("at_nodes") = false;
293  _problem->addMaterial(material_type, material_name, params);
294  }
295  if (_deps.dependsOn(_included_objects, "pressure_saturation_nodal"))
296  {
297  const std::string material_type = "PorousFlow1PhaseP";
298  const std::string material_name = "PorousFlowUnsaturated_1PhaseP_VG_nodal";
299  InputParameters params = _factory.getValidParams(material_type);
301  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
302  params.set<UserObjectName>("PorousFlowDictator") = _dictator_name;
303  params.set<std::vector<VariableName>>("porepressure") = {_pp_var};
304  params.set<UserObjectName>("capillary_pressure") = _capillary_pressure_name;
305  params.set<bool>("at_nodes") = true;
306  _problem->addMaterial(material_type, material_name, params);
307  }
308 
309  if (_deps.dependsOn(_included_objects, "relative_permeability_qp"))
310  {
313  else
315  }
316 
317  if (_deps.dependsOn(_included_objects, "relative_permeability_nodal"))
318  {
321  else
323  }
324 
325  if (_deps.dependsOn(_included_objects, "volumetric_strain_qp") ||
326  _deps.dependsOn(_included_objects, "volumetric_strain_nodal"))
328 }
329 
330 void
332 {
334 
336  addSaturationAux(0);
337 }
virtual void addMaterials() override
Add all Materials.
void addSaturationAux(unsigned phase)
Add an AuxVariable and AuxKernel to calculate saturation.
const bool _subdomain_names_set
indicates, if the vector of subdomain names is set (dont set block restrictions, if not) ...
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.
std::vector< SubdomainName > _subdomain_names
if this vector is not empty the variables, kernels and materials are restricted to these subdomains ...
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)