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:
Ian Bell
2025-10-05 11:02:51 -04:00
committed by GitHub
parent eac9028460
commit 9eb3eb8db1
67 changed files with 2744 additions and 2638 deletions

View File

@@ -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: '*'

View File

@@ -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

View File

@@ -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

View File

@@ -709,5 +709,4 @@ double asinh(double value) {
# undef EOS
#endif
#endif

View File

@@ -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);

View File

@@ -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
};
};

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -141,7 +141,7 @@ class IncompressibleFluid
strict = true;
xid = IFRAC_UNDEFINED;
};
virtual ~IncompressibleFluid(){};
virtual ~IncompressibleFluid() {};
std::string getName() const {
return name;

View File

@@ -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;

View File

@@ -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);
};

View File

@@ -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) {

View File

@@ -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

View File

@@ -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,

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {};
};
/**

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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() {

View File

@@ -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);
};

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -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++;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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")) {

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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);

View File

@@ -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();

View File

@@ -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
}

View File

@@ -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];
}

View File

@@ -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);

View File

@@ -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 &param_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
{

View File

@@ -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") {

View File

@@ -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)));
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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. 146149, 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. 146149, 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);
}
}
/*