3 # define _CRTDBG_MAP_ALLOC
4 # ifndef _CRT_SECURE_NO_WARNINGS
5 # define _CRT_SECURE_NO_WARNINGS
10 # include <sys/stat.h>
26 throw NotImplementedError(
"Empty constructor is not implemented for incompressible fluids");
56 throw NotImplementedError(
"Mixture-style constructor is not implemented yet for incompressible fluids");
66 std::cout <<
format(
"Incompressible backend: Called update with %d and %f, %f ", input_pair, value1, value2) << std::endl;
75 throw ValueError(
format(
"%s is an incompressible fluid, mass fractions must be set to a vector with ONE entry, not %d.", this->
name().c_str(),
82 throw ValueError(
format(
"%s is a pure fluid. The composition has to be set to a vector with one entry equal to 1.0. %s is not valid.",
90 format(
"%s is a solution or brine. Mass fractions must be set to a vector with one entry between 0 and 1. %s is not valid.",
126 throw ValueError(
"Incompressible fluids can only handle saturated liquid, Q=0.");
195 std::cout <<
format(
"Incompressible backend: Called set_fractions with %s ",
vec_to_string(fractions).c_str()) << std::endl;
196 if (fractions.size() != 1)
197 throw ValueError(
format(
"The incompressible backend only supports one entry in the fraction vector and not %d.", fractions.size()));
198 if ((this->
_fractions.size() != 1) || (this->_fractions[0] != fractions[0])) {
200 std::cout <<
format(
"Incompressible backend: Updating the fractions triggered a change in reference state %s -> %s",
214 std::cout <<
format(
"Incompressible backend: Called set_mole_fractions with %s ",
vec_to_string(mole_fractions).c_str()) << std::endl;
215 if (mole_fractions.size() != 1)
216 throw ValueError(
format(
"The incompressible backend only supports one entry in the mole fraction vector and not %d.", mole_fractions.size()));
220 std::cout <<
format(
"Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",
vec_to_string(mole_fractions).c_str(),
226 std::vector<CoolPropDbl> tmp_fractions;
227 for (std::size_t i = 0; i < mole_fractions.size(); i++) {
240 std::cout <<
format(
"Incompressible backend: Called set_mass_fractions with %s ",
vec_to_string(mass_fractions).c_str()) << std::endl;
241 if (mass_fractions.size() != 1)
242 throw ValueError(
format(
"The incompressible backend only supports one entry in the mass fraction vector and not %d.", mass_fractions.size()));
246 std::cout <<
format(
"Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",
vec_to_string(mass_fractions).c_str(),
252 std::vector<CoolPropDbl> tmp_fractions;
253 for (std::size_t i = 0; i < mass_fractions.size(); i++) {
266 std::cout <<
format(
"Incompressible backend: Called set_volu_fractions with %s ",
vec_to_string(volu_fractions).c_str()) << std::endl;
267 if (volu_fractions.size() != 1)
269 format(
"The incompressible backend only supports one entry in the volume fraction vector and not %d.", volu_fractions.size()));
273 std::cout <<
format(
"Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",
vec_to_string(volu_fractions).c_str(),
279 std::vector<CoolPropDbl> tmp_fractions;
280 for (std::size_t i = 0; i < volu_fractions.size(); i++) {
414 :
p(
p), x(x), h_in(h_in), backend(backend) {}
415 double call(
double target) {
446 :
p(
p), x(x), s_in(s_in), backend(backend) {}
447 double call(
double target) {
502 if (param ==
iT && given ==
iP) {
505 throw ValueError(
"For incompressibles, the only valid inputs to calc_melting_line are T(p)");
531 if ((Of ==
iDmass) && (Wrt ==
iP))
return 0.0;
552 throw ValueError(
"Incompressible fluids only support a limited subset of partial derivatives.");
578 # include <catch2/catch_all.hpp>
582 TEST_CASE(
"Internal consistency checks and example use cases for the incompressible backend",
"[IncompressibleBackend]") {
586 SECTION(
"Test case for Methanol from SecCool") {
594 std::vector<CoolPropDbl> fractions;
595 fractions.push_back(0.4);
598 fractions.push_back(0.4);
604 double T = 273.15 + 10;
614 val = fluid.
rho(T, p, x);
631 val = backend.
hmass();
643 val = backend.
smass();
655 val = fluid.
visc(T, p, x);
667 val = fluid.
cond(T, p, x);
678 val = fluid.
rho(T, p, x);
711 val = backend.
smass();
713 res = backend.
smass();
723 val = fluid.
c(T, p, x);
757 double Tref = 20 + 273.15 - 20;
758 double pref = 101325 * 10;
764 res = backend.
hmass();
774 res = backend.
smass();
786 res = backend.
hmass();
796 res = backend.
smass();
808 res = backend.
hmass();
818 res = backend.
smass();
828 SECTION(
"Tests for the full implementation using PropsSI") {
831 std::string fluid(
"ExampleMelinder");
833 double T = -5 + 273.15;
841 expected = 9.6212e+02;
842 std::vector<std::string> fluid_Melinder(1, fluid);
843 std::vector<std::vector<double>> IO =
CoolProp::PropsSImulti(std::vector<std::string>(1,
"D"),
"T", std::vector<double>(1, T),
"P",
844 std::vector<double>(1, p),
"INCOMP", fluid_Melinder, std::vector<double>(1, x));
845 REQUIRE(!IO.empty());
875 std::string name =
"INCOMP::" + fluid +
format(
"[%f]", x);
891 std::string name =
"INCOMP::" + fluid +
format(
"[%f]", x);
898 SECTION(
"SecCool example") {
900 std::string backend =
"INCOMP";
901 std::vector<std::string> fluids(1,
"ExampleSecCool");
902 double T = -5 + 273.15;
905 std::vector<double> x_vec = std::vector<double>(1, x);
906 std::vector<double> T_vec = std::vector<double>(1, T);
907 std::vector<double> p_vec = std::vector<double>(1, p);
910 double dexpected = 9.4844e+02;
911 std::vector<std::vector<double>> IO =
913 REQUIRE(!IO.empty());
914 double dactual = IO[0][0];
923 CHECK(
check_abs(dexpected, dactual, acc));
927 double cpexpected = 3.6304e+03;
928 double cpactual =
CoolProp::PropsSImulti(std::vector<std::string>(1,
"C"),
"T", T_vec,
"P", p_vec, backend, fluids, x_vec)[0][0];
937 CHECK(
check_abs(cpexpected, cpactual, acc));
940 SECTION(
"INCOMP::ExamplePure") {
942 std::string fluid = std::string(
"INCOMP::ExamplePure");
943 double T = +55 + 273.15;
947 double dexpected = 7.3646e+02;
956 CHECK(
check_abs(dexpected, dactual, acc));
960 double cpexpected = 2.2580e+03;
969 CHECK(
check_abs(cpexpected, cpactual, acc));