#include #include #include #include #include import mean_field; import test_helpers; TEST_CASE("Polytropic EOS Satisfies Its Analytic Identities", tags::barotrope_eos_unit) { constexpr double polytropic_index = 3.0; constexpr double polytropic_constant = 1.5; const mean_field::eos::Polytrope barotrope(polytropic_index, polytropic_constant); const std::array densities{1.0e-6, 1.0e-3, 0.1, 0.7, 2.0}; for (const double density : densities) { const double pressure = barotrope.pressure_from_density(density); const double enthalpy = barotrope.enthalpy_from_density(density); const double reconstructed_density = barotrope.density_from_enthalpy(enthalpy); const double reconstructed_pressure = barotrope.pressure_from_enthalpy(enthalpy); const double reconstructed_enthalpy = barotrope.enthalpy_from_pressure(pressure); CHECK_THAT(reconstructed_density, Catch::Matchers::WithinRel(density, 2.0e-14)); CHECK_THAT(reconstructed_pressure, Catch::Matchers::WithinRel(pressure, 2.0e-14)); CHECK_THAT(reconstructed_enthalpy, Catch::Matchers::WithinRel(enthalpy, 2.0e-14)); CHECK_THAT(pressure, Catch::Matchers::WithinRel( density * enthalpy / (polytropic_index + 1.0), 2.0e-14)); CHECK_THAT(barotrope.pressure_derivative_from_enthalpy(enthalpy), Catch::Matchers::WithinRel(density, 2.0e-14)); CHECK_THAT( barotrope.pressure_derivative_from_density(density), Catch::Matchers::WithinRel(enthalpy / polytropic_index, 2.0e-14)); } } TEST_CASE("Polytropic EOS Derivatives Match Centered Differences", tags::barotrope_eos_jacobian) { const mean_field::eos::Polytrope barotrope(3.0, 1.5); const std::array enthalpies{0.05, 0.2, 0.7, 1.4}; for (const double enthalpy : enthalpies) { const double step = 1.0e-6 * std::max(1.0, enthalpy); const double density_difference = (barotrope.density_from_enthalpy(enthalpy + step) - barotrope.density_from_enthalpy(enthalpy - step)) / (2.0 * step); const double pressure_difference = (barotrope.pressure_from_enthalpy(enthalpy + step) - barotrope.pressure_from_enthalpy(enthalpy - step)) / (2.0 * step); CHECK_THAT( density_difference, Catch::Matchers::WithinRel( barotrope.density_derivative_from_enthalpy(enthalpy), 5.0e-10)); CHECK_THAT( pressure_difference, Catch::Matchers::WithinRel( barotrope.pressure_derivative_from_enthalpy(enthalpy), 5.0e-10)); } } TEST_CASE("Polytropic EOS Has An Exact Zero Density Surface", tags::barotrope_eos_unit) { const mean_field::eos::Polytrope barotrope(3.0, 1.5); CHECK(barotrope.density_from_enthalpy(-1.0) == 0.0); CHECK(barotrope.density_from_enthalpy(0.0) == 0.0); CHECK(barotrope.pressure_from_enthalpy(-1.0) == 0.0); CHECK(barotrope.pressure_from_enthalpy(0.0) == 0.0); CHECK(barotrope.density_derivative_from_enthalpy(-1.0) == 0.0); CHECK(barotrope.density_derivative_from_enthalpy(0.0) == 0.0); CHECK(barotrope.pressure_derivative_from_enthalpy(0.0) == 0.0); } TEST_CASE("Polytropic EOS Rejects Invalid Material Parameters", tags::barotrope_eos_unit) { CHECK_THROWS_AS(mean_field::eos::Polytrope(0.5, 1.0), std::invalid_argument); CHECK_THROWS_AS(mean_field::eos::Polytrope(3.0, 0.0), std::invalid_argument); CHECK_THROWS_AS( mean_field::eos::Polytrope(std::numeric_limits::infinity(), 1.0), std::invalid_argument); const mean_field::eos::Polytrope barotrope(3.0, 1.0); CHECK_THROWS_AS(barotrope.pressure_from_density(-1.0), std::domain_error); CHECK_THROWS_AS(barotrope.enthalpy_from_density(-1.0), std::domain_error); CHECK_THROWS_AS(barotrope.enthalpy_from_pressure(-1.0), std::domain_error); }