diff --git a/modules/fluid_properties/include/fluidproperties/SinglePhaseFluidProperties.h b/modules/fluid_properties/include/fluidproperties/SinglePhaseFluidProperties.h index f2548f81c309..7e8dd4bdb27d 100644 --- a/modules/fluid_properties/include/fluidproperties/SinglePhaseFluidProperties.h +++ b/modules/fluid_properties/include/fluidproperties/SinglePhaseFluidProperties.h @@ -438,12 +438,15 @@ class SinglePhaseFluidProperties : public FluidProperties /** * Newton's method may be used to convert between variable sets - * _tolerance, _T_initial_guess, and _p_initial_guess are the parameters for these - * iterative solves */ + /// Relative tolerance of the solves const Real _tolerance; + /// Initial guess for temperature (or temperature used to compute the initial guess) const Real _T_initial_guess; + /// Initial guess for pressure (or pressure used to compute the initial guess) const Real _p_initial_guess; + /// Maximum number of iterations for the variable conversion newton solves + const unsigned int _max_newton_its; private: void unimplementedDerivativeMethod(const std::string & property_function_name) const diff --git a/modules/fluid_properties/include/fluidproperties/TabulatedFluidProperties.h b/modules/fluid_properties/include/fluidproperties/TabulatedFluidProperties.h index 5858d5416823..4f5e1730e7f8 100644 --- a/modules/fluid_properties/include/fluidproperties/TabulatedFluidProperties.h +++ b/modules/fluid_properties/include/fluidproperties/TabulatedFluidProperties.h @@ -226,7 +226,15 @@ class TabulatedFluidProperties : public SinglePhaseFluidProperties /// - if user-specified, use _v_min/max and _e_min/max /// - if reading a (v,e) interpolation, the bounds of that range /// - if a _fp exist find the min/max v/e from T_min/max and p_min/max + void createVGridVector(); void createVEGridVectors(); + /// Create (or reset) the grid vectors for the specific volume and enthalpy interpolation + /// The order of priority for determining the range boundaries in v and h: + /// - if user-specified, use _v_min/max and _e_min/max + /// - if a _fp exist find the min/max v/e from T_min/max and p_min/max + /// - if reading a (p,T) tabulation, the bounds of the enthalpy grid + /// - if reading a (v,e) tabulation, the bounds of the enthalpy grid + void createVHGridVectors(); /// Standardized error message for missing interpolation void missingVEInterpolationError(const std::string & function_name) const; @@ -336,6 +344,8 @@ class TabulatedFluidProperties : public SinglePhaseFluidProperties bool _log_space_v; /// log-space the internal energy interpolation grid axis instead of linear bool _log_space_e; + /// log-space the enthalpy interpolation grid axis instead of linear + bool _log_space_h; /// User-selected out-of-bounds behavior MooseEnum _OOBBehavior; @@ -345,6 +355,7 @@ class TabulatedFluidProperties : public SinglePhaseFluidProperties Ignore, Throw, DeclareInvalid, + WarnInvalid, SetToClosestBound }; diff --git a/modules/fluid_properties/src/fluidproperties/NaKFluidProperties.C b/modules/fluid_properties/src/fluidproperties/NaKFluidProperties.C index c75e1afd63c5..c6ddb80f634d 100644 --- a/modules/fluid_properties/src/fluidproperties/NaKFluidProperties.C +++ b/modules/fluid_properties/src/fluidproperties/NaKFluidProperties.C @@ -69,8 +69,13 @@ NaKFluidProperties::T_from_p_rho(Real pressure, Real density) const // NOTE we could also invert analytically the third degree polynomial, see Cardan's method auto lambda = [&](Real p, Real current_T, Real & new_rho, Real & drho_dp, Real & drho_dT) { rho_from_p_T(p, current_T, new_rho, drho_dp, drho_dT); }; - Real T = FluidPropertiesUtils::NewtonSolve( - pressure, density, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_rho") + Real T = FluidPropertiesUtils::NewtonSolve(pressure, + density, + _T_initial_guess, + _tolerance, + lambda, + name() + "::T_from_p_rho", + _max_newton_its) .first; // check for nans if (std::isnan(T)) diff --git a/modules/fluid_properties/src/fluidproperties/SimpleFluidProperties.C b/modules/fluid_properties/src/fluidproperties/SimpleFluidProperties.C index 7cb3273e9532..a6697617c020 100644 --- a/modules/fluid_properties/src/fluidproperties/SimpleFluidProperties.C +++ b/modules/fluid_properties/src/fluidproperties/SimpleFluidProperties.C @@ -67,7 +67,8 @@ SimpleFluidProperties::molarMass() const return _molar_mass; } -Real SimpleFluidProperties::beta_from_p_T(Real /*pressure*/, Real /*temperature*/) const +Real +SimpleFluidProperties::beta_from_p_T(Real /*pressure*/, Real /*temperature*/) const { return _thermal_expansion; } @@ -81,7 +82,8 @@ SimpleFluidProperties::beta_from_p_T( dbeta_dT = 0.0; } -Real SimpleFluidProperties::cp_from_p_T(Real /*pressure*/, Real /*temperature*/) const +Real +SimpleFluidProperties::cp_from_p_T(Real /*pressure*/, Real /*temperature*/) const { return _cp; } @@ -95,7 +97,11 @@ SimpleFluidProperties::cp_from_p_T( dcp_dT = 0.0; } -Real SimpleFluidProperties::cp_from_v_e(Real /*v*/, Real /*e*/) const { return _cp; } +Real +SimpleFluidProperties::cp_from_v_e(Real /*v*/, Real /*e*/) const +{ + return _cp; +} void SimpleFluidProperties::cp_from_v_e(Real v, Real e, Real & cp, Real & dcp_dv, Real & dcp_de) const @@ -105,7 +111,8 @@ SimpleFluidProperties::cp_from_v_e(Real v, Real e, Real & cp, Real & dcp_dv, Rea dcp_de = 0.0; } -Real SimpleFluidProperties::cv_from_p_T(Real /*pressure*/, Real /*temperature*/) const +Real +SimpleFluidProperties::cv_from_p_T(Real /*pressure*/, Real /*temperature*/) const { return _cv; } @@ -119,7 +126,11 @@ SimpleFluidProperties::cv_from_p_T( dcv_dT = 0.0; } -Real SimpleFluidProperties::cv_from_v_e(Real /*v*/, Real /*e*/) const { return _cv; } +Real +SimpleFluidProperties::cv_from_v_e(Real /*v*/, Real /*e*/) const +{ + return _cv; +} void SimpleFluidProperties::cv_from_v_e(Real v, Real e, Real & cv, Real & dcv_dv, Real & dcv_de) const @@ -171,7 +182,8 @@ SimpleFluidProperties::c_from_v_e(Real v, Real e, Real & c, Real & dc_dv, Real & dc_de = 0.0; } -Real SimpleFluidProperties::k_from_p_T(Real /*pressure*/, Real /*temperature*/) const +Real +SimpleFluidProperties::k_from_p_T(Real /*pressure*/, Real /*temperature*/) const { return _thermal_conductivity; } @@ -185,7 +197,8 @@ SimpleFluidProperties::k_from_p_T( dk_dT = 0; } -Real SimpleFluidProperties::k_from_v_e(Real /*v*/, Real /*e*/) const +Real +SimpleFluidProperties::k_from_v_e(Real /*v*/, Real /*e*/) const { return _thermal_conductivity; } @@ -199,7 +212,8 @@ SimpleFluidProperties::k_from_v_e( dk_de = 0; } -Real SimpleFluidProperties::s_from_p_T(Real /*pressure*/, Real /*temperature*/) const +Real +SimpleFluidProperties::s_from_p_T(Real /*pressure*/, Real /*temperature*/) const { return _specific_entropy; } @@ -213,12 +227,17 @@ SimpleFluidProperties::s_from_p_T( ds_dT = 0; } -Real SimpleFluidProperties::s_from_h_p(Real /*enthalpy*/, Real /*pressure*/) const +Real +SimpleFluidProperties::s_from_h_p(Real /*enthalpy*/, Real /*pressure*/) const { return _specific_entropy; } -Real SimpleFluidProperties::s_from_v_e(Real /*v*/, Real /*e*/) const { return _specific_entropy; } +Real +SimpleFluidProperties::s_from_v_e(Real /*v*/, Real /*e*/) const +{ + return _specific_entropy; +} void SimpleFluidProperties::s_from_v_e( @@ -326,7 +345,7 @@ SimpleFluidProperties::T_from_p_h(Real p, Real h) const auto lambda = [&](Real p, Real current_T, Real & new_rho, Real & dh_dp, Real & dh_dT) { h_from_p_T(p, current_T, new_rho, dh_dp, dh_dT); }; return FluidPropertiesUtils::NewtonSolve( - p, h, T_initial, _tolerance, lambda, name() + "::T_from_p_h") + p, h, T_initial, _tolerance, lambda, name() + "::T_from_p_h", _max_newton_its) .first; } @@ -429,7 +448,8 @@ SimpleFluidProperties::e_from_v_h(Real v, Real h, Real & e, Real & de_dv, Real & de_dh = de_dp * dp_dh + de_dT * dT_dh; } -Real SimpleFluidProperties::mu_from_p_T(Real /*pressure*/, Real /*temperature*/) const +Real +SimpleFluidProperties::mu_from_p_T(Real /*pressure*/, Real /*temperature*/) const { return _viscosity; } @@ -443,7 +463,11 @@ SimpleFluidProperties::mu_from_p_T( dmu_dT = 0.0; } -Real SimpleFluidProperties::mu_from_v_e(Real /*v*/, Real /*e*/) const { return _viscosity; } +Real +SimpleFluidProperties::mu_from_v_e(Real /*v*/, Real /*e*/) const +{ + return _viscosity; +} void SimpleFluidProperties::mu_from_v_e(Real v, Real e, Real & mu, Real & dmu_dv, Real & dmu_de) const diff --git a/modules/fluid_properties/src/fluidproperties/SinglePhaseFluidProperties.C b/modules/fluid_properties/src/fluidproperties/SinglePhaseFluidProperties.C index 70dad43c9323..a6e32d7064e2 100644 --- a/modules/fluid_properties/src/fluidproperties/SinglePhaseFluidProperties.C +++ b/modules/fluid_properties/src/fluidproperties/SinglePhaseFluidProperties.C @@ -28,6 +28,8 @@ SinglePhaseFluidProperties::validParams() 2e5, "p_initial_guess > 0", "Pressure initial guess for Newton Method variable set conversion"); + params.addParam( + "max_newton_its", 100, "Maximum number of Newton iterations for variable set conversions"); params.addParamNamesToGroup("tolerance T_initial_guess p_initial_guess", "Variable set conversions Newton solve"); @@ -39,7 +41,8 @@ SinglePhaseFluidProperties::SinglePhaseFluidProperties(const InputParameters & p // downstream apps are creating fluid properties without their parameters, hence the workaround _tolerance(isParamValid("tolerance") ? getParam("tolerance") : 1e-8), _T_initial_guess(isParamValid("T_initial_guess") ? getParam("T_initial_guess") : 400), - _p_initial_guess(isParamValid("p_initial_guess") ? getParam("p_initial_guess") : 2e5) + _p_initial_guess(isParamValid("p_initial_guess") ? getParam("p_initial_guess") : 2e5), + _max_newton_its(getParam("max_newton_its")) { } diff --git a/modules/fluid_properties/src/fluidproperties/TabulatedBicubicFluidProperties.C b/modules/fluid_properties/src/fluidproperties/TabulatedBicubicFluidProperties.C index 704006c17ed6..c87a9c8b2c21 100644 --- a/modules/fluid_properties/src/fluidproperties/TabulatedBicubicFluidProperties.C +++ b/modules/fluid_properties/src/fluidproperties/TabulatedBicubicFluidProperties.C @@ -69,8 +69,8 @@ TabulatedBicubicFluidProperties::constructInterpolation() bool conversion_succeeded = true; unsigned int fail_counter_ve = 0; unsigned int fail_counter_vh = 0; - // Create interpolations of (p,T) from (v,e) and (v,h) - if (_construct_pT_from_ve || _construct_pT_from_vh) + // Create interpolations of (p,T) from (v,e) + if (_construct_pT_from_ve) { // Grids in specific volume and internal energy can be either linear or logarithmic // NOTE: this could have been called already when generating tabulated data @@ -159,31 +159,12 @@ TabulatedBicubicFluidProperties::constructInterpolation() std::make_unique(_specific_volume, _internal_energy, T_from_v_e); } + // Create interpolations of (p,T) from (v,h) if (_construct_pT_from_vh) { - if (_fp) - { - // extreme values of enthalpy for the grid bounds - Real h1 = h_from_p_T(_pressure_min, _temperature_min); - Real h2 = h_from_p_T(_pressure_max, _temperature_min); - Real h3 = h_from_p_T(_pressure_min, _temperature_max); - Real h4 = h_from_p_T(_pressure_max, _temperature_max); - _h_min = std::min({h1, h2, h3, h4}); - _h_max = std::max({h1, h2, h3, h4}); - } - // if csv exists, get max and min values from csv file - else - { - _h_max = *max_element(_properties[_enthalpy_idx].begin(), _properties[_enthalpy_idx].end()); - _h_min = *min_element(_properties[_enthalpy_idx].begin(), _properties[_enthalpy_idx].end()); - } - Real dh = (_h_max - _h_min) / ((Real)_num_e - 1); - - // Create h grid for interpolation - // enthalpy & internal energy use same # grid points - _enthalpy.resize(_num_e); - for (unsigned int j = 0; j < _num_e; ++j) - _enthalpy[j] = _h_min + j * dh; + // Grids in specific volume and enthalpy can be either linear or logarithmic + // NOTE: the specific volume grid could have been created when generating tabulated data + createVHGridVectors(); // initialize vectors for interpolation std::vector> p_from_v_h(_num_v); diff --git a/modules/fluid_properties/src/fluidproperties/TabulatedFluidProperties.C b/modules/fluid_properties/src/fluidproperties/TabulatedFluidProperties.C index 98691387b2a6..95d02c59617c 100644 --- a/modules/fluid_properties/src/fluidproperties/TabulatedFluidProperties.C +++ b/modules/fluid_properties/src/fluidproperties/TabulatedFluidProperties.C @@ -111,6 +111,11 @@ TabulatedFluidProperties::validParams() false, "Option to use a base-10 logarithmically-spaced grid for specific internal energy instead " "of a linearly-spaced grid."); + params.addParam( + "use_log_grid_h", + false, + "Option to use a base-10 logarithmically-spaced grid for specific enthalpy instead " + "of a linearly-spaced grid."); // Out of bounds behavior params.addDeprecatedParam( @@ -120,7 +125,7 @@ TabulatedFluidProperties::validParams() "This parameter has been replaced by the 'out_of_bounds_behavior' parameter which offers " "more flexibility. The option to error is called 'throw' in that parameter."); // NOTE: this enum must remain the same as OOBBehavior in the header - MooseEnum OOBBehavior("ignore throw declare_invalid set_to_closest_bound", "throw"); + MooseEnum OOBBehavior("ignore throw declare_invalid warn_invalid set_to_closest_bound", "throw"); params.addParam("out_of_bounds_behavior", OOBBehavior, "Property evaluation behavior when evaluated outside the " @@ -132,14 +137,17 @@ TabulatedFluidProperties::validParams() params.addParam( "allow_fp_and_tabulation", false, "Whether to allow the two sources of data concurrently"); - params.addParamNamesToGroup("fluid_property_file save_file", "Tabulation file read/write"); + params.addParamNamesToGroup("fluid_property_file fluid_property_ve_file " + "fluid_property_output_file fluid_property_ve_output_file", + "Tabulation file read/write"); params.addParamNamesToGroup("construct_pT_from_ve construct_pT_from_vh", "Variable set conversion"); params.addParamNamesToGroup("temperature_min temperature_max pressure_min pressure_max e_min " "e_max v_min v_max error_on_out_of_bounds out_of_bounds_behavior", "Tabulation and interpolation bounds"); - params.addParamNamesToGroup("num_T num_p num_v num_e use_log_grid_v", - "Tabulation and interpolation discretization"); + params.addParamNamesToGroup( + "num_T num_p num_v num_e use_log_grid_v use_log_grid_e use_log_grid_h", + "Tabulation and interpolation discretization"); return params; } @@ -200,6 +208,7 @@ TabulatedFluidProperties::TabulatedFluidProperties(const InputParameters & param _num_e(getParam("num_e")), _log_space_v(getParam("use_log_grid_v")), _log_space_e(getParam("use_log_grid_e")), + _log_space_h(getParam("use_log_grid_h")), _OOBBehavior(getParam("out_of_bounds_behavior")) { // Check that initial guess (used in Newton Method) is within min and max values @@ -231,7 +240,7 @@ TabulatedFluidProperties::TabulatedFluidProperties(const InputParameters & param } else if (isParamValid("v_min") || isParamValid("v_max")) paramError("v_min", - "Either both or none of the min and max values of the specific internal energy " + "Either both or none of the min and max values of the specific volume " "should be specified"); else _v_bounds_specified = false; @@ -279,8 +288,12 @@ TabulatedFluidProperties::TabulatedFluidProperties(const InputParameters & param "from the bounds of the input tabulation."); if (!_fp && !_file_name_ve_in.empty() && (isParamSetByUser("num_e") || isParamSetByUser("num_v"))) mooseWarning("User-specified grid sizes in specific volume and internal energy are ignored " - "when reading a 'fluid_property_ve_file'. The tabulation bounds are selected " - "from the bounds of the input tabulation."); + "when reading a 'fluid_property_ve_file'. The tabulation widths are read " + "from the input tabulation."); + if (!_file_name_ve_in.empty() && (_log_space_v || _log_space_e)) + mooseWarning( + "User specfied logarithmic grids in specific volume and energy are ignored when reading a " + "'fluid_properties_ve_file'. The tabulation grid is read from the input tabulation"); } void @@ -545,8 +558,13 @@ TabulatedFluidProperties::T_from_p_rho(Real pressure, Real rho) const { auto lambda = [&](Real p, Real current_T, Real & new_rho, Real & drho_dp, Real & drho_dT) { rho_from_p_T(p, current_T, new_rho, drho_dp, drho_dT); }; - Real T = FluidPropertiesUtils::NewtonSolve( - pressure, rho, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_rho") + Real T = FluidPropertiesUtils::NewtonSolve(pressure, + rho, + _T_initial_guess, + _tolerance, + lambda, + name() + "::T_from_p_rho", + _max_newton_its) .first; // check for nans if (std::isnan(T)) @@ -573,8 +591,13 @@ TabulatedFluidProperties::T_from_p_s(Real pressure, Real s) const { auto lambda = [&](Real p, Real current_T, Real & new_s, Real & ds_dp, Real & ds_dT) { s_from_p_T(p, current_T, new_s, ds_dp, ds_dT); }; - Real T = FluidPropertiesUtils::NewtonSolve( - pressure, s, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_s") + Real T = FluidPropertiesUtils::NewtonSolve(pressure, + s, + _T_initial_guess, + _tolerance, + lambda, + name() + "::T_from_p_s", + _max_newton_its) .first; // check for nans if (std::isnan(T)) @@ -875,7 +898,8 @@ TabulatedFluidProperties::e_from_v_h(Real v, Real h) const /*e initial guess*/ h - _p_initial_guess * v, _tolerance, lambda, - name() + "::e_from_v_h") + name() + "::e_from_v_h", + _max_newton_its) .first; return e; } @@ -911,7 +935,8 @@ TabulatedFluidProperties::e_from_v_h(Real v, Real h, Real & e, Real & de_dv, Rea /*e initial guess*/ h - _p_initial_guess * v, _tolerance, lambda, - name() + "::e_from_v_h"); + name() + "::e_from_v_h", + _max_newton_its); e = e_data.first; // Finite difference approximation const auto e2 = e_from_v_h(v * (1 + TOLERANCE), h); @@ -1773,6 +1798,8 @@ TabulatedFluidProperties::checkInputVariables(T & pressure, T & temperature) con pressure = std::max(_pressure_min, std::min(pressure, _pressure_max)); if (_OOBBehavior == DeclareInvalid) flagInvalidSolution("Pressure out of bounds"); + else if (_OOBBehavior == WarnInvalid) + flagSolutionWarning("Pressure out of bounds"); } } @@ -1789,6 +1816,8 @@ TabulatedFluidProperties::checkInputVariables(T & pressure, T & temperature) con temperature = std::max(T(_temperature_min), std::min(temperature, T(_temperature_max))); if (_OOBBehavior == DeclareInvalid) flagInvalidSolution("Temperature out of bounds"); + else if (_OOBBehavior == WarnInvalid) + flagSolutionWarning("Temperature out of bounds"); } } } @@ -1810,6 +1839,8 @@ TabulatedFluidProperties::checkInputVariablesVE(T & v, T & e) const e = std::max(_e_min, std::min(e, _e_max)); if (_OOBBehavior == DeclareInvalid) flagInvalidSolution("Specific internal energy out of bounds"); + else if (_OOBBehavior == WarnInvalid) + flagSolutionWarning("Specific internal energy out of bounds"); } } @@ -1824,6 +1855,8 @@ TabulatedFluidProperties::checkInputVariablesVE(T & v, T & e) const v = std::max(T(_v_min), std::min(v, T(_v_max))); if (_OOBBehavior == DeclareInvalid) flagInvalidSolution("Specific volume out of bounds"); + else if (_OOBBehavior == WarnInvalid) + flagSolutionWarning("Specific volume out of bounds"); } } } @@ -1989,10 +2022,6 @@ TabulatedFluidProperties::readFileTabulationData(const bool use_pT) paramError("construct_pT_from_ve", "Reading a (v,e) tabulation and generating (p,T) to (v,e) interpolation tables is " "not supported at this time."); - if (_construct_pT_from_vh) - paramError("construct_pT_from_vh", - "Reading a (v,e) tabulation and generating (p,T) to (v,h) interpolation tables is " - "not supported at this time."); // Make sure we use the tabulation bounds _e_bounds_specified = true; @@ -2139,9 +2168,9 @@ TabulatedFluidProperties::computePropertyIndicesInInterpolationVectors() } void -TabulatedFluidProperties::createVEGridVectors() +TabulatedFluidProperties::createVGridVector() { - mooseAssert(_file_name_ve_in.empty(), "We should be reading the (v, e) grid from file"); + mooseAssert(_file_name_ve_in.empty(), "We should be reading the specific volume grid from file"); if (!_v_bounds_specified) { if (_fp) @@ -2164,6 +2193,8 @@ TabulatedFluidProperties::createVEGridVectors() _v_max = 1 / rho_min; _v_min = 1 / rho_max; } + // Prevent changing the bounds of the grid + _v_bounds_specified = true; } // Create v grid for interpolation @@ -2183,7 +2214,12 @@ TabulatedFluidProperties::createVEGridVectors() for (unsigned int j = 0; j < _num_v; ++j) _specific_volume[j] = _v_min + j * dv; } +} +void +TabulatedFluidProperties::createVEGridVectors() +{ + createVGridVector(); if (!_e_bounds_specified) { if (_fp) @@ -2229,6 +2265,60 @@ TabulatedFluidProperties::createVEGridVectors() } } +void +TabulatedFluidProperties::createVHGridVectors() +{ + if (_file_name_ve_in.empty()) + createVGridVector(); + if (_fp) + { + // extreme values of enthalpy for the grid bounds + Real h1 = h_from_p_T(_pressure_min, _temperature_min); + Real h2 = h_from_p_T(_pressure_max, _temperature_min); + Real h3 = h_from_p_T(_pressure_min, _temperature_max); + Real h4 = h_from_p_T(_pressure_max, _temperature_max); + _h_min = std::min({h1, h2, h3, h4}); + _h_max = std::max({h1, h2, h3, h4}); + } + // if csv exists, get max and min values from csv file + else if (_properties.size()) + { + _h_max = *max_element(_properties[_enthalpy_idx].begin(), _properties[_enthalpy_idx].end()); + _h_min = *min_element(_properties[_enthalpy_idx].begin(), _properties[_enthalpy_idx].end()); + } + else if (_properties_ve.size()) + { + _h_max = *max_element(_properties[_enthalpy_idx].begin(), _properties[_enthalpy_idx].end()); + _h_min = *min_element(_properties[_enthalpy_idx].begin(), _properties[_enthalpy_idx].end()); + } + else + mooseError("Need a source to compute the enthalpy grid bounds: either a FP object, or a (p,T) " + "tabulation file or a (v,e) tabulation file"); + + // Create h grid for interpolation + // enthalpy & internal energy use same # grid points + _enthalpy.resize(_num_e); + if (_log_space_h) + { + // incrementing the exponent linearly will yield a log-spaced grid after taking the value to + // the power of 10 + if (_h_min < 0) + mooseError("Logarithmic grid in specific energy can only be used with a positive enthalpy. " + "Current minimum: " + + std::to_string(_h_min)); + Real dh = (std::log10(_h_max) - std::log10(_h_min)) / ((Real)_num_e - 1); + Real log_h_min = std::log10(_h_min); + for (const auto j : make_range(_num_e)) + _enthalpy[j] = std::pow(10, log_h_min + j * dh); + } + else + { + Real dh = (_h_max - _h_min) / ((Real)_num_e - 1); + for (const auto j : make_range(_num_e)) + _enthalpy[j] = _h_min + j * dh; + } +} + void TabulatedFluidProperties::missingVEInterpolationError(const std::string & function_name) const { diff --git a/modules/fluid_properties/src/fluidproperties/TemperaturePressureFunctionFluidProperties.C b/modules/fluid_properties/src/fluidproperties/TemperaturePressureFunctionFluidProperties.C index 906968c4957e..3a1696a02d51 100644 --- a/modules/fluid_properties/src/fluidproperties/TemperaturePressureFunctionFluidProperties.C +++ b/modules/fluid_properties/src/fluidproperties/TemperaturePressureFunctionFluidProperties.C @@ -64,7 +64,7 @@ TemperaturePressureFunctionFluidProperties::T_from_p_h(Real p, Real h) const auto lambda = [&](Real p, Real current_T, Real & new_h, Real & dh_dp, Real & dh_dT) { h_from_p_T(p, current_T, new_h, dh_dp, dh_dT); }; Real T = FluidPropertiesUtils::NewtonSolve( - p, h, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_h") + p, h, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_h", _max_newton_its) .first; // check for nans if (std::isnan(T)) @@ -115,7 +115,8 @@ TemperaturePressureFunctionFluidProperties::cp_from_v_e( dcp_de = (cp_pert - cp) / eps / e; } -Real TemperaturePressureFunctionFluidProperties::cv_from_v_e(Real /* v */, Real /* e */) const +Real +TemperaturePressureFunctionFluidProperties::cv_from_v_e(Real /* v */, Real /* e */) const { return _cv; } @@ -304,8 +305,9 @@ TemperaturePressureFunctionFluidProperties::cp_from_p_T( dcp_dT = pressure * d2v_dT2; } -Real TemperaturePressureFunctionFluidProperties::cv_from_p_T(Real /* pressure */, - Real /* temperature */) const +Real +TemperaturePressureFunctionFluidProperties::cv_from_p_T(Real /* pressure */, + Real /* temperature */) const { return _cv; } diff --git a/modules/fluid_properties/test/tests/tabulated/tests b/modules/fluid_properties/test/tests/tabulated/tests index e476c1acbcc4..58616dae1ecd 100644 --- a/modules/fluid_properties/test/tests/tabulated/tests +++ b/modules/fluid_properties/test/tests/tabulated/tests @@ -132,6 +132,22 @@ expect_err = 'Temperature initial guess for \(p,T\), \(v,e\) conversions 100000 is outside the range of tabulated temperature' detail = 'if the user-specified temperature initial guess for variable set inversions is out of bounds' [] + [missing_energy_bound] + type = RunException + input = 'tabulated_v_e.i' + cli_args = "FluidProperties/tabulated/fluid_property_file='fluid_properties.csv' + FluidProperties/tabulated/e_min=100" + expect_err = 'Either both or none of the min and max values of the specific internal energy should be specified' + detail = 'if the user only specified one bound for a range of specific internal energy,' + [] + [missing_specific_volume_bound] + type = RunException + input = 'tabulated_v_e.i' + cli_args = "FluidProperties/tabulated/v_min=1e3 + FluidProperties/tabulated/fluid_property_file='fluid_properties.csv'" + expect_err = 'Either both or none of the min and max values of the specific volume should be specified' + detail = 'if the user only specified one bound for a range of specific volume.' + [] [] # Note that these could be unit tests [out_of_bounds] @@ -170,6 +186,26 @@ expect_err = 'Temperature out of bounds' detail = 'declare the solution invalid if the desired temperature for a fluid property evaluation is outside the user-specified bounds, when prescribed to do so in such conditions' [] + [warn_pressure_out_of_bounds] + type = RunApp + input = 'tabulated.i' + cli_args = "AuxVariables/pressure/initial_condition=1e4 " + "FluidProperties/tabulated/out_of_bounds_behavior=warn_invalid " + "Problem/solve=true Kernels/diff/type=MatDiffusion " + "Kernels/diff/diffusivity=viscosity" + expect_out = 'Pressure out of bounds' + detail = 'count the number of occurrences if the desired pressure for a fluid property evaluation is outside the user-specified bounds, when prescribed to do so in such conditions,' + [] + [warn_temperature_out_of_bounds] + type = RunApp + input = 'tabulated.i' + cli_args = "AuxVariables/temperature/initial_condition=250 " + "FluidProperties/tabulated/out_of_bounds_behavior=warn_invalid " + "Problem/solve=true Kernels/diff/type=MatDiffusion " + "Kernels/diff/diffusivity=viscosity" + expect_out = 'Temperature out of bounds' + detail = 'count the number of occurrences if the desired temperature for a fluid property evaluation is outside the user-specified bounds, when prescribed to do so in such conditions,' + [] [ignore_pressure_out_of_bounds] type = RunApp input = 'tabulated.i' @@ -183,4 +219,34 @@ detail = 'ignore if the desired temperature for a fluid property evaluation is outside the user-specified bounds, when prescribed to ignore in such conditions' [] [] + [warnings] + requirement = 'The system shall return a warning if' + [num_grids_ve] + type = RunException + input = 'tabulated_v_e.i' + cli_args = "FluidProperties/tabulated/fluid_property_ve_file='gold/fluid_properties_out_ve.csv' + FluidProperties/tabulated/num_v=200" + expect_err = 'User-specified grid sizes in specific volume and internal energy are ignored' + allow_warnings = false + detail = 'the user specifies a grid size when reading the interpolation grid from file,' + [] + [min_max_ve] + type = RunException + input = 'tabulated_v_e.i' + cli_args = "FluidProperties/tabulated/fluid_property_ve_file='gold/fluid_properties_out_ve.csv' + FluidProperties/tabulated/v_min=20 FluidProperties/tabulated/v_max=20" + expect_err = 'User-specified bounds in specific volume and internal energy are ignored' + allow_warnings = false + detail = 'the user specifies a grid extent when reading the interpolation grid from file,' + [] + [log_ve] + type = RunException + input = 'tabulated_v_e.i' + cli_args = "FluidProperties/tabulated/fluid_property_ve_file='gold/fluid_properties_out_ve.csv' + FluidProperties/tabulated/use_log_grid_v=true" + expect_err = 'User specfied logarithmic grids in specific volume and energy are ignored' + allow_warnings = false + detail = 'the user specifies that the grid is logarithmic when reading the interpolation grid from file.' + [] + [] []