feat(surface): major work on implementing surface constraints in a presciption agnostic manner
This commit is contained in:
200
tests/physics/polytropic_eos_relations.cpp
Normal file
200
tests/physics/polytropic_eos_relations.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <concepts>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
|
||||
import mean_field;
|
||||
import test_helpers;
|
||||
|
||||
namespace {
|
||||
namespace eos = mean_field::eos;
|
||||
|
||||
template <typename Candidate>
|
||||
concept HasAnyUnaryEquationOfStateConversion =
|
||||
requires(const Candidate &candidate, const double value) { candidate.pressure_from_density(value); } ||
|
||||
requires(const Candidate &candidate, const double value) { candidate.pressure_from_enthalpy(value); } ||
|
||||
requires(const Candidate &candidate, const double value) { candidate.enthalpy_from_density(value); } ||
|
||||
requires(const Candidate &candidate, const double value) { candidate.enthalpy_from_pressure(value); } ||
|
||||
requires(const Candidate &candidate, const double value) { candidate.density_from_enthalpy(value); } ||
|
||||
requires(const Candidate &candidate, const double value) {
|
||||
candidate.density_derivative_from_enthalpy(value);
|
||||
} ||
|
||||
requires(const Candidate &candidate, const double value) {
|
||||
candidate.pressure_derivative_from_enthalpy(value);
|
||||
} ||
|
||||
requires(const Candidate &candidate, const double value) { candidate.pressure_derivative_from_density(value); };
|
||||
} // namespace
|
||||
|
||||
TEST_CASE(
|
||||
"Polytropic EOS Declares Its Thermodynamic Relation Contract",
|
||||
tags::polytropic_eos_relation_contract
|
||||
) {
|
||||
using Polytrope = eos::Polytrope;
|
||||
|
||||
STATIC_CHECK(eos::EquationOfStateModel<Polytrope>);
|
||||
STATIC_CHECK_FALSE(std::is_polymorphic_v<Polytrope>);
|
||||
STATIC_CHECK_FALSE(HasAnyUnaryEquationOfStateConversion<Polytrope>);
|
||||
STATIC_CHECK(Polytrope::Relations::size == 5);
|
||||
|
||||
STATIC_CHECK(eos::SupportsRelation<Polytrope, eos::PressureFromDensity>);
|
||||
STATIC_CHECK(eos::SupportsRelation<Polytrope, eos::PressureFromSpecificEnthalpy>);
|
||||
STATIC_CHECK(eos::SupportsRelation<Polytrope, eos::SpecificEnthalpyFromDensity>);
|
||||
STATIC_CHECK(eos::SupportsRelation<Polytrope, eos::SpecificEnthalpyFromPressure>);
|
||||
STATIC_CHECK(eos::SupportsRelation<Polytrope, eos::DensityFromSpecificEnthalpy>);
|
||||
|
||||
STATIC_CHECK(eos::SupportsPartialDerivative<Polytrope, eos::PressureFromDensity, eos::quantity::Density>);
|
||||
STATIC_CHECK(
|
||||
eos::SupportsPartialDerivative<Polytrope, eos::PressureFromSpecificEnthalpy, eos::quantity::SpecificEnthalpy>
|
||||
);
|
||||
STATIC_CHECK(
|
||||
eos::SupportsPartialDerivative<Polytrope, eos::DensityFromSpecificEnthalpy, eos::quantity::SpecificEnthalpy>
|
||||
);
|
||||
|
||||
STATIC_CHECK_FALSE(
|
||||
eos::SupportsPartialDerivative<Polytrope, eos::SpecificEnthalpyFromPressure, eos::quantity::Pressure>
|
||||
);
|
||||
STATIC_CHECK_FALSE(
|
||||
eos::SupportsPartialDerivative<Polytrope, eos::SpecificEnthalpyFromDensity, eos::quantity::Density>
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Polytropic EOS Typed Relations Preserve Analytic Values",
|
||||
tags::polytropic_eos_characterization
|
||||
) {
|
||||
constexpr std::array<double, 3> polytropicIndices{1.0, 1.5, 3.0};
|
||||
constexpr std::array<double, 2> polytropicConstants{0.25, 0.73};
|
||||
constexpr std::array<double, 4> densities{0.0, 1.0e-6, 0.2, 2.0};
|
||||
constexpr std::array<double, 4> specificEnthalpies{-0.3, 0.0, 0.2, 1.7};
|
||||
constexpr std::array<double, 4> pressures{0.0, 1.0e-8, 0.3, 4.0};
|
||||
|
||||
for (const double polytropicIndex : polytropicIndices) {
|
||||
for (const double polytropicConstant : polytropicConstants) {
|
||||
const eos::Polytrope equationOfState(polytropicIndex, polytropicConstant);
|
||||
|
||||
for (const double density : densities) {
|
||||
CAPTURE(polytropicIndex, polytropicConstant, density);
|
||||
|
||||
const double expectedPressure = polytropicConstant * std::pow(density, 1.0 + 1.0 / polytropicIndex);
|
||||
const double expectedSpecificEnthalpy =
|
||||
(polytropicIndex + 1.0) * polytropicConstant * std::pow(density, 1.0 / polytropicIndex);
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::Pressure>(equationOfState, eos::DensityValue{density}).value() ==
|
||||
expectedPressure
|
||||
);
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::SpecificEnthalpy>(equationOfState, eos::DensityValue{density})
|
||||
.value() == expectedSpecificEnthalpy
|
||||
);
|
||||
|
||||
CHECK_THAT(
|
||||
(eos::partialDerivative<eos::quantity::Pressure, eos::quantity::Density>(
|
||||
equationOfState, eos::DensityValue{density}
|
||||
)
|
||||
.value()),
|
||||
Catch::Matchers::WithinRel(
|
||||
density == 0.0 ? 0.0 : expectedSpecificEnthalpy / polytropicIndex, 2.0e-15
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
for (const double specificEnthalpy : specificEnthalpies) {
|
||||
CAPTURE(polytropicIndex, polytropicConstant, specificEnthalpy);
|
||||
|
||||
const double expectedDensity =
|
||||
specificEnthalpy <= 0.0
|
||||
? 0.0
|
||||
: std::pow(specificEnthalpy / ((polytropicIndex + 1.0) * polytropicConstant), polytropicIndex);
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::Density>(equationOfState, eos::SpecificEnthalpyValue{specificEnthalpy})
|
||||
.value() == expectedDensity
|
||||
);
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::Pressure>(
|
||||
equationOfState, eos::SpecificEnthalpyValue{specificEnthalpy}
|
||||
)
|
||||
.value() ==
|
||||
(specificEnthalpy <= 0.0 ? 0.0 : expectedDensity * specificEnthalpy / (polytropicIndex + 1.0))
|
||||
);
|
||||
|
||||
CHECK(
|
||||
(eos::partialDerivative<eos::quantity::Pressure, eos::quantity::SpecificEnthalpy>(
|
||||
equationOfState, eos::SpecificEnthalpyValue{specificEnthalpy}
|
||||
)
|
||||
.value() == expectedDensity)
|
||||
);
|
||||
}
|
||||
|
||||
for (const double pressure : pressures) {
|
||||
CAPTURE(polytropicIndex, polytropicConstant, pressure);
|
||||
|
||||
const double indexPlusOne = polytropicIndex + 1.0;
|
||||
const double expectedSpecificEnthalpy = indexPlusOne *
|
||||
std::pow(polytropicConstant, polytropicIndex / indexPlusOne) *
|
||||
std::pow(pressure, 1.0 / indexPlusOne);
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::SpecificEnthalpy>(equationOfState, eos::PressureValue{pressure})
|
||||
.value() == expectedSpecificEnthalpy
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Typed Polytropic EOS Preserves Domain And Exterior Semantics",
|
||||
tags::polytropic_eos_relation_contract
|
||||
) {
|
||||
const eos::Polytrope equationOfState(3.0, 0.75);
|
||||
|
||||
try {
|
||||
static_cast<void>(eos::evaluate<eos::quantity::Pressure>(equationOfState, eos::DensityValue{-0.1}));
|
||||
FAIL("A negative density must be rejected.");
|
||||
} catch (const eos::EvaluationError &error) {
|
||||
CHECK(error.code() == eos::EvaluationErrorCode::outside_domain);
|
||||
}
|
||||
|
||||
try {
|
||||
static_cast<void>(eos::evaluate<eos::quantity::SpecificEnthalpy>(
|
||||
equationOfState, eos::PressureValue{std::numeric_limits<double>::quiet_NaN()}
|
||||
));
|
||||
FAIL("A nonfinite pressure must be rejected.");
|
||||
} catch (const eos::EvaluationError &error) {
|
||||
CHECK(error.code() == eos::EvaluationErrorCode::nonfinite_input);
|
||||
}
|
||||
|
||||
constexpr double exteriorSpecificEnthalpy = -0.3;
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::Density>(equationOfState, eos::SpecificEnthalpyValue{exteriorSpecificEnthalpy})
|
||||
.value() == 0.0
|
||||
);
|
||||
|
||||
CHECK(
|
||||
eos::evaluate<eos::quantity::Pressure>(equationOfState, eos::SpecificEnthalpyValue{exteriorSpecificEnthalpy})
|
||||
.value() == 0.0
|
||||
);
|
||||
|
||||
CHECK(
|
||||
(eos::partialDerivative<eos::quantity::Density, eos::quantity::SpecificEnthalpy>(
|
||||
equationOfState, eos::SpecificEnthalpyValue{exteriorSpecificEnthalpy}
|
||||
)
|
||||
.value() == 0.0)
|
||||
);
|
||||
|
||||
CHECK(
|
||||
(eos::partialDerivative<eos::quantity::Pressure, eos::quantity::SpecificEnthalpy>(
|
||||
equationOfState, eos::SpecificEnthalpyValue{exteriorSpecificEnthalpy}
|
||||
)
|
||||
.value() == 0.0)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user