https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
11
12#include "FEProblem.h"
13#include "Conversion.h"
14#include "libmesh/string_to_enum.h"
15
16registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_user_object");
17
18registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_kernel");
19
20registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_material");
21
22registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_aux_variable");
23
24registerMooseAction("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
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
82void
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
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
109void
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
245void
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);
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
277void
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
330void
registerMooseAction("PorousFlowApp", PorousFlowUnsaturated, "add_user_object")
std::shared_ptr< FEProblemBase > & _problem
bool dependsOn(const T &key, const T &value)
InputParameters getValidParams(const std::string &name) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
Factory & _factory
enum PorousFlowActionBase::StabilizationEnum _stabilization
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.
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 addSaturationAux(unsigned phase)
Add an AuxVariable and AuxKernel to calculate saturation.
std::vector< SubdomainName > _subdomain_names
if this vector is not empty the variables, kernels and materials are restricted to these subdomains
const bool _subdomain_names_set
indicates, if the vector of subdomain names is set (dont set block restrictions, if not)
const std::vector< VariableName > _mass_fraction_vars
Name of the mass-fraction variables (if any)
const std::vector< VariableName > _temperature_var
Name of the temperature variable (if any)
void addAdvectiveFluxCalculatorUnsaturated(unsigned phase, bool multiply_by_density, std::string userobject_name)
bool _transient
Flag to denote if the simulation is transient.
const unsigned _num_mass_fraction_vars
Number of mass-fraction variables.
const std::string _dictator_name
The name of the PorousFlowDictator object to be added.
void addAdvectiveFluxCalculatorUnsaturatedMultiComponent(unsigned phase, unsigned fluid_component, bool multiply_by_density, std::string userobject_name)
std::vector< VariableName > _coupled_displacements
Displacement Variable names.
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 RealVectorValue _gravity
Gravity.
virtual void addUserObjects()
Add all other UserObjects.
std::vector< std::string > _included_objects
List of Kernels, AuxKernels, Materials, etc, that are added in this input file.
void addCapillaryPressureVG(Real m, Real alpha, std::string userobject_name, Real sat_lr=0.0)
Adds a van Genuchten capillary pressure UserObject.
void addAdvectiveFluxCalculatorUnsaturatedHeat(unsigned phase, bool multiply_by_density, std::string userobject_name)
DependencyResolver< std::string > _deps
All dependencies of kernels, auxkernels, materials, etc, are stored in _dependencies.
Base class for actions involving a single fluid phase.
const std::vector< AuxVariableName > _save_component_rate_in
Name of the variables (if any) that will record the fluid-components' rate of change.
virtual void addAuxObjects() override
Add all AuxVariables and AuxKernels.
static InputParameters validParams()
const VariableName _pp_var
Porepressure NonlinearVariable name.
virtual void addKernels() override
Add all Kernels.
const std::string _base_name
base_name used in the TensorMechanics strain calculator
virtual void addMaterials() override
Add all Materials.
virtual void addMaterialDependencies() override
Add all material dependencies so that the correct version of each material can be added.
const bool _thermal
Flags to indicate whether thermal or mechanical effects are included.
Action for simulation involving a single phase, partially or fully saturated fluid.
const Real _s_res
Residual saturation to use in the relative permeability expressions.
static InputParameters validParams()
enum PorousFlowUnsaturated::RelpermTypeChoiceEnum _relperm_type
virtual void addUserObjects() override
Add all other UserObjects.
PorousFlowUnsaturated(const InputParameters &params)
virtual void addKernels() override
Add all Kernels.
RelpermTypeChoiceEnum
Fluid relative permeability type (FLAC or Corey)
const Real _van_genuchten_m
Van Genuchten m parameter.
virtual void addAuxObjects() override
Add all AuxVariables and AuxKernels.
const std::string _capillary_pressure_name
Name of the capillary pressure UserObject.
virtual void addMaterials() override
Add all Materials.
virtual void addMaterialDependencies() override
Add all material dependencies so that the correct version of each material can be added.
const bool _add_saturation_aux
Add an Aux Variable to record saturation.
const Real _van_genuchten_alpha
Van Genuchten alpha parameter.
const Real _relative_permeability_exponent
Relative permeability exponent.
std::string stringify(const T &t)