mirror of
https://github.com/CoolProp/CoolProp.git
synced 2026-01-22 12:28:04 -05:00
Move HmolarP to TabularBackend
This commit is contained in:
@@ -8,87 +8,34 @@
|
||||
void CoolProp::BicubicBackend::update(CoolProp::input_pairs input_pair, double val1, double val2)
|
||||
{
|
||||
if (get_debug_level() > 0){ std::cout << format("update(%s,%g,%g)\n", get_input_pair_short_desc(input_pair).c_str(), val1, val2); }
|
||||
// Clear cached values
|
||||
clear();
|
||||
|
||||
// Clear cached variables
|
||||
clear();
|
||||
|
||||
// Convert to mass-based units if necessary
|
||||
CoolPropDbl ld_value1 = val1, ld_value2 = val2;
|
||||
mass_to_molar_inputs(input_pair, ld_value1, ld_value2);
|
||||
val1 = ld_value1; val2 = ld_value2;
|
||||
|
||||
// To start, set quality to value that is for single-phase
|
||||
// Check the tables, build if neccessary
|
||||
check_tables();
|
||||
|
||||
// Flush the cached indices (set to large number)
|
||||
cached_single_phase_i = std::numeric_limits<std::size_t>::max();
|
||||
cached_single_phase_j = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iL = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iV = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
// To start, set quality to value that is impossible
|
||||
_Q = -1000;
|
||||
|
||||
// Flush the cached indices (set to large number)
|
||||
cached_single_phase_i = std::numeric_limits<std::size_t>::max();
|
||||
cached_single_phase_j = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iL = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iV = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation;
|
||||
PhaseEnvelopeData & phase_envelope = dataset->phase_envelope;
|
||||
SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph;
|
||||
SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT;
|
||||
|
||||
switch(input_pair){
|
||||
case HmolarP_INPUTS:{
|
||||
_hmolar = val1; _p = val2;
|
||||
if (!single_phase_logph.native_inputs_are_in_range(_hmolar, _p)){
|
||||
// Use the AbstractState instance
|
||||
using_single_phase_table = false;
|
||||
if (get_debug_level() > 5){ std::cout << "inputs are not in range"; }
|
||||
throw ValueError(format("inputs are not in range, hmolar=%Lg, p=%Lg", static_cast<CoolPropDbl>(_hmolar), _p));
|
||||
}
|
||||
else{
|
||||
using_single_phase_table = true; // Use the table !
|
||||
std::size_t iL, iV, iclosest = 0;
|
||||
CoolPropDbl hL = 0, hV = 0;
|
||||
SimpleState closest_state;
|
||||
bool is_two_phase = false;
|
||||
// Phase is imposed, use it
|
||||
if (imposed_phase_index != iphase_not_imposed){
|
||||
is_two_phase = (imposed_phase_index == iphase_twophase);
|
||||
}
|
||||
else{
|
||||
if (is_mixture){
|
||||
is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iHmolar, _hmolar, iclosest, closest_state);
|
||||
}
|
||||
else{
|
||||
is_two_phase = pure_saturation.is_inside(iP, _p, iHmolar, _hmolar, iL, iV, hL, hV);
|
||||
}
|
||||
}
|
||||
if ( is_two_phase )
|
||||
{
|
||||
using_single_phase_table = false;
|
||||
_Q = (static_cast<double>(_hmolar)-hL)/(hV-hL);
|
||||
if(!is_in_closed_range(0.0,1.0,static_cast<double>(_Q))){
|
||||
throw ValueError("vapor quality is not in (0,1)");
|
||||
}
|
||||
else{
|
||||
cached_saturation_iL = iL; cached_saturation_iV = iV;
|
||||
_phase = iphase_twophase;
|
||||
}
|
||||
}
|
||||
else{
|
||||
// Find and cache the indices i, j
|
||||
selected_table = SELECTED_PH_TABLE;
|
||||
single_phase_logph.find_native_nearest_good_cell(_hmolar, _p, cached_single_phase_i, cached_single_phase_j);
|
||||
CellCoeffs &cell = dataset->coeffs_ph[cached_single_phase_i][cached_single_phase_j];
|
||||
if (!cell.valid()){
|
||||
if (cell.has_valid_neighbor()){
|
||||
// Get new good neighbor
|
||||
cell.get_alternate(cached_single_phase_i, cached_single_phase_j);
|
||||
}
|
||||
else{
|
||||
if (!cell.valid()){throw ValueError(format("Cell is invalid and has no good neighbors for hmolar = %g, p= %g",val1,val2));}
|
||||
}
|
||||
}
|
||||
// Recalculate the phase
|
||||
recalculate_singlephase_phase();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PUmolar_INPUTS:
|
||||
case PSmolar_INPUTS:
|
||||
case DmolarP_INPUTS:{
|
||||
@@ -302,6 +249,7 @@ void CoolProp::BicubicBackend::update(CoolProp::input_pairs input_pair, double v
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HmolarP_INPUTS:
|
||||
case PQ_INPUTS:
|
||||
case QT_INPUTS:
|
||||
TabularBackend::update(input_pair, val1, val2); break;
|
||||
@@ -310,6 +258,21 @@ void CoolProp::BicubicBackend::update(CoolProp::input_pairs input_pair, double v
|
||||
}
|
||||
}
|
||||
|
||||
void CoolProp::BicubicBackend::find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector<std::vector<CellCoeffs> > &coeffs, double x, double y, std::size_t &i, std::size_t &j)
|
||||
{
|
||||
table.find_native_nearest_good_cell(x, y, i, j);
|
||||
const CellCoeffs &cell = coeffs[i][j];
|
||||
if (!cell.valid()){
|
||||
if (cell.has_valid_neighbor()){
|
||||
// Get new good neighbor
|
||||
cell.get_alternate(i, j);
|
||||
}
|
||||
else{
|
||||
if (!cell.valid()){ throw ValueError(format("Cell is invalid and has no good neighbors for x = %g, y= %g", x, y)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Use the single_phase table to evaluate an output for a transport property
|
||||
*
|
||||
* Here we use linear interpolation because we don't have any information about the derivatives with respect to the
|
||||
|
||||
@@ -134,6 +134,8 @@ class BicubicBackend : public TabularBackend
|
||||
double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j){
|
||||
return evaluate_single_phase(dataset->single_phase_logpT, dataset->coeffs_pT, output, _T, _p, i, j);
|
||||
};
|
||||
|
||||
virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector<std::vector<CellCoeffs> > &coeffs, double x, double y, std::size_t &i, std::size_t &j);
|
||||
|
||||
/**
|
||||
* @brief Evaluate the single-phase transport properties using linear interpolation. Works well except for near the critical point
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
void CoolProp::TTSEBackend::update(CoolProp::input_pairs input_pair, double val1, double val2)
|
||||
{
|
||||
if (get_debug_level() > 0){ std::cout << format("update(%s,%g,%g)\n", get_input_pair_short_desc(input_pair).c_str(), val1, val2); }
|
||||
|
||||
// Clear cached variables
|
||||
clear();
|
||||
|
||||
@@ -16,69 +18,22 @@ void CoolProp::TTSEBackend::update(CoolProp::input_pairs input_pair, double val1
|
||||
|
||||
// Check the tables, build if neccessary
|
||||
check_tables();
|
||||
|
||||
|
||||
// Flush the cached indices (set to large number)
|
||||
cached_single_phase_i = std::numeric_limits<std::size_t>::max();
|
||||
cached_single_phase_i = std::numeric_limits<std::size_t>::max();
|
||||
cached_single_phase_j = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iL = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iL = std::numeric_limits<std::size_t>::max();
|
||||
cached_saturation_iV = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
// To start, set quality to value that is impossible
|
||||
_Q = -1000;
|
||||
|
||||
PhaseEnvelopeData & phase_envelope = dataset->phase_envelope;
|
||||
PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation;
|
||||
PhaseEnvelopeData & phase_envelope = dataset->phase_envelope;
|
||||
SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph;
|
||||
SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT;
|
||||
|
||||
switch(input_pair){
|
||||
case HmolarP_INPUTS:{
|
||||
_hmolar = val1; _p = val2;
|
||||
if (!single_phase_logph.native_inputs_are_in_range(_hmolar, _p)){
|
||||
// Use the AbstractState instance
|
||||
using_single_phase_table = false;
|
||||
if (get_debug_level() > 5){ std::cout << "inputs are not in range"; }
|
||||
throw ValueError(format("inputs are not in range, hmolar=%Lg, p=%Lg", static_cast<CoolPropDbl>(_hmolar), _p));
|
||||
}
|
||||
else{
|
||||
using_single_phase_table = true; // Use the table !
|
||||
std::size_t iL, iV;
|
||||
CoolPropDbl hL = 0, hV = 0;
|
||||
std::size_t iclosest = 0;
|
||||
SimpleState closest_state;
|
||||
bool is_two_phase = false;
|
||||
// Phase is imposed, use it
|
||||
if (imposed_phase_index != iphase_not_imposed){
|
||||
is_two_phase = (imposed_phase_index == iphase_twophase);
|
||||
}
|
||||
else{
|
||||
if (is_mixture){
|
||||
is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iHmolar, _hmolar, iclosest, closest_state);
|
||||
}
|
||||
else{
|
||||
is_two_phase = pure_saturation.is_inside(iP, _p, iHmolar, _hmolar, iL, iV, hL, hV);
|
||||
}
|
||||
}
|
||||
if ( is_two_phase ){
|
||||
using_single_phase_table = false;
|
||||
_Q = (static_cast<double>(_hmolar)-hL)/(hV-hL);
|
||||
if(!is_in_closed_range(0.0,1.0,static_cast<double>(_Q))){
|
||||
throw ValueError("vapor quality is not in (0,1)");
|
||||
}
|
||||
else{
|
||||
cached_saturation_iL = iL; cached_saturation_iV = iV; _phase = iphase_twophase;
|
||||
}
|
||||
}
|
||||
else{
|
||||
// Find and cache the indices i, j
|
||||
selected_table = SELECTED_PH_TABLE;
|
||||
single_phase_logph.find_native_nearest_good_neighbor(_hmolar, _p, cached_single_phase_i, cached_single_phase_j);
|
||||
// Recalculate the phase
|
||||
recalculate_singlephase_phase();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PUmolar_INPUTS:
|
||||
case PSmolar_INPUTS:
|
||||
case DmolarP_INPUTS:{
|
||||
@@ -224,6 +179,7 @@ void CoolProp::TTSEBackend::update(CoolProp::input_pairs input_pair, double val1
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HmolarP_INPUTS:
|
||||
case PQ_INPUTS:
|
||||
case QT_INPUTS:
|
||||
TabularBackend::update(input_pair, val1, val2); break;
|
||||
|
||||
@@ -45,6 +45,11 @@ class TTSEBackend : public TabularBackend
|
||||
double invert_single_phase_x(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j);
|
||||
double invert_single_phase_y(SinglePhaseGriddedTableData &table, parameters output, double y, double x, std::size_t i, std::size_t j);
|
||||
|
||||
/// Find the best set of i,j for native inputs.
|
||||
virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector<std::vector<CellCoeffs> > &coeffs, double x, double y, std::size_t &i, std::size_t &j){
|
||||
return table.find_native_nearest_good_neighbor(x, y, i, j);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Evaluate a derivative in terms of the native inputs of the table
|
||||
* @param table A reference to the table to be used
|
||||
|
||||
@@ -658,6 +658,53 @@ void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double v
|
||||
|
||||
switch (input_pair)
|
||||
{
|
||||
case HmolarP_INPUTS:{
|
||||
_hmolar = val1; _p = val2;
|
||||
if (!single_phase_logph.native_inputs_are_in_range(_hmolar, _p)){
|
||||
// Use the AbstractState instance
|
||||
using_single_phase_table = false;
|
||||
if (get_debug_level() > 5){ std::cout << "inputs are not in range"; }
|
||||
throw ValueError(format("inputs are not in range, hmolar=%Lg, p=%Lg", static_cast<CoolPropDbl>(_hmolar), _p));
|
||||
}
|
||||
else{
|
||||
using_single_phase_table = true; // Use the table !
|
||||
std::size_t iL, iV, iclosest = 0;
|
||||
CoolPropDbl hL = 0, hV = 0;
|
||||
SimpleState closest_state;
|
||||
bool is_two_phase = false;
|
||||
// Phase is imposed, use it
|
||||
if (imposed_phase_index != iphase_not_imposed){
|
||||
is_two_phase = (imposed_phase_index == iphase_twophase);
|
||||
}
|
||||
else{
|
||||
if (is_mixture){
|
||||
is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iHmolar, _hmolar, iclosest, closest_state);
|
||||
}
|
||||
else{
|
||||
is_two_phase = pure_saturation.is_inside(iP, _p, iHmolar, _hmolar, iL, iV, hL, hV);
|
||||
}
|
||||
}
|
||||
if (is_two_phase){
|
||||
using_single_phase_table = false;
|
||||
_Q = (static_cast<double>(_hmolar)-hL)/(hV-hL);
|
||||
if (!is_in_closed_range(0.0, 1.0, static_cast<double>(_Q))){
|
||||
throw ValueError("vapor quality is not in (0,1)");
|
||||
}
|
||||
else{
|
||||
cached_saturation_iL = iL; cached_saturation_iV = iV;
|
||||
_phase = iphase_twophase;
|
||||
}
|
||||
}
|
||||
else{
|
||||
selected_table = SELECTED_PH_TABLE;
|
||||
// Find and cache the indices i, j
|
||||
find_native_nearest_good_indices(single_phase_logph, dataset->coeffs_ph, _hmolar, _p, cached_single_phase_i, cached_single_phase_j);
|
||||
// Recalculate the phase
|
||||
recalculate_singlephase_phase();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PQ_INPUTS:{
|
||||
std::size_t iL = 0, iV = 0;
|
||||
_p = val1; _Q = val2;
|
||||
|
||||
@@ -818,6 +818,16 @@ class TabularBackend : public AbstractState
|
||||
*/
|
||||
void calc_unspecify_phase(){ imposed_phase_index = iphase_not_imposed; };
|
||||
|
||||
virtual double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0;
|
||||
virtual double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0;
|
||||
|
||||
/// Ask the derived class to find the nearest good set of i,j that it wants to use (pure virtual)
|
||||
virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector<std::vector<CellCoeffs> > &coeffs, double x, double y, std::size_t &i, std::size_t &j) = 0;
|
||||
|
||||
phases calc_phase(void){ return _phase; }
|
||||
CoolPropDbl calc_T_critical(void){return this->AS->T_critical();};
|
||||
CoolPropDbl calc_Ttriple(void){return this->AS->Ttriple();};
|
||||
@@ -837,12 +847,7 @@ class TabularBackend : public AbstractState
|
||||
const std::vector<CoolPropDbl> calc_mass_fractions(void){ return AS->get_mass_fractions(); };
|
||||
|
||||
CoolPropDbl calc_molar_mass(void){return AS->molar_mass();};
|
||||
virtual double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j) = 0;
|
||||
virtual double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0;
|
||||
virtual double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0;
|
||||
|
||||
CoolPropDbl calc_saturated_liquid_keyed_output(parameters key);
|
||||
CoolPropDbl calc_saturated_vapor_keyed_output(parameters key);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user