feat(field-support): added field support system, mid migration
currently the barotope and the pressure force operator are migrated to the new support system
This commit is contained in:
259
tests/models/stellar_model.cpp
Normal file
259
tests/models/stellar_model.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
import mean_field;
|
||||
import test_helpers;
|
||||
|
||||
namespace {
|
||||
struct StellarModelExtensionTracker final {
|
||||
int structureValidationCount{0};
|
||||
int surfaceValidationCount{0};
|
||||
int surfaceResolutionCount{0};
|
||||
|
||||
const mean_field::eos::EquationOfState *structureEquationOfState{nullptr};
|
||||
|
||||
const mean_field::eos::EquationOfState *surfaceValidationEquationOfState{nullptr};
|
||||
|
||||
const mean_field::eos::EquationOfState *surfaceResolutionEquationOfState{nullptr};
|
||||
};
|
||||
|
||||
class StellarModelTestStructure final : public mean_field::models::structure::StructureBase {
|
||||
public:
|
||||
explicit StellarModelTestStructure(std::shared_ptr<StellarModelExtensionTracker> tracker)
|
||||
: m_tracker(std::move(tracker)),
|
||||
m_equationOfState(
|
||||
3.0,
|
||||
0.25
|
||||
) {
|
||||
}
|
||||
|
||||
[[nodiscard]] const mean_field::eos::EquationOfState &equationOfState() const noexcept override {
|
||||
m_tracker->structureEquationOfState = &m_equationOfState;
|
||||
return m_equationOfState;
|
||||
}
|
||||
|
||||
[[nodiscard]] double targetMass() const noexcept override {
|
||||
return 2.5;
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::models::structure::StructureSeed
|
||||
makeInitialSeed(const mean_field::models::structure::StructureSeedRequest &request) const override {
|
||||
mean_field::models::structure::StructureSeed seed;
|
||||
|
||||
seed.radius.SetSize(2);
|
||||
seed.density.SetSize(2);
|
||||
seed.enthalpy.SetSize(2);
|
||||
|
||||
seed.radius(0) = 0.0;
|
||||
seed.radius(1) = 1.0;
|
||||
|
||||
seed.density(0) = request.centralDensity;
|
||||
seed.density(1) = 0.0;
|
||||
|
||||
seed.enthalpy(0) = 1.0;
|
||||
seed.enthalpy(1) = 0.0;
|
||||
|
||||
seed.stellarRadius = 1.0;
|
||||
seed.centralDensity = request.centralDensity;
|
||||
seed.centralEnthalpy = 1.0;
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
void validate() const override {
|
||||
++m_tracker->structureValidationCount;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<StellarModelExtensionTracker> m_tracker;
|
||||
mean_field::eos::Polytrope m_equationOfState;
|
||||
};
|
||||
|
||||
class StellarModelTestSurface final : public mean_field::surface::SurfaceBase {
|
||||
public:
|
||||
explicit StellarModelTestSurface(std::shared_ptr<StellarModelExtensionTracker> tracker)
|
||||
: m_tracker(std::move(tracker)) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
mean_field::surface::ResolvedSurfaceCondition
|
||||
resolve(const mean_field::eos::EquationOfState &equationOfState) const override {
|
||||
++m_tracker->surfaceResolutionCount;
|
||||
|
||||
m_tracker->surfaceResolutionEquationOfState = &equationOfState;
|
||||
|
||||
return mean_field::surface::ResolvedSurfaceCondition{0.375};
|
||||
}
|
||||
|
||||
void validate(const mean_field::eos::EquationOfState &equationOfState) const override {
|
||||
++m_tracker->surfaceValidationCount;
|
||||
|
||||
m_tracker->surfaceValidationEquationOfState = &equationOfState;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<StellarModelExtensionTracker> m_tracker;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Owns Structure And Surface Prescriptions",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
STATIC_REQUIRE_FALSE(std::is_copy_constructible_v<mean_field::models::StellarModel>);
|
||||
|
||||
STATIC_REQUIRE_FALSE(std::is_copy_assignable_v<mean_field::models::StellarModel>);
|
||||
|
||||
STATIC_REQUIRE(std::is_nothrow_move_constructible_v<mean_field::models::StellarModel>);
|
||||
|
||||
STATIC_REQUIRE(std::is_nothrow_move_assignable_v<mean_field::models::StellarModel>);
|
||||
|
||||
mean_field::models::StellarModel model{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.0},
|
||||
mean_field::surface::Isobaric{0.0}
|
||||
};
|
||||
|
||||
CHECK(model.targetMass() == 1.0);
|
||||
CHECK(model.resolvedSurfaceCondition().targetEnthalpy == 0.0);
|
||||
|
||||
CHECK(
|
||||
dynamic_cast<const mean_field::models::structure::PolytropicStructure *>(&model.structurePrescription()) !=
|
||||
nullptr
|
||||
);
|
||||
|
||||
CHECK(dynamic_cast<const mean_field::surface::Isobaric *>(&model.surfacePrescription()) != nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Delegates Seed Construction To Its Structure",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
mean_field::models::StellarModel model{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.0},
|
||||
mean_field::surface::Isobaric{}
|
||||
};
|
||||
|
||||
const mean_field::models::structure::StructureSeed seed =
|
||||
model.makeInitialSeed({.centralDensity = 2.0, .radialSampleCount = 64});
|
||||
|
||||
CHECK(seed.radius.Size() == 64);
|
||||
CHECK(seed.density.Size() == 64);
|
||||
CHECK(seed.enthalpy.Size() == 64);
|
||||
CHECK(seed.centralDensity == 2.0);
|
||||
CHECK(seed.stellarRadius > 0.0);
|
||||
CHECK(seed.density(0) == 2.0);
|
||||
CHECK(seed.density(63) == 0.0);
|
||||
CHECK(seed.enthalpy(63) == 0.0);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Moving A Stellar Model Preserves Stable Prescription Addresses",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
mean_field::models::StellarModel originalModel{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.0},
|
||||
mean_field::surface::Isobaric{}
|
||||
};
|
||||
|
||||
const mean_field::models::structure::StructureBase *structureAddress = &originalModel.structurePrescription();
|
||||
|
||||
const mean_field::surface::SurfaceBase *surfaceAddress = &originalModel.surfacePrescription();
|
||||
|
||||
const mean_field::eos::EquationOfState *equationOfStateAddress = &originalModel.equationOfState();
|
||||
|
||||
mean_field::models::StellarModel movedModel{std::move(originalModel)};
|
||||
|
||||
CHECK(&movedModel.structurePrescription() == structureAddress);
|
||||
CHECK(&movedModel.surfacePrescription() == surfaceAddress);
|
||||
CHECK(&movedModel.equationOfState() == equationOfStateAddress);
|
||||
CHECK(movedModel.targetMass() == 1.0);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Resolves A Positive Isobaric Surface",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
constexpr double targetPressure = 0.03125;
|
||||
|
||||
mean_field::models::StellarModel model{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.0},
|
||||
mean_field::surface::Isobaric{targetPressure}
|
||||
};
|
||||
|
||||
const double targetEnthalpy = model.resolvedSurfaceCondition().targetEnthalpy;
|
||||
|
||||
CHECK(targetEnthalpy > 0.0);
|
||||
CHECK(
|
||||
std::abs(model.equationOfState().pressure_from_enthalpy(targetEnthalpy) - targetPressure) <
|
||||
64.0 * std::numeric_limits<double>::epsilon()
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Supports Custom Structure And Surface Prescriptions",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
const auto tracker = std::make_shared<StellarModelExtensionTracker>();
|
||||
|
||||
mean_field::models::StellarModel model{StellarModelTestStructure{tracker}, StellarModelTestSurface{tracker}};
|
||||
|
||||
REQUIRE(tracker->structureValidationCount == 1);
|
||||
REQUIRE(tracker->surfaceValidationCount == 1);
|
||||
REQUIRE(tracker->surfaceResolutionCount == 1);
|
||||
|
||||
CHECK(dynamic_cast<const StellarModelTestStructure *>(&model.structurePrescription()) != nullptr);
|
||||
|
||||
CHECK(dynamic_cast<const StellarModelTestSurface *>(&model.surfacePrescription()) != nullptr);
|
||||
|
||||
const mean_field::eos::EquationOfState *ownedEquationOfState = &model.equationOfState();
|
||||
|
||||
CHECK(tracker->structureEquationOfState == ownedEquationOfState);
|
||||
|
||||
CHECK(tracker->surfaceValidationEquationOfState == ownedEquationOfState);
|
||||
|
||||
CHECK(tracker->surfaceResolutionEquationOfState == ownedEquationOfState);
|
||||
|
||||
CHECK(model.targetMass() == 2.5);
|
||||
|
||||
CHECK(model.resolvedSurfaceCondition().targetEnthalpy == 0.375);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Move Assignment Preserves Stellar Model Prescription Addresses",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
mean_field::models::StellarModel sourceModel{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.25},
|
||||
mean_field::surface::Isobaric{0.0}
|
||||
};
|
||||
|
||||
mean_field::models::StellarModel destinationModel{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{2.0, 0.5}, 4.0},
|
||||
mean_field::surface::Isobaric{0.02}
|
||||
};
|
||||
|
||||
const mean_field::models::structure::StructureBase *sourceStructureAddress = &sourceModel.structurePrescription();
|
||||
|
||||
const mean_field::surface::SurfaceBase *sourceSurfaceAddress = &sourceModel.surfacePrescription();
|
||||
|
||||
const mean_field::eos::EquationOfState *sourceEquationOfStateAddress = &sourceModel.equationOfState();
|
||||
|
||||
const double sourceTargetEnthalpy = sourceModel.resolvedSurfaceCondition().targetEnthalpy;
|
||||
|
||||
destinationModel = std::move(sourceModel);
|
||||
|
||||
CHECK(&destinationModel.structurePrescription() == sourceStructureAddress);
|
||||
|
||||
CHECK(&destinationModel.surfacePrescription() == sourceSurfaceAddress);
|
||||
|
||||
CHECK(&destinationModel.equationOfState() == sourceEquationOfStateAddress);
|
||||
|
||||
CHECK(destinationModel.targetMass() == 1.25);
|
||||
|
||||
CHECK(destinationModel.resolvedSurfaceCondition().targetEnthalpy == sourceTargetEnthalpy);
|
||||
}
|
||||
Reference in New Issue
Block a user