Files
Emily Boudreaux d1f59d6d70 feat(mean_field): added dimensions, discritization, and start of eos
The full rewrite of mean_field into something maintainable is progressing. dimensions is mostly done, discritization (domain, blocks, and fields) is done, and eos is progressing quickly
2026-09-15 10:42:00 -04:00

183 lines
7.1 KiB
C++

#include <array>
#include <cstddef>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <mfem.hpp>
#include <stroid/stroid.h>
#include "serif/discretization/domain/schema/schemas.hpp"
#include "serif/discretization/domain/schema/validation/all.hpp"
#include "serif/tests/test_tags.hpp"
#include "serif/tests/discritization/domain/domain_test_utils.hpp"
namespace domain = serif::discretization::domain;
namespace schema = domain::schema;
namespace schema_validation = schema::validation;
TEST_CASE(
"Complete Schema Validation Accepts A Synthetic Core Envelope Vacuum Mesh",
tags::unit &tags::mesh &tags::utils &tags::domain
) {
const mfem::Mesh mesh = domain_test_utils::make_layered_mesh();
const auto validation =
schema_validation::validate_schema<schema::CoreEnvelopeVacuumDomainSchema>(mesh);
REQUIRE(validation.valid());
REQUIRE(validation.relationResults.size() == 7);
CHECK(validation.failed_relation_count() == 0);
CHECK(validation.passed_relation_count() == 7);
CHECK_FALSE(validation.first_failed_relation_index().has_value());
constexpr std::array<std::string_view, 7> expectedRelationNames{"fully_connected", "fully_connected",
"fully_connected", "inscribed",
"inscribed", "domain_boundary",
"domain_boundary"};
for (std::size_t relationIndex = 0; relationIndex < expectedRelationNames.size(); ++relationIndex) {
CHECK(validation.relationResults[relationIndex].relationIndex == relationIndex);
CHECK(validation.relationResults[relationIndex].relationName == expectedRelationNames[relationIndex]);
CHECK(validation.relationResults[relationIndex].valid());
}
}
TEST_CASE(
"Complete Schema Validation Evaluates Every Relation After A Failure",
tags::unit &tags::mesh &tags::utils &tags::domain
) {
/*
* All material topology and the outer vacuum boundary are valid.
* Only the Stellar/Vacuum boundary tagging is intentionally absent.
*/
const mfem::Mesh mesh = domain_test_utils::make_layered_mesh(false, true);
const auto validation =
schema_validation::validate_schema<schema::CoreEnvelopeVacuumDomainSchema>(mesh);
CHECK_FALSE(validation.valid());
REQUIRE(validation.relationResults.size() == 7);
CHECK(validation.failed_relation_count() == 1);
CHECK(validation.passed_relation_count() == 6);
REQUIRE(validation.first_failed_relation_index().has_value());
CHECK(*validation.first_failed_relation_index() == 5);
for (std::size_t relationIndex = 0; relationIndex < 7; ++relationIndex) {
CAPTURE(relationIndex);
if (relationIndex == 5) {
CHECK_FALSE(validation.relationResults[relationIndex].valid());
CHECK(
validation.relationResults[relationIndex].result.failure ==
schema_validation::RelationValidationFailure::DomainBoundaryExpectedFaceIsUntagged
);
continue;
}
CHECK(validation.relationResults[relationIndex].valid());
}
}
TEST_CASE(
"STROID Meshes Satisfy The Core Envelope Vacuum Domain Schema",
tags::integration &tags::mesh &tags::utils &tags::domain
) {
constexpr std::array<domain_test_utils::StroidCase, 3> testCases{
domain_test_utils::StroidCase{
.name = "spherical_low_order", .refinementLevels = 0, .order = 1, .flattening = 0.0
},
domain_test_utils::StroidCase{.name = "oblate", .refinementLevels = 0, .order = 2, .flattening = 0.15},
domain_test_utils::StroidCase{.name = "refined_oblate", .refinementLevels = 1, .order = 2, .flattening = 0.10}
};
for (const auto &[name, refinementLevels, order, flattening] : testCases) {
INFO("STROID case = " << name);
INFO("Refinement levels = " << refinementLevels);
INFO("Order = " << order);
INFO("Flattening = " << flattening);
const stroid::config::MeshConfig config = domain_test_utils::make_stroid_config(refinementLevels, order, flattening);
stroid::StroidMesh stroidMesh = stroid::GenerateMesh(config);
REQUIRE(stroidMesh.reference_mesh != nullptr);
REQUIRE(stroidMesh.mesh != nullptr);
/*
* Validate both the reference topology and the projected
* physical mesh. The mapping/projection must not alter
* material or boundary semantics.
*/
domain_test_utils::check_schema_is_valid<schema::CoreEnvelopeVacuumDomainSchema>(
*stroidMesh.reference_mesh
);
domain_test_utils::check_schema_is_valid<schema::CoreEnvelopeVacuumDomainSchema>(
*stroidMesh.mesh
);
}
}
TEST_CASE(
"STROID Material And Boundary Id Conventions Are Fully Schema Driven",
tags::integration &tags::mesh &tags::utils &tags::domain
) {
stroid::config::MeshConfig config = domain_test_utils::make_stroid_config(0, 1, 0.0);
config.core_id = 11;
config.envelope_id = 17;
config.vacuum_id = 29;
config.surface_bdr_id = 101;
config.inf_bdr_id = 203;
stroid::StroidMesh stroidMesh = stroid::GenerateMesh(config);
REQUIRE(stroidMesh.reference_mesh != nullptr);
REQUIRE(stroidMesh.mesh != nullptr);
/*
* The same semantic topology must validate when a mesh generator
* uses an entirely different attribute numbering convention.
*/
domain_test_utils::check_schema_is_valid<domain_test_utils::AlternateIdSchema>(*stroidMesh.reference_mesh);
domain_test_utils::check_schema_is_valid<domain_test_utils::AlternateIdSchema>(*stroidMesh.mesh);
/*
* Conversely, the production 1/2/3 + 1/2 schema must not silently
* accept a mesh generated under another numbering convention.
*/
const auto productionValidation =
schema_validation::validate_schema<schema::CoreEnvelopeVacuumDomainSchema>(*stroidMesh.mesh);
CHECK_FALSE(productionValidation.valid());
CHECK(productionValidation.failed_relation_count() > 0);
}
TEST_CASE(
"Complete Schema Validation Rejects A Mesh Without Vacuum",
tags::unit &tags::mesh &tags::utils &tags::domain
) {
const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(3, 3, {2, 2, 2, 2, 1, 2, 2, 2, 2}, {});
const auto validation = schema_validation::validate_schema<schema::CoreEnvelopeVacuumDomainSchema>(mesh);
CHECK_FALSE(validation.valid());
REQUIRE(validation.relationResults.size() == 7);
/*
* FullyConnected<VacuumDomain>
*/
CHECK_FALSE(validation.relationResults[2].valid());
CHECK(
validation.relationResults[2].result.failure ==
schema_validation::RelationValidationFailure::DomainAbsent
);
/*
* Inscribed<StellarDomains, VacuumDomain>
*/
CHECK_FALSE(validation.relationResults[4].valid());
CHECK(
validation.relationResults[4].result.failure ==
schema_validation::RelationValidationFailure::OuterDomainAbsent
);
}