test(plot): use composed matchers to tolerate cross-platform libm jitter (#2760)

The Plot isoline `.value` checks asserted at WithinAbs(value, 1e-10), which
is platform-fragile: libm transcendentals (exp/log/pow) differ in the last
few bits across glibc, Apple libm, and UCRT, and that propagates through
the EOS solvers into ~1e-9 to 1e-10 relative differences in the computed
range bounds. Reference data regenerated on macOS in #2749 therefore broke
the Linux CI.

Switch to `WithinAbs(v, abs) || WithinRel(v, 1e-8)`: keeps the absolute
tolerance as a near-zero safety net and adds a 1e-8 relative tolerance
that comfortably covers the observed cross-platform jitter (worst case
~5e-9 rel for p_isolines[4]). Updated the generator script and re-ran it
to regenerate src/CoolPropPlot.cpp.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ian Bell
2026-04-20 19:06:15 -04:00
committed by GitHub
parent 833160481b
commit 5b53e4394a
2 changed files with 128 additions and 125 deletions

View File

@@ -77,27 +77,27 @@ def generate_ph_test():
# Generate value checks
for i in range(5):
value = plot._isolines[py_param][i].value
print(f' CHECK_THAT({cpp_name.lower()}_isolines[{i}].value, WithinAbs({value}, 1e-10));')
print(f' CHECK_THAT({cpp_name.lower()}_isolines[{i}].value, WithinAbs({value}, 1e-10) || WithinRel({value}, 1e-8));')
# Generate expected x values
print(' const double expected_x[isoline_count][points_per_isoline] = {')
for i in range(5):
x_values = [format_number(x) for x in plot._isolines[py_param][i].x]
print(' {' + ', '.join(x_values) + '},')
print(' };')
# Generate expected y values
print(' const double expected_y[isoline_count][points_per_isoline] = {')
for i in range(5):
y_values = [format_number(y) for y in plot._isolines[py_param][i].y]
print(' {' + ', '.join(y_values) + '},')
print(' };')
# Generate validation loop
print(f' for (int i = 0; i < {cpp_name.lower()}_isolines.size(); ++i) {{')
print(f' REQUIRE({cpp_name.lower()}_isolines[i].size() == points_per_isoline);')
print(f' for (int j = 0; j < {cpp_name.lower()}_isolines[i].size(); ++j) {{')
# Check for NaN values in this isoline type
has_nan_x = any(math.isnan(x) for isoline in plot._isolines[py_param] for x in isoline.x)
@@ -171,9 +171,9 @@ def generate_ts_test():
for i in range(5):
value = plot._isolines[py_param][i].value
if cpp_name == 'P':
print(f' CHECK_THAT({cpp_name.lower()}_isolines[{i}].value, WithinAbs({value}, 1e-7));')
print(f' CHECK_THAT({cpp_name.lower()}_isolines[{i}].value, WithinAbs({value}, 1e-7) || WithinRel({value}, 1e-8));')
else:
print(f' CHECK_THAT({cpp_name.lower()}_isolines[{i}].value, WithinAbs({value}, 1e-10));')
print(f' CHECK_THAT({cpp_name.lower()}_isolines[{i}].value, WithinAbs({value}, 1e-10) || WithinRel({value}, 1e-8));')
# Add blank line only for the first Q isolines section
if cpp_name == 'Q':

View File

@@ -474,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.07372753976784, 1e-10));
CHECK_THAT(plot.value_at(CoolProp::iQ, 300000, 200000), WithinAbs(0.550443478743443, 1e-10));
@@ -507,24 +507,24 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
std::vector<double> q_values = CoolProp::Plot::generate_values_in_range(CoolProp::iQ, q_range, isoline_count);
CoolProp::Plot::Isolines q_isolines = plot.calc_isolines(CoolProp::iQ, q_values, points_per_isoline);
REQUIRE(q_isolines.size() == isoline_count);
CHECK_THAT(q_isolines[0].value, WithinAbs(0.0, 1e-10));
CHECK_THAT(q_isolines[1].value, WithinAbs(0.25, 1e-10));
CHECK_THAT(q_isolines[2].value, WithinAbs(0.5, 1e-10));
CHECK_THAT(q_isolines[3].value, WithinAbs(0.75, 1e-10));
CHECK_THAT(q_isolines[4].value, WithinAbs(1.0, 1e-10));
CHECK_THAT(q_isolines[0].value, WithinAbs(0.0, 1e-10) || WithinRel(0.0, 1e-8));
CHECK_THAT(q_isolines[1].value, WithinAbs(0.25, 1e-10) || WithinRel(0.25, 1e-8));
CHECK_THAT(q_isolines[2].value, WithinAbs(0.5, 1e-10) || WithinRel(0.5, 1e-8));
CHECK_THAT(q_isolines[3].value, WithinAbs(0.75, 1e-10) || WithinRel(0.75, 1e-8));
CHECK_THAT(q_isolines[4].value, WithinAbs(1.0, 1e-10) || WithinRel(1.0, 1e-8));
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);
@@ -540,24 +540,24 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
std::vector<double> t_values = CoolProp::Plot::generate_values_in_range(CoolProp::iT, t_range, isoline_count);
CoolProp::Plot::Isolines t_isolines = plot.calc_isolines(CoolProp::iT, t_values, points_per_isoline);
REQUIRE(t_isolines.size() == isoline_count);
CHECK_THAT(t_isolines[0].value, WithinAbs(173.15, 1e-10));
CHECK_THAT(t_isolines[1].value, WithinAbs(243.6125, 1e-10));
CHECK_THAT(t_isolines[2].value, WithinAbs(314.07500000000005, 1e-10));
CHECK_THAT(t_isolines[3].value, WithinAbs(384.5375, 1e-10));
CHECK_THAT(t_isolines[4].value, WithinAbs(455.0, 1e-10));
CHECK_THAT(t_isolines[0].value, WithinAbs(173.15, 1e-10) || WithinRel(173.15, 1e-8));
CHECK_THAT(t_isolines[1].value, WithinAbs(243.6125, 1e-10) || WithinRel(243.6125, 1e-8));
CHECK_THAT(t_isolines[2].value, WithinAbs(314.07500000000005, 1e-10) || WithinRel(314.07500000000005, 1e-8));
CHECK_THAT(t_isolines[3].value, WithinAbs(384.5375, 1e-10) || WithinRel(384.5375, 1e-8));
CHECK_THAT(t_isolines[4].value, WithinAbs(455.0, 1e-10) || WithinRel(455.0, 1e-8));
const double expected_x[isoline_count][points_per_isoline] = {
{75373.1268990847, 75410.9911120364, 75576.5817007017, 76301.4918516847, 79487.8877890133},
{382785.230587562, 161389.442353424, 161516.218619861, 162076.984158713, 164637.062378302},
{439466.649843278, 438148.172824113, 431912.06623801, 257605.319479567, 257512.83924738},
{504550.626065609, 503783.529360494, 500331.593280179, 482707.178357055, 366958.520782669},
{577604.594975215, 577097.06504804, 574850.152315428, 564443.78972976, 507875.800623495},
{75373.1268990847, 75410.9911120364, 75576.5817007017, 76301.4918516847, 79487.8877890133},
{382785.230587562, 161389.442353424, 161516.218619861, 162076.984158713, 164637.062378302},
{439466.649843278, 438148.172824113, 431912.06623801, 257605.319479567, 257512.83924738},
{504550.626065609, 503783.529360494, 500331.593280179, 482707.178357055, 366958.520782669},
{577604.594975215, 577097.06504804, 574850.152315428, 564443.78972976, 507875.800623495},
};
const double expected_y[isoline_count][points_per_isoline] = {
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
};
for (int i = 0; i < t_isolines.size(); ++i) {
REQUIRE(t_isolines[i].size() == points_per_isoline);
@@ -573,24 +573,24 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
std::vector<double> s_values = CoolProp::Plot::generate_values_in_range(CoolProp::iSmass, s_range, isoline_count);
CoolProp::Plot::Isolines s_isolines = plot.calc_isolines(CoolProp::iSmass, s_values, points_per_isoline);
REQUIRE(s_isolines.size() == isoline_count);
CHECK_THAT(s_isolines[0].value, WithinAbs(426.0094838589179, 1e-10));
CHECK_THAT(s_isolines[1].value, WithinAbs(925.275035740241, 1e-10));
CHECK_THAT(s_isolines[2].value, WithinAbs(1424.540587621564, 1e-10));
CHECK_THAT(s_isolines[3].value, WithinAbs(1923.8061395028872, 1e-10));
CHECK_THAT(s_isolines[4].value, WithinAbs(2423.07169138421, 1e-10));
CHECK_THAT(s_isolines[0].value, WithinAbs(426.0094838589179, 1e-10) || WithinRel(426.0094838589179, 1e-8));
CHECK_THAT(s_isolines[1].value, WithinAbs(925.275035740241, 1e-10) || WithinRel(925.275035740241, 1e-8));
CHECK_THAT(s_isolines[2].value, WithinAbs(1424.540587621564, 1e-10) || WithinRel(1424.540587621564, 1e-8));
CHECK_THAT(s_isolines[3].value, WithinAbs(1923.8061395028872, 1e-10) || WithinRel(1923.8061395028872, 1e-8));
CHECK_THAT(s_isolines[4].value, WithinAbs(2423.07169138421, 1e-10) || WithinRel(2423.07169138421, 1e-8));
const double expected_x[isoline_count][points_per_isoline] = {
{73758.1368332803, 73811.2861610949, 74043.6241895902, 75058.8771715002, 79487.8877891817},
{176257.349845128, 179794.80776134, 180290.319046059, 181487.967470984, 186690.959613052},
{286286.17581826, 303984.726429065, 321692.362822335, 335551.688988092, 344087.839489012},
{399372.560529313, 433400.354293214, 471964.896215781, 513835.931067728, 555824.663129382},
{577604.594975103, 635258.237157865, 698999.44597458, 768745.631258105, std::nan("")},
{73758.1368332803, 73811.2861610949, 74043.6241895902, 75058.8771715002, 79487.8877891817},
{176257.349845128, 179794.80776134, 180290.319046059, 181487.967470984, 186690.959613052},
{286286.17581826, 303984.726429065, 321692.362822335, 335551.688988092, 344087.839489012},
{399372.560529313, 433400.354293214, 471964.896215781, 513835.931067728, 555824.663129382},
{577604.594975103, 635258.237157865, 698999.44597458, 768745.631258105, std::nan("")},
};
const double expected_y[isoline_count][points_per_isoline] = {
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
};
for (int i = 0; i < s_isolines.size(); ++i) {
REQUIRE(s_isolines[i].size() == points_per_isoline);
@@ -609,24 +609,24 @@ TEST_CASE("Check that the isolines are the same as from Python", "[Plot]") {
std::vector<double> d_values = CoolProp::Plot::generate_values_in_range(CoolProp::iDmass, d_range, isoline_count);
CoolProp::Plot::Isolines d_isolines = plot.calc_isolines(CoolProp::iDmass, d_values, points_per_isoline);
REQUIRE(d_isolines.size() == isoline_count);
CHECK_THAT(d_isolines[0].value, WithinAbs(0.6749779869915704, 1e-10));
CHECK_THAT(d_isolines[1].value, WithinAbs(4.704765645221012, 1e-10));
CHECK_THAT(d_isolines[2].value, WithinAbs(32.793395048494105, 1e-10));
CHECK_THAT(d_isolines[3].value, WithinAbs(228.57817793729427, 1e-10));
CHECK_THAT(d_isolines[4].value, WithinAbs(1593.2471569921404, 1e-10));
CHECK_THAT(d_isolines[0].value, WithinAbs(0.6749779869915704, 1e-10) || WithinRel(0.6749779869915704, 1e-8));
CHECK_THAT(d_isolines[1].value, WithinAbs(4.704765645221012, 1e-10) || WithinRel(4.704765645221012, 1e-8));
CHECK_THAT(d_isolines[2].value, WithinAbs(32.793395048494105, 1e-10) || WithinRel(32.793395048494105, 1e-8));
CHECK_THAT(d_isolines[3].value, WithinAbs(228.57817793729427, 1e-10) || WithinRel(228.57817793729427, 1e-8));
CHECK_THAT(d_isolines[4].value, WithinAbs(1593.2471569921404, 1e-10) || WithinRel(1593.2471569921404, 1e-8));
const double expected_x[isoline_count][points_per_isoline] = {
{577604.594973719, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
{202365.843978241, 419230.11212018, std::nan(""), std::nan(""), std::nan("")},
{142114.49128355, 204388.004481049, 351216.809719432, std::nan(""), std::nan("")},
{133470.418481179, 172415.768781909, 235383.044878653, 357492.457498284, 669493.626069481},
{70518.3287887542, 70601.2088968633, 70963.5807782658, 72548.3591964927, 79487.8877885823},
{577604.594973719, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
{202365.843978241, 419230.11212018, std::nan(""), std::nan(""), std::nan("")},
{142114.49128355, 204388.004481049, 351216.809719432, std::nan(""), std::nan("")},
{133470.418481179, 172415.768781909, 235383.044878653, 357492.457498284, 669493.626069481},
{70518.3287887542, 70601.2088968633, 70963.5807782658, 72548.3591964927, 79487.8877885823},
};
const double expected_y[isoline_count][points_per_isoline] = {
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
{24999.9999999246, 109298.142140435, 477843.35501547, 2089095.63750003, 9133370.87732516},
};
for (int i = 0; i < d_isolines.size(); ++i) {
REQUIRE(d_isolines[i].size() == points_per_isoline);
@@ -669,25 +669,25 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
std::vector<double> q_values = CoolProp::Plot::generate_values_in_range(CoolProp::iQ, q_range, isoline_count);
CoolProp::Plot::Isolines q_isolines = plot.calc_isolines(CoolProp::iQ, q_values, points_per_isoline);
REQUIRE(q_isolines.size() == isoline_count);
CHECK_THAT(q_isolines[0].value, WithinAbs(0.0, 1e-10));
CHECK_THAT(q_isolines[1].value, WithinAbs(0.25, 1e-10));
CHECK_THAT(q_isolines[2].value, WithinAbs(0.5, 1e-10));
CHECK_THAT(q_isolines[3].value, WithinAbs(0.75, 1e-10));
CHECK_THAT(q_isolines[4].value, WithinAbs(1.0, 1e-10));
CHECK_THAT(q_isolines[0].value, WithinAbs(0.0, 1e-10) || WithinRel(0.0, 1e-8));
CHECK_THAT(q_isolines[1].value, WithinAbs(0.25, 1e-10) || WithinRel(0.25, 1e-8));
CHECK_THAT(q_isolines[2].value, WithinAbs(0.5, 1e-10) || WithinRel(0.5, 1e-8));
CHECK_THAT(q_isolines[3].value, WithinAbs(0.75, 1e-10) || WithinRel(0.75, 1e-8));
CHECK_THAT(q_isolines[4].value, WithinAbs(1.0, 1e-10) || WithinRel(1.0, 1e-8));
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) {
@@ -704,24 +704,24 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
std::vector<double> p_values = CoolProp::Plot::generate_values_in_range(CoolProp::iP, p_range, isoline_count);
CoolProp::Plot::Isolines p_isolines = plot.calc_isolines(CoolProp::iP, p_values, points_per_isoline);
REQUIRE(p_isolines.size() == isoline_count);
CHECK_THAT(p_isolines[0].value, WithinAbs(24999.999999924625, 1e-7));
CHECK_THAT(p_isolines[1].value, WithinAbs(109298.14214043504, 1e-7));
CHECK_THAT(p_isolines[2].value, WithinAbs(477843.35501546983, 1e-7));
CHECK_THAT(p_isolines[3].value, WithinAbs(2089095.6375000286, 1e-7));
CHECK_THAT(p_isolines[4].value, WithinAbs(9133370.877325162, 1e-7));
CHECK_THAT(p_isolines[0].value, WithinAbs(24999.999999924625, 1e-7) || WithinRel(24999.999999924625, 1e-8));
CHECK_THAT(p_isolines[1].value, WithinAbs(109298.14214043504, 1e-7) || WithinRel(109298.14214043504, 1e-8));
CHECK_THAT(p_isolines[2].value, WithinAbs(477843.35501546983, 1e-7) || WithinRel(477843.35501546983, 1e-8));
CHECK_THAT(p_isolines[3].value, WithinAbs(2089095.6375000286, 1e-7) || WithinRel(2089095.6375000286, 1e-8));
CHECK_THAT(p_isolines[4].value, WithinAbs(9133370.877325162, 1e-7) || WithinRel(9133370.877325162, 1e-8));
const double expected_x[isoline_count][points_per_isoline] = {
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
};
const double expected_y[isoline_count][points_per_isoline] = {
{171.786072658977, 220.381369310426, 220.381369310426, 265.36247722467, 454.999999999897},
{171.798910666077, 248.745218250597, 248.745218250597, 308.633922578156, 506.387752765209},
{171.854988815553, 258.195699077655, 287.473037339606, 355.964867195189, 560.293101205153},
{172.099235421019, 258.742471435868, 342.561817266701, 411.323964498156, 618.036314182066},
{173.150000000039, 261.02106158166, 371.327173902085, 484.42783162311, std::nan("")},
{171.786072658977, 220.381369310426, 220.381369310426, 265.36247722467, 454.999999999897},
{171.798910666077, 248.745218250597, 248.745218250597, 308.633922578156, 506.387752765209},
{171.854988815553, 258.195699077655, 287.473037339606, 355.964867195189, 560.293101205153},
{172.099235421019, 258.742471435868, 342.561817266701, 411.323964498156, 618.036314182066},
{173.150000000039, 261.02106158166, 371.327173902085, 484.42783162311, std::nan("")},
};
for (int i = 0; i < p_isolines.size(); ++i) {
REQUIRE(p_isolines[i].size() == points_per_isoline);
@@ -741,24 +741,24 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
std::vector<double> h_values = CoolProp::Plot::generate_values_in_range(CoolProp::iHmass, h_range, isoline_count);
CoolProp::Plot::Isolines h_isolines = plot.calc_isolines(CoolProp::iHmass, h_values, points_per_isoline);
REQUIRE(h_isolines.size() == isoline_count);
CHECK_THAT(h_isolines[0].value, WithinAbs(75373.12689908473, 1e-10));
CHECK_THAT(h_isolines[1].value, WithinAbs(200930.99391811722, 1e-10));
CHECK_THAT(h_isolines[2].value, WithinAbs(326488.86093714973, 1e-10));
CHECK_THAT(h_isolines[3].value, WithinAbs(452046.7279561822, 1e-10));
CHECK_THAT(h_isolines[4].value, WithinAbs(577604.5949752147, 1e-10));
CHECK_THAT(h_isolines[0].value, WithinAbs(75373.12689908473, 1e-10) || WithinRel(75373.12689908473, 1e-8));
CHECK_THAT(h_isolines[1].value, WithinAbs(200930.99391811722, 1e-10) || WithinRel(200930.99391811722, 1e-8));
CHECK_THAT(h_isolines[2].value, WithinAbs(326488.86093714973, 1e-10) || WithinRel(326488.86093714973, 1e-8));
CHECK_THAT(h_isolines[3].value, WithinAbs(452046.7279561822, 1e-10) || WithinRel(452046.7279561822, 1e-8));
CHECK_THAT(h_isolines[4].value, WithinAbs(577604.5949752147, 1e-10) || WithinRel(577604.5949752147, 1e-8));
const double expected_x[isoline_count][points_per_isoline] = {
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
{426.009483858918, 925.275035740241, 1424.54058762156, 1923.80613950289, 2423.07169138421},
};
const double expected_y[isoline_count][points_per_isoline] = {
{172.17457530891, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
{196.074550633801, 266.631159311947, std::nan(""), std::nan(""), std::nan("")},
{213.66468184215, 299.984652703029, 301.726570478677, std::nan(""), std::nan("")},
{228.411201679483, 322.843563824883, 426.787882130031, 331.521169967994, 328.042167528594},
{241.568258022782, 341.66133891579, 458.593848045217, std::nan(""), 455.000000000079},
{172.17457530891, std::nan(""), std::nan(""), std::nan(""), std::nan("")},
{196.074550633801, 266.631159311947, std::nan(""), std::nan(""), std::nan("")},
{213.66468184215, 299.984652703029, 301.726570478677, std::nan(""), std::nan("")},
{228.411201679483, 322.843563824883, 426.787882130031, 331.521169967994, 328.042167528594},
{241.568258022782, 341.66133891579, 458.593848045217, std::nan(""), 455.000000000079},
};
for (int i = 0; i < h_isolines.size(); ++i) {
REQUIRE(h_isolines[i].size() == points_per_isoline);
@@ -778,21 +778,24 @@ TEST_CASE("Basic TS Plot has same output as Python", "[Plot]") {
std::vector<double> d_values = CoolProp::Plot::generate_values_in_range(CoolProp::iDmass, d_range, isoline_count);
CoolProp::Plot::Isolines d_isolines = plot.calc_isolines(CoolProp::iDmass, d_values, points_per_isoline);
REQUIRE(d_isolines.size() == isoline_count);
CHECK_THAT(d_isolines[0].value, WithinAbs(0.6749779869915704, 1e-10));
CHECK_THAT(d_isolines[1].value, WithinAbs(4.704765645221012, 1e-10));
CHECK_THAT(d_isolines[2].value, WithinAbs(32.793395048494105, 1e-10));
CHECK_THAT(d_isolines[3].value, WithinAbs(228.57817793729427, 1e-10));
CHECK_THAT(d_isolines[4].value, WithinAbs(1593.2471569921404, 1e-10));
CHECK_THAT(d_isolines[0].value, WithinAbs(0.6749779869915704, 1e-10) || WithinRel(0.6749779869915704, 1e-8));
CHECK_THAT(d_isolines[1].value, WithinAbs(4.704765645221012, 1e-10) || WithinRel(4.704765645221012, 1e-8));
CHECK_THAT(d_isolines[2].value, WithinAbs(32.793395048494105, 1e-10) || WithinRel(32.793395048494105, 1e-8));
CHECK_THAT(d_isolines[3].value, WithinAbs(228.57817793729427, 1e-10) || WithinRel(228.57817793729427, 1e-8));
CHECK_THAT(d_isolines[4].value, WithinAbs(1593.2471569921404, 1e-10) || WithinRel(1593.2471569921404, 1e-8));
const double expected_x[isoline_count][points_per_isoline] = {
{524.173878302998, 1911.09303197673, 2092.95299735844, 2262.71394473455, 2423.07169138421},
{448.103089615505, 1715.11956249458, 1932.46627813425, 2103.15612327652, 2263.90953791769},
{437.189451893868, 972.489749676145, 1758.36241052051, 1935.75228615955, 2099.2064319409},
{435.623706482598, 865.946977105681, 1292.02339683129, 1720.27746043046, 1899.38158004687},
{426.009483858917, 710.877062876878, 946.968704706707, 1151.91782375263, 1335.56507098392},
{524.173878302998, 1911.09303197673, 2092.95299735844, 2262.71394473455, 2423.07169138421},
{448.103089615505, 1715.11956249458, 1932.46627813425, 2103.15612327652, 2263.90953791769},
{437.189451893868, 972.489749676145, 1758.36241052051, 1935.75228615955, 2099.2064319409},
{435.623706482598, 865.946977105681, 1292.02339683129, 1720.27746043046, 1899.38158004687},
{426.009483858917, 710.877062876878, 946.968704706707, 1151.91782375263, 1335.56507098392},
};
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);