www.mooseframework.org
PorousFlowFluidMass.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 "PorousFlowFluidMass.h"
11 
12 #include "MooseVariable.h"
13 
14 #include "libmesh/quadrature.h"
15 
17 
18 template <>
19 InputParameters
21 {
22  InputParameters params = validParams<ElementIntegralPostprocessor>();
23  params.addParam<unsigned int>(
24  "fluid_component",
25  0,
26  "The index corresponding to the fluid component that this Postprocessor acts on");
27  params.addRequiredParam<UserObjectName>(
28  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names.");
29  params.addParam<std::vector<unsigned int>>("phase",
30  "The index of the fluid phase that this "
31  "Postprocessor is restricted to. Multiple "
32  "indices can be entered");
33  params.addRangeCheckedParam<Real>("saturation_threshold",
34  1.0,
35  "saturation_threshold >= 0 & saturation_threshold <= 1",
36  "The saturation threshold below which the mass is calculated "
37  "for a specific phase. Default is 1.0. Note: only one "
38  "phase_index can be entered");
39  params.addParam<unsigned int>("kernel_variable_number",
40  0,
41  "The PorousFlow variable number (according to the dictator) of "
42  "the fluid-mass kernel. This is required only in the unusual "
43  "situation where a variety of different finite-element "
44  "interpolation schemes are employed in the simulation");
45  params.set<bool>("use_displaced_mesh") = true;
46  params.addClassDescription("Calculates the mass of a fluid component in a region");
47  return params;
48 }
49 
50 PorousFlowFluidMass::PorousFlowFluidMass(const InputParameters & parameters)
51  : ElementIntegralPostprocessor(parameters),
52 
53  _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
54  _fluid_component(getParam<unsigned int>("fluid_component")),
55  _phase_index(getParam<std::vector<unsigned int>>("phase")),
56  _porosity(getMaterialProperty<Real>("PorousFlow_porosity_nodal")),
57  _fluid_density(getMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal")),
58  _fluid_saturation(getMaterialProperty<std::vector<Real>>("PorousFlow_saturation_nodal")),
59  _mass_fraction(
60  getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal")),
61  _saturation_threshold(getParam<Real>("saturation_threshold")),
62  _var(getParam<unsigned>("kernel_variable_number") < _dictator.numVariables()
63  ? &_fe_problem.getStandardVariable(
64  _tid,
65  _dictator
66  .getCoupledStandardMooseVars()[getParam<unsigned>("kernel_variable_number")]
67  ->name())
68  : nullptr)
69 {
70  const unsigned int num_phases = _dictator.numPhases();
71  const unsigned int num_components = _dictator.numComponents();
72 
73  // Check that the number of components entered is not greater than the total number of components
74  if (_fluid_component >= num_components)
75  paramError(
76  "fluid_component",
77  "The Dictator proclaims that the number of components in this simulation is ",
78  num_components,
79  " whereas you have used a component index of ",
81  ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
82 
83  // Check that the number of phases entered is not more than the total possible phases
84  if (_phase_index.size() > num_phases)
85  paramError("phase",
86  "The Dictator decrees that the number of phases in this simulation is ",
87  num_phases,
88  " but you have entered ",
89  _phase_index.size(),
90  " phases.");
91 
92  // Check that kernel_variable_number is OK
93  if (getParam<unsigned>("kernel_variable_number") >= _dictator.numVariables())
94  paramError("kernel_variable_number",
95  "The Dictator pronounces that the number of PorousFlow variables is ",
97  ", however you have used ",
98  getParam<unsigned>("kernel_variable_number"),
99  ". This is an error");
100 
101  // Now that we know kernel_variable_number is OK, _var must be OK,
102  // so ensure that reinit is called on _var:
103  addMooseVariableDependency(_var);
104 
105  // Also check that the phase indices entered are not greater than the number of phases
106  // to avoid a segfault. Note that the input parser takes care of negative inputs so we
107  // don't need to guard against them
108  if (!_phase_index.empty())
109  {
110  unsigned int max_phase_num = *std::max_element(_phase_index.begin(), _phase_index.end());
111  if (max_phase_num > num_phases - 1)
112  paramError("phase",
113  "The Dictator proclaims that the phase index ",
114  max_phase_num,
115  " is greater than the largest phase index possible, which is ",
116  num_phases - 1);
117  }
118 
119  // Using saturation_threshold only makes sense for a specific phase_index
120  if (_saturation_threshold < 1.0 && _phase_index.size() != 1)
121  paramError("saturation_threshold",
122  "A single phase_index must be entered when prescribing a saturation_threshold");
123 
124  // If _phase_index is empty, create vector of all phase numbers to calculate mass over all phases
125  if (_phase_index.empty())
126  for (unsigned int i = 0; i < num_phases; ++i)
127  _phase_index.push_back(i);
128 }
129 
130 Real
132 {
133  Real sum = 0;
134 
135  // The use of _test in the loops below mean that the
136  // integral is exactly the same as the one computed
137  // by the PorousFlowMassTimeDerivative Kernel. Because that
138  // Kernel is lumped, this Postprocessor also needs to
139  // be lumped. Hence the use of the "nodal" Material
140  // Properties
141  const VariableTestValue & test = _var->phi();
142 
143  for (unsigned node = 0; node < test.size(); ++node)
144  {
145  Real nodal_volume = 0.0;
146  for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
147  nodal_volume += _JxW[_qp] * _coord[_qp] * test[node][_qp];
148 
149  Real mass = 0.0;
150  for (auto ph : _phase_index)
151  {
152  if (_fluid_saturation[node][ph] <= _saturation_threshold)
153  mass += _fluid_density[node][ph] * _fluid_saturation[node][ph] *
154  _mass_fraction[node][ph][_fluid_component];
155  }
156  sum += nodal_volume * _porosity[node] * mass;
157  }
158 
159  return sum;
160 }
161 
162 Real
164 {
165  return 0.0;
166 }
PorousFlowFluidMass::computeIntegral
virtual Real computeIntegral() override
Definition: PorousFlowFluidMass.C:131
PorousFlowFluidMass::_fluid_component
const unsigned int _fluid_component
The fluid component index that this Postprocessor applies to.
Definition: PorousFlowFluidMass.h:35
PorousFlowFluidMass::_porosity
const MaterialProperty< Real > & _porosity
Porosity.
Definition: PorousFlowFluidMass.h:39
validParams< PorousFlowFluidMass >
InputParameters validParams< PorousFlowFluidMass >()
Definition: PorousFlowFluidMass.C:20
PorousFlowFluidMass::_saturation_threshold
const Real _saturation_threshold
Saturation threshold - only fluid mass at saturations below this are calculated.
Definition: PorousFlowFluidMass.h:47
PorousFlowFluidMass::_phase_index
std::vector< unsigned int > _phase_index
The phase indices that this Postprocessor is restricted to.
Definition: PorousFlowFluidMass.h:37
PorousFlowFluidMass::_fluid_saturation
const MaterialProperty< std::vector< Real > > & _fluid_saturation
Phase saturation (-)
Definition: PorousFlowFluidMass.h:43
PorousFlowDictator
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
Definition: PorousFlowDictator.h:71
PorousFlowDictator::numPhases
unsigned int numPhases() const
The number of fluid phases.
Definition: PorousFlowDictator.C:105
registerMooseObject
registerMooseObject("PorousFlowApp", PorousFlowFluidMass)
PorousFlowFluidMass::PorousFlowFluidMass
PorousFlowFluidMass(const InputParameters &parameters)
Definition: PorousFlowFluidMass.C:50
PorousFlowDictator::numVariables
unsigned int numVariables() const
The number of PorousFlow variables.
Definition: PorousFlowDictator.C:99
PorousFlowFluidMass::computeQpIntegral
virtual Real computeQpIntegral() override
Definition: PorousFlowFluidMass.C:163
name
const std::string name
Definition: Setup.h:21
PorousFlowFluidMass::_dictator
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
Definition: PorousFlowFluidMass.h:33
PorousFlowFluidMass.h
PorousFlowDictator::numComponents
unsigned int numComponents() const
The number of fluid components.
Definition: PorousFlowDictator.C:111
PorousFlowFluidMass::_mass_fraction
const MaterialProperty< std::vector< std::vector< Real > > > & _mass_fraction
Mass fraction of each fluid component in each phase.
Definition: PorousFlowFluidMass.h:45
PorousFlowFluidMass::_fluid_density
const MaterialProperty< std::vector< Real > > & _fluid_density
Phase density (kg/m^3)
Definition: PorousFlowFluidMass.h:41
PorousFlowFluidMass::_var
MooseVariable *const _var
The variable for the corresponding PorousFlowMassTimeDerivative Kernel: this provides test functions.
Definition: PorousFlowFluidMass.h:49
PorousFlowFluidMass
Postprocessor produces the mass of a given fluid component in a region.
Definition: PorousFlowFluidMass.h:23