https://mooseframework.inl.gov
FVPorousFlowFluidMass.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 "FVPorousFlowFluidMass.h"
11 
13 
16 {
18  params.addParam<unsigned int>(
19  "fluid_component",
20  0,
21  "The index corresponding to the fluid component that this Postprocessor acts on");
22  params.addRequiredParam<UserObjectName>(
23  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names.");
24  params.addParam<std::vector<unsigned int>>("phase",
25  {},
26  "The index of the fluid phase that this "
27  "Postprocessor is restricted to. Multiple "
28  "indices can be entered");
29  params.addRangeCheckedParam<Real>("saturation_threshold",
30  1.0,
31  "saturation_threshold >= 0 & saturation_threshold <= 1",
32  "The saturation threshold below which the mass is calculated "
33  "for a specific phase. Default is 1.0. Note: only one "
34  "phase_index can be entered");
35  params.addParam<std::string>(
36  "base_name",
37  "For non-mechanically-coupled systems with no TensorMechanics strain calculators, base_name "
38  "need not be set. For mechanically-coupled systems, base_name should be the same base_name "
39  "as given to the TensorMechanics object that computes strain, so that this Postprocessor can "
40  "correctly account for changes in mesh volume. For non-mechanically-coupled systems, "
41  "base_name should not be the base_name of any TensorMechanics strain calculators.");
42  params.set<bool>("use_displaced_mesh") = false;
43  params.suppressParameter<bool>("use_displaced_mesh");
44  params.addClassDescription("Calculates the mass of a fluid component in a region");
45  return params;
46 }
47 
49  : ElementIntegralPostprocessor(parameters),
50  _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
51  _fluid_component(getParam<unsigned int>("fluid_component")),
52  _phase_index(getParam<std::vector<unsigned int>>("phase")),
53  _base_name(isParamValid("base_name") ? getParam<std::string>("base_name") + "_" : ""),
54  _has_total_strain(hasMaterialProperty<RankTwoTensor>(_base_name + "total_strain")),
55  _total_strain(_has_total_strain
56  ? &getMaterialProperty<RankTwoTensor>(_base_name + "total_strain")
57  : nullptr),
58  _porosity(getADMaterialProperty<Real>("PorousFlow_porosity_qp")),
59  _fluid_density(getADMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_qp")),
60  _fluid_saturation(getADMaterialProperty<std::vector<Real>>("PorousFlow_saturation_qp")),
61  _mass_fraction(
62  getADMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_qp")),
63  _saturation_threshold(getParam<Real>("saturation_threshold"))
64 {
65  const unsigned int num_phases = _dictator.numPhases();
66  const unsigned int num_components = _dictator.numComponents();
67 
68  // Check that the number of components entered is not greater than the total number of components
69  if (_fluid_component >= num_components)
70  paramError(
71  "fluid_component",
72  "The Dictator proclaims that the number of components in this simulation is ",
73  num_components,
74  " whereas you have used a component index of ",
76  ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
77 
78  // Check that the number of phases entered is not more than the total possible phases
79  if (_phase_index.size() > num_phases)
80  paramError("phase",
81  "The Dictator decrees that the number of phases in this simulation is ",
82  num_phases,
83  " but you have entered ",
84  _phase_index.size(),
85  " phases.");
86 
87  // Also check that the phase indices entered are not greater than the number of phases
88  // to avoid a segfault. Note that the input parser takes care of negative inputs so we
89  // don't need to guard against them
90  if (!_phase_index.empty())
91  {
92  unsigned int max_phase_num = *std::max_element(_phase_index.begin(), _phase_index.end());
93  if (max_phase_num > num_phases - 1)
94  paramError("phase",
95  "The Dictator proclaims that the phase index ",
96  max_phase_num,
97  " is greater than the largest phase index possible, which is ",
98  num_phases - 1);
99  }
100 
101  // Using saturation_threshold only makes sense for a specific phase_index
102  if (_saturation_threshold < 1.0 && _phase_index.size() != 1)
103  paramError("saturation_threshold",
104  "A single phase_index must be entered when prescribing a saturation_threshold");
105 
106  // If _phase_index is empty, create vector of all phase numbers to calculate mass over all phases
107  if (_phase_index.empty())
108  for (unsigned int i = 0; i < num_phases; ++i)
109  _phase_index.push_back(i);
110 
111  // Error if a strain base_name is provided but doesn't exist
112  if (parameters.isParamSetByUser("base_name") && !_has_total_strain)
113  paramError("base_name", "A strain base_name ", _base_name, " does not exist");
114 }
115 
116 Real
118 {
119  // The fluid mass for the finite volume case is much simpler
120  Real mass = 0.0;
121  const Real strain = (_has_total_strain ? (*_total_strain)[_qp].trace() : 0.0);
122 
123  for (auto ph : _phase_index)
124  {
128  }
129 
130  return MetaPhysicL::raw_value(_porosity[_qp]) * (1.0 + strain) * mass;
131 }
const std::string _base_name
base name used in the Tensor Mechanics strain calculator
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
FVPorousFlowFluidMass(const InputParameters &parameters)
T & set(const std::string &name, bool quiet_mode=false)
unsigned int numComponents() const
The number of fluid components.
auto raw_value(const Eigen::Map< T > &in)
const ADMaterialProperty< std::vector< Real > > & _fluid_density
Phase density (kg/m^3)
std::vector< unsigned int > _phase_index
The phase indices that this Postprocessor is restricted to.
void addRequiredParam(const std::string &name, const std::string &doc_string)
void suppressParameter(const std::string &name)
const ADMaterialProperty< std::vector< std::vector< Real > > > & _mass_fraction
Mass fraction of each fluid component in each phase.
Postprocessor that calculates the mass of a given fluid component in the given phase(s) in a given bl...
static InputParameters validParams()
const ADMaterialProperty< Real > & _porosity
Porosity.
const Real _saturation_threshold
Saturation threshold - only fluid mass at saturations below this are calculated.
const ADMaterialProperty< std::vector< Real > > & _fluid_saturation
Phase saturation (-)
void paramError(const std::string &param, Args... args) const
unsigned int numPhases() const
The number of fluid phases.
const unsigned int _fluid_component
The fluid component index that this Postprocessor applies to.
virtual Real computeQpIntegral() override
bool isParamSetByUser(const std::string &name) const
const bool _has_total_strain
Whether there is a Material called _base_name_total_strain.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
registerMooseObject("PorousFlowApp", FVPorousFlowFluidMass)
void addClassDescription(const std::string &doc_string)
const InputParameters & parameters() const
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
static InputParameters validParams()
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void ErrorVector unsigned int