Files
MeanField_SERiF/tests/discritization/domain/mesh_topology.cpp
Emily Boudreaux cb20faeb3d test(tests): added test suite
The test suite is extensive. Note that LLMs were used to aid in the development of the test suite. All LLM generated code was manually reviewed.
2026-11-09 13:53:17 -05:00

60 lines
2.8 KiB
C++

#include <vector>
#include <catch2/catch_test_macros.hpp>
#include "serif/discretization/domain/mesh/topology.hpp"
#include "serif/discretization/domain/schema/schemas.hpp"
#include "serif/discretization/domain/schema/validation/all.hpp"
namespace {
namespace domain = serif::discretization::domain;
/** @brief Represent the core, envelope, vacuum and their interfaces without a finite-element backend. */
[[nodiscard]] domain::mesh::MeshTopologyData layered_topology() {
return {
.elementDomainIDs = {1, 2, 3},
.faceElements = {{.firstElementID = 0, .secondElementID = 1}, {.firstElementID = 1, .secondElementID = 2}, {.firstElementID = 2}},
.boundaryElementBoundaryIDs = {1, 2},
.boundaryElementFaceIDs = {1, 2}
};
}
}
TEST_CASE("Physical schema validation uses backend-independent mesh connectivity", "[unit][discretization][domain]") {
const domain::mesh::MeshTopology topology(layered_topology());
const auto result = domain::schema::validation::validate_schema<domain::schema::CoreEnvelopeVacuumDomainSchema>(topology);
REQUIRE(result);
CHECK(result.relation_count() == 7);
CHECK(topology.element_neighbors(0) == std::vector<int>{1});
CHECK((topology.element_neighbors(1) == std::vector<int>{0, 2}));
CHECK(topology.boundary_elements_on_face(1) == std::vector<int>{0});
CHECK(topology.boundary_element_face(1) == 2);
CHECK(topology.face_elements(2).secondElementID == -1);
}
TEST_CASE("Neutral topology rejects invalid indexing before deriving adjacency", "[unit][discretization][domain]") {
domain::mesh::MeshTopologyData data = layered_topology();
SECTION("A face names an absent volume element") {
data.faceElements.front().firstElementID = 3;
}
SECTION("Boundary labels and faces have different counts") {
data.boundaryElementFaceIDs.pop_back();
}
SECTION("A boundary names an absent face") {
data.boundaryElementFaceIDs.front() = 3;
}
CHECK_THROWS(domain::mesh::MeshTopology(data));
}
TEST_CASE("Neutral topology retains unresolved and multiply labelled boundary faces", "[unit][discretization][domain]") {
domain::mesh::MeshTopologyData data = layered_topology();
data.boundaryElementBoundaryIDs.insert(data.boundaryElementBoundaryIDs.end(), {7, 8});
data.boundaryElementFaceIDs.insert(data.boundaryElementFaceIDs.end(), {1, -1});
const domain::mesh::MeshTopology topology(data);
CHECK((topology.boundary_elements_on_face(1) == std::vector<int>{0, 2}));
CHECK(topology.boundary_element_face(3) == -1);
CHECK(topology.boundary_element_boundary_id(3) == 8);
CHECK(topology.element_neighbors(-1).empty());
CHECK(topology.boundary_elements_on_face(100).empty());
CHECK(topology.element_domain_id(100) == 0);
}