3# define _CRTDBG_MAP_ALLOC
4# ifndef _CRT_SECURE_NO_WARNINGS
5# define _CRT_SECURE_NO_WARNINGS
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) <<
'\n';
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.");
199 std::cout <<
format(
"Incompressible backend: Called set_fractions with %s ",
vec_to_string(fractions).c_str()) <<
'\n';
200 if (fractions.size() != 1)
201 throw ValueError(
format(
"The incompressible backend only supports one entry in the fraction vector and not %d.", fractions.size()));
202 if ((this->
_fractions.size() != 1) || (this->_fractions[0] != fractions[0])) {
204 std::cout <<
format(
"Incompressible backend: Updating the fractions triggered a change in reference state %s -> %s",
218 std::cout <<
format(
"Incompressible backend: Called set_mole_fractions with %s ",
vec_to_string(mole_fractions).c_str()) <<
'\n';
219 if (mole_fractions.size() != 1)
220 throw ValueError(
format(
"The incompressible backend only supports one entry in the mole fraction vector and not %d.", mole_fractions.size()));
224 std::cout <<
format(
"Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",
vec_to_string(mole_fractions).c_str(),
230 std::vector<CoolPropDbl> tmp_fractions;
231 tmp_fractions.reserve(mole_fractions.size());
232 for (
auto mole_fraction : mole_fractions) {
245 std::cout <<
format(
"Incompressible backend: Called set_mass_fractions with %s ",
vec_to_string(mass_fractions).c_str()) <<
'\n';
246 if (mass_fractions.size() != 1)
247 throw ValueError(
format(
"The incompressible backend only supports one entry in the mass fraction vector and not %d.", mass_fractions.size()));
251 std::cout <<
format(
"Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",
vec_to_string(mass_fractions).c_str(),
257 std::vector<CoolPropDbl> tmp_fractions;
258 tmp_fractions.reserve(mass_fractions.size());
259 for (
auto mass_fraction : mass_fractions) {
272 std::cout <<
format(
"Incompressible backend: Called set_volu_fractions with %s ",
vec_to_string(volu_fractions).c_str()) <<
'\n';
273 if (volu_fractions.size() != 1)
275 format(
"The incompressible backend only supports one entry in the volume fraction vector and not %d.", volu_fractions.size()));
279 std::cout <<
format(
"Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",
vec_to_string(volu_fractions).c_str(),
285 std::vector<CoolPropDbl> tmp_fractions;
286 tmp_fractions.reserve(volu_fractions.size());
287 for (
auto volu_fraction : volu_fractions) {
415 :
p(
p), x(x), h_in(h_in), backend(backend) {}
416 double call(
double target)
override {
447 :
p(
p), x(x), s_in(s_in), backend(backend) {}
448 double call(
double target)
override {
503 if (param ==
iT && given ==
iP) {
506 throw ValueError(
"For incompressibles, the only valid inputs to calc_melting_line are T(p)");
532 if ((Of ==
iDmass) && (Wrt ==
iP))
return 0.0;
553 throw ValueError(
"Incompressible fluids only support a limited subset of partial derivatives.");
579# include <catch2/catch_all.hpp>
583TEST_CASE(
"Internal consistency checks and example use cases for the incompressible backend",
"[IncompressibleBackend]") {
587 SECTION(
"Test case for Methanol from SecCool") {
595 std::vector<CoolPropDbl> fractions;
596 fractions.push_back(0.4);
599 fractions.push_back(0.4);
605 double T = 273.15 + 10;
615 val = fluid.
rho(
T, p, x);
632 val = backend.
hmass();
644 val = backend.
smass();
656 val = fluid.
visc(
T, p, x);
668 val = fluid.
cond(
T, p, x);
679 val = fluid.
rho(
T, p, x);
712 val = backend.
smass();
714 res = backend.
smass();
724 val = fluid.
c(
T, p, x);
758 double Tref = 20 + 273.15 - 20;
759 double pref = 101325 * 10;
765 res = backend.
hmass();
775 res = backend.
smass();
787 res = backend.
hmass();
797 res = backend.
smass();
809 res = backend.
hmass();
819 res = backend.
smass();
829 SECTION(
"Tests for the full implementation using PropsSI") {
832 std::string fluid(
"ExampleMelinder");
834 double T = -5 + 273.15;
842 expected = 9.6212e+02;
843 std::vector<std::string> fluid_Melinder(1, fluid);
844 std::vector<std::vector<double>> IO =
CoolProp::PropsSImulti(std::vector<std::string>(1,
"D"),
"T", std::vector<double>(1,
T),
"P",
845 std::vector<double>(1, p),
"INCOMP", fluid_Melinder, std::vector<double>(1, x));
846 REQUIRE(!IO.empty());
876 std::string name =
"INCOMP::" + fluid +
format(
"[%f]", x);
892 std::string name =
"INCOMP::" + fluid +
format(
"[%f]", x);
899 SECTION(
"SecCool example") {
901 std::string backend =
"INCOMP";
902 std::vector<std::string> fluids(1,
"ExampleSecCool");
903 double T = -5 + 273.15;
906 std::vector<double> x_vec = std::vector<double>(1, x);
907 std::vector<double> T_vec = std::vector<double>(1,
T);
908 std::vector<double> p_vec = std::vector<double>(1, p);
911 double dexpected = 9.4844e+02;
912 std::vector<std::vector<double>> IO =
914 REQUIRE(!IO.empty());
915 double dactual = IO[0][0];
924 CHECK(
check_abs(dexpected, dactual, acc));
928 double cpexpected = 3.6304e+03;
929 double cpactual =
CoolProp::PropsSImulti(std::vector<std::string>(1,
"C"),
"T", T_vec,
"P", p_vec, backend, fluids, x_vec)[0][0];
938 CHECK(
check_abs(cpexpected, cpactual, acc));
941 SECTION(
"INCOMP::ExamplePure") {
943 std::string fluid = std::string(
"INCOMP::ExamplePure");
944 double T = +55 + 273.15;
948 double dexpected = 7.3646e+02;
957 CHECK(
check_abs(dexpected, dactual, acc));
961 double cpexpected = 2.2580e+03;
970 CHECK(
check_abs(cpexpected, cpactual, acc));