2 # ifndef _CRTDBG_MAP_ALLOC
3 # define _CRTDBG_MAP_ALLOC
5 # ifndef _CRT_SECURE_NO_WARNINGS
6 # define _CRT_SECURE_NO_WARNINGS
14 #if defined(__ISWINDOWS__)
25 # define DBL_EPSILON std::numeric_limits<double>::epsilon()
51 #if defined(ENABLE_CATCH)
52 # include <catch2/catch_all.hpp>
57 static int debug_level = 0;
58 static std::string error_string;
59 static std::string warning_string;
73 warning_string = warning;
81 i = fluid_string.find(
"::");
82 return i != std::string::npos;
85 void extract_backend(std::string fluid_string, std::string& backend, std::string& fluid) {
89 if (fluid_string.find(
"REFPROP-MIX:") == 0) {
90 fluid_string.replace(0, 12,
"REFPROP::");
92 if (fluid_string.find(
"REFPROP-") == 0) {
93 fluid_string.replace(0, 8,
"REFPROP::");
97 backend = fluid_string.substr(0, i);
99 fluid = fluid_string.substr(i + 2);
102 fluid = fluid_string;
105 std::cout <<
format(
"%s:%d: backend extracted. backend: %s. fluid: %s\n", __FILE__, __LINE__, backend.c_str(), fluid.c_str());
110 return (fluid_string.find(
"[") != std::string::npos && fluid_string.find(
"]") != std::string::npos);
114 return (fluid_string.find(
'-') != std::string::npos && fluid_string.find(
'%') != std::string::npos);
126 std::string
extract_fractions(
const std::string& fluid_string, std::vector<double>& fractions) {
130 std::vector<std::string> names;
133 std::vector<std::string> pairs =
strsplit(fluid_string,
'&');
135 for (std::size_t i = 0; i < pairs.size(); ++i) {
136 const std::string& fluid = pairs[i];
139 if (fluid[fluid.size() - 1] !=
']')
throw ValueError(
format(
"Fluid entry [%s] must end with ']' character", pairs[i].c_str()));
142 std::vector<std::string> name_fraction =
strsplit(fluid.substr(0, fluid.size() - 1),
'[');
144 if (name_fraction.size() != 2) {
145 throw ValueError(
format(
"Could not break [%s] into name/fraction", fluid.substr(0, fluid.size() - 1).c_str()));
149 const std::string &name = name_fraction[0], &fraction = name_fraction[1];
155 std::stringstream ssfraction(fraction);
157 ssfraction.imbue(std::locale(ssfraction.getloc(),
new delim(c)));
160 if (ssfraction.rdbuf()->in_avail() != 0) {
161 throw ValueError(
format(
"fraction [%s] was not converted fully", fraction.c_str()));
164 if (f > 1 || f < 0) {
165 throw ValueError(
format(
"fraction [%s] was not converted to a value between 0 and 1 inclusive", fraction.c_str()));
172 fractions.push_back(f);
175 names.push_back(name);
180 std::cout <<
format(
"%s:%d: Detected fractions of %s for %s.", __FILE__, __LINE__,
vec_to_string(fractions).c_str(),
181 (
strjoin(names,
"&")).c_str());
188 std::vector<std::string> fluid_parts =
strsplit(fluid_string,
'-');
190 if (fluid_parts.size() != 2) {
192 format(
"Format of incompressible solution string [%s] is invalid, should be like \"EG-20%\" or \"EG-0.2\" ", fluid_string.c_str()));
197 x = strtod(fluid_parts[1].c_str(), &pEnd);
203 fractions.push_back(x);
205 std::cout <<
format(
"%s:%d: Detected incompressible concentration of %s for %s.", __FILE__, __LINE__,
vec_to_string(fractions).c_str(),
206 fluid_parts[0].c_str());
207 return fluid_parts[0];
213 void _PropsSI_initialize(
const std::string& backend,
const std::vector<std::string>& fluid_names,
const std::vector<double>& z,
214 shared_ptr<AbstractState>& State) {
216 if (fluid_names.empty()) {
217 throw ValueError(
"fluid_names cannot be empty");
220 std::vector<double> fractions(1, 1.0);
221 const std::vector<double>* fractions_ptr = NULL;
223 if (fluid_names.size() > 1) {
228 }
else if (fluid_names.size() == 1) {
233 fractions_ptr = &fractions;
239 fractions_ptr = &fractions;
250 if (!State->available_in_high_level()) {
252 "This AbstractState derived class cannot be used in the high-level interface; see www.coolprop.org/dev/coolprop/LowLevelAPI.html");
256 if (State->using_mole_fractions()) {
258 if (State->get_mole_fractions().empty()) {
259 State->set_mole_fractions(*fractions_ptr);
261 }
else if (State->using_mass_fractions()) {
262 State->set_mass_fractions(*fractions_ptr);
263 }
else if (State->using_volu_fractions()) {
264 State->set_volu_fractions(*fractions_ptr);
267 std::cout <<
format(
"%s:%d: _PropsSI, could not set composition to %s, defaulting to mole fraction.\n", __FILE__, __LINE__,
289 std::vector<output_parameter> outputs;
290 for (std::vector<std::string>::const_iterator str = Outputs.begin(); str != Outputs.end(); ++str) {
309 outputs.push_back(out);
316 const std::vector<double>& in1,
const std::vector<double>& in2, std::vector<std::vector<double>>& IO) {
319 if (in1.size() != in2.size()) {
320 throw ValueError(
format(
"lengths of in1 [%d] and in2 [%d] are not the same", in1.size(), in2.size()));
322 bool one_input_one_output = (in1.size() == 1 && in2.size() == 1 && output_parameters.size() == 1);
324 bool all_trivial_outputs =
true;
325 for (std::size_t j = 0; j < output_parameters.size(); ++j) {
327 all_trivial_outputs =
false;
332 bool all_outputs_in_inputs =
true;
337 for (std::size_t j = 0; j < output_parameters.size(); ++j) {
339 all_outputs_in_inputs =
false;
342 if (!(output_parameters[j].Of1 == p1 || output_parameters[j].Of1 == p2)) {
343 all_outputs_in_inputs =
false;
348 if (!all_trivial_outputs) {
349 throw ValueError(
format(
"Input pair variable is invalid and output(s) are non-trivial; cannot do state update"));
351 all_outputs_in_inputs =
false;
355 std::cout <<
format(
"%s (%d): input pair = %d ", __FILE__, __LINE__, input_pair) << std::endl;
356 std::cout <<
format(
"%s (%d): in1 = %s ", __FILE__, __LINE__,
vec_to_string(in1).c_str()) << std::endl;
357 std::cout <<
format(
"%s (%d): in2 = %s ", __FILE__, __LINE__,
vec_to_string(in2).c_str()) << std::endl;
365 std::size_t N1 = std::max(
static_cast<std::size_t
>(1), in1.size());
366 std::size_t N2 = std::max(
static_cast<std::size_t
>(1), output_parameters.size());
367 IO.resize(N1, std::vector<double>(N2, _HUGE));
370 bool success =
false;
371 bool success_inner =
false;
374 std::cout <<
format(
"%s (%d): Iterating over %d input value pairs.", __FILE__, __LINE__, IO.size()) << std::endl;
378 for (std::size_t i = 0; i < IO.size(); ++i) {
380 success_inner =
false;
382 if (input_pair !=
INPUT_PAIR_INVALID && !all_trivial_outputs && !all_outputs_in_inputs) {
384 if (!use_guesses || i == 0) {
385 State->update(input_pair, in1[i], in2[i]);
387 State->update_with_guesses(input_pair, in1[i], in2[i], guesses);
392 if (one_input_one_output) {
397 for (std::size_t j = 0; j < IO[i].size(); ++j) {
403 for (std::size_t j = 0; j < IO[i].size(); ++j) {
405 if (all_outputs_in_inputs) {
406 if (p1 == output_parameters[j].Of1) {
408 success_inner =
true;
410 }
else if (p2 == output_parameters[j].Of1) {
412 success_inner =
true;
420 switch (output.
type) {
423 IO[i][j] = State->keyed_output(output.
Of1);
425 switch (output.
Of1) {
430 guesses.
T = IO[i][j];
433 guesses.
p = IO[i][j];
436 guesses.
hmolar = IO[i][j];
439 guesses.
smolar = IO[i][j];
442 throw ValueError(
"Don't understand this parameter");
447 IO[i][j] = State->first_partial_deriv(output.
Of1, output.
Wrt1, output.
Constant1);
450 IO[i][j] = State->first_saturation_deriv(output.
Of1, output.
Wrt1);
460 success_inner =
true;
462 if (one_input_one_output) {
470 if (use_guesses && success_inner) {
473 guesses.
rhomolar = State->rhomolar();
480 guesses.
T = State->T();
487 success |= success_inner;
489 if (success ==
false) {
495 bool StripPhase(std::string& Name, shared_ptr<AbstractState>& State)
498 std::vector<std::string> strVec =
strsplit(Name,
'|');
499 if (strVec.size() > 1) {
501 std::string strBackend = State->backend_name();
503 throw ValueError(
"Cannot set phase on Incompressible Fluid; always liquid phase");
505 throw ValueError(
"Can't set phase on IF97 Backend");
507 throw ValueError(
"Can't set phase on TTSE Backend in PropsSI");
509 throw ValueError(
"Can't set phase on BICUBIC Backend in PropsSI");
511 throw ValueError(
"Can't set phase on VTPR Backend in PropsSI");
514 if (strVec.size() > 2)
519 std::basic_string<char>::iterator str_Iter;
520 std::string strPhase = strVec[1];
521 if (strPhase.find(
"iphase_") != strPhase.npos) {
522 str_Iter = strPhase.erase(strPhase.begin());
524 if (strPhase.find(
"phase_") == strPhase.npos) {
525 strPhase.insert(0,
"phase_");
529 throw ValueError(
format(
"Phase string \"%s\" is not a valid phase", strVec[1]));
533 State->specify_phase(imposed);
539 void _PropsSImulti(
const std::vector<std::string>& Outputs,
const std::string& Name1,
const std::vector<double>& Prop1,
const std::string& Name2,
540 const std::vector<double>& Prop2,
const std::string& backend,
const std::vector<std::string>& fluids,
541 const std::vector<double>& fractions, std::vector<std::vector<double>>& IO) {
542 shared_ptr<AbstractState> State;
545 std::vector<output_parameter> output_parameters;
546 std::vector<double> v1, v2;
551 }
catch (std::exception& e) {
553 throw ValueError(
format(
"Initialize failed for backend: \"%s\", fluid: \"%s\" fractions \"%s\"; error: %s", backend.c_str(),
558 std::string N1 = Name1;
559 std::string N2 = Name2;
562 if (HasPhase1 && HasPhase2)
563 throw ValueError(
"Phase can only be specified on one of the input key strings");
568 }
catch (std::exception& e) {
570 throw ValueError(
format(
"Input pair parsing failed for Name1: \"%s\", Name2: \"%s\"; err: %s", Name1.c_str(), Name2.c_str(), e.what()));
575 }
catch (std::exception& e) {
577 throw ValueError(
format(
"Output parameter parsing failed; error: %s", e.what()));
584 std::vector<std::vector<double>>
PropsSImulti(
const std::vector<std::string>& Outputs,
const std::string& Name1,
const std::vector<double>& Prop1,
585 const std::string& Name2,
const std::vector<double>& Prop2,
const std::string& backend,
586 const std::vector<std::string>& fluids,
const std::vector<double>& fractions) {
587 std::vector<std::vector<double>> IO;
589 #if !defined(NO_ERROR_CATCHING)
594 _PropsSImulti(Outputs, Name1, Prop1, Name2, Prop2, backend, fluids, fractions, IO);
599 #if !defined(NO_ERROR_CATCHING)
600 }
catch (
const std::exception& e) {
602 # if defined(PROPSSI_ERROR_STDOUT)
603 std::cout << e.what() << std::endl;
606 std::cout << e.what() << std::endl;
611 return std::vector<std::vector<double>>();
613 double PropsSI(
const std::string& Output,
const std::string& Name1,
double Prop1,
const std::string& Name2,
double Prop2,
const std::string& Ref) {
614 #if !defined(NO_ERROR_CATCHING)
621 std::string backend, fluid;
623 std::vector<double> fractions(1, 1.0);
626 std::vector<std::vector<double>> IO;
627 _PropsSImulti(
strsplit(Output,
'&'), Name1, std::vector<double>(1, Prop1), Name2, std::vector<double>(1, Prop2), backend,
628 strsplit(fluid_string,
'&'), fractions, IO);
632 if (IO.size() != 1 || IO[0].size() != 1) {
636 double val = IO[0][0];
639 std::cout <<
format(
"_PropsSI will return %g", val) << std::endl;
643 #if !defined(NO_ERROR_CATCHING)
644 }
catch (
const std::exception& e) {
647 +
format(
" : PropsSI(\"%s\",\"%s\",%0.10g,\"%s\",%0.10g,\"%s\")", Output.c_str(), Name1.c_str(), Prop1, Name2.c_str(), Prop2, Ref.c_str()));
648 # if defined(PROPSSI_ERROR_STDOUT)
649 std::cout << e.what() << std::endl;
652 std::cout << e.what() << std::endl;
662 if (backend ==
"SRK" || backend ==
"PR") {
665 }
else if (backend ==
"HEOS") {
668 }
else if (backend ==
"PCSAFT") {
672 throw ValueError(
format(
"You have provided an invalid backend [%s] to add_fluids_as_JSON; valid options are SRK, PR, HEOS", backend.c_str()));
676 #if defined(ENABLE_CATCH)
677 TEST_CASE(
"Check inputs to PropsSI",
"[PropsSI]") {
678 SECTION(
"Single state, single output") {
681 SECTION(
"Single state, single output, saturation derivative") {
684 SECTION(
"Single state, single output, pure incompressible") {
687 SECTION(
"Single state, trivial output, pure incompressible") {
690 SECTION(
"Bad input pair") {
693 SECTION(
"Single state, single output, 40% incompressible") {
696 SECTION(
"Single state, single output, predefined CoolProp mixture") {
699 SECTION(
"Single state, single output") {
702 SECTION(
"Single state, single output, predefined mixture") {
705 SECTION(
"Single state, single output, predefined mixture from REFPROP") {
708 SECTION(
"Single state, single output, bad predefined mixture from REFPROP") {
711 SECTION(
"Predefined mixture") {
712 std::vector<double> p(1, 101325), Q(1, 1.0), z;
713 std::vector<std::string> outputs(1,
"T");
714 outputs.push_back(
"Dmolar");
715 std::vector<std::vector<double>> IO;
716 std::vector<std::string> fluids(1,
"R410A.mix");
719 SECTION(
"Single state, two outputs") {
720 std::vector<double> p(1, 101325), Q(1, 1.0), z(1, 1.0);
721 std::vector<std::string> outputs(1,
"T");
722 outputs.push_back(
"Dmolar");
723 std::vector<std::string> fluids(1,
"Water");
726 SECTION(
"Single state, two bad outputs") {
727 std::vector<double> p(1, 101325), Q(1, 1.0), z(1, 1.0);
728 std::vector<std::vector<double>> IO;
729 std::vector<std::string> outputs(1,
"???????");
730 outputs.push_back(
"?????????");
731 std::vector<std::string> fluids(1,
"Water");
733 CHECK(IO.size() == 0);
735 SECTION(
"Two states, one output") {
736 std::vector<double> p(2, 101325), Q(2, 1.0), z(1, 1.0);
737 std::vector<std::string> outputs(1,
"T");
738 std::vector<std::string> fluids(1,
"Water");
741 SECTION(
"Two states, two outputs") {
742 std::vector<double> p(2, 101325), Q(2, 1.0), z(1, 1.0);
743 std::vector<std::string> outputs(1,
"T");
744 outputs.push_back(
"Dmolar");
745 std::vector<std::string> fluids(1,
"Water");
748 SECTION(
"cp and its derivative representation") {
749 std::vector<double> p(1, 101325), Q(1, 1.0), z(1, 1.0);
750 std::vector<std::vector<double>> IO;
751 std::vector<std::string> outputs(1,
"Cpmolar");
752 outputs.push_back(
"d(Hmolar)/d(T)|P");
753 std::vector<std::string> fluids(1,
"Water");
757 REQUIRE(!IO.empty());
760 CHECK(std::abs(IO[0][0] - IO[0][1]) < 1e-5);
762 SECTION(
"bad fluid") {
763 std::vector<double> p(1, 101325), Q(1, 1.0), z(1, 1.0);
764 std::vector<std::vector<double>> IO;
765 std::vector<std::string> outputs(1,
"Cpmolar");
766 outputs.push_back(
"d(Hmolar)/d(T)|P");
767 std::vector<std::string> fluids(1,
"????????");
773 SECTION(
"bad mole fraction length") {
774 std::vector<double> p(1, 101325), Q(1, 1.0), z(1, 1.0);
775 std::vector<std::vector<double>> IO;
776 std::vector<std::string> outputs(1,
"T");
777 std::vector<std::string> fluids(1,
"Water&Ethanol");
783 SECTION(
"bad input lengths") {
784 std::vector<double> p(1, 101325), Q(2, 1.0), z(100, 1.0);
785 std::vector<std::vector<double>> IO;
786 std::vector<std::string> outputs(1,
"Cpmolar");
787 outputs.push_back(
"d(Hmolar)/d(T)|P");
788 std::vector<std::string> fluids(1,
"Water");
794 SECTION(
"bad input pair") {
795 std::vector<double> Q(2, 1.0), z(1, 1.0);
796 std::vector<std::vector<double>> IO;
797 std::vector<std::string> outputs(1,
"Cpmolar");
798 outputs.push_back(
"d(Hmolar)/d(T)|P");
799 std::vector<std::string> fluids(1,
"Water");
812 double Props1SI(std::string FluidName, std::string Output) {
815 if (valid_fluid1 && valid_fluid2) {
816 set_error_string(
format(
"Both inputs to Props1SI [%s,%s] are valid fluids", Output.c_str(), FluidName.c_str()));
819 if (!valid_fluid1 && !valid_fluid2) {
820 set_error_string(
format(
"Neither input to Props1SI [%s,%s] is a valid fluid", Output.c_str(), FluidName.c_str()));
823 if (!valid_fluid1 && valid_fluid2) {
825 std::swap(Output, FluidName);
829 double val1 =
PropsSI(Output,
"", 0,
"", 0, FluidName);
831 set_error_string(
format(
"Unable to use input parameter [%s] in Props1SI for fluid %s; error was %s", Output.c_str(), FluidName.c_str(),
839 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) {
840 std::vector<double> zero_vector(1, 0.);
841 std::vector<std::vector<double>> val1 =
PropsSImulti(Outputs,
"", zero_vector,
"", zero_vector, backend, fluids, fractions);
847 #if defined(ENABLE_CATCH)
848 TEST_CASE(
"Check inputs to Props1SI",
"[Props1SI],[PropsSI]") {
849 SECTION(
"Good fluid, good parameter") {
852 SECTION(
"Good fluid, good parameter") {
855 SECTION(
"Good fluid, good parameter, inverted") {
858 SECTION(
"Good fluid, bad parameter") {
861 SECTION(
"Bad fluid, good parameter") {
869 std::string backend, fluid;
870 std::vector<double> fractions;
881 double saturation_ancillary(
const std::string& fluid_name,
const std::string& output,
int Q,
const std::string& input,
double value) {
884 std::vector<std::string> names(1, fluid_name);
893 std::string backend, fluid;
895 if (backend ==
"REFPROP") {
897 int ierr = 0, ixflag = 1;
898 double h0 = 0, s0 = 0, t0 = 0, p0 = 0;
899 char herr[255], hrf[4];
901 const char* refstate = reference_state.c_str();
902 if (strlen(refstate) > 3) {
903 if (reference_state ==
"ASHRAE") {
906 throw ValueError(
format(
"Reference state string [%s] is more than 3 characters long", reference_state.c_str()));
911 REFPROP_SETREF(hrf, ixflag, x0, h0, s0, t0, p0, ierr, herr, 3, 255);
912 }
else if (backend ==
"HEOS" || backend ==
"?") {
914 if (!reference_state.compare(
"IIR")) {
916 throw ValueError(
format(
"Cannot use IIR reference state; Ttriple [%Lg] is greater than 273.15 K", HEOS.
Ttriple()));
921 double deltah = HEOS.
hmass() - 200000;
922 double deltas = HEOS.
smass() - 1000;
928 std::cout <<
format(
"set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2);
930 }
else if (!reference_state.compare(
"ASHRAE")) {
932 throw ValueError(
format(
"Cannot use ASHRAE reference state; Ttriple [%Lg] is greater than than 233.15 K", HEOS.
Ttriple()));
937 double deltah = HEOS.
hmass() - 0;
938 double deltas = HEOS.
smass() - 0;
944 std::cout <<
format(
"set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2);
946 }
else if (!reference_state.compare(
"NBP")) {
948 throw ValueError(
format(
"Cannot use NBP reference state; p_triple [%Lg Pa] is greater than than 101325 Pa", HEOS.
p_triple()));
953 double deltah = HEOS.
hmass() - 0;
954 double deltas = HEOS.
smass() - 0;
960 std::cout <<
format(
"set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2);
962 }
else if (!reference_state.compare(
"DEF")) {
964 }
else if (!reference_state.compare(
"RESET")) {
967 throw ValueError(
format(
"Reference state string is invalid: [%s]", reference_state.c_str()));
972 std::vector<std::string> _comps(1, Ref);
978 double deltah = HEOS.
hmolar() - hmolar0;
979 double deltas = HEOS.
smolar() - smolar0;
986 if (!ParamName.compare(
"version")) {
988 }
else if (!ParamName.compare(
"gitrevision")) {
990 }
else if (!ParamName.compare(
"errstring")) {
991 std::string temp = error_string;
994 }
else if (!ParamName.compare(
"warnstring")) {
995 std::string temp = warning_string;
998 }
else if (!ParamName.compare(
"FluidsList") || !ParamName.compare(
"fluids_list") || !ParamName.compare(
"fluidslist")) {
1000 }
else if (!ParamName.compare(
"incompressible_list_pure")) {
1002 }
else if (!ParamName.compare(
"incompressible_list_solution")) {
1004 }
else if (!ParamName.compare(
"mixture_binary_pairs_list")) {
1006 }
else if (!ParamName.compare(
"parameter_list")) {
1008 }
else if (!ParamName.compare(
"predefined_mixtures")) {
1010 }
else if (!ParamName.compare(
"HOME")) {
1012 }
else if (ParamName ==
"REFPROP_version") {
1014 }
else if (ParamName ==
"cubic_fluids_schema") {
1016 }
else if (ParamName ==
"cubic_fluids_list") {
1018 }
else if (ParamName ==
"pcsaft_fluids_schema") {
1021 throw ValueError(
format(
"Input parameter [%s] is invalid", ParamName.c_str()));
1024 #if defined(ENABLE_CATCH)
1025 TEST_CASE(
"Check inputs to get_global_param_string",
"[get_global_param_string]") {
1026 const int num_good_inputs = 8;
1027 std::string good_inputs[num_good_inputs] = {
1028 "version",
"gitrevision",
"fluids_list",
"incompressible_list_pure",
"incompressible_list_solution",
"mixture_binary_pairs_list",
1029 "parameter_list",
"predefined_mixtures"};
1030 std::ostringstream ss3c;
1031 for (
int i = 0; i < num_good_inputs; ++i) {
1032 ss3c <<
"Test for" << good_inputs[i];
1033 SECTION(ss3c.str(),
"") {
1041 std::string backend, fluid;
1044 return AS->fluid_param_string(ParamName);
1046 #if defined(ENABLE_CATCH)
1047 TEST_CASE(
"Check inputs to get_fluid_param_string",
"[get_fluid_param_string]") {
1048 const int num_good_inputs = 10;
1049 std::string good_inputs[num_good_inputs] = {
"aliases",
1053 "BibTeX-CONDUCTIVITY",
1056 "BibTeX-SURFACE_TENSION",
1057 "BibTeX-MELTING_LINE",
1058 "BibTeX-VISCOSITY"};
1059 std::ostringstream ss3c;
1060 for (
int i = 0; i < num_good_inputs; ++i) {
1061 ss3c <<
"Test for" << good_inputs[i];
1062 SECTION(ss3c.str(),
"") {
1079 return "supercritical";
1081 return "supercritical_gas";
1083 return "supercritical_liquid";
1085 return "critical_point";
1093 return "not_imposed";
1095 throw ValueError(
"I should never be thrown");
1097 std::string
PhaseSI(
const std::string& Name1,
double Prop1,
const std::string& Name2,
double Prop2,
const std::string& FluidName) {
1098 double Phase_double =
PropsSI(
"Phase", Name1, Prop1, Name2, Prop2, FluidName);
1102 if (strError !=
"") {
1103 strPhase.append(
": " + strError);
1107 std::size_t Phase_int =
static_cast<std::size_t
>(Phase_double);