Finish moving old version of PT to TabularBackend

This commit is contained in:
Ian Bell
2015-12-06 19:38:14 -07:00
parent 9c4f25d34d
commit b0eabd6981
5 changed files with 86 additions and 173 deletions

View File

@@ -4,113 +4,6 @@
#include "MatrixMath.h"
#include "Backends/Helmholtz/PhaseEnvelopeRoutines.h"
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 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;
// 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;
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 PT_INPUTS:{
_p = val1; _T = val2;
if (!single_phase_logpT.native_inputs_are_in_range(_T, _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, p=%g Pa, T=%g K", _p, _T));
}
else{
using_single_phase_table = true; // Use the table !
std::size_t iL = 0, iV = 0, iclosest = 0;
CoolPropDbl TL = 0, TV = 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, iT, _T, iclosest, closest_state);
}
else{
is_two_phase = pure_saturation.is_inside(iP, _p, iT, _T, iL, iV, TL, TV);
}
}
if ( is_two_phase )
{
using_single_phase_table = false;
throw ValueError(format("P,T with TTSE cannot be two-phase for now"));
}
else{
// Find and cache the indices i, j
selected_table = SELECTED_PT_TABLE;
single_phase_logpT.find_native_nearest_good_cell(_T, _p, cached_single_phase_i, cached_single_phase_j);
CellCoeffs &cell = dataset->coeffs_pT[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 p = %g Pa, T= %g K",val1,val2));}
}
}
// If p < pc, you might be getting a liquid solution when you want a vapor solution or vice versa
// if you are very close to the saturation curve, so we figure out what the saturation temperature
// is for the given pressure
if (_p < this->AS->p_critical())
{
double Ts = pure_saturation.evaluate(iT, _p, _Q, iL, iV);
double TL = single_phase_logpT.T[cached_single_phase_i][cached_single_phase_j];
double TR = single_phase_logpT.T[cached_single_phase_i+1][cached_single_phase_j];
if (TL < Ts && Ts < TR){
if (_T < Ts){
if (cached_single_phase_i == 0){throw ValueError(format("P, T are near saturation, but cannot move the cell to the left")); }
// It's liquid, move the cell to the left
cached_single_phase_i--;
}else{
if (cached_single_phase_i > single_phase_logpT.Nx-2){ throw ValueError(format("P,T are near saturation, but cannot move the cell to the right")); }
// It's vapor, move to the right
cached_single_phase_i++;
}
}
}
// Recalculate the phase
recalculate_singlephase_phase();
}
}
break;
}
default:
TabularBackend::update(input_pair, val1, val2); break;
}
}
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);

View File

@@ -91,10 +91,6 @@ class BicubicBackend : public TabularBackend
};
std::string backend_name(void){return "BicubicBackend";}
/** Update the state
*/
void update(CoolProp::input_pairs input_pair, double val1, double val2);
/**
* @brief Evaluate a derivative in terms of the native inputs of the table
* @param table A reference to the table to be used

View File

@@ -4,66 +4,6 @@
#include "TTSEBackend.h"
#include "CoolProp.h"
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();
// 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;
// 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;
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 PT_INPUTS:{
_p = val1; _T = val2;
if (!single_phase_logpT.native_inputs_are_in_range(_T, _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, p=%g Pa, T=%g K", _p, _T));
}
else{
using_single_phase_table = true; // Use the table !
std::size_t iL = 0, iV = 0;
CoolPropDbl TL = 0, TV = 0;
if (pure_saturation.is_inside(iP, _p, iT, _T, iL, iV, TL, TV)){
using_single_phase_table = false;
throw ValueError(format("P,T with TTSE cannot be two-phase for now"));
}
else{
// Find and cache the indices i, j
selected_table = SELECTED_PT_TABLE;
single_phase_logpT.find_native_nearest_neighbor(_T, _p, cached_single_phase_i, cached_single_phase_j);
// Recalculate the phase
recalculate_singlephase_phase();
}
}
break;
}
default:
TabularBackend::update(input_pair, val1, val2); break;
}
}
/** Use the single_phase table to evaluate an output for a transport property
*
* Here we use bilinear interpolation because we don't have any information about the derivatives with respect to the

View File

@@ -23,7 +23,6 @@ class TTSEBackend : public TabularBackend
is_mixture = (this->AS->get_mole_fractions().size() > 1);
}
}
void update(CoolProp::input_pairs input_pair, double val1, double val2);
double evaluate_single_phase(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j);
double evaluate_single_phase_transport(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j);
double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j){

View File

@@ -651,6 +651,28 @@ CoolPropDbl CoolProp::TabularBackend::calc_first_two_phase_deriv(parameters Of,
void CoolProp::TabularBackend::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();
// 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;
// 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;
PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation;
PhaseEnvelopeData & phase_envelope = dataset->phase_envelope;
SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph;
@@ -705,6 +727,69 @@ void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double v
}
break;
}
case PT_INPUTS:{
_p = val1; _T = val2;
if (!single_phase_logpT.native_inputs_are_in_range(_T, _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, p=%g Pa, T=%g K", _p, _T));
}
else{
using_single_phase_table = true; // Use the table !
std::size_t iL = 0, iV = 0, iclosest = 0;
CoolPropDbl TL = 0, TV = 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, iT, _T, iclosest, closest_state);
}
else{
is_two_phase = pure_saturation.is_inside(iP, _p, iT, _T, iL, iV, TL, TV);
}
}
if (is_two_phase)
{
using_single_phase_table = false;
throw ValueError(format("P,T with TTSE cannot be two-phase for now"));
}
else{
selected_table = SELECTED_PT_TABLE;
// Find and cache the indices i, j
find_native_nearest_good_indices(single_phase_logpT, dataset->coeffs_pT, _T, _p, cached_single_phase_i, cached_single_phase_j);
// If p < pc, you might be getting a liquid solution when you want a vapor solution or vice versa
// if you are very close to the saturation curve, so we figure out what the saturation temperature
// is for the given pressure
if (_p < this->AS->p_critical())
{
double Ts = pure_saturation.evaluate(iT, _p, _Q, iL, iV);
double TL = single_phase_logpT.T[cached_single_phase_i][cached_single_phase_j];
double TR = single_phase_logpT.T[cached_single_phase_i+1][cached_single_phase_j];
if (TL < Ts && Ts < TR){
if (_T < Ts){
if (cached_single_phase_i == 0){ throw ValueError(format("P, T are near saturation, but cannot move the cell to the left")); }
// It's liquid, move the cell to the left
cached_single_phase_i--;
}
else{
if (cached_single_phase_i > single_phase_logpT.Nx-2){ throw ValueError(format("P,T are near saturation, but cannot move the cell to the right")); }
// It's vapor, move to the right
cached_single_phase_i++;
}
}
}
// Recalculate the phase
recalculate_singlephase_phase();
}
}
break;
}
case PUmolar_INPUTS:
case PSmolar_INPUTS:
case DmolarP_INPUTS:{
@@ -875,7 +960,7 @@ void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double v
break;
}
default:
throw ValueError("Sorry, but this set of inputs is not supported for Bicubic backend");
throw ValueError("Sorry, but this set of inputs is not supported for Tabular backend");
}
}