mirror of
https://github.com/CoolProp/CoolProp.git
synced 2026-01-09 14:08:08 -05:00
Run clang-format with claude code and fix VS warnings (#2629)
* Run clang-format with claude code and fix VS warnings * More clang-format * And the tests too * Cleanup from clang-tidy * More constness and modernization * Cleanup and modernization
This commit is contained in:
@@ -60,6 +60,9 @@ Checks: |
|
||||
-readability-function-cognitive-complexity,
|
||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||
-modernize-use-override,
|
||||
-readability-identifier-length,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-readability-math-missing-parentheses,
|
||||
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '*'
|
||||
|
||||
@@ -94,7 +94,7 @@ class AbstractState
|
||||
bool isTwoPhase(void) {
|
||||
return (this->_phase == iphase_twophase);
|
||||
}
|
||||
|
||||
|
||||
CacheArray<70> cache;
|
||||
using CAE = CacheArrayElement<double>;
|
||||
|
||||
@@ -115,13 +115,16 @@ class AbstractState
|
||||
/// Transport properties
|
||||
CAE _viscosity = cache.next(), _conductivity = cache.next(), _surface_tension = cache.next();
|
||||
|
||||
CAE _hmolar = cache.next(), _smolar = cache.next(), _umolar = cache.next(), _logp = cache.next(), _logrhomolar = cache.next(), _cpmolar = cache.next(), _cp0molar = cache.next(), _cvmolar = cache.next(), _speed_sound = cache.next(), _gibbsmolar = cache.next(), _helmholtzmolar = cache.next();
|
||||
CAE _hmolar = cache.next(), _smolar = cache.next(), _umolar = cache.next(), _logp = cache.next(), _logrhomolar = cache.next(),
|
||||
_cpmolar = cache.next(), _cp0molar = cache.next(), _cvmolar = cache.next(), _speed_sound = cache.next(), _gibbsmolar = cache.next(),
|
||||
_helmholtzmolar = cache.next();
|
||||
|
||||
/// Residual properties
|
||||
CAE _hmolar_residual = cache.next(), _smolar_residual = cache.next(), _gibbsmolar_residual = cache.next();
|
||||
|
||||
/// Excess properties
|
||||
CAE _hmolar_excess = cache.next(), _smolar_excess = cache.next(), _gibbsmolar_excess = cache.next(), _umolar_excess = cache.next(), _volumemolar_excess = cache.next(), _helmholtzmolar_excess = cache.next();
|
||||
CAE _hmolar_excess = cache.next(), _smolar_excess = cache.next(), _gibbsmolar_excess = cache.next(), _umolar_excess = cache.next(),
|
||||
_volumemolar_excess = cache.next(), _helmholtzmolar_excess = cache.next();
|
||||
|
||||
/// Ancillary values
|
||||
CAE _rhoLanc = cache.next(), _rhoVanc = cache.next(), _pLanc = cache.next(), _pVanc = cache.next(), _TLanc = cache.next(), _TVanc = cache.next();
|
||||
@@ -132,12 +135,16 @@ class AbstractState
|
||||
CAE _rho_spline = cache.next(), _drho_spline_dh__constp = cache.next(), _drho_spline_dp__consth = cache.next();
|
||||
|
||||
/// Cached low-level elements for in-place calculation of other properties
|
||||
CAE _alpha0 = cache.next(), _dalpha0_dTau = cache.next(), _dalpha0_dDelta = cache.next(), _d2alpha0_dTau2 = cache.next(), _d2alpha0_dDelta_dTau = cache.next(), _d2alpha0_dDelta2 = cache.next(), _d3alpha0_dTau3 = cache.next(),
|
||||
_d3alpha0_dDelta_dTau2 = cache.next(), _d3alpha0_dDelta2_dTau = cache.next(), _d3alpha0_dDelta3 = cache.next(), _alphar = cache.next(), _dalphar_dTau = cache.next(), _dalphar_dDelta = cache.next(), _d2alphar_dTau2 = cache.next(),
|
||||
_d2alphar_dDelta_dTau = cache.next(), _d2alphar_dDelta2 = cache.next(), _d3alphar_dTau3 = cache.next(), _d3alphar_dDelta_dTau2 = cache.next(), _d3alphar_dDelta2_dTau = cache.next(), _d3alphar_dDelta3 = cache.next(), _d4alphar_dTau4 = cache.next(),
|
||||
_d4alphar_dDelta_dTau3 = cache.next(), _d4alphar_dDelta2_dTau2 = cache.next(), _d4alphar_dDelta3_dTau = cache.next(), _d4alphar_dDelta4 = cache.next();
|
||||
CAE _alpha0 = cache.next(), _dalpha0_dTau = cache.next(), _dalpha0_dDelta = cache.next(), _d2alpha0_dTau2 = cache.next(),
|
||||
_d2alpha0_dDelta_dTau = cache.next(), _d2alpha0_dDelta2 = cache.next(), _d3alpha0_dTau3 = cache.next(), _d3alpha0_dDelta_dTau2 = cache.next(),
|
||||
_d3alpha0_dDelta2_dTau = cache.next(), _d3alpha0_dDelta3 = cache.next(), _alphar = cache.next(), _dalphar_dTau = cache.next(),
|
||||
_dalphar_dDelta = cache.next(), _d2alphar_dTau2 = cache.next(), _d2alphar_dDelta_dTau = cache.next(), _d2alphar_dDelta2 = cache.next(),
|
||||
_d3alphar_dTau3 = cache.next(), _d3alphar_dDelta_dTau2 = cache.next(), _d3alphar_dDelta2_dTau = cache.next(),
|
||||
_d3alphar_dDelta3 = cache.next(), _d4alphar_dTau4 = cache.next(), _d4alphar_dDelta_dTau3 = cache.next(),
|
||||
_d4alphar_dDelta2_dTau2 = cache.next(), _d4alphar_dDelta3_dTau = cache.next(), _d4alphar_dDelta4 = cache.next();
|
||||
|
||||
CAE _dalphar_dDelta_lim = cache.next(), _d2alphar_dDelta2_lim = cache.next(), _d2alphar_dDelta_dTau_lim = cache.next(), _d3alphar_dDelta2_dTau_lim = cache.next();
|
||||
CAE _dalphar_dDelta_lim = cache.next(), _d2alphar_dDelta2_lim = cache.next(), _d2alphar_dDelta_dTau_lim = cache.next(),
|
||||
_d3alphar_dDelta2_dTau_lim = cache.next();
|
||||
|
||||
/// Two-Phase variables
|
||||
CAE _rhoLmolar = cache.next(), _rhoVmolar = cache.next();
|
||||
@@ -697,7 +704,7 @@ class AbstractState
|
||||
AbstractState() : _fluid_type(FLUID_TYPE_UNDEFINED), _phase(iphase_unknown) {
|
||||
clear();
|
||||
}
|
||||
virtual ~AbstractState(){};
|
||||
virtual ~AbstractState() {};
|
||||
|
||||
/// A factory function to return a pointer to a new-allocated instance of one of the backends.
|
||||
/**
|
||||
@@ -838,9 +845,9 @@ class AbstractState
|
||||
|
||||
/// Update the state using two state variables
|
||||
virtual void update(CoolProp::input_pairs input_pair, double Value1, double Value2) = 0;
|
||||
|
||||
|
||||
/// Update the state for QT inputs for pure fluids when using the superancillary functions
|
||||
virtual void update_QT_pure_superanc(double Q, double T){
|
||||
virtual void update_QT_pure_superanc(double Q, double T) {
|
||||
throw NotImplementedError("update_QT_pure_superanc is not implemented for this backend");
|
||||
};
|
||||
|
||||
@@ -1615,7 +1622,7 @@ class AbstractStateGenerator
|
||||
{
|
||||
public:
|
||||
virtual AbstractState* get_AbstractState(const std::vector<std::string>& fluid_names) = 0;
|
||||
virtual ~AbstractStateGenerator(){};
|
||||
virtual ~AbstractStateGenerator() {};
|
||||
};
|
||||
|
||||
/** Register a backend in the backend library (statically defined in AbstractState.cpp and not
|
||||
|
||||
@@ -240,7 +240,7 @@ class MeltingLineVariables
|
||||
polynomial_in_Theta; /// The data needed for a melting curve formed of segments that are polynomials in \f$ \theta \f$
|
||||
int type;
|
||||
|
||||
MeltingLineVariables() : Tmin(_HUGE), Tmax(_HUGE), pmin(_HUGE), pmax(_HUGE), T_m(_HUGE), type(MELTING_LINE_NOT_SET){};
|
||||
MeltingLineVariables() : Tmin(_HUGE), Tmax(_HUGE), pmin(_HUGE), pmax(_HUGE), T_m(_HUGE), type(MELTING_LINE_NOT_SET) {};
|
||||
|
||||
/**
|
||||
* \brief Evaluate the melting line
|
||||
|
||||
@@ -709,5 +709,4 @@ double asinh(double value) {
|
||||
# undef EOS
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,36 +32,35 @@ namespace CoolProp {
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
class CachedElement
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
bool is_cached = false;
|
||||
double value;
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
/// Default constructor
|
||||
CachedElement() {
|
||||
this->clear();
|
||||
};
|
||||
|
||||
|
||||
/// Function to carry out the caching
|
||||
void _do_cache(double value) {
|
||||
this->value = value;
|
||||
this->is_cached = true;
|
||||
}
|
||||
|
||||
|
||||
/// Assignment operator - sets the value and sets the flag
|
||||
void operator=(const double& value) {
|
||||
_do_cache(value);
|
||||
};
|
||||
|
||||
|
||||
/// Cast to boolean, for checking if cached
|
||||
operator bool() {
|
||||
return is_cached;
|
||||
};
|
||||
|
||||
|
||||
/// Cast to double, for returning value
|
||||
operator double() {
|
||||
if (is_cached) {
|
||||
@@ -89,35 +88,34 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NumType>
|
||||
template <typename NumType>
|
||||
class CacheArrayElement
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
NumType& value;
|
||||
bool& is_cached;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
public:
|
||||
// Constructor with value
|
||||
CacheArrayElement(NumType& val, bool& is_cached) : value(val), is_cached(is_cached) {};
|
||||
|
||||
|
||||
/// Function to carry out the caching
|
||||
void _do_cache(double value) {
|
||||
this->value = value;
|
||||
this->is_cached = true;
|
||||
}
|
||||
|
||||
|
||||
/// Assignment operator - sets the value and sets the flag
|
||||
void operator=(const double& value) {
|
||||
_do_cache(value);
|
||||
};
|
||||
|
||||
|
||||
/// Cast to boolean, for checking if cached
|
||||
operator bool() {
|
||||
return is_cached;
|
||||
};
|
||||
|
||||
|
||||
/// Cast to double, for returning value
|
||||
operator double() {
|
||||
if (is_cached) {
|
||||
@@ -145,26 +143,25 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
class CacheArray
|
||||
{
|
||||
|
||||
template<int N>
|
||||
class CacheArray{
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
std::size_t inext = 0;
|
||||
std::array<double, N> m_values = create_filled_array<double, N>(_HUGE);
|
||||
std::array<bool, N> m_cached = create_filled_array<bool, N>(false);
|
||||
|
||||
public:
|
||||
void clear(){
|
||||
void clear() {
|
||||
memset(m_values.data(), 0, sizeof(m_values));
|
||||
memset(m_cached.data(), false, sizeof(m_cached));
|
||||
}
|
||||
auto factory(std::size_t i){
|
||||
auto factory(std::size_t i) {
|
||||
return CacheArrayElement<double>(m_values[i], m_cached[i]);
|
||||
}
|
||||
auto next(){
|
||||
if (inext > N){
|
||||
auto next() {
|
||||
if (inext > N) {
|
||||
throw ValueError("No more cache elements available");
|
||||
}
|
||||
auto el = factory(inext);
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
X(VTPR_ALWAYS_RELOAD_LIBRARY, "VTPR_ALWAYS_RELOAD_LIBRARY", false, \
|
||||
"If true, the library will always be reloaded, no matter what is currently loaded") \
|
||||
X(FLOAT_PUNCTUATION, "FLOAT_PUNCTUATION", ".", "The first character of this string will be used as the separator between the number fraction.") \
|
||||
X(ENABLE_SUPERANCILLARIES, "ENABLE_SUPERANCILLARIES", true, "If true, the superancillary functions will be used for VLE of pure fluids") \
|
||||
X(ENABLE_SUPERANCILLARIES, "ENABLE_SUPERANCILLARIES", true, "If true, the superancillary functions will be used for VLE of pure fluids") \
|
||||
X(LIST_STRING_DELIMITER, "LIST_STRING_DELIMITER", ",", "The delimiter to be used when converting a list of strings to a string")
|
||||
|
||||
// Use preprocessor to create the Enum
|
||||
@@ -116,8 +116,10 @@ std::string config_key_description(const std::string& key);
|
||||
class ConfigurationItem
|
||||
{
|
||||
public:
|
||||
ConfigurationDataTypes get_type() const { return type; }
|
||||
|
||||
ConfigurationDataTypes get_type() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
/// Cast to boolean
|
||||
operator bool() const {
|
||||
check_data_type(CONFIGURATION_BOOL_TYPE);
|
||||
@@ -283,7 +285,7 @@ class Configuration
|
||||
Configuration() {
|
||||
set_defaults();
|
||||
};
|
||||
~Configuration(){};
|
||||
~Configuration() {};
|
||||
|
||||
/// Get an item from the configuration
|
||||
ConfigurationItem& get_item(configuration_keys key) {
|
||||
@@ -307,63 +309,68 @@ class Configuration
|
||||
std::unordered_map<configuration_keys, ConfigurationItem>& get_items(void) {
|
||||
return items;
|
||||
};
|
||||
|
||||
bool possibly_set_from_env(configuration_keys key){
|
||||
|
||||
bool possibly_set_from_env(configuration_keys key) {
|
||||
/// Try to get from environment variable with the key name, prefixed by "COOLPROP_"
|
||||
std::string envkey = "COOLPROP_" + config_key_to_string(key);
|
||||
const char *envval = std::getenv(envkey.c_str());
|
||||
if (envval){
|
||||
auto tobool = [](const std::string x){
|
||||
if (x == "True" || x == "true"){ return true;}
|
||||
if (x == "False" || x == "false"){ return false;}
|
||||
const char* envval = std::getenv(envkey.c_str());
|
||||
if (envval) {
|
||||
auto tobool = [](const std::string x) {
|
||||
if (x == "True" || x == "true") {
|
||||
return true;
|
||||
}
|
||||
if (x == "False" || x == "false") {
|
||||
return false;
|
||||
}
|
||||
throw ValueError(x);
|
||||
};
|
||||
switch (get_item(key).get_type()){
|
||||
switch (get_item(key).get_type()) {
|
||||
case ConfigurationDataTypes::CONFIGURATION_STRING_TYPE:
|
||||
items.erase(key); items.emplace(key, ConfigurationItem(key, std::string(envval)));
|
||||
items.erase(key);
|
||||
items.emplace(key, ConfigurationItem(key, std::string(envval)));
|
||||
break;
|
||||
case ConfigurationDataTypes::CONFIGURATION_INTEGER_TYPE:
|
||||
int i;
|
||||
try{
|
||||
try {
|
||||
i = std::stoi(envval);
|
||||
}
|
||||
catch(...){
|
||||
} catch (...) {
|
||||
auto skey = config_key_to_string(key);
|
||||
std::string msg = "Unable to convert \""+std::string(envval)+"\" to int for key ["+skey+"]";
|
||||
std::string msg = "Unable to convert \"" + std::string(envval) + "\" to int for key [" + skey + "]";
|
||||
std::cerr << msg << std::endl;
|
||||
throw ValueError(msg);
|
||||
}
|
||||
items.erase(key); items.emplace(key, ConfigurationItem(key, i));
|
||||
items.erase(key);
|
||||
items.emplace(key, ConfigurationItem(key, i));
|
||||
break;
|
||||
case ConfigurationDataTypes::CONFIGURATION_DOUBLE_TYPE:
|
||||
double d;
|
||||
try{
|
||||
try {
|
||||
d = std::stod(envval);
|
||||
}
|
||||
catch(...){
|
||||
} catch (...) {
|
||||
auto skey = config_key_to_string(key);
|
||||
std::string msg = "Unable to convert \""+std::string(envval)+"\" to double for key ["+skey+"]";
|
||||
std::string msg = "Unable to convert \"" + std::string(envval) + "\" to double for key [" + skey + "]";
|
||||
std::cerr << msg << std::endl;
|
||||
throw ValueError(msg);
|
||||
}
|
||||
items.erase(key); items.emplace(key, ConfigurationItem(key, d));
|
||||
items.erase(key);
|
||||
items.emplace(key, ConfigurationItem(key, d));
|
||||
break;
|
||||
case ConfigurationDataTypes::CONFIGURATION_BOOL_TYPE:
|
||||
bool b;
|
||||
try{
|
||||
try {
|
||||
b = tobool(envval);
|
||||
}
|
||||
catch(...){
|
||||
} catch (...) {
|
||||
auto skey = config_key_to_string(key);
|
||||
std::string msg = "Unable to convert \""+std::string(envval)+"\" to bool for key ["+skey+"]";
|
||||
std::string msg = "Unable to convert \"" + std::string(envval) + "\" to bool for key [" + skey + "]";
|
||||
std::cerr << msg << std::endl;
|
||||
throw ValueError(msg);
|
||||
}
|
||||
items.erase(key); items.emplace(key, ConfigurationItem(key, b));
|
||||
items.erase(key);
|
||||
items.emplace(key, ConfigurationItem(key, b));
|
||||
break;
|
||||
default:
|
||||
auto skey = config_key_to_string(key);
|
||||
throw ValueError("This key ["+skey+"] has the wrong type; value was "+std::string(envval)+" ");
|
||||
throw ValueError("This key [" + skey + "] has the wrong type; value was " + std::string(envval) + " ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -382,9 +389,9 @@ class Configuration
|
||||
|
||||
// See if the variable is already present as environment variable
|
||||
#define X(Enum, String, Default, Desc) possibly_set_from_env(Enum);
|
||||
CONFIGURATION_KEYS_ENUM
|
||||
CONFIGURATION_KEYS_ENUM
|
||||
#undef X
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,9 @@ double Props1SI(std::string FluidName, std::string Output);
|
||||
* @param backend The string representation of the backend (HEOS, REFPROP, INCOMP, etc.)
|
||||
* @param fluids The fluid name(s)
|
||||
* @param fractions The fractions (molar, mass, volume, etc.) of the components
|
||||
*/
|
||||
std::vector<std::vector<double>> Props1SImulti(const std::vector<std::string>& Outputs, const std::string& backend, const std::vector<std::string>& fluids, const std::vector<double>& fractions);
|
||||
*/
|
||||
std::vector<std::vector<double>> Props1SImulti(const std::vector<std::string>& Outputs, const std::string& backend,
|
||||
const std::vector<std::string>& fluids, const std::vector<double>& fractions);
|
||||
/// Return a value that depends on the thermodynamic state
|
||||
/// @param Output The output parameter, one of "T","D","H",etc.
|
||||
/// @param Name1 The first state variable name, one of "T","D","H",etc.
|
||||
|
||||
@@ -42,7 +42,7 @@ struct CriticalRegionSplines
|
||||
double T_min, T_max, rhomolar_min, rhomolar_max;
|
||||
std::vector<double> cL, cV;
|
||||
bool enabled;
|
||||
CriticalRegionSplines() : T_min(_HUGE), T_max(_HUGE), rhomolar_min(_HUGE), rhomolar_max(_HUGE), enabled(false){};
|
||||
CriticalRegionSplines() : T_min(_HUGE), T_max(_HUGE), rhomolar_min(_HUGE), rhomolar_max(_HUGE), enabled(false) {};
|
||||
|
||||
const void get_densities(double T, double rho_min, double rho_crit, double rho_max, double& rhoL, double& rhoV) const {
|
||||
int Nsoln = -1, Ngood = 0;
|
||||
@@ -288,15 +288,15 @@ struct ViscosityHigherOrderVariables
|
||||
{
|
||||
enum ViscosityHigherOrderEnum
|
||||
{
|
||||
VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND, ///< Use \ref TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand
|
||||
VISCOSITY_HIGHER_ORDER_HYDROGEN, ///< Use \ref TransportRoutines::viscosity_hydrogen_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_HEXANE, ///< Use \ref TransportRoutines::viscosity_hexane_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_HEPTANE, ///< Use \ref TransportRoutines::viscosity_heptane_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_ETHANE, ///< Use \ref TransportRoutines::viscosity_ethane_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_BENZENE, ///< Use \ref TransportRoutines::viscosity_benzene_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_TOLUENE, ///< Use \ref TransportRoutines::viscosity_toluene_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_CO2_LAESECKE_JPCRD_2017,///< Use \ref TransportRoutines::viscosity_CO2_higher_order_hardcoded_LaeseckeJPCRD2017
|
||||
VISCOSITY_HIGHER_ORDER_FRICTION_THEORY, ///< Use \ref TransportRoutines::viscosity_higher_order_friction_theory
|
||||
VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND, ///< Use \ref TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand
|
||||
VISCOSITY_HIGHER_ORDER_HYDROGEN, ///< Use \ref TransportRoutines::viscosity_hydrogen_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_HEXANE, ///< Use \ref TransportRoutines::viscosity_hexane_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_HEPTANE, ///< Use \ref TransportRoutines::viscosity_heptane_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_ETHANE, ///< Use \ref TransportRoutines::viscosity_ethane_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_BENZENE, ///< Use \ref TransportRoutines::viscosity_benzene_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_TOLUENE, ///< Use \ref TransportRoutines::viscosity_toluene_higher_order_hardcoded
|
||||
VISCOSITY_HIGHER_ORDER_CO2_LAESECKE_JPCRD_2017, ///< Use \ref TransportRoutines::viscosity_CO2_higher_order_hardcoded_LaeseckeJPCRD2017
|
||||
VISCOSITY_HIGHER_ORDER_FRICTION_THEORY, ///< Use \ref TransportRoutines::viscosity_higher_order_friction_theory
|
||||
VISCOSITY_HIGHER_ORDER_NOT_SET
|
||||
};
|
||||
ViscosityHigherOrderEnum type = VISCOSITY_HIGHER_ORDER_NOT_SET;
|
||||
@@ -399,13 +399,13 @@ struct Ancillaries
|
||||
*/
|
||||
class EquationOfState
|
||||
{
|
||||
public:
|
||||
public:
|
||||
using SuperAncillary_t = superancillary::SuperAncillary<std::vector<double>>;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
std::string superancillaries_str;
|
||||
std::optional<SuperAncillary_t> superancillaries = std::nullopt; ///< The superancillaries
|
||||
|
||||
std::optional<SuperAncillary_t> superancillaries = std::nullopt; ///< The superancillaries
|
||||
|
||||
public:
|
||||
SimpleState reduce, ///< Reducing state used for the EOS (usually, but not always, the critical point)
|
||||
sat_min_liquid, ///< The saturated liquid state at the minimum saturation temperature
|
||||
@@ -426,33 +426,31 @@ private:
|
||||
BibTeX_CP0; ///< The bibtex key for the ideal gas specific heat correlation
|
||||
CriticalRegionSplines
|
||||
critical_region_splines; ///< A cubic spline in the form T = f(rho) for saturated liquid and saturated vapor curves in the near-critical region
|
||||
|
||||
|
||||
/// Get the optional of the populated superancillary
|
||||
std::optional<SuperAncillary_t> & get_superanc_optional(){
|
||||
|
||||
if (!superancillaries){
|
||||
if (!superancillaries_str.empty()){
|
||||
// auto start = std::chrono::high_resolution_clock::now(); // Start time
|
||||
std::optional<SuperAncillary_t>& get_superanc_optional() {
|
||||
|
||||
if (!superancillaries) {
|
||||
if (!superancillaries_str.empty()) {
|
||||
// auto start = std::chrono::high_resolution_clock::now(); // Start time
|
||||
// Now do the parsing pass and replace with the actual superancillary
|
||||
superancillaries.emplace(SuperAncillary_t(superancillaries_str));
|
||||
// auto end = std::chrono::high_resolution_clock::now(); // End time
|
||||
// auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
// auto end = std::chrono::high_resolution_clock::now(); // End time
|
||||
// auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
//std::cout << "Execution time: " << duration.count() << " microseconds for " << BibTeX_EOS << std::endl;
|
||||
}
|
||||
}
|
||||
return superancillaries;
|
||||
}
|
||||
|
||||
|
||||
/// Set the placeholder string for the superancillaries to allow for lazy construction, particularly important in debug builds
|
||||
void set_superancillaries_str(const std::string &s){
|
||||
void set_superancillaries_str(const std::string& s) {
|
||||
superancillaries_str = s;
|
||||
// Do the construction greedily by default, but allow it to be lazy if you want
|
||||
#if !defined(LAZY_LOAD_SUPERANCILLARIES)
|
||||
get_superanc_optional();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Validate the EOS that was just constructed
|
||||
void validate() {
|
||||
@@ -542,13 +540,13 @@ class CoolPropFluid
|
||||
CoolPropFluid() : ECS_qd(-_HUGE) {
|
||||
this->ChemSpider_id = -1;
|
||||
};
|
||||
~CoolPropFluid(){};
|
||||
~CoolPropFluid() {};
|
||||
const EquationOfState& EOS() const {
|
||||
return EOSVector[0];
|
||||
} ///< Get a reference to the equation of state
|
||||
EquationOfState& EOS() {
|
||||
return EOSVector[0];
|
||||
} ///< Get a reference to the equation of state
|
||||
} ///< Get a reference to the equation of state
|
||||
std::vector<EquationOfState> EOSVector; ///< The equations of state that could be used for this fluid
|
||||
|
||||
std::string name; ///< The name of the fluid
|
||||
|
||||
@@ -105,7 +105,7 @@ EXPORT_CODE void CONVENTION Props1SImulti(const char* Outputs, char* backend, co
|
||||
*
|
||||
* \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output)
|
||||
*/
|
||||
EXPORT_CODE double CONVENTION PropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref);
|
||||
EXPORT_CODE double CONVENTION PropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* FluidName);
|
||||
/**
|
||||
*\overload
|
||||
*\sa \ref CoolProp::PropsSImulti(const std::vector<std::string>& Outputs, const std::string& Name1, const std::vector<double>& Prop1,
|
||||
@@ -137,7 +137,7 @@ EXPORT_CODE void CONVENTION PropsSImulti(const char* Outputs, const char* Name1,
|
||||
*
|
||||
* \note This function returns the phase string in pre-allocated phase variable. If buffer is not large enough, no copy is made
|
||||
*/
|
||||
EXPORT_CODE long CONVENTION PhaseSI(const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref, char* phase, int n);
|
||||
EXPORT_CODE long CONVENTION PhaseSI(const char* Name1, double Prop1, const char* Name2, double Prop2, const char* FluidName, char* phase, int n);
|
||||
|
||||
/**
|
||||
*\overload
|
||||
@@ -155,7 +155,7 @@ EXPORT_CODE long CONVENTION get_global_param_string(const char* param, char* Out
|
||||
*
|
||||
* @returns error_code 1 = Ok 0 = error
|
||||
*/
|
||||
EXPORT_CODE long CONVENTION get_parameter_information_string(const char* key, char* Output, int n);
|
||||
EXPORT_CODE long CONVENTION get_parameter_information_string(const char* param, char* Output, int n);
|
||||
/**
|
||||
* \overload
|
||||
* \sa \ref CoolProp::get_fluid_param_string
|
||||
@@ -219,7 +219,7 @@ EXPORT_CODE int CONVENTION set_reference_stateD(const char* Ref, double T, doubl
|
||||
* \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output)
|
||||
*/
|
||||
EXPORT_CODE void CONVENTION propssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2,
|
||||
const char* Ref, double* output);
|
||||
const char* FluidName, double* output);
|
||||
|
||||
/// Convert from degrees Fahrenheit to Kelvin (useful primarily for testing)
|
||||
EXPORT_CODE double CONVENTION F2K(double T_F);
|
||||
@@ -234,7 +234,7 @@ EXPORT_CODE long CONVENTION get_param_index(const char* param);
|
||||
*
|
||||
* @returns index The index as a long. If input is invalid, returns -1
|
||||
*/
|
||||
EXPORT_CODE long CONVENTION get_input_pair_index(const char* param);
|
||||
EXPORT_CODE long CONVENTION get_input_pair_index(const char* pair);
|
||||
/** \brief Redirect all output that would go to console (stdout) to a file
|
||||
*/
|
||||
EXPORT_CODE long CONVENTION redirect_stdout(const char* file);
|
||||
@@ -404,7 +404,7 @@ EXPORT_CODE double CONVENTION AbstractState_get_fugacity(const long handle, cons
|
||||
* @return
|
||||
*/
|
||||
EXPORT_CODE double CONVENTION AbstractState_get_fugacity_coefficient(const long handle, const long i, long* errcode, char* message_buffer,
|
||||
const long buffer_length);
|
||||
const long buffer_length);
|
||||
/**
|
||||
* @brief Update the state of the AbstractState
|
||||
* @param handle The integer handle for the state class stored in memory
|
||||
@@ -492,8 +492,8 @@ EXPORT_CODE double CONVENTION AbstractState_first_partial_deriv(const long handl
|
||||
*/
|
||||
|
||||
EXPORT_CODE double CONVENTION AbstractState_second_two_phase_deriv(const long handle, const long Of1, const long Wrt1, const long Constant1,
|
||||
const long Wrt2, const long Constant2, long* errcode, char* message_buffer,
|
||||
const long buffer_length);
|
||||
const long Wrt2, const long Constant2, long* errcode, char* message_buffer,
|
||||
const long buffer_length);
|
||||
/**
|
||||
* @brief Calculate the second partial derivative int two-phase region from the AbstractState using integer values for the desired parameters
|
||||
* @param handle The integer handle for the state class stored in memory
|
||||
@@ -526,9 +526,9 @@ EXPORT_CODE double CONVENTION AbstractState_second_partial_deriv(const long hand
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
EXPORT_CODE double CONVENTION AbstractState_first_two_phase_deriv_splined(const long handle, const long Of, const long Wrt, const long Constant,
|
||||
const double x_end,long* errcode, char* message_buffer, const long buffer_length);
|
||||
const double x_end, long* errcode, char* message_buffer,
|
||||
const long buffer_length);
|
||||
/**
|
||||
* @brief Calculate the first partial derivative in homogeneous phases from the AbstractState using integer values for the desired parameters
|
||||
* @param handle The integer handle for the state class stored in memory
|
||||
@@ -714,10 +714,10 @@ EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long han
|
||||
*
|
||||
* @note If there is an error in an update call for one of the inputs, no change in the output array will be made
|
||||
*/
|
||||
EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data_checkedMemory(const long handle, const long length, const long maxComponents, double* T,
|
||||
double* p, double* rhomolar_vap, double* rhomolar_liq, double* x, double* y,
|
||||
long* actual_length, long* actual_components, long* errcode, char* message_buffer,
|
||||
const long buffer_length);
|
||||
EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data_checkedMemory(const long handle, const long length, const long maxComponents,
|
||||
double* T, double* p, double* rhomolar_vap, double* rhomolar_liq,
|
||||
double* x, double* y, long* actual_length, long* actual_components,
|
||||
long* errcode, char* message_buffer, const long buffer_length);
|
||||
|
||||
/**
|
||||
* @brief Build the spinodal
|
||||
|
||||
@@ -34,14 +34,16 @@ Either ``x[i]`` or ``y[i]`` may be NaN if the isoline is not defined at that poi
|
||||
class Isoline
|
||||
{
|
||||
public:
|
||||
std::vector<double> x; ///< x positions of the isoline, in SI unit of the x axis of the queried ``PropertyPlot``. May contain NaN values.
|
||||
std::vector<double> y; ///< y positions of the isoline, in SI unit of the y axis of the queried ``PropertyPlot``. May contain NaN values.
|
||||
double value; ///< Value of the isoline in SI units.
|
||||
std::vector<double> x; ///< x positions of the isoline, in SI unit of the x axis of the queried ``PropertyPlot``. May contain NaN values.
|
||||
std::vector<double> y; ///< y positions of the isoline, in SI unit of the y axis of the queried ``PropertyPlot``. May contain NaN values.
|
||||
double value; ///< Value of the isoline in SI units.
|
||||
|
||||
/**
|
||||
@brief Convenience method to get the number of points in the isoline. ``size() = x.size() = y.size()``.
|
||||
*/
|
||||
size_t size() const { return x.size(); };
|
||||
size_t size() const {
|
||||
return x.size();
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<CoolProp::AbstractState> state_;
|
||||
@@ -50,7 +52,8 @@ class Isoline
|
||||
CoolProp::parameters ykey_;
|
||||
CoolProp::parameters key_;
|
||||
|
||||
Isoline(CoolProp::parameters key, CoolProp::parameters xkey, CoolProp::parameters ykey, double value, const std::shared_ptr<CoolProp::AbstractState>& state);
|
||||
Isoline(CoolProp::parameters key, CoolProp::parameters xkey, CoolProp::parameters ykey, double value,
|
||||
const std::shared_ptr<CoolProp::AbstractState>& state);
|
||||
|
||||
Range get_sat_bounds(CoolProp::parameters key) const;
|
||||
void calc_sat_range(int count);
|
||||
@@ -136,7 +139,8 @@ class PropertyPlot
|
||||
@param xkey The parameter to plot on the x axis (e.g. for "ph" plots this would be ``CoolProp::iHmass``, and for "Ts" plots this would be ``CoolProp::iSmass``)
|
||||
@param tp_limits The temperature and pressure limits of the plot.
|
||||
*/
|
||||
PropertyPlot(const std::string& fluid_name, CoolProp::parameters ykey, CoolProp::parameters xkey, CoolProp::Plot::TPLimits tp_limits = CoolProp::Plot::TPLimits::Def);
|
||||
PropertyPlot(const std::string& fluid_name, CoolProp::parameters ykey, CoolProp::parameters xkey,
|
||||
CoolProp::Plot::TPLimits tp_limits = CoolProp::Plot::TPLimits::Def);
|
||||
|
||||
/**
|
||||
@brief Retrieve a valid range of values (inclusive) for the isoline with the given ``key`` in SI units.
|
||||
@@ -187,7 +191,8 @@ class PropertyPlot
|
||||
|
||||
Range get_sat_bounds(CoolProp::parameters key) const;
|
||||
Range2D get_Tp_limits() const;
|
||||
Range2D get_axis_limits(CoolProp::parameters xkey = CoolProp::parameters::iundefined_parameter, CoolProp::parameters ykey = CoolProp::parameters::iundefined_parameter, bool autoscale = true) const;
|
||||
Range2D get_axis_limits(CoolProp::parameters xkey = CoolProp::parameters::iundefined_parameter,
|
||||
CoolProp::parameters ykey = CoolProp::parameters::iundefined_parameter, bool autoscale = true) const;
|
||||
};
|
||||
|
||||
} /* namespace Plot */
|
||||
|
||||
@@ -73,7 +73,7 @@ class Dictionary
|
||||
string_vectors_map string_vectors;
|
||||
|
||||
public:
|
||||
Dictionary(){};
|
||||
Dictionary() {};
|
||||
bool is_empty(void) const {
|
||||
return numbers.empty() && strings.empty() && double_vectors.empty() && string_vectors.empty();
|
||||
}
|
||||
|
||||
@@ -110,15 +110,15 @@ enum parameters
|
||||
iUmolar_idealgas, ///< The ideal gas molar internal energy
|
||||
|
||||
// Mass specific thermodynamic properties
|
||||
iDmass, ///< Mass-based density
|
||||
iHmass, ///< Mass-based enthalpy
|
||||
iSmass, ///< Mass-based entropy
|
||||
iCpmass, ///< Mass-based constant-pressure specific heat
|
||||
iCp0mass, ///< Mass-based ideal-gas specific heat
|
||||
iCvmass, ///< Mass-based constant-volume specific heat
|
||||
iUmass, ///< Mass-based internal energy
|
||||
iGmass, ///< Mass-based Gibbs energy
|
||||
iHelmholtzmass, ///< Mass-based Helmholtz energy
|
||||
iDmass, ///< Mass-based density
|
||||
iHmass, ///< Mass-based enthalpy
|
||||
iSmass, ///< Mass-based entropy
|
||||
iCpmass, ///< Mass-based constant-pressure specific heat
|
||||
iCp0mass, ///< Mass-based ideal-gas specific heat
|
||||
iCvmass, ///< Mass-based constant-volume specific heat
|
||||
iUmass, ///< Mass-based internal energy
|
||||
iGmass, ///< Mass-based Gibbs energy
|
||||
iHelmholtzmass, ///< Mass-based Helmholtz energy
|
||||
iHmass_idealgas, ///< The ideal gas specific enthalpy
|
||||
iSmass_idealgas, ///< The ideal gas specific entropy
|
||||
iUmass_idealgas, ///< The ideal gas specific internal energy
|
||||
@@ -224,10 +224,10 @@ phases get_phase_index(const std::string& param_name);
|
||||
/// Return true if passed PC-SAFT association scheme name is valid, otherwise false
|
||||
/// @param scheme_name The association scheme string to be checked ("2B" for instance)
|
||||
/// @param iOutput Gets updated with the schemes enum value if scheme_name is found
|
||||
bool is_valid_scheme(const std::string &scheme_name, schemes &iOutput);
|
||||
bool is_valid_scheme(const std::string& scheme_name, schemes& iOutput);
|
||||
|
||||
/// Return the enum key corresponding to the association scheme name ("2B" for instance)
|
||||
schemes get_scheme_index(const std::string &scheme_name);
|
||||
schemes get_scheme_index(const std::string& scheme_name);
|
||||
|
||||
/// Returns true if the input is trivial (constants, critical parameters, etc.)
|
||||
bool is_trivial_parameter(int key);
|
||||
|
||||
@@ -28,7 +28,7 @@ class CoolPropBaseError : public std::exception
|
||||
eDirectorySize
|
||||
};
|
||||
CoolPropBaseError(const std::string& err, ErrCode code) throw() : m_code(code), m_err(err) {}
|
||||
~CoolPropBaseError() throw(){};
|
||||
~CoolPropBaseError() throw() {};
|
||||
virtual const char* what() const throw() {
|
||||
return m_err.c_str();
|
||||
}
|
||||
|
||||
@@ -56,12 +56,11 @@ struct HelmholtzDerivatives
|
||||
#undef X
|
||||
CoolPropDbl tau, delta, T_red, rhomolar_red;
|
||||
|
||||
void reset(CoolPropDbl v) {
|
||||
void reset(CoolPropDbl v){
|
||||
#define X(name) name = v;
|
||||
LIST_OF_DERIVATIVE_VARIABLES
|
||||
LIST_OF_DERIVATIVE_VARIABLES
|
||||
#undef X
|
||||
}
|
||||
HelmholtzDerivatives operator+(const HelmholtzDerivatives& other) const {
|
||||
} HelmholtzDerivatives operator+(const HelmholtzDerivatives& other) const {
|
||||
HelmholtzDerivatives _new;
|
||||
#define X(name) _new.name = name + other.name;
|
||||
LIST_OF_DERIVATIVE_VARIABLES
|
||||
@@ -75,10 +74,8 @@ struct HelmholtzDerivatives
|
||||
#undef X
|
||||
return _new;
|
||||
}
|
||||
HelmholtzDerivatives() {
|
||||
HelmholtzDerivatives() : tau(0.0), delta(0.0), T_red(_HUGE), rhomolar_red(_HUGE) {
|
||||
reset(0.0);
|
||||
T_red = _HUGE;
|
||||
rhomolar_red = _HUGE;
|
||||
};
|
||||
/// Retrieve a single value based on the number of derivatives with respect to tau and delta
|
||||
double get(std::size_t itau, std::size_t idelta) {
|
||||
@@ -168,8 +165,8 @@ struct HelmholtzDerivatives
|
||||
class BaseHelmholtzTerm
|
||||
{
|
||||
public:
|
||||
BaseHelmholtzTerm(){};
|
||||
virtual ~BaseHelmholtzTerm(){};
|
||||
BaseHelmholtzTerm() {};
|
||||
virtual ~BaseHelmholtzTerm() {};
|
||||
|
||||
/// Returns the base, non-dimensional, Helmholtz energy term (no derivatives) [-]
|
||||
/** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$
|
||||
@@ -292,11 +289,11 @@ class BaseHelmholtzTerm
|
||||
};
|
||||
|
||||
virtual void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) = 0;
|
||||
#if ENABLE_CATCH
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const {
|
||||
throw CoolProp::NotImplementedError("The mcx derivative function was not implemented");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ResidualHelmholtzGeneralizedExponentialElement
|
||||
@@ -360,7 +357,7 @@ class ResidualHelmholtzGeneralizedExponential : public BaseHelmholtzTerm
|
||||
std::vector<ResidualHelmholtzGeneralizedExponentialElement> elements;
|
||||
// Default Constructor
|
||||
ResidualHelmholtzGeneralizedExponential()
|
||||
: delta_li_in_u(false), tau_mi_in_u(false), eta1_in_u(false), eta2_in_u(false), beta1_in_u(false), beta2_in_u(false), finished(false), N(0){};
|
||||
: delta_li_in_u(false), tau_mi_in_u(false), eta1_in_u(false), eta2_in_u(false), beta1_in_u(false), beta2_in_u(false), finished(false), N(0) {};
|
||||
/** \brief Add and convert an old-style power (polynomial) term to generalized form
|
||||
*
|
||||
* Term of the format
|
||||
@@ -474,10 +471,9 @@ class ResidualHelmholtzGeneralizedExponential : public BaseHelmholtzTerm
|
||||
* Term of the format
|
||||
* \f$ \alpha^r=\displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} \exp(-gd_j\delta^{ld_j}-gt_j\tau^{lt_i})\f$
|
||||
*/
|
||||
void add_DoubleExponential(
|
||||
const std::vector<CoolPropDbl>& n, const std::vector<CoolPropDbl>& d, const std::vector<CoolPropDbl>& t,
|
||||
const std::vector<CoolPropDbl>& gd, const std::vector<CoolPropDbl>& ld,
|
||||
const std::vector<CoolPropDbl>& gt, const std::vector<CoolPropDbl>& lt) {
|
||||
void add_DoubleExponential(const std::vector<CoolPropDbl>& n, const std::vector<CoolPropDbl>& d, const std::vector<CoolPropDbl>& t,
|
||||
const std::vector<CoolPropDbl>& gd, const std::vector<CoolPropDbl>& ld, const std::vector<CoolPropDbl>& gt,
|
||||
const std::vector<CoolPropDbl>& lt) {
|
||||
for (std::size_t i = 0; i < n.size(); ++i) {
|
||||
ResidualHelmholtzGeneralizedExponentialElement el;
|
||||
el.n = n[i];
|
||||
@@ -543,9 +539,9 @@ class ResidualHelmholtzGeneralizedExponential : public BaseHelmholtzTerm
|
||||
void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) override;
|
||||
//void allEigen(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw();
|
||||
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ResidualHelmholtzNonAnalyticElement
|
||||
@@ -564,7 +560,7 @@ class ResidualHelmholtzNonAnalytic : public BaseHelmholtzTerm
|
||||
N = 0;
|
||||
};
|
||||
/// Destructor. No implementation
|
||||
~ResidualHelmholtzNonAnalytic(){};
|
||||
~ResidualHelmholtzNonAnalytic() {};
|
||||
/// Constructor
|
||||
ResidualHelmholtzNonAnalytic(const std::vector<CoolPropDbl>& n, const std::vector<CoolPropDbl>& a, const std::vector<CoolPropDbl>& b,
|
||||
const std::vector<CoolPropDbl>& beta, const std::vector<CoolPropDbl>& A, const std::vector<CoolPropDbl>& B,
|
||||
@@ -637,9 +633,9 @@ class ResidualHelmholtzGaoB : public BaseHelmholtzTerm
|
||||
void to_json(rapidjson::Value& el, rapidjson::Document& doc);
|
||||
void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) override;
|
||||
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// The generalized Lee-Kesler formulation of Xiang & Deiters: doi:10.1016/j.ces.2007.11.029
|
||||
@@ -715,7 +711,7 @@ class ResidualHelmholtzSAFTAssociating : public BaseHelmholtzTerm
|
||||
bool disabled;
|
||||
|
||||
//Destructor. No Implementation
|
||||
~ResidualHelmholtzSAFTAssociating(){};
|
||||
~ResidualHelmholtzSAFTAssociating() {};
|
||||
|
||||
void to_json(rapidjson::Value& el, rapidjson::Document& doc);
|
||||
|
||||
@@ -743,12 +739,9 @@ class BaseHelmholtzContainer
|
||||
protected:
|
||||
std::array<double, 16> cache = create_filled_array<double, 16>(_HUGE);
|
||||
std::array<bool, 16> is_cached = create_filled_array<bool, 16>(false);
|
||||
constexpr static std::size_t i00 = 0, i01 = 1, i02 = 2, i03 = 3, i04 = 4,
|
||||
i10 = 5, i11 = 6, i12 = 7, i13 = 8,
|
||||
i20 = 9, i21 = 10, i22 = 11,
|
||||
i30 = 12, i31 = 13,
|
||||
i40 = 14;
|
||||
|
||||
constexpr static std::size_t i00 = 0, i01 = 1, i02 = 2, i03 = 3, i04 = 4, i10 = 5, i11 = 6, i12 = 7, i13 = 8, i20 = 9, i21 = 10, i22 = 11,
|
||||
i30 = 12, i31 = 13, i40 = 14;
|
||||
|
||||
bool cache_valid(std::size_t i) const {
|
||||
return is_cached[i];
|
||||
}
|
||||
@@ -1018,9 +1011,9 @@ class IdealHelmholtzPower : public BaseHelmholtzTerm
|
||||
bool enabled;
|
||||
|
||||
public:
|
||||
IdealHelmholtzPower() : N(0), enabled(false){};
|
||||
IdealHelmholtzPower() : N(0), enabled(false) {};
|
||||
// Constructor
|
||||
IdealHelmholtzPower(const std::vector<CoolPropDbl>& n, const std::vector<CoolPropDbl>& t) : n(n), t(t), N(n.size()), enabled(true){};
|
||||
IdealHelmholtzPower(const std::vector<CoolPropDbl>& n, const std::vector<CoolPropDbl>& t) : n(n), t(t), N(n.size()), enabled(true) {};
|
||||
|
||||
bool is_enabled() const {
|
||||
return enabled;
|
||||
@@ -1137,7 +1130,7 @@ class IdealHelmholtzCP0Constant : public BaseHelmholtzTerm
|
||||
};
|
||||
|
||||
/// Destructor
|
||||
~IdealHelmholtzCP0Constant(){};
|
||||
~IdealHelmholtzCP0Constant() {};
|
||||
|
||||
bool is_enabled() const {
|
||||
return enabled;
|
||||
@@ -1220,9 +1213,9 @@ class IdealHelmholtzGERG2004Sinh : public BaseHelmholtzTerm
|
||||
};
|
||||
void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) override;
|
||||
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
class IdealHelmholtzGERG2004Cosh : public BaseHelmholtzTerm
|
||||
@@ -1256,10 +1249,9 @@ class IdealHelmholtzGERG2004Cosh : public BaseHelmholtzTerm
|
||||
};
|
||||
void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) override;
|
||||
|
||||
#if ENABLE_CATCH
|
||||
#if ENABLE_CATCH
|
||||
virtual mcx::MultiComplex<double> one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const override;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
///// Term in the ideal-gas specific heat equation that is based on Aly-Lee formulation
|
||||
@@ -1412,7 +1404,7 @@ class IdealHelmholtzContainer : public BaseHelmholtzContainer
|
||||
IdealHelmholtzGERG2004Cosh GERG2004Cosh;
|
||||
IdealHelmholtzGERG2004Sinh GERG2004Sinh;
|
||||
|
||||
IdealHelmholtzContainer() : _prefactor(1.0){};
|
||||
IdealHelmholtzContainer() : _prefactor(1.0) {};
|
||||
|
||||
void set_prefactor(double prefactor) {
|
||||
_prefactor = prefactor;
|
||||
|
||||
@@ -141,7 +141,7 @@ class IncompressibleFluid
|
||||
strict = true;
|
||||
xid = IFRAC_UNDEFINED;
|
||||
};
|
||||
virtual ~IncompressibleFluid(){};
|
||||
virtual ~IncompressibleFluid() {};
|
||||
|
||||
std::string getName() const {
|
||||
return name;
|
||||
|
||||
@@ -11,15 +11,15 @@ namespace CoolProp {
|
||||
|
||||
struct PCSAFTValues
|
||||
{
|
||||
CoolPropDbl m; ///< Number of segments
|
||||
CoolPropDbl sigma; ///< Segment diameter (1/Angstrom)
|
||||
CoolPropDbl u; ///< Dispersion energy divided by Boltzmann constant (K)
|
||||
CoolPropDbl uAB; ///< Association energy (K)
|
||||
CoolPropDbl volA; ///< Association volume
|
||||
std::vector<std::string> assocScheme; ///< The type of association for each associating functional group (see Huang and Radosz 1990)
|
||||
CoolPropDbl dipm; ///< Dipole moment (Debye)
|
||||
CoolPropDbl dipnum; ///< Number of dipole moments per molecule
|
||||
CoolPropDbl z; ///< Charge of the compound
|
||||
CoolPropDbl m; ///< Number of segments
|
||||
CoolPropDbl sigma; ///< Segment diameter (1/Angstrom)
|
||||
CoolPropDbl u; ///< Dispersion energy divided by Boltzmann constant (K)
|
||||
CoolPropDbl uAB; ///< Association energy (K)
|
||||
CoolPropDbl volA; ///< Association volume
|
||||
std::vector<std::string> assocScheme; ///< The type of association for each associating functional group (see Huang and Radosz 1990)
|
||||
CoolPropDbl dipm; ///< Dipole moment (Debye)
|
||||
CoolPropDbl dipnum; ///< Number of dipole moments per molecule
|
||||
CoolPropDbl z; ///< Charge of the compound
|
||||
};
|
||||
|
||||
class PCSAFTFluid
|
||||
@@ -32,9 +32,9 @@ class PCSAFTFluid
|
||||
PCSAFTValues params;
|
||||
|
||||
public:
|
||||
PCSAFTFluid(){};
|
||||
PCSAFTFluid() {};
|
||||
PCSAFTFluid(rapidjson::Value::ValueIterator itr);
|
||||
~PCSAFTFluid(){};
|
||||
~PCSAFTFluid() {};
|
||||
|
||||
std::string getName() const {
|
||||
return name;
|
||||
|
||||
@@ -26,10 +26,10 @@ class Polynomial2D
|
||||
|
||||
public:
|
||||
/// Constructors
|
||||
Polynomial2D(){};
|
||||
Polynomial2D() {};
|
||||
|
||||
/// Destructor. No implementation
|
||||
virtual ~Polynomial2D(){};
|
||||
virtual ~Polynomial2D() {};
|
||||
|
||||
public:
|
||||
/// Convert the coefficient vector.
|
||||
@@ -199,7 +199,7 @@ class Poly2DResidual : public FuncWrapper1DWithDeriv
|
||||
/// @param z_in double value that represents the current output in the 3rd dimension
|
||||
/// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y)
|
||||
Poly2DResidual(Polynomial2D& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis);
|
||||
virtual ~Poly2DResidual(){};
|
||||
virtual ~Poly2DResidual() {};
|
||||
|
||||
double call(double target);
|
||||
double deriv(double target);
|
||||
@@ -217,10 +217,10 @@ class Polynomial2DFrac : public Polynomial2D
|
||||
|
||||
public:
|
||||
/// Constructors
|
||||
Polynomial2DFrac(){};
|
||||
Polynomial2DFrac() {};
|
||||
|
||||
/// Destructor. No implementation
|
||||
virtual ~Polynomial2DFrac(){};
|
||||
virtual ~Polynomial2DFrac() {};
|
||||
|
||||
public:
|
||||
// /// Integration functions
|
||||
@@ -419,7 +419,7 @@ class Poly2DFracResidual : public Poly2DResidual
|
||||
/// @param y_base base value for y (y = y_in - y_base)
|
||||
Poly2DFracResidual(Polynomial2DFrac& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis,
|
||||
const int& x_exp, const int& y_exp, const double& x_base, const double& y_base);
|
||||
virtual ~Poly2DFracResidual(){};
|
||||
virtual ~Poly2DFracResidual() {};
|
||||
double call(double target);
|
||||
double deriv(double target);
|
||||
};
|
||||
@@ -445,7 +445,7 @@ class Poly2DFracIntResidual : public Poly2DFracResidual
|
||||
/// @param int_axis axis for the integration (0=x, 1=y)
|
||||
Poly2DFracIntResidual(Polynomial2DFrac& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis,
|
||||
const int& x_exp, const int& y_exp, const double& x_base, const double& y_base, const int& int_axis);
|
||||
virtual ~Poly2DFracIntResidual(){};
|
||||
virtual ~Poly2DFracIntResidual() {};
|
||||
double call(double target);
|
||||
double deriv(double target);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ class FuncWrapper1D
|
||||
int iter;
|
||||
int verbosity = 0;
|
||||
FuncWrapper1D() : errcode(0), errstring(""), iter(0) {};
|
||||
virtual ~FuncWrapper1D(){};
|
||||
virtual ~FuncWrapper1D() {};
|
||||
virtual double call(double) = 0;
|
||||
/**
|
||||
* /brief A function for checking whether the input is in range;
|
||||
@@ -58,8 +58,8 @@ class FuncWrapperND
|
||||
public:
|
||||
int errcode;
|
||||
std::string errstring;
|
||||
FuncWrapperND() : errcode(0), errstring(""){};
|
||||
virtual ~FuncWrapperND(){};
|
||||
FuncWrapperND() : errcode(0), errstring("") {};
|
||||
virtual ~FuncWrapperND() {};
|
||||
virtual std::vector<double> call(const std::vector<double>&) = 0; // must be provided
|
||||
virtual std::vector<std::vector<double>> Jacobian(const std::vector<double>&);
|
||||
};
|
||||
@@ -87,10 +87,10 @@ inline double Secant(FuncWrapper1D& f, double x0, double dx, double ftol, int ma
|
||||
return Secant(&f, x0, dx, ftol, maxiter);
|
||||
}
|
||||
|
||||
inline double ExtrapolatingSecant(FuncWrapper1D& f, double x0, double dx, double ftol, int maxiter){
|
||||
inline double ExtrapolatingSecant(FuncWrapper1D& f, double x0, double dx, double ftol, int maxiter) {
|
||||
return ExtrapolatingSecant(&f, x0, dx, ftol, maxiter);
|
||||
}
|
||||
inline double BoundedSecant(FuncWrapper1D& f, double x0, double xmin, double xmax, double dx, double ftol, int maxiter){
|
||||
inline double BoundedSecant(FuncWrapper1D& f, double x0, double xmin, double xmax, double dx, double ftol, int maxiter) {
|
||||
return BoundedSecant(&f, x0, xmin, xmax, dx, ftol, maxiter);
|
||||
}
|
||||
inline double Newton(FuncWrapper1DWithDeriv& f, double x0, double ftol, int maxiter) {
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
#include <Eigen/Dense>
|
||||
|
||||
template<typename Callable>
|
||||
auto romberg_diff(Callable& func, double x, std::size_t order=2, double h=0.1){
|
||||
|
||||
// Initialize the table
|
||||
auto r = Eigen::ArrayXd(order, order);
|
||||
|
||||
// Compute the first column using the central difference formula
|
||||
for (auto i = 0; i < order; ++i){
|
||||
r(i, 0) = (func(x + h) - func(x - h)) / (2 * h);
|
||||
h /= 2.0;
|
||||
}
|
||||
|
||||
// Apply Richardson extrapolation
|
||||
for (auto i = 1; i < order; ++i){
|
||||
for (auto j = i; j < order; ++j){
|
||||
double fouri = pow(4, i);
|
||||
r(j, i) = (fouri * r(j, i-1) - r(j-1, i-1)) / (fouri - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return r(order - 1, order - 1);
|
||||
template <typename Callable>
|
||||
auto romberg_diff(Callable& func, double x, std::size_t order = 2, double h = 0.1) {
|
||||
|
||||
// Initialize the table
|
||||
auto r = Eigen::ArrayXd(order, order);
|
||||
|
||||
// Compute the first column using the central difference formula
|
||||
for (auto i = 0; i < order; ++i) {
|
||||
r(i, 0) = (func(x + h) - func(x - h)) / (2 * h);
|
||||
h /= 2.0;
|
||||
}
|
||||
|
||||
// Apply Richardson extrapolation
|
||||
for (auto i = 1; i < order; ++i) {
|
||||
for (auto j = i; j < order; ++j) {
|
||||
double fouri = pow(4, i);
|
||||
r(j, i) = (fouri * r(j, i - 1) - r(j - 1, i - 1)) / (fouri - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return r(order - 1, order - 1);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,8 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "math.h"
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "AbstractState.h"
|
||||
#include "DataStructures.h"
|
||||
#include "Backends/IF97/IF97Backend.h"
|
||||
@@ -62,7 +62,7 @@ class IF97BackendGenerator : public AbstractStateGenerator
|
||||
public:
|
||||
AbstractState* get_AbstractState(const std::vector<std::string>& fluid_names) {
|
||||
if (fluid_names.size() == 1) { // Check that fluid_names[0] has only one component
|
||||
std::string str = fluid_names[0]; // Check that the fluid name is an alias for "Water"
|
||||
const std::string str = fluid_names[0]; // Check that the fluid name is an alias for "Water"
|
||||
if ((upper(str) == "WATER") || (upper(str) == "H2O")) {
|
||||
return new IF97Backend();
|
||||
} else {
|
||||
@@ -146,16 +146,16 @@ AbstractState* AbstractState::factory(const std::string& backend, const std::vec
|
||||
#if !defined(NO_TABULAR_BACKENDS)
|
||||
else if (f1 == TTSE_BACKEND_FAMILY) {
|
||||
// Will throw if there is a problem with this backend
|
||||
shared_ptr<AbstractState> AS(factory(f2, fluid_names));
|
||||
const shared_ptr<AbstractState> AS(factory(f2, fluid_names));
|
||||
return new TTSEBackend(AS);
|
||||
} else if (f1 == BICUBIC_BACKEND_FAMILY) {
|
||||
// Will throw if there is a problem with this backend
|
||||
shared_ptr<AbstractState> AS(factory(f2, fluid_names));
|
||||
const shared_ptr<AbstractState> AS(factory(f2, fluid_names));
|
||||
return new BicubicBackend(AS);
|
||||
}
|
||||
#endif
|
||||
else if (!backend.compare("?") || backend.empty()) {
|
||||
std::size_t idel = fluid_names[0].find("::");
|
||||
else if (backend == "?" || backend.empty()) {
|
||||
const std::size_t idel = fluid_names[0].find("::");
|
||||
// Backend has not been specified, and we have to figure out what the backend is by parsing the string
|
||||
if (idel == std::string::npos) // No '::' found, no backend specified, try HEOS, otherwise a failure
|
||||
{
|
||||
@@ -170,7 +170,7 @@ AbstractState* AbstractState::factory(const std::string& backend, const std::vec
|
||||
throw ValueError(format("Invalid backend name [%s] to factory function", backend.c_str()));
|
||||
}
|
||||
}
|
||||
std::vector<std::string> AbstractState::fluid_names(void) {
|
||||
std::vector<std::string> AbstractState::fluid_names() {
|
||||
return calc_fluid_names();
|
||||
}
|
||||
bool AbstractState::clear_comp_change() {
|
||||
@@ -201,10 +201,10 @@ void AbstractState::mass_to_molar_inputs(CoolProp::input_pairs& input_pair, Cool
|
||||
// Check if a mass based input, convert it to molar units
|
||||
|
||||
switch (input_pair) {
|
||||
case DmassT_INPUTS: ///< Mass density in kg/m^3, Temperature in K
|
||||
//case HmassT_INPUTS: ///< Enthalpy in J/kg, Temperature in K (NOT CURRENTLY IMPLEMENTED)
|
||||
case SmassT_INPUTS: ///< Entropy in J/kg/K, Temperature in K
|
||||
//case TUmass_INPUTS: ///< Temperature in K, Internal energy in J/kg (NOT CURRENTLY IMPLEMENTED)
|
||||
case DmassT_INPUTS: ///< Mass density in kg/m^3, Temperature in K
|
||||
//case HmassT_INPUTS: ///< Enthalpy in J/kg, Temperature in K (NOT CURRENTLY IMPLEMENTED)
|
||||
case SmassT_INPUTS: ///< Entropy in J/kg/K, Temperature in K
|
||||
//case TUmass_INPUTS: ///< Temperature in K, Internal energy in J/kg (NOT CURRENTLY IMPLEMENTED)
|
||||
case DmassP_INPUTS: ///< Mass density in kg/m^3, Pressure in Pa
|
||||
case DmassQ_INPUTS: ///< Mass density in kg/m^3, molar quality
|
||||
case HmassP_INPUTS: ///< Enthalpy in J/kg, Pressure in Pa
|
||||
@@ -220,7 +220,7 @@ void AbstractState::mass_to_molar_inputs(CoolProp::input_pairs& input_pair, Cool
|
||||
molar_mass();
|
||||
|
||||
// Molar mass (just for compactness of the following switch)
|
||||
CoolPropDbl mm = static_cast<CoolPropDbl>(_molar_mass);
|
||||
const auto mm = static_cast<CoolPropDbl>(_molar_mass);
|
||||
|
||||
switch (input_pair) {
|
||||
case DmassT_INPUTS:
|
||||
@@ -472,166 +472,166 @@ double AbstractState::keyed_output(parameters key) {
|
||||
case ifundamental_derivative_of_gas_dynamics:
|
||||
return fundamental_derivative_of_gas_dynamics();
|
||||
case iTau:
|
||||
return _reducing.T/_T;
|
||||
return _reducing.T / _T;
|
||||
case iDelta:
|
||||
return _rhomolar/_reducing.rhomolar;
|
||||
return _rhomolar / _reducing.rhomolar;
|
||||
default:
|
||||
throw ValueError(format("This input [%d: \"%s\"] is not valid for keyed_output", key, get_parameter_information(key, "short").c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
double AbstractState::tau(void) {
|
||||
double AbstractState::tau() {
|
||||
if (!_tau) _tau = calc_reciprocal_reduced_temperature();
|
||||
return _tau;
|
||||
}
|
||||
double AbstractState::delta(void) {
|
||||
double AbstractState::delta() {
|
||||
if (!_delta) _delta = calc_reduced_density();
|
||||
return _delta;
|
||||
}
|
||||
double AbstractState::Tmin(void) {
|
||||
double AbstractState::Tmin() {
|
||||
return calc_Tmin();
|
||||
}
|
||||
double AbstractState::Tmax(void) {
|
||||
double AbstractState::Tmax() {
|
||||
return calc_Tmax();
|
||||
}
|
||||
double AbstractState::Ttriple(void) {
|
||||
double AbstractState::Ttriple() {
|
||||
return calc_Ttriple();
|
||||
}
|
||||
double AbstractState::pmax(void) {
|
||||
double AbstractState::pmax() {
|
||||
return calc_pmax();
|
||||
}
|
||||
double AbstractState::T_critical(void) {
|
||||
double AbstractState::T_critical() {
|
||||
return calc_T_critical();
|
||||
}
|
||||
double AbstractState::T_reducing(void) {
|
||||
double AbstractState::T_reducing() {
|
||||
if (!ValidNumber(_reducing.T)) {
|
||||
calc_reducing_state();
|
||||
}
|
||||
return _reducing.T;
|
||||
}
|
||||
double AbstractState::p_critical(void) {
|
||||
double AbstractState::p_critical() {
|
||||
return calc_p_critical();
|
||||
}
|
||||
double AbstractState::p_triple(void) {
|
||||
double AbstractState::p_triple() {
|
||||
return calc_p_triple();
|
||||
}
|
||||
double AbstractState::rhomolar_critical(void) {
|
||||
double AbstractState::rhomolar_critical() {
|
||||
return calc_rhomolar_critical();
|
||||
}
|
||||
double AbstractState::rhomass_critical(void) {
|
||||
double AbstractState::rhomass_critical() {
|
||||
return calc_rhomolar_critical() * molar_mass();
|
||||
}
|
||||
double AbstractState::rhomolar_reducing(void) {
|
||||
double AbstractState::rhomolar_reducing() {
|
||||
if (!ValidNumber(_reducing.rhomolar)) {
|
||||
calc_reducing_state();
|
||||
}
|
||||
return _reducing.rhomolar;
|
||||
}
|
||||
double AbstractState::rhomass_reducing(void) {
|
||||
double AbstractState::rhomass_reducing() {
|
||||
return rhomolar_reducing() * molar_mass();
|
||||
}
|
||||
double AbstractState::hmolar(void) {
|
||||
double AbstractState::hmolar() {
|
||||
if (!_hmolar) _hmolar = calc_hmolar();
|
||||
return _hmolar;
|
||||
}
|
||||
double AbstractState::hmolar_residual(void) {
|
||||
double AbstractState::hmolar_residual() {
|
||||
if (!_hmolar_residual) _hmolar_residual = calc_hmolar_residual();
|
||||
return _hmolar_residual;
|
||||
}
|
||||
double AbstractState::hmolar_idealgas(void) {
|
||||
return gas_constant()*T()*(1 + tau()*dalpha0_dTau());
|
||||
double AbstractState::hmolar_idealgas() {
|
||||
return gas_constant() * T() * (1 + tau() * dalpha0_dTau());
|
||||
}
|
||||
double AbstractState::hmass_idealgas(void) {
|
||||
return hmolar_idealgas()/molar_mass();
|
||||
double AbstractState::hmass_idealgas() {
|
||||
return hmolar_idealgas() / molar_mass();
|
||||
}
|
||||
double AbstractState::hmolar_excess(void) {
|
||||
double AbstractState::hmolar_excess() {
|
||||
if (!_hmolar_excess) calc_excess_properties();
|
||||
return _hmolar_excess;
|
||||
}
|
||||
double AbstractState::smolar(void) {
|
||||
double AbstractState::smolar() {
|
||||
if (!_smolar) _smolar = calc_smolar();
|
||||
return _smolar;
|
||||
}
|
||||
double AbstractState::smolar_residual(void) {
|
||||
double AbstractState::smolar_residual() {
|
||||
if (!_smolar_residual) _smolar_residual = calc_smolar_residual();
|
||||
return _smolar_residual;
|
||||
}
|
||||
double AbstractState::smolar_idealgas(void) {
|
||||
return gas_constant()*(tau()*dalpha0_dTau() - alpha0());
|
||||
double AbstractState::smolar_idealgas() {
|
||||
return gas_constant() * (tau() * dalpha0_dTau() - alpha0());
|
||||
}
|
||||
double AbstractState::smass_idealgas(void) {
|
||||
return smolar_idealgas()/molar_mass();
|
||||
double AbstractState::smass_idealgas() {
|
||||
return smolar_idealgas() / molar_mass();
|
||||
}
|
||||
double AbstractState::neff(void) {
|
||||
double tau = calc_T_reducing()/_T;
|
||||
double delta = _rhomolar/calc_rhomolar_reducing();
|
||||
double Ar01 = delta*dalphar_dDelta();
|
||||
double Ar11 = tau*delta*d2alphar_dDelta_dTau();
|
||||
double Ar20 = tau*tau*d2alphar_dTau2();
|
||||
return -3.0*(Ar01-Ar11)/Ar20;
|
||||
double AbstractState::neff() {
|
||||
const double tau = calc_T_reducing() / _T;
|
||||
const double delta = _rhomolar / calc_rhomolar_reducing();
|
||||
const double Ar01 = delta * dalphar_dDelta();
|
||||
const double Ar11 = tau * delta * d2alphar_dDelta_dTau();
|
||||
const double Ar20 = tau * tau * d2alphar_dTau2();
|
||||
return -3.0 * (Ar01 - Ar11) / Ar20;
|
||||
}
|
||||
double AbstractState::smolar_excess(void) {
|
||||
double AbstractState::smolar_excess() {
|
||||
if (!_smolar_excess) calc_excess_properties();
|
||||
return _smolar_excess;
|
||||
}
|
||||
double AbstractState::umolar(void) {
|
||||
double AbstractState::umolar() {
|
||||
if (!_umolar) _umolar = calc_umolar();
|
||||
return _umolar;
|
||||
}
|
||||
double AbstractState::umolar_excess(void) {
|
||||
double AbstractState::umolar_excess() {
|
||||
if (!_umolar_excess) calc_excess_properties();
|
||||
return _umolar_excess;
|
||||
}
|
||||
double AbstractState::umolar_idealgas(void) {
|
||||
return gas_constant()*T()*(tau()*dalpha0_dTau());
|
||||
double AbstractState::umolar_idealgas() {
|
||||
return gas_constant() * T() * (tau() * dalpha0_dTau());
|
||||
}
|
||||
double AbstractState::umass_idealgas(void) {
|
||||
return umolar_idealgas()/molar_mass();
|
||||
double AbstractState::umass_idealgas() {
|
||||
return umolar_idealgas() / molar_mass();
|
||||
}
|
||||
double AbstractState::gibbsmolar(void) {
|
||||
double AbstractState::gibbsmolar() {
|
||||
if (!_gibbsmolar) _gibbsmolar = calc_gibbsmolar();
|
||||
return _gibbsmolar;
|
||||
}
|
||||
double AbstractState::gibbsmolar_residual(void) {
|
||||
double AbstractState::gibbsmolar_residual() {
|
||||
if (!_gibbsmolar_residual) _gibbsmolar_residual = calc_gibbsmolar_residual();
|
||||
return _gibbsmolar_residual;
|
||||
}
|
||||
double AbstractState::gibbsmolar_excess(void) {
|
||||
double AbstractState::gibbsmolar_excess() {
|
||||
if (!_gibbsmolar_excess) calc_excess_properties();
|
||||
return _gibbsmolar_excess;
|
||||
}
|
||||
double AbstractState::helmholtzmolar(void) {
|
||||
double AbstractState::helmholtzmolar() {
|
||||
if (!_helmholtzmolar) _helmholtzmolar = calc_helmholtzmolar();
|
||||
return _helmholtzmolar;
|
||||
}
|
||||
double AbstractState::helmholtzmolar_excess(void) {
|
||||
double AbstractState::helmholtzmolar_excess() {
|
||||
if (!_helmholtzmolar_excess) calc_excess_properties();
|
||||
return _helmholtzmolar_excess;
|
||||
}
|
||||
double AbstractState::volumemolar_excess(void) {
|
||||
double AbstractState::volumemolar_excess() {
|
||||
if (!_volumemolar_excess) calc_excess_properties();
|
||||
return _volumemolar_excess;
|
||||
}
|
||||
double AbstractState::cpmolar(void) {
|
||||
double AbstractState::cpmolar() {
|
||||
if (!_cpmolar) _cpmolar = calc_cpmolar();
|
||||
return _cpmolar;
|
||||
}
|
||||
double AbstractState::cp0molar(void) {
|
||||
double AbstractState::cp0molar() {
|
||||
return calc_cpmolar_idealgas();
|
||||
}
|
||||
double AbstractState::cvmolar(void) {
|
||||
double AbstractState::cvmolar() {
|
||||
if (!_cvmolar) _cvmolar = calc_cvmolar();
|
||||
return _cvmolar;
|
||||
}
|
||||
double AbstractState::speed_sound(void) {
|
||||
double AbstractState::speed_sound() {
|
||||
if (!_speed_sound) _speed_sound = calc_speed_sound();
|
||||
return _speed_sound;
|
||||
}
|
||||
double AbstractState::viscosity(void) {
|
||||
double AbstractState::viscosity() {
|
||||
if (!_viscosity) _viscosity = calc_viscosity();
|
||||
return _viscosity;
|
||||
}
|
||||
double AbstractState::conductivity(void) {
|
||||
double AbstractState::conductivity() {
|
||||
if (!_conductivity) _conductivity = calc_conductivity();
|
||||
return _conductivity;
|
||||
}
|
||||
@@ -644,15 +644,15 @@ double AbstractState::acentric_factor() {
|
||||
double AbstractState::saturation_ancillary(parameters param, int Q, parameters given, double value) {
|
||||
return calc_saturation_ancillary(param, Q, given, value);
|
||||
}
|
||||
double AbstractState::surface_tension(void) {
|
||||
double AbstractState::surface_tension() {
|
||||
if (!_surface_tension) _surface_tension = calc_surface_tension();
|
||||
return _surface_tension;
|
||||
}
|
||||
double AbstractState::molar_mass(void) {
|
||||
double AbstractState::molar_mass() {
|
||||
if (!_molar_mass) _molar_mass = calc_molar_mass();
|
||||
return _molar_mass;
|
||||
}
|
||||
double AbstractState::gas_constant(void) {
|
||||
double AbstractState::gas_constant() {
|
||||
if (!_gas_constant) _gas_constant = calc_gas_constant();
|
||||
return _gas_constant;
|
||||
}
|
||||
@@ -675,28 +675,28 @@ double AbstractState::chemical_potential(std::size_t i) {
|
||||
void AbstractState::build_phase_envelope(const std::string& type) {
|
||||
calc_phase_envelope(type);
|
||||
}
|
||||
double AbstractState::isothermal_compressibility(void) {
|
||||
double AbstractState::isothermal_compressibility() {
|
||||
return 1.0 / _rhomolar * first_partial_deriv(iDmolar, iP, iT);
|
||||
}
|
||||
double AbstractState::isobaric_expansion_coefficient(void) {
|
||||
double AbstractState::isobaric_expansion_coefficient() {
|
||||
return -1.0 / _rhomolar * first_partial_deriv(iDmolar, iT, iP);
|
||||
}
|
||||
double AbstractState::isentropic_expansion_coefficient(void) {
|
||||
double AbstractState::isentropic_expansion_coefficient() {
|
||||
return _rhomolar / _p * first_partial_deriv(iP, iDmolar, iSmolar);
|
||||
}
|
||||
double AbstractState::Bvirial(void) {
|
||||
double AbstractState::Bvirial() {
|
||||
return calc_Bvirial();
|
||||
}
|
||||
double AbstractState::Cvirial(void) {
|
||||
double AbstractState::Cvirial() {
|
||||
return calc_Cvirial();
|
||||
}
|
||||
double AbstractState::dBvirial_dT(void) {
|
||||
double AbstractState::dBvirial_dT() {
|
||||
return calc_dBvirial_dT();
|
||||
}
|
||||
double AbstractState::dCvirial_dT(void) {
|
||||
double AbstractState::dCvirial_dT() {
|
||||
return calc_dCvirial_dT();
|
||||
}
|
||||
double AbstractState::compressibility_factor(void) {
|
||||
double AbstractState::compressibility_factor() {
|
||||
return calc_compressibility_factor();
|
||||
}
|
||||
|
||||
@@ -707,7 +707,7 @@ double AbstractState::fundamental_derivative_of_gas_dynamics() {
|
||||
|
||||
// Get the derivatives of the parameters in the partial derivative with respect to T and rho
|
||||
void get_dT_drho(AbstractState& AS, parameters index, CoolPropDbl& dT, CoolPropDbl& drho) {
|
||||
CoolPropDbl T = AS.T(), rho = AS.rhomolar(), rhor = AS.rhomolar_reducing(), Tr = AS.T_reducing(), dT_dtau = -pow(T, 2) / Tr,
|
||||
const CoolPropDbl T = AS.T(), rho = AS.rhomolar(), rhor = AS.rhomolar_reducing(), Tr = AS.T_reducing(), dT_dtau = -pow(T, 2) / Tr,
|
||||
R = AS.gas_constant(), delta = rho / rhor, tau = Tr / T;
|
||||
|
||||
switch (index) {
|
||||
@@ -774,11 +774,11 @@ void get_dT_drho(AbstractState& AS, parameters index, CoolPropDbl& dT, CoolPropD
|
||||
case iGmass:
|
||||
case iGmolar: {
|
||||
// dg/dT|rho
|
||||
double dTau_dT = 1 / dT_dtau;
|
||||
const double dTau_dT = 1 / dT_dtau;
|
||||
dT = R * AS.T() * (AS.dalpha0_dTau() + AS.dalphar_dTau() + AS.delta() * AS.d2alphar_dDelta_dTau()) * dTau_dT
|
||||
+ R * (1 + AS.alpha0() + AS.alphar() + AS.delta() * AS.dalphar_dDelta());
|
||||
// dg/drho|T
|
||||
double dDelta_drho = 1 / rhor;
|
||||
const double dDelta_drho = 1 / rhor;
|
||||
drho = AS.T() * R * (AS.dalpha0_dDelta() + AS.dalphar_dDelta() + AS.delta() * AS.d2alphar_dDelta2() + AS.dalphar_dDelta()) * dDelta_drho;
|
||||
if (index == iGmass) {
|
||||
// dg/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass
|
||||
@@ -852,20 +852,20 @@ void get_dT_drho(AbstractState& AS, parameters index, CoolPropDbl& dT, CoolPropD
|
||||
}
|
||||
case ispeed_sound: {
|
||||
//dwdT
|
||||
double aa = 1.0 + delta * AS.dalphar_dDelta() - delta * tau * AS.d2alphar_dDelta_dTau();
|
||||
double bb = pow(tau, 2) * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2());
|
||||
double daa_dTau = -delta * tau * AS.d3alphar_dDelta_dTau2();
|
||||
double dbb_dTau = pow(tau, 2) * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2.0 * tau * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2());
|
||||
double w = AS.speed_sound();
|
||||
const double aa = 1.0 + delta * AS.dalphar_dDelta() - delta * tau * AS.d2alphar_dDelta_dTau();
|
||||
const double bb = pow(tau, 2) * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2());
|
||||
const double daa_dTau = -delta * tau * AS.d3alphar_dDelta_dTau2();
|
||||
const double dbb_dTau = pow(tau, 2) * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2.0 * tau * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2());
|
||||
const double w = AS.speed_sound();
|
||||
dT = 1.0 / 2.0 / w / T
|
||||
* (pow(w, 2)
|
||||
- R * Tr / AS.molar_mass()
|
||||
* (2.0 * delta * AS.d2alphar_dDelta_dTau() + pow(delta, 2) * AS.d3alphar_dDelta2_dTau()
|
||||
- (2 * aa / bb * daa_dTau - pow(aa / bb, 2) * dbb_dTau)));
|
||||
//dwdrho
|
||||
double daa_dDelta =
|
||||
const double daa_dDelta =
|
||||
AS.dalphar_dDelta() + delta * AS.d2alphar_dDelta2() - tau * (AS.d2alphar_dDelta_dTau() + delta * AS.d3alphar_dDelta2_dTau());
|
||||
double dbb_dDelta = pow(tau, 2) * (AS.d3alpha0_dDelta_dTau2() + AS.d3alphar_dDelta_dTau2());
|
||||
const double dbb_dDelta = pow(tau, 2) * (AS.d3alpha0_dDelta_dTau2() + AS.d3alphar_dDelta_dTau2());
|
||||
drho = R * T / 2.0 / AS.molar_mass() / w / rhor
|
||||
* (2.0 * (AS.dalphar_dDelta() + delta * AS.d2alphar_dDelta2())
|
||||
+ (2.0 * delta * AS.d2alphar_dDelta2() + pow(delta, 2) * AS.d3alphar_dDelta3())
|
||||
@@ -877,7 +877,7 @@ void get_dT_drho(AbstractState& AS, parameters index, CoolPropDbl& dT, CoolPropD
|
||||
}
|
||||
}
|
||||
void get_dT_drho_second_derivatives(AbstractState& AS, int index, CoolPropDbl& dT2, CoolPropDbl& drho_dT, CoolPropDbl& drho2) {
|
||||
CoolPropDbl T = AS.T(), rho = AS.rhomolar(), rhor = AS.rhomolar_reducing(), Tr = AS.T_reducing(), R = AS.gas_constant(), delta = rho / rhor,
|
||||
const CoolPropDbl T = AS.T(), rho = AS.rhomolar(), rhor = AS.rhomolar_reducing(), Tr = AS.T_reducing(), R = AS.gas_constant(), delta = rho / rhor,
|
||||
tau = Tr / T;
|
||||
|
||||
// Here we use T and rho as independent variables since derivations are already done by Thorade, 2013,
|
||||
|
||||
@@ -366,9 +366,9 @@ class SaturationResidual : public CoolProp::FuncWrapper1D
|
||||
double imposed_variable;
|
||||
double deltaL, deltaV;
|
||||
|
||||
SaturationResidual(){};
|
||||
SaturationResidual() {};
|
||||
SaturationResidual(CoolProp::AbstractCubicBackend* ACB, CoolProp::input_pairs inputs, double imposed_variable)
|
||||
: ACB(ACB), inputs(inputs), imposed_variable(imposed_variable){};
|
||||
: ACB(ACB), inputs(inputs), imposed_variable(imposed_variable) {};
|
||||
|
||||
double call(double value) {
|
||||
int Nsolns = 0;
|
||||
|
||||
@@ -95,7 +95,7 @@ class AbstractCubicBackend : public HelmholtzEOSMixtureBackend
|
||||
throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param, "short").c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Return a string from the backend for the mixture/fluid
|
||||
std::string fluid_param_string(const std::string&);
|
||||
/// Calculate the gas constant in J/mol/K
|
||||
@@ -292,7 +292,7 @@ class PengRobinsonBackend : public AbstractCubicBackend
|
||||
{
|
||||
|
||||
public:
|
||||
PengRobinsonBackend(){}; // Default constructor (make sure you know what you are doing)
|
||||
PengRobinsonBackend() {}; // Default constructor (make sure you know what you are doing)
|
||||
PengRobinsonBackend(const std::vector<double>& Tc, const std::vector<double>& pc, const std::vector<double>& acentric, double R_u,
|
||||
bool generate_SatL_and_SatV = true) {
|
||||
cubic.reset(new PengRobinson(Tc, pc, acentric, R_u));
|
||||
@@ -341,7 +341,7 @@ class CubicResidualHelmholtz : public ResidualHelmholtz
|
||||
CubicResidualHelmholtz() {
|
||||
ACB = NULL;
|
||||
};
|
||||
CubicResidualHelmholtz(AbstractCubicBackend* ACB) : ACB(ACB){};
|
||||
CubicResidualHelmholtz(AbstractCubicBackend* ACB) : ACB(ACB) {};
|
||||
|
||||
// copy assignment
|
||||
CubicResidualHelmholtz& operator=(CubicResidualHelmholtz& other) {
|
||||
|
||||
@@ -74,17 +74,17 @@ class CubicsLibraryClass
|
||||
// Add/Replace name->JSONstring mapping to easily pull out if the user wants it
|
||||
// Convert fuid_json to a string and store it in the map.
|
||||
std::pair<std::map<std::string, std::string>::iterator, bool> addJson;
|
||||
addJson = JSONstring_map.insert(std::pair<std::string, std::string>(upper(val.name),cpjson::json2string(*itr)));
|
||||
addJson = JSONstring_map.insert(std::pair<std::string, std::string>(upper(val.name), cpjson::json2string(*itr)));
|
||||
if (addJson.second == false && get_config_bool(OVERWRITE_FLUIDS)) {
|
||||
// Already there, see http://www.cplusplus.com/reference/map/map/insert/
|
||||
JSONstring_map.erase(addJson.first);
|
||||
addJson = JSONstring_map.insert(std::pair<std::string, std::string>(upper(val.name),cpjson::json2string(*itr)));
|
||||
addJson = JSONstring_map.insert(std::pair<std::string, std::string>(upper(val.name), cpjson::json2string(*itr)));
|
||||
if (get_debug_level() > 0) {
|
||||
std::cout << "added the cubic fluid: " + val.name << std::endl;
|
||||
}
|
||||
assert(addJson.second == true);
|
||||
}
|
||||
|
||||
|
||||
counter++;
|
||||
}
|
||||
return counter;
|
||||
@@ -103,7 +103,7 @@ class CubicsLibraryClass
|
||||
} else {
|
||||
throw ValueError(format("Fluid identifier [%s] was not found in CubicsLibrary", uppercase_identifier.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Then, load the fluids we would like to add
|
||||
rapidjson::Document doc;
|
||||
cpjson::JSON_string_to_rapidjson(it->second, doc);
|
||||
|
||||
@@ -25,7 +25,7 @@ struct CubicsValues
|
||||
std::string alpha_type; ///< The type of alpha function
|
||||
std::vector<double> alpha_coeffs; ///< The vector of coefficients for the alpha function
|
||||
IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy
|
||||
CubicsValues() : rhomolarc(-1){};
|
||||
CubicsValues() : rhomolarc(-1) {};
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,13 +25,13 @@ class AbstractCubicAlphaFunction
|
||||
sqrt_Tr_Tci; ///< The sqrt of the (constant) reducing temperature divided by the critical temperature of the pure component
|
||||
std::vector<double> c; ///< The vector of constants
|
||||
public:
|
||||
virtual ~AbstractCubicAlphaFunction(){};
|
||||
virtual ~AbstractCubicAlphaFunction() {};
|
||||
virtual double term(double tau, std::size_t itau) = 0;
|
||||
void set_Tr_over_Tci(double Tr_over_Tci) {
|
||||
this->Tr_over_Tci = Tr_over_Tci;
|
||||
this->sqrt_Tr_Tci = sqrt(Tr_over_Tci);
|
||||
};
|
||||
AbstractCubicAlphaFunction(double a0, double Tr_over_Tci) : a0(a0), Tr_over_Tci(Tr_over_Tci), sqrt_Tr_Tci(sqrt(Tr_over_Tci)){};
|
||||
AbstractCubicAlphaFunction(double a0, double Tr_over_Tci) : a0(a0), Tr_over_Tci(Tr_over_Tci), sqrt_Tr_Tci(sqrt(Tr_over_Tci)) {};
|
||||
};
|
||||
|
||||
/// An implementation of AbstractCubicAlphaFunction for the baseline alpha function of PR or SRK
|
||||
@@ -100,7 +100,7 @@ class AbstractCubic
|
||||
AbstractCubic(std::vector<double> Tc, std::vector<double> pc, std::vector<double> acentric, double R_u, double Delta_1, double Delta_2,
|
||||
std::vector<double> C1 = std::vector<double>(), std::vector<double> C2 = std::vector<double>(),
|
||||
std::vector<double> C3 = std::vector<double>());
|
||||
virtual ~AbstractCubic(){};
|
||||
virtual ~AbstractCubic() {};
|
||||
/// Set the constants for the Mathias-Copeman alpha function, or if C1,C2,C3 are all empty, set the default alpha model
|
||||
void set_alpha(const std::vector<double>& C1, const std::vector<double>& C2, const std::vector<double>& C3);
|
||||
/// Set the alpha function for the i-th component
|
||||
|
||||
@@ -35,7 +35,8 @@ void UNIFAC::UNIFACMixture::set_interaction_parameter(const std::size_t mgi1, co
|
||||
}
|
||||
}
|
||||
double UNIFAC::UNIFACMixture::get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter) {
|
||||
std::map<std::pair<int, int>, UNIFACLibrary::InteractionParameters>::iterator it = this->interaction.find(std::pair<int, int>(static_cast<int>(mgi1), static_cast<int>(mgi2)));
|
||||
std::map<std::pair<int, int>, UNIFACLibrary::InteractionParameters>::iterator it =
|
||||
this->interaction.find(std::pair<int, int>(static_cast<int>(mgi1), static_cast<int>(mgi2)));
|
||||
if (it == this->interaction.end()) {
|
||||
throw CoolProp::ValueError(format("Unable to match mgi-mgi pair: [%d,%d]", static_cast<int>(mgi1), static_cast<int>(mgi1)));
|
||||
} else {
|
||||
|
||||
@@ -51,7 +51,7 @@ class UNIFACMixture
|
||||
std::vector<ComponentData> pure_data;
|
||||
|
||||
public:
|
||||
UNIFACMixture(const UNIFACLibrary::UNIFACParameterLibrary& library, const double T_r) : library(library), T_r(T_r){};
|
||||
UNIFACMixture(const UNIFACLibrary::UNIFACParameterLibrary& library, const double T_r) : library(library), T_r(T_r) {};
|
||||
|
||||
/**
|
||||
* \brief Set all the interaction parameters between groups
|
||||
|
||||
@@ -51,7 +51,7 @@ struct ComponentGroup
|
||||
{
|
||||
int count;
|
||||
UNIFACLibrary::Group group;
|
||||
ComponentGroup(const int count, const UNIFACLibrary::Group group) : count(count), group(group){};
|
||||
ComponentGroup(const int count, const UNIFACLibrary::Group group) : count(count), group(group) {};
|
||||
};
|
||||
|
||||
/// A structure containing the groups and additional information for a component
|
||||
@@ -95,7 +95,7 @@ struct UNIFACParameterLibrary
|
||||
void populate(rapidjson::Value& group_data, rapidjson::Value& interaction_data, rapidjson::Value& decomp_data);
|
||||
|
||||
public:
|
||||
UNIFACParameterLibrary() : m_populated(false){};
|
||||
UNIFACParameterLibrary() : m_populated(false) {};
|
||||
|
||||
/// Return true if library has been populated
|
||||
bool is_populated() {
|
||||
|
||||
@@ -106,13 +106,13 @@ void CoolProp::VTPRBackend::set_binary_interaction_double(const std::size_t i, c
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
}
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
cubic->set_interaction_parameter(i, j, parameter, value);
|
||||
for (std::vector<shared_ptr<HelmholtzEOSMixtureBackend>>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) {
|
||||
(*it)->set_binary_interaction_double(i, j, parameter, value);
|
||||
@@ -127,13 +127,13 @@ double CoolProp::VTPRBackend::get_binary_interaction_double(const std::size_t i,
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
}
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
return cubic->get_interaction_parameter(i, j, parameter);
|
||||
};
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ class VTPRCubic : public PengRobinson
|
||||
public:
|
||||
VTPRCubic(std::vector<double> Tc, std::vector<double> pc, std::vector<double> acentric, double R_u,
|
||||
const UNIFACLibrary::UNIFACParameterLibrary& lib)
|
||||
: PengRobinson(Tc, pc, acentric, R_u), unifaq(lib, T_r){};
|
||||
: PengRobinson(Tc, pc, acentric, R_u), unifaq(lib, T_r) {};
|
||||
|
||||
VTPRCubic(double Tc, double pc, double acentric, double R_u, const UNIFACLibrary::UNIFACParameterLibrary& lib)
|
||||
: PengRobinson(std::vector<double>(1, Tc), std::vector<double>(1, pc), std::vector<double>(1, acentric), R_u), unifaq(lib, T_r){};
|
||||
: PengRobinson(std::vector<double>(1, Tc), std::vector<double>(1, pc), std::vector<double>(1, acentric), R_u), unifaq(lib, T_r) {};
|
||||
|
||||
/// Get a reference to the managed UNIFAC instance
|
||||
UNIFAC::UNIFACMixture& get_unifaq() {
|
||||
|
||||
@@ -20,9 +20,9 @@ typedef std::vector<std::vector<CoolPropDbl>> STLMatrix;
|
||||
class DepartureFunction
|
||||
{
|
||||
public:
|
||||
DepartureFunction(){};
|
||||
DepartureFunction(const ResidualHelmholtzGeneralizedExponential& _phi) : phi(_phi){};
|
||||
virtual ~DepartureFunction(){};
|
||||
DepartureFunction() {};
|
||||
DepartureFunction(const ResidualHelmholtzGeneralizedExponential& _phi) : phi(_phi) {};
|
||||
virtual ~DepartureFunction() {};
|
||||
ResidualHelmholtzGeneralizedExponential phi;
|
||||
HelmholtzDerivatives derivs;
|
||||
|
||||
@@ -104,7 +104,7 @@ class DepartureFunction
|
||||
class GERG2008DepartureFunction : public DepartureFunction
|
||||
{
|
||||
public:
|
||||
GERG2008DepartureFunction(){};
|
||||
GERG2008DepartureFunction() {};
|
||||
GERG2008DepartureFunction(const std::vector<double>& n, const std::vector<double>& d, const std::vector<double>& t,
|
||||
const std::vector<double>& eta, const std::vector<double>& epsilon, const std::vector<double>& beta,
|
||||
const std::vector<double>& gamma, std::size_t Npower) {
|
||||
@@ -128,7 +128,7 @@ class GERG2008DepartureFunction : public DepartureFunction
|
||||
phi.add_GERG2008Gaussian(_n, _d, _t, _eta, _epsilon, _beta, _gamma);
|
||||
}
|
||||
};
|
||||
~GERG2008DepartureFunction(){};
|
||||
~GERG2008DepartureFunction() {};
|
||||
};
|
||||
|
||||
/** \brief A hybrid gaussian with temperature and density dependence along with
|
||||
@@ -142,7 +142,7 @@ class GERG2008DepartureFunction : public DepartureFunction
|
||||
class GaussianExponentialDepartureFunction : public DepartureFunction
|
||||
{
|
||||
public:
|
||||
GaussianExponentialDepartureFunction(){};
|
||||
GaussianExponentialDepartureFunction() {};
|
||||
GaussianExponentialDepartureFunction(const std::vector<double>& n, const std::vector<double>& d, const std::vector<double>& t,
|
||||
const std::vector<double>& l, const std::vector<double>& eta, const std::vector<double>& epsilon,
|
||||
const std::vector<double>& beta, const std::vector<double>& gamma, std::size_t Npower) {
|
||||
@@ -167,7 +167,7 @@ class GaussianExponentialDepartureFunction : public DepartureFunction
|
||||
}
|
||||
phi.finish();
|
||||
};
|
||||
~GaussianExponentialDepartureFunction(){};
|
||||
~GaussianExponentialDepartureFunction() {};
|
||||
};
|
||||
|
||||
/** \brief A polynomial/exponential departure function
|
||||
@@ -181,7 +181,7 @@ class GaussianExponentialDepartureFunction : public DepartureFunction
|
||||
class ExponentialDepartureFunction : public DepartureFunction
|
||||
{
|
||||
public:
|
||||
ExponentialDepartureFunction(){};
|
||||
ExponentialDepartureFunction() {};
|
||||
ExponentialDepartureFunction(const std::vector<double>& n, const std::vector<double>& d, const std::vector<double>& t,
|
||||
const std::vector<double>& l) {
|
||||
std::vector<CoolPropDbl> _n(n.begin(), n.begin() + n.size());
|
||||
@@ -190,7 +190,7 @@ class ExponentialDepartureFunction : public DepartureFunction
|
||||
std::vector<CoolPropDbl> _l(l.begin(), l.begin() + l.size());
|
||||
phi.add_Power(_n, _d, _t, _l);
|
||||
};
|
||||
~ExponentialDepartureFunction(){};
|
||||
~ExponentialDepartureFunction() {};
|
||||
};
|
||||
|
||||
typedef shared_ptr<DepartureFunction> DepartureFunctionPointer;
|
||||
@@ -202,7 +202,7 @@ class ExcessTerm
|
||||
std::vector<std::vector<DepartureFunctionPointer>> DepartureFunctionMatrix;
|
||||
STLMatrix F;
|
||||
|
||||
ExcessTerm() : N(0){};
|
||||
ExcessTerm() : N(0) {};
|
||||
|
||||
// copy assignment
|
||||
ExcessTerm& operator=(ExcessTerm& other) {
|
||||
|
||||
@@ -213,7 +213,7 @@ void FlashRoutines::DP_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
} else {
|
||||
throw ValueError("I should never get here");
|
||||
}
|
||||
if (!std::isfinite(T0)){
|
||||
if (!std::isfinite(T0)) {
|
||||
throw ValueError("Starting value of T0 is not valid in DP_flash");
|
||||
}
|
||||
// Then, do the solver using the full EOS
|
||||
@@ -223,7 +223,7 @@ void FlashRoutines::DP_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
HEOS._Q = -1;
|
||||
// Update the state for conditions where the state was guessed
|
||||
HEOS.recalculate_singlephase_phase();
|
||||
if (!get_config_bool(DONT_CHECK_PROPERTY_LIMITS) && HEOS._T > 1.5*HEOS.Tmax()){
|
||||
if (!get_config_bool(DONT_CHECK_PROPERTY_LIMITS) && HEOS._T > 1.5 * HEOS.Tmax()) {
|
||||
throw CoolProp::OutOfRangeError(format("DP yielded T > 1.5Tmax w/ T (%g) K").c_str());
|
||||
}
|
||||
} else {
|
||||
@@ -242,7 +242,7 @@ class DQ_flash_residual : public FuncWrapper1DWithTwoDerivs
|
||||
public:
|
||||
HelmholtzEOSMixtureBackend& HEOS;
|
||||
double rhomolar, Q_target;
|
||||
DQ_flash_residual(HelmholtzEOSMixtureBackend& HEOS, double rhomolar, double Q_target) : HEOS(HEOS), rhomolar(rhomolar), Q_target(Q_target){};
|
||||
DQ_flash_residual(HelmholtzEOSMixtureBackend& HEOS, double rhomolar, double Q_target) : HEOS(HEOS), rhomolar(rhomolar), Q_target(Q_target) {};
|
||||
double call(double T) {
|
||||
HEOS.update(QT_INPUTS, 0, T); // Doesn't matter whether liquid or vapor, we are just doing a full VLE call for given T
|
||||
double rhoL = HEOS.saturated_liquid_keyed_output(iDmolar);
|
||||
@@ -268,9 +268,10 @@ void FlashRoutines::DQ_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
double Tmin = HEOS.Tmin() + 0.1;
|
||||
double rhomolar = HEOS._rhomolar;
|
||||
double Q = HEOS._Q;
|
||||
const double eps = 1e-12; // small tolerance to allow for slop in iterative calculations
|
||||
if (rhomolar >= (HEOS.rhomolar_critical() + eps) && Q > (0 + eps)){
|
||||
throw CoolProp::OutOfRangeError(format("DQ inputs are not defined for density (%g) above critical density (%g) and Q>0", rhomolar, HEOS.rhomolar_critical()).c_str());
|
||||
const double eps = 1e-12; // small tolerance to allow for slop in iterative calculations
|
||||
if (rhomolar >= (HEOS.rhomolar_critical() + eps) && Q > (0 + eps)) {
|
||||
throw CoolProp::OutOfRangeError(
|
||||
format("DQ inputs are not defined for density (%g) above critical density (%g) and Q>0", rhomolar, HEOS.rhomolar_critical()).c_str());
|
||||
}
|
||||
DQ_flash_residual resid(HEOS, rhomolar, Q);
|
||||
Brent(resid, Tmin, Tmax, DBL_EPSILON, 1e-10, 100);
|
||||
@@ -351,15 +352,16 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
CoolPropDbl T = HEOS._T;
|
||||
CoolPropDbl Q = HEOS._Q;
|
||||
if (HEOS.is_pure_or_pseudopure) {
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()){
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()) {
|
||||
auto& optsuperanc = HEOS.get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
|
||||
|
||||
CoolPropDbl Tcrit_num = superanc.get_Tcrit_num();
|
||||
if (T > Tcrit_num){
|
||||
throw ValueError(format("Temperature to QT_flash [%0.8Lg K] may not be above the numerical critical point of %0.15Lg K", T, Tcrit_num));
|
||||
if (T > Tcrit_num) {
|
||||
throw ValueError(
|
||||
format("Temperature to QT_flash [%0.8Lg K] may not be above the numerical critical point of %0.15Lg K", T, Tcrit_num));
|
||||
}
|
||||
auto rhoL = superanc.eval_sat(T, 'D', 0);
|
||||
auto rhoV = superanc.eval_sat(T, 'D', 1);
|
||||
@@ -372,8 +374,7 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The maximum possible saturation temperature
|
||||
// Critical point for pure fluids, slightly different for pseudo-pure, very different for mixtures
|
||||
CoolPropDbl Tmax_sat = HEOS.calc_Tmax_sat() + 1e-13;
|
||||
@@ -385,7 +386,7 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
|
||||
// Get a reference to keep the code a bit cleaner
|
||||
const CriticalRegionSplines& splines = HEOS.components[0].EOS().critical_region_splines;
|
||||
|
||||
|
||||
if ((get_config_bool(CRITICAL_WITHIN_1UK) && std::abs(T - Tmax_sat) < 1e-6) || std::abs(T - Tmax_sat) < 1e-12) {
|
||||
// If exactly(ish) at the critical temperature, liquid and vapor have the critial density
|
||||
HEOS.SatL->update(DmolarT_INPUTS, HEOS.rhomolar_critical(), HEOS._T);
|
||||
@@ -599,14 +600,15 @@ void get_Henrys_coeffs_FP(const std::string& CAS, double& A, double& B, double&
|
||||
}
|
||||
void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
if (HEOS.is_pure_or_pseudopure) {
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()){
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()) {
|
||||
auto& optsuperanc = HEOS.get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
CoolPropDbl pmax_num = superanc.get_pmax();
|
||||
if (HEOS._p > pmax_num){
|
||||
throw ValueError(format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", HEOS._p, pmax_num));
|
||||
if (HEOS._p > pmax_num) {
|
||||
throw ValueError(
|
||||
format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", HEOS._p, pmax_num));
|
||||
}
|
||||
auto T = superanc.get_T_from_p(HEOS._p);
|
||||
auto rhoL = superanc.eval_sat(T, 'D', 0);
|
||||
@@ -621,7 +623,7 @@ void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (HEOS.components[0].EOS().pseudo_pure) {
|
||||
// It is a pseudo-pure mixture
|
||||
|
||||
@@ -1196,31 +1198,26 @@ void FlashRoutines::HSU_D_flash(HelmholtzEOSMixtureBackend& HEOS, parameters oth
|
||||
optionsD.omega = 1;
|
||||
optionsD.use_logdelta = false;
|
||||
optionsD.max_iterations = 200;
|
||||
for (int i_try = 0; i_try < 7; i_try++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (HEOS._rhomolar > HEOS.rhomolar_critical())
|
||||
{
|
||||
for (int i_try = 0; i_try < 7; i_try++) {
|
||||
try {
|
||||
if (HEOS._rhomolar > HEOS.rhomolar_critical()) {
|
||||
optionsD.imposed_rho = SaturationSolvers::saturation_D_pure_options::IMPOSED_RHOL;
|
||||
SaturationSolvers::saturation_D_pure(HEOS, HEOS._rhomolar, optionsD);
|
||||
// SatL and SatV have the saturation values
|
||||
Sat = HEOS.SatL;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
optionsD.imposed_rho = SaturationSolvers::saturation_D_pure_options::IMPOSED_RHOV;
|
||||
SaturationSolvers::saturation_D_pure(HEOS, HEOS._rhomolar, optionsD);
|
||||
// SatL and SatV have the saturation values
|
||||
Sat = HEOS.SatV;
|
||||
}
|
||||
break; // good solve
|
||||
}
|
||||
catch(CoolPropBaseError)
|
||||
{
|
||||
break; // good solve
|
||||
} catch (CoolPropBaseError) {
|
||||
optionsD.omega /= 2;
|
||||
optionsD.max_iterations *= 2;
|
||||
if (i_try >= 6){throw;}
|
||||
if (i_try >= 6) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1481,7 +1478,8 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
HEOS->specify_phase(phase);
|
||||
default:
|
||||
// Otherwise don't do anything (this is to make compiler happy)
|
||||
{}
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
double call(double T) {
|
||||
@@ -1499,8 +1497,8 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
|
||||
// Store the value of density
|
||||
rhomolar = HEOS->rhomolar();
|
||||
|
||||
if (verbosity > 0 && iter == 0){
|
||||
|
||||
if (verbosity > 0 && iter == 0) {
|
||||
std::cout << format("T: %0.15g rho: %0.15g eos: %0.15g", T, rhomolar, eos);
|
||||
}
|
||||
|
||||
@@ -1535,55 +1533,52 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
}
|
||||
};
|
||||
solver_resid resid(&HEOS, HEOS._p, value, other, Tmin, Tmax);
|
||||
|
||||
class resid_2D : public FuncWrapperND{
|
||||
public:
|
||||
|
||||
class resid_2D : public FuncWrapperND
|
||||
{
|
||||
public:
|
||||
HelmholtzEOSMixtureBackend* HEOS;
|
||||
CoolPropDbl p, value;
|
||||
parameters other;
|
||||
int iter;
|
||||
std::vector<std::vector<double>> J = {{-1.0, -1.0},{-1.0, -1.0}};
|
||||
|
||||
std::vector<std::vector<double>> J = {{-1.0, -1.0}, {-1.0, -1.0}};
|
||||
|
||||
resid_2D(HelmholtzEOSMixtureBackend* HEOS, double p, CoolPropDbl value, parameters other, double Tmin, double Tmax)
|
||||
: HEOS(HEOS),
|
||||
p(p),
|
||||
value(value),
|
||||
other(other),
|
||||
iter(0){}
|
||||
std::vector<double> call(const std::vector<double>&x) override{
|
||||
: HEOS(HEOS), p(p), value(value), other(other), iter(0) {}
|
||||
std::vector<double> call(const std::vector<double>& x) override {
|
||||
double T = x[0], rhomolar = x[1];
|
||||
HEOS->update_DmolarT_direct(rhomolar, T);
|
||||
J[0][0] = HEOS->first_partial_deriv(iP, iT, iDmolar)/p;
|
||||
J[0][1] = HEOS->first_partial_deriv(iP, iDmolar, iT)/p;
|
||||
J[0][0] = HEOS->first_partial_deriv(iP, iT, iDmolar) / p;
|
||||
J[0][1] = HEOS->first_partial_deriv(iP, iDmolar, iT) / p;
|
||||
J[1][0] = HEOS->first_partial_deriv(other, iT, iDmolar);
|
||||
J[1][1] = HEOS->first_partial_deriv(other, iDmolar, iT);
|
||||
|
||||
return {(HEOS->p()-p)/p, HEOS->keyed_output(other) - value};
|
||||
|
||||
return {(HEOS->p() - p) / p, HEOS->keyed_output(other) - value};
|
||||
}
|
||||
std::vector<std::vector<double>> Jacobian(const std::vector<double>&/*x*/) override{
|
||||
std::vector<std::vector<double>> Jacobian(const std::vector<double>& /*x*/) override {
|
||||
// pre-calculated in call function
|
||||
return J;
|
||||
}
|
||||
};
|
||||
resid_2D solver_resid2d(&HEOS, HEOS._p, value, other, Tmin, Tmax);
|
||||
|
||||
|
||||
// Get residual values at the bounds
|
||||
double resid_Tmin = resid.call(Tmin);
|
||||
double rhomolar_Tmin = HEOS.rhomolar();
|
||||
|
||||
|
||||
double resid_Tmax = resid.call(Tmax);
|
||||
double rhomolar_Tmax = HEOS.rhomolar();
|
||||
|
||||
|
||||
// For the derivative-based methods, figure out which point to start from
|
||||
bool use_min = std::abs(resid_Tmin) < std::abs(resid_Tmax);
|
||||
double Tstart = use_min ? Tmin : Tmax;
|
||||
double rhomolarstart = use_min ? rhomolar_Tmin : rhomolar_Tmax;
|
||||
|
||||
try {
|
||||
if (get_debug_level() > 0){
|
||||
if (get_debug_level() > 0) {
|
||||
resid.verbosity = 1;
|
||||
}
|
||||
if (resid_Tmin*resid_Tmax < 0){
|
||||
if (resid_Tmin * resid_Tmax < 0) {
|
||||
// The residual values bound zero, use the TOMS748 method (no derivatives)
|
||||
// See: https://www.boost.org/doc/libs/1_58_0/libs/math/doc/html/math_toolkit/internals1/roots2.html#math_toolkit.internals1.roots2.algorithm_toms_748_alefeld_potra
|
||||
//
|
||||
@@ -1592,8 +1587,8 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
// and higher-order methods
|
||||
resid.iter = 0;
|
||||
boost::math::uintmax_t max_iter = 100;
|
||||
|
||||
auto f = [&resid](const double T){ return resid.call(T); };
|
||||
|
||||
auto f = [&resid](const double T) { return resid.call(T); };
|
||||
// Want 44 bits to be correct, tolerance is 2^(1-bits) ::
|
||||
// >>> 2**(1-44)
|
||||
// 1.1368683772161603e-13
|
||||
@@ -1601,12 +1596,11 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
if (!is_in_closed_range(Tmin, Tmax, static_cast<CoolPropDbl>(resid.HEOS->T()))) {
|
||||
throw ValueError(format("TOMS748 method yielded out of bound T of %g", static_cast<CoolPropDbl>(resid.HEOS->T())));
|
||||
}
|
||||
|
||||
|
||||
// Un-specify the phase of the fluid
|
||||
HEOS.unspecify_phase();
|
||||
HEOS.recalculate_singlephase_phase();
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
resid.iter = 0;
|
||||
Halley(resid, Tstart, 1e-12, 100);
|
||||
if (!is_in_closed_range(Tmin, Tmax, static_cast<CoolPropDbl>(resid.HEOS->T())) || resid.HEOS->phase() != phase) {
|
||||
@@ -1617,12 +1611,12 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
HEOS.recalculate_singlephase_phase();
|
||||
}
|
||||
} catch (...) {
|
||||
try{
|
||||
try {
|
||||
double p_critical_ = HEOS.p_critical();
|
||||
if (0.95*p_critical_ > HEOS._p || HEOS._p > p_critical_){
|
||||
if (0.95 * p_critical_ > HEOS._p || HEOS._p > p_critical_) {
|
||||
throw;
|
||||
}
|
||||
if (get_debug_level() > 0){
|
||||
if (get_debug_level() > 0) {
|
||||
std::cout << resid.errstring << std::endl;
|
||||
}
|
||||
std::vector<double> x0 = {Tstart, rhomolarstart};
|
||||
@@ -1633,14 +1627,13 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
// Un-specify the phase of the fluid
|
||||
HEOS.unspecify_phase();
|
||||
HEOS.recalculate_singlephase_phase();
|
||||
}
|
||||
catch(...){
|
||||
if (get_debug_level() > 0){
|
||||
} catch (...) {
|
||||
if (get_debug_level() > 0) {
|
||||
std::cout << resid.errstring << std::endl;
|
||||
}
|
||||
// Un-specify the phase of the fluid
|
||||
HEOS.unspecify_phase();
|
||||
|
||||
|
||||
// Determine why you were out of range if you can
|
||||
//
|
||||
CoolPropDbl eos0 = resid.eos0, eos1 = resid.eos1;
|
||||
@@ -1648,13 +1641,13 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HE
|
||||
std::string units = get_parameter_information(other, "units");
|
||||
if (eos1 > eos0 && value > eos1) {
|
||||
throw ValueError(
|
||||
format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is above the maximum value of %0.12Lg %s",
|
||||
name.c_str(), value, units.c_str(), eos1, units.c_str()));
|
||||
format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is above the maximum value of %0.12Lg %s",
|
||||
name.c_str(), value, units.c_str(), eos1, units.c_str()));
|
||||
}
|
||||
if (eos1 > eos0 && value < eos0) {
|
||||
throw ValueError(
|
||||
format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is below the minimum value of %0.12Lg %s",
|
||||
name.c_str(), value, units.c_str(), eos0, units.c_str()));
|
||||
format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is below the minimum value of %0.12Lg %s",
|
||||
name.c_str(), value, units.c_str(), eos0, units.c_str()));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
@@ -1695,14 +1688,16 @@ void FlashRoutines::HSU_P_flash(HelmholtzEOSMixtureBackend& HEOS, parameters oth
|
||||
if (HEOS._p < HEOS.p_triple()) {
|
||||
Tmin = std::max(HEOS.Tmin(), HEOS.Ttriple());
|
||||
} else {
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()){
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()) {
|
||||
auto& optsuperanc = HEOS.get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
CoolPropDbl pmax_num = superanc.get_pmax();
|
||||
if (HEOS._p > pmax_num){
|
||||
throw ValueError(format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", HEOS._p, pmax_num));
|
||||
if (HEOS._p > pmax_num) {
|
||||
throw ValueError(
|
||||
format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", HEOS._p,
|
||||
pmax_num));
|
||||
}
|
||||
Tmin = superanc.get_T_from_p(HEOS._p);
|
||||
break;
|
||||
@@ -1717,34 +1712,34 @@ void FlashRoutines::HSU_P_flash(HelmholtzEOSMixtureBackend& HEOS, parameters oth
|
||||
break;
|
||||
}
|
||||
case iphase_liquid: {
|
||||
|
||||
|
||||
// Sometimes the minimum pressure for the melting line is a bit above the triple point pressure
|
||||
if (HEOS.has_melting_line() && HEOS._p > HEOS.calc_melting_line(iP_min, -1, -1)) {
|
||||
Tmin = HEOS.calc_melting_line(iT, iP, HEOS._p) - 1e-3;
|
||||
} else {
|
||||
Tmin = HEOS.Tmin() - 1e-3;
|
||||
}
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()){
|
||||
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && HEOS.is_pure()) {
|
||||
auto& optsuperanc = HEOS.get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
CoolPropDbl pmax_num = superanc.get_pmax();
|
||||
if (HEOS._p > pmax_num){
|
||||
throw ValueError(format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", HEOS._p, pmax_num));
|
||||
if (HEOS._p > pmax_num) {
|
||||
throw ValueError(format(
|
||||
"Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", HEOS._p, pmax_num));
|
||||
}
|
||||
Tmax = superanc.get_T_from_p(HEOS._p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (saturation_called) {
|
||||
Tmax = HEOS.SatL->T();
|
||||
} else {
|
||||
Tmax = HEOS._TLanc.pt() + 0.01;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case iphase_supercritical_liquid:
|
||||
@@ -1817,7 +1812,7 @@ void FlashRoutines::solver_for_rho_given_T_oneof_HSU(HelmholtzEOSMixtureBackend&
|
||||
}
|
||||
};
|
||||
solver_resid resid(&HEOS, T, value, other);
|
||||
|
||||
|
||||
double T_critical_ = (HEOS.is_pure_or_pseudopure) ? HEOS.T_critical() : HEOS._crit.T;
|
||||
|
||||
// Supercritical temperature
|
||||
@@ -1945,7 +1940,7 @@ void FlashRoutines::DHSU_T_flash(HelmholtzEOSMixtureBackend& HEOS, parameters ot
|
||||
if (HEOS.imposed_phase_index != iphase_not_imposed) {
|
||||
// Use the phase defined by the imposed phase
|
||||
HEOS._phase = HEOS.imposed_phase_index;
|
||||
double T_critical_ = (HEOS.is_pure_or_pseudopure) ? HEOS.T_critical() : HEOS._crit.T ;
|
||||
double T_critical_ = (HEOS.is_pure_or_pseudopure) ? HEOS.T_critical() : HEOS._crit.T;
|
||||
// The remaining code in this branch was added to set some needed parameters if phase is imposed,
|
||||
// since HEOS.T_phase_determination_pure_or_pseudopure() is not being called.
|
||||
if (HEOS._T < T_critical_) //
|
||||
@@ -2070,7 +2065,7 @@ void FlashRoutines::HS_flash_twophase(HelmholtzEOSMixtureBackend& HEOS, CoolProp
|
||||
HelmholtzEOSMixtureBackend& HEOS;
|
||||
CoolPropDbl hmolar, smolar, Qs;
|
||||
Residual(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec)
|
||||
: HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec), Qs(_HUGE){};
|
||||
: HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec), Qs(_HUGE) {};
|
||||
double call(double T) {
|
||||
HEOS.update(QT_INPUTS, 0, T);
|
||||
HelmholtzEOSMixtureBackend &SatL = HEOS.get_SatL(), &SatV = HEOS.get_SatV();
|
||||
@@ -2161,7 +2156,7 @@ void FlashRoutines::HS_flash(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
HelmholtzEOSMixtureBackend& HEOS;
|
||||
CoolPropDbl hmolar, smolar;
|
||||
Residual(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec)
|
||||
: HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec){};
|
||||
: HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec) {};
|
||||
double call(double T) {
|
||||
HEOS.update(SmolarT_INPUTS, smolar, T);
|
||||
double r = HEOS.hmolar() - hmolar;
|
||||
@@ -2284,10 +2279,9 @@ TEST_CASE("Test critical points for nitrogen + ethane with HEOS", "[critical_poi
|
||||
HEOS->set_mole_fractions(z);
|
||||
CAPTURE(z0);
|
||||
std::vector<CriticalState> pts;
|
||||
try{
|
||||
try {
|
||||
pts = HEOS->all_critical_points();
|
||||
}
|
||||
catch(std::exception& e){
|
||||
} catch (std::exception& e) {
|
||||
CAPTURE(e.what());
|
||||
failure_count++;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ double SaturationAncillaryFunction::invert(double value, double min_bound, doubl
|
||||
// because then you get (negative number)^(double) which is undefined.
|
||||
return Brent(resid, min_bound, max_bound, DBL_EPSILON, 1e-10, 100);
|
||||
} catch (...) {
|
||||
return ExtrapolatingSecant(resid,max_bound, -0.01, 1e-12, 100);
|
||||
return ExtrapolatingSecant(resid, max_bound, -0.01, 1e-12, 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value)
|
||||
public:
|
||||
MeltingLinePiecewisePolynomialInTrSegment* part;
|
||||
CoolPropDbl given_p;
|
||||
solver_resid(MeltingLinePiecewisePolynomialInTrSegment* part, CoolPropDbl p) : part(part), given_p(p){};
|
||||
solver_resid(MeltingLinePiecewisePolynomialInTrSegment* part, CoolPropDbl p) : part(part), given_p(p) {};
|
||||
double call(double T) {
|
||||
|
||||
CoolPropDbl calc_p = part->evaluate(T);
|
||||
@@ -233,7 +233,7 @@ CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value)
|
||||
public:
|
||||
MeltingLinePiecewisePolynomialInThetaSegment* part;
|
||||
CoolPropDbl given_p;
|
||||
solver_resid(MeltingLinePiecewisePolynomialInThetaSegment* part, CoolPropDbl p) : part(part), given_p(p){};
|
||||
solver_resid(MeltingLinePiecewisePolynomialInThetaSegment* part, CoolPropDbl p) : part(part), given_p(p) {};
|
||||
double call(double T) {
|
||||
|
||||
CoolPropDbl calc_p = part->evaluate(T);
|
||||
@@ -345,11 +345,11 @@ TEST_CASE("Tests for values from melting lines", "[melting]") {
|
||||
double actual_T = -_HUGE;
|
||||
double EOS_pmax = AS->pmax();
|
||||
double T_pmax_required = -1;
|
||||
try{
|
||||
try {
|
||||
CoolProp::set_config_bool(DONT_CHECK_PROPERTY_LIMITS, true);
|
||||
T_pmax_required = AS->melting_line(iT, iP, EOS_pmax);
|
||||
} catch (...) {
|
||||
}
|
||||
catch(...){}
|
||||
CoolProp::set_config_bool(DONT_CHECK_PROPERTY_LIMITS, false);
|
||||
CAPTURE(T_pmax_required);
|
||||
CAPTURE(EOS_pmax);
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
# include "all_fluids_JSON_z.h"
|
||||
# undef INCBIN_CONST
|
||||
# undef INCBIN_ALIGN
|
||||
#else
|
||||
#include "incbin.h"
|
||||
// Use the magic of the incbin library to include binary data in compressed form
|
||||
#if defined(_MSC_VER)
|
||||
#include "all_fluids_JSON_z.h"
|
||||
#else
|
||||
# include "incbin.h"
|
||||
// Use the magic of the incbin library to include binary data in compressed form
|
||||
# if defined(_MSC_VER)
|
||||
# include "all_fluids_JSON_z.h"
|
||||
# else
|
||||
|
||||
INCBIN(all_fluids_JSON_z, "all_fluids.json.z");
|
||||
#endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace CoolProp {
|
||||
@@ -33,9 +33,11 @@ void load() {
|
||||
if (code != 0) {
|
||||
throw ValueError("Unable to uncompress the fluid data from z compressed form");
|
||||
}
|
||||
|
||||
if (getenv("COOLPROP_DISABLE_SUPERANCILLARIES_ENTIRELY")){
|
||||
std::cout << "CoolProp: superancillaries have been disabled because the COOLPROP_DISABLE_SUPERANCILLARIES_ENTIRELY environment variable has been defined" << std::endl;
|
||||
|
||||
if (getenv("COOLPROP_DISABLE_SUPERANCILLARIES_ENTIRELY")) {
|
||||
std::cout << "CoolProp: superancillaries have been disabled because the COOLPROP_DISABLE_SUPERANCILLARIES_ENTIRELY environment variable has "
|
||||
"been defined"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
rapidjson::Document dd;
|
||||
|
||||
@@ -127,14 +127,14 @@ class JSONFluidLibrary
|
||||
std::vector<CoolPropDbl> lt = cpjson::get_long_double_array(contribution["lt"]);
|
||||
std::vector<CoolPropDbl> gd = cpjson::get_long_double_array(contribution["gd"]);
|
||||
std::vector<CoolPropDbl> ld = cpjson::get_long_double_array(contribution["ld"]);
|
||||
|
||||
|
||||
assert(n.size() == d.size());
|
||||
assert(n.size() == t.size());
|
||||
assert(n.size() == gt.size());
|
||||
assert(n.size() == lt.size());
|
||||
assert(n.size() == gd.size());
|
||||
assert(n.size() == ld.size());
|
||||
alphar.GenExp.add_DoubleExponential(n,d,t,gd,ld,gt,lt);
|
||||
alphar.GenExp.add_DoubleExponential(n, d, t, gd, ld, gt, lt);
|
||||
} else if (!type.compare("ResidualHelmholtzExponential")) {
|
||||
std::vector<CoolPropDbl> n = cpjson::get_long_double_array(contribution["n"]);
|
||||
std::vector<CoolPropDbl> d = cpjson::get_long_double_array(contribution["d"]);
|
||||
@@ -391,11 +391,10 @@ class JSONFluidLibrary
|
||||
// BibTex keys
|
||||
EOS.BibTeX_EOS = cpjson::get_string(EOS_json, "BibTeX_EOS");
|
||||
EOS.BibTeX_CP0 = cpjson::get_string(EOS_json, "BibTeX_CP0");
|
||||
|
||||
if (EOS_json.HasMember("SUPERANCILLARY")){
|
||||
if (getenv("COOLPROP_DISABLE_SUPERANCILLARIES_ENTIRELY")){
|
||||
}
|
||||
else{
|
||||
|
||||
if (EOS_json.HasMember("SUPERANCILLARY")) {
|
||||
if (getenv("COOLPROP_DISABLE_SUPERANCILLARIES_ENTIRELY")) {
|
||||
} else {
|
||||
// This is inefficient as we do JSON(rapidjson) -> string -> JSON(nlohmann)
|
||||
// which implies two large parsing passes
|
||||
EOS.set_superancillaries_str(cpjson::json2string(EOS_json["SUPERANCILLARY"]));
|
||||
@@ -806,8 +805,7 @@ class JSONFluidLibrary
|
||||
if (!target.compare("CO2")) {
|
||||
fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2;
|
||||
return;
|
||||
}
|
||||
else if (!target.compare("CarbonDioxideHuberJPCRD2016")) {
|
||||
} else if (!target.compare("CarbonDioxideHuberJPCRD2016")) {
|
||||
fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2_HUBER_JPCRD_2016;
|
||||
return;
|
||||
} else if (!target.compare("Ethane")) {
|
||||
|
||||
@@ -30,7 +30,7 @@ inline std::string vecstring_to_string(const std::vector<std::string>& a) {
|
||||
class HelmholtzEOSBackend : public HelmholtzEOSMixtureBackend
|
||||
{
|
||||
public:
|
||||
HelmholtzEOSBackend(){};
|
||||
HelmholtzEOSBackend() {};
|
||||
HelmholtzEOSBackend(CoolPropFluid Fluid) {
|
||||
set_components(std::vector<CoolPropFluid>(1, Fluid));
|
||||
};
|
||||
@@ -61,7 +61,7 @@ class HelmholtzEOSBackend : public HelmholtzEOSMixtureBackend
|
||||
std::cout << "successfully set up state" << std::endl;
|
||||
}
|
||||
};
|
||||
virtual ~HelmholtzEOSBackend(){};
|
||||
virtual ~HelmholtzEOSBackend() {};
|
||||
std::string backend_name(void) {
|
||||
return get_backend_string(HEOS_BACKEND_PURE);
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@ void HelmholtzEOSMixtureBackend::set_mole_fractions(const std::vector<CoolPropDb
|
||||
throw ValueError(format("size of mole fraction vector [%d] does not equal that of component vector [%d]", mf.size(), N));
|
||||
}
|
||||
// Copy values without reallocating memory
|
||||
this->mole_fractions = mf; // Most effective copy
|
||||
this->resize(N); // No reallocation of this->mole_fractions happens
|
||||
this->mole_fractions = mf; // Most effective copy
|
||||
this->resize(N); // No reallocation of this->mole_fractions happens
|
||||
clear_comp_change();
|
||||
};
|
||||
void HelmholtzEOSMixtureBackend::sync_linked_states(const HelmholtzEOSMixtureBackend* const source) {
|
||||
@@ -263,39 +263,34 @@ std::string HelmholtzEOSMixtureBackend::fluid_param_string(const std::string& Pa
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<EquationOfState::SuperAncillary_t>& HelmholtzEOSMixtureBackend::get_superanc_optional(){
|
||||
if (!is_pure()){
|
||||
std::optional<EquationOfState::SuperAncillary_t>& HelmholtzEOSMixtureBackend::get_superanc_optional() {
|
||||
if (!is_pure()) {
|
||||
throw CoolProp::ValueError("Only available for pure (and not pseudo-pure) fluids");
|
||||
}
|
||||
return components[0].EOS().get_superanc_optional();
|
||||
}
|
||||
|
||||
double HelmholtzEOSMixtureBackend::get_fluid_parameter_double(const size_t i, const std::string& parameter){
|
||||
double HelmholtzEOSMixtureBackend::get_fluid_parameter_double(const size_t i, const std::string& parameter) {
|
||||
if (i >= N) {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
if (parameter.find("SUPERANC::") == 0){
|
||||
if (parameter.find("SUPERANC::") == 0) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
std::string key = parameter.substr(10);
|
||||
if (key == "pmax"){
|
||||
if (key == "pmax") {
|
||||
return superanc.get_pmax();
|
||||
}
|
||||
else if (key == "pmin"){
|
||||
} else if (key == "pmin") {
|
||||
return superanc.get_pmin();
|
||||
}
|
||||
else if (key == "Tmin"){
|
||||
} else if (key == "Tmin") {
|
||||
return superanc.get_Tmin();
|
||||
}
|
||||
else if (key == "Tcrit_num"){
|
||||
} else if (key == "Tcrit_num") {
|
||||
return superanc.get_Tcrit_num();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw ValueError(format("Superancillary parameter [%s] is invalid", key.c_str()));
|
||||
}
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
throw ValueError(format("Superancillary not available for this fluid"));
|
||||
}
|
||||
} else {
|
||||
@@ -303,17 +298,16 @@ double HelmholtzEOSMixtureBackend::get_fluid_parameter_double(const size_t i, co
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HelmholtzEOSMixtureBackend::apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string& model) {
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
if (model == "linear") {
|
||||
double Tc1 = get_fluid_constant(i, iT_critical), Tc2 = get_fluid_constant(j, iT_critical);
|
||||
@@ -339,12 +333,12 @@ void HelmholtzEOSMixtureBackend::set_binary_interaction_double(const std::size_t
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
if (parameter == "Fij") {
|
||||
residual_helmholtz->Excess.F[i][j] = value;
|
||||
@@ -362,12 +356,12 @@ double HelmholtzEOSMixtureBackend::get_binary_interaction_double(const std::size
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
if (parameter == "Fij") {
|
||||
return residual_helmholtz->Excess.F[i][j];
|
||||
@@ -385,12 +379,12 @@ void HelmholtzEOSMixtureBackend::set_binary_interaction_string(const std::size_t
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
if (parameter == "function") {
|
||||
residual_helmholtz->Excess.DepartureFunctionMatrix[i][j].reset(get_departure_function(value));
|
||||
@@ -653,7 +647,7 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_background(CoolPropDbl et
|
||||
case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_RAINWATER_FRIEND: {
|
||||
CoolPropDbl B_eta_initial = TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend(*this);
|
||||
CoolPropDbl rho = rhomolar();
|
||||
initial_density = eta_dilute * B_eta_initial * rho; //TODO: Check units once AMTG
|
||||
initial_density = eta_dilute * B_eta_initial * rho; //TODO: Check units once AMTG
|
||||
break;
|
||||
}
|
||||
case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_EMPIRICAL: {
|
||||
@@ -1087,10 +1081,10 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_T_critical(void) {
|
||||
throw ValueError(format("critical point finding routine found %d critical points", critpts.size()));
|
||||
}
|
||||
} else {
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()){
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()) {
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
return optsuperanc.value().get_Tcrit_num(); // from the numerical critical point satisfying dp/drho|T = d2p/drho2|T = 0
|
||||
if (optsuperanc) {
|
||||
return optsuperanc.value().get_Tcrit_num(); // from the numerical critical point satisfying dp/drho|T = d2p/drho2|T = 0
|
||||
}
|
||||
}
|
||||
return components[0].crit.T;
|
||||
@@ -1106,10 +1100,10 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_p_critical(void) {
|
||||
throw ValueError(format("critical point finding routine found %d critical points", critpts.size()));
|
||||
}
|
||||
} else {
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()){
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()) {
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
return optsuperanc.value().get_pmax(); // from the numerical critical point satisfying dp/drho|T = d2p/drho2|T = 0
|
||||
if (optsuperanc) {
|
||||
return optsuperanc.value().get_pmax(); // from the numerical critical point satisfying dp/drho|T = d2p/drho2|T = 0
|
||||
}
|
||||
}
|
||||
return components[0].crit.p;
|
||||
@@ -1125,10 +1119,10 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_rhomolar_critical(void) {
|
||||
throw ValueError(format("critical point finding routine found %d critical points", critpts.size()));
|
||||
}
|
||||
} else {
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()){
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()) {
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
if (optsuperanc){
|
||||
return optsuperanc.value().get_rhocrit_num(); // from the numerical critical point satisfying dp/drho|T = d2p/drho2|T = 0
|
||||
if (optsuperanc) {
|
||||
return optsuperanc.value().get_rhocrit_num(); // from the numerical critical point satisfying dp/drho|T = d2p/drho2|T = 0
|
||||
}
|
||||
}
|
||||
return components[0].crit.rhomolar;
|
||||
@@ -1211,20 +1205,20 @@ void HelmholtzEOSMixtureBackend::update_QT_pure_superanc(CoolPropDbl Q, CoolProp
|
||||
clear();
|
||||
_Q = Q;
|
||||
_T = T;
|
||||
if (!is_pure()){
|
||||
if (!is_pure()) {
|
||||
throw ValueError(format("Is not a pure fluid"));
|
||||
}
|
||||
if (!get_config_bool(ENABLE_SUPERANCILLARIES)){
|
||||
if (!get_config_bool(ENABLE_SUPERANCILLARIES)) {
|
||||
throw ValueError(format("Superancillaries are not enabled"));
|
||||
}
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
if (!optsuperanc){
|
||||
if (!optsuperanc) {
|
||||
throw ValueError(format("Superancillaries not available for this fluid"));
|
||||
}
|
||||
|
||||
|
||||
auto& superanc = optsuperanc.value();
|
||||
CoolPropDbl Tcrit_num = superanc.get_Tcrit_num();
|
||||
if (T > Tcrit_num){
|
||||
if (T > Tcrit_num) {
|
||||
throw ValueError(format("Temperature to QT_flash [%0.8Lg K] may not be above the numerical critical point of %0.15Lg K", T, Tcrit_num));
|
||||
}
|
||||
auto rhoL = superanc.eval_sat(T, 'D', 0);
|
||||
@@ -1235,11 +1229,10 @@ void HelmholtzEOSMixtureBackend::update_QT_pure_superanc(CoolPropDbl Q, CoolProp
|
||||
_p = p;
|
||||
_rhomolar = 1 / (Q / rhoV + (1 - Q) / rhoL);
|
||||
_phase = iphase_twophase;
|
||||
|
||||
|
||||
post_update(false /*optional_checks*/);
|
||||
}
|
||||
|
||||
|
||||
void HelmholtzEOSMixtureBackend::update_TDmolarP_unchecked(CoolPropDbl T, CoolPropDbl rhomolar, CoolPropDbl p) {
|
||||
|
||||
clear();
|
||||
@@ -1253,8 +1246,6 @@ void HelmholtzEOSMixtureBackend::update_TDmolarP_unchecked(CoolPropDbl T, CoolPr
|
||||
post_update(optional_checks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HelmholtzEOSMixtureBackend::update_DmolarT_direct(CoolPropDbl rhomolar, CoolPropDbl T) {
|
||||
// TODO: This is just a quick fix for #878 - should be done more systematically
|
||||
const CoolPropDbl rhomolar_min = 0;
|
||||
@@ -1524,7 +1515,7 @@ void HelmholtzEOSMixtureBackend::post_update(bool optional_checks) {
|
||||
_delta = _rhomolar / _reducing.rhomolar;
|
||||
|
||||
// Update the terms in the excess contribution
|
||||
if (!is_pure_or_pseudopure){
|
||||
if (!is_pure_or_pseudopure) {
|
||||
residual_helmholtz->Excess.update(_tau, _delta);
|
||||
}
|
||||
}
|
||||
@@ -1556,17 +1547,11 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
|
||||
// Maximum saturation temperature - Equal to critical pressure for pure fluids
|
||||
CoolPropDbl psat_max = calc_pmax_sat();
|
||||
|
||||
|
||||
double T_crit_ = T_critical(), p_crit_ = p_critical(), rhomolar_crit_ = rhomolar_critical();
|
||||
auto smolar_critical = [this, &T_crit_, &rhomolar_crit_](){
|
||||
return this->calc_smolar_nocache(T_crit_, rhomolar_crit_);
|
||||
};
|
||||
auto hmolar_critical = [this, &T_crit_, &rhomolar_crit_](){
|
||||
return this->calc_hmolar_nocache(T_crit_, rhomolar_crit_);
|
||||
};
|
||||
auto umolar_critical = [this, &T_crit_, &rhomolar_crit_](){
|
||||
return this->calc_umolar_nocache(T_crit_, rhomolar_crit_);
|
||||
};
|
||||
auto smolar_critical = [this, &T_crit_, &rhomolar_crit_]() { return this->calc_smolar_nocache(T_crit_, rhomolar_crit_); };
|
||||
auto hmolar_critical = [this, &T_crit_, &rhomolar_crit_]() { return this->calc_hmolar_nocache(T_crit_, rhomolar_crit_); };
|
||||
auto umolar_critical = [this, &T_crit_, &rhomolar_crit_]() { return this->calc_umolar_nocache(T_crit_, rhomolar_crit_); };
|
||||
|
||||
// Check supercritical pressure
|
||||
if (_p > psat_max) {
|
||||
@@ -1624,22 +1609,23 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
}
|
||||
// Check between triple point pressure and psat_max
|
||||
else if (_p >= components[0].EOS().ptriple * 0.9999 && _p <= psat_max) {
|
||||
|
||||
|
||||
// First try the superancillaries, use them to determine the state if you can
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()){
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()) {
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
// Superancillaries are enabled and available, they will be used to determine the phase
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
CoolPropDbl pmax_num = superanc.get_pmax();
|
||||
if (_p > pmax_num){
|
||||
throw ValueError(format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", _p, pmax_num));
|
||||
if (_p > pmax_num) {
|
||||
throw ValueError(
|
||||
format("Pressure to PQ_flash [%0.8Lg Pa] may not be above the numerical critical point of %0.15Lg Pa", _p, pmax_num));
|
||||
}
|
||||
auto Tsat = superanc.get_T_from_p(_p);
|
||||
auto rhoL = superanc.eval_sat(Tsat, 'D', 0);
|
||||
auto rhoV = superanc.eval_sat(Tsat, 'D', 1);
|
||||
auto psat = _p;
|
||||
|
||||
|
||||
if (other == iT) {
|
||||
if (value < Tsat - 100 * DBL_EPSILON) {
|
||||
this->_phase = iphase_liquid;
|
||||
@@ -1693,8 +1679,7 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Then fall back to normal ancillaries, use them to determine the state if you can
|
||||
|
||||
// Calculate dew and bubble temps from the ancillaries (everything needs them)
|
||||
@@ -1855,10 +1840,10 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
if (!is_pure_or_pseudopure) {
|
||||
throw ValueError("possibly two-phase inputs not supported for mixtures for now");
|
||||
}
|
||||
|
||||
|
||||
// The slow full VLE calculation is required
|
||||
{
|
||||
|
||||
|
||||
// Actually have to use saturation information sadly
|
||||
// For the given pressure, find the saturation state
|
||||
// Run the saturation routines to determine the saturation densities and pressures
|
||||
@@ -1866,14 +1851,14 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
HEOS._p = this->_p;
|
||||
HEOS._Q = 0; // ?? What is the best to do here? Doesn't matter for our purposes since pure fluid
|
||||
FlashRoutines::PQ_flash(HEOS);
|
||||
|
||||
|
||||
// We called the saturation routines, so HEOS.SatL and HEOS.SatV are now updated
|
||||
// with the saturated liquid and vapor values, which can therefore be used in
|
||||
// the other solvers
|
||||
saturation_called = true;
|
||||
|
||||
|
||||
CoolPropDbl Q;
|
||||
|
||||
|
||||
if (other == iT) {
|
||||
if (value < HEOS.SatL->T() - 100 * DBL_EPSILON) {
|
||||
this->_phase = iphase_liquid;
|
||||
@@ -1910,7 +1895,7 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
// Update the two-Phase variables
|
||||
_rhoLmolar = HEOS.SatL->rhomolar();
|
||||
_rhoVmolar = HEOS.SatV->rhomolar();
|
||||
|
||||
|
||||
//
|
||||
if (Q < -1e-9) {
|
||||
this->_phase = iphase_liquid;
|
||||
@@ -1923,7 +1908,7 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
|
||||
} else {
|
||||
this->_phase = iphase_twophase;
|
||||
}
|
||||
|
||||
|
||||
_Q = Q;
|
||||
// Load the outputs
|
||||
_T = _Q * HEOS.SatV->T() + (1 - _Q) * HEOS.SatL->T();
|
||||
@@ -1954,7 +1939,7 @@ void HelmholtzEOSMixtureBackend::calc_ssat_max(void) {
|
||||
{
|
||||
public:
|
||||
HelmholtzEOSMixtureBackend* HEOS;
|
||||
Residual(HelmholtzEOSMixtureBackend& HEOS) : HEOS(&HEOS){};
|
||||
Residual(HelmholtzEOSMixtureBackend& HEOS) : HEOS(&HEOS) {};
|
||||
double call(double T) {
|
||||
HEOS->update(QT_INPUTS, 1, T);
|
||||
// dTdp_along_sat
|
||||
@@ -1989,7 +1974,7 @@ void HelmholtzEOSMixtureBackend::calc_hsat_max(void) {
|
||||
{
|
||||
public:
|
||||
HelmholtzEOSMixtureBackend* HEOS;
|
||||
Residualhmax(HelmholtzEOSMixtureBackend& HEOS) : HEOS(&HEOS){};
|
||||
Residualhmax(HelmholtzEOSMixtureBackend& HEOS) : HEOS(&HEOS) {};
|
||||
double call(double T) {
|
||||
HEOS->update(QT_INPUTS, 1, T);
|
||||
// dTdp_along_sat
|
||||
@@ -2014,17 +1999,11 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
if (!ValidNumber(value)) {
|
||||
throw ValueError(format("value to T_phase_determination_pure_or_pseudopure is invalid"));
|
||||
};
|
||||
|
||||
|
||||
double T_crit_ = T_critical(), p_crit_ = p_critical(), rhomolar_crit_ = rhomolar_critical();
|
||||
auto smolar_critical = [this, &T_crit_, &rhomolar_crit_](){
|
||||
return this->calc_smolar_nocache(T_crit_, rhomolar_crit_);
|
||||
};
|
||||
auto hmolar_critical = [this, &T_crit_, &rhomolar_crit_](){
|
||||
return this->calc_hmolar_nocache(T_crit_, rhomolar_crit_);
|
||||
};
|
||||
auto umolar_critical = [this, &T_crit_, &rhomolar_crit_](){
|
||||
return this->calc_umolar_nocache(T_crit_, rhomolar_crit_);
|
||||
};
|
||||
auto smolar_critical = [this, &T_crit_, &rhomolar_crit_]() { return this->calc_smolar_nocache(T_crit_, rhomolar_crit_); };
|
||||
auto hmolar_critical = [this, &T_crit_, &rhomolar_crit_]() { return this->calc_hmolar_nocache(T_crit_, rhomolar_crit_); };
|
||||
auto umolar_critical = [this, &T_crit_, &rhomolar_crit_]() { return this->calc_umolar_nocache(T_crit_, rhomolar_crit_); };
|
||||
|
||||
// T is known, another input P, T, H, S, U is given (all molar)
|
||||
if (_T < T_crit_ && _p > p_crit_) {
|
||||
@@ -2061,10 +2040,10 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
}
|
||||
} else if (_T < T_crit_) // Gas, 2-Phase, Liquid, or Supercritical Liquid Region
|
||||
{
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()){
|
||||
if (get_config_bool(ENABLE_SUPERANCILLARIES) && is_pure()) {
|
||||
auto& optsuperanc = get_superanc_optional();
|
||||
// Superancillaries are enabled and available, they will be used to determine the phase
|
||||
if (optsuperanc){
|
||||
if (optsuperanc) {
|
||||
auto& superanc = optsuperanc.value();
|
||||
auto rhoL = superanc.eval_sat(_T, 'D', 0);
|
||||
auto rhoV = superanc.eval_sat(_T, 'D', 1);
|
||||
@@ -2073,14 +2052,12 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
_rhoVanc = rhoV;
|
||||
_rhoLmolar = rhoL;
|
||||
_rhoVmolar = rhoV;
|
||||
|
||||
if (other == iP){
|
||||
if (std::abs(psat/value-1) < 1e-6){
|
||||
|
||||
if (other == iP) {
|
||||
if (std::abs(psat / value - 1) < 1e-6) {
|
||||
throw ValueError(
|
||||
format("Saturation pressure [%g Pa] corresponding to T [%g K] is within 1e-4 %% of given p [%Lg Pa]", psat, _T, value)
|
||||
);
|
||||
}
|
||||
else if (value < psat) {
|
||||
format("Saturation pressure [%g Pa] corresponding to T [%g K] is within 1e-4 %% of given p [%Lg Pa]", psat, _T, value));
|
||||
} else if (value < psat) {
|
||||
_phase = iphase_gas;
|
||||
_Q = -1000;
|
||||
} else if (value > psat) {
|
||||
@@ -2090,7 +2067,7 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
return;
|
||||
}
|
||||
double Q = -1;
|
||||
if (other == iDmolar){
|
||||
if (other == iDmolar) {
|
||||
// Special case density as an input
|
||||
Q = (1 / value - 1 / rhoL) / (1 / rhoV - 1 / rhoL);
|
||||
if (Q <= 0) {
|
||||
@@ -2109,13 +2086,13 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
_rhomolar = value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SatL->update_TDmolarP_unchecked(_T, rhoL, psat);
|
||||
SatV->update_TDmolarP_unchecked(_T, rhoV, psat);
|
||||
|
||||
|
||||
switch (other) {
|
||||
case iDmolar:
|
||||
Q = (1/value - 1/SatL->rhomolar()) / (1/SatV->rhomolar() - 1/SatL->rhomolar());
|
||||
Q = (1 / value - 1 / SatL->rhomolar()) / (1 / SatV->rhomolar() - 1 / SatL->rhomolar());
|
||||
break;
|
||||
case iSmolar:
|
||||
Q = (value - SatL->smolar()) / (SatV->smolar() - SatL->smolar());
|
||||
@@ -2129,13 +2106,13 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
default:
|
||||
throw ValueError(format("bad input for other"));
|
||||
}
|
||||
|
||||
|
||||
if (Q < 0) {
|
||||
this->_phase = iphase_liquid;
|
||||
SatL->clear();
|
||||
SatV->clear();
|
||||
_Q = -1000;
|
||||
|
||||
|
||||
} else if (Q > 1) {
|
||||
this->_phase = iphase_gas;
|
||||
SatL->clear();
|
||||
@@ -2150,8 +2127,7 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Start to think about the saturation stuff
|
||||
// First try to use the ancillary equations if you are far enough away
|
||||
// You know how accurate the ancillary equations are thanks to using CoolProp code to refit them
|
||||
@@ -2719,11 +2695,12 @@ CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp_global(CoolPropDbl T, Cool
|
||||
// Vapor root found, return it
|
||||
return rho_vap;
|
||||
} else {
|
||||
throw CoolProp::ValueError(format("No density solutions for T=%g,p=%g,z=%s", T, p, vec_to_string(static_cast<std::vector<double>>(mole_fractions), "%0.12g").c_str()));
|
||||
throw CoolProp::ValueError(format("No density solutions for T=%g,p=%g,z=%s", T, p,
|
||||
vec_to_string(static_cast<std::vector<double>>(mole_fractions), "%0.12g").c_str()));
|
||||
}
|
||||
} else {
|
||||
throw CoolProp::ValueError(
|
||||
format("One stationary point (not good) for T=%g,p=%g,z=%s", T, p, vec_to_string(static_cast<std::vector<double>>(mole_fractions), "%0.12g").c_str()));
|
||||
throw CoolProp::ValueError(format("One stationary point (not good) for T=%g,p=%g,z=%s", T, p,
|
||||
vec_to_string(static_cast<std::vector<double>>(mole_fractions), "%0.12g").c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2778,19 +2755,18 @@ CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl
|
||||
} else if (phase == iphase_supercritical_liquid) {
|
||||
CoolPropDbl rhoLancval = static_cast<CoolPropDbl>(components[0].ancillaries.rhoL.evaluate(T));
|
||||
CoolPropDbl rhoLtripleancval = static_cast<CoolPropDbl>(components[0].ancillaries.rhoL.evaluate(Ttriple()));
|
||||
|
||||
|
||||
// Next we try with a Brent method bounded solver since the function should be 1-1 in most cases
|
||||
// But some EOS have a maximum in pressure so if rhoc*4 is after the maximum in pressure, this method will fail
|
||||
// and fall back to a narrower range of densities
|
||||
try{
|
||||
try {
|
||||
double rhomolar = Brent(resid, rhoLancval * 0.99, rhomolar_critical() * 4, DBL_EPSILON, 1e-8, 100);
|
||||
if (!ValidNumber(rhomolar)) {
|
||||
throw ValueError();
|
||||
}
|
||||
return rhomolar;
|
||||
}
|
||||
catch(...){
|
||||
double rhomolar = Brent(resid, rhoLancval * 0.99, rhoLtripleancval*1.1, DBL_EPSILON, 1e-8, 100);
|
||||
} catch (...) {
|
||||
double rhomolar = Brent(resid, rhoLancval * 0.99, rhoLtripleancval * 1.1, DBL_EPSILON, 1e-8, 100);
|
||||
if (!ValidNumber(rhomolar)) {
|
||||
throw ValueError();
|
||||
}
|
||||
@@ -3013,9 +2989,10 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar(void) {
|
||||
|
||||
// Calculate derivatives if needed, or just use cached values
|
||||
auto ders = this->calc_all_alpha0_derivs_nocache(mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar);
|
||||
CoolPropDbl da0_dTau = ders.dalphar_dtau; // Note: while the naming here refers to alphar for historical reasons, it is actually the ideal-gas part
|
||||
CoolPropDbl a0 = ders.alphar; // Note: while the naming here refers to alphar for historical reasons, it is actually the ideal-gas part
|
||||
|
||||
CoolPropDbl da0_dTau =
|
||||
ders.dalphar_dtau; // Note: while the naming here refers to alphar for historical reasons, it is actually the ideal-gas part
|
||||
CoolPropDbl a0 = ders.alphar; // Note: while the naming here refers to alphar for historical reasons, it is actually the ideal-gas part
|
||||
|
||||
CoolPropDbl ar = alphar();
|
||||
CoolPropDbl dar_dTau = dalphar_dTau();
|
||||
CoolPropDbl R_u = gas_constant();
|
||||
@@ -3390,9 +3367,8 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_alpha0_deriv_nocache(const int nTau
|
||||
}
|
||||
|
||||
HelmholtzDerivatives HelmholtzEOSMixtureBackend::calc_all_alpha0_derivs_nocache(const std::vector<CoolPropDbl>& mole_fractions,
|
||||
const CoolPropDbl& tau, const CoolPropDbl& delta, const CoolPropDbl& Tr,
|
||||
const CoolPropDbl& rhor) {
|
||||
CoolPropDbl val;
|
||||
const CoolPropDbl& tau, const CoolPropDbl& delta,
|
||||
const CoolPropDbl& Tr, const CoolPropDbl& rhor) {
|
||||
if (components.size() == 0) {
|
||||
throw ValueError("No alpha0 derivatives are available");
|
||||
}
|
||||
@@ -3409,10 +3385,10 @@ HelmholtzDerivatives HelmholtzEOSMixtureBackend::calc_all_alpha0_derivs_nocache(
|
||||
return E.alpha0.all(taustar, deltastar, false);
|
||||
} else {
|
||||
HelmholtzDerivatives ders;
|
||||
|
||||
|
||||
// See Table B5, GERG 2008 from Kunz Wagner, JCED, 2012
|
||||
std::size_t N = mole_fractions.size();
|
||||
CoolPropDbl summer_00=0, summer_01=0, summer_10=0, summer_02=0, summer_11=0, summer_20=0;
|
||||
CoolPropDbl summer_00 = 0, summer_01 = 0, summer_10 = 0, summer_02 = 0, summer_11 = 0, summer_20 = 0;
|
||||
CoolPropDbl tau_i, delta_i, rho_ci, T_ci;
|
||||
CoolPropDbl Rmix = gas_constant();
|
||||
for (unsigned int i = 0; i < N; ++i) {
|
||||
@@ -3429,7 +3405,7 @@ HelmholtzDerivatives HelmholtzEOSMixtureBackend::calc_all_alpha0_derivs_nocache(
|
||||
{
|
||||
// All the ideal-gas derivatives for the pure component
|
||||
auto pure = components[i].EOS().alpha0.all(tau_i, delta_i);
|
||||
|
||||
|
||||
double logxi = (std::abs(mole_fractions[i]) > DBL_EPSILON) ? log(mole_fractions[i]) : 0;
|
||||
// Note: you see alphar here, that is a book-keeping artifact, it is really alpha for ideal gas
|
||||
summer_00 += mole_fractions[i] * Rratio * (pure.alphar + logxi);
|
||||
@@ -3447,7 +3423,7 @@ HelmholtzDerivatives HelmholtzEOSMixtureBackend::calc_all_alpha0_derivs_nocache(
|
||||
ders.d2alphar_ddelta2 = summer_02;
|
||||
ders.d2alphar_ddelta_dtau = summer_11;
|
||||
ders.d2alphar_dtau2 = summer_20;
|
||||
|
||||
|
||||
return ders;
|
||||
}
|
||||
}
|
||||
@@ -3829,7 +3805,7 @@ CoolProp::CriticalState HelmholtzEOSMixtureBackend::calc_critical_point(double r
|
||||
HelmholtzEOSMixtureBackend& HEOS;
|
||||
double L1, M1;
|
||||
Eigen::MatrixXd Lstar, Mstar;
|
||||
Resid(HelmholtzEOSMixtureBackend& HEOS) : HEOS(HEOS), L1(_HUGE), M1(_HUGE){};
|
||||
Resid(HelmholtzEOSMixtureBackend& HEOS) : HEOS(HEOS), L1(_HUGE), M1(_HUGE) {};
|
||||
std::vector<double> call(const std::vector<double>& tau_delta) {
|
||||
double rhomolar = tau_delta[1] * HEOS.rhomolar_reducing();
|
||||
double T = HEOS.T_reducing() / tau_delta[0];
|
||||
@@ -3916,7 +3892,8 @@ class OneDimObjective : public FuncWrapper1DWithTwoDerivs
|
||||
CoolProp::HelmholtzEOSMixtureBackend& HEOS;
|
||||
const double delta;
|
||||
double _call, _deriv, _second_deriv;
|
||||
OneDimObjective(HelmholtzEOSMixtureBackend& HEOS, double delta0) : HEOS(HEOS), delta(delta0), _call(_HUGE), _deriv(_HUGE), _second_deriv(_HUGE){};
|
||||
OneDimObjective(HelmholtzEOSMixtureBackend& HEOS, double delta0)
|
||||
: HEOS(HEOS), delta(delta0), _call(_HUGE), _deriv(_HUGE), _second_deriv(_HUGE) {};
|
||||
double call(double tau) {
|
||||
double rhomolar = HEOS.rhomolar_reducing() * delta, T = HEOS.T_reducing() / tau;
|
||||
HEOS.update_DmolarT_direct(rhomolar, T);
|
||||
@@ -4242,7 +4219,7 @@ void HelmholtzEOSMixtureBackend::set_reference_stateS(const std::string& referen
|
||||
void HelmholtzEOSMixtureBackend::set_reference_stateD(double T, double rhomolar, double hmolar0, double smolar0) {
|
||||
for (std::size_t i = 0; i < components.size(); ++i) {
|
||||
CoolProp::HelmholtzEOSMixtureBackend HEOS(std::vector<CoolPropFluid>(1, components[i]));
|
||||
|
||||
|
||||
// Skip the cache and phase calculation because we are given a temperature and density directly;
|
||||
// just evaluate the EOS
|
||||
double hmolar = calc_hmolar_nocache(T, rhomolar);
|
||||
|
||||
@@ -19,20 +19,22 @@ class FlashRoutines;
|
||||
|
||||
class ResidualHelmholtz;
|
||||
|
||||
// This class contains the mole fractions for a given mixture.
|
||||
class MoleFractions{
|
||||
private:
|
||||
std::vector<CoolPropDbl> mole_fractions; ///< The bulk mole fractions of the mixture
|
||||
// This class contains the mole fractions for a given mixture.
|
||||
class MoleFractions
|
||||
{
|
||||
private:
|
||||
std::vector<CoolPropDbl> mole_fractions; ///< The bulk mole fractions of the mixture
|
||||
template <typename T>
|
||||
bool verify_mole_fractions_set(T i) const {
|
||||
if (i >= mole_fractions.size()){
|
||||
if (i >= mole_fractions.size()) {
|
||||
throw CoolProp::ValueError("mole fractions are not set for all components");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
void resize(T N){
|
||||
void resize(T N) {
|
||||
return mole_fractions.resize(N);
|
||||
}
|
||||
std::size_t size() const {
|
||||
@@ -42,8 +44,8 @@ class MoleFractions{
|
||||
mole_fractions.clear();
|
||||
}
|
||||
// operator overloads
|
||||
template<typename T>
|
||||
MoleFractions& operator=(const std::vector<T>& values){
|
||||
template <typename T>
|
||||
MoleFractions& operator=(const std::vector<T>& values) {
|
||||
mole_fractions = values;
|
||||
return *this;
|
||||
}
|
||||
@@ -52,7 +54,9 @@ class MoleFractions{
|
||||
verify_mole_fractions_set(i);
|
||||
return mole_fractions[i];
|
||||
}
|
||||
operator std::vector<CoolPropDbl>& () { return mole_fractions; }
|
||||
operator std::vector<CoolPropDbl>&() {
|
||||
return mole_fractions;
|
||||
}
|
||||
};
|
||||
|
||||
class HelmholtzEOSMixtureBackend : public AbstractState
|
||||
@@ -91,11 +95,11 @@ class HelmholtzEOSMixtureBackend : public AbstractState
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<CoolPropFluid> components; ///< The components that are in use
|
||||
bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false)
|
||||
MoleFractions mole_fractions; ///< The bulk mole fractions of the mixture
|
||||
std::vector<CoolPropDbl> K, ///< The K factors for the components
|
||||
lnK; ///< The natural logarithms of the K factors of the components
|
||||
std::vector<CoolPropFluid> components; ///< The components that are in use
|
||||
bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false)
|
||||
MoleFractions mole_fractions; ///< The bulk mole fractions of the mixture
|
||||
std::vector<CoolPropDbl> K, ///< The K factors for the components
|
||||
lnK; ///< The natural logarithms of the K factors of the components
|
||||
|
||||
SimpleState _crit;
|
||||
std::size_t N; ///< Number of components
|
||||
@@ -104,7 +108,7 @@ class HelmholtzEOSMixtureBackend : public AbstractState
|
||||
std::vector<CoolProp::CriticalState> _calc_all_critical_points(bool find_critical_points = true);
|
||||
|
||||
static void set_fluid_enthalpy_entropy_offset(CoolPropFluid& component, double delta_a1, double delta_a2, const std::string& ref);
|
||||
|
||||
|
||||
std::optional<EquationOfState::SuperAncillary_t>& get_superanc_optional();
|
||||
|
||||
public:
|
||||
@@ -116,7 +120,7 @@ class HelmholtzEOSMixtureBackend : public AbstractState
|
||||
// Copy over the reducing and departure terms to all linked states (recursively)
|
||||
void sync_linked_states(const HelmholtzEOSMixtureBackend* const);
|
||||
|
||||
virtual ~HelmholtzEOSMixtureBackend(){};
|
||||
virtual ~HelmholtzEOSMixtureBackend() {};
|
||||
std::string backend_name(void) {
|
||||
return get_backend_string(HEOS_BACKEND_MIX);
|
||||
}
|
||||
@@ -591,9 +595,9 @@ class HelmholtzEOSMixtureBackend : public AbstractState
|
||||
*/
|
||||
CoolPropDbl calc_alpha0_deriv_nocache(const int nTau, const int nDelta, const std::vector<CoolPropDbl>& mole_fractions, const CoolPropDbl& tau,
|
||||
const CoolPropDbl& delta, const CoolPropDbl& Tr, const CoolPropDbl& rhor);
|
||||
|
||||
|
||||
HelmholtzDerivatives calc_all_alpha0_derivs_nocache(const std::vector<CoolPropDbl>& mole_fractions, const CoolPropDbl& tau,
|
||||
const CoolPropDbl& delta, const CoolPropDbl& Tr, const CoolPropDbl& rhor);
|
||||
const CoolPropDbl& delta, const CoolPropDbl& Tr, const CoolPropDbl& rhor);
|
||||
|
||||
virtual void calc_reducing_state(void);
|
||||
virtual SimpleState calc_reducing_state_nocache(const std::vector<CoolPropDbl>& mole_fractions);
|
||||
@@ -802,8 +806,8 @@ class ResidualHelmholtz
|
||||
ExcessTerm Excess;
|
||||
CorrespondingStatesTerm CS;
|
||||
|
||||
ResidualHelmholtz(){};
|
||||
ResidualHelmholtz(const ExcessTerm& E, const CorrespondingStatesTerm& C) : Excess(E), CS(C){};
|
||||
ResidualHelmholtz() {};
|
||||
ResidualHelmholtz(const ExcessTerm& E, const CorrespondingStatesTerm& C) : Excess(E), CS(C) {};
|
||||
virtual ~ResidualHelmholtz() = default;
|
||||
|
||||
ResidualHelmholtz copy() {
|
||||
|
||||
@@ -1147,9 +1147,9 @@ template <class backend>
|
||||
class DerivativeFixture
|
||||
{
|
||||
public:
|
||||
shared_ptr<CoolProp::HelmholtzEOSMixtureBackend> HEOS, HEOS_plus_tau, HEOS_minus_tau, HEOS_plus_delta, HEOS_minus_delta, HEOS_plus_2tau, HEOS_minus_2tau, HEOS_plus_2delta, HEOS_minus_2delta, HEOS_plus_T__constp,
|
||||
HEOS_minus_T__constp, HEOS_plus_p__constT, HEOS_minus_p__constT, HEOS_plus_T__constrho, HEOS_minus_T__constrho, HEOS_plus_rho__constT,
|
||||
HEOS_minus_rho__constT;
|
||||
shared_ptr<CoolProp::HelmholtzEOSMixtureBackend> HEOS, HEOS_plus_tau, HEOS_minus_tau, HEOS_plus_delta, HEOS_minus_delta, HEOS_plus_2tau,
|
||||
HEOS_minus_2tau, HEOS_plus_2delta, HEOS_minus_2delta, HEOS_plus_T__constp, HEOS_minus_T__constp, HEOS_plus_p__constT, HEOS_minus_p__constT,
|
||||
HEOS_plus_T__constrho, HEOS_minus_T__constrho, HEOS_plus_rho__constT, HEOS_minus_rho__constT;
|
||||
std::vector<shared_ptr<CoolProp::HelmholtzEOSMixtureBackend>> HEOS_plus_z, HEOS_minus_z, HEOS_plus_z__constTrho, HEOS_minus_z__constTrho,
|
||||
HEOS_plus_n, HEOS_minus_n, HEOS_plus_2z, HEOS_minus_2z, HEOS_plus_2z__constTrho, HEOS_minus_2z__constTrho;
|
||||
CoolProp::x_N_dependency_flag xN;
|
||||
@@ -1197,12 +1197,14 @@ class DerivativeFixture
|
||||
// Constant composition, varying state
|
||||
HEOS_plus_tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() + dtau));
|
||||
HEOS_minus_tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() - dtau));
|
||||
HEOS_plus_2tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() + 2*dtau));
|
||||
HEOS_minus_2tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() - 2*dtau));
|
||||
HEOS_plus_2tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() + 2 * dtau));
|
||||
HEOS_minus_2tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() - 2 * dtau));
|
||||
HEOS_plus_delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() + ddelta) * HEOS->rhomolar_reducing(), HEOS->T_reducing() / HEOS->tau());
|
||||
HEOS_minus_delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() - ddelta) * HEOS->rhomolar_reducing(), HEOS->T_reducing() / HEOS->tau());
|
||||
HEOS_plus_2delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() + 2*ddelta) * HEOS->rhomolar_reducing(), HEOS->T_reducing() / HEOS->tau());
|
||||
HEOS_minus_2delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() - 2*ddelta) * HEOS->rhomolar_reducing(), HEOS->T_reducing() / HEOS->tau());
|
||||
HEOS_plus_2delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() + 2 * ddelta) * HEOS->rhomolar_reducing(),
|
||||
HEOS->T_reducing() / HEOS->tau());
|
||||
HEOS_minus_2delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() - 2 * ddelta) * HEOS->rhomolar_reducing(),
|
||||
HEOS->T_reducing() / HEOS->tau());
|
||||
HEOS_plus_T__constp->update(CoolProp::PT_INPUTS, HEOS->p(), HEOS->T() + dT);
|
||||
HEOS_minus_T__constp->update(CoolProp::PT_INPUTS, HEOS->p(), HEOS->T() - dT);
|
||||
HEOS_plus_p__constT->update(CoolProp::PT_INPUTS, HEOS->p() + dp, HEOS->T());
|
||||
@@ -1418,9 +1420,13 @@ class DerivativeFixture
|
||||
double analytic = f(*HEOS, i, j, k, xN);
|
||||
double numeric = 0;
|
||||
if (wrt == TAU) {
|
||||
numeric = (-1.0/12.0*g(*HEOS_plus_2tau, i, j, k, xN) + 2.0/3.0*g(*HEOS_plus_tau, i, j, k, xN) -2.0/3.0*g(*HEOS_minus_tau, i, j, k, xN) +1.0/12.0*g(*HEOS_minus_2tau, i, j, k, xN)) / dtau;
|
||||
numeric = (-1.0 / 12.0 * g(*HEOS_plus_2tau, i, j, k, xN) + 2.0 / 3.0 * g(*HEOS_plus_tau, i, j, k, xN)
|
||||
- 2.0 / 3.0 * g(*HEOS_minus_tau, i, j, k, xN) + 1.0 / 12.0 * g(*HEOS_minus_2tau, i, j, k, xN))
|
||||
/ dtau;
|
||||
} else if (wrt == DELTA) {
|
||||
numeric = (-1.0/12.0*g(*HEOS_plus_2delta, i, j, k, xN) + 2.0/3.0*g(*HEOS_plus_delta, i, j, k, xN) -2.0/3.0*g(*HEOS_minus_delta, i, j, k, xN) +1.0/12.0*g(*HEOS_minus_2delta, i, j, k, xN)) / ddelta;
|
||||
numeric = (-1.0 / 12.0 * g(*HEOS_plus_2delta, i, j, k, xN) + 2.0 / 3.0 * g(*HEOS_plus_delta, i, j, k, xN)
|
||||
- 2.0 / 3.0 * g(*HEOS_minus_delta, i, j, k, xN) + 1.0 / 12.0 * g(*HEOS_minus_2delta, i, j, k, xN))
|
||||
/ ddelta;
|
||||
}
|
||||
CAPTURE(name);
|
||||
CAPTURE(i);
|
||||
@@ -1676,11 +1682,11 @@ TEST_CASE_METHOD(DerivativeFixture<SRKBackend>, "Check derivatives for SRK", "[m
|
||||
tol = 1e-3; // Relax the tolerance a bit
|
||||
run_checks();
|
||||
};
|
||||
// Make sure you set the VTPR UNIFAC path with something like set_config_string(VTPR_UNIFAC_PATH, "/Users/ian/Code/CUBAC/dev/unifaq/");
|
||||
//TEST_CASE_METHOD(DerivativeFixture<VTPRBackend>, "Check derivatives for VTPR", "[mixture_derivs2]")
|
||||
//{
|
||||
// tol = 1e-4; // Relax the tolerance a bit
|
||||
// run_checks();
|
||||
//};
|
||||
// Make sure you set the VTPR UNIFAC path with something like set_config_string(VTPR_UNIFAC_PATH, "/Users/ian/Code/CUBAC/dev/unifaq/");
|
||||
//TEST_CASE_METHOD(DerivativeFixture<VTPRBackend>, "Check derivatives for VTPR", "[mixture_derivs2]")
|
||||
//{
|
||||
// tol = 1e-4; // Relax the tolerance a bit
|
||||
// run_checks();
|
||||
//};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,8 +29,8 @@ class PredefinedMixturesLibrary
|
||||
load_from_JSON(doc);
|
||||
}
|
||||
|
||||
void load_from_JSON(rapidjson::Document & doc){
|
||||
if (!doc.IsArray() || !doc[0].IsObject()){
|
||||
void load_from_JSON(rapidjson::Document& doc) {
|
||||
if (!doc.IsArray() || !doc[0].IsObject()) {
|
||||
throw ValueError("You must provide an array of objects");
|
||||
}
|
||||
// Iterate over the papers in the listing
|
||||
@@ -778,7 +778,7 @@ void parse_HMX_BNC(const std::string& s, std::vector<REFPROP_binary_element>& BI
|
||||
dep.e.push_back(string2double(bits[3]));
|
||||
}
|
||||
if (dep.Nspecial > 0) {
|
||||
if (dep.a.size() - 1 < dep.Npower) {
|
||||
if (dep.a.size() - 1 < static_cast<size_t>(dep.Npower)) {
|
||||
dep.eta.push_back(0);
|
||||
dep.epsilon.push_back(0);
|
||||
dep.beta.push_back(0);
|
||||
|
||||
@@ -34,8 +34,8 @@ class ReducingFunction
|
||||
std::size_t N;
|
||||
|
||||
public:
|
||||
ReducingFunction() : N(0){};
|
||||
virtual ~ReducingFunction(){};
|
||||
ReducingFunction() : N(0) {};
|
||||
virtual ~ReducingFunction() {};
|
||||
|
||||
virtual ReducingFunction* copy() = 0;
|
||||
|
||||
@@ -183,19 +183,19 @@ class GERG2008ReducingFunction : public ReducingFunction
|
||||
};
|
||||
|
||||
/// Default destructor
|
||||
~GERG2008ReducingFunction(){};
|
||||
~GERG2008ReducingFunction() {};
|
||||
|
||||
/// Set all beta and gamma values in one shot
|
||||
void set_binary_interaction_double(const std::size_t i, const std::size_t j, double betaT, double gammaT, double betaV, double gammaV) {
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
beta_T[i][j] = betaT;
|
||||
beta_T[j][i] = 1 / betaT;
|
||||
@@ -212,12 +212,12 @@ class GERG2008ReducingFunction : public ReducingFunction
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= N) {
|
||||
if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= N) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N - 1));
|
||||
}
|
||||
if (parameter == "betaT") {
|
||||
beta_T[i][j] = value;
|
||||
@@ -550,7 +550,7 @@ class ConstantReducingFunction : public ReducingFunction
|
||||
double T_c, rhomolar_c;
|
||||
|
||||
public:
|
||||
ConstantReducingFunction(const double T_c, const double rhomolar_c) : T_c(T_c), rhomolar_c(rhomolar_c){};
|
||||
ConstantReducingFunction(const double T_c, const double rhomolar_c) : T_c(T_c), rhomolar_c(rhomolar_c) {};
|
||||
|
||||
ReducingFunction* copy() {
|
||||
return new ConstantReducingFunction(T_c, rhomolar_c);
|
||||
|
||||
@@ -345,7 +345,7 @@ CoolPropDbl TransportRoutines::viscosity_CO2_higher_order_hardcoded_LaeseckeJPCR
|
||||
double Tt = HEOS.Ttriple(), rho_tL = 1178.53;
|
||||
double Tr = HEOS.T() / Tt, rhor = HEOS.rhomass() / rho_tL;
|
||||
// Eq. (9) from Laesecke, JPCRD, 2017
|
||||
double eta_tL = pow(rho_tL, 2.0/3.0) * sqrt(HEOS.gas_constant() * Tt) / (pow(HEOS.molar_mass(), 1.0/6.0) * 84446887.43579945);
|
||||
double eta_tL = pow(rho_tL, 2.0 / 3.0) * sqrt(HEOS.gas_constant() * Tt) / (pow(HEOS.molar_mass(), 1.0 / 6.0) * 84446887.43579945);
|
||||
// Eq. (8) from Laesecke, JPCRD, 2017
|
||||
double residual = eta_tL * (c1 * Tr * pow(rhor, 3) + (pow(rhor, 2) + pow(rhor, gamma)) / (Tr - c2));
|
||||
return residual;
|
||||
@@ -598,11 +598,11 @@ CoolPropDbl TransportRoutines::viscosity_dilute_CO2_LaeseckeJPCRD2017(HelmholtzE
|
||||
double eta0, den;
|
||||
double T = HEOS.T();
|
||||
|
||||
double a[] = {
|
||||
1749.354893188350, -369.069300007128, 5423856.34887691, -2.21283852168356, -269503.247933569, 73145.021531826, 5.34368649509278};
|
||||
|
||||
double a[] = {1749.354893188350, -369.069300007128, 5423856.34887691, -2.21283852168356, -269503.247933569, 73145.021531826, 5.34368649509278};
|
||||
|
||||
// Eq. (4) from Laesecke, JPRCD, 2016
|
||||
den = a[0] + a[1] * pow(T, 1.0/6.0) + a[2] * exp(a[3] * pow(T, 1.0/3.0)) + (a[4] + a[5] * pow(T, 1.0/3.0)) / exp(pow(T, 1.0 / 3.0)) + a[6] * sqrt(T);
|
||||
den = a[0] + a[1] * pow(T, 1.0 / 6.0) + a[2] * exp(a[3] * pow(T, 1.0 / 3.0)) + (a[4] + a[5] * pow(T, 1.0 / 3.0)) / exp(pow(T, 1.0 / 3.0))
|
||||
+ a[6] * sqrt(T);
|
||||
eta0 = 0.0010055 * sqrt(T) / den; // [Pa-s]
|
||||
return eta0;
|
||||
}
|
||||
@@ -826,11 +826,11 @@ CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_CO2(HelmholtzEOSMix
|
||||
CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_CO2_HuberJPCRD2016(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
|
||||
double tau = HEOS.tau();
|
||||
double l[]={0.0151874307, 0.0280674040, 0.0228564190, -0.00741624210};
|
||||
double l[] = {0.0151874307, 0.0280674040, 0.0228564190, -0.00741624210};
|
||||
// Huber 2016 Eq. (3)
|
||||
double lambda_0 = pow(tau, -0.5)/(l[0] + l[1] * tau + l[2] * pow(tau, 2) + l[3] * pow(tau, 3)); // [mW/m/K]
|
||||
|
||||
return lambda_0/1000;
|
||||
double lambda_0 = pow(tau, -0.5) / (l[0] + l[1] * tau + l[2] * pow(tau, 2) + l[3] * pow(tau, 3)); // [mW/m/K]
|
||||
|
||||
return lambda_0 / 1000;
|
||||
}
|
||||
|
||||
CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_ethane(HelmholtzEOSMixtureBackend& HEOS) {
|
||||
|
||||
@@ -107,7 +107,6 @@ class TransportRoutines
|
||||
static CoolPropDbl viscosity_dilute_cyclohexane(HelmholtzEOSMixtureBackend& HEOS);
|
||||
static CoolPropDbl viscosity_dilute_CO2_LaeseckeJPCRD2017(HelmholtzEOSMixtureBackend& HEOS);
|
||||
|
||||
|
||||
/** \brief Viscosity hardcoded for Methanol
|
||||
*
|
||||
* From Xiang et al., A New Reference Correlation for the Viscosity of Methanol, J. Phys. Chem. Ref. Data, Vol. 35, No. 4, 2006
|
||||
|
||||
@@ -16,7 +16,7 @@ void SaturationSolvers::saturation_critical(HelmholtzEOSMixtureBackend& HEOS, pa
|
||||
HelmholtzEOSMixtureBackend* HEOS;
|
||||
CoolPropDbl T, desired_p;
|
||||
|
||||
inner_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl T, CoolPropDbl desired_p) : HEOS(HEOS), T(T), desired_p(desired_p){};
|
||||
inner_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl T, CoolPropDbl desired_p) : HEOS(HEOS), T(T), desired_p(desired_p) {};
|
||||
double call(double rhomolar_liq) {
|
||||
HEOS->SatL->update(DmolarT_INPUTS, rhomolar_liq, T);
|
||||
CoolPropDbl calc_p = HEOS->SatL->p();
|
||||
@@ -36,7 +36,7 @@ void SaturationSolvers::saturation_critical(HelmholtzEOSMixtureBackend& HEOS, pa
|
||||
CoolPropDbl rhomolar_crit;
|
||||
|
||||
outer_resid(HelmholtzEOSMixtureBackend& HEOS, CoolProp::parameters ykey, CoolPropDbl y)
|
||||
: HEOS(&HEOS), ykey(ykey), y(y), rhomolar_crit(HEOS.rhomolar_critical()){};
|
||||
: HEOS(&HEOS), ykey(ykey), y(y), rhomolar_crit(HEOS.rhomolar_critical()) {};
|
||||
double call(double rhomolar_vap) {
|
||||
// Calculate the other variable (T->p or p->T) for given vapor density
|
||||
CoolPropDbl T, p, rhomolar_liq;
|
||||
@@ -83,7 +83,7 @@ void SaturationSolvers::saturation_T_pure_1D_P(HelmholtzEOSMixtureBackend& HEOS,
|
||||
CoolPropDbl T, rhomolar_liq, rhomolar_vap;
|
||||
|
||||
solver_resid(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, CoolPropDbl rhomolar_liq_guess, CoolPropDbl rhomolar_vap_guess)
|
||||
: HEOS(&HEOS), T(T), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess){};
|
||||
: HEOS(&HEOS), T(T), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess) {};
|
||||
double call(double p) {
|
||||
// Recalculate the densities using the current guess values
|
||||
HEOS->SatL->update_TP_guessrho(T, p, rhomolar_liq);
|
||||
@@ -128,7 +128,7 @@ void SaturationSolvers::saturation_P_pure_1D_T(HelmholtzEOSMixtureBackend& HEOS,
|
||||
CoolPropDbl p, rhomolar_liq, rhomolar_vap;
|
||||
|
||||
solver_resid(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl p, CoolPropDbl rhomolar_liq_guess, CoolPropDbl rhomolar_vap_guess)
|
||||
: HEOS(&HEOS), p(p), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess){};
|
||||
: HEOS(&HEOS), p(p), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess) {};
|
||||
double call(double T) {
|
||||
// Recalculate the densities using the current guess values
|
||||
HEOS->SatL->update_TP_guessrho(T, p, rhomolar_liq);
|
||||
@@ -597,12 +597,11 @@ void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend& HEOS, C
|
||||
// reset the phase for the next update.
|
||||
SatL->specify_phase(iphase_liquid);
|
||||
SatV->specify_phase(iphase_gas);
|
||||
if (error > 1e-8 && max_abs_value(v) > 1e-9){
|
||||
if (error > 1e-8 && max_abs_value(v) > 1e-9) {
|
||||
throw SolutionError(format("saturation_PHSU_pure solver was good, but went bad. Current error is %Lg", error));
|
||||
}
|
||||
}
|
||||
void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar, saturation_D_pure_options& options)
|
||||
{
|
||||
void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar, saturation_D_pure_options& options) {
|
||||
/*
|
||||
This function is inspired by the method of Akasaka:
|
||||
|
||||
@@ -708,41 +707,46 @@ void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend& HEOS, Cool
|
||||
|
||||
if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) {
|
||||
if (options.use_logdelta)
|
||||
deltaV = exp(log(deltaV)+omega*v[1]);
|
||||
else
|
||||
{
|
||||
if (deltaV + omega*v[1] <= 0) {omega = 0.5*deltaV/v[1];} // gone off track, take a smaller step
|
||||
if (tau + omega*v[0] <= 0) {omega = 0.5*tau/v[0];}
|
||||
deltaV += omega*v[1];
|
||||
deltaV = exp(log(deltaV) + omega * v[1]);
|
||||
else {
|
||||
if (deltaV + omega * v[1] <= 0) {
|
||||
omega = 0.5 * deltaV / v[1];
|
||||
} // gone off track, take a smaller step
|
||||
if (tau + omega * v[0] <= 0) {
|
||||
omega = 0.5 * tau / v[0];
|
||||
}
|
||||
deltaV += omega * v[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (options.use_logdelta)
|
||||
deltaL = exp(log(deltaL)+omega*v[1]);
|
||||
else
|
||||
{
|
||||
if (deltaL + omega*v[1] <= 0) {omega = 0.5*deltaL/v[1];} // gone off track, take a smaller step
|
||||
if (tau + omega*v[0] <= 0) {omega = 0.5*tau/v[0];}
|
||||
deltaL += omega*v[1];
|
||||
deltaL = exp(log(deltaL) + omega * v[1]);
|
||||
else {
|
||||
if (deltaL + omega * v[1] <= 0) {
|
||||
omega = 0.5 * deltaL / v[1];
|
||||
} // gone off track, take a smaller step
|
||||
if (tau + omega * v[0] <= 0) {
|
||||
omega = 0.5 * tau / v[0];
|
||||
}
|
||||
deltaL += omega * v[1];
|
||||
}
|
||||
}
|
||||
|
||||
tau += omega*v[0];
|
||||
tau += omega * v[0];
|
||||
|
||||
rhoL = deltaL*reduce.rhomolar;
|
||||
rhoV = deltaV*reduce.rhomolar;
|
||||
T = reduce.T/tau;
|
||||
rhoL = deltaL * reduce.rhomolar;
|
||||
rhoV = deltaV * reduce.rhomolar;
|
||||
T = reduce.T / tau;
|
||||
|
||||
p_error = (pL-pV)/pL;
|
||||
p_error = (pL - pV) / pL;
|
||||
|
||||
error = sqrt(pow(r[0], 2) + pow(r[1], 2));
|
||||
iter++;
|
||||
if (T < 0) {
|
||||
throw SolutionError(format("saturation_D_pure solver T < 0"));
|
||||
}
|
||||
if (iter > options.max_iterations){
|
||||
throw SolutionError(format("saturation_D_pure solver did not converge after %d iterations with rho: %g mol/m^3",options.max_iterations,rhomolar));
|
||||
if (iter > options.max_iterations) {
|
||||
throw SolutionError(
|
||||
format("saturation_D_pure solver did not converge after %d iterations with rho: %g mol/m^3", options.max_iterations, rhomolar));
|
||||
}
|
||||
} while (error > 1e-9);
|
||||
CoolPropDbl p_error_limit = 1e-3;
|
||||
@@ -961,7 +965,9 @@ void SaturationSolvers::saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend& HE
|
||||
&& !get_config_bool(DONT_CHECK_PROPERTY_LIMITS)) {
|
||||
|
||||
if (get_debug_level() > 5) {
|
||||
std::cout << format("[Maxwell] ancillaries correction T: %0.16Lg rhoL: %0.16Lg rhoV: %0.16Lg rhoc: %g rhoLtrip: %g rhoVtrip: %g\n", T, rhoL, rhoV, crit.rhomolar, tripleL.rhomolar, tripleV.rhomolar );
|
||||
std::cout << format(
|
||||
"[Maxwell] ancillaries correction T: %0.16Lg rhoL: %0.16Lg rhoV: %0.16Lg rhoc: %g rhoLtrip: %g rhoVtrip: %g\n", T, rhoL,
|
||||
rhoV, crit.rhomolar, tripleL.rhomolar, tripleV.rhomolar);
|
||||
}
|
||||
|
||||
// Lets assume that liquid density is more or less linear with T
|
||||
@@ -1722,7 +1728,7 @@ class RachfordRiceResidual : public FuncWrapper1DWithDeriv
|
||||
const std::vector<double>&z, &lnK;
|
||||
|
||||
public:
|
||||
RachfordRiceResidual(const std::vector<double>& z, const std::vector<double>& lnK) : z(z), lnK(lnK){};
|
||||
RachfordRiceResidual(const std::vector<double>& z, const std::vector<double>& lnK) : z(z), lnK(lnK) {};
|
||||
double call(double beta) {
|
||||
return FlashRoutines::g_RachfordRice(z, lnK, beta);
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ class newton_raphson_twophase
|
||||
beta(_HUGE),
|
||||
N(0),
|
||||
logging(false),
|
||||
Nsteps(0){};
|
||||
Nsteps(0) {};
|
||||
|
||||
void resize(unsigned int N);
|
||||
|
||||
@@ -489,7 +489,7 @@ class newton_raphson_saturation
|
||||
Eigen::VectorXd r, err_rel;
|
||||
std::vector<SuccessiveSubstitutionStep> step_logger;
|
||||
|
||||
newton_raphson_saturation(){};
|
||||
newton_raphson_saturation() {};
|
||||
|
||||
void resize(std::size_t N);
|
||||
|
||||
@@ -556,7 +556,7 @@ class PTflash_twophase
|
||||
PTflash_twophase_options& IO;
|
||||
std::vector<SuccessiveSubstitutionStep> step_logger;
|
||||
|
||||
PTflash_twophase(HelmholtzEOSMixtureBackend& HEOS, PTflash_twophase_options& IO) : HEOS(HEOS), IO(IO){};
|
||||
PTflash_twophase(HelmholtzEOSMixtureBackend& HEOS, PTflash_twophase_options& IO) : HEOS(HEOS), IO(IO) {};
|
||||
|
||||
/** \brief Call the Newton-Raphson Solver to solve the equilibrium conditions
|
||||
*
|
||||
@@ -607,7 +607,7 @@ class StabilityEvaluationClass
|
||||
m_T(-1),
|
||||
m_p(-1),
|
||||
_stable(false),
|
||||
debug(false){};
|
||||
debug(false) {};
|
||||
/** \brief Specify T&P, otherwise they are loaded the HEOS instance
|
||||
*/
|
||||
void set_TP(double T, double p) {
|
||||
|
||||
@@ -18,8 +18,8 @@ class IF97Backend : public AbstractState
|
||||
/// Additional cached elements used only in this backend since the "normal"
|
||||
/// backends use only molar units while IF97 uses mass-based units
|
||||
CachedElement _hmass, _rhomass, _smass,
|
||||
_reverse; // Also need a way to flag using the IF97 reverse calcs for h(p,s) and s(p,h)
|
||||
/// CachedElement _hVmass, _hLmass, _sVmass, sLmass;
|
||||
_reverse; // Also need a way to flag using the IF97 reverse calcs for h(p,s) and s(p,h)
|
||||
/// CachedElement _hVmass, _hLmass, _sVmass, sLmass;
|
||||
|
||||
public:
|
||||
/// The name of the backend being used
|
||||
@@ -40,7 +40,7 @@ class IF97Backend : public AbstractState
|
||||
void set_mole_fractions(const std::vector<CoolPropDbl>& mole_fractions) {
|
||||
throw NotImplementedError("Mole composition has not been implemented.");
|
||||
};
|
||||
void set_mass_fractions(const std::vector<CoolPropDbl>& mass_fractions){}; // Not implemented, but don't throw any errors
|
||||
void set_mass_fractions(const std::vector<CoolPropDbl>& mass_fractions) {}; // Not implemented, but don't throw any errors
|
||||
void set_volu_fractions(const std::vector<CoolPropDbl>& volu_fractions) {
|
||||
throw NotImplementedError("Volume composition has not been implemented.");
|
||||
};
|
||||
@@ -67,7 +67,7 @@ class IF97Backend : public AbstractState
|
||||
|
||||
// Set phase based on cached values in _p & _T or, if reverse, from (_p,_smass) or (_p,_hmass)
|
||||
void set_phase() {
|
||||
double epsilon = 3.3e-5; // IAPWS-IF97 RMS saturated pressure inconsistency
|
||||
double epsilon = 3.3e-5; // IAPWS-IF97 RMS saturated pressure inconsistency
|
||||
if (!_reverse) {
|
||||
if ((std::abs(_T - IF97::Tcrit) < epsilon / 10.0) && // RMS temperature inconsistency ~ epsilon/10
|
||||
(std::abs(_p - IF97::Pcrit) < epsilon)) { // within epsilon of [Tcrit,Pcrit]
|
||||
@@ -75,45 +75,45 @@ class IF97Backend : public AbstractState
|
||||
} else if (_T > IF97::Tcrit) { // to the right of the critical point
|
||||
if (_p > IF97::Pcrit) { // above the critical point pressure
|
||||
_phase = iphase_supercritical;
|
||||
} else { // below the critical point pressure
|
||||
} else { // below the critical point pressure
|
||||
_phase = iphase_supercritical_gas;
|
||||
}
|
||||
} else { // to the left of the critical point
|
||||
if (_p > IF97::Pcrit) { // above the critical point pressure
|
||||
} else { // to the left of the critical point
|
||||
if (_p > IF97::Pcrit) { // above the critical point pressure
|
||||
_phase = iphase_supercritical_liquid;
|
||||
} else { // at or below critical point pressure
|
||||
} else { // at or below critical point pressure
|
||||
double psat = IF97::psat97(_T);
|
||||
if (_p > psat * (1.0 + epsilon)) { // above the saturation curve
|
||||
if (_p > psat * (1.0 + epsilon)) { // above the saturation curve
|
||||
_phase = iphase_liquid;
|
||||
} else if (_p < psat * (1.0 - epsilon)) { // below the saturation curve
|
||||
} else if (_p < psat * (1.0 - epsilon)) { // below the saturation curve
|
||||
_phase = iphase_gas;
|
||||
} else // exactly on saturation curve (within 1e-4 %)
|
||||
} else // exactly on saturation curve (within 1e-4 %)
|
||||
_phase = iphase_twophase;
|
||||
}
|
||||
}
|
||||
} else { // Backwards: Determine phase from _p & _smass or _hmass
|
||||
} else { // Backwards: Determine phase from _p & _smass or _hmass
|
||||
int IF97Region;
|
||||
if (_smass) { // Get IF97 Region
|
||||
IF97Region = IF97::BackwardRegion(_p, _smass, IF97_SMASS); // using p, s
|
||||
} else {
|
||||
IF97Region = IF97::BackwardRegion(_p, _hmass, IF97_HMASS); // using p, h
|
||||
}
|
||||
switch (IF97Region) { // Convert IF97 Region to CP iPhase
|
||||
case 1: // IF97::REGION1
|
||||
switch (IF97Region) { // Convert IF97 Region to CP iPhase
|
||||
case 1: // IF97::REGION1
|
||||
if (_p <= IF97::Pcrit) {
|
||||
_phase = iphase_liquid;
|
||||
} else {
|
||||
_phase = iphase_supercritical_liquid;
|
||||
};
|
||||
break;
|
||||
case 2: // IF97::REGION2
|
||||
case 2: // IF97::REGION2
|
||||
if (_T <= IF97::Tcrit) {
|
||||
_phase = iphase_gas;
|
||||
} else {
|
||||
_phase = iphase_supercritical_gas;
|
||||
};
|
||||
break;
|
||||
case 3: // IF97::REGION3
|
||||
case 3: // IF97::REGION3
|
||||
if (_T < IF97::Tsat97(_p)) {
|
||||
if (_p <= IF97::Pcrit) {
|
||||
_phase = iphase_liquid;
|
||||
@@ -128,10 +128,10 @@ class IF97Backend : public AbstractState
|
||||
}
|
||||
};
|
||||
break;
|
||||
case 4: // IF97::REGION4 (Saturation
|
||||
_phase = iphase_twophase; // already handled but here for completeness
|
||||
case 4: // IF97::REGION4 (Saturation
|
||||
_phase = iphase_twophase; // already handled but here for completeness
|
||||
break;
|
||||
case 5: // IF97::REGION5 or O.B.
|
||||
case 5: // IF97::REGION5 or O.B.
|
||||
default:
|
||||
throw CoolProp::OutOfRangeError("Outside of IF97 Reverse Function Bounds");
|
||||
break;
|
||||
@@ -187,9 +187,9 @@ class IF97Backend : public AbstractState
|
||||
case HmassP_INPUTS:
|
||||
if (!(_hmass)) _hmass = value1; // don't set if already set above
|
||||
_p = value2;
|
||||
_reverse = 1.0; // only ever set for HP and SP Inputs
|
||||
_reverse = 1.0; // only ever set for HP and SP Inputs
|
||||
_T = IF97::T_phmass(_p, _hmass);
|
||||
_Q = -1; // Default if not set in 2-Phase Region
|
||||
_Q = -1; // Default if not set in 2-Phase Region
|
||||
// ...if in the vapor dome (Region 4), calculate Quality...
|
||||
if (IF97::BackwardRegion(_p, _hmass, IF97_HMASS) == 4) {
|
||||
H = _hmass;
|
||||
|
||||
@@ -37,7 +37,7 @@ class IncompressibleBackend : public AbstractState
|
||||
|
||||
public:
|
||||
IncompressibleBackend();
|
||||
virtual ~IncompressibleBackend(){};
|
||||
virtual ~IncompressibleBackend() {};
|
||||
std::string backend_name(void) {
|
||||
return get_backend_string(INCOMP_BACKEND);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ double IncompressibleFluid::baseExponential(IncompressibleData data, double y, d
|
||||
}
|
||||
|
||||
// Guard the function against zero denominators in exp((double)(coeffs[0] / ((y - ybase) + coeffs[1]) - coeffs[2]))
|
||||
auto fnc = [&](double x) { return exp((double)(coeffs[0] / (x) - coeffs[2])); } ;
|
||||
auto fnc = [&](double x) { return exp((double)(coeffs[0] / (x)-coeffs[2])); };
|
||||
double x_den = (y - ybase) + coeffs[1];
|
||||
double x_lo = -INCOMP_EPSILON;
|
||||
double x_hi = +INCOMP_EPSILON;
|
||||
@@ -68,7 +68,7 @@ double IncompressibleFluid::baseLogexponential(IncompressibleData data, double y
|
||||
}
|
||||
|
||||
// Guard the function against zero denominators in exp((double)(log((double)(1.0 / ((y - ybase) + coeffs[0]) + 1.0 / ((y - ybase) + coeffs[0]) / ((y - ybase) + coeffs[0]))) * coeffs[1] + coeffs[2]))
|
||||
auto fnc = [&](double x) { return exp((double)(log((double)(1.0 / (x) + 1.0 / (x) / (x))) * coeffs[1] + coeffs[2])); } ;
|
||||
auto fnc = [&](double x) { return exp((double)(log((double)(1.0 / (x) + 1.0 / (x) / (x))) * coeffs[1] + coeffs[2])); };
|
||||
double x_den = (y - ybase) + coeffs[0];
|
||||
double x_lo = -INCOMP_EPSILON;
|
||||
double x_hi = +INCOMP_EPSILON;
|
||||
@@ -695,7 +695,7 @@ TEST_CASE("Internal consistency checks and example use cases for the incompressi
|
||||
CHECK_THROWS(CH3OH.u(T, p, x));
|
||||
|
||||
// Compare viscosity
|
||||
expected = 0.0023970245009602097; // Pa-s // Melinder 3.48 mPas @ 24.87 wt%, 0C
|
||||
expected = 0.0023970245009602097; // Pa-s // Melinder 3.48 mPas @ 24.87 wt%, 0C
|
||||
actual = CH3OH.visc(T, p, x);
|
||||
{
|
||||
CAPTURE(T);
|
||||
|
||||
@@ -334,11 +334,11 @@ JSONIncompressibleLibrary::JSONIncompressibleLibrary() {
|
||||
};
|
||||
|
||||
/// Default destructor
|
||||
JSONIncompressibleLibrary::~JSONIncompressibleLibrary(){
|
||||
// freeClear(fluid_map);
|
||||
// fluid_map.clear();
|
||||
// name_vector.clear();
|
||||
// string_to_index_map.clear();
|
||||
JSONIncompressibleLibrary::~JSONIncompressibleLibrary() {
|
||||
// freeClear(fluid_map);
|
||||
// fluid_map.clear();
|
||||
// name_vector.clear();
|
||||
// string_to_index_map.clear();
|
||||
};
|
||||
|
||||
/// A general function to parse the json files that hold the coefficient matrices
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,24 +15,26 @@ namespace CoolProp {
|
||||
|
||||
const static double kb = 1.380649e-23; // Boltzmann constant, J K^-1
|
||||
const static double PI = 3.141592653589793;
|
||||
const static double N_AV = 6.02214076e23; // Avagadro's number
|
||||
const static double E_CHRG = 1.6021766208e-19; // elementary charge, units of coulomb
|
||||
const static double perm_vac = 8.854187817e-22; //permittivity in vacuum, C V^-1 Angstrom^-1
|
||||
const static double N_AV = 6.02214076e23; // Avagadro's number
|
||||
const static double E_CHRG = 1.6021766208e-19; // elementary charge, units of coulomb
|
||||
const static double perm_vac = 8.854187817e-22; //permittivity in vacuum, C V^-1 Angstrom^-1
|
||||
|
||||
class PCSAFTBackend : public AbstractState {
|
||||
class PCSAFTBackend : public AbstractState
|
||||
{
|
||||
|
||||
protected:
|
||||
std::vector<PCSAFTFluid> components; ///< The components that are in use
|
||||
std::vector<int> assoc_num; ///< The number of association sites for each molecule
|
||||
std::vector<int> assoc_matrix; ///< Whether or not association occurs between two association sites. 0 means no association, any nonzero number signifies association
|
||||
std::vector<double> k_ij; ///< binary interaction parameters
|
||||
std::vector<double> k_ijT; ///< temperature dependent binary interaction parameters
|
||||
bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false)
|
||||
std::vector<CoolPropDbl> mole_fractions; ///< The bulk mole fractions of the mixture
|
||||
std::vector<double> mole_fractions_double; ///< A copy of the bulk mole fractions of the mixture stored as doubles
|
||||
std::vector<CoolPropDbl> K, ///< The K factors for the components
|
||||
lnK; ///< The natural logarithms of the K factors of the components
|
||||
double dielc; ///< The dielectric constant of the solvent, if ion term is used
|
||||
protected:
|
||||
std::vector<PCSAFTFluid> components; ///< The components that are in use
|
||||
std::vector<int> assoc_num; ///< The number of association sites for each molecule
|
||||
std::vector<int>
|
||||
assoc_matrix; ///< Whether or not association occurs between two association sites. 0 means no association, any nonzero number signifies association
|
||||
std::vector<double> k_ij; ///< binary interaction parameters
|
||||
std::vector<double> k_ijT; ///< temperature dependent binary interaction parameters
|
||||
bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false)
|
||||
std::vector<CoolPropDbl> mole_fractions; ///< The bulk mole fractions of the mixture
|
||||
std::vector<double> mole_fractions_double; ///< A copy of the bulk mole fractions of the mixture stored as doubles
|
||||
std::vector<CoolPropDbl> K, ///< The K factors for the components
|
||||
lnK; ///< The natural logarithms of the K factors of the components
|
||||
double dielc; ///< The dielectric constant of the solvent, if ion term is used
|
||||
|
||||
shared_ptr<PCSAFTBackend> SatL;
|
||||
shared_ptr<PCSAFTBackend> SatV;
|
||||
@@ -48,20 +50,18 @@ protected:
|
||||
void post_update(bool optional_checks = true);
|
||||
|
||||
CoolPropDbl solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, phases phase);
|
||||
double estimate_flash_p(PCSAFTBackend &PCSAFT);
|
||||
double estimate_flash_t(PCSAFTBackend &PCSAFT);
|
||||
double outerTQ(double p_guess, PCSAFTBackend &PCSAFT);
|
||||
double outerPQ(double t_guess, PCSAFTBackend &PCSAFT);
|
||||
double estimate_flash_p(PCSAFTBackend& PCSAFT);
|
||||
double estimate_flash_t(PCSAFTBackend& PCSAFT);
|
||||
double outerTQ(double p_guess, PCSAFTBackend& PCSAFT);
|
||||
double outerPQ(double t_guess, PCSAFTBackend& PCSAFT);
|
||||
phases calc_phase_internal(CoolProp::input_pairs input_pair);
|
||||
CoolPropDbl reduced_to_molar(CoolPropDbl nu, CoolPropDbl T);
|
||||
|
||||
// these functions are used internally to solve for association parameters
|
||||
vector<double> XA_find(vector<double> XA_guess, vector<double> delta_ij, double den,
|
||||
vector<double> x);
|
||||
vector<double> dXAdx_find(vector<int> assoc_num, vector<double> delta_ij,
|
||||
double den, vector<double> XA, vector<double> ddelta_dx, vector<double> x);
|
||||
vector<double> dXAdt_find(vector<double> delta_ij, double den,
|
||||
vector<double> XA, vector<double> ddelta_dt, vector<double> x);
|
||||
vector<double> XA_find(vector<double> XA_guess, vector<double> delta_ij, double den, vector<double> x);
|
||||
vector<double> dXAdx_find(vector<int> assoc_num, vector<double> delta_ij, double den, vector<double> XA, vector<double> ddelta_dx,
|
||||
vector<double> x);
|
||||
vector<double> dXAdt_find(vector<double> delta_ij, double den, vector<double> XA, vector<double> ddelta_dt, vector<double> x);
|
||||
void set_assoc_matrix();
|
||||
double dielc_water(double t);
|
||||
|
||||
|
||||
@@ -75,19 +75,18 @@ char refpropPath[] = "";
|
||||
#endif
|
||||
|
||||
/// Query an environment variable and return in optional if present
|
||||
std::optional<std::string> get_envvar(const char* var){
|
||||
std::optional<std::string> get_envvar(const char* var) {
|
||||
char* valptr = getenv(var);
|
||||
if(valptr == nullptr){
|
||||
if (valptr == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return std::string(valptr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Find either FLUIDS or fluids folder relative to the root path provided; return the path
|
||||
std::string get_casesensitive_fluids(const std::string& root) {
|
||||
if (get_envvar("COOLPROP_REFPROP_ROOT")){
|
||||
if (get_envvar("COOLPROP_REFPROP_ROOT")) {
|
||||
return "";
|
||||
}
|
||||
std::string joined = join_path(root, "fluids");
|
||||
@@ -103,7 +102,7 @@ std::string get_casesensitive_fluids(const std::string& root) {
|
||||
}
|
||||
}
|
||||
std::string get_REFPROP_fluid_path_prefix() {
|
||||
if (get_envvar("COOLPROP_REFPROP_ROOT")){
|
||||
if (get_envvar("COOLPROP_REFPROP_ROOT")) {
|
||||
return "";
|
||||
}
|
||||
std::string rpPath = refpropPath;
|
||||
@@ -129,7 +128,7 @@ std::string get_REFPROP_fluid_path_prefix() {
|
||||
#endif
|
||||
}
|
||||
std::string get_REFPROP_mixtures_path_prefix() {
|
||||
if (get_envvar("COOLPROP_REFPROP_ROOT")){
|
||||
if (get_envvar("COOLPROP_REFPROP_ROOT")) {
|
||||
return "";
|
||||
}
|
||||
std::string rpPath = refpropPath;
|
||||
@@ -236,18 +235,18 @@ bool REFPROPMixtureBackend::REFPROP_supported() {
|
||||
// Function names were defined in "REFPROP_lib.h",
|
||||
// This platform theoretically supports Refprop.
|
||||
std::string err;
|
||||
|
||||
|
||||
bool loaded_REFPROP = false;
|
||||
|
||||
|
||||
auto root = get_envvar("COOLPROP_REFPROP_ROOT");
|
||||
const std::string alt_rp_path = get_config_string(ALTERNATIVE_REFPROP_PATH);
|
||||
const std::string alt_rp_name = get_config_string(ALTERNATIVE_REFPROP_LIBRARY_PATH);
|
||||
|
||||
if (root){
|
||||
|
||||
if (root) {
|
||||
loaded_REFPROP = ::load_REFPROP(err, root.value().c_str(), "");
|
||||
SETPATHdll(const_cast<char*>(root.value().c_str()), 400);
|
||||
}
|
||||
if (!loaded_REFPROP){
|
||||
if (!loaded_REFPROP) {
|
||||
if (!alt_rp_name.empty()) {
|
||||
loaded_REFPROP = ::load_REFPROP(err, "", alt_rp_name);
|
||||
} else {
|
||||
@@ -566,12 +565,12 @@ std::string REFPROPMixtureBackend::get_binary_interaction_string(const std::stri
|
||||
std::string shmodij(hmodij);
|
||||
//if (shmodij.find("KW") == 0 || shmodij.find("GE") == 0) // Starts with KW or GE
|
||||
//{
|
||||
if (parameter == "model") {
|
||||
return shmodij;
|
||||
} else {
|
||||
throw ValueError(format(" I don't know what to do with your parameter [%s]", parameter.c_str()));
|
||||
return "";
|
||||
}
|
||||
if (parameter == "model") {
|
||||
return shmodij;
|
||||
} else {
|
||||
throw ValueError(format(" I don't know what to do with your parameter [%s]", parameter.c_str()));
|
||||
return "";
|
||||
}
|
||||
//} else {
|
||||
// //throw ValueError(format("For now, model [%s] must start with KW or GE", hmodij));
|
||||
// return "";
|
||||
@@ -583,12 +582,12 @@ void REFPROPMixtureBackend::set_binary_interaction_string(const std::size_t i, c
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= Ncomp) {
|
||||
if (j < 0 || j >= Ncomp) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, Ncomp-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, Ncomp - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, Ncomp-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, Ncomp - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= Ncomp) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, Ncomp-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, Ncomp - 1));
|
||||
}
|
||||
int icomp = static_cast<int>(i) + 1, jcomp = static_cast<int>(j) + 1, ierr = 0L;
|
||||
char hmodij[3], hfmix[255], hbinp[255], hfij[255], hmxrul[255];
|
||||
@@ -618,12 +617,12 @@ void REFPROPMixtureBackend::set_binary_interaction_double(const std::size_t i, c
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= Ncomp) {
|
||||
if (j < 0 || j >= Ncomp) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, Ncomp-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, Ncomp - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, Ncomp-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, Ncomp - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= Ncomp) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, Ncomp-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, Ncomp - 1));
|
||||
}
|
||||
int icomp = static_cast<int>(i) + 1, jcomp = static_cast<int>(j) + 1, ierr = 0L;
|
||||
char hmodij[3], hfmix[255], hbinp[255], hfij[255], hmxrul[255];
|
||||
@@ -636,23 +635,23 @@ void REFPROPMixtureBackend::set_binary_interaction_double(const std::size_t i, c
|
||||
std::string shmodij(hmodij);
|
||||
//if (shmodij.find("KW") == 0 || shmodij.find("GE") == 0) // Starts with KW or GE
|
||||
//{
|
||||
if (parameter == "betaT") {
|
||||
fij[0] = value;
|
||||
} else if (parameter == "gammaT") {
|
||||
fij[1] = value;
|
||||
} else if (parameter == "betaV") {
|
||||
fij[2] = value;
|
||||
} else if (parameter == "gammaV") {
|
||||
fij[3] = value;
|
||||
} else if (parameter == "Fij") {
|
||||
fij[4] = value;
|
||||
} else {
|
||||
throw ValueError(format("I don't know what to do with your parameter [%s]", parameter.c_str()));
|
||||
}
|
||||
SETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, &ierr, herr, 3, 255, 255);
|
||||
if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)) {
|
||||
throw ValueError(format("Unable to set parameter[%s] to value[%g]: %s", parameter.c_str(), value, herr));
|
||||
}
|
||||
if (parameter == "betaT") {
|
||||
fij[0] = value;
|
||||
} else if (parameter == "gammaT") {
|
||||
fij[1] = value;
|
||||
} else if (parameter == "betaV") {
|
||||
fij[2] = value;
|
||||
} else if (parameter == "gammaV") {
|
||||
fij[3] = value;
|
||||
} else if (parameter == "Fij") {
|
||||
fij[4] = value;
|
||||
} else {
|
||||
throw ValueError(format("I don't know what to do with your parameter [%s]", parameter.c_str()));
|
||||
}
|
||||
SETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, &ierr, herr, 3, 255, 255);
|
||||
if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)) {
|
||||
throw ValueError(format("Unable to set parameter[%s] to value[%g]: %s", parameter.c_str(), value, herr));
|
||||
}
|
||||
//} else {
|
||||
// throw ValueError(format("For now, model [%s] must start with KW or GE", hmodij));
|
||||
//}
|
||||
@@ -663,12 +662,12 @@ double REFPROPMixtureBackend::get_binary_interaction_double(const std::size_t i,
|
||||
// bound-check indices
|
||||
if (i < 0 || i >= Ncomp) {
|
||||
if (j < 0 || j >= Ncomp) {
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, Ncomp-1));
|
||||
throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, Ncomp - 1));
|
||||
} else {
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, Ncomp-1));
|
||||
throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, Ncomp - 1));
|
||||
}
|
||||
} else if (j < 0 || j >= Ncomp) {
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, Ncomp-1));
|
||||
throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, Ncomp - 1));
|
||||
}
|
||||
int icomp = static_cast<int>(i) + 1, jcomp = static_cast<int>(j) + 1;
|
||||
char hmodij[3], hfmix[255], hbinp[255], hfij[255], hmxrul[255];
|
||||
@@ -680,22 +679,22 @@ double REFPROPMixtureBackend::get_binary_interaction_double(const std::size_t i,
|
||||
std::string shmodij(hmodij);
|
||||
//if (shmodij.find("KW") == 0 || shmodij.find("GE") == 0) // Starts with KW or GE
|
||||
//{
|
||||
double val;
|
||||
if (parameter == "betaT") {
|
||||
val = fij[0];
|
||||
} else if (parameter == "gammaT") {
|
||||
val = fij[1];
|
||||
} else if (parameter == "betaV") {
|
||||
val = fij[2];
|
||||
} else if (parameter == "gammaV") {
|
||||
val = fij[3];
|
||||
} else if (parameter == "Fij") {
|
||||
val = fij[4];
|
||||
} else {
|
||||
throw ValueError(format(" I don't know what to do with your parameter [%s]", parameter.c_str()));
|
||||
return _HUGE;
|
||||
}
|
||||
return val;
|
||||
double val;
|
||||
if (parameter == "betaT") {
|
||||
val = fij[0];
|
||||
} else if (parameter == "gammaT") {
|
||||
val = fij[1];
|
||||
} else if (parameter == "betaV") {
|
||||
val = fij[2];
|
||||
} else if (parameter == "gammaV") {
|
||||
val = fij[3];
|
||||
} else if (parameter == "Fij") {
|
||||
val = fij[4];
|
||||
} else {
|
||||
throw ValueError(format(" I don't know what to do with your parameter [%s]", parameter.c_str()));
|
||||
return _HUGE;
|
||||
}
|
||||
return val;
|
||||
//} else {
|
||||
// //throw ValueError(format("For now, model [%s] must start with KW or GE", hmodij));
|
||||
// return _HUGE;
|
||||
@@ -1241,7 +1240,7 @@ phases REFPROPMixtureBackend::GetRPphase() {
|
||||
}
|
||||
} else { // RefProp might return Q = 920 for Metastable
|
||||
RPphase = iphase_unknown; // but CoolProp doesn't have an enumerator for this state,
|
||||
} // so it's unknown as well.
|
||||
} // so it's unknown as well.
|
||||
|
||||
if ((_Q == 999) || (_Q == -997)) { // One last check for _Q == 999||-997 (Supercritical)
|
||||
RPphase = iphase_supercritical; // T >= Tcrit AND P >= Pcrit
|
||||
@@ -1712,10 +1711,10 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu
|
||||
} // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());}
|
||||
|
||||
// Set all cache values that can be set with unit conversion to SI
|
||||
_p = p_kPa * 1000; // 1000 for conversion from kPa to Pa
|
||||
_rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3
|
||||
_rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3
|
||||
_rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3
|
||||
_p = p_kPa * 1000; // 1000 for conversion from kPa to Pa
|
||||
_rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3
|
||||
_rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3
|
||||
_rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3
|
||||
break;
|
||||
}
|
||||
case TUmass_INPUTS: {
|
||||
@@ -2072,7 +2071,7 @@ void REFPROPMixtureBackend::calc_true_critical_point(double& T, double& rho) {
|
||||
{
|
||||
public:
|
||||
const std::vector<double> z;
|
||||
wrapper(const std::vector<double>& z) : z(z){};
|
||||
wrapper(const std::vector<double>& z) : z(z) {};
|
||||
std::vector<double> call(const std::vector<double>& x) {
|
||||
std::vector<double> r(2);
|
||||
double dpdrho__constT = _HUGE, d2pdrho2__constT = _HUGE;
|
||||
@@ -2149,7 +2148,7 @@ void REFPROPMixtureBackend::calc_ideal_curve(const std::string& type, std::vecto
|
||||
}
|
||||
};
|
||||
|
||||
THERM0dllOutputs REFPROPMixtureBackend::call_THERM0dll(double T, double rho_mol_dm3, const std::vector<double> &mole_fractions){
|
||||
THERM0dllOutputs REFPROPMixtureBackend::call_THERM0dll(double T, double rho_mol_dm3, const std::vector<double>& mole_fractions) {
|
||||
/*
|
||||
subroutineTHERM0dll(T, D, z, P0, e0, h0, s0, Cv0, Cp00, w0, a0, g0)
|
||||
Compute ideal-gas thermal quantities as a function of temperature, density, and composition from core functions.
|
||||
@@ -2171,12 +2170,13 @@ THERM0dllOutputs REFPROPMixtureBackend::call_THERM0dll(double T, double rho_mol_
|
||||
g0 [double ,out] :: Gibbs free energy [J/mol]
|
||||
*/
|
||||
THERM0dllOutputs o;
|
||||
if (mole_fractions.size() != 20){
|
||||
if (mole_fractions.size() != 20) {
|
||||
throw ValueError("mole fractions must be of size 20");
|
||||
}
|
||||
std::vector<double> mf = mole_fractions;
|
||||
|
||||
THERM0dll(&T, &rho_mol_dm3, &(mf[0]), &o.p_kPa, &o.umol_Jmol, &o.hmol_Jmol, &o.smol_JmolK, &o.cvmol_JmolK, &o.cpmol_JmolK, &o.w_ms, &o.amol_Jmol, &o.gmol_Jmol);
|
||||
|
||||
THERM0dll(&T, &rho_mol_dm3, &(mf[0]), &o.p_kPa, &o.umol_Jmol, &o.hmol_Jmol, &o.smol_JmolK, &o.cvmol_JmolK, &o.cpmol_JmolK, &o.w_ms, &o.amol_Jmol,
|
||||
&o.gmol_Jmol);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,17 @@
|
||||
|
||||
namespace CoolProp {
|
||||
|
||||
struct THERM0dllOutputs{
|
||||
double p_kPa; /// Pressure [kPa]
|
||||
double umol_Jmol; /// Internal energy [J/mol]
|
||||
double hmol_Jmol; /// Enthalpy [J/mol]
|
||||
double smol_JmolK; /// Entropy [J/mol-K]
|
||||
double cvmol_JmolK; /// Isochoric heat capacity [J/mol-K]
|
||||
double cpmol_JmolK; /// Isobaric heat capacity [J/mol-K]
|
||||
double w_ms; /// Speed of sound [m/s]
|
||||
double amol_Jmol; ///Helmholtz energy [J/mol]
|
||||
double gmol_Jmol; /// Gibbs free energy [J/mol]
|
||||
struct THERM0dllOutputs
|
||||
{
|
||||
double p_kPa; /// Pressure [kPa]
|
||||
double umol_Jmol; /// Internal energy [J/mol]
|
||||
double hmol_Jmol; /// Enthalpy [J/mol]
|
||||
double smol_JmolK; /// Entropy [J/mol-K]
|
||||
double cvmol_JmolK; /// Isochoric heat capacity [J/mol-K]
|
||||
double cpmol_JmolK; /// Isobaric heat capacity [J/mol-K]
|
||||
double w_ms; /// Speed of sound [m/s]
|
||||
double amol_Jmol; ///Helmholtz energy [J/mol]
|
||||
double gmol_Jmol; /// Gibbs free energy [J/mol]
|
||||
};
|
||||
|
||||
class REFPROPMixtureBackend : public AbstractState
|
||||
@@ -263,9 +264,9 @@ class REFPROPMixtureBackend : public AbstractState
|
||||
CoolPropDbl calc_Tmax(void);
|
||||
/// Calculate the minimum temperature
|
||||
CoolPropDbl calc_Tmin(void);
|
||||
|
||||
|
||||
/// Call into the THERM0dll method and return outputs as a struct. REFPROP must already be setup
|
||||
THERM0dllOutputs call_THERM0dll(double T, double rho_mol_dm3, const std::vector<double> &mole_fractions);
|
||||
THERM0dllOutputs call_THERM0dll(double T, double rho_mol_dm3, const std::vector<double>& mole_fractions);
|
||||
|
||||
/// Calculate the residual entropy in J/mol/K (should be a uniquely negative quantity)
|
||||
CoolPropDbl calc_smolar_residual(void) {
|
||||
|
||||
@@ -97,7 +97,7 @@ class PackablePhaseEnvelopeData : public PhaseEnvelopeData
|
||||
public:
|
||||
int revision;
|
||||
|
||||
PackablePhaseEnvelopeData() : revision(0){};
|
||||
PackablePhaseEnvelopeData() : revision(0) {};
|
||||
|
||||
void copy_from_nonpackable(const PhaseEnvelopeData& PED) {
|
||||
/* Use X macros to auto-generate the copying */
|
||||
@@ -106,7 +106,7 @@ class PackablePhaseEnvelopeData : public PhaseEnvelopeData
|
||||
#undef X
|
||||
/* Use X macros to auto-generate the copying */
|
||||
#define X(name) name = PED.name;
|
||||
PHASE_ENVELOPE_MATRICES
|
||||
PHASE_ENVELOPE_MATRICES
|
||||
#undef X
|
||||
};
|
||||
|
||||
@@ -123,7 +123,7 @@ class PackablePhaseEnvelopeData : public PhaseEnvelopeData
|
||||
#undef X
|
||||
/* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair<std::string, std::vector<std::vector<CoolPropDbl> > >("T", T)); */
|
||||
#define X(name) matrices.insert(std::pair<std::string, std::vector<std::vector<double>>>(#name, name));
|
||||
PHASE_ENVELOPE_MATRICES
|
||||
PHASE_ENVELOPE_MATRICES
|
||||
#undef X
|
||||
};
|
||||
std::map<std::string, std::vector<double>>::iterator get_vector_iterator(const std::string& name) {
|
||||
@@ -1035,7 +1035,7 @@ class TabularDataLibrary
|
||||
std::map<std::string, TabularDataSet> data;
|
||||
|
||||
public:
|
||||
TabularDataLibrary(){};
|
||||
TabularDataLibrary() {};
|
||||
std::string path_to_tables(shared_ptr<CoolProp::AbstractState>& AS) {
|
||||
std::vector<std::string> fluids = AS->fluid_names();
|
||||
std::vector<CoolPropDbl> fractions = AS->get_mole_fractions();
|
||||
|
||||
@@ -37,7 +37,7 @@ std::string format(const char* fmt, ...) {
|
||||
static void delarray(char* p) {
|
||||
delete[] p;
|
||||
}
|
||||
}; // to use delete[]
|
||||
}; // to use delete[]
|
||||
shared_ptr<char> buffer(new char[size], deleter::delarray); // I'd prefer unique_ptr, but it's only available since c++11
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
@@ -67,8 +67,8 @@ configuration_keys config_string_to_key(const std::string& s) {
|
||||
|
||||
std::unique_ptr<Configuration> pconfig;
|
||||
/// A helper function to ensure that configuration is not accessed before it is initialized (was formerly static)
|
||||
Configuration* _get_config(){
|
||||
if (!pconfig){
|
||||
Configuration* _get_config() {
|
||||
if (!pconfig) {
|
||||
pconfig = std::make_unique<Configuration>();
|
||||
}
|
||||
return pconfig.get();
|
||||
|
||||
@@ -117,7 +117,7 @@ bool has_solution_concentration(const std::string& fluid_string) {
|
||||
struct delim : std::numpunct<char>
|
||||
{
|
||||
char m_c;
|
||||
delim(char c) : m_c(c){};
|
||||
delim(char c) : m_c(c) {};
|
||||
char do_decimal_point() const {
|
||||
return m_c;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ std::string extract_fractions(const std::string& fluid_string, std::vector<doubl
|
||||
// with the configuration variable FLOAT_PUNCTUATION to change the locale to something more convenient for you (e.g., a ',')
|
||||
// See also http://en.cppreference.com/w/cpp/locale/numpunct/decimal_point
|
||||
std::stringstream ssfraction(fraction);
|
||||
char c = get_config_string(FLOAT_PUNCTUATION)[0];
|
||||
const char c = get_config_string(FLOAT_PUNCTUATION)[0];
|
||||
ssfraction.imbue(std::locale(ssfraction.getloc(), new delim(c)));
|
||||
double f;
|
||||
ssfraction >> f;
|
||||
@@ -228,7 +228,7 @@ void _PropsSI_initialize(const std::string& backend, const std::vector<std::stri
|
||||
} else if (fluid_names.size() == 1) {
|
||||
if (has_fractions_in_string(fluid_names[0]) || has_solution_concentration(fluid_names[0])) {
|
||||
// Extract fractions from the string
|
||||
std::string fluid_string = extract_fractions(fluid_names[0], fractions);
|
||||
const std::string fluid_string = extract_fractions(fluid_names[0], fractions);
|
||||
// Set the pointer - we are going to use the extracted fractions
|
||||
fractions_ptr = &fractions;
|
||||
// Reset the state
|
||||
@@ -319,7 +319,7 @@ void _PropsSI_outputs(shared_ptr<AbstractState>& State, const std::vector<output
|
||||
if (in1.size() != in2.size()) {
|
||||
throw ValueError(format("lengths of in1 [%d] and in2 [%d] are not the same", in1.size(), in2.size()));
|
||||
}
|
||||
bool one_input_one_output = (in1.size() == 1 && in2.size() == 1 && output_parameters.size() == 1);
|
||||
const bool one_input_one_output = (in1.size() == 1 && in2.size() == 1 && output_parameters.size() == 1);
|
||||
// If all trivial outputs, never do a state update
|
||||
bool all_trivial_outputs = true;
|
||||
for (std::size_t j = 0; j < output_parameters.size(); ++j) {
|
||||
@@ -362,8 +362,8 @@ void _PropsSI_outputs(shared_ptr<AbstractState>& State, const std::vector<output
|
||||
GuessesStructure guesses;
|
||||
|
||||
// Resize the output matrix
|
||||
std::size_t N1 = std::max(static_cast<std::size_t>(1), in1.size());
|
||||
std::size_t N2 = std::max(static_cast<std::size_t>(1), output_parameters.size());
|
||||
const std::size_t N1 = std::max(static_cast<std::size_t>(1), in1.size());
|
||||
const std::size_t N2 = std::max(static_cast<std::size_t>(1), output_parameters.size());
|
||||
IO.resize(N1, std::vector<double>(N2, _HUGE));
|
||||
|
||||
// Throw an error if at the end, there were no successes
|
||||
@@ -498,7 +498,7 @@ bool StripPhase(std::string& Name, shared_ptr<AbstractState>& State)
|
||||
std::vector<std::string> strVec = strsplit(Name, '|'); // Split input key string in to vector containing input key [0] and phase string [1]
|
||||
if (strVec.size() > 1) { // If there is a phase string (contains "|" character)
|
||||
// Check for invalid backends for setting phase in PropsSI
|
||||
std::string strBackend = State->backend_name();
|
||||
const std::string strBackend = State->backend_name();
|
||||
if (strBackend == get_backend_string(INCOMP_BACKEND))
|
||||
throw ValueError("Cannot set phase on Incompressible Fluid; always liquid phase"); // incompressible fluids are always "liquid".
|
||||
if (strBackend == get_backend_string(IF97_BACKEND))
|
||||
@@ -555,10 +555,10 @@ void _PropsSImulti(const std::vector<std::string>& Outputs, const std::string& N
|
||||
}
|
||||
|
||||
//strip any imposed phase from input key strings here
|
||||
std::string N1 = Name1; // Make Non-constant copy of Name1 that we can modify
|
||||
std::string N2 = Name2; // Make Non-constant copy of Name2 that we can modify
|
||||
bool HasPhase1 = StripPhase(N1, State); // strip phase string from first name if needed
|
||||
bool HasPhase2 = StripPhase(N2, State); // strip phase string from second name if needed
|
||||
std::string N1 = Name1; // Make Non-constant copy of Name1 that we can modify
|
||||
std::string N2 = Name2; // Make Non-constant copy of Name2 that we can modify
|
||||
const bool HasPhase1 = StripPhase(N1, State); // strip phase string from first name if needed
|
||||
const bool HasPhase2 = StripPhase(N2, State); // strip phase string from second name if needed
|
||||
if (HasPhase1 && HasPhase2) // if both Names have a phase string, don't allow it.
|
||||
throw ValueError("Phase can only be specified on one of the input key strings");
|
||||
|
||||
@@ -610,7 +610,7 @@ std::vector<std::vector<double>> PropsSImulti(const std::vector<std::string>& Ou
|
||||
#endif
|
||||
return std::vector<std::vector<double>>();
|
||||
}
|
||||
double PropsSI(const std::string& Output, const std::string& Name1, double Prop1, const std::string& Name2, double Prop2, const std::string& Ref) {
|
||||
double PropsSI(const std::string& Output, const std::string& Name1, double Prop1, const std::string& Name2, double Prop2, const std::string& FluidName) {
|
||||
#if !defined(NO_ERROR_CATCHING)
|
||||
try {
|
||||
#endif
|
||||
@@ -619,10 +619,10 @@ double PropsSI(const std::string& Output, const std::string& Name1, double Prop1
|
||||
// Here is the real code that is inside the try block
|
||||
|
||||
std::string backend, fluid;
|
||||
extract_backend(Ref, backend, fluid);
|
||||
extract_backend(FluidName, backend, fluid);
|
||||
std::vector<double> fractions(1, 1.0);
|
||||
// extract_fractions checks for has_fractions_in_string / has_solution_concentration; no need to double check
|
||||
std::string fluid_string = extract_fractions(fluid, fractions);
|
||||
const std::string fluid_string = extract_fractions(fluid, fractions);
|
||||
std::vector<std::vector<double>> IO;
|
||||
_PropsSImulti(strsplit(Output, '&'), Name1, std::vector<double>(1, Prop1), Name2, std::vector<double>(1, Prop2), backend,
|
||||
strsplit(fluid_string, '&'), fractions, IO);
|
||||
@@ -633,7 +633,7 @@ double PropsSI(const std::string& Output, const std::string& Name1, double Prop1
|
||||
throw ValueError(format("output should be 1x1; error was %s", get_global_param_string("errstring").c_str()));
|
||||
}
|
||||
|
||||
double val = IO[0][0];
|
||||
const double val = IO[0][0];
|
||||
|
||||
if (get_debug_level() > 1) {
|
||||
std::cout << format("_PropsSI will return %g", val) << std::endl;
|
||||
@@ -644,7 +644,7 @@ double PropsSI(const std::string& Output, const std::string& Name1, double Prop1
|
||||
} catch (const std::exception& e) {
|
||||
set_error_string(
|
||||
e.what()
|
||||
+ format(" : PropsSI(\"%s\",\"%s\",%0.10g,\"%s\",%0.10g,\"%s\")", Output.c_str(), Name1.c_str(), Prop1, Name2.c_str(), Prop2, Ref.c_str()));
|
||||
+ format(" : PropsSI(\"%s\",\"%s\",%0.10g,\"%s\",%0.10g,\"%s\")", Output.c_str(), Name1.c_str(), Prop1, Name2.c_str(), Prop2, FluidName.c_str()));
|
||||
# if defined(PROPSSI_ERROR_STDOUT)
|
||||
std::cout << e.what() << std::endl;
|
||||
# endif
|
||||
@@ -810,8 +810,8 @@ TEST_CASE("Check inputs to PropsSI", "[PropsSI]") {
|
||||
****************************************************/
|
||||
|
||||
double Props1SI(std::string FluidName, std::string Output) {
|
||||
bool valid_fluid1 = is_valid_fluid_string(FluidName);
|
||||
bool valid_fluid2 = is_valid_fluid_string(Output);
|
||||
const bool valid_fluid1 = is_valid_fluid_string(FluidName);
|
||||
const bool valid_fluid2 = is_valid_fluid_string(Output);
|
||||
if (valid_fluid1 && valid_fluid2) {
|
||||
set_error_string(format("Both inputs to Props1SI [%s,%s] are valid fluids", Output.c_str(), FluidName.c_str()));
|
||||
return _HUGE;
|
||||
@@ -826,7 +826,7 @@ double Props1SI(std::string FluidName, std::string Output) {
|
||||
}
|
||||
|
||||
// First input is the fluid, second input is the input parameter
|
||||
double val1 = PropsSI(Output, "", 0, "", 0, FluidName);
|
||||
const double val1 = PropsSI(Output, "", 0, "", 0, FluidName);
|
||||
if (!ValidNumber(val1)) {
|
||||
set_error_string(format("Unable to use input parameter [%s] in Props1SI for fluid %s; error was %s", Output.c_str(), FluidName.c_str(),
|
||||
get_global_param_string("errstring").c_str()));
|
||||
@@ -836,14 +836,14 @@ double Props1SI(std::string FluidName, std::string Output) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::vector<double>> Props1SImulti(const std::vector<std::string>& Outputs, const std::string& backend, const std::vector<std::string>& fluids, const std::vector<double>& fractions) {
|
||||
std::vector<std::vector<double>> Props1SImulti(const std::vector<std::string>& Outputs, const std::string& backend,
|
||||
const std::vector<std::string>& fluids, const std::vector<double>& fractions) {
|
||||
std::vector<double> zero_vector(1, 0.);
|
||||
std::vector<std::vector<double>> val1 = PropsSImulti(Outputs, "", zero_vector, "", zero_vector, backend, fluids, fractions);
|
||||
// error handling is done in PropsSImulti, val1 will be an empty vector if an error occured
|
||||
return val1;
|
||||
}
|
||||
|
||||
|
||||
#if defined(ENABLE_CATCH)
|
||||
TEST_CASE("Check inputs to Props1SI", "[Props1SI],[PropsSI]") {
|
||||
SECTION("Good fluid, good parameter") {
|
||||
@@ -864,12 +864,12 @@ TEST_CASE("Check inputs to Props1SI", "[Props1SI],[PropsSI]") {
|
||||
};
|
||||
#endif
|
||||
|
||||
bool is_valid_fluid_string(const std::string& input_fluid_string) {
|
||||
bool is_valid_fluid_string(const std::string& fluidstring) {
|
||||
try {
|
||||
std::string backend, fluid;
|
||||
std::vector<double> fractions;
|
||||
// First try to extract backend and fractions
|
||||
extract_backend(input_fluid_string, backend, fluid);
|
||||
extract_backend(fluidstring, backend, fluid);
|
||||
std::string fluid_string = extract_fractions(fluid, fractions);
|
||||
// We are going to let the factory function load the state
|
||||
shared_ptr<AbstractState> State(AbstractState::factory(backend, fluid_string));
|
||||
@@ -889,9 +889,9 @@ double saturation_ancillary(const std::string& fluid_name, const std::string& ou
|
||||
|
||||
return HEOS.saturation_ancillary(iOutput, Q, iInput, value);
|
||||
}
|
||||
void set_reference_stateS(const std::string& fluid_string, const std::string& reference_state) {
|
||||
void set_reference_stateS(const std::string& FluidName, const std::string& reference_state) {
|
||||
std::string backend, fluid;
|
||||
extract_backend(fluid_string, backend, fluid);
|
||||
extract_backend(FluidName, backend, fluid);
|
||||
if (backend == "REFPROP") {
|
||||
|
||||
int ierr = 0, ixflag = 1;
|
||||
@@ -901,17 +901,19 @@ void set_reference_stateS(const std::string& fluid_string, const std::string& re
|
||||
const char* refstate = reference_state.c_str();
|
||||
if (strlen(refstate) > 3) {
|
||||
if (reference_state == "ASHRAE") {
|
||||
strcpy(hrf, "ASH");
|
||||
strncpy(hrf, "ASH", sizeof(hrf) - 1);
|
||||
hrf[sizeof(hrf) - 1] = '\0';
|
||||
} else {
|
||||
throw ValueError(format("Reference state string [%s] is more than 3 characters long", reference_state.c_str()));
|
||||
}
|
||||
} else {
|
||||
strcpy(hrf, refstate);
|
||||
strncpy(hrf, refstate, sizeof(hrf) - 1);
|
||||
hrf[sizeof(hrf) - 1] = '\0';
|
||||
}
|
||||
REFPROP_SETREF(hrf, ixflag, x0, h0, s0, t0, p0, ierr, herr, 3, 255);
|
||||
} else if (backend == "HEOS" || backend == "?") {
|
||||
CoolProp::HelmholtzEOSMixtureBackend HEOS(std::vector<std::string>(1, fluid));
|
||||
if (!reference_state.compare("IIR")) {
|
||||
if (reference_state == "IIR") {
|
||||
if (HEOS.Ttriple() > 273.15) {
|
||||
throw ValueError(format("Cannot use IIR reference state; Ttriple [%Lg] is greater than 273.15 K", HEOS.Ttriple()));
|
||||
}
|
||||
@@ -927,7 +929,7 @@ void set_reference_stateS(const std::string& fluid_string, const std::string& re
|
||||
if (get_debug_level() > 0) {
|
||||
std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2);
|
||||
}
|
||||
} else if (!reference_state.compare("ASHRAE")) {
|
||||
} else if (reference_state == "ASHRAE") {
|
||||
if (HEOS.Ttriple() > 233.15) {
|
||||
throw ValueError(format("Cannot use ASHRAE reference state; Ttriple [%Lg] is greater than than 233.15 K", HEOS.Ttriple()));
|
||||
}
|
||||
@@ -943,7 +945,7 @@ void set_reference_stateS(const std::string& fluid_string, const std::string& re
|
||||
if (get_debug_level() > 0) {
|
||||
std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2);
|
||||
}
|
||||
} else if (!reference_state.compare("NBP")) {
|
||||
} else if (reference_state == "NBP") {
|
||||
if (HEOS.p_triple() > 101325) {
|
||||
throw ValueError(format("Cannot use NBP reference state; p_triple [%Lg Pa] is greater than than 101325 Pa", HEOS.p_triple()));
|
||||
}
|
||||
@@ -959,17 +961,17 @@ void set_reference_stateS(const std::string& fluid_string, const std::string& re
|
||||
if (get_debug_level() > 0) {
|
||||
std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2);
|
||||
}
|
||||
} else if (!reference_state.compare("DEF")) {
|
||||
} else if (reference_state == "DEF") {
|
||||
set_fluid_enthalpy_entropy_offset(fluid, 0, 0, "DEF");
|
||||
} else if (!reference_state.compare("RESET")) {
|
||||
} else if (reference_state == "RESET") {
|
||||
set_fluid_enthalpy_entropy_offset(fluid, 0, 0, "RESET");
|
||||
} else {
|
||||
throw ValueError(format("Reference state string is invalid: [%s]", reference_state.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
void set_reference_stateD(const std::string& Ref, double T, double rhomolar, double hmolar0, double smolar0) {
|
||||
std::vector<std::string> _comps(1, Ref);
|
||||
void set_reference_stateD(const std::string& FluidName, double T, double rhomolar, double hmolar0, double smolar0) {
|
||||
std::vector<std::string> _comps(1, FluidName);
|
||||
CoolProp::HelmholtzEOSMixtureBackend HEOS(_comps);
|
||||
|
||||
HEOS.update(DmolarT_INPUTS, rhomolar, T);
|
||||
@@ -979,35 +981,35 @@ void set_reference_stateD(const std::string& Ref, double T, double rhomolar, dou
|
||||
double deltas = HEOS.smolar() - smolar0; // offset from specified entropy in J/mol/K
|
||||
double delta_a1 = deltas / (HEOS.gas_constant());
|
||||
double delta_a2 = -deltah / (HEOS.gas_constant() * HEOS.get_reducing_state().T);
|
||||
set_fluid_enthalpy_entropy_offset(Ref, delta_a1, delta_a2, "custom");
|
||||
set_fluid_enthalpy_entropy_offset(FluidName, delta_a1, delta_a2, "custom");
|
||||
}
|
||||
|
||||
std::string get_global_param_string(const std::string& ParamName) {
|
||||
if (!ParamName.compare("version")) {
|
||||
if (ParamName == "version") {
|
||||
return version;
|
||||
} else if (!ParamName.compare("gitrevision")) {
|
||||
} else if (ParamName == "gitrevision") {
|
||||
return gitrevision;
|
||||
} else if (!ParamName.compare("errstring")) {
|
||||
} else if (ParamName == "errstring") {
|
||||
std::string temp = error_string;
|
||||
error_string = "";
|
||||
return temp;
|
||||
} else if (!ParamName.compare("warnstring")) {
|
||||
} else if (ParamName == "warnstring") {
|
||||
std::string temp = warning_string;
|
||||
warning_string = "";
|
||||
return temp;
|
||||
} else if (!ParamName.compare("FluidsList") || !ParamName.compare("fluids_list") || !ParamName.compare("fluidslist")) {
|
||||
} else if (ParamName == "FluidsList" || ParamName == "fluids_list" || ParamName == "fluidslist") {
|
||||
return get_fluid_list();
|
||||
} else if (!ParamName.compare("incompressible_list_pure")) {
|
||||
} else if (ParamName == "incompressible_list_pure") {
|
||||
return get_incompressible_list_pure();
|
||||
} else if (!ParamName.compare("incompressible_list_solution")) {
|
||||
} else if (ParamName == "incompressible_list_solution") {
|
||||
return get_incompressible_list_solution();
|
||||
} else if (!ParamName.compare("mixture_binary_pairs_list")) {
|
||||
} else if (ParamName == "mixture_binary_pairs_list") {
|
||||
return get_csv_mixture_binary_pairs();
|
||||
} else if (!ParamName.compare("parameter_list")) {
|
||||
} else if (ParamName == "parameter_list") {
|
||||
return get_csv_parameter_list();
|
||||
} else if (!ParamName.compare("predefined_mixtures")) {
|
||||
} else if (ParamName == "predefined_mixtures") {
|
||||
return get_csv_predefined_mixtures();
|
||||
} else if (!ParamName.compare("HOME")) {
|
||||
} else if (ParamName == "HOME") {
|
||||
return get_home_dir();
|
||||
} else if (ParamName == "REFPROP_version") {
|
||||
return REFPROPMixtureBackend::version();
|
||||
@@ -1102,8 +1104,8 @@ std::string PhaseSI(const std::string& Name1, double Prop1, const std::string& N
|
||||
if (strError != "") { // if error string is not empty,
|
||||
strPhase.append(": " + strError); // append it to the phase string.
|
||||
}
|
||||
return strPhase; // return the "unknown" phase string
|
||||
} // else
|
||||
return strPhase; // return the "unknown" phase string
|
||||
} // else
|
||||
std::size_t Phase_int = static_cast<std::size_t>(Phase_double); // convert returned phase to int
|
||||
return phase_lookup_string(static_cast<phases>(Phase_int)); // return phase as a string
|
||||
}
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
#include <mutex>
|
||||
|
||||
void str2buf(const std::string& str, char* buf, int n) {
|
||||
if (str.size() < static_cast<unsigned int>(n))
|
||||
strcpy(buf, str.c_str());
|
||||
else
|
||||
if (str.size() < static_cast<unsigned int>(n)) {
|
||||
strncpy(buf, str.c_str(), n - 1);
|
||||
buf[n - 1] = '\0';
|
||||
} else {
|
||||
throw CoolProp::ValueError("Buffer is too small; must be at least " + std::to_string(str.size()) + " characters in size");
|
||||
}
|
||||
}
|
||||
void HandleException(long* errcode, char* message_buffer, const long buffer_length) {
|
||||
try {
|
||||
@@ -228,10 +230,10 @@ EXPORT_CODE void CONVENTION Props1SImulti(const char* Outputs, char* backend, co
|
||||
if (_result.size() == 0) {
|
||||
*resdim1 = 0;
|
||||
} else {
|
||||
if (_result.size() > *resdim1)
|
||||
if (_result.size() > static_cast<size_t>(*resdim1))
|
||||
throw CoolProp::ValueError(format("Result vector [%d] is bigger than allocated memory [%d]", _result[0].size(), *resdim1));
|
||||
*resdim1 = _result[0].size();
|
||||
for (int i = 0; i < _result[0].size(); i++) {
|
||||
*resdim1 = static_cast<long>(_result[0].size());
|
||||
for (size_t i = 0; i < _result[0].size(); i++) {
|
||||
result[i] = _result[0][i];
|
||||
}
|
||||
}
|
||||
@@ -275,13 +277,13 @@ EXPORT_CODE void CONVENTION PropsSImulti(const char* Outputs, const char* Name1,
|
||||
*resdim1 = 0;
|
||||
*resdim2 = 0;
|
||||
} else {
|
||||
if (_result.size() > *resdim1 || _result[0].size() > *resdim2)
|
||||
if (_result.size() > static_cast<size_t>(*resdim1) || _result[0].size() > static_cast<size_t>(*resdim2))
|
||||
throw CoolProp::ValueError(
|
||||
format("Result matrix [%d x %d] is bigger than allocated memory [%d x %d]", _result.size(), _result[0].size(), *resdim1, *resdim2));
|
||||
*resdim1 = _result.size();
|
||||
*resdim2 = _result[0].size();
|
||||
for (int i = 0; i < _result.size(); i++) {
|
||||
for (int j = 0; j < _result[i].size(); j++) {
|
||||
*resdim1 = static_cast<long>(_result.size());
|
||||
*resdim2 = static_cast<long>(_result[0].size());
|
||||
for (size_t i = 0; i < _result.size(); i++) {
|
||||
for (size_t j = 0; j < _result[i].size(); j++) {
|
||||
result[j + _result[i].size() * i] = _result[i][j];
|
||||
}
|
||||
}
|
||||
@@ -405,7 +407,7 @@ EXPORT_CODE long CONVENTION get_fluid_param_string(const char* fluid, const char
|
||||
EXPORT_CODE long CONVENTION get_fluid_param_string_len(const char* fluid, const char* param) {
|
||||
try {
|
||||
std::string s = CoolProp::get_fluid_param_string(std::string(fluid), std::string(param));
|
||||
return s.size();
|
||||
return static_cast<long>(s.size());
|
||||
} catch (std::exception& e) {
|
||||
CoolProp::set_error_string(e.what());
|
||||
} catch (...) {
|
||||
@@ -485,7 +487,7 @@ class AbstractStateLibrary
|
||||
std::mutex ASLib_mutex;
|
||||
|
||||
public:
|
||||
AbstractStateLibrary() : next_handle(0){};
|
||||
AbstractStateLibrary() : next_handle(0) {};
|
||||
long add(shared_ptr<CoolProp::AbstractState> AS) {
|
||||
std::lock_guard<std::mutex> guard(ASLib_mutex);
|
||||
ASlibrary.insert(std::pair<std::size_t, shared_ptr<CoolProp::AbstractState>>(this->next_handle, AS));
|
||||
@@ -573,7 +575,7 @@ EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions(const long handle,
|
||||
try {
|
||||
shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
|
||||
std::vector<double> _fractions = AS->get_mole_fractions();
|
||||
*N = _fractions.size();
|
||||
*N = static_cast<long>(_fractions.size());
|
||||
if (*N <= maxN) {
|
||||
for (int i = 0; i < *N; i++)
|
||||
fractions[i] = _fractions[i];
|
||||
@@ -608,7 +610,7 @@ EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions_satState(const long
|
||||
"quality [%g] is within two-phase region (0 <= quality <= 1)",
|
||||
static_cast<double>(quality)));
|
||||
}
|
||||
*N = _fractions.size();
|
||||
*N = static_cast<long>(_fractions.size());
|
||||
if (*N <= maxN) {
|
||||
for (int i = 0; i < *N; i++) {
|
||||
fractions[i] = _fractions[i];
|
||||
@@ -632,7 +634,7 @@ EXPORT_CODE double CONVENTION AbstractState_get_fugacity(const long handle, cons
|
||||
return _HUGE;
|
||||
}
|
||||
EXPORT_CODE double CONVENTION AbstractState_get_fugacity_coefficient(const long handle, const long i, long* errcode, char* message_buffer,
|
||||
const long buffer_length) {
|
||||
const long buffer_length) {
|
||||
*errcode = 0;
|
||||
try {
|
||||
shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
|
||||
@@ -724,14 +726,14 @@ EXPORT_CODE double CONVENTION AbstractState_second_partial_deriv(const long hand
|
||||
}
|
||||
|
||||
EXPORT_CODE double CONVENTION AbstractState_second_two_phase_deriv(const long handle, const long Of1, const long Wrt1, const long Constant1,
|
||||
const long Wrt2, const long Constant2, long* errcode, char* message_buffer,
|
||||
const long buffer_length) {
|
||||
const long Wrt2, const long Constant2, long* errcode, char* message_buffer,
|
||||
const long buffer_length) {
|
||||
*errcode = 0;
|
||||
try {
|
||||
shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
|
||||
return AS->second_two_phase_deriv(static_cast<CoolProp::parameters>(Of1), static_cast<CoolProp::parameters>(Wrt1),
|
||||
static_cast<CoolProp::parameters>(Constant1), static_cast<CoolProp::parameters>(Wrt2),
|
||||
static_cast<CoolProp::parameters>(Constant2));
|
||||
static_cast<CoolProp::parameters>(Constant1), static_cast<CoolProp::parameters>(Wrt2),
|
||||
static_cast<CoolProp::parameters>(Constant2));
|
||||
} catch (...) {
|
||||
HandleException(errcode, message_buffer, buffer_length);
|
||||
}
|
||||
@@ -765,7 +767,6 @@ EXPORT_CODE double CONVENTION AbstractState_first_two_phase_deriv_splined(const
|
||||
return _HUGE;
|
||||
}
|
||||
|
||||
|
||||
EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2,
|
||||
const long length, double* T, double* p, double* rhomolar, double* hmolar,
|
||||
double* smolar, long* errcode, char* message_buffer, const long buffer_length) {
|
||||
@@ -903,21 +904,21 @@ EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long han
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data_checkedMemory(const long handle, const long length, const long maxComponents, double* T,
|
||||
double* p, double* rhomolar_vap, double* rhomolar_liq, double* x, double* y,
|
||||
long* actual_length, long* actual_components, long* errcode, char* message_buffer,
|
||||
const long buffer_length) {
|
||||
EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data_checkedMemory(const long handle, const long length, const long maxComponents,
|
||||
double* T, double* p, double* rhomolar_vap, double* rhomolar_liq,
|
||||
double* x, double* y, long* actual_length, long* actual_components,
|
||||
long* errcode, char* message_buffer, const long buffer_length) {
|
||||
*errcode = 0;
|
||||
try {
|
||||
shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
|
||||
CoolProp::PhaseEnvelopeData pe = AS->get_phase_envelope_data();
|
||||
*actual_length = pe.T.size();
|
||||
*actual_length = static_cast<long>(pe.T.size());
|
||||
if (pe.T.size() > static_cast<std::size_t>(length)) {
|
||||
throw CoolProp::ValueError(format("Length of phase envelope vectors [%d] is greater than allocated buffer length [%d]",
|
||||
static_cast<int>(pe.T.size()), static_cast<int>(length)));
|
||||
}
|
||||
*actual_components = pe.x.size();
|
||||
if (*actual_components > static_cast<std::size_t>(maxComponents)) {
|
||||
*actual_components = static_cast<long>(pe.x.size());
|
||||
if (static_cast<std::size_t>(*actual_components) > static_cast<std::size_t>(maxComponents)) {
|
||||
throw CoolProp::ValueError(format("Length of phase envelope composition vectors [%d] is greater than allocated buffer length [%d]",
|
||||
static_cast<int>(*actual_components), static_cast<int>(maxComponents)));
|
||||
}
|
||||
@@ -926,7 +927,7 @@ EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data_checkedMemory(
|
||||
*(p + i) = pe.p[i];
|
||||
*(rhomolar_vap + i) = pe.rhomolar_vap[i];
|
||||
*(rhomolar_liq + i) = pe.rhomolar_liq[i];
|
||||
for (std::size_t j = 0; j < *actual_components; ++j) {
|
||||
for (std::size_t j = 0; j < static_cast<std::size_t>(*actual_components); ++j) {
|
||||
*(x + i * *actual_components + j) = pe.x[j][i];
|
||||
*(y + i * *actual_components + j) = pe.y[j][i];
|
||||
}
|
||||
|
||||
@@ -26,24 +26,31 @@ enum IsolineSupported
|
||||
};
|
||||
|
||||
const std::map<CoolProp::parameters, std::map<int, IsolineSupported>> xy_switch = {
|
||||
{CoolProp::iDmass, {{TS, Flipped}, {PH, Flipped}, {HS, Yes }, {PS, Flipped}, {PD, No }, {TD, No }, {PT, Yes }}},
|
||||
{CoolProp::iHmass, {{TS, Yes }, {PH, No }, {HS, No }, {PS, Flipped}, {PD, Flipped}, {TD, Yes }, {PT, Yes }}},
|
||||
{CoolProp::iP, {{TS, Yes }, {PH, No }, {HS, Yes }, {PS, No }, {PD, No }, {TD, Yes }, {PT, No }}},
|
||||
{CoolProp::iSmass, {{TS, No }, {PH, Flipped}, {HS, No }, {PS, No }, {PD, Flipped}, {TD, Yes }, {PT, Flipped}}},
|
||||
{CoolProp::iT, {{TS, No }, {PH, Flipped}, {HS, Yes }, {PS, Yes }, {PD, Yes }, {TD, No }, {PT, No }}},
|
||||
{CoolProp::iQ, {{TS, Flipped}, {PH, Flipped}, {HS, Flipped}, {PS, Flipped}, {PD, Flipped}, {TD, Flipped}, {PT, Yes }}}
|
||||
};
|
||||
{CoolProp::iDmass, {{TS, Flipped}, {PH, Flipped}, {HS, Yes}, {PS, Flipped}, {PD, No}, {TD, No}, {PT, Yes}}},
|
||||
{CoolProp::iHmass, {{TS, Yes}, {PH, No}, {HS, No}, {PS, Flipped}, {PD, Flipped}, {TD, Yes}, {PT, Yes}}},
|
||||
{CoolProp::iP, {{TS, Yes}, {PH, No}, {HS, Yes}, {PS, No}, {PD, No}, {TD, Yes}, {PT, No}}},
|
||||
{CoolProp::iSmass, {{TS, No}, {PH, Flipped}, {HS, No}, {PS, No}, {PD, Flipped}, {TD, Yes}, {PT, Flipped}}},
|
||||
{CoolProp::iT, {{TS, No}, {PH, Flipped}, {HS, Yes}, {PS, Yes}, {PD, Yes}, {TD, No}, {PT, No}}},
|
||||
{CoolProp::iQ, {{TS, Flipped}, {PH, Flipped}, {HS, Flipped}, {PS, Flipped}, {PD, Flipped}, {TD, Flipped}, {PT, Yes}}}};
|
||||
|
||||
Scale default_scale(CoolProp::parameters key) {
|
||||
switch (key) {
|
||||
case CoolProp::iDmass: return Scale::Log;
|
||||
case CoolProp::iHmass: return Scale::Lin;
|
||||
case CoolProp::iP: return Scale::Log;
|
||||
case CoolProp::iSmass: return Scale::Lin;
|
||||
case CoolProp::iT: return Scale::Lin;
|
||||
case CoolProp::iUmass: return Scale::Lin;
|
||||
case CoolProp::iQ: return Scale::Lin;
|
||||
default: return Scale::Lin;
|
||||
case CoolProp::iDmass:
|
||||
return Scale::Log;
|
||||
case CoolProp::iHmass:
|
||||
return Scale::Lin;
|
||||
case CoolProp::iP:
|
||||
return Scale::Log;
|
||||
case CoolProp::iSmass:
|
||||
return Scale::Lin;
|
||||
case CoolProp::iT:
|
||||
return Scale::Lin;
|
||||
case CoolProp::iUmass:
|
||||
return Scale::Lin;
|
||||
case CoolProp::iQ:
|
||||
return Scale::Lin;
|
||||
default:
|
||||
return Scale::Lin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +78,7 @@ std::shared_ptr<CoolProp::AbstractState> get_critical_point(const std::shared_pt
|
||||
crit_state.stable = true;
|
||||
} catch (...) {
|
||||
try {
|
||||
for (CoolProp::CriticalState crit_state_tmp: state->all_critical_points()) {
|
||||
for (CoolProp::CriticalState crit_state_tmp : state->all_critical_points()) {
|
||||
if (crit_state_tmp.stable && (crit_state_tmp.T > crit_state.T || !std::isfinite(crit_state.T))) {
|
||||
crit_state.T = crit_state_tmp.T;
|
||||
crit_state.p = crit_state_tmp.p;
|
||||
@@ -86,19 +93,20 @@ std::shared_ptr<CoolProp::AbstractState> get_critical_point(const std::shared_pt
|
||||
|
||||
std::shared_ptr<CoolProp::AbstractState> new_state(CoolProp::AbstractState::factory(state->backend_name(), state->fluid_names()));
|
||||
std::vector<double> masses = state->get_mass_fractions();
|
||||
if (masses.size() > 1)
|
||||
new_state->set_mass_fractions(masses);
|
||||
if (masses.size() > 1) new_state->set_mass_fractions(masses);
|
||||
|
||||
if (std::isfinite(crit_state.p) && std::isfinite(crit_state.T)) {
|
||||
try {
|
||||
new_state->specify_phase(CoolProp::iphase_critical_point);
|
||||
new_state->update(CoolProp::PT_INPUTS, crit_state.p, crit_state.T);
|
||||
return new_state;
|
||||
} catch (...) { }
|
||||
} catch (...) {
|
||||
}
|
||||
try {
|
||||
new_state->update(CoolProp::PT_INPUTS, crit_state.p, crit_state.T);
|
||||
return new_state;
|
||||
} catch (...) { }
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
if (std::isfinite(crit_state.rhomolar) && std::isfinite(crit_state.T)) {
|
||||
@@ -106,11 +114,13 @@ std::shared_ptr<CoolProp::AbstractState> get_critical_point(const std::shared_pt
|
||||
new_state->specify_phase(CoolProp::iphase_critical_point);
|
||||
new_state->update(CoolProp::DmolarT_INPUTS, crit_state.rhomolar, crit_state.T);
|
||||
return new_state;
|
||||
} catch (...) { }
|
||||
} catch (...) {
|
||||
}
|
||||
try {
|
||||
new_state->update(CoolProp::DmolarT_INPUTS, crit_state.rhomolar, crit_state.T);
|
||||
return new_state;
|
||||
} catch (...) { }
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
throw CoolProp::ValueError("Could not calculate the critical point data.");
|
||||
return nullptr;
|
||||
@@ -118,7 +128,6 @@ std::shared_ptr<CoolProp::AbstractState> get_critical_point(const std::shared_pt
|
||||
|
||||
} /* namespace Detail */
|
||||
|
||||
|
||||
std::vector<double> generate_values_in_range(Scale scale, const Range& range, int count) {
|
||||
if (scale == Scale::Log)
|
||||
return logspace(range.min, range.max, count);
|
||||
@@ -130,13 +139,9 @@ std::vector<double> generate_values_in_range(CoolProp::parameters type, const Ra
|
||||
return generate_values_in_range(Detail::default_scale(type), range, count);
|
||||
}
|
||||
|
||||
|
||||
Isoline::Isoline(CoolProp::parameters key, CoolProp::parameters xkey, CoolProp::parameters ykey, double value, const std::shared_ptr<CoolProp::AbstractState>& state)
|
||||
: key_(key),
|
||||
xkey_(xkey),
|
||||
ykey_(ykey),
|
||||
value(value),
|
||||
state_(state) {
|
||||
Isoline::Isoline(CoolProp::parameters key, CoolProp::parameters xkey, CoolProp::parameters ykey, double value,
|
||||
const std::shared_ptr<CoolProp::AbstractState>& state)
|
||||
: key_(key), xkey_(xkey), ykey_(ykey), value(value), state_(state) {
|
||||
this->critical_state_ = Detail::get_critical_point(state);
|
||||
}
|
||||
|
||||
@@ -173,14 +178,14 @@ void Isoline::calc_sat_range(int count) {
|
||||
double y_crit = critical_state_->keyed_output(ykey_);
|
||||
x.resize(one.size());
|
||||
y.resize(one.size());
|
||||
for (int i = 0; i < one.size(); ++i) {
|
||||
for (size_t i = 0; i < one.size(); ++i) {
|
||||
try {
|
||||
state_->update(input_pair, one[i], two[i]);
|
||||
x[i] = state_->keyed_output(xkey_);
|
||||
y[i] = state_->keyed_output(ykey_);
|
||||
} catch (...) {
|
||||
if ((input_pair == CoolProp::QT_INPUTS && abs(two[i] - t_crit) < 1e0)
|
||||
|| (input_pair == CoolProp::PQ_INPUTS && abs(one[i] - p_crit) < 1e2)) {
|
||||
|| (input_pair == CoolProp::PQ_INPUTS && abs(one[i] - p_crit) < 1e2)) {
|
||||
x[i] = x_crit;
|
||||
y[i] = y_crit;
|
||||
std::cerr << "ERROR near critical inputs" << std::endl;
|
||||
@@ -244,7 +249,7 @@ void Isoline::calc_range(std::vector<double>& xvals, std::vector<double>& yvals)
|
||||
vals[xpos] = xvals;
|
||||
vals[ypos] = yvals;
|
||||
|
||||
for (int i = 0; i < vals[2].size(); ++i) {
|
||||
for (size_t i = 0; i < vals[2].size(); ++i) {
|
||||
try {
|
||||
state_->update((CoolProp::input_pairs)pair, vals[0][i], vals[1][i]);
|
||||
vals[2][i] = state_->keyed_output(idxs[2]);
|
||||
@@ -253,7 +258,7 @@ void Isoline::calc_range(std::vector<double>& xvals, std::vector<double>& yvals)
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < idxs.size(); ++i) {
|
||||
for (size_t i = 0; i < idxs.size(); ++i) {
|
||||
if (idxs[i] == xkey_) x = vals[i];
|
||||
if (idxs[i] == ykey_) y = vals[i];
|
||||
}
|
||||
@@ -261,8 +266,7 @@ void Isoline::calc_range(std::vector<double>& xvals, std::vector<double>& yvals)
|
||||
}
|
||||
|
||||
PropertyPlot::PropertyPlot(const std::string& fluid_name, CoolProp::parameters ykey, CoolProp::parameters xkey, TPLimits tp_limits)
|
||||
: xkey_(xkey),
|
||||
ykey_(ykey) {
|
||||
: xkey_(xkey), ykey_(ykey) {
|
||||
this->state_ = Detail::process_fluid_state(fluid_name);
|
||||
this->critical_state_ = Detail::get_critical_point(state_);
|
||||
|
||||
@@ -276,13 +280,21 @@ PropertyPlot::PropertyPlot(const std::string& fluid_name, CoolProp::parameters y
|
||||
axis_pair_ = CoolProp::generate_update_pair(xkey, 0, ykey, 1, out1, out2);
|
||||
swap_axis_inputs_for_update_ = (out1 == 1);
|
||||
|
||||
const double HI_FACTOR = 2.25; // Upper default limits: HI_FACTOR*T_crit and HI_FACTOR*p_crit
|
||||
const double LO_FACTOR = 1.01; // Lower default limits: LO_FACTOR*T_triple and LO_FACTOR*p_triple
|
||||
const double HI_FACTOR = 2.25; // Upper default limits: HI_FACTOR*T_crit and HI_FACTOR*p_crit
|
||||
const double LO_FACTOR = 1.01; // Lower default limits: LO_FACTOR*T_triple and LO_FACTOR*p_triple
|
||||
switch (tp_limits) {
|
||||
case TPLimits::None: this->Tp_limits_ = {{Detail::NaN, Detail::NaN}, {Detail::NaN, Detail::NaN}}; break;
|
||||
case TPLimits::Def: this->Tp_limits_ = {{LO_FACTOR, HI_FACTOR}, {LO_FACTOR, HI_FACTOR}}; break;
|
||||
case TPLimits::Achp: this->Tp_limits_ = {{173.15, 493.15}, {0.25e5, HI_FACTOR}}; break;
|
||||
case TPLimits::Orc: this->Tp_limits_ = {{273.15, 673.15}, {0.25e5, HI_FACTOR}}; break;
|
||||
case TPLimits::None:
|
||||
this->Tp_limits_ = {{Detail::NaN, Detail::NaN}, {Detail::NaN, Detail::NaN}};
|
||||
break;
|
||||
case TPLimits::Def:
|
||||
this->Tp_limits_ = {{LO_FACTOR, HI_FACTOR}, {LO_FACTOR, HI_FACTOR}};
|
||||
break;
|
||||
case TPLimits::Achp:
|
||||
this->Tp_limits_ = {{173.15, 493.15}, {0.25e5, HI_FACTOR}};
|
||||
break;
|
||||
case TPLimits::Orc:
|
||||
this->Tp_limits_ = {{273.15, 673.15}, {0.25e5, HI_FACTOR}};
|
||||
break;
|
||||
}
|
||||
|
||||
Range2D ranges = get_axis_limits();
|
||||
@@ -316,8 +328,7 @@ std::vector<CoolProp::parameters> PropertyPlot::supported_isoline_keys() const {
|
||||
for (auto it = Detail::xy_switch.begin(); it != Detail::xy_switch.end(); ++it) {
|
||||
const std::map<int, Detail::IsolineSupported>& supported = it->second;
|
||||
auto supported_xy = supported.find(ykey_ * 10 + xkey_);
|
||||
if (supported_xy != supported.end() && supported_xy->second != Detail::IsolineSupported::No)
|
||||
keys.push_back(it->first);
|
||||
if (supported_xy != supported.end() && supported_xy->second != Detail::IsolineSupported::No) keys.push_back(it->first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
@@ -327,19 +338,26 @@ double PropertyPlot::value_at(CoolProp::parameters key, double xvalue, double yv
|
||||
if (key == ykey_) return yvalue;
|
||||
|
||||
try {
|
||||
if (swap_axis_inputs_for_update_)
|
||||
std::swap(xvalue, yvalue);
|
||||
if (swap_axis_inputs_for_update_) std::swap(xvalue, yvalue);
|
||||
state_->specify_phase(phase);
|
||||
state_->update(axis_pair_, xvalue, yvalue);
|
||||
switch (key) {
|
||||
case CoolProp::iT: return state_->T();
|
||||
case CoolProp::iP: return state_->p();
|
||||
case CoolProp::iDmass: return state_->rhomass();
|
||||
case CoolProp::iHmass: return state_->hmass();
|
||||
case CoolProp::iSmass: return state_->smass();
|
||||
case CoolProp::iUmass: return state_->umass();
|
||||
case CoolProp::iQ: return state_->Q();
|
||||
default: return Detail::NaN;
|
||||
case CoolProp::iT:
|
||||
return state_->T();
|
||||
case CoolProp::iP:
|
||||
return state_->p();
|
||||
case CoolProp::iDmass:
|
||||
return state_->rhomass();
|
||||
case CoolProp::iHmass:
|
||||
return state_->hmass();
|
||||
case CoolProp::iSmass:
|
||||
return state_->smass();
|
||||
case CoolProp::iUmass:
|
||||
return state_->umass();
|
||||
case CoolProp::iQ:
|
||||
return state_->Q();
|
||||
default:
|
||||
return Detail::NaN;
|
||||
}
|
||||
} catch (...) {
|
||||
return Detail::NaN;
|
||||
@@ -373,20 +391,40 @@ PropertyPlot::Range2D PropertyPlot::get_Tp_limits() const {
|
||||
Range tsat = get_sat_bounds(CoolProp::iT);
|
||||
Range psat = get_sat_bounds(CoolProp::iP);
|
||||
|
||||
const double ID_FACTOR = 10.0; // Values below this number are interpreted as factors
|
||||
if (std::isnan(t.min)) t.min = 0.0;
|
||||
else if (t.min < ID_FACTOR) t.min *= tsat.min;
|
||||
if (std::isnan(t.max)) t.max = 1e6;
|
||||
else if (t.max < ID_FACTOR) t.max *= tsat.max;
|
||||
if (std::isnan(p.min)) p.min = 0.0;
|
||||
else if (p.min < ID_FACTOR) p.min *= psat.min;
|
||||
if (std::isnan(p.max)) p.max = 1e10;
|
||||
else if (p.max < ID_FACTOR) p.max *= psat.max;
|
||||
const double ID_FACTOR = 10.0; // Values below this number are interpreted as factors
|
||||
if (std::isnan(t.min))
|
||||
t.min = 0.0;
|
||||
else if (t.min < ID_FACTOR)
|
||||
t.min *= tsat.min;
|
||||
if (std::isnan(t.max))
|
||||
t.max = 1e6;
|
||||
else if (t.max < ID_FACTOR)
|
||||
t.max *= tsat.max;
|
||||
if (std::isnan(p.min))
|
||||
p.min = 0.0;
|
||||
else if (p.min < ID_FACTOR)
|
||||
p.min *= psat.min;
|
||||
if (std::isnan(p.max))
|
||||
p.max = 1e10;
|
||||
else if (p.max < ID_FACTOR)
|
||||
p.max *= psat.max;
|
||||
|
||||
try { t.min = std::max(t.min, state_->trivial_keyed_output(CoolProp::iT_min)); } catch (...) {}
|
||||
try { t.max = std::min(t.max, state_->trivial_keyed_output(CoolProp::iT_max)); } catch (...) {}
|
||||
try { p.min = std::max(p.min, state_->trivial_keyed_output(CoolProp::iP_min)); } catch (...) {}
|
||||
try { p.max = std::min(p.max, state_->trivial_keyed_output(CoolProp::iP_max)); } catch (...) {}
|
||||
try {
|
||||
t.min = std::max(t.min, state_->trivial_keyed_output(CoolProp::iT_min));
|
||||
} catch (...) {
|
||||
}
|
||||
try {
|
||||
t.max = std::min(t.max, state_->trivial_keyed_output(CoolProp::iT_max));
|
||||
} catch (...) {
|
||||
}
|
||||
try {
|
||||
p.min = std::max(p.min, state_->trivial_keyed_output(CoolProp::iP_min));
|
||||
} catch (...) {
|
||||
}
|
||||
try {
|
||||
p.max = std::min(p.max, state_->trivial_keyed_output(CoolProp::iP_max));
|
||||
} catch (...) {
|
||||
}
|
||||
return {t, p};
|
||||
}
|
||||
|
||||
@@ -409,7 +447,8 @@ PropertyPlot::Range2D PropertyPlot::get_axis_limits(CoolProp::parameters xkey, C
|
||||
xrange.max = std::max(xrange.max, x);
|
||||
yrange.min = std::min(yrange.min, y);
|
||||
yrange.max = std::max(yrange.max, y);
|
||||
} catch (...) { }
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return {xrange, yrange};
|
||||
@@ -421,7 +460,6 @@ PropertyPlot::Range2D PropertyPlot::get_axis_limits(CoolProp::parameters xkey, C
|
||||
} /* namespace Plot */
|
||||
} /* namespace CoolProp */
|
||||
|
||||
|
||||
#ifdef ENABLE_CATCH
|
||||
# include <catch2/catch_all.hpp>
|
||||
# include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
@@ -436,7 +474,7 @@ using Catch::Matchers::WithinRel;
|
||||
TEST_CASE("Check value_at for p-h plots", "[Plot]") {
|
||||
CoolProp::Plot::PropertyPlot plot("R134a", CoolProp::iP, CoolProp::iHmass, CoolProp::Plot::TPLimits::Achp);
|
||||
|
||||
CHECK_THAT(plot.value_at(CoolProp::iP, 300000/*Pa*/, 200000/*J/kg*/), WithinAbs(200000, 1e-10));
|
||||
CHECK_THAT(plot.value_at(CoolProp::iP, 300000 /*Pa*/, 200000 /*J/kg*/), WithinAbs(200000, 1e-10));
|
||||
CHECK_THAT(plot.value_at(CoolProp::iHmass, 300000, 200000), WithinAbs(300000, 1e-10));
|
||||
CHECK_THAT(plot.value_at(CoolProp::iT, 300000, 200000), WithinAbs(263.0737275397678, 1e-10));
|
||||
CHECK_THAT(plot.value_at(CoolProp::iQ, 300000, 200000), WithinAbs(0.5504434787434432, 1e-10));
|
||||
@@ -475,18 +513,18 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
|
||||
CHECK_THAT(q_isolines[3].value, WithinAbs(0.75, 1e-10));
|
||||
CHECK_THAT(q_isolines[4].value, WithinAbs(1.0, 1e-10));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{71455.0825704527, 132940.602012992, 198498.370551912, 271578.877763124, 389490.979699808},
|
||||
{137326.831168219, 191267.585241559, 248361.039003664, 309540.80583791, 389563.709352125},
|
||||
{203198.579765986, 249594.568470126, 298223.707455415, 347502.733912697, 389636.439004441},
|
||||
{269070.328363753, 307921.551698693, 348086.375907167, 385464.661987484, 389709.168656758},
|
||||
{334942.07696152, 366248.53492726, 397949.044358919, 423426.59006227, 389781.898309075},
|
||||
{71455.0825704527, 132940.602012992, 198498.370551912, 271578.877763124, 389490.979699808},
|
||||
{137326.831168219, 191267.585241559, 248361.039003664, 309540.80583791, 389563.709352125},
|
||||
{203198.579765986, 249594.568470126, 298223.707455415, 347502.733912697, 389636.439004441},
|
||||
{269070.328363753, 307921.551698693, 348086.375907167, 385464.661987484, 389709.168656758},
|
||||
{334942.07696152, 366248.53492726, 397949.044358919, 423426.59006227, 389781.898309075},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
{389.56705952134, 25851.3343934178, 281115.856001781, 1316960.5263817, 4059273.23696491},
|
||||
};
|
||||
for (int i = 0; i < q_isolines.size(); ++i) {
|
||||
REQUIRE(q_isolines[i].size() == points_per_isoline);
|
||||
@@ -508,18 +546,18 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
|
||||
CHECK_THAT(t_isolines[3].value, WithinAbs(384.5375, 1e-10));
|
||||
CHECK_THAT(t_isolines[4].value, WithinAbs(455.0, 1e-10));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{75373.1268990848, 75410.9911120345, 75576.5817006844, 76301.4918515715, 79487.8877883422},
|
||||
{382785.230587559, 161389.442353423, 161516.218619848, 162076.984158624, 164637.062377748},
|
||||
{439466.649843277, 438148.172824179, 431912.0662387, 257605.319479605, 257512.839247251},
|
||||
{504550.626065608, 503783.529360532, 500331.593280543, 482707.178360249, 366958.520785585},
|
||||
{577604.594975215, 577097.065048065, 574850.152315662, 564443.789731467, 507875.800635261},
|
||||
{75373.1268990848, 75410.9911120345, 75576.5817006844, 76301.4918515715, 79487.8877883422},
|
||||
{382785.230587559, 161389.442353423, 161516.218619848, 162076.984158624, 164637.062377748},
|
||||
{439466.649843277, 438148.172824179, 431912.0662387, 257605.319479605, 257512.839247251},
|
||||
{504550.626065608, 503783.529360532, 500331.593280543, 482707.178360249, 366958.520785585},
|
||||
{577604.594975215, 577097.065048065, 574850.152315662, 564443.789731467, 507875.800635261},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
};
|
||||
for (int i = 0; i < t_isolines.size(); ++i) {
|
||||
REQUIRE(t_isolines[i].size() == points_per_isoline);
|
||||
@@ -541,18 +579,18 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
|
||||
CHECK_THAT(s_isolines[3].value, WithinAbs(1923.806139503257, 1e-10));
|
||||
CHECK_THAT(s_isolines[4].value, WithinAbs(2423.07169138421, 1e-10));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{73758.1368335347, 73811.2861613466, 74043.6241898207, 75058.8771715961, 79487.8877884637},
|
||||
{176257.349845383, 179794.807761573, 180290.319046323, 181487.967471084, 186690.959612256},
|
||||
{286286.175818458, 303984.726428782, 321692.362821643, 335551.688987588, 344087.839487745},
|
||||
{399372.560529476, 433400.354292387, 471964.89621373, 513835.931064411, 555824.663124966},
|
||||
{577604.594975221, 635258.237156301, 698999.445970987, 768745.631252166, std::nan("")},
|
||||
{73758.1368335347, 73811.2861613466, 74043.6241898207, 75058.8771715961, 79487.8877884637},
|
||||
{176257.349845383, 179794.807761573, 180290.319046323, 181487.967471084, 186690.959612256},
|
||||
{286286.175818458, 303984.726428782, 321692.362821643, 335551.688987588, 344087.839487745},
|
||||
{399372.560529476, 433400.354292387, 471964.89621373, 513835.931064411, 555824.663124966},
|
||||
{577604.594975221, 635258.237156301, 698999.445970987, 768745.631252166, std::nan("")},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
};
|
||||
for (int i = 0; i < s_isolines.size(); ++i) {
|
||||
REQUIRE(s_isolines[i].size() == points_per_isoline);
|
||||
@@ -577,18 +615,18 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
|
||||
CHECK_THAT(d_isolines[3].value, WithinAbs(228.57817793711163, 1e-10));
|
||||
CHECK_THAT(d_isolines[4].value, WithinAbs(1593.2471569904417, 1e-10));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{577604.594975212, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
|
||||
{202365.843978511, 419230.112111493, std::nan(""), std::nan(""), std::nan("")},
|
||||
{142114.491283644, 204388.004478758, 351216.809707051, std::nan(""), std::nan("")},
|
||||
{133470.418481246, 172415.768780675, 235383.044874193, 357492.457483747, 669493.625997729},
|
||||
{70518.3287895177, 70601.2088976224, 70963.5807789929, 72548.359197014, 79487.8877879113},
|
||||
{577604.594975212, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
|
||||
{202365.843978511, 419230.112111493, std::nan(""), std::nan(""), std::nan("")},
|
||||
{142114.491283644, 204388.004478758, 351216.809707051, std::nan(""), std::nan("")},
|
||||
{133470.418481246, 172415.768780675, 235383.044874193, 357492.457483747, 669493.625997729},
|
||||
{70518.3287895177, 70601.2088976224, 70963.5807789929, 72548.359197014, 79487.8877879113},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
{25000, 109298.142136262, 477843.354977538, 2089095.63724813, 9133370.87584761},
|
||||
};
|
||||
for (int i = 0; i < d_isolines.size(); ++i) {
|
||||
REQUIRE(d_isolines[i].size() == points_per_isoline);
|
||||
@@ -638,18 +676,18 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
|
||||
CHECK_THAT(q_isolines[4].value, WithinAbs(1.0, 1e-10));
|
||||
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{412.617538232079, 728.71482941326, 994.524404955042, 1237.31924154895, 1561.70306865236},
|
||||
{800.440438274308, 992.708859865778, 1177.8221470675, 1354.80424987622, 1561.8974228315},
|
||||
{1188.26333831654, 1256.70289031829, 1361.11988917995, 1472.28925820349, 1562.09177701064},
|
||||
{1576.08623835876, 1520.69692077081, 1544.4176312924, 1589.77426653076, 1562.28613118978},
|
||||
{1963.90913840099, 1784.69095122333, 1727.71537340486, 1707.25927485803, 1562.48048536892},
|
||||
{412.617538232079, 728.71482941326, 994.524404955042, 1237.31924154895, 1561.70306865236},
|
||||
{800.440438274308, 992.708859865778, 1177.8221470675, 1354.80424987622, 1561.8974228315},
|
||||
{1188.26333831654, 1256.70289031829, 1361.11988917995, 1472.28925820349, 1562.09177701064},
|
||||
{1576.08623835876, 1520.69692077081, 1544.4176312924, 1589.77426653076, 1562.28613118978},
|
||||
{1963.90913840099, 1784.69095122333, 1727.71537340486, 1707.25927485803, 1562.48048536892},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
{169.850074842393, 220.940538422734, 272.031002003074, 323.121465583414, 374.211929163755},
|
||||
};
|
||||
|
||||
for (int i = 0; i < q_isolines.size(); ++i) {
|
||||
@@ -672,18 +710,18 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
|
||||
CHECK_THAT(p_isolines[3].value, WithinAbs(2089095.6372481277, 1e-7));
|
||||
CHECK_THAT(p_isolines[4].value, WithinAbs(9133370.87584761, 1e-7));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{171.786072659192, 220.381369310476, 220.381369310476, 265.362477224881, 455.000000000006},
|
||||
{171.798910666292, 248.745218249749, 248.745218249749, 308.633922577123, 506.387752763855},
|
||||
{171.854988815762, 258.195699077866, 287.473037337147, 355.964867192619, 560.29310120217},
|
||||
{172.099235421196, 258.742471436004, 342.561817261331, 411.323964493198, 618.036314177106},
|
||||
{173.15, 261.021061581425, 371.327173900344, 484.427831614361, std::nan("")},
|
||||
{171.786072659192, 220.381369310476, 220.381369310476, 265.362477224881, 455.000000000006},
|
||||
{171.798910666292, 248.745218249749, 248.745218249749, 308.633922577123, 506.387752763855},
|
||||
{171.854988815762, 258.195699077866, 287.473037337147, 355.964867192619, 560.29310120217},
|
||||
{172.099235421196, 258.742471436004, 342.561817261331, 411.323964493198, 618.036314177106},
|
||||
{173.15, 261.021061581425, 371.327173900344, 484.427831614361, std::nan("")},
|
||||
};
|
||||
for (int i = 0; i < p_isolines.size(); ++i) {
|
||||
REQUIRE(p_isolines[i].size() == points_per_isoline);
|
||||
@@ -709,18 +747,18 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
|
||||
CHECK_THAT(h_isolines[3].value, WithinAbs(452046.72795618215, 1e-10));
|
||||
CHECK_THAT(h_isolines[4].value, WithinAbs(577604.5949752146, 1e-10));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
{426.009483860398, 925.275035741351, 1424.5405876223, 1923.80613950326, 2423.07169138421},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{172.174575309065, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
|
||||
{196.074550634008, 266.631159312075, std::nan(""), std::nan(""), std::nan("")},
|
||||
{213.664681842583, 299.984652703232, 301.726570477946, std::nan(""), std::nan("")},
|
||||
{228.411201679534, 322.843563825212, 426.787882130168, 331.521169967777, 328.042167528594},
|
||||
{241.568258023047, 341.661338916035, 458.593848045394, std::nan(""), 455.000000000079},
|
||||
{172.174575309065, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
|
||||
{196.074550634008, 266.631159312075, std::nan(""), std::nan(""), std::nan("")},
|
||||
{213.664681842583, 299.984652703232, 301.726570477946, std::nan(""), std::nan("")},
|
||||
{228.411201679534, 322.843563825212, 426.787882130168, 331.521169967777, 328.042167528594},
|
||||
{241.568258023047, 341.661338916035, 458.593848045394, std::nan(""), 455.000000000079},
|
||||
};
|
||||
for (int i = 0; i < h_isolines.size(); ++i) {
|
||||
REQUIRE(h_isolines[i].size() == points_per_isoline);
|
||||
@@ -746,18 +784,15 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
|
||||
CHECK_THAT(d_isolines[3].value, WithinAbs(228.57817793711163, 1e-10));
|
||||
CHECK_THAT(d_isolines[4].value, WithinAbs(1593.2471569904417, 1e-10));
|
||||
const double expected_x[isoline_count][points_per_isoline] = {
|
||||
{524.17387831234, 1911.09303197673, 2092.95299735844, 2262.71394473455, 2423.07169138421},
|
||||
{448.103089616845, 1715.11956249481, 1932.46627813427, 2103.15612327654, 2263.90953791772},
|
||||
{437.189451894057, 972.489749676211, 1758.36241052056, 1935.7522861596, 2099.20643194095},
|
||||
{435.623706482622, 865.946977105694, 1292.02339683139, 1720.27746043057, 1899.38158004697},
|
||||
{426.009483860398, 710.877062878169, 946.968704707899, 1151.91782375377, 1335.56507098504},
|
||||
{524.17387831234, 1911.09303197673, 2092.95299735844, 2262.71394473455, 2423.07169138421},
|
||||
{448.103089616845, 1715.11956249481, 1932.46627813427, 2103.15612327654, 2263.90953791772},
|
||||
{437.189451894057, 972.489749676211, 1758.36241052056, 1935.7522861596, 2099.20643194095},
|
||||
{435.623706482622, 865.946977105694, 1292.02339683139, 1720.27746043057, 1899.38158004697},
|
||||
{426.009483860398, 710.877062878169, 946.968704707899, 1151.91782375377, 1335.56507098504},
|
||||
};
|
||||
const double expected_y[isoline_count][points_per_isoline] = {
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455}, {173.15, 243.6125, 314.075, 384.5375, 455}, {173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
{173.15, 243.6125, 314.075, 384.5375, 455}, {173.15, 243.6125, 314.075, 384.5375, 455},
|
||||
};
|
||||
for (int i = 0; i < d_isolines.size(); ++i) {
|
||||
REQUIRE(d_isolines[i].size() == points_per_isoline);
|
||||
|
||||
@@ -180,13 +180,13 @@ std::string get_parameter_information(int key, const std::string& info) {
|
||||
const std::map<int, std::string>* M;
|
||||
auto& parameter_information = get_parameter_information();
|
||||
// Hook up the right map (since they are all of the same type)
|
||||
if (!info.compare("IO")) {
|
||||
if (info == "IO") {
|
||||
M = &(parameter_information.IO_map);
|
||||
} else if (!info.compare("short")) {
|
||||
} else if (info == "short") {
|
||||
M = &(parameter_information.short_desc_map);
|
||||
} else if (!info.compare("long")) {
|
||||
} else if (info == "long") {
|
||||
M = &(parameter_information.description_map);
|
||||
} else if (!info.compare("units")) {
|
||||
} else if (info == "units") {
|
||||
M = &(parameter_information.units_map);
|
||||
} else {
|
||||
throw ValueError(format("Bad info string [%s] to get_parameter_information", info.c_str()));
|
||||
@@ -434,25 +434,17 @@ struct scheme_info
|
||||
};
|
||||
|
||||
const scheme_info scheme_info_list[] = {
|
||||
{ i1, "1"},
|
||||
{ i2a, "2A"},
|
||||
{ i2b, "2B"},
|
||||
{ i3a, "3A"},
|
||||
{ i3b, "3B"},
|
||||
{ i4a, "4A"},
|
||||
{ i4b, "4B"},
|
||||
{ i4c, "4C"},
|
||||
{i1, "1"}, {i2a, "2A"}, {i2b, "2B"}, {i3a, "3A"}, {i3b, "3B"}, {i4a, "4A"}, {i4b, "4B"}, {i4c, "4C"},
|
||||
};
|
||||
|
||||
class SchemeInformation {
|
||||
public:
|
||||
class SchemeInformation
|
||||
{
|
||||
public:
|
||||
std::map<schemes, std::string> short_desc_map;
|
||||
std::map<std::string, schemes> index_map;
|
||||
SchemeInformation()
|
||||
{
|
||||
SchemeInformation() {
|
||||
const scheme_info* const end = scheme_info_list + sizeof(scheme_info_list) / sizeof(scheme_info_list[0]);
|
||||
for (const scheme_info* el = scheme_info_list; el != end; ++el)
|
||||
{
|
||||
for (const scheme_info* el = scheme_info_list; el != end; ++el) {
|
||||
short_desc_map.insert(std::pair<schemes, std::string>(el->key, el->short_desc));
|
||||
index_map.insert(std::pair<std::string, schemes>(el->short_desc, el->key));
|
||||
}
|
||||
@@ -476,27 +468,25 @@ const std::string& get_scheme_short_desc(schemes scheme) {
|
||||
throw ValueError("Cannot find the short scheme description.");
|
||||
}
|
||||
|
||||
bool is_valid_scheme(const std::string &scheme_name, schemes &iOutput) {
|
||||
bool is_valid_scheme(const std::string& scheme_name, schemes& iOutput) {
|
||||
auto& scheme_information = get_scheme_information();
|
||||
auto it = scheme_information.index_map.find(scheme_name);
|
||||
// If equal to end, not found
|
||||
if (it != scheme_information.index_map.end()){
|
||||
if (it != scheme_information.index_map.end()) {
|
||||
// Found, return it
|
||||
iOutput = static_cast<schemes>(it->second);
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
schemes get_scheme_index(const std::string ¶m_name) {
|
||||
schemes get_scheme_index(const std::string& scheme_name) {
|
||||
schemes iScheme;
|
||||
if (is_valid_scheme(param_name, iScheme)){
|
||||
if (is_valid_scheme(scheme_name, iScheme)) {
|
||||
return iScheme;
|
||||
}
|
||||
else{
|
||||
throw ValueError(format("Your input name [%s] is not valid in get_scheme_index (names are case sensitive)",param_name.c_str()));
|
||||
} else {
|
||||
throw ValueError(format("Your input name [%s] is not valid in get_scheme_index (names are case sensitive)", scheme_name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,21 +762,19 @@ const std::vector<backend_family_info> backend_family_list = {
|
||||
{TREND_BACKEND_FAMILY, "TREND"}, {TTSE_BACKEND_FAMILY, "TTSE"}, {BICUBIC_BACKEND_FAMILY, "BICUBIC"}, {SRK_BACKEND_FAMILY, "SRK"},
|
||||
{PR_BACKEND_FAMILY, "PR"}, {VTPR_BACKEND_FAMILY, "VTPR"}, {PCSAFT_BACKEND_FAMILY, "PCSAFT"}};
|
||||
|
||||
const std::vector<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},
|
||||
{PCSAFT_BACKEND, "PCSAFTBackend", PCSAFT_BACKEND_FAMILY}
|
||||
};
|
||||
const std::vector<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},
|
||||
{PCSAFT_BACKEND, "PCSAFTBackend", PCSAFT_BACKEND_FAMILY}};
|
||||
|
||||
class BackendInformation
|
||||
{
|
||||
|
||||
@@ -287,7 +287,7 @@ void ResidualHelmholtzGeneralizedExponential::all(const CoolPropDbl& tau, const
|
||||
mcx::MultiComplex<double> ResidualHelmholtzGeneralizedExponential::one_mcx(const mcx::MultiComplex<double>& tau,
|
||||
const mcx::MultiComplex<double>& delta) const {
|
||||
//throw CoolProp::NotImplementedError("Nope");
|
||||
mcx::MultiComplex<double> sum00 = 0.0*tau*delta;
|
||||
mcx::MultiComplex<double> sum00 = 0.0 * tau * delta;
|
||||
auto ln_tau = log(tau);
|
||||
auto ln_delta = log(delta);
|
||||
const std::size_t N = elements.size();
|
||||
@@ -592,8 +592,7 @@ void ResidualHelmholtzNonAnalytic::all(const CoolPropDbl& tau_in, const CoolProp
|
||||
}
|
||||
|
||||
#if ENABLE_CATCH
|
||||
mcx::MultiComplex<double> ResidualHelmholtzNonAnalytic::one_mcx(const mcx::MultiComplex<double>& tau,
|
||||
const mcx::MultiComplex<double>& delta) const {
|
||||
mcx::MultiComplex<double> ResidualHelmholtzNonAnalytic::one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const {
|
||||
|
||||
mcx::MultiComplex<double> sum00 = 0.0 * tau * delta;
|
||||
for (unsigned int i = 0; i < N; ++i) {
|
||||
@@ -752,12 +751,11 @@ void ResidualHelmholtzGaoB::all(const CoolPropDbl& tau, const CoolPropDbl& delta
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if ENABLE_CATCH
|
||||
mcx::MultiComplex<double> ResidualHelmholtzGaoB::one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const {
|
||||
mcx::MultiComplex<double> sum00 = 0.0;
|
||||
for (std::size_t i = 0; i < static_cast<int>(n.size()); ++i) {
|
||||
auto u = b[i] + beta[i] * (tau-gamma[i])*(tau-gamma[i]);
|
||||
auto u = b[i] + beta[i] * (tau - gamma[i]) * (tau - gamma[i]);
|
||||
auto Ftau = pow(tau, t[i]) * exp(1.0 / u);
|
||||
auto Fdelta = pow(delta, d[i]) * exp(eta[i] * pow(delta - epsilon[i], 2));
|
||||
sum00 += n[i] * Ftau * Fdelta;
|
||||
@@ -1111,8 +1109,7 @@ void ResidualHelmholtzSAFTAssociating::all(const CoolPropDbl& tau, const CoolPro
|
||||
}
|
||||
|
||||
#if ENABLE_CATCH
|
||||
mcx::MultiComplex<double> IdealHelmholtzCP0PolyT::one_mcx(const mcx::MultiComplex<double>& tau,
|
||||
const mcx::MultiComplex<double>& delta) const {
|
||||
mcx::MultiComplex<double> IdealHelmholtzCP0PolyT::one_mcx(const mcx::MultiComplex<double>& tau, const mcx::MultiComplex<double>& delta) const {
|
||||
mcx::MultiComplex<double> sum = 0.0;
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if (std::abs(t[i]) < 10 * DBL_EPSILON) {
|
||||
@@ -1212,23 +1209,23 @@ void IdealHelmholtzPower::all(const CoolPropDbl& tau, const CoolPropDbl& delta,
|
||||
}
|
||||
}
|
||||
void IdealHelmholtzPlanckEinsteinGeneralized::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() {
|
||||
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CoolPropDbl s00 = 0, s01 = 0, s02 = 0, s03 = 0, s04 = 0;
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
const CoolPropDbl expthetataui = exp(theta[i] * tau);
|
||||
const CoolPropDbl para = c[i] + d[i] * expthetataui;
|
||||
|
||||
|
||||
s00 += n[i] * log(para);
|
||||
s01 += n[i] * theta[i] * d[i] * expthetataui / para;
|
||||
s02 += n[i] * POW2(theta[i]) * c[i] * d[i] * expthetataui / POW2(para);
|
||||
s03 += n[i] * POW3(theta[i]) * c[i] * d[i] * (c[i] - d[i] * expthetataui) * expthetataui / POW3(para);
|
||||
const CoolPropDbl bracket = 6 * POW3(d[i]) * POW3(expthetataui) - 12 * d[i] * d[i] * para * POW2(expthetataui)
|
||||
+ 7 * d[i] * POW2(para) * expthetataui - POW3(para);
|
||||
const CoolPropDbl bracket =
|
||||
6 * POW3(d[i]) * POW3(expthetataui) - 12 * d[i] * d[i] * para * POW2(expthetataui) + 7 * d[i] * POW2(para) * expthetataui - POW3(para);
|
||||
s04 += -n[i] * d[i] * POW4(theta[i]) * bracket * expthetataui / POW4(para);
|
||||
}
|
||||
derivs.alphar += s00;
|
||||
@@ -1423,7 +1420,6 @@ mcx::MultiComplex<double> IdealHelmholtzGERG2004Cosh::one_mcx(const mcx::MultiCo
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//void IdealHelmholtzCP0AlyLee::to_json(rapidjson::Value &el, rapidjson::Document &doc){
|
||||
// el.AddMember("type","IdealGasHelmholtzCP0AlyLee",doc.GetAllocator());
|
||||
// rapidjson::Value _n(rapidjson::kArrayType);
|
||||
@@ -1501,7 +1497,7 @@ class HelmholtzConsistencyFixture
|
||||
{
|
||||
// Signs of eta are flipped relative to paper from Gao et al., implemented with opposite sign in CoolProp
|
||||
std::vector<CoolPropDbl> beta = {0.3696, 0.2962}, epsilon = {0.4478, 0.44689}, eta = {-2.8452, -2.8342}, gamma = {1.108, 1.313},
|
||||
n = {-1.6909858, 0.93739074}, t = {4.3315, 4.015}, d = {1, 1}, b = {1.244, 0.6826};
|
||||
n = {-1.6909858, 0.93739074}, t = {4.3315, 4.015}, d = {1, 1}, b = {1.244, 0.6826};
|
||||
GaoB.reset(new CoolProp::ResidualHelmholtzGaoB(n, t, d, eta, beta, gamma, epsilon, b));
|
||||
}
|
||||
|
||||
@@ -1820,20 +1816,9 @@ std::string terms[] = {"Lead", "LogTau", "IGPower", "PlanckEinstei
|
||||
std::string derivs[] = {"dTau", "dTau2", "dTau3", "dDelta", "dDelta2", "dDelta3", "dDelta_dTau",
|
||||
"dDelta_dTau2", "dDelta2_dTau", "dTau4", "dDelta_dTau3", "dDelta2_dTau2", "dDelta3_dTau", "dDelta4"};
|
||||
std::map<std::string, std::tuple<int, int>> counts = {
|
||||
{"dTau", {1, 0}},
|
||||
{"dTau2", {2, 0}},
|
||||
{"dTau3", {3, 0}},
|
||||
{"dTau4", {4, 0}},
|
||||
{"dDelta", {0, 1}},
|
||||
{"dDelta2", {0, 2}},
|
||||
{"dDelta3", {0, 3}},
|
||||
{"dDelta4", {0, 4}},
|
||||
{"dDelta_dTau", {1, 1}},
|
||||
{"dDelta_dTau2", {2, 1}},
|
||||
{"dDelta2_dTau", {1, 2}},
|
||||
{"dDelta_dTau3", {3, 1}},
|
||||
{"dDelta2_dTau2", {2, 2}},
|
||||
{"dDelta3_dTau", {1, 3}},
|
||||
{"dTau", {1, 0}}, {"dTau2", {2, 0}}, {"dTau3", {3, 0}}, {"dTau4", {4, 0}}, {"dDelta", {0, 1}},
|
||||
{"dDelta2", {0, 2}}, {"dDelta3", {0, 3}}, {"dDelta4", {0, 4}}, {"dDelta_dTau", {1, 1}}, {"dDelta_dTau2", {2, 1}},
|
||||
{"dDelta2_dTau", {1, 2}}, {"dDelta_dTau3", {3, 1}}, {"dDelta2_dTau2", {2, 2}}, {"dDelta3_dTau", {1, 3}},
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(HelmholtzConsistencyFixture, "Helmholtz energy derivatives", "[helmholtz]") {
|
||||
@@ -1872,7 +1857,7 @@ TEST_CASE_METHOD(HelmholtzConsistencyFixture, "Helmholtz energy derivatives", "[
|
||||
CAPTURE(terms[i]);
|
||||
double deriv_tolerance = 1e-9;
|
||||
if (terms[i] == "GERG2004Cosh" || terms[i] == "GERG2004Sinh" || terms[i] == "CP0PolyT") {
|
||||
deriv_tolerance = 1e-7; // due to, I think, a loss in precision in the log function of multicomplex
|
||||
deriv_tolerance = 1e-7; // due to, I think, a loss in precision in the log function of multicomplex
|
||||
}
|
||||
double val_tolerance = 1e-14;
|
||||
if (terms[i] == "CP0PolyT") {
|
||||
|
||||
@@ -378,7 +378,7 @@ static double Secant_Tdb_at_saturated_W(double psi_w, double p, double T_guess)
|
||||
BrentSolverResids(double psi_w, double p) : psi_w(psi_w), p(p) {
|
||||
pp_water = psi_w * p;
|
||||
};
|
||||
~BrentSolverResids(){};
|
||||
~BrentSolverResids() {};
|
||||
|
||||
double call(double T) {
|
||||
double p_ws;
|
||||
@@ -1598,7 +1598,6 @@ class HAProps_T_Residual : public CoolProp::FuncWrapper1D
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Calculate T (dry bulb temp) and psi_w (water mole fraction) given the pair of inputs
|
||||
void _HAPropsSI_inputs(double p, const std::vector<givens>& input_keys, const std::vector<double>& input_vals, double& T, double& psi_w) {
|
||||
if (CoolProp::get_debug_level() > 0) {
|
||||
@@ -2279,24 +2278,20 @@ struct hel
|
||||
};
|
||||
};
|
||||
std::vector<hel> table_A11 = {hel("T", 473.15, "W", 0.00, "P", 101325, "B", 45.07 + 273.15), hel("T", 473.15, "W", 0.00, "P", 101325, "V", 1.341),
|
||||
hel("T", 473.15, "W", 0.00, "P", 101325, "H", 202520), hel("T", 473.15, "W", 0.00, "P", 101325, "S", 555.8),
|
||||
hel("T", 473.15, "W", 0.50, "P", 101325, "B", 81.12 + 273.15), hel("T", 473.15, "W", 0.50, "P", 101325, "V", 2.416),
|
||||
hel("T", 473.15, "W", 0.50, "P", 101325, "H", 1641400), hel("T", 473.15, "W", 0.50, "P", 101325, "S", 4829.5),
|
||||
hel("T", 473.15, "W", 1.00, "P", 101325, "B", 88.15 + 273.15), hel("T", 473.15, "W", 1.00, "P", 101325, "V", 3.489),
|
||||
hel("T", 473.15, "W", 1.00, "P", 101325, "H", 3079550), hel("T", 473.15, "W", 1.00, "P", 101325, "S", 8889.0)};
|
||||
hel("T", 473.15, "W", 0.00, "P", 101325, "H", 202520), hel("T", 473.15, "W", 0.00, "P", 101325, "S", 555.8),
|
||||
hel("T", 473.15, "W", 0.50, "P", 101325, "B", 81.12 + 273.15), hel("T", 473.15, "W", 0.50, "P", 101325, "V", 2.416),
|
||||
hel("T", 473.15, "W", 0.50, "P", 101325, "H", 1641400), hel("T", 473.15, "W", 0.50, "P", 101325, "S", 4829.5),
|
||||
hel("T", 473.15, "W", 1.00, "P", 101325, "B", 88.15 + 273.15), hel("T", 473.15, "W", 1.00, "P", 101325, "V", 3.489),
|
||||
hel("T", 473.15, "W", 1.00, "P", 101325, "H", 3079550), hel("T", 473.15, "W", 1.00, "P", 101325, "S", 8889.0)};
|
||||
|
||||
std::vector<hel> table_A12 = {hel("T", 473.15, "W", 0.00, "P", 1e6, "B", 90.47 + 273.15),
|
||||
hel("T", 473.15, "W", 0.00, "P", 1e6, "V", 0.136),
|
||||
hel("T", 473.15, "W", 0.00, "P", 1e6, "H", 201940),
|
||||
// hel("T", 473.15, "W", 0.00, "P", 1e6, "S", -101.1), Using CoolProp 4.2, this value seems incorrect from report
|
||||
hel("T", 473.15, "W", 0.50, "P", 1e6, "B", 148.49 + 273.15),
|
||||
hel("T", 473.15, "W", 0.50, "P", 1e6, "V", 0.243),
|
||||
hel("T", 473.15, "W", 0.50, "P", 1e6, "H", 1630140),
|
||||
hel("T", 473.15, "W", 0.50, "P", 1e6, "S", 3630.2),
|
||||
hel("T", 473.15, "W", 1.00, "P", 1e6, "B", 159.92 + 273.15),
|
||||
hel("T", 473.15, "W", 1.00, "P", 1e6, "V", 0.347),
|
||||
hel("T", 473.15, "W", 1.00, "P", 1e6, "H", 3050210),
|
||||
hel("T", 473.15, "W", 1.00, "P", 1e6, "S", 7141.3)};
|
||||
std::vector<hel> table_A12 = {
|
||||
hel("T", 473.15, "W", 0.00, "P", 1e6, "B", 90.47 + 273.15), hel("T", 473.15, "W", 0.00, "P", 1e6, "V", 0.136),
|
||||
hel("T", 473.15, "W", 0.00, "P", 1e6, "H", 201940),
|
||||
// hel("T", 473.15, "W", 0.00, "P", 1e6, "S", -101.1), Using CoolProp 4.2, this value seems incorrect from report
|
||||
hel("T", 473.15, "W", 0.50, "P", 1e6, "B", 148.49 + 273.15), hel("T", 473.15, "W", 0.50, "P", 1e6, "V", 0.243),
|
||||
hel("T", 473.15, "W", 0.50, "P", 1e6, "H", 1630140), hel("T", 473.15, "W", 0.50, "P", 1e6, "S", 3630.2),
|
||||
hel("T", 473.15, "W", 1.00, "P", 1e6, "B", 159.92 + 273.15), hel("T", 473.15, "W", 1.00, "P", 1e6, "V", 0.347),
|
||||
hel("T", 473.15, "W", 1.00, "P", 1e6, "H", 3050210), hel("T", 473.15, "W", 1.00, "P", 1e6, "S", 7141.3)};
|
||||
|
||||
std::vector<hel> table_A15 = {
|
||||
hel("T", 473.15, "W", 0.10, "P", 1e7, "B", 188.92 + 273.15), hel("T", 473.15, "W", 0.10, "P", 1e7, "V", 0.016),
|
||||
@@ -2441,7 +2436,7 @@ class ConsistencyTestData
|
||||
|
||||
TEST_CASE("HAProps tests", "[HAProps]") {
|
||||
Eigen::ArrayXd Tdb = Eigen::ArrayXd::LinSpaced(100, -10, 55) + 273.15;
|
||||
for (auto Tdb_ : Tdb){
|
||||
for (auto Tdb_ : Tdb) {
|
||||
CAPTURE(Tdb_);
|
||||
CHECK(ValidNumber(HumidAir::HAProps("W", "T", Tdb_, "R", 1, "P", 101.325)));
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "Exceptions.h"
|
||||
#include <algorithm>
|
||||
|
||||
bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator& ode, double tstart, double tend, double hmin, double hmax, double eps_allowed,
|
||||
bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator& ode, double tmin, double tmax, double hmin, double hmax, double eps_allowed,
|
||||
double step_relax) {
|
||||
// Get the starting array of variables of integration
|
||||
std::vector<double> xold = ode.get_initial_array();
|
||||
@@ -13,11 +13,11 @@ bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator& ode, double tstart, dou
|
||||
|
||||
// Start at an index of 0
|
||||
int Itheta = 0;
|
||||
double t0 = tstart;
|
||||
double t0 = tmin;
|
||||
double h = hmin;
|
||||
|
||||
// Figure out if t is increasing or decreasing in the integration and set a flag
|
||||
bool forwards_integration = ((tend - tstart) > 0);
|
||||
bool forwards_integration = ((tmax - tmin) > 0);
|
||||
// If backwards integration, flip the sign of the step
|
||||
if (!forwards_integration) {
|
||||
h *= -1;
|
||||
@@ -45,13 +45,13 @@ bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator& ode, double tstart, dou
|
||||
|
||||
// If the step would go beyond the end of the region of integration,
|
||||
// just take a step to the end of the region of integration
|
||||
if (forwards_integration && (t0 + h > tend)) {
|
||||
if (forwards_integration && (t0 + h > tmax)) {
|
||||
disableAdaptive = true;
|
||||
h = tend - t0;
|
||||
h = tmax - t0;
|
||||
}
|
||||
if (!forwards_integration && (t0 + h < tend)) {
|
||||
if (!forwards_integration && (t0 + h < tmax)) {
|
||||
disableAdaptive = true;
|
||||
h = tend - t0;
|
||||
h = tmax - t0;
|
||||
}
|
||||
|
||||
ode.pre_step_callback();
|
||||
@@ -152,13 +152,13 @@ bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator& ode, double tstart, dou
|
||||
}
|
||||
|
||||
// Overshot the end, oops... That's an error
|
||||
if (forwards_integration && (t0 - tend > +1e-3)) {
|
||||
throw CoolProp::ValueError(format("t0 - tend [%g] > 1e-3", t0 - tend));
|
||||
if (forwards_integration && (t0 - tmax > +1e-3)) {
|
||||
throw CoolProp::ValueError(format("t0 - tmax [%g] > 1e-3", t0 - tmax));
|
||||
}
|
||||
if (!forwards_integration && (t0 - tend < -1e-3)) {
|
||||
throw CoolProp::ValueError(format("t0 - tend [%g] < -1e-3", t0 - tend));
|
||||
if (!forwards_integration && (t0 - tmax < -1e-3)) {
|
||||
throw CoolProp::ValueError(format("t0 - tmax [%g] < -1e-3", t0 - tmax));
|
||||
}
|
||||
} while (((forwards_integration) && t0 < tend - 1e-10) || ((!forwards_integration) && t0 > tend + 1e-10));
|
||||
} while (((forwards_integration) && t0 < tmax - 1e-10) || ((!forwards_integration) && t0 > tmax + 1e-10));
|
||||
|
||||
// No termination was requested
|
||||
return false;
|
||||
@@ -177,9 +177,9 @@ TEST_CASE("Integrate y'=y", "[ODEIntegrator]") {
|
||||
return std::vector<double>(1, 1);
|
||||
}
|
||||
|
||||
virtual void pre_step_callback(){};
|
||||
virtual void pre_step_callback() {};
|
||||
|
||||
virtual void post_deriv_callback(){};
|
||||
virtual void post_deriv_callback() {};
|
||||
|
||||
virtual void post_step_callback(double t, double h, std::vector<double>& y) {
|
||||
this->t.push_back(t);
|
||||
|
||||
@@ -471,7 +471,7 @@ double Polynomial2DFrac::evaluate(const Eigen::MatrixXd& coefficients, const dou
|
||||
const double x_hi = x_base + CPPOLY_DELTA;
|
||||
const double y_lo = evaluate(coefficients, x_lo, firstExponent, x_base);
|
||||
const double y_hi = evaluate(coefficients, x_hi, firstExponent, x_base);
|
||||
return (y_hi - y_lo)/(x_hi - x_lo) * (x_in - x_lo) + y_lo;
|
||||
return (y_hi - y_lo) / (x_hi - x_lo) * (x_in - x_lo) + y_lo;
|
||||
}
|
||||
|
||||
Eigen::MatrixXd tmpCoeffs(coefficients);
|
||||
@@ -520,7 +520,7 @@ double Polynomial2DFrac::evaluate(const Eigen::MatrixXd& coefficients, const dou
|
||||
const double x_hi = x_base + CPPOLY_DELTA;
|
||||
const double z_lo = evaluate(coefficients, x_lo, y_in, x_exp, y_exp, x_base, y_base);
|
||||
const double z_hi = evaluate(coefficients, x_hi, y_in, x_exp, y_exp, x_base, y_base);
|
||||
return (z_hi - z_lo)/(x_hi - x_lo) * (x_in - x_lo) + z_lo;
|
||||
return (z_hi - z_lo) / (x_hi - x_lo) * (x_in - x_lo) + z_lo;
|
||||
}
|
||||
if ((y_exp < 0) && (std::abs(y_in - y_base) < CPPOLY_EPSILON)) {
|
||||
// throw ValueError(format("%s (%d): A fraction cannot be evaluated with zero as denominator, y_in-y_base=%f ", __FILE__, __LINE__, y_in - y_base));
|
||||
@@ -529,7 +529,7 @@ double Polynomial2DFrac::evaluate(const Eigen::MatrixXd& coefficients, const dou
|
||||
const double y_hi = y_base + CPPOLY_DELTA;
|
||||
const double z_lo = evaluate(coefficients, x_in, y_lo, x_exp, y_exp, x_base, y_base);
|
||||
const double z_hi = evaluate(coefficients, x_in, y_hi, x_exp, y_exp, x_base, y_base);
|
||||
return (z_hi - z_lo)/(y_hi - y_lo) * (y_in - y_lo) + z_lo;
|
||||
return (z_hi - z_lo) / (y_hi - y_lo) * (y_in - y_lo) + z_lo;
|
||||
}
|
||||
|
||||
Eigen::MatrixXd tmpCoeffs(coefficients);
|
||||
|
||||
123
src/Solvers.cpp
123
src/Solvers.cpp
@@ -108,7 +108,7 @@ In the newton function, a 1-D Newton-Raphson solver is implemented using exact s
|
||||
*/
|
||||
double Newton(FuncWrapper1DWithDeriv* f, double x0, double ftol, int maxiter) {
|
||||
double x, dx, dfdx, fval = 999;
|
||||
|
||||
|
||||
// Initialize
|
||||
f->iter = 0;
|
||||
f->errstring.clear();
|
||||
@@ -122,8 +122,8 @@ double Newton(FuncWrapper1DWithDeriv* f, double x0, double ftol, int maxiter) {
|
||||
f->errstring = "Residual function in newton returned invalid number";
|
||||
throw ValueError("Residual function in newton returned invalid number");
|
||||
};
|
||||
|
||||
if (f->verbosity > 0){
|
||||
|
||||
if (f->verbosity > 0) {
|
||||
std::cout << format("i: %d, x: %0.15g, dx: %g, f: %g, dfdx: %g", f->iter, x, dx, fval, dfdx) << std::endl;
|
||||
}
|
||||
|
||||
@@ -190,13 +190,11 @@ double Halley(FuncWrapper1DWithTwoDerivs* f, double x0, double ftol, int maxiter
|
||||
|
||||
dx = -omega * (2 * fval * dfdx) / (2 * POW2(dfdx) - fval * d2fdx2);
|
||||
|
||||
if (f->verbosity > 0){
|
||||
if (f->verbosity > 0) {
|
||||
std::cout << format("i: %d, x: %0.15g, dx: %g, f: %g, dfdx: %g, d2fdx2: %g", f->iter, x, dx, fval, dfdx, d2fdx2) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
x += dx;
|
||||
|
||||
|
||||
|
||||
if (std::abs(dx / x) < xtol_rel) {
|
||||
return x;
|
||||
@@ -429,62 +427,77 @@ Note that this is different than the Secant function because if something goes o
|
||||
@param maxiter Maximum number of iterations
|
||||
@returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity
|
||||
*/
|
||||
double ExtrapolatingSecant(FuncWrapper1D* f, double x0, double dx, double tol, int maxiter)
|
||||
{
|
||||
#if defined(COOLPROP_DEEP_DEBUG)
|
||||
double ExtrapolatingSecant(FuncWrapper1D* f, double x0, double dx, double tol, int maxiter) {
|
||||
#if defined(COOLPROP_DEEP_DEBUG)
|
||||
static std::vector<double> xlog, flog;
|
||||
xlog.clear(); flog.clear();
|
||||
#endif
|
||||
xlog.clear();
|
||||
flog.clear();
|
||||
#endif
|
||||
|
||||
// Initialization
|
||||
double x1=0,x2=0,x3=0,y0=0,y1=0,y2=0,x=x0,fval=999;
|
||||
f->iter=1;
|
||||
double x1 = 0, x2 = 0, x3 = 0, y0 = 0, y1 = 0, y2 = 0, x = x0, fval = 999;
|
||||
f->iter = 1;
|
||||
f->errstring.clear();
|
||||
|
||||
|
||||
// The relaxation factor (less than 1 for smaller steps)
|
||||
double omega = f->options.get_double("omega", 1.0);
|
||||
|
||||
if (std::abs(dx)==0){ f->errstring="dx cannot be zero"; return _HUGE;}
|
||||
while (f->iter<=2 || std::abs(fval)>tol)
|
||||
{
|
||||
if (f->iter==1){x1=x0; x=x1;}
|
||||
if (f->iter==2){x2=x0+dx; x=x2;}
|
||||
if (f->iter>2) {x=x2;}
|
||||
|
||||
if (f->input_not_in_range(x)){
|
||||
throw ValueError(format("Input [%g] is out of range",x));
|
||||
}
|
||||
|
||||
fval = f->call(x);
|
||||
|
||||
#if defined(COOLPROP_DEEP_DEBUG)
|
||||
xlog.push_back(x);
|
||||
flog.push_back(fval);
|
||||
#endif
|
||||
|
||||
if (!ValidNumber(fval)){
|
||||
if (f->iter==1){return x;}
|
||||
else {return x2-omega*y1/(y1-y0)*(x2-x1);}
|
||||
};
|
||||
if (f->iter==1){y1=fval;}
|
||||
if (f->iter>1)
|
||||
{
|
||||
double deltax = x2-x1;
|
||||
if (std::abs(deltax)<1e-14){
|
||||
return x;
|
||||
}
|
||||
y2=fval;
|
||||
double deltay = y2-y1;
|
||||
if (f->iter > 2 && std::abs(deltay)<1e-14){
|
||||
return x;
|
||||
}
|
||||
x3=x2-omega*y2/(y2-y1)*(x2-x1);
|
||||
y0=y1;y1=y2; x1=x2; x2=x3;
|
||||
|
||||
if (std::abs(dx) == 0) {
|
||||
f->errstring = "dx cannot be zero";
|
||||
return _HUGE;
|
||||
}
|
||||
while (f->iter <= 2 || std::abs(fval) > tol) {
|
||||
if (f->iter == 1) {
|
||||
x1 = x0;
|
||||
x = x1;
|
||||
}
|
||||
if (f->iter>maxiter)
|
||||
{
|
||||
f->errstring=std::string("reached maximum number of iterations");
|
||||
if (f->iter == 2) {
|
||||
x2 = x0 + dx;
|
||||
x = x2;
|
||||
}
|
||||
if (f->iter > 2) {
|
||||
x = x2;
|
||||
}
|
||||
|
||||
if (f->input_not_in_range(x)) {
|
||||
throw ValueError(format("Input [%g] is out of range", x));
|
||||
}
|
||||
|
||||
fval = f->call(x);
|
||||
|
||||
#if defined(COOLPROP_DEEP_DEBUG)
|
||||
xlog.push_back(x);
|
||||
flog.push_back(fval);
|
||||
#endif
|
||||
|
||||
if (!ValidNumber(fval)) {
|
||||
if (f->iter == 1) {
|
||||
return x;
|
||||
} else {
|
||||
return x2 - omega * y1 / (y1 - y0) * (x2 - x1);
|
||||
}
|
||||
};
|
||||
if (f->iter == 1) {
|
||||
y1 = fval;
|
||||
}
|
||||
if (f->iter > 1) {
|
||||
double deltax = x2 - x1;
|
||||
if (std::abs(deltax) < 1e-14) {
|
||||
return x;
|
||||
}
|
||||
y2 = fval;
|
||||
double deltay = y2 - y1;
|
||||
if (f->iter > 2 && std::abs(deltay) < 1e-14) {
|
||||
return x;
|
||||
}
|
||||
x3 = x2 - omega * y2 / (y2 - y1) * (x2 - x1);
|
||||
y0 = y1;
|
||||
y1 = y2;
|
||||
x1 = x2;
|
||||
x2 = x3;
|
||||
}
|
||||
if (f->iter > maxiter) {
|
||||
f->errstring = std::string("reached maximum number of iterations");
|
||||
throw SolutionError(format("Secant reached maximum number of iterations"));
|
||||
}
|
||||
f->iter += 1;
|
||||
|
||||
@@ -1030,7 +1030,7 @@ TEST_CASE("Tests for solvers in P,Y flash using Water", "[flash],[PH],[PS],[PU]"
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("R134A saturation bug in dev", "[2545]"){
|
||||
TEST_CASE("R134A saturation bug in dev", "[2545]") {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", "R134A"));
|
||||
AS->update(QT_INPUTS, 1, 273);
|
||||
double p = AS->p();
|
||||
@@ -1358,7 +1358,7 @@ class AncillaryFixture
|
||||
for (std::size_t i = 0; i < fluids.size(); ++i) {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", fluids[i]));
|
||||
auto* rHEOS = dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
if (!rHEOS->is_pure()){
|
||||
if (!rHEOS->is_pure()) {
|
||||
continue;
|
||||
}
|
||||
do_sat(AS);
|
||||
@@ -1540,7 +1540,7 @@ class SatTFixture
|
||||
for (std::size_t i = 0; i < fluids.size(); ++i) {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", fluids[i]));
|
||||
auto* rHEOS = dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
if (!rHEOS->is_pure()){
|
||||
if (!rHEOS->is_pure()) {
|
||||
continue;
|
||||
}
|
||||
do_sat(AS);
|
||||
@@ -1969,19 +1969,17 @@ TEST_CASE("Check the first two-phase derivative using splines", "[first_two_phas
|
||||
D. cmake --build bld
|
||||
E. stdout has the values for the derivatives in mass-based units
|
||||
*/
|
||||
|
||||
|
||||
using paramtuple = std::tuple<parameters, parameters, parameters>;
|
||||
|
||||
SECTION("Compared with reference data"){
|
||||
|
||||
std::map<paramtuple, double> pairs = {
|
||||
{{iDmass, iP, iHmass}, 0.00056718665544440146},
|
||||
{{iDmass, iHmass, iP}, -0.0054665229407696173},
|
||||
{{iDmass, iDmass, iDmass}, 179.19799206447755}
|
||||
};
|
||||
|
||||
|
||||
SECTION("Compared with reference data") {
|
||||
|
||||
std::map<paramtuple, double> pairs = {{{iDmass, iP, iHmass}, 0.00056718665544440146},
|
||||
{{iDmass, iHmass, iP}, -0.0054665229407696173},
|
||||
{{iDmass, iDmass, iDmass}, 179.19799206447755}};
|
||||
|
||||
std::unique_ptr<CoolProp::HelmholtzEOSBackend> AS(new CoolProp::HelmholtzEOSBackend("n-Propane"));
|
||||
for (auto& [pair, expected_value]: pairs) {
|
||||
for (auto& [pair, expected_value] : pairs) {
|
||||
// See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU
|
||||
std::ostringstream ss1;
|
||||
auto& [p1, p2, p3] = pair;
|
||||
@@ -1996,10 +1994,10 @@ TEST_CASE("Check the first two-phase derivative using splines", "[first_two_phas
|
||||
}
|
||||
}
|
||||
}
|
||||
SECTION("Finite diffs"){
|
||||
std::vector<paramtuple> pairs = {{iDmass, iHmass, iP}, {iDmolar, iHmolar, iP}};//, {iDmass, iHmass, iP}};
|
||||
SECTION("Finite diffs") {
|
||||
std::vector<paramtuple> pairs = {{iDmass, iHmass, iP}, {iDmolar, iHmolar, iP}}; //, {iDmass, iHmass, iP}};
|
||||
std::unique_ptr<CoolProp::HelmholtzEOSBackend> AS(new CoolProp::HelmholtzEOSBackend("n-Propane"));
|
||||
for (auto& pair: pairs) {
|
||||
for (auto& pair : pairs) {
|
||||
// See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU
|
||||
std::ostringstream ss1;
|
||||
auto& [p1, p2, p3] = pair;
|
||||
@@ -2090,16 +2088,16 @@ TEST_CASE("Check the PC-SAFT pressure function", "[pcsaft_pressure]") {
|
||||
CHECK(abs((p_calc / p) - 1) < 1e-5);
|
||||
|
||||
p_calc = CoolProp::PropsSI("P", "T", 274., "Dmolar", 55530.40675319466, "PCSAFT::WATER");
|
||||
CHECK(abs((p_calc/p) - 1) < 1e-5);
|
||||
CHECK(abs((p_calc / p) - 1) < 1e-5);
|
||||
|
||||
p_calc = CoolProp::PropsSI("P", "T", 305., "Dmolar", 16965.6697209874,"PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((p_calc/p) - 1) < 1e-5);
|
||||
p_calc = CoolProp::PropsSI("P", "T", 305., "Dmolar", 16965.6697209874, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((p_calc / p) - 1) < 1e-5);
|
||||
|
||||
p_calc = CoolProp::PropsSI("P", "T", 240., "Dmolar", 15955.50941242, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((p_calc/p) - 1) < 1e-5);
|
||||
CHECK(abs((p_calc / p) - 1) < 1e-5);
|
||||
|
||||
p_calc = CoolProp::PropsSI("P", "T", 298.15, "Dmolar", 9368.903838750752, "PCSAFT::METHANOL[0.055]&CYCLOHEXANE[0.945]");
|
||||
CHECK(abs((p_calc/p) - 1) < 1e-5);
|
||||
CHECK(abs((p_calc / p) - 1) < 1e-5);
|
||||
|
||||
//p_calc = CoolProp::PropsSI("P", "T", 298.15, "Dmolar", 55757.07260200306, "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]");
|
||||
//CHECK(abs((p_calc/p) - 1) < 1e-5);
|
||||
@@ -2121,20 +2119,21 @@ TEST_CASE("Check the PC-SAFT density function", "[pcsaft_density]") {
|
||||
den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 274., "P", 101325, "PCSAFT::WATER");
|
||||
CHECK(abs((den_calc / den) - 1) < 1e-5);
|
||||
|
||||
den = 17240.; // source: DIPPR correlation
|
||||
den_calc = CoolProp::PropsSI("Dmolar","T|liquid",305.,"P",101325,"PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((den_calc/den) - 1) < 2e-2);
|
||||
den = 17240.; // source: DIPPR correlation
|
||||
den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 305., "P", 101325, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((den_calc / den) - 1) < 2e-2);
|
||||
|
||||
den = 15955.509146801696;
|
||||
den_calc = CoolProp::PropsSI("Dmolar","T|liquid",240.,"P",101325,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((den_calc/den) - 1) < 1e-5);
|
||||
den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 240., "P", 101325, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((den_calc / den) - 1) < 1e-5);
|
||||
|
||||
den = 9368.90368306872;
|
||||
den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 298.15, "P", 101325, "PCSAFT::METHANOL[0.055]&CYCLOHEXANE[0.945]");
|
||||
CHECK(abs((den_calc / den) - 1) < 1e-5);
|
||||
|
||||
den = 55740.157290833515;
|
||||
den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 298.15, "P", 101325, "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]");
|
||||
den_calc =
|
||||
CoolProp::PropsSI("Dmolar", "T|liquid", 298.15, "P", 101325, "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]");
|
||||
CHECK(abs((den_calc / den) - 1) < 1e-5);
|
||||
|
||||
den = 16621.0;
|
||||
@@ -2150,8 +2149,8 @@ TEST_CASE("Check the PC-SAFT density function", "[pcsaft_density]") {
|
||||
CHECK(abs((den_calc / den) - 1) < 1e-2);
|
||||
|
||||
den = 623.59;
|
||||
den_calc = CoolProp::PropsSI("Dmolar","T|liquid", 430,"P", 2000000, "PCSAFT::PROPANE");
|
||||
CHECK(abs((den_calc/den) - 1) < 1e-2);
|
||||
den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 430, "P", 2000000, "PCSAFT::PROPANE");
|
||||
CHECK(abs((den_calc / den) - 1) < 1e-2);
|
||||
}
|
||||
|
||||
TEST_CASE("Check the PC-SAFT residual enthalpy function", "[pcsaft_enthalpy]") {
|
||||
@@ -2164,20 +2163,20 @@ TEST_CASE("Check the PC-SAFT residual enthalpy function", "[pcsaft_enthalpy]") {
|
||||
CHECK(abs((h_calc / h) - 1) < 1e-5);
|
||||
|
||||
h = -38925.302571456035;
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 16655.853047419932,"PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((h_calc/h) - 1) < 1e-5);
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 16655.853047419932, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((h_calc / h) - 1) < 1e-5);
|
||||
|
||||
h = -15393.870073928741;
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 85.70199446609787, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((h_calc / h) - 1) < 1e-5);
|
||||
|
||||
h = -18242.128097841978;
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 13141.475980937616,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((h_calc/h) - 1) < 1e-5);
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 13141.475980937616, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((h_calc / h) - 1) < 1e-5);
|
||||
|
||||
h = -93.819615173017169;
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 37.963459290365265,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((h_calc/h) - 1) < 1e-5);
|
||||
h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 37.963459290365265, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((h_calc / h) - 1) < 1e-5);
|
||||
|
||||
// checks based on values from the HEOS backend
|
||||
h = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "HEOS::TOLUENE");
|
||||
@@ -2208,20 +2207,20 @@ TEST_CASE("Check the PC-SAFT residual entropy function", "[pcsaft_entropy]") {
|
||||
CHECK(abs((s_calc / s) - 1) < 1e-5);
|
||||
|
||||
s = -47.42736805661422;
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 16655.853047419932,"PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((s_calc/s) - 1) < 1e-5);
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 16655.853047419932, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((s_calc / s) - 1) < 1e-5);
|
||||
|
||||
s = -34.0021996393859;
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 85.70199446609787, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((s_calc / s) - 1) < 1e-5);
|
||||
|
||||
s = -26.42525828195748;
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 13141.475980937616,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((s_calc/s) - 1) < 1e-5);
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 13141.475980937616, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((s_calc / s) - 1) < 1e-5);
|
||||
|
||||
s = -0.08427662199177874;
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 37.963459290365265,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((s_calc/s) - 1) < 1e-5);
|
||||
s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 37.963459290365265, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((s_calc / s) - 1) < 1e-5);
|
||||
|
||||
// checks based on values from the HEOS backend
|
||||
s = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "HEOS::TOLUENE");
|
||||
@@ -2251,20 +2250,20 @@ TEST_CASE("Check the PC-SAFT residual gibbs energy function", "[pcsaft_gibbs]")
|
||||
CHECK(abs((g_calc / g) - 1) < 1e-5);
|
||||
|
||||
g = -7038.128334100866;
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual","T|liquid",325.,"Dmolar", 16655.853314424,"PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((g_calc/g) - 1) < 1e-5);
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual", "T|liquid", 325., "Dmolar", 16655.853314424, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((g_calc / g) - 1) < 1e-5);
|
||||
|
||||
g = -2109.4916554917604;
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual", "T|gas", 325., "Dmolar", 85.70199446609787, "PCSAFT::ACETIC ACID");
|
||||
CHECK(abs((g_calc / g) - 1) < 1e-5);
|
||||
|
||||
g = 6178.973332408309;
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual","T|liquid",325.,"Dmolar", 13141.47619110254,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((g_calc/g) - 1) < 1e-5);
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual", "T|liquid", 325., "Dmolar", 13141.47619110254, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((g_calc / g) - 1) < 1e-5);
|
||||
|
||||
g = -33.038791982589615;
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual","T|gas",325.,"Dmolar", 37.96344503293008,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((g_calc/g) - 1) < 1e-5);
|
||||
g_calc = CoolProp::PropsSI("Gmolar_residual", "T|gas", 325., "Dmolar", 37.96344503293008, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((g_calc / g) - 1) < 1e-5);
|
||||
}
|
||||
|
||||
TEST_CASE("Check vapor pressures calculated using PC-SAFT", "[pcsaft_vapor_pressure]") {
|
||||
@@ -2281,8 +2280,8 @@ TEST_CASE("Check vapor pressures calculated using PC-SAFT", "[pcsaft_vapor_press
|
||||
CHECK(abs((vp_calc / vp) - 1) < 1e-3);
|
||||
|
||||
vp = 622763.506195;
|
||||
vp_calc = CoolProp::PropsSI("P","T", 300.,"Q", 0,"PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((vp_calc/vp) - 1) < 1e-3);
|
||||
vp_calc = CoolProp::PropsSI("P", "T", 300., "Q", 0, "PCSAFT::DIMETHYL ETHER");
|
||||
CHECK(abs((vp_calc / vp) - 1) < 1e-3);
|
||||
|
||||
// This test doesn't pass yet. The flash algorithm for the PC-SAFT backend is not yet robust enough.
|
||||
// vp = 1.7551e-4;
|
||||
@@ -2305,9 +2304,9 @@ TEST_CASE("Check PC-SAFT interaction parameter functions", "[pcsaft_binary_inter
|
||||
CHECK(atof(get_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij").c_str()) == -0.127);
|
||||
}
|
||||
|
||||
TEST_CASE("Check bubble pressures calculated using PC-SAFT", "[pcsaft_bubble_pressure]")
|
||||
{
|
||||
double vp = 1816840.45112607; // source: H.-M. Lin, H. M. Sebastian, J. J. Simnick, and K.-C. Chao, “Gas-liquid equilibrium in binary mixtures of methane with N-decane, benzene, and toluene,” J. Chem. Eng. Data, vol. 24, no. 2, pp. 146–149, Apr. 1979.
|
||||
TEST_CASE("Check bubble pressures calculated using PC-SAFT", "[pcsaft_bubble_pressure]") {
|
||||
double vp =
|
||||
1816840.45112607; // source: H.-M. Lin, H. M. Sebastian, J. J. Simnick, and K.-C. Chao, “Gas-liquid equilibrium in binary mixtures of methane with N-decane, benzene, and toluene,” J. Chem. Eng. Data, vol. 24, no. 2, pp. 146–149, Apr. 1979.
|
||||
double vp_calc = CoolProp::PropsSI("P", "T", 421.05, "Q", 0, "PCSAFT::METHANE[0.0252]&BENZENE[0.9748]");
|
||||
CHECK(abs((vp_calc / vp) - 1) < 1e-3);
|
||||
|
||||
@@ -2325,8 +2324,7 @@ TEST_CASE("Check bubble pressures calculated using PC-SAFT", "[pcsaft_bubble_pre
|
||||
std::string CAS_aacid = "64-19-7";
|
||||
try {
|
||||
get_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij");
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
set_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij", -0.127);
|
||||
}
|
||||
|
||||
@@ -2339,8 +2337,8 @@ TEST_CASE("Check bubble pressures calculated using PC-SAFT", "[pcsaft_bubble_pre
|
||||
CHECK(abs((vp_calc / vp) - 1) < 2e-2);
|
||||
|
||||
vp = 2387.42669687;
|
||||
vp_calc = CoolProp::PropsSI("P","T", 298.15,"Q", 0,"PCSAFT::Na+[0.0907304774758426]&Cl-[0.0907304774758426]&WATER[0.818539045048315]");
|
||||
CHECK(abs((vp_calc/vp) - 1) < 0.23);
|
||||
vp_calc = CoolProp::PropsSI("P", "T", 298.15, "Q", 0, "PCSAFT::Na+[0.0907304774758426]&Cl-[0.0907304774758426]&WATER[0.818539045048315]");
|
||||
CHECK(abs((vp_calc / vp) - 1) < 0.23);
|
||||
}
|
||||
|
||||
TEST_CASE("Check bubble temperatures calculated using PC-SAFT", "[pcsaft_bubble_temperature]") {
|
||||
@@ -2370,12 +2368,11 @@ TEST_CASE("Check bubble temperatures calculated using PC-SAFT", "[pcsaft_bubble_
|
||||
CHECK(abs((t_calc / t) - 1) < 1e-3);
|
||||
|
||||
// set binary interaction parameter, if not already set
|
||||
std::string CAS_water = get_fluid_param_string("WATER","CAS");
|
||||
std::string CAS_water = get_fluid_param_string("WATER", "CAS");
|
||||
std::string CAS_aacid = "64-19-7";
|
||||
try {
|
||||
get_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij");
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
set_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij", -0.127);
|
||||
}
|
||||
|
||||
@@ -2394,7 +2391,7 @@ TEST_CASE("Check bubble temperatures calculated using PC-SAFT", "[pcsaft_bubble_
|
||||
|
||||
TEST_CASE("Github issue #2470", "[pureflash]") {
|
||||
auto fluide = "Nitrogen";
|
||||
auto enthalpy = 67040.57857; //J / kg
|
||||
auto enthalpy = 67040.57857; //J / kg
|
||||
auto pressure = 3368965.046; //Pa
|
||||
std::shared_ptr<CoolProp::AbstractState> AS(AbstractState::factory("HEOS", fluide));
|
||||
AS->update(PQ_INPUTS, pressure, 1);
|
||||
@@ -2448,11 +2445,11 @@ TEST_CASE("Github issue #2608", "[2608]") {
|
||||
std::shared_ptr<CoolProp::AbstractState> AS(AbstractState::factory("HEOS", "CO2"));
|
||||
double pc = AS->p_critical();
|
||||
CHECK_NOTHROW(AS->update(CoolProp::PT_INPUTS, 73.8e5, 218.048));
|
||||
SECTION("Without phase"){
|
||||
SECTION("Without phase") {
|
||||
AS->unspecify_phase();
|
||||
CHECK_NOTHROW(AS->update(CoolProp::PSmass_INPUTS, 73.8e5, 1840.68));
|
||||
}
|
||||
SECTION("With phase"){
|
||||
SECTION("With phase") {
|
||||
AS->specify_phase(iphase_supercritical_gas);
|
||||
CHECK_NOTHROW(AS->update(CoolProp::PSmass_INPUTS, 73.8e5, 1840.68));
|
||||
AS->unspecify_phase();
|
||||
@@ -2470,19 +2467,17 @@ TEST_CASE("Github issue #2622", "[2622]") {
|
||||
|
||||
/// Update at just below the triple point temp
|
||||
AS->update(PT_INPUTS, p5, 165.999);
|
||||
|
||||
|
||||
AS->update(HmassP_INPUTS, h5, p5);
|
||||
double A = AS->T();
|
||||
CAPTURE(A);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> linspace(T start, T end, int num) {
|
||||
std::vector<T> linspaced;
|
||||
if (num <= 0) {
|
||||
return linspaced; // Return empty vector for invalid num
|
||||
return linspaced; // Return empty vector for invalid num
|
||||
}
|
||||
if (num == 1) {
|
||||
linspaced.push_back(start);
|
||||
@@ -2502,14 +2497,14 @@ TEST_CASE("Github issue #2582", "[2582]") {
|
||||
AS->update(PQ_INPUTS, 73.33e5, 0);
|
||||
double hmass_liq = AS->saturated_liquid_keyed_output(iHmass);
|
||||
double hmass_vap = AS->saturated_vapor_keyed_output(iHmass);
|
||||
// std::cout << pc << std::endl;
|
||||
// std::cout << hmass_liq << std::endl;
|
||||
// std::cout << hmass_vap << std::endl;
|
||||
for (auto hmass: linspace(100e3, 700e3, 1000)){
|
||||
// std::cout << pc << std::endl;
|
||||
// std::cout << hmass_liq << std::endl;
|
||||
// std::cout << hmass_vap << std::endl;
|
||||
for (auto hmass : linspace(100e3, 700e3, 1000)) {
|
||||
CAPTURE(hmass);
|
||||
CHECK_NOTHROW(AS->update(CoolProp::HmassP_INPUTS, hmass, 73.76e5));
|
||||
}
|
||||
for (auto hmass: linspace(100e3, 700e3, 1000)){
|
||||
for (auto hmass : linspace(100e3, 700e3, 1000)) {
|
||||
CAPTURE(hmass);
|
||||
CHECK_NOTHROW(AS->update(CoolProp::HmassP_INPUTS, hmass, 73.33e5));
|
||||
}
|
||||
@@ -2524,92 +2519,89 @@ TEST_CASE("Github issue #2594", "[2594]") {
|
||||
double rholiq = AS->rhomolar();
|
||||
double umass_liq = AS->saturated_liquid_keyed_output(iUmass);
|
||||
double umass_vap = AS->saturated_vapor_keyed_output(iUmass);
|
||||
// std::cout << std::setprecision(20) << pc << std::endl;
|
||||
// std::cout << umass_liq << std::endl;
|
||||
// std::cout << umass_vap << std::endl;
|
||||
|
||||
// std::cout << std::setprecision(20) << pc << std::endl;
|
||||
// std::cout << umass_liq << std::endl;
|
||||
// std::cout << umass_vap << std::endl;
|
||||
|
||||
auto umass = 314719.5306503257;
|
||||
// auto& rHEOS = *dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
// bool sat_called = false;
|
||||
// auto MM = AS->molar_mass();
|
||||
// rHEOS.p_phase_determination_pure_or_pseudopure(iUmolar, umass*MM, sat_called);
|
||||
// CHECK(rHEOS.phase() == iphase_liquid);
|
||||
|
||||
// auto& rHEOS = *dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
// bool sat_called = false;
|
||||
// auto MM = AS->molar_mass();
|
||||
// rHEOS.p_phase_determination_pure_or_pseudopure(iUmolar, umass*MM, sat_called);
|
||||
// CHECK(rHEOS.phase() == iphase_liquid);
|
||||
|
||||
AS->update(DmolarP_INPUTS, rholiq, p);
|
||||
double rho1 = AS->rhomolar();
|
||||
double T1 = AS->T();
|
||||
double dumolardT_P = AS->first_partial_deriv(iUmolar, iT, iP);
|
||||
double dpdrho_T = AS->first_partial_deriv(iP, iDmolar, iT);
|
||||
// double dumassdT_P = AS->first_partial_deriv(iUmass, iT, iP);
|
||||
|
||||
// double dumassdT_P = AS->first_partial_deriv(iUmass, iT, iP);
|
||||
|
||||
AS->specify_phase(iphase_liquid);
|
||||
AS->update(PT_INPUTS, p, Tsat);
|
||||
double rho2 = AS->rhomolar();
|
||||
double T2 = AS->T();
|
||||
double dpdrho_T_imposed = AS->first_partial_deriv(iP, iDmolar, iT);
|
||||
double dpdrho_T_imposed = AS->first_partial_deriv(iP, iDmolar, iT);
|
||||
double dumolardT_P_imposed = AS->first_partial_deriv(iUmolar, iT, iP);
|
||||
// double dumassdT_P_imposed = AS->first_partial_deriv(iUmass, iT, iP);
|
||||
// double dumassdT_P_imposed = AS->first_partial_deriv(iUmass, iT, iP);
|
||||
AS->unspecify_phase();
|
||||
|
||||
|
||||
CHECK_NOTHROW(AS->update(CoolProp::PUmass_INPUTS, p, umass));
|
||||
|
||||
BENCHMARK("dp/drho|T"){
|
||||
|
||||
BENCHMARK("dp/drho|T") {
|
||||
return AS->first_partial_deriv(iP, iDmolar, iT);
|
||||
};
|
||||
BENCHMARK("du/dT|p"){
|
||||
BENCHMARK("du/dT|p") {
|
||||
return AS->first_partial_deriv(iUmolar, iT, iP);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("CoolProp.jl tests", "[2598]") {
|
||||
// // Whoah, actually quite a few change meaningfully
|
||||
// SECTION("Check pcrit doesn't change too much with SA on"){
|
||||
// auto init = get_config_bool(ENABLE_SUPERANCILLARIES);
|
||||
// for (auto fluid : strsplit(get_global_param_string("fluids_list"), ',')){
|
||||
// CAPTURE(fluid);
|
||||
// set_config_bool(ENABLE_SUPERANCILLARIES, true); auto pcrit_SA = Props1SI(fluid, "pcrit");
|
||||
// set_config_bool(ENABLE_SUPERANCILLARIES, false); auto pcrit_noSA = Props1SI(fluid, "pcrit");
|
||||
// CAPTURE(pcrit_SA - pcrit_noSA);
|
||||
// CHECK(std::abs(pcrit_SA/pcrit_noSA-1) < 1E-2);
|
||||
// }
|
||||
// set_config_bool(ENABLE_SUPERANCILLARIES, init);
|
||||
// }
|
||||
|
||||
for (auto fluid : strsplit(get_global_param_string("fluids_list"), ',')){
|
||||
// // Whoah, actually quite a few change meaningfully
|
||||
// SECTION("Check pcrit doesn't change too much with SA on"){
|
||||
// auto init = get_config_bool(ENABLE_SUPERANCILLARIES);
|
||||
// for (auto fluid : strsplit(get_global_param_string("fluids_list"), ',')){
|
||||
// CAPTURE(fluid);
|
||||
// set_config_bool(ENABLE_SUPERANCILLARIES, true); auto pcrit_SA = Props1SI(fluid, "pcrit");
|
||||
// set_config_bool(ENABLE_SUPERANCILLARIES, false); auto pcrit_noSA = Props1SI(fluid, "pcrit");
|
||||
// CAPTURE(pcrit_SA - pcrit_noSA);
|
||||
// CHECK(std::abs(pcrit_SA/pcrit_noSA-1) < 1E-2);
|
||||
// }
|
||||
// set_config_bool(ENABLE_SUPERANCILLARIES, init);
|
||||
// }
|
||||
|
||||
for (auto fluid : strsplit(get_global_param_string("fluids_list"), ',')) {
|
||||
auto pcrit = Props1SI(fluid, "pcrit");
|
||||
auto Tcrit = Props1SI(fluid, "Tcrit");
|
||||
CAPTURE(fluid);
|
||||
CAPTURE(PhaseSI("P", pcrit+50000, "T", Tcrit+3, fluid));
|
||||
CAPTURE(PhaseSI("P", pcrit+50000, "T", Tcrit-3, fluid));
|
||||
CAPTURE(PhaseSI("P", pcrit-50000, "T", Tcrit+3, fluid));
|
||||
|
||||
CAPTURE(PropsSI("Q", "P", pcrit+50000, "T", Tcrit+3, fluid));
|
||||
CAPTURE(PropsSI("Q", "P", pcrit+50000, "T", Tcrit-3, fluid));
|
||||
CAPTURE(PropsSI("Q", "P", pcrit-50000, "T", Tcrit+3, fluid));
|
||||
|
||||
CHECK(PhaseSI("P", pcrit+50000, "T", Tcrit+3, fluid)=="supercritical");
|
||||
CHECK(PhaseSI("P", pcrit+50000, "T", Tcrit-3, fluid)=="supercritical_liquid");
|
||||
CHECK(PhaseSI("P", pcrit-50000, "T", Tcrit+3, fluid)=="supercritical_gas");
|
||||
CAPTURE(PhaseSI("P", pcrit + 50000, "T", Tcrit + 3, fluid));
|
||||
CAPTURE(PhaseSI("P", pcrit + 50000, "T", Tcrit - 3, fluid));
|
||||
CAPTURE(PhaseSI("P", pcrit - 50000, "T", Tcrit + 3, fluid));
|
||||
|
||||
CAPTURE(PropsSI("Q", "P", pcrit + 50000, "T", Tcrit + 3, fluid));
|
||||
CAPTURE(PropsSI("Q", "P", pcrit + 50000, "T", Tcrit - 3, fluid));
|
||||
CAPTURE(PropsSI("Q", "P", pcrit - 50000, "T", Tcrit + 3, fluid));
|
||||
|
||||
CHECK(PhaseSI("P", pcrit + 50000, "T", Tcrit + 3, fluid) == "supercritical");
|
||||
CHECK(PhaseSI("P", pcrit + 50000, "T", Tcrit - 3, fluid) == "supercritical_liquid");
|
||||
CHECK(PhaseSI("P", pcrit - 50000, "T", Tcrit + 3, fluid) == "supercritical_gas");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Check methanol EOS matches REFPROP 10", "[2538]"){
|
||||
TEST_CASE("Check methanol EOS matches REFPROP 10", "[2538]") {
|
||||
auto TNBP_RP = PropsSI("T", "P", 101325, "Q", 0, "REFPROP::METHANOL");
|
||||
auto TNBP_CP = PropsSI("T", "P", 101325, "Q", 0, "HEOS::METHANOL");
|
||||
CHECK(TNBP_RP == Catch::Approx(TNBP_CP).epsilon(1e-6));
|
||||
|
||||
|
||||
auto rhoL_RP = PropsSI("D", "T", 400, "Q", 0, "REFPROP::METHANOL");
|
||||
auto rhoL_CP = PropsSI("D", "T", 400, "Q", 0, "HEOS::METHANOL");
|
||||
CHECK(rhoL_RP == Catch::Approx(rhoL_CP).epsilon(1e-12));
|
||||
|
||||
|
||||
auto cp0_RP = PropsSI("CP0MOLAR", "T", 400, "Dmolar", 1e-5, "REFPROP::METHANOL");
|
||||
auto cp0_CP = PropsSI("CP0MOLAR", "T", 400, "Dmolar", 1e-5, "HEOS::METHANOL");
|
||||
CHECK(cp0_RP == Catch::Approx(cp0_CP).epsilon(1e-4));
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Check phase determination for PC-SAFT backend", "[pcsaft_phase]") {
|
||||
double den = 9033.114209728405;
|
||||
double den_calc = CoolProp::PropsSI("Dmolar", "T", 320., "P", 101325., "PCSAFT::TOLUENE");
|
||||
@@ -2624,174 +2616,176 @@ TEST_CASE("Check phase determination for PC-SAFT backend", "[pcsaft_phase]") {
|
||||
CHECK(phase == get_phase_index("phase_gas"));
|
||||
}
|
||||
|
||||
TEST_CASE("Check that indexes for mixtures are assigned correctly, especially for the association term", "[pcsaft_indexes]")
|
||||
{
|
||||
TEST_CASE("Check that indexes for mixtures are assigned correctly, especially for the association term", "[pcsaft_indexes]") {
|
||||
// The tests are performed by adding parameters for extra compounds that actually
|
||||
// are not present in the system and ensuring that the properties of the fluid do not change.
|
||||
|
||||
// Binary mixture: water-acetic acid
|
||||
// set binary interaction parameter, if not already set
|
||||
std::string CAS_water = get_fluid_param_string("WATER","CAS");
|
||||
// set binary interaction parameter, if not already set
|
||||
std::string CAS_water = get_fluid_param_string("WATER", "CAS");
|
||||
std::string CAS_aacid = "64-19-7";
|
||||
try {
|
||||
get_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij");
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
set_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij", -0.127);
|
||||
}
|
||||
|
||||
double t = 413.5385;
|
||||
double rho = 15107.481234283325;
|
||||
double p = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::ACETIC ACID"); // only parameters for acetic acid
|
||||
double p_extra = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::ACETIC ACID[1.0]&WATER[0]"); // same composition, but with mixture parameters
|
||||
CHECK(abs((p_extra - p)/ p * 100) < 1e-1);
|
||||
double p = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::ACETIC ACID"); // only parameters for acetic acid
|
||||
double p_extra =
|
||||
CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::ACETIC ACID[1.0]&WATER[0]"); // same composition, but with mixture parameters
|
||||
CHECK(abs((p_extra - p) / p * 100) < 1e-1);
|
||||
|
||||
// Binary mixture: water-furfural
|
||||
t = 400; // K
|
||||
t = 400; // K
|
||||
// p = 34914.37778265716; // Pa
|
||||
rho = 10657.129498214763;
|
||||
p = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::FURFURAL"); // only parameters for furfural
|
||||
p_extra = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::WATER[0]&FURFURAL[1.0]"); // same composition, but with mixture of components
|
||||
CHECK(abs((p_extra - p)/ p * 100) < 1e-1);
|
||||
p = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::FURFURAL"); // only parameters for furfural
|
||||
p_extra = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::WATER[0]&FURFURAL[1.0]"); // same composition, but with mixture of components
|
||||
CHECK(abs((p_extra - p) / p * 100) < 1e-1);
|
||||
|
||||
// Mixture: NaCl in water with random 4th component
|
||||
t = 298.15; // K
|
||||
t = 298.15; // K
|
||||
// p = 3153.417688548272; // Pa
|
||||
rho = 55320.89616248148;
|
||||
p = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::WATER"); // only parameters for water
|
||||
p_extra = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::Na+[0]&Cl-[0]&WATER[1.0]&DIMETHOXYMETHANE[0]"); // same composition, but with mixture of components
|
||||
CHECK(abs((p_extra - p)/ p * 100) < 1e-1);
|
||||
p = CoolProp::PropsSI("P", "T", t, "Dmolar", rho, "PCSAFT::WATER"); // only parameters for water
|
||||
p_extra = CoolProp::PropsSI("P", "T", t, "Dmolar", rho,
|
||||
"PCSAFT::Na+[0]&Cl-[0]&WATER[1.0]&DIMETHOXYMETHANE[0]"); // same composition, but with mixture of components
|
||||
CHECK(abs((p_extra - p) / p * 100) < 1e-1);
|
||||
}
|
||||
|
||||
/// A fixture class to enable superancillaries just for a given test
|
||||
class SuperAncillaryOnFixture{
|
||||
private:
|
||||
class SuperAncillaryOnFixture
|
||||
{
|
||||
private:
|
||||
const configuration_keys m_key = ENABLE_SUPERANCILLARIES;
|
||||
const bool initial_value;
|
||||
public:
|
||||
|
||||
public:
|
||||
SuperAncillaryOnFixture() : initial_value(CoolProp::get_config_bool(m_key)) {
|
||||
CoolProp::set_config_bool(m_key, true);
|
||||
}
|
||||
~SuperAncillaryOnFixture(){
|
||||
~SuperAncillaryOnFixture() {
|
||||
CoolProp::set_config_bool(m_key, initial_value);
|
||||
}
|
||||
};
|
||||
|
||||
/// A fixture class to enable superancillaries just for a given test
|
||||
class SuperAncillaryOffFixture{
|
||||
private:
|
||||
class SuperAncillaryOffFixture
|
||||
{
|
||||
private:
|
||||
const configuration_keys m_key = ENABLE_SUPERANCILLARIES;
|
||||
const bool initial_value;
|
||||
public:
|
||||
|
||||
public:
|
||||
SuperAncillaryOffFixture() : initial_value(CoolProp::get_config_bool(m_key)) {
|
||||
CoolProp::set_config_bool(m_key, false);
|
||||
}
|
||||
~SuperAncillaryOffFixture(){
|
||||
~SuperAncillaryOffFixture() {
|
||||
CoolProp::set_config_bool(m_key, initial_value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_CASE_METHOD(SuperAncillaryOnFixture, "Check superancillary for water", "[superanc]") {
|
||||
|
||||
|
||||
auto json = nlohmann::json::parse(get_fluid_param_string("WATER", "JSON"))[0].at("EOS")[0].at("SUPERANCILLARY");
|
||||
superancillary::SuperAncillary<std::vector<double>> anc{json};
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", "Water"));
|
||||
shared_ptr<CoolProp::AbstractState> IF97(CoolProp::AbstractState::factory("IF97", "Water"));
|
||||
auto& rHEOS = *dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
BENCHMARK("HEOS.clear()"){
|
||||
BENCHMARK("HEOS.clear()") {
|
||||
return rHEOS.clear();
|
||||
};
|
||||
BENCHMARK("HEOS rho(T)"){
|
||||
BENCHMARK("HEOS rho(T)") {
|
||||
return AS->update(QT_INPUTS, 1.0, 300.0);
|
||||
};
|
||||
BENCHMARK("HEOS update_QT_pure_superanc(Q,T)"){
|
||||
BENCHMARK("HEOS update_QT_pure_superanc(Q,T)") {
|
||||
return rHEOS.update_QT_pure_superanc(1.0, 300.0);
|
||||
};
|
||||
BENCHMARK("superanc rho(T)"){
|
||||
BENCHMARK("superanc rho(T)") {
|
||||
return anc.eval_sat(300.0, 'D', 1);
|
||||
};
|
||||
BENCHMARK("IF97 rho(T)"){
|
||||
BENCHMARK("IF97 rho(T)") {
|
||||
return IF97->update(QT_INPUTS, 1.0, 300.0);
|
||||
};
|
||||
|
||||
|
||||
double Tmin = AS->get_fluid_parameter_double(0, "SUPERANC::Tmin");
|
||||
double Tc = AS->get_fluid_parameter_double(0, "SUPERANC::Tcrit_num");
|
||||
double pmin = AS->get_fluid_parameter_double(0, "SUPERANC::pmin");
|
||||
double pmax = AS->get_fluid_parameter_double(0, "SUPERANC::pmax");
|
||||
|
||||
|
||||
CHECK_THROWS(AS->get_fluid_parameter_double(1, "SUPERANC::pmax"));
|
||||
|
||||
BENCHMARK("HEOS rho(p)"){
|
||||
|
||||
BENCHMARK("HEOS rho(p)") {
|
||||
return AS->update(PQ_INPUTS, 101325, 1.0);
|
||||
};
|
||||
BENCHMARK("superanc T(p)"){
|
||||
BENCHMARK("superanc T(p)") {
|
||||
return anc.get_T_from_p(101325);
|
||||
};
|
||||
BENCHMARK("IF97 rho(p)"){
|
||||
BENCHMARK("IF97 rho(p)") {
|
||||
return IF97->update(PQ_INPUTS, 101325, 1.0);
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SuperAncillaryOnFixture, "Benchmark class construction", "[superanc]") {
|
||||
|
||||
BENCHMARK("Water [SA]"){
|
||||
|
||||
BENCHMARK("Water [SA]") {
|
||||
return shared_ptr<CoolProp::AbstractState>(CoolProp::AbstractState::factory("HEOS", "Water"));
|
||||
};
|
||||
BENCHMARK("R410A [no SA]"){
|
||||
BENCHMARK("R410A [no SA]") {
|
||||
return shared_ptr<CoolProp::AbstractState>(CoolProp::AbstractState::factory("HEOS", "R410A"));
|
||||
};
|
||||
BENCHMARK("propane [SA]"){
|
||||
BENCHMARK("propane [SA]") {
|
||||
return shared_ptr<CoolProp::AbstractState>(CoolProp::AbstractState::factory("HEOS", "n-Propane"));
|
||||
};
|
||||
BENCHMARK("air, pseudo-pure [SA]"){
|
||||
BENCHMARK("air, pseudo-pure [SA]") {
|
||||
return shared_ptr<CoolProp::AbstractState>(CoolProp::AbstractState::factory("HEOS", "Air"));
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SuperAncillaryOffFixture, "Check superancillary-like calculations with superancillary disabled for water", "[superanc]") {
|
||||
|
||||
|
||||
auto json = nlohmann::json::parse(get_fluid_param_string("WATER", "JSON"))[0].at("EOS")[0].at("SUPERANCILLARY");
|
||||
superancillary::SuperAncillary<std::vector<double>> anc{json};
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", "Water"));
|
||||
shared_ptr<CoolProp::AbstractState> IF97(CoolProp::AbstractState::factory("IF97", "Water"));
|
||||
auto& approxrhoL = anc.get_approx1d('D', 0);
|
||||
|
||||
BENCHMARK("HEOS rho(T)"){
|
||||
|
||||
BENCHMARK("HEOS rho(T)") {
|
||||
return AS->update(QT_INPUTS, 1.0, 300.0);
|
||||
};
|
||||
BENCHMARK("superanc rho(T)"){
|
||||
BENCHMARK("superanc rho(T)") {
|
||||
return anc.eval_sat(300.0, 'D', 1);
|
||||
};
|
||||
BENCHMARK("superanc rho(T) with expansion directly"){
|
||||
BENCHMARK("superanc rho(T) with expansion directly") {
|
||||
return approxrhoL.eval(300.0);
|
||||
};
|
||||
BENCHMARK("superanc get_index rho(T)"){
|
||||
BENCHMARK("superanc get_index rho(T)") {
|
||||
return approxrhoL.get_index(300.0);
|
||||
};
|
||||
BENCHMARK("IF97 rho(T)"){
|
||||
BENCHMARK("IF97 rho(T)") {
|
||||
return IF97->update(QT_INPUTS, 1.0, 300.0);
|
||||
};
|
||||
|
||||
BENCHMARK("HEOS rho(p)"){
|
||||
|
||||
BENCHMARK("HEOS rho(p)") {
|
||||
return AS->update(PQ_INPUTS, 101325, 1.0);
|
||||
};
|
||||
BENCHMARK("superanc T(p)"){
|
||||
BENCHMARK("superanc T(p)") {
|
||||
return anc.get_T_from_p(101325);
|
||||
};
|
||||
BENCHMARK("IF97 rho(p)"){
|
||||
BENCHMARK("IF97 rho(p)") {
|
||||
return IF97->update(PQ_INPUTS, 101325, 1.0);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE_METHOD(SuperAncillaryOnFixture, "Check superancillary functions are available for all pure fluids", "[ancillary]") {
|
||||
for (auto & fluid : strsplit(CoolProp::get_global_param_string("fluids_list"), ',')){
|
||||
for (auto& fluid : strsplit(CoolProp::get_global_param_string("fluids_list"), ',')) {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", fluid));
|
||||
auto& rHEOS = *dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
if (rHEOS.is_pure()){
|
||||
if (rHEOS.is_pure()) {
|
||||
CAPTURE(fluid);
|
||||
CHECK_NOTHROW(rHEOS.update_QT_pure_superanc(1, rHEOS.T_critical()*0.9999));
|
||||
CHECK_NOTHROW(rHEOS.update_QT_pure_superanc(1, rHEOS.T_critical() * 0.9999));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2837,7 +2831,7 @@ TEST_CASE_METHOD(SuperAncillaryOnFixture, "Check h_fg", "[superanc]") {
|
||||
|
||||
TEST_CASE_METHOD(SuperAncillaryOnFixture, "Performance regression; on", "[2438]") {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", "CO2"));
|
||||
BENCHMARK("HP regression"){
|
||||
BENCHMARK("HP regression") {
|
||||
AS->update(HmassP_INPUTS, 300e3, 70e5);
|
||||
return AS;
|
||||
};
|
||||
@@ -2846,7 +2840,7 @@ TEST_CASE_METHOD(SuperAncillaryOnFixture, "Performance regression; on", "[2438]"
|
||||
}
|
||||
TEST_CASE_METHOD(SuperAncillaryOffFixture, "Performance regression; off", "[2438]") {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", "CO2"));
|
||||
BENCHMARK("HP regression"){
|
||||
BENCHMARK("HP regression") {
|
||||
AS->update(HmassP_INPUTS, 300e3, 70e5);
|
||||
return AS;
|
||||
};
|
||||
@@ -2860,8 +2854,8 @@ TEST_CASE_METHOD(SuperAncillaryOnFixture, "Performance regression for TS; on", "
|
||||
auto sL = AS->saturated_liquid_keyed_output(iSmolar);
|
||||
auto sV = AS->saturated_vapor_keyed_output(iSmolar);
|
||||
auto N = 1000000U;
|
||||
for (auto i = 0; i < N; ++i){
|
||||
AS->update(SmolarT_INPUTS, (sL + sV)/2 + i*1e-14, T);
|
||||
for (auto i = 0; i < N; ++i) {
|
||||
AS->update(SmolarT_INPUTS, (sL + sV) / 2 + i * 1e-14, T);
|
||||
}
|
||||
CHECK(AS->T() != 0);
|
||||
}
|
||||
@@ -2872,8 +2866,8 @@ TEST_CASE_METHOD(SuperAncillaryOnFixture, "Performance regression for TS; on", "
|
||||
AS->update(QT_INPUTS, 1, T);
|
||||
auto sL = AS->saturated_liquid_keyed_output(iSmolar);
|
||||
auto sV = AS->saturated_vapor_keyed_output(iSmolar);
|
||||
BENCHMARK("ST regression"){
|
||||
AS->update(SmolarT_INPUTS, (sL + sV)/2, T);
|
||||
BENCHMARK("ST regression") {
|
||||
AS->update(SmolarT_INPUTS, (sL + sV) / 2, T);
|
||||
return AS;
|
||||
};
|
||||
}
|
||||
@@ -2884,108 +2878,118 @@ TEST_CASE_METHOD(SuperAncillaryOffFixture, "Performance regression for TS; off",
|
||||
AS->update(QT_INPUTS, 1, T);
|
||||
auto sL = AS->saturated_liquid_keyed_output(iSmolar);
|
||||
auto sV = AS->saturated_vapor_keyed_output(iSmolar);
|
||||
BENCHMARK("ST regression"){
|
||||
AS->update(SmolarT_INPUTS, (sL + sV)/2, T);
|
||||
BENCHMARK("ST regression") {
|
||||
AS->update(SmolarT_INPUTS, (sL + sV) / 2, T);
|
||||
return AS;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SuperAncillaryOnFixture, "Benchmarking caching options", "[caching]") {
|
||||
std::array<double, 16> buf15; buf15.fill(0.0);
|
||||
std::array<double, 100> buf100; buf100.fill(0.0);
|
||||
std::array<bool, 100> bool100; bool100.fill(false);
|
||||
std::array<double, 16> buf15;
|
||||
buf15.fill(0.0);
|
||||
std::array<double, 100> buf100;
|
||||
buf100.fill(0.0);
|
||||
std::array<bool, 100> bool100;
|
||||
bool100.fill(false);
|
||||
std::vector<CachedElement> cache100(100);
|
||||
for (auto i = 0; i < cache100.size(); ++i){ cache100[i] = _HUGE; }
|
||||
|
||||
for (auto i = 0; i < cache100.size(); ++i) {
|
||||
cache100[i] = _HUGE;
|
||||
}
|
||||
|
||||
std::vector<std::optional<double>> opt100(100);
|
||||
for (auto i = 0; i < opt100.size(); ++i){ opt100[i] = _HUGE; }
|
||||
|
||||
BENCHMARK("memset array15 w/ 0"){
|
||||
for (auto i = 0; i < opt100.size(); ++i) {
|
||||
opt100[i] = _HUGE;
|
||||
}
|
||||
|
||||
BENCHMARK("memset array15 w/ 0") {
|
||||
std::memset(buf15.data(), 0, sizeof(buf15));
|
||||
return buf15;
|
||||
};
|
||||
BENCHMARK("std::fill_n array15"){
|
||||
BENCHMARK("std::fill_n array15") {
|
||||
std::fill_n(buf15.data(), 15, _HUGE);
|
||||
return buf15;
|
||||
};
|
||||
BENCHMARK("std::fill array15"){
|
||||
BENCHMARK("std::fill array15") {
|
||||
std::fill(buf15.begin(), buf15.end(), _HUGE);
|
||||
return buf15;
|
||||
};
|
||||
BENCHMARK("array15.fill()"){
|
||||
BENCHMARK("array15.fill()") {
|
||||
buf15.fill(_HUGE);
|
||||
return buf15;
|
||||
};
|
||||
BENCHMARK("memset array100 w/ 0"){
|
||||
BENCHMARK("memset array100 w/ 0") {
|
||||
memset(buf100.data(), 0, sizeof(buf100));
|
||||
return buf100;
|
||||
};
|
||||
BENCHMARK("memset bool100 w/ 0"){
|
||||
BENCHMARK("memset bool100 w/ 0") {
|
||||
memset(bool100.data(), false, sizeof(bool100));
|
||||
return buf100;
|
||||
};
|
||||
BENCHMARK("std::fill_n array100"){
|
||||
BENCHMARK("std::fill_n array100") {
|
||||
std::fill_n(buf100.data(), 100, _HUGE);
|
||||
return buf100;
|
||||
};
|
||||
BENCHMARK("fill array100"){
|
||||
BENCHMARK("fill array100") {
|
||||
buf100.fill(_HUGE);
|
||||
return buf100;
|
||||
};
|
||||
BENCHMARK("fill cache100"){
|
||||
for (auto i = 0; i < cache100.size(); ++i){ cache100[i] = _HUGE; }
|
||||
BENCHMARK("fill cache100") {
|
||||
for (auto i = 0; i < cache100.size(); ++i) {
|
||||
cache100[i] = _HUGE;
|
||||
}
|
||||
return cache100;
|
||||
};
|
||||
BENCHMARK("fill opt100"){
|
||||
for (auto i = 0; i < opt100.size(); ++i){ opt100[i] = _HUGE; }
|
||||
BENCHMARK("fill opt100") {
|
||||
for (auto i = 0; i < opt100.size(); ++i) {
|
||||
opt100[i] = _HUGE;
|
||||
}
|
||||
return opt100;
|
||||
};
|
||||
}
|
||||
std::vector<std::tuple<double, double, double, double>> MSA22values = {
|
||||
{200, 199.97, 142.56, 1.29559},
|
||||
{300, 300.19, 214.07, 1.70203},
|
||||
{400, 400.98, 286.16, 1.99194},
|
||||
{500, 503.02, 359.49, 2.21952},
|
||||
{200, 199.97, 142.56, 1.29559},
|
||||
{300, 300.19, 214.07, 1.70203},
|
||||
{400, 400.98, 286.16, 1.99194},
|
||||
{500, 503.02, 359.49, 2.21952},
|
||||
};
|
||||
|
||||
TEST_CASE("Ideal gas thermodynamic properties", "[2589]"){
|
||||
TEST_CASE("Ideal gas thermodynamic properties", "[2589]") {
|
||||
shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory("HEOS", "Air"));
|
||||
shared_ptr<CoolProp::AbstractState> RP(CoolProp::AbstractState::factory("REFPROP", "Air"));
|
||||
|
||||
|
||||
auto& rRP = *dynamic_cast<REFPROPMixtureBackend*>(AS.get());
|
||||
auto& rHEOS = *dynamic_cast<HelmholtzEOSMixtureBackend*>(AS.get());
|
||||
|
||||
|
||||
AS->specify_phase(iphase_gas);
|
||||
RP->specify_phase(iphase_gas);
|
||||
|
||||
|
||||
double pig = 101325;
|
||||
|
||||
// Moran & Shapiro Table A-22 reference is h(T=0) = 0, but that doesn't play nicely
|
||||
// with tau=Tc/T = oo and delta = 0/rhor = 0
|
||||
|
||||
for (auto [T_K, h_kJkg, u_kJkg, s_kJkgK] : MSA22values){
|
||||
double rho = pig/(AS->gas_constant()*T_K); // ideal-gas molar density assuming Z=1
|
||||
|
||||
for (auto [T_K, h_kJkg, u_kJkg, s_kJkgK] : MSA22values) {
|
||||
double rho = pig / (AS->gas_constant() * T_K); // ideal-gas molar density assuming Z=1
|
||||
AS->update(DmolarT_INPUTS, rho, T_K);
|
||||
RP->update(DmolarT_INPUTS, rho, T_K);
|
||||
|
||||
CHECK(AS->smass_idealgas()/AS->gas_constant() == Catch::Approx(RP->smass_idealgas()/AS->gas_constant()));
|
||||
CHECK(AS->hmass_idealgas()/AS->gas_constant() == Catch::Approx(RP->hmass_idealgas()/AS->gas_constant()));
|
||||
|
||||
|
||||
CHECK(AS->smass_idealgas() / AS->gas_constant() == Catch::Approx(RP->smass_idealgas() / AS->gas_constant()));
|
||||
CHECK(AS->hmass_idealgas() / AS->gas_constant() == Catch::Approx(RP->hmass_idealgas() / AS->gas_constant()));
|
||||
|
||||
std::vector<double> mf(20, 1.0);
|
||||
auto o = rRP.call_THERM0dll(T_K, rho/1e3, mf);
|
||||
auto o = rRP.call_THERM0dll(T_K, rho / 1e3, mf);
|
||||
CHECK(o.hmol_Jmol == Catch::Approx(RP->hmolar_idealgas()).epsilon(1e-12));
|
||||
CHECK(o.smol_JmolK == Catch::Approx(RP->smolar_idealgas()).epsilon(1e-12));
|
||||
CHECK(o.umol_Jmol == Catch::Approx(RP->umolar_idealgas()).epsilon(1e-12));
|
||||
|
||||
|
||||
CAPTURE(T_K);
|
||||
CAPTURE(AS->hmass_idealgas());
|
||||
CAPTURE(AS->hmass_idealgas()-h_kJkg*1e3);
|
||||
CAPTURE(AS->hmass_idealgas() - h_kJkg * 1e3);
|
||||
CAPTURE(AS->smass_idealgas());
|
||||
CAPTURE(AS->smass_idealgas()-s_kJkgK*1e3);
|
||||
CAPTURE(AS->smass_idealgas() - s_kJkgK * 1e3);
|
||||
CAPTURE(AS->umass_idealgas());
|
||||
CAPTURE(AS->umass_idealgas()-u_kJkg*1e3);
|
||||
CAPTURE(AS->umass_idealgas() - u_kJkg * 1e3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user