Line data Source code
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 "PorousFlowHeatEnergy.h" 11 : 12 : #include "MooseVariable.h" 13 : 14 : #include "libmesh/quadrature.h" 15 : 16 : registerMooseObject("PorousFlowApp", PorousFlowHeatEnergy); 17 : 18 : InputParameters 19 875 : PorousFlowHeatEnergy::validParams() 20 : { 21 875 : InputParameters params = ElementIntegralPostprocessor::validParams(); 22 1750 : params.addRequiredParam<UserObjectName>( 23 : "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names."); 24 1750 : params.addParam<bool>( 25 1750 : "include_porous_skeleton", true, "Include the heat energy of the porous skeleton"); 26 1750 : params.addParam<std::vector<unsigned int>>("phase", 27 : {}, 28 : "The index(es) of the fluid phase that this " 29 : "Postprocessor is restricted to. Multiple " 30 : "indices can be entered."); 31 1750 : params.addParam<std::string>( 32 : "base_name", 33 : "For non-mechanically-coupled systems with no TensorMechanics strain calculators, base_name " 34 : "need not be set. For mechanically-coupled systems, base_name should be the same base_name " 35 : "as given to the TensorMechanics object that computes strain, so that this Postprocessor can " 36 : "correctly account for changes in mesh volume. For non-mechanically-coupled systems, " 37 : "base_name should not be the base_name of any TensorMechanics strain calculators."); 38 875 : params.set<bool>("use_displaced_mesh") = false; 39 875 : params.suppressParameter<bool>("use_displaced_mesh"); 40 1750 : params.addParam<unsigned int>("kernel_variable_number", 41 1750 : 0, 42 : "The PorousFlow variable number (according to the dictatory) of " 43 : "the heat-energy kernel. This is required only in the unusual " 44 : "situation where a variety of different finite-element " 45 : "interpolation schemes are employed in the simulation"); 46 875 : params.addClassDescription("Calculates the sum of heat energy of fluid phase(s) and/or the " 47 : "porous skeleton in a region"); 48 875 : return params; 49 0 : } 50 : 51 468 : PorousFlowHeatEnergy::PorousFlowHeatEnergy(const InputParameters & parameters) 52 : : ElementIntegralPostprocessor(parameters), 53 468 : _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")), 54 468 : _num_phases(_dictator.numPhases()), 55 940 : _base_name(isParamValid("base_name") ? getParam<std::string>("base_name") + "_" : ""), 56 468 : _has_total_strain(hasMaterialProperty<RankTwoTensor>(_base_name + "total_strain")), 57 936 : _total_strain(_has_total_strain 58 754 : ? &getMaterialProperty<RankTwoTensor>(_base_name + "total_strain") 59 : : nullptr), 60 468 : _fluid_present(_num_phases > 0), 61 936 : _include_porous_skeleton(getParam<bool>("include_porous_skeleton")), 62 936 : _phase_index(getParam<std::vector<unsigned int>>("phase")), 63 936 : _porosity(getMaterialProperty<Real>("PorousFlow_porosity_nodal")), 64 936 : _rock_energy_nodal(getMaterialProperty<Real>("PorousFlow_matrix_internal_energy_nodal")), 65 914 : _fluid_density(_fluid_present ? &getMaterialProperty<std::vector<Real>>( 66 : "PorousFlow_fluid_phase_density_nodal") 67 : : nullptr), 68 468 : _fluid_saturation_nodal( 69 914 : _fluid_present ? &getMaterialProperty<std::vector<Real>>("PorousFlow_saturation_nodal") 70 : : nullptr), 71 914 : _energy_nodal(_fluid_present ? &getMaterialProperty<std::vector<Real>>( 72 : "PorousFlow_fluid_phase_internal_energy_nodal") 73 : : nullptr), 74 1404 : _var(getParam<unsigned>("kernel_variable_number") < _dictator.numVariables() 75 934 : ? &_fe_problem.getStandardVariable( 76 466 : _tid, 77 466 : _dictator 78 1400 : .getCoupledStandardMooseVars()[getParam<unsigned>("kernel_variable_number")] 79 : ->name()) 80 468 : : nullptr) 81 : { 82 468 : if (!_phase_index.empty()) 83 : { 84 : // Check that the phase indices entered are not greater than the number of phases 85 332 : const unsigned int max_phase_num = *std::max_element(_phase_index.begin(), _phase_index.end()); 86 332 : if (max_phase_num > _num_phases - 1) 87 2 : paramError("phase", 88 : "The Dictator proclaims that the phase index ", 89 : max_phase_num, 90 : " is greater than the largest phase index possible, which is ", 91 : _num_phases - 1); 92 : } 93 : 94 : // Check that kernel_variable_number is OK 95 1398 : if (getParam<unsigned>("kernel_variable_number") >= _dictator.numVariables()) 96 2 : paramError("kernel_variable_number", 97 : "The Dictator pronounces that the number of PorousFlow variables is ", 98 2 : _dictator.numVariables(), 99 : ", however you have used ", 100 2 : getParam<unsigned>("kernel_variable_number"), 101 : ". This is an error"); 102 : 103 : // Now that we know kernel_variable_number is OK, _var must be OK, 104 : // so ensure that reinit is called on _var: 105 464 : addMooseVariableDependency(_var); 106 : 107 : // Error if a strain base_name is provided but doesn't exist 108 928 : if (parameters.isParamSetByUser("base_name") && !_has_total_strain) 109 2 : paramError("base_name", "A strain base_name ", _base_name, " does not exist"); 110 462 : } 111 : 112 : Real 113 2726 : PorousFlowHeatEnergy::computeIntegral() 114 : { 115 : Real sum = 0; 116 : 117 : // The use of _test in the loops below mean that the 118 : // integral is exactly the same as the one computed 119 : // by the PorousFlowMassTimeDerivative Kernel. Because that 120 : // Kernel is lumped, this Postprocessor also needs to 121 : // be lumped. Hence the use of the "nodal" Material 122 : // Properties 123 2726 : const VariableTestValue & test = _var->phi(); 124 : 125 15978 : for (unsigned node = 0; node < test.size(); ++node) 126 : { 127 : Real nodal_volume = 0.0; 128 86484 : for (_qp = 0; _qp < _qrule->n_points(); ++_qp) 129 : { 130 73232 : const Real n_v = _JxW[_qp] * _coord[_qp] * test[node][_qp]; 131 73232 : if (_has_total_strain) 132 27616 : nodal_volume += n_v * (1.0 + (*_total_strain)[_qp].trace()); 133 : else 134 45616 : nodal_volume += n_v; 135 : } 136 : 137 : Real energy = 0.0; 138 13252 : if (_include_porous_skeleton) 139 12312 : energy += (1.0 - _porosity[node]) * _rock_energy_nodal[node]; 140 : 141 18988 : for (auto ph : _phase_index) 142 5736 : energy += (*_fluid_density)[node][ph] * (*_fluid_saturation_nodal)[node][ph] * 143 5736 : (*_energy_nodal)[node][ph] * _porosity[node]; 144 : 145 13252 : sum += nodal_volume * energy; 146 : } 147 : 148 2726 : return sum; 149 : } 150 : 151 : Real 152 0 : PorousFlowHeatEnergy::computeQpIntegral() 153 : { 154 0 : return 0.0; 155 : }