mirror of
https://github.com/CoolProp/CoolProp.git
synced 2026-01-23 04:47:57 -05:00
* Added first working version of VTPR; * Get VTPR building hopefully * Remove more constant iterators * Make VTPR accessible through factory * One last const iterator * Fix a_alpha bug and make sqrt(2) into sqrt(2.0) * Added analytic first derivative for VTPR * Fix another set of sqrt(2) -> sqrt(2.0) * Add some info on the derivatives for VTPR Looks less hopeless than I had feared * gE/RT needs to be multiplied by RT; closes #1161 * Added first working version of VTPR; * Get VTPR building hopefully * Remove more constant iterators * Make VTPR accessible through factory * One last const iterator * Fix a_alpha bug and make sqrt(2) into sqrt(2.0) * Added analytic first derivative for VTPR * Fix another set of sqrt(2) -> sqrt(2.0) * Add some info on the derivatives for VTPR Looks less hopeless than I had feared * gE/RT needs to be multiplied by RT; closes #1161 * Add VTPR code from @JonWel (#1194) * 1rst draft to implement a simple volume translation to cubics * A bit more of VT * Derivatives for volume translation * Better cm initialisation * Solves the cubic equation with volume translation * Correct the volume translation analytic development Looks good now * Update VTPR to be able to use volume translation * Unprotect cm_term This allows it to be used from the VTPR backend * Update CoolPropLib.def * Better derrivative of PI_12 The expression is simpler this way * Solves #1176 Thanks @ibell * Change the way the volume translation parrameter is set * Start the bm derivatives for VTPR * Correct one derivative * Small bug * Better bm derivatives for VTPR * Add am and bm component derivatives for VTPR @ibell I did not check yet the component derivatives of this commit, bu I checked the other ones with your code. I'll have to addapt your code to also check these ones. I separate the `am_term` and `bm_term` as the `am_bm_term` function was called twice. This reduce the call to the am_term part as this part ends up being called only once, and this helped writing the component derivatives. The tau derivative is done numerically untill we find time to develop the analytical one. The `am_bm_term` function started with a `set_temperature()`. I did not checked yet why this is needed and put this set temperature at the beginning of each of the `am_term` component derivatives. I'll try to addapt the checking code tomorow. * tab to spaces * Re-writing of cubic coefficients Introducing 3 intermediary varriables that simplify the cubic's coefficient with the volume translation. * 1rst draft to implement a simple volume translation to cubics * A bit more of VT * Derivatives for volume translation * Better cm initialisation * Solves the cubic equation with volume translation * Correct the volume translation analytic development Looks good now * Update VTPR to be able to use volume translation * Unprotect cm_term This allows it to be used from the VTPR backend * Update CoolPropLib.def * Better derrivative of PI_12 The expression is simpler this way * Solves #1176 Thanks @ibell * Change the way the volume translation parrameter is set * Start the bm derivatives for VTPR * Correct one derivative * Small bug * Better bm derivatives for VTPR * Add am and bm component derivatives for VTPR @ibell I did not check yet the component derivatives of this commit, bu I checked the other ones with your code. I'll have to addapt your code to also check these ones. I separate the `am_term` and `bm_term` as the `am_bm_term` function was called twice. This reduce the call to the am_term part as this part ends up being called only once, and this helped writing the component derivatives. The tau derivative is done numerically untill we find time to develop the analytical one. The `am_bm_term` function started with a `set_temperature()`. I did not checked yet why this is needed and put this set temperature at the beginning of each of the `am_term` component derivatives. I'll try to addapt the checking code tomorow. * tab to spaces * Re-writing of cubic coefficients Introducing 3 intermediary varriables that simplify the cubic's coefficient with the volume translation.
676 lines
33 KiB
C++
676 lines
33 KiB
C++
|
|
|
|
#include "DataStructures.h"
|
|
#include "Exceptions.h"
|
|
#include "CoolPropTools.h"
|
|
#include "CoolProp.h"
|
|
|
|
namespace CoolProp{
|
|
|
|
struct parameter_info
|
|
{
|
|
int key;
|
|
const char *short_desc, *IO, *units, *description;
|
|
bool trivial; ///< True if the input is trivial, and can be directly calculated (constants like critical properties, etc.)
|
|
};
|
|
|
|
const parameter_info parameter_info_list[] = {
|
|
/// Input/Output parameters
|
|
{iT, "T", "IO", "K", "Temperature", false},
|
|
{iP, "P", "IO", "Pa", "Pressure", false},
|
|
{iDmolar, "Dmolar", "IO", "mol/m^3", "Molar density", false},
|
|
{iHmolar, "Hmolar", "IO", "J/mol", "Molar specific enthalpy", false},
|
|
{iSmolar, "Smolar", "IO", "J/mol/K", "Molar specific entropy", false},
|
|
{iUmolar, "Umolar", "IO", "J/mol", "Molar specific internal energy", false},
|
|
{iGmolar, "Gmolar", "O", "J/mol", "Molar specific Gibbs energy", false},
|
|
{iHelmholtzmolar, "Helmholtzmolar", "O", "J/mol", "Molar specific Helmholtz energy", false},
|
|
{iDmass, "Dmass", "IO", "kg/m^3", "Mass density", false},
|
|
{iHmass, "Hmass", "IO", "J/kg", "Mass specific enthalpy", false},
|
|
{iSmass, "Smass", "IO", "J/kg/K", "Mass specific entropy", false},
|
|
{iUmass, "Umass", "IO", "J/kg", "Mass specific internal energy", false},
|
|
{iGmass, "Gmass", "O", "J/kg", "Mass specific Gibbs energy", false},
|
|
{iHelmholtzmass, "Helmholtzmass", "O", "J/kg", "Mass specific Helmholtz energy", false},
|
|
{iQ, "Q", "IO", "mol/mol", "Mass vapor quality", false},
|
|
{iDelta, "Delta", "IO", "-", "Reduced density (rho/rhoc)", false},
|
|
{iTau, "Tau", "IO", "-", "Reciprocal reduced temperature (Tc/T)", false},
|
|
/// Output only
|
|
{iCpmolar, "Cpmolar", "O", "J/mol/K", "Molar specific constant pressure specific heat", false},
|
|
{iCpmass, "Cpmass", "O", "J/kg/K", "Mass specific constant pressure specific heat", false},
|
|
{iCvmolar, "Cvmolar", "O", "J/mol/K", "Molar specific constant volume specific heat", false},
|
|
{iCvmass, "Cvmass", "O", "J/kg/K", "Mass specific constant volume specific heat", false},
|
|
{iCp0molar, "Cp0molar", "O", "J/mol/K", "Ideal gas molar specific constant pressure specific heat",false},
|
|
{iCp0mass, "Cp0mass", "O", "J/kg/K", "Ideal gas mass specific constant pressure specific heat",false},
|
|
{iSmolar_residual, "Smolar_residual", "O", "J/mol/K", "Residual molar entropy (sr/R = tau*dar_dtau-ar)",false},
|
|
{iGWP20, "GWP20", "O", "-", "20-year global warming potential", true},
|
|
{iGWP100, "GWP100", "O", "-", "100-year global warming potential", true},
|
|
{iGWP500, "GWP500", "O", "-", "500-year global warming potential", true},
|
|
{iFH, "FH", "O", "-", "Flammability hazard", true},
|
|
{iHH, "HH", "O", "-", "Health hazard", true},
|
|
{iPH, "PH", "O", "-", "Physical hazard", true},
|
|
{iODP, "ODP", "O", "-", "Ozone depletion potential", true},
|
|
{iBvirial, "Bvirial", "O", "-", "Second virial coefficient", false},
|
|
{iCvirial, "Cvirial", "O", "-", "Third virial coefficient", false},
|
|
{idBvirial_dT, "dBvirial_dT", "O", "-", "Derivative of second virial coefficient with respect to T",false},
|
|
{idCvirial_dT, "dCvirial_dT", "O", "-", "Derivative of third virial coefficient with respect to T",false},
|
|
{igas_constant, "gas_constant", "O", "J/mol/K", "Molar gas constant", true},
|
|
{imolar_mass, "molar_mass", "O", "kg/mol", "Molar mass", true},
|
|
{iacentric_factor, "acentric", "O", "-", "Acentric factor", true},
|
|
{idipole_moment, "dipole_moment", "O", "C-m", "Dipole moment", true},
|
|
{irhomass_reducing, "rhomass_reducing", "O", "kg/m^3", "Mass density at reducing point", true},
|
|
{irhomolar_reducing, "rhomolar_reducing", "O", "mol/m^3", "Molar density at reducing point", true},
|
|
{irhomolar_critical, "rhomolar_critical", "O", "mol/m^3", "Molar density at critical point", true},
|
|
{irhomass_critical, "rhomass_critical", "O", "kg/m^3", "Mass density at critical point", true},
|
|
{iT_reducing, "T_reducing", "O", "K", "Temperature at the reducing point", true},
|
|
{iT_critical, "T_critical", "O", "K", "Temperature at the critical point", true},
|
|
{iT_triple, "T_triple", "O", "K", "Temperature at the triple point", true},
|
|
{iT_max, "T_max", "O", "K", "Maximum temperature limit", true},
|
|
{iT_min, "T_min", "O", "K", "Minimum temperature limit", true},
|
|
{iP_min, "P_min", "O", "Pa", "Minimum pressure limit", true},
|
|
{iP_max, "P_max", "O", "Pa", "Maximum pressure limit", true},
|
|
{iP_critical, "p_critical", "O", "Pa", "Pressure at the critical point", true},
|
|
{iP_reducing, "p_reducing", "O", "Pa", "Pressure at the reducing point", true},
|
|
{iP_triple, "p_triple", "O", "Pa", "Pressure at the triple point (pure only)", true},
|
|
{ifraction_min, "fraction_min", "O", "-", "Fraction (mole, mass, volume) minimum value for incompressible solutions",true},
|
|
{ifraction_max, "fraction_max", "O", "-", "Fraction (mole, mass, volume) maximum value for incompressible solutions",true},
|
|
{iT_freeze, "T_freeze", "O", "K", "Freezing temperature for incompressible solutions",true},
|
|
|
|
{ispeed_sound, "speed_of_sound", "O", "m/s", "Speed of sound", false},
|
|
{iviscosity, "viscosity", "O", "Pa-s", "Viscosity", false},
|
|
{iconductivity, "conductivity", "O", "W/m/K", "Thermal conductivity", false},
|
|
{isurface_tension, "surface_tension", "O", "N/m", "Surface tension", false},
|
|
{iPrandtl, "Prandtl", "O", "-", "Prandtl number", false},
|
|
|
|
{iisothermal_compressibility, "isothermal_compressibility", "O", "1/Pa", "Isothermal compressibility",false},
|
|
{iisobaric_expansion_coefficient, "isobaric_expansion_coefficient", "O", "1/K", "Isobaric expansion coefficient",false},
|
|
{iZ, "Z", "O", "-", "Compressibility factor",false},
|
|
{ifundamental_derivative_of_gas_dynamics, "fundamental_derivative_of_gas_dynamics", "O", "-", "Fundamental derivative of gas dynamics",false},
|
|
{iPIP, "PIP", "O", "-", "Phase identification parameter", false},
|
|
|
|
{ialphar, "alphar", "O", "-", "Residual Helmholtz energy", false},
|
|
{idalphar_dtau_constdelta, "dalphar_dtau_constdelta", "O", "-", "Derivative of residual Helmholtz energy with tau",false},
|
|
{idalphar_ddelta_consttau, "dalphar_ddelta_consttau", "O", "-", "Derivative of residual Helmholtz energy with delta",false},
|
|
|
|
{ialpha0, "alpha0", "O", "-", "Ideal Helmholtz energy", false},
|
|
{idalpha0_dtau_constdelta, "dalpha0_dtau_constdelta", "O", "-", "Derivative of ideal Helmholtz energy with tau",false},
|
|
{idalpha0_ddelta_consttau, "dalpha0_ddelta_consttau", "O", "-", "Derivative of ideal Helmholtz energy with delta",false},
|
|
|
|
{iPhase, "Phase", "O", "-", "Phase index as a float", false},
|
|
|
|
};
|
|
|
|
class ParameterInformation
|
|
{
|
|
public:
|
|
std::map<int, bool> trivial_map;
|
|
std::map<int, std::string> short_desc_map, description_map, IO_map, units_map;
|
|
std::map<std::string, int> index_map;
|
|
ParameterInformation()
|
|
{
|
|
const parameter_info* const end = parameter_info_list + sizeof(parameter_info_list) / sizeof(parameter_info_list[0]);
|
|
for (const parameter_info* el = parameter_info_list; el != end; ++el)
|
|
{
|
|
short_desc_map.insert(std::pair<int, std::string>(el->key, el->short_desc));
|
|
IO_map.insert(std::pair<int, std::string>(el->key, el->IO));
|
|
units_map.insert(std::pair<int, std::string>(el->key, el->units));
|
|
description_map.insert(std::pair<int, std::string>(el->key, el->description));
|
|
index_map_insert(el->short_desc, el->key);
|
|
trivial_map.insert(std::pair<int, bool>(el->key, el->trivial));
|
|
}
|
|
// Backward compatibility aliases
|
|
index_map_insert("D", iDmass);
|
|
index_map_insert("H", iHmass);
|
|
index_map_insert("M", imolar_mass);
|
|
index_map_insert("S", iSmass);
|
|
index_map_insert("U", iUmass);
|
|
index_map_insert("C", iCpmass);
|
|
index_map_insert("O", iCvmass);
|
|
index_map_insert("G", iGmass);
|
|
index_map_insert("V", iviscosity);
|
|
index_map_insert("L", iconductivity);
|
|
index_map_insert("pcrit", iP_critical);
|
|
index_map_insert("Pcrit", iP_critical);
|
|
index_map_insert("Tcrit", iT_critical);
|
|
index_map_insert("Ttriple", iT_triple);
|
|
index_map_insert("ptriple", iP_triple);
|
|
index_map_insert("rhocrit", irhomass_critical);
|
|
index_map_insert("Tmin", iT_min);
|
|
index_map_insert("Tmax", iT_max);
|
|
index_map_insert("pmax", iP_max);
|
|
index_map_insert("pmin", iP_min);
|
|
index_map_insert("molemass", imolar_mass);
|
|
index_map_insert("molarmass", imolar_mass);
|
|
index_map_insert("A", ispeed_sound);
|
|
index_map_insert("I", isurface_tension);
|
|
}
|
|
private:
|
|
void index_map_insert(const std::string &desc, int key) {
|
|
index_map.insert(std::pair<std::string, int>(desc, key));
|
|
index_map.insert(std::pair<std::string, int>(upper(desc), key));
|
|
}
|
|
};
|
|
|
|
static ParameterInformation parameter_information;
|
|
|
|
bool is_trivial_parameter(int key)
|
|
{
|
|
// Try to find it
|
|
std::map<int, bool>::const_iterator it = parameter_information.trivial_map.find(key);
|
|
// If equal to end, not found
|
|
if (it != parameter_information.trivial_map.end())
|
|
{
|
|
// Found it, return it
|
|
return it->second;
|
|
}
|
|
else
|
|
{
|
|
throw ValueError(format("Unable to match the key [%d: %s] in is_trivial_parameter",key, get_parameter_information(key, "short").c_str()));
|
|
}
|
|
}
|
|
|
|
std::string get_parameter_information(int key, const std::string &info)
|
|
{
|
|
std::map<int, std::string> *M;
|
|
|
|
// Hook up the right map (since they are all of the same type)
|
|
if (!info.compare("IO")){
|
|
M = &(parameter_information.IO_map);
|
|
}
|
|
else if (!info.compare("short")){
|
|
M = &(parameter_information.short_desc_map);
|
|
}
|
|
else if (!info.compare("long")){
|
|
M = &(parameter_information.description_map);
|
|
}
|
|
else if (!info.compare("units")){
|
|
M = &(parameter_information.units_map);
|
|
}
|
|
else
|
|
throw ValueError(format("Bad info string [%s] to get_parameter_information",info.c_str()));
|
|
|
|
// Try to find it
|
|
std::map<int, std::string>::const_iterator it = M->find(key);
|
|
// If equal to end, not found
|
|
if (it != M->end())
|
|
{
|
|
// Found it, return it
|
|
return it->second;
|
|
}
|
|
else
|
|
{
|
|
throw ValueError(format("Unable to match the key [%d] in get_parameter_information for info [%s]",key, info.c_str()));
|
|
}
|
|
}
|
|
|
|
/// Return a list of parameters
|
|
std::string get_csv_parameter_list()
|
|
{
|
|
std::vector<std::string> strings;
|
|
for(std::map<std::string,int>::const_iterator it = parameter_information.index_map.begin(); it != parameter_information.index_map.end(); ++it )
|
|
{
|
|
strings.push_back(it->first);
|
|
}
|
|
return strjoin(strings, ",");
|
|
}
|
|
bool is_valid_parameter(const std::string ¶m_name, parameters &iOutput)
|
|
{
|
|
// Try to find it
|
|
std::map<std::string, int>::const_iterator it = parameter_information.index_map.find(param_name);
|
|
// If equal to end, not found
|
|
if (it != parameter_information.index_map.end()){
|
|
// Found, return it
|
|
iOutput = static_cast<parameters>(it->second);
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool is_valid_first_derivative(const std::string &name, parameters &iOf, parameters &iWrt, parameters &iConstant)
|
|
{
|
|
if (get_debug_level() > 5){std::cout << format("is_valid_first_derivative(%s)",name.c_str());}
|
|
// There should be exactly one /
|
|
// There should be exactly one |
|
|
|
|
// Suppose we start with "d(P)/d(T)|Dmolar"
|
|
std::vector<std::string> split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "Dmolar"
|
|
if (split_at_bar.size() != 2){return false;}
|
|
|
|
std::vector<std::string> split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)"
|
|
if (split_at_slash.size() != 2){return false;}
|
|
|
|
std::size_t i0 = split_at_slash[0].find("(");
|
|
std::size_t i1 = split_at_slash[0].find(")", i0);
|
|
if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){return false;}
|
|
std::string num = split_at_slash[0].substr(i0+1, i1-i0-1);
|
|
|
|
i0 = split_at_slash[1].find("(");
|
|
i1 = split_at_slash[1].find(")", i0);
|
|
if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){return false;}
|
|
std::string den = split_at_slash[1].substr(i0+1, i1-i0-1);
|
|
|
|
parameters Of, Wrt, Constant;
|
|
if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && is_valid_parameter(split_at_bar[1], Constant)){
|
|
iOf = Of; iWrt = Wrt; iConstant = Constant; return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool is_valid_first_saturation_derivative(const std::string &name, parameters &iOf, parameters &iWrt)
|
|
{
|
|
if (get_debug_level() > 5){ std::cout << format("is_valid_first_saturation_derivative(%s)", name.c_str()); }
|
|
// There should be exactly one /
|
|
// There should be exactly one |
|
|
|
|
// Suppose we start with "d(P)/d(T)|sigma"
|
|
std::vector<std::string> split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "sigma"
|
|
if (split_at_bar.size() != 2){ return false; }
|
|
|
|
std::vector<std::string> split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)"
|
|
if (split_at_slash.size() != 2){ return false; }
|
|
|
|
std::size_t i0 = split_at_slash[0].find("(");
|
|
std::size_t i1 = split_at_slash[0].find(")", i0);
|
|
if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){ return false; }
|
|
std::string num = split_at_slash[0].substr(i0+1, i1-i0-1);
|
|
|
|
i0 = split_at_slash[1].find("(");
|
|
i1 = split_at_slash[1].find(")", i0);
|
|
if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){ return false; }
|
|
std::string den = split_at_slash[1].substr(i0+1, i1-i0-1);
|
|
|
|
parameters Of, Wrt;
|
|
if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && upper(split_at_bar[1]) == "SIGMA"){
|
|
iOf = Of; iWrt = Wrt; return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool is_valid_second_derivative(const std::string &name, parameters &iOf1, parameters &iWrt1, parameters &iConstant1, parameters &iWrt2, parameters &iConstant2)
|
|
{
|
|
if (get_debug_level() > 5){std::cout << format("is_valid_second_derivative(%s)",name.c_str());}
|
|
|
|
// Suppose we start with "d(d(P)/d(Dmolar)|T)/d(Dmolar)|T"
|
|
std::size_t i = name.rfind('|');
|
|
if ((i == 0) || (i == std::string::npos)){return false;}
|
|
std::string constant2 = name.substr(i+1); // "T"
|
|
if (!is_valid_parameter(constant2, iConstant2)){return false;};
|
|
std::string left_of_bar = name.substr(0, i); // "d(d(P)/d(Dmolar)|T)/d(Dmolar)"
|
|
|
|
i = left_of_bar.rfind('/');
|
|
if ((i == 0) || (i == std::string::npos)){return false;}
|
|
std::string left_of_slash = left_of_bar.substr(0, i); // "d(d(P)/d(Dmolar)|T)"
|
|
std::string right_of_slash = left_of_bar.substr(i + 1); // "d(Dmolar)"
|
|
|
|
i = left_of_slash.find("(");
|
|
std::size_t i1 = left_of_slash.rfind(")");
|
|
if (!((i > 0) && (i != std::string::npos) && (i1 > (i+1)) && (i1 != std::string::npos))){return false;}
|
|
std::string num = left_of_slash.substr(i+1, i1-i-1); // "d(P)/d(Dmolar)|T"
|
|
if (!is_valid_first_derivative(num, iOf1, iWrt1, iConstant1)){return false;}
|
|
|
|
i = right_of_slash.find("(");
|
|
i1 = right_of_slash.rfind(")");
|
|
if (!((i > 0) && (i != std::string::npos) && (i1 > (i+1)) && (i1 != std::string::npos))){return false;}
|
|
std::string den = right_of_slash.substr(i+1, i1-i-1); // "Dmolar"
|
|
if (!is_valid_parameter(den, iWrt2)){return false;}
|
|
|
|
// If we haven't quit yet, all is well
|
|
return true;
|
|
}
|
|
|
|
struct phase_info
|
|
{
|
|
phases key;
|
|
const char *short_desc, *long_desc;
|
|
};
|
|
|
|
const phase_info phase_info_list[] = {
|
|
{ iphase_liquid, "phase_liquid", "" },
|
|
{ iphase_gas, "phase_gas", "" },
|
|
{ iphase_twophase, "phase_twophase", "" },
|
|
{ iphase_supercritical, "phase_supercritical", "" },
|
|
{ iphase_supercritical_gas, "phase_supercritical_gas", "p < pc, T > Tc" },
|
|
{ iphase_supercritical_liquid, "phase_supercritical_liquid", "p > pc, T < Tc" },
|
|
{ iphase_critical_point, "phase_critical_point", "p = pc, T = Tc" },
|
|
{ iphase_unknown, "phase_unknown", "" },
|
|
{ iphase_not_imposed, "phase_not_imposed", "" },
|
|
};
|
|
|
|
class PhaseInformation
|
|
{
|
|
public:
|
|
std::map<phases, std::string> short_desc_map, long_desc_map;
|
|
std::map<std::string, phases> index_map;
|
|
PhaseInformation()
|
|
{
|
|
const phase_info* const end = phase_info_list + sizeof(phase_info_list) / sizeof(phase_info_list[0]);
|
|
for (const phase_info* el = phase_info_list; el != end; ++el)
|
|
{
|
|
short_desc_map.insert(std::pair<phases, std::string>(el->key, el->short_desc));
|
|
long_desc_map.insert(std::pair<phases, std::string>(el->key, el->long_desc));
|
|
index_map.insert(std::pair<std::string, phases>(el->short_desc, el->key));
|
|
}
|
|
}
|
|
};
|
|
static PhaseInformation phase_information;
|
|
|
|
const std::string& get_phase_short_desc(phases phase)
|
|
{
|
|
return phase_information.short_desc_map[phase];
|
|
}
|
|
bool is_valid_phase(const std::string &phase_name, phases &iOutput)
|
|
{
|
|
// Try to find it
|
|
std::map<std::string, phases>::const_iterator it = phase_information.index_map.find(phase_name);
|
|
// If equal to end, not found
|
|
if (it != phase_information.index_map.end()){
|
|
// Found, return it
|
|
iOutput = static_cast<phases>(it->second);
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
phases get_phase_index(const std::string ¶m_name)
|
|
{
|
|
phases iPhase;
|
|
if (is_valid_phase(param_name, iPhase)){
|
|
return iPhase;
|
|
}
|
|
else{
|
|
throw ValueError(format("Your input name [%s] is not valid in get_phase_index (names are case sensitive)",param_name.c_str()));
|
|
}
|
|
}
|
|
parameters get_parameter_index(const std::string ¶m_name)
|
|
{
|
|
parameters iOutput;
|
|
if (is_valid_parameter(param_name, iOutput)){
|
|
return iOutput;
|
|
}
|
|
else{
|
|
throw ValueError(format("Your input name [%s] is not valid in get_parameter_index (names are case sensitive)",param_name.c_str()));
|
|
}
|
|
}
|
|
|
|
struct input_pair_info
|
|
{
|
|
input_pairs key;
|
|
const char *short_desc, *long_desc;
|
|
};
|
|
|
|
const input_pair_info input_pair_list[] = {
|
|
{ QT_INPUTS, "QT_INPUTS", "Molar quality, Temperature in K" },
|
|
{ QSmolar_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/mol/K" },
|
|
{ QSmass_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/kg/K" },
|
|
{ HmolarQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/mol, Molar quality" },
|
|
{ HmassQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/kg, Molar quality" },
|
|
{ DmassQ_INPUTS, "DmassQ_INPUTS", "Molar density kg/m^3, Molar quality" },
|
|
{ DmolarQ_INPUTS, "DmolarQ_INPUTS", "Molar density in mol/m^3, Molar quality" },
|
|
|
|
{ PQ_INPUTS, "PQ_INPUTS", "Pressure in Pa, Molar quality" },
|
|
|
|
{ PT_INPUTS, "PT_INPUTS", "Pressure in Pa, Temperature in K" },
|
|
|
|
|
|
{ DmassT_INPUTS, "DmassT_INPUTS", "Mass density in kg/m^3, Temperature in K" },
|
|
{ DmolarT_INPUTS, "DmolarT_INPUTS", "Molar density in mol/m^3, Temperature in K" },
|
|
{ HmassT_INPUTS, "HmassT_INPUTS", "Enthalpy in J/kg, Temperature in K" },
|
|
{ HmolarT_INPUTS, "HmolarT_INPUTS", "Enthalpy in J/mol, Temperature in K" },
|
|
{ SmassT_INPUTS, "SmassT_INPUTS", "Entropy in J/kg/K, Temperature in K" },
|
|
{ SmolarT_INPUTS, "SmolarT_INPUTS", "Entropy in J/mol/K, Temperature in K" },
|
|
{ TUmass_INPUTS, "TUmass_INPUTS", "Temperature in K, Internal energy in J/kg" },
|
|
{ TUmolar_INPUTS, "TUmolar_INPUTS", "Temperature in K, Internal energy in J/mol" },
|
|
|
|
{ DmassP_INPUTS, "DmassP_INPUTS", "Mass density in kg/m^3, Pressure in Pa" },
|
|
{ DmolarP_INPUTS, "DmolarP_INPUTS", "Molar density in mol/m^3, Pressure in Pa" },
|
|
{ HmassP_INPUTS, "HmassP_INPUTS", "Enthalpy in J/kg, Pressure in Pa" },
|
|
{ HmolarP_INPUTS, "HmolarP_INPUTS", "Enthalpy in J/mol, Pressure in Pa" },
|
|
{ PSmass_INPUTS, "PSmass_INPUTS", "Pressure in Pa, Entropy in J/kg/K" },
|
|
{ PSmolar_INPUTS, "PSmolar_INPUTS", "Pressure in Pa, Entropy in J/mol/K " },
|
|
{ PUmass_INPUTS, "PUmass_INPUTS", "Pressure in Pa, Internal energy in J/kg" },
|
|
{ PUmolar_INPUTS, "PUmolar_INPUTS", "Pressure in Pa, Internal energy in J/mol" },
|
|
|
|
{ DmassHmass_INPUTS, "DmassHmass_INPUTS", "Mass density in kg/m^3, Enthalpy in J/kg" },
|
|
{ DmolarHmolar_INPUTS, "DmolarHmolar_INPUTS", "Molar density in mol/m^3, Enthalpy in J/mol" },
|
|
{ DmassSmass_INPUTS, "DmassSmass_INPUTS", "Mass density in kg/m^3, Entropy in J/kg/K" },
|
|
{ DmolarSmolar_INPUTS, "DmolarSmolar_INPUTS", "Molar density in mol/m^3, Entropy in J/mol/K" },
|
|
{ DmassUmass_INPUTS, "DmassUmass_INPUTS", "Mass density in kg/m^3, Internal energy in J/kg" },
|
|
{ DmolarUmolar_INPUTS, "DmolarUmolar_INPUTS", "Molar density in mol/m^3, Internal energy in J/mol" },
|
|
|
|
{ HmassSmass_INPUTS, "HmassSmass_INPUTS", "Enthalpy in J/kg, Entropy in J/kg/K" },
|
|
{ HmolarSmolar_INPUTS, "HmolarSmolar_INPUTS", "Enthalpy in J/mol, Entropy in J/mol/K" },
|
|
{ SmassUmass_INPUTS, "SmassUmass_INPUTS", "Entropy in J/kg/K, Internal energy in J/kg" },
|
|
{ SmolarUmolar_INPUTS, "SmolarUmolar_INPUTS", "Entropy in J/mol/K, Internal energy in J/mol" },
|
|
};
|
|
|
|
class InputPairInformation
|
|
{
|
|
public:
|
|
std::map<input_pairs, std::string> short_desc_map, long_desc_map;
|
|
std::map<std::string, input_pairs> index_map;
|
|
InputPairInformation()
|
|
{
|
|
const input_pair_info* const end = input_pair_list + sizeof(input_pair_list) / sizeof(input_pair_list[0]);
|
|
for (const input_pair_info* el = input_pair_list; el != end; ++el)
|
|
{
|
|
short_desc_map.insert(std::pair<input_pairs, std::string>(el->key, el->short_desc));
|
|
long_desc_map.insert(std::pair<input_pairs, std::string>(el->key, el->long_desc));
|
|
index_map.insert(std::pair<std::string,input_pairs >(el->short_desc, el->key));
|
|
}
|
|
}
|
|
};
|
|
|
|
static InputPairInformation input_pair_information;
|
|
|
|
input_pairs get_input_pair_index(const std::string &input_pair_name)
|
|
{
|
|
std::map<std::string, input_pairs>::iterator it = input_pair_information.index_map.find(input_pair_name);
|
|
if (it != input_pair_information.index_map.end()){
|
|
return it->second;
|
|
}
|
|
else{
|
|
throw ValueError(format("Your input name [%s] is not valid in get_input_pair_index (names are case sensitive)",input_pair_name.c_str()));
|
|
}
|
|
}
|
|
|
|
const std::string& get_input_pair_short_desc(input_pairs pair)
|
|
{
|
|
return input_pair_information.short_desc_map[pair];
|
|
}
|
|
const std::string& get_input_pair_long_desc(input_pairs pair)
|
|
{
|
|
return input_pair_information.long_desc_map[pair];
|
|
}
|
|
void split_input_pair(input_pairs pair, parameters &p1, parameters &p2)
|
|
{
|
|
switch(pair){
|
|
case QT_INPUTS: p1 = iQ; p2 = iT; break;
|
|
case QSmolar_INPUTS: p1 = iQ; p2 = iSmolar; break;
|
|
case QSmass_INPUTS: p1 = iQ; p2 = iSmass; break;
|
|
case HmolarQ_INPUTS: p1 = iHmolar; p2 = iQ; break;
|
|
case HmassQ_INPUTS: p1 = iHmass; p2 = iQ; break;
|
|
case PQ_INPUTS: p1 = iP; p2 = iQ; break;
|
|
case PT_INPUTS: p1 = iP; p2 = iT; break;
|
|
case DmassT_INPUTS: p1 = iDmass; p2 = iT; break;
|
|
case DmolarT_INPUTS: p1 = iDmolar; p2 = iT; break;
|
|
case HmassT_INPUTS: p1 = iHmass; p2 = iT; break;
|
|
case HmolarT_INPUTS: p1 = iHmolar; p2 = iT; break;
|
|
case SmassT_INPUTS: p1 = iSmass; p2 = iT; break;
|
|
case SmolarT_INPUTS: p1 = iSmolar; p2 = iT; break;
|
|
case TUmass_INPUTS: p1 = iT; p2 = iUmass; break;
|
|
case TUmolar_INPUTS: p1 = iT; p2 = iUmolar; break;
|
|
case DmassP_INPUTS: p1 = iDmass; p2 = iP; break;
|
|
case DmolarP_INPUTS: p1 = iDmolar; p2 = iP; break;
|
|
case DmassQ_INPUTS: p1 = iDmass; p2 = iQ; break;
|
|
case DmolarQ_INPUTS: p1 = iDmolar; p2 = iQ; break;
|
|
case HmassP_INPUTS: p1 = iHmass; p2 = iP; break;
|
|
case HmolarP_INPUTS: p1 = iHmolar; p2 = iP; break;
|
|
case PSmass_INPUTS: p1 = iP; p2 = iSmass; break;
|
|
case PSmolar_INPUTS: p1 = iP; p2 = iSmolar; break;
|
|
case PUmass_INPUTS: p1 = iP; p2 = iUmass; break;
|
|
case PUmolar_INPUTS: p1 = iP; p2 = iUmolar; break;
|
|
case DmassHmass_INPUTS: p1 = iDmass; p2 = iHmass; break;
|
|
case DmolarHmolar_INPUTS: p1 = iDmolar; p2 = iHmolar; break;
|
|
case DmassSmass_INPUTS: p1 = iDmass; p2 = iSmass; break;
|
|
case DmolarSmolar_INPUTS: p1 = iDmolar; p2 = iSmolar; break;
|
|
case DmassUmass_INPUTS: p1 = iDmass; p2 = iUmass; break;
|
|
case DmolarUmolar_INPUTS: p1 = iDmolar; p2 = iUmolar; break;
|
|
case HmassSmass_INPUTS: p1 = iHmass; p2 = iSmass;break;
|
|
case HmolarSmolar_INPUTS: p1 = iHmolar; p2 = iSmolar; break;
|
|
case SmassUmass_INPUTS: p1 = iSmass; p2 = iUmass; break;
|
|
case SmolarUmolar_INPUTS: p1 = iSmolar; p2 = iUmolar; break;
|
|
default: throw ValueError(format("Invalid input pair"));
|
|
}
|
|
}
|
|
|
|
struct backend_family_info {
|
|
backend_families family;
|
|
const char * name;
|
|
};
|
|
|
|
struct backend_info {
|
|
backends backend;
|
|
const char * name;
|
|
backend_families family;
|
|
|
|
};
|
|
|
|
const backend_family_info backend_family_list[] = {
|
|
{ HEOS_BACKEND_FAMILY, "HEOS"},
|
|
{ REFPROP_BACKEND_FAMILY, "REFPROP" },
|
|
{ INCOMP_BACKEND_FAMILY, "INCOMP" },
|
|
{ IF97_BACKEND_FAMILY, "IF97" },
|
|
{ TREND_BACKEND_FAMILY, "TREND" },
|
|
{ TTSE_BACKEND_FAMILY, "TTSE" },
|
|
{ BICUBIC_BACKEND_FAMILY, "BICUBIC" },
|
|
{ SRK_BACKEND_FAMILY, "SRK" },
|
|
{ PR_BACKEND_FAMILY, "PR" },
|
|
{ VTPR_BACKEND_FAMILY, "VTPR" }
|
|
};
|
|
|
|
const backend_info backend_list[] = {
|
|
{ HEOS_BACKEND_PURE, "HelmholtzEOSBackend", HEOS_BACKEND_FAMILY },
|
|
{ HEOS_BACKEND_MIX, "HelmholtzEOSMixtureBackend", HEOS_BACKEND_FAMILY },
|
|
{ REFPROP_BACKEND_PURE, "REFPROPBackend", REFPROP_BACKEND_FAMILY },
|
|
{ REFPROP_BACKEND_MIX, "REFPROPMixtureBackend", REFPROP_BACKEND_FAMILY },
|
|
{ INCOMP_BACKEND, "IncompressibleBackend", INCOMP_BACKEND_FAMILY },
|
|
{ IF97_BACKEND, "IF97Backend", IF97_BACKEND_FAMILY },
|
|
{ TREND_BACKEND, "TRENDBackend", TREND_BACKEND_FAMILY },
|
|
{ TTSE_BACKEND, "TTSEBackend", TTSE_BACKEND_FAMILY },
|
|
{ BICUBIC_BACKEND, "BicubicBackend", BICUBIC_BACKEND_FAMILY },
|
|
{ SRK_BACKEND, "SRKBackend", SRK_BACKEND_FAMILY },
|
|
{ PR_BACKEND, "PengRobinsonBackend", PR_BACKEND_FAMILY },
|
|
{ VTPR_BACKEND, "VTPRBackend", VTPR_BACKEND_FAMILY }
|
|
};
|
|
|
|
class BackendInformation {
|
|
public:
|
|
std::map<backend_families, std::string> family_name_map; /// < from family to family name
|
|
std::map<backends, backend_families> backend_family_map; /// < from backend to family
|
|
std::map<backends, std::string> backend_name_map; /// < from backend to backend name
|
|
|
|
std::map<std::string, backend_families> family_name_map_r; /// < from backend name **or** family name to family
|
|
std::map<std::string, backends> backend_name_map_r; /// < from backend name to backend
|
|
|
|
BackendInformation() {
|
|
const backend_family_info* const family_end = backend_family_list + sizeof(backend_family_list) / sizeof(backend_family_list[0]);
|
|
for (const backend_family_info* el = backend_family_list; el != family_end; ++el) {
|
|
family_name_map.insert(std::pair<backend_families, std::string>(el->family, el->name));
|
|
family_name_map_r.insert(std::pair<std::string, backend_families>(el->name, el->family));
|
|
}
|
|
const backend_info* const backend_end = backend_list + sizeof(backend_list) / sizeof(backend_list[0]);
|
|
for (const backend_info* el = backend_list; el != backend_end; ++el) {
|
|
backend_family_map.insert(std::pair<backends, backend_families>(el->backend, el->family));
|
|
backend_name_map.insert(std::pair<backends, std::string>(el->backend, el->name));
|
|
backend_name_map_r.insert(std::pair<std::string, backends>(el->name, el->backend));
|
|
family_name_map_r.insert(std::pair<std::string, backend_families>(el->name, el->family));
|
|
}
|
|
}
|
|
};
|
|
|
|
static BackendInformation backend_information;
|
|
|
|
/// Convert a string into the enum values
|
|
void extract_backend_families(std::string backend_string, backend_families &f1, backend_families &f2) {
|
|
f1 = INVALID_BACKEND_FAMILY;
|
|
f2 = INVALID_BACKEND_FAMILY;
|
|
std::size_t i = backend_string.find("&");
|
|
std::map<std::string, backend_families>::const_iterator it;
|
|
if (i != std::string::npos) {
|
|
it = backend_information.family_name_map_r.find(backend_string.substr(0, i));// Before "&"
|
|
if (it != backend_information.family_name_map_r.end()) f1 = it->second;
|
|
it = backend_information.family_name_map_r.find(backend_string.substr(i + 1)); // After "&"
|
|
if (it != backend_information.family_name_map_r.end()) f2 = it->second;
|
|
} else {
|
|
it = backend_information.family_name_map_r.find(backend_string);
|
|
if (it != backend_information.family_name_map_r.end()) f1 = it->second;
|
|
}
|
|
}
|
|
|
|
void extract_backend_families_string(std::string backend_string, backend_families &f1, std::string &f2) {
|
|
backend_families f2_enum;
|
|
extract_backend_families(backend_string, f1, f2_enum);
|
|
std::map<backend_families, std::string>::const_iterator it;
|
|
it = backend_information.family_name_map.find(f2_enum);
|
|
if (it != backend_information.family_name_map.end()) f2 = it->second;
|
|
else f2.clear();
|
|
}
|
|
|
|
std::string get_backend_string(backends backend) {
|
|
std::map<backends, std::string>::const_iterator it;
|
|
it = backend_information.backend_name_map.find(backend);
|
|
if (it != backend_information.backend_name_map.end()) return it->second;
|
|
else return std::string("");
|
|
}
|
|
|
|
} /* namespace CoolProp */
|
|
|
|
|
|
|
|
#ifdef ENABLE_CATCH
|
|
#include "catch.hpp"
|
|
|
|
TEST_CASE("Check that all parameters are descibed","")
|
|
{
|
|
for (int i = 1; i < CoolProp::iundefined_parameter; ++i){
|
|
std::ostringstream ss;
|
|
ss << "Parameter index," << i << "last index:" << CoolProp::iundefined_parameter;
|
|
SECTION(ss.str(), "")
|
|
{
|
|
std::string prior;
|
|
if (i > 1){
|
|
CHECK_NOTHROW(prior = CoolProp::get_parameter_information(i-1,"short"));
|
|
CAPTURE(prior);
|
|
}
|
|
CHECK_NOTHROW(CoolProp::get_parameter_information(i,"short"));
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check that all phases are descibed","[phase_index]")
|
|
{
|
|
for (int i = 0; i < CoolProp::iphase_not_imposed; ++i){
|
|
std::ostringstream ss;
|
|
ss << "Parameter index," << i << "last index:" << CoolProp::iundefined_parameter;
|
|
SECTION(ss.str(), "")
|
|
{
|
|
std::string stringrepr;
|
|
int key;
|
|
CHECK_NOTHROW(stringrepr = CoolProp::get_phase_short_desc(static_cast<CoolProp::phases>(i)));
|
|
CAPTURE(stringrepr);
|
|
CHECK_NOTHROW(key = CoolProp::get_phase_index(stringrepr));
|
|
CAPTURE(key);
|
|
CHECK(key == i);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|