test(tests): added test suite
The test suite is extensive. Note that LLMs were used to aid in the development of the test suite. All LLM generated code was manually reviewed.
This commit is contained in:
135
tests/eos/barotrope_meanfield.cpp
Normal file
135
tests/eos/barotrope_meanfield.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
// Preserve the independent identities, finite differences, and surface conventions from MeanField's barotrope tests.
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
|
||||
#include "serif/eos/evaluation.hpp"
|
||||
#include "serif/eos/models/polytropic.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace eos = serif::eos;
|
||||
namespace quantity = serif::dimensions;
|
||||
using Catch::Matchers::WithinRel;
|
||||
|
||||
/** @brief Evaluate a centered difference independently of the EOS derivative implementation. */
|
||||
template <typename Function>
|
||||
[[nodiscard]] double centered_derivative(Function&& function, const double value, const double step)
|
||||
{
|
||||
return (function(value + step) - function(value - step)) / (2.0 * step);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MeanField polytropic round trips preserve the original strict identities", "[unit][eos][meanfield]")
|
||||
{
|
||||
const eos::models::Polytrope model{3.0, 1.5};
|
||||
for (const double density : {1.0e-6, 1.0e-3, 0.1, 0.7, 2.0})
|
||||
{
|
||||
CAPTURE(density);
|
||||
const double pressure = eos::evaluate<quantity::Pressure>(model, quantity::DensityValue{density}).value();
|
||||
const double enthalpy = eos::evaluate<quantity::SpecificEnthalpy>(model, quantity::DensityValue{density}).value();
|
||||
CHECK_THAT(eos::evaluate<quantity::MassDensity>(model, quantity::SpecificEnthalpyValue{enthalpy}).value(), WithinRel(density, 2.0e-14));
|
||||
CHECK_THAT(eos::evaluate<quantity::Pressure>(model, quantity::SpecificEnthalpyValue{enthalpy}).value(), WithinRel(pressure, 2.0e-14));
|
||||
CHECK_THAT(eos::evaluate<quantity::SpecificEnthalpy>(model, quantity::PressureValue{pressure}).value(), WithinRel(enthalpy, 2.0e-14));
|
||||
CHECK_THAT(pressure, WithinRel(density * enthalpy / 4.0, 2.0e-14));
|
||||
CHECK_THAT((eos::partial_derivative<quantity::Pressure, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{enthalpy}).value()), WithinRel(density, 2.0e-14));
|
||||
CHECK_THAT((eos::partial_derivative<quantity::Pressure, quantity::MassDensity>(model, quantity::DensityValue{density}).value()), WithinRel(enthalpy / 3.0, 2.0e-14));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MeanField polytropic thermodynamic identities span integer and fractional indices", "[unit][eos][meanfield]")
|
||||
{
|
||||
for (const double index : {1.0, 1.5, 3.0})
|
||||
{
|
||||
const eos::models::Polytrope model{index, 0.73};
|
||||
CHECK(model.polytropic_index() == index);
|
||||
CHECK(model.polytropic_constant() == 0.73);
|
||||
CHECK(model.enthalpy_scale() == (index + 1.0) * 0.73);
|
||||
for (const double density : {1.0e-4, 0.02, 0.37, 2.4})
|
||||
{
|
||||
CAPTURE(index, density);
|
||||
const double pressure = eos::evaluate<quantity::Pressure>(model, quantity::DensityValue{density}).value();
|
||||
const double enthalpy = eos::evaluate<quantity::SpecificEnthalpy>(model, quantity::DensityValue{density}).value();
|
||||
const double recovered_density = eos::evaluate<quantity::MassDensity>(model, quantity::SpecificEnthalpyValue{enthalpy}).value();
|
||||
const double recovered_pressure = eos::evaluate<quantity::Pressure>(model, quantity::SpecificEnthalpyValue{enthalpy}).value();
|
||||
CHECK_THAT(pressure, WithinRel(0.73 * std::pow(density, 1.0 + 1.0 / index), 2.0e-13));
|
||||
CHECK_THAT(enthalpy, WithinRel((index + 1.0) * 0.73 * std::pow(density, 1.0 / index), 2.0e-13));
|
||||
CHECK_THAT(recovered_density, WithinRel(density, 5.0e-13));
|
||||
CHECK_THAT(recovered_pressure, WithinRel(pressure, 5.0e-13));
|
||||
CHECK_THAT(recovered_pressure, WithinRel(density * enthalpy / (index + 1.0), 5.0e-13));
|
||||
CHECK((eos::partial_derivative<quantity::Pressure, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{enthalpy}).value()) == recovered_density);
|
||||
CHECK_THAT((eos::partial_derivative<quantity::Pressure, quantity::MassDensity>(model, quantity::DensityValue{density}).value()), WithinRel(enthalpy / index, 5.0e-13));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MeanField cubic polytrope derivatives retain the strict centered difference tolerance", "[unit][eos][meanfield]")
|
||||
{
|
||||
const eos::models::Polytrope model{3.0, 1.5};
|
||||
for (const double enthalpy : {0.05, 0.2, 0.7, 1.4})
|
||||
{
|
||||
CAPTURE(enthalpy);
|
||||
const double step = 1.0e-6 * std::max(1.0, enthalpy);
|
||||
const double density_derivative = centered_derivative([&](const double value)
|
||||
{
|
||||
return eos::evaluate<quantity::MassDensity>(model, quantity::SpecificEnthalpyValue{value}).value();
|
||||
}, enthalpy, step);
|
||||
const double pressure_derivative = centered_derivative([&](const double value)
|
||||
{
|
||||
return eos::evaluate<quantity::Pressure>(model, quantity::SpecificEnthalpyValue{value}).value();
|
||||
}, enthalpy, step);
|
||||
CHECK_THAT(density_derivative, WithinRel((eos::partial_derivative<quantity::MassDensity, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{enthalpy}).value()), 5.0e-10));
|
||||
CHECK_THAT(pressure_derivative, WithinRel((eos::partial_derivative<quantity::Pressure, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{enthalpy}).value()), 5.0e-10));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MeanField pressure and density derivatives match centered differences for every original index", "[unit][eos][meanfield]")
|
||||
{
|
||||
for (const double index : {1.0, 1.5, 3.0})
|
||||
{
|
||||
const eos::models::Polytrope model{index, 0.61};
|
||||
for (const double value : {0.2, 0.73, 1.8})
|
||||
{
|
||||
CAPTURE(index, value);
|
||||
const double step = 2.0e-6 * std::max(1.0, std::abs(value));
|
||||
const double pressure_enthalpy = centered_derivative([&](const double enthalpy)
|
||||
{
|
||||
return eos::evaluate<quantity::Pressure>(model, quantity::SpecificEnthalpyValue{enthalpy}).value();
|
||||
}, value, step);
|
||||
const double pressure_density = centered_derivative([&](const double density)
|
||||
{
|
||||
return eos::evaluate<quantity::Pressure>(model, quantity::DensityValue{density}).value();
|
||||
}, value, step);
|
||||
const double density_enthalpy = centered_derivative([&](const double enthalpy)
|
||||
{
|
||||
return eos::evaluate<quantity::MassDensity>(model, quantity::SpecificEnthalpyValue{enthalpy}).value();
|
||||
}, value, step);
|
||||
CHECK_THAT(pressure_enthalpy, WithinRel((eos::partial_derivative<quantity::Pressure, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{value}).value()), 5.0e-8));
|
||||
CHECK_THAT(pressure_density, WithinRel((eos::partial_derivative<quantity::Pressure, quantity::MassDensity>(model, quantity::DensityValue{value}).value()), 5.0e-8));
|
||||
CHECK_THAT(density_enthalpy, WithinRel((eos::partial_derivative<quantity::MassDensity, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{value}).value()), 5.0e-8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MeanField polytropic surface keeps the n one right derivative and zero exterior", "[unit][eos][meanfield]")
|
||||
{
|
||||
for (const double index : {1.0, 1.5, 3.0})
|
||||
{
|
||||
const eos::models::Polytrope model{index, 0.47};
|
||||
for (const double enthalpy : {0.0, -0.3, -1.0})
|
||||
{
|
||||
CAPTURE(index, enthalpy);
|
||||
CHECK(eos::evaluate<quantity::MassDensity>(model, quantity::SpecificEnthalpyValue{enthalpy}).value() == 0.0);
|
||||
CHECK(eos::evaluate<quantity::Pressure>(model, quantity::SpecificEnthalpyValue{enthalpy}).value() == 0.0);
|
||||
CHECK((eos::partial_derivative<quantity::Pressure, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{enthalpy}).value()) == 0.0);
|
||||
const double density_derivative = index == 1.0 && enthalpy == 0.0 ? 1.0 / model.enthalpy_scale() : 0.0;
|
||||
CHECK((eos::partial_derivative<quantity::MassDensity, quantity::SpecificEnthalpy>(model, quantity::SpecificEnthalpyValue{enthalpy}).value()) == density_derivative);
|
||||
}
|
||||
CHECK(eos::evaluate<quantity::Pressure>(model, quantity::DensityValue{0.0}).value() == 0.0);
|
||||
CHECK(eos::evaluate<quantity::SpecificEnthalpy>(model, quantity::DensityValue{0.0}).value() == 0.0);
|
||||
CHECK((eos::partial_derivative<quantity::Pressure, quantity::MassDensity>(model, quantity::DensityValue{0.0}).value()) == 0.0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user