#include #include #include #include "serif/discretization/domain/mesh/topology.hpp" #include "serif/discretization/domain/physical_domains.hpp" #include "serif/discretization/domain/relation/relations.hpp" #include "serif/discretization/domain/relation/validation/runtime.hpp" #include "serif/discretization/domain/schema/schemas.hpp" #include "serif/discretization/domain/schema/validation/boundary.hpp" #include "serif/discretization/domain/types.hpp" #include "serif/tests/test_tags.hpp" #include "serif/tests/discritization/domain/domain_test_utils.hpp" namespace domain = serif::discretization::domain; namespace relation = domain::relation; namespace schema = domain::schema; namespace validation = schema::validation; using domain::mesh::MeshTopology; TEST_CASE( "Domain Boundary Accepts A Complete Internal Stellar Vacuum Interface", tags::unit &tags::mesh &tags::utils &tags::domain ) { std::vector boundaries{{.firstVertexId = 1, .secondVertexId = 4, .attribute = 1}}; const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(2, 1, {2, 3}, boundaries); const MeshTopology topology{mesh}; const auto result = validation::RelationValidator>:: template validate(topology); CHECK(result); /* * Interface ordering is intentionally semantic rather * than oriented. */ const auto reversedResult = validation::RelationValidator>:: template validate(topology); CHECK(reversedResult); } TEST_CASE( "Domain Boundary Accepts A Complete Exterior Vacuum Boundary", tags::unit &tags::mesh &tags::utils &tags::domain ) { const std::vector attributes{3}; std::vector boundaries; domain_test_utils::append_exterior_boundaries( boundaries, attributes, 1, 1, [](const int materialId) { return materialId == 3; }, 2 ); const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(1, 1, attributes, boundaries); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK(result); } TEST_CASE( "Domain Boundary Rejects A Tagged Internal Face For An Exterior Boundary", tags::unit &tags::mesh &tags::utils &tags::domain ) { const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(2, 1, {3, 3}, {{.firstVertexId = 1, .secondVertexId = 4, .attribute = 2}}); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK_FALSE(result); CHECK( result.failure == validation::RelationValidationFailure::DomainBoundaryTaggedFaceHasWrongTopology ); } TEST_CASE( "Domain Boundary Rejects A Tagged Exterior Face Of The Wrong Material", tags::unit &tags::mesh &tags::utils &tags::domain ) { const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(1, 1, {2}, {{.firstVertexId = 0, .secondVertexId = 1, .attribute = 2}}); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK_FALSE(result); CHECK( result.failure == validation::RelationValidationFailure::DomainBoundaryTaggedFaceTouchesUnexpectedDomain ); } TEST_CASE( "Domain Boundary Rejects A Tagged Internal Interface With Unexpected " "Materials", tags::unit &tags::mesh &tags::utils &tags::domain ) { const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(2, 1, {1, 2}, {{.firstVertexId = 1, .secondVertexId = 4, .attribute = 1}}); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK_FALSE(result); CHECK( result.failure == validation::RelationValidationFailure::DomainBoundaryTaggedFaceTouchesUnexpectedDomain ); } TEST_CASE( "Domain Boundary Rejects An Untagged Expected Interface", tags::unit &tags::mesh &tags::utils &tags::domain ) { const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(2, 1, {2, 3}, {}); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK_FALSE(result); CHECK(result.failure == validation::RelationValidationFailure::DomainBoundaryExpectedFaceIsUntagged); REQUIRE(result.domainBoundaryDiagnostics.has_value()); CHECK(result.domainBoundaryDiagnostics->faceID >= 0); CHECK(result.domainBoundaryDiagnostics->boundaryElementID == -1); CHECK_FALSE(result.domainBoundaryDiagnostics->actualBoundaryID.has_value()); } TEST_CASE( "Domain Boundary Rejects An Expected Interface With The Wrong Attribute", tags::unit &tags::mesh &tags::utils &tags::domain ) { const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(2, 1, {2, 3}, {{.firstVertexId = 1, .secondVertexId = 4, .attribute = 9}}); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK_FALSE(result); CHECK( result.failure == validation::RelationValidationFailure::DomainBoundaryExpectedFaceHasWrongID ); REQUIRE(result.domainBoundaryDiagnostics.has_value()); REQUIRE(result.domainBoundaryDiagnostics->actualBoundaryID.has_value()); CHECK(*result.domainBoundaryDiagnostics->actualBoundaryID == 9); CHECK(result.domainBoundaryDiagnostics->expectedBoundaryID == 1); } TEST_CASE( "Domain Boundary Rejects A Relation That Is Not Realized Anywhere", tags::unit &tags::mesh &tags::utils &tags::domain ) { const mfem::Mesh mesh = domain_test_utils::make_grid_mesh(2, 1, {2, 2}, {}); const auto result = validation::RelationValidator>:: template validate(MeshTopology{mesh}); CHECK_FALSE(result); CHECK(result.failure == validation::RelationValidationFailure::DomainBoundaryAbsent); }