feat(surface): surface deformation prescriptions
restricted the unknown state vector to surface deformation and implemented one prescription, NodalRadialSurface, while the full volumetric displacment field is reconstructed analytically from that. This reduced the number of degrees of freedom in the system by a factor of 80 while also removing many null vectors from the system.
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
import mean_field;
|
||||
import test_helpers;
|
||||
|
||||
@@ -96,19 +98,18 @@ namespace {
|
||||
} // namespace
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Owns Structure And Surface Prescriptions",
|
||||
tags::stellar_model_type_contract
|
||||
"Stellar Model Owns Structure Prescription And Surface Condition",
|
||||
tags::stellar_model_type_contract &tags::surface_condition_type_contract
|
||||
) {
|
||||
STATIC_CHECK(mean_field::models::StructurePrescription<mean_field::models::structure::PolytropicStructure>);
|
||||
STATIC_CHECK(mean_field::models::StructurePrescription<StellarModelTestStructure>);
|
||||
STATIC_CHECK_FALSE(mean_field::models::StructurePrescription<StructureWithoutSeed>);
|
||||
|
||||
STATIC_CHECK(
|
||||
mean_field::models::SurfacePrescription<
|
||||
mean_field::surface::ConstantPressureSurface, mean_field::eos::Polytrope>
|
||||
mean_field::models::SurfaceCondition<mean_field::surface::ConstantPressureSurface, mean_field::eos::Polytrope>
|
||||
);
|
||||
STATIC_CHECK_FALSE(
|
||||
mean_field::models::SurfacePrescription<SurfaceWithoutPhysicalQuantity, mean_field::eos::Polytrope>
|
||||
mean_field::models::SurfaceCondition<SurfaceWithoutPhysicalQuantity, mean_field::eos::Polytrope>
|
||||
);
|
||||
|
||||
STATIC_CHECK_FALSE(std::derived_from<StellarModelTestStructure, mean_field::models::structure::StructureBase>);
|
||||
@@ -141,14 +142,68 @@ TEST_CASE(
|
||||
decltype(model.structurePrescription()), const mean_field::models::structure::PolytropicStructure &>
|
||||
);
|
||||
STATIC_CHECK(
|
||||
std::same_as<decltype(model.surfacePrescription()), const mean_field::surface::ConstantPressureSurface &>
|
||||
std::same_as<decltype(model.surfaceCondition()), const mean_field::surface::ConstantPressureSurface &>
|
||||
);
|
||||
STATIC_CHECK(std::same_as<decltype(model.equationOfState()), const mean_field::eos::Polytrope &>);
|
||||
STATIC_CHECK(
|
||||
std::same_as<
|
||||
typename PolytropicStellarModel::SurfaceDeformationPrescriptionType,
|
||||
mean_field::deformation::NodalRadialSurface>
|
||||
);
|
||||
STATIC_CHECK(
|
||||
std::same_as<
|
||||
typename PolytropicStellarModel::StellarInteriorDeformationExtensionType,
|
||||
mean_field::deformation::PowerLawRadialInteriorExtension>
|
||||
);
|
||||
STATIC_CHECK(
|
||||
std::same_as<
|
||||
typename PolytropicStellarModel::VacuumDeformationExtensionType,
|
||||
mean_field::deformation::FixedInfinityRadialVacuumExtension>
|
||||
);
|
||||
|
||||
CHECK(model.targetMass() == 1.0);
|
||||
CHECK(model.compiledSurfaceConstraint().targetPressure() == mean_field::eos::PressureValue{0.0});
|
||||
CHECK(&model.equationOfState() == &model.structurePrescription().equationOfState());
|
||||
CHECK(model.surfacePrescription().targetPressure() == mean_field::eos::PressureValue{0.0});
|
||||
CHECK(model.surfaceCondition().targetPressure() == mean_field::eos::PressureValue{0.0});
|
||||
CHECK(model.surfaceDeformationPrescription().descriptor().name == "NodalRadialSurface");
|
||||
CHECK(model.stellarInteriorDeformationExtension().radialPower() == 2.0);
|
||||
CHECK(model.vacuumDeformationExtension().descriptor().name == "FixedInfinityRadialVacuumExtension");
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Owns Explicit Surface Interior And Vacuum Deformation Policies",
|
||||
tags::stellar_model_deformation_ownership
|
||||
) {
|
||||
mfem::Vector referenceCenter(3);
|
||||
referenceCenter(0) = 0.125;
|
||||
referenceCenter(1) = -0.25;
|
||||
referenceCenter(2) = 0.375;
|
||||
|
||||
mean_field::models::StellarModel model{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.0},
|
||||
mean_field::surface::ConstantPressureSurface{mean_field::eos::PressureValue{0.0}},
|
||||
mean_field::deformation::NodalRadialSurface{referenceCenter},
|
||||
mean_field::deformation::PowerLawRadialInteriorExtension{3.0},
|
||||
mean_field::deformation::FixedInfinityRadialVacuumExtension{}
|
||||
};
|
||||
|
||||
CHECK(model.surfaceDeformationPrescription().referenceCenter()(0) == referenceCenter(0));
|
||||
CHECK(model.surfaceDeformationPrescription().referenceCenter()(1) == referenceCenter(1));
|
||||
CHECK(model.surfaceDeformationPrescription().referenceCenter()(2) == referenceCenter(2));
|
||||
CHECK(model.stellarInteriorDeformationExtension().radialPower() == 3.0);
|
||||
CHECK(
|
||||
model.vacuumDeformationExtension().descriptor().outerBoundaryBehavior ==
|
||||
mean_field::deformation::VacuumOuterBoundaryBehavior::FixedAtReferenceInfinity
|
||||
);
|
||||
|
||||
const auto *surfaceDeformationAddress = &model.surfaceDeformationPrescription();
|
||||
const auto *interiorDeformationAddress = &model.stellarInteriorDeformationExtension();
|
||||
const auto *vacuumDeformationAddress = &model.vacuumDeformationExtension();
|
||||
auto movedModel = std::move(model);
|
||||
|
||||
CHECK(&movedModel.surfaceDeformationPrescription() == surfaceDeformationAddress);
|
||||
CHECK(&movedModel.stellarInteriorDeformationExtension() == interiorDeformationAddress);
|
||||
CHECK(&movedModel.vacuumDeformationExtension() == vacuumDeformationAddress);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
@@ -184,7 +239,7 @@ TEST_CASE(
|
||||
|
||||
const mean_field::models::structure::PolytropicStructure *structureAddress = &originalModel.structurePrescription();
|
||||
|
||||
const mean_field::surface::ConstantPressureSurface *surfaceAddress = &originalModel.surfacePrescription();
|
||||
const mean_field::surface::ConstantPressureSurface *surfaceAddress = &originalModel.surfaceCondition();
|
||||
|
||||
const mean_field::eos::Polytrope *equationOfStateAddress = &originalModel.equationOfState();
|
||||
|
||||
@@ -193,7 +248,7 @@ TEST_CASE(
|
||||
mean_field::models::StellarModel movedModel{std::move(originalModel)};
|
||||
|
||||
CHECK(&movedModel.structurePrescription() == structureAddress);
|
||||
CHECK(&movedModel.surfacePrescription() == surfaceAddress);
|
||||
CHECK(&movedModel.surfaceCondition() == surfaceAddress);
|
||||
CHECK(&movedModel.equationOfState() == equationOfStateAddress);
|
||||
CHECK(&movedModel.compiledSurfaceConstraint() == compiledSurfaceConstraintAddress);
|
||||
CHECK(movedModel.targetMass() == 1.0);
|
||||
@@ -221,7 +276,7 @@ TEST_CASE(
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Supports Custom Structure And Surface Prescriptions",
|
||||
"Stellar Model Supports Custom Structure Prescriptions And Surface Conditions",
|
||||
tags::barotrope &tags::unit &tags::model
|
||||
) {
|
||||
const auto tracker = std::make_shared<StellarModelExtensionTracker>();
|
||||
@@ -261,9 +316,12 @@ TEST_CASE(
|
||||
const mean_field::models::structure::PolytropicStructure *sourceStructureAddress =
|
||||
&sourceModel.structurePrescription();
|
||||
|
||||
const mean_field::surface::ConstantPressureSurface *sourceSurfaceAddress = &sourceModel.surfacePrescription();
|
||||
const mean_field::surface::ConstantPressureSurface *sourceSurfaceAddress = &sourceModel.surfaceCondition();
|
||||
|
||||
const mean_field::eos::Polytrope *sourceEquationOfStateAddress = &sourceModel.equationOfState();
|
||||
const auto *sourceSurfaceDeformationAddress = &sourceModel.surfaceDeformationPrescription();
|
||||
const auto *sourceInteriorDeformationAddress = &sourceModel.stellarInteriorDeformationExtension();
|
||||
const auto *sourceVacuumDeformationAddress = &sourceModel.vacuumDeformationExtension();
|
||||
|
||||
const mean_field::eos::PressureValue sourceTargetPressure =
|
||||
sourceModel.compiledSurfaceConstraint().targetPressure();
|
||||
@@ -272,10 +330,16 @@ TEST_CASE(
|
||||
|
||||
CHECK(&destinationModel.structurePrescription() == sourceStructureAddress);
|
||||
|
||||
CHECK(&destinationModel.surfacePrescription() == sourceSurfaceAddress);
|
||||
CHECK(&destinationModel.surfaceCondition() == sourceSurfaceAddress);
|
||||
|
||||
CHECK(&destinationModel.equationOfState() == sourceEquationOfStateAddress);
|
||||
|
||||
CHECK(&destinationModel.surfaceDeformationPrescription() == sourceSurfaceDeformationAddress);
|
||||
|
||||
CHECK(&destinationModel.stellarInteriorDeformationExtension() == sourceInteriorDeformationAddress);
|
||||
|
||||
CHECK(&destinationModel.vacuumDeformationExtension() == sourceVacuumDeformationAddress);
|
||||
|
||||
CHECK(destinationModel.targetMass() == 1.25);
|
||||
|
||||
CHECK(destinationModel.compiledSurfaceConstraint().targetPressure() == sourceTargetPressure);
|
||||
@@ -307,6 +371,13 @@ TEST_CASE(
|
||||
CHECK(views[0].targetMass() == 1.0);
|
||||
CHECK(views[1].targetMass() == 2.5);
|
||||
CHECK(views[1].surfaceCondition().targetPressure == 0.375);
|
||||
CHECK(views[0].surfaceDeformation().name == "NodalRadialSurface");
|
||||
CHECK(views[0].surfaceDeformation().motionKind == mean_field::deformation::SurfaceMotionKind::Radial);
|
||||
CHECK(views[0].stellarInteriorDeformation().name == "PowerLawRadialInteriorExtension");
|
||||
CHECK(
|
||||
views[0].vacuumDeformation().outerBoundaryBehavior ==
|
||||
mean_field::deformation::VacuumOuterBoundaryBehavior::FixedAtReferenceInfinity
|
||||
);
|
||||
REQUIRE(views[1].surfaceDependencies().stateFields.size() == 1);
|
||||
CHECK(
|
||||
views[1].surfaceDependencies().residualRowField ==
|
||||
@@ -350,6 +421,9 @@ TEST_CASE(
|
||||
|
||||
REQUIRE(pressure.has_value());
|
||||
CHECK(view.targetMass() == movedModel.targetMass());
|
||||
CHECK(view.surfaceDeformation() == movedModel.surfaceDeformationPrescription().descriptor());
|
||||
CHECK(view.stellarInteriorDeformation() == movedModel.stellarInteriorDeformationExtension().descriptor());
|
||||
CHECK(view.vacuumDeformation() == movedModel.vacuumDeformationExtension().descriptor());
|
||||
CHECK(
|
||||
pressure->value() == mean_field::eos::evaluate<mean_field::eos::quantity::Pressure>(
|
||||
movedModel.equationOfState(), mean_field::eos::DensityValue{0.7}
|
||||
@@ -358,3 +432,48 @@ TEST_CASE(
|
||||
);
|
||||
CHECK(seed.radius.Size() == 8);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Stellar Model Compiles Its Deformation Policies Against The Finite Element Discretization",
|
||||
tags::stellar_model_deformation_compilation
|
||||
) {
|
||||
mean_field::utils::Args args = test_utils::setup_args();
|
||||
mean_field::fem::FEM fem = mean_field::fem::setup_fem(args.mesh_file, args, 0);
|
||||
REQUIRE(fem.okay());
|
||||
|
||||
mfem::Vector referenceCenter(fem.mesh->SpaceDimension());
|
||||
referenceCenter = 0.0;
|
||||
const mean_field::models::StellarModel model{
|
||||
mean_field::models::structure::PolytropicStructure{mean_field::eos::Polytrope{3.0, 0.25}, 1.0},
|
||||
mean_field::surface::ConstantPressureSurface{mean_field::eos::PressureValue{0.0}},
|
||||
mean_field::deformation::NodalRadialSurface{referenceCenter},
|
||||
mean_field::deformation::PowerLawRadialInteriorExtension{3.0},
|
||||
mean_field::deformation::FixedInfinityRadialVacuumExtension{}
|
||||
};
|
||||
|
||||
auto prepared = model.compileDomainDeformation(fem);
|
||||
STATIC_CHECK(mean_field::deformation::PreparedDomainDeformationOperator<decltype(prepared)>);
|
||||
CHECK(prepared.matchesCurrentDiscretization());
|
||||
CHECK(prepared.stellarInteriorExtension().radialPower() == 3.0);
|
||||
CHECK(prepared.discretizationDependencies().physicalMeshIdentity == fem.mesh.get());
|
||||
CHECK(prepared.discretizationDependencies().logicalReferenceMeshIdentity == fem.logicalReferenceMesh.get());
|
||||
CHECK(prepared.parameterCount() == prepared.surfaceDeformationPrescription().parameterCount());
|
||||
CHECK(prepared.volumeDisplacementSize() == fem.displacementFes->GetTrueVSize());
|
||||
|
||||
STATIC_CHECK_FALSE(std::is_copy_constructible_v<mean_field::deformation::PreparedDomainDeformationRuntime>);
|
||||
STATIC_CHECK(std::is_nothrow_move_constructible_v<mean_field::deformation::PreparedDomainDeformationRuntime>);
|
||||
mean_field::deformation::PreparedDomainDeformationRuntime runtime{std::move(prepared)};
|
||||
STATIC_CHECK(mean_field::deformation::PreparedDomainDeformationOperator<decltype(runtime)>);
|
||||
mean_field::deformation::PreparedDomainDeformationRuntime movedRuntime{std::move(runtime)};
|
||||
|
||||
CHECK(movedRuntime.matchesCurrentDiscretization());
|
||||
CHECK(movedRuntime.parameterCount() > 0);
|
||||
CHECK(movedRuntime.volumeDisplacementSize() == fem.displacementFes->GetTrueVSize());
|
||||
CHECK(movedRuntime.compositionReport().assignedScalarDofCount() == fem.surfaceDeformationFes->GetTrueVSize());
|
||||
|
||||
mfem::Vector zeroParameters(movedRuntime.parameterCount());
|
||||
mfem::Vector volumeDisplacement(movedRuntime.volumeDisplacementSize());
|
||||
zeroParameters = 0.0;
|
||||
movedRuntime.buildVolumeDisplacement(zeroParameters, volumeDisplacement);
|
||||
CHECK(volumeDisplacement.Norml2() == 0.0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user