LCOV - code coverage report
Current view: top level - src/postprocessors - PorousFlowFluidMass.C (source / functions) Hit Total Coverage
Test: porous_flow Test Coverage Lines: 59 63 93.7 %
Date: 2017-11-21 14:47:27 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /****************************************************************/
       2             : /* MOOSE - Multiphysics Object Oriented Simulation Environment  */
       3             : /*                                                              */
       4             : /*          All contents are licensed under LGPL V2.1           */
       5             : /*             See LICENSE for full restrictions                */
       6             : /****************************************************************/
       7             : 
       8             : #include "PorousFlowFluidMass.h"
       9             : 
      10             : // MOOSE includes
      11             : #include "MooseVariable.h"
      12             : 
      13             : #include "libmesh/quadrature.h"
      14             : 
      15             : template <>
      16             : InputParameters
      17         124 : validParams<PorousFlowFluidMass>()
      18             : {
      19         124 :   InputParameters params = validParams<ElementIntegralPostprocessor>();
      20         372 :   params.addParam<unsigned int>(
      21             :       "fluid_component",
      22             :       0,
      23         124 :       "The index corresponding to the fluid component that this Postprocessor acts on");
      24         372 :   params.addRequiredParam<UserObjectName>(
      25         124 :       "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names.");
      26         372 :   params.addParam<std::vector<unsigned int>>("phase",
      27             :                                              "The index of the fluid phase that this "
      28             :                                              "Postprocessor is restricted to.  Multiple "
      29         124 :                                              "indices can be entered");
      30         496 :   params.addRangeCheckedParam<Real>("saturation_threshold",
      31             :                                     1.0,
      32             :                                     "saturation_threshold >= 0 & saturation_threshold <= 1",
      33             :                                     "The saturation threshold below which the mass is calculated "
      34             :                                     "for a specific phase. Default is 1.0. Note: only one "
      35         124 :                                     "phase_index can be entered");
      36         372 :   params.addParam<unsigned int>("kernel_variable_number",
      37             :                                 0,
      38             :                                 "The PorousFlow variable number (according to the dictator) of "
      39             :                                 "the fluid-mass kernel.  This is required only in the unusual "
      40             :                                 "situation where a variety of different finite-element "
      41         124 :                                 "interpolation schemes are employed in the simulation");
      42         248 :   params.set<bool>("use_displaced_mesh") = true;
      43         248 :   params.addClassDescription("Calculates the mass of a fluid component in a region");
      44         124 :   return params;
      45             : }
      46             : 
      47         124 : PorousFlowFluidMass::PorousFlowFluidMass(const InputParameters & parameters)
      48             :   : ElementIntegralPostprocessor(parameters),
      49             : 
      50         248 :     _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
      51         372 :     _fluid_component(getParam<unsigned int>("fluid_component")),
      52             :     _phase_index(getParam<std::vector<unsigned int>>("phase")),
      53         248 :     _porosity(getMaterialProperty<Real>("PorousFlow_porosity_nodal")),
      54         248 :     _fluid_density(getMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal")),
      55         248 :     _fluid_saturation(getMaterialProperty<std::vector<Real>>("PorousFlow_saturation_nodal")),
      56             :     _mass_fraction(
      57         248 :         getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal")),
      58         372 :     _saturation_threshold(getParam<Real>("saturation_threshold")),
      59         372 :     _var(getParam<unsigned>("kernel_variable_number") < _dictator.numVariables()
      60         617 :              ? _dictator.getCoupledMooseVars()[getParam<unsigned>("kernel_variable_number")]
      61        1488 :              : nullptr)
      62             : {
      63         124 :   const unsigned int num_phases = _dictator.numPhases();
      64         124 :   const unsigned int num_components = _dictator.numComponents();
      65             : 
      66             :   /// Check that the number of components entered is not greater than the total number of components
      67         124 :   if (_fluid_component >= num_components)
      68           0 :     mooseError("The Dictator proclaims that the number of components in this simulation is ",
      69             :                num_components,
      70             :                " whereas you have used the Postprocessor PorousFlowFluidMass with component = ",
      71             :                _fluid_component,
      72           0 :                ".  The Dictator does not take such mistakes lightly.");
      73             : 
      74             :   /// Check that the number of phases entered is not more than the total possible phases
      75         124 :   if (_phase_index.size() > num_phases)
      76             :     mooseError("The Dictator decrees that the number of phases in this simulation is ",
      77             :                num_phases,
      78             :                " but you have entered ",
      79           1 :                _phase_index.size(),
      80             :                " phases in the Postprocessor ",
      81           2 :                _name);
      82             : 
      83             :   /// Check that kernel_variable_number is OK
      84         369 :   if (getParam<unsigned>("kernel_variable_number") >= _dictator.numVariables())
      85           1 :     mooseError(
      86             :         "PorousFlowFluidMass: The dictator pronounces that the number of porous-flow variables is ",
      87           1 :         _dictator.numVariables(),
      88             :         ", however you have used kernel_variable_number = ",
      89             :         getParam<unsigned>("kernel_variable_number"),
      90           1 :         ".  This is an error");
      91             : 
      92             :   /**
      93             :    * Also check that the phase indices entered are not greater than the number of phases
      94             :    * to avoid a segfault. Note that the input parser takes care of negative inputs so we
      95             :    * don't need to guard against them
      96             :    */
      97         122 :   if (!_phase_index.empty())
      98             :   {
      99          21 :     unsigned int max_phase_num = *std::max_element(_phase_index.begin(), _phase_index.end());
     100          21 :     if (max_phase_num > num_phases - 1)
     101             :       mooseError("The Dictator proclaims that the phase index ",
     102             :                  max_phase_num,
     103             :                  " in the Postprocessor ",
     104           1 :                  _name,
     105             :                  " is greater than the largest phase index possible, which is ",
     106           2 :                  num_phases - 1);
     107             :   }
     108             : 
     109             :   /// Using saturation_threshold only makes sense for a specific phase_index
     110         123 :   if (_saturation_threshold < 1.0 && _phase_index.size() != 1)
     111             :     mooseError("A single phase_index must be entered when prescribing a saturation_threshold in "
     112             :                "the Postprocessor ",
     113           1 :                _name);
     114             : 
     115             :   /// If _phase_index is empty, create vector of all phase numbers to calculate mass over all phases
     116         120 :   if (_phase_index.empty())
     117         222 :     for (unsigned int i = 0; i < num_phases; ++i)
     118         121 :       _phase_index.push_back(i);
     119         120 : }
     120             : 
     121             : Real
     122       38303 : PorousFlowFluidMass::computeIntegral()
     123             : {
     124             :   Real sum = 0;
     125             : 
     126             :   /** The use of _test in the loops below mean that the
     127             :    * integral is exactly the same as the one computed
     128             :    * by the PorousFlowMassTimeDerivative Kernel.  Because that
     129             :    * Kernel is lumped, this Postprocessor also needs to
     130             :    * be lumped.  Hence the use of the "nodal" Material
     131             :    * Properties
     132             :    */
     133       38303 :   const VariableTestValue & test = _var->phi();
     134             : 
     135      351803 :   for (unsigned node = 0; node < test.size(); ++node)
     136             :   {
     137             :     Real nodal_volume = 0.0;
     138     1806532 :     for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
     139     2986064 :       nodal_volume += _JxW[_qp] * _coord[_qp] * test[node][_qp];
     140             : 
     141             :     Real mass = 0.0;
     142      330348 :     for (auto ph : _phase_index)
     143             :     {
     144      347196 :       if (_fluid_saturation[node][ph] <= _saturation_threshold)
     145      520773 :         mass += _fluid_density[node][ph] * _fluid_saturation[node][ph] *
     146      173591 :                 _mass_fraction[node][ph][_fluid_component];
     147             :     }
     148      313500 :     sum += nodal_volume * _porosity[node] * mass;
     149             :   }
     150             : 
     151       38303 :   return sum;
     152             : }
     153             : 
     154             : Real
     155           0 : PorousFlowFluidMass::computeQpIntegral()
     156             : {
     157           0 :   return 0.0;
     158        2499 : }

Generated by: LCOV version 1.11