76 this->_rhomass.
clear();
86 double epsilon = 3.3e-5;
88 if ((std::abs(
_T - IF97::Tcrit) < epsilon / 10.0) &&
89 (std::abs(
_p - IF97::Pcrit) < epsilon)) {
91 }
else if (
_T > IF97::Tcrit) {
92 if (
_p > IF97::Pcrit) {
98 if (
_p > IF97::Pcrit) {
101 double psat = IF97::psat97(
_T);
102 if (
_p > psat * (1.0 + epsilon)) {
104 }
else if (
_p < psat * (1.0 - epsilon)) {
113 IF97Region = IF97::BackwardRegion(
_p,
_smass, IF97_SMASS);
115 IF97Region = IF97::BackwardRegion(
_p,
_hmass, IF97_HMASS);
117 switch (IF97Region) {
119 if (
_p <= IF97::Pcrit) {
126 if (
_T <= IF97::Tcrit) {
133 if (
_T < IF97::Tsat97(
_p)) {
134 if (
_p <= IF97::Pcrit) {
140 if (
_T <= IF97::Tcrit) {
169 double H, S, hLmass, hVmass, sLmass, sVmass;
173 switch (input_pair) {
194 throw ValueError(
format(
"Saturation pressure [%g Pa] corresponding to T [%g K] is within 3.3e-3 %% of given p [%Lg Pa]",
195 IF97::psat97(
_T),
_T,
_p));
203 _T = IF97::Tsat97(
_p);
210 _p = IF97::psat97(
_T);
225 if (IF97::BackwardRegion(
_p,
_hmass, IF97_HMASS) == 4) {
227 hVmass = IF97::hvap_p(
_p);
228 hLmass = IF97::hliq_p(
_p);
229 _Q = std::min(1.0, std::max(0.0, (
H - hLmass) / (hVmass - hLmass)));
247 if (IF97::BackwardRegion(
_p,
_smass, IF97_SMASS) == 4) {
249 sVmass = IF97::svap_p(
_p);
250 sLmass = IF97::sliq_p(
_p);
251 _Q = std::min(1.0, std::max(0.0, (S - sLmass) / (sVmass - sLmass)));
268 if (IF97::BackwardRegion(
_p,
_hmass, IF97_HMASS) == 4) {
270 hVmass = IF97::hvap_p(
_p);
271 hLmass = IF97::hliq_p(
_p);
272 _Q = std::min(1.0, std::max(0.0, (
H - hLmass) / (hVmass - hLmass)));
280 throw ValueError(
"This pair of inputs is not yet supported");
295 return IF97::rholiq_p(
_p);
298 return IF97::hliq_p(
_p);
301 return IF97::sliq_p(
_p);
304 return IF97::cpliq_p(
_p);
307 return IF97::cvliq_p(
_p);
310 return IF97::uliq_p(
_p);
313 return IF97::speed_soundliq_p(
_p);
316 return IF97::viscliq_p(
_p);
319 return IF97::tcondliq_p(
_p);
322 return IF97::sigma97(
_T);
325 return IF97::prandtlliq_p(
_p);
334 return IF97::rhovap_p(
_p);
337 return IF97::hvap_p(
_p);
340 return IF97::svap_p(
_p);
343 return IF97::cpvap_p(
_p);
346 return IF97::cvvap_p(
_p);
349 return IF97::uvap_p(
_p);
352 return IF97::speed_soundvap_p(
_p);
355 return IF97::viscvap_p(
_p);
358 return IF97::tcondvap_p(
_p);
361 return IF97::sigma97(
_T);
364 return IF97::prandtlvap_p(
_p);
373 if (std::abs(
_Q) < 1e-10) {
375 }
else if (std::abs(
_Q - 1) < 1e-10) {
399 return IF97::sigma97(
_T);
412 return IF97::rhomass_Tp(
_T,
_p);
415 return IF97::hmass_Tp(
_T,
_p);
418 return IF97::smass_Tp(
_T,
_p);
421 return IF97::cpmass_Tp(
_T,
_p);
424 return IF97::cvmass_Tp(
_T,
_p);
427 return IF97::umass_Tp(
_T,
_p);
430 return IF97::speed_sound_Tp(
_T,
_p);
433 return IF97::visc_Tp(
_T,
_p);
436 return IF97::tcond_Tp(
_T,
_p);
442 return IF97::prandtl_Tp(
_T,
_p);
470 return IF97::hmass_psmass(
_p,
_smass);
488 return IF97::smass_phmass(
_p,
_hmass);
577 return IF97::get_Ttrip();
581 return IF97::get_ptrip();
585 return IF97::get_Tcrit();
589 return IF97::get_pcrit();
598 return IF97::get_MW();
602 return IF97::get_Acentric();
608 return IF97::get_Pmax();
613 return IF97::get_Tmax();
617 return IF97::get_Tmin();
632 return IF97::get_rhocrit();
678 const CoolProp::parameters* outputs, std::size_t N_outputs,
double* out_buffer, std::size_t out_buffer_size,
int* status_flags,
680 if (N_outputs != 0 && N_inputs > std::numeric_limits<std::size_t>::max() / N_outputs) {
681 throw ValueError(
format(
"fast_evaluate: N_inputs * N_outputs would overflow size_t (N_inputs=%zu, N_outputs=%zu)", N_inputs, N_outputs));
683 const std::size_t required_out = N_inputs * N_outputs;
684 if (out_buffer_size < required_out) {
685 throw ValueError(
format(
"fast_evaluate: out_buffer_size=%zu < required %zu (N_inputs * N_outputs)", out_buffer_size, required_out));
687 if (status_flags_size < N_inputs) {
688 throw ValueError(
format(
"fast_evaluate: status_flags_size=%zu < required %zu (N_inputs)", status_flags_size, N_inputs));
690 if (N_inputs == 0)
return;
693 if (val1 ==
nullptr || val2 ==
nullptr || outputs ==
nullptr || out_buffer ==
nullptr || status_flags ==
nullptr) {
694 throw ValueError(
"fast_evaluate: null pointer argument");
696 if (N_outputs == 0) {
697 for (std::size_t k = 0; k < N_inputs; ++k)
702 const bool is_PT = (input_pair ==
PT_INPUTS);
705 if (!is_PT && !is_HmassP && !is_HmolarP) {
706 throw ValueError(
format(
"fast_evaluate (IF97): input_pair %s not supported (use PT_INPUTS, HmassP_INPUTS, HmolarP_INPUTS)",
711 constexpr std::size_t MAX_FE_OUTPUTS = 64;
712 if (N_outputs > MAX_FE_OUTPUTS) {
713 throw ValueError(
format(
"fast_evaluate: N_outputs=%zu exceeds compile-time limit %zu", N_outputs, MAX_FE_OUTPUTS));
715 for (std::size_t o = 0; o < N_outputs; ++o) {
716 switch (outputs[o]) {
744 const double NaN = std::numeric_limits<double>::quiet_NaN();
750 auto fill_nan_row = [&](std::size_t k) {
751 for (std::size_t o = 0; o < N_outputs; ++o) {
752 out_buffer[k * N_outputs + o] =
NaN;
756 for (std::size_t k = 0; k < N_inputs; ++k) {
757 const double v1 = val1[k];
758 const double v2 = val2[k];
761 const double hmass_k = is_HmassP ? v1 : (is_HmolarP ? (v1 / M) : 0.0);
762 bool dome_hit =
false;
763 double T_sat_k = 0.0, Q_k = 0.0, hL_k = 0.0, hV_k = 0.0;
772 bool inverse_ok =
false;
774 T_k = IF97::T_phmass(p_k, hmass_k);
776 }
catch (
const std::exception&) {
784 if (p_k > 0 && p_k <= IF97::Pcrit) {
786 const double hL_probe = IF97::hliq_p(p_k);
787 const double hV_probe = IF97::hvap_p(p_k);
788 if (hmass_k >= hL_probe && hmass_k <= hV_probe) {
789 T_sat_k = IF97::Tsat97(p_k);
792 Q_k = (hmass_k - hL_k) / (hV_k - hL_k);
797 }
catch (
const std::exception&) {
812 if (!(p_k > 0 && T_k > 0 && p_k <= IF97::get_Pmax() && T_k >= IF97::get_Tmin() && T_k <= IF97::get_Tmax())) {
822 if (!skip_twophase_check && is_PT && T_k <= IF97::Tcrit) {
823 const double psat = IF97::psat97(T_k);
824 const double eps = 3.3e-5;
825 if (std::abs(p_k - psat) <= psat * eps) {
832 bool eval_failed =
false;
836 double rhoL_k = 0.0, rhoV_k = 0.0;
837 double sL_k = 0.0, sV_k = 0.0;
838 double uL_k = 0.0, uV_k = 0.0;
839 bool have_rho =
false, have_s =
false, have_u =
false;
840 auto ensure_rho_sat = [&] {
841 if (have_rho)
return;
842 rhoL_k = IF97::rholiq_p(p_k);
843 rhoV_k = IF97::rhovap_p(p_k);
846 auto ensure_s_sat = [&] {
848 sL_k = IF97::sliq_p(p_k);
849 sV_k = IF97::svap_p(p_k);
852 auto ensure_u_sat = [&] {
854 uL_k = IF97::uliq_p(p_k);
855 uV_k = IF97::uvap_p(p_k);
858 for (std::size_t o = 0; o < N_outputs; ++o) {
884 const double vL = 1.0 / rhoL_k;
885 const double vV = 1.0 / rhoV_k;
886 const double rho_mass = 1.0 / ((1.0 - Q_k) * vL + Q_k * vV);
887 val = (out_key ==
iDmass) ? rho_mass : rho_mass / M;
893 const double s_mass = (1.0 - Q_k) * sL_k + Q_k * sV_k;
894 val = (out_key ==
iSmass) ? s_mass : s_mass * M;
900 const double u_mass = (1.0 - Q_k) * uL_k + Q_k * uV_k;
901 val = (out_key ==
iUmass) ? u_mass : u_mass * M;
931 val = IF97::rhomass_Tp(T_k, p_k);
934 val = IF97::rhomass_Tp(T_k, p_k) / M;
937 val = IF97::hmass_Tp(T_k, p_k);
940 val = IF97::hmass_Tp(T_k, p_k) * M;
943 val = IF97::smass_Tp(T_k, p_k);
946 val = IF97::smass_Tp(T_k, p_k) * M;
949 val = IF97::umass_Tp(T_k, p_k);
952 val = IF97::umass_Tp(T_k, p_k) * M;
955 val = IF97::cpmass_Tp(T_k, p_k);
958 val = IF97::cpmass_Tp(T_k, p_k) * M;
961 val = IF97::cvmass_Tp(T_k, p_k);
964 val = IF97::cvmass_Tp(T_k, p_k) * M;
967 val = IF97::speed_sound_Tp(T_k, p_k);
970 val = IF97::visc_Tp(T_k, p_k);
973 val = IF97::tcond_Tp(T_k, p_k);
976 val = IF97::prandtl_Tp(T_k, p_k);
991 out_buffer[k * N_outputs + o] = val;
992 }
catch (
const std::exception&) {
994 out_buffer[k * N_outputs + o] =
NaN;