Files
MeanField_SERiF/tests/preconditioner/layout.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

103 lines
4.3 KiB
C++

#include <array>
#include <limits>
#include <catch2/catch_test_macros.hpp>
#include "serif/discretization/blocks/vector_view.hpp"
#include "serif/operators/linearized_system_view.hpp"
#include "serif/utils/dependencies/dependencies.hpp"
namespace
{
namespace blocks = serif::discretization::blocks;
namespace dependencies = serif::utils::dependencies;
using Kind = blocks::RepresentedValueKind;
struct Density
{
};
struct Shape
{
};
struct Gradient
{
};
struct Potential
{
};
struct Enthalpy
{
};
struct MassConstraint
{
};
struct CentralConstraint
{
};
using Values = dependencies::KeyList<Density, Shape, Gradient, Potential, Enthalpy, MassConstraint, CentralConstraint>;
using Residuals = dependencies::KeyList<Gradient, Potential, Density, Shape, Enthalpy, MassConstraint, CentralConstraint>;
using Layout = blocks::SystemLayout<Values, Residuals>;
} // namespace
TEST_CASE("System layout preserves every uneven physical block in independent state and residual orders", "[preconditioner][layout][unit]")
{
// The original equilibrium_coordinates.cpp fixture deliberately totals 22 on both sides with different orders.
const Layout layout{.state_sizes = {2, 3, 4, 5, 6, 1, 1}, .residual_sizes = {4, 5, 2, 3, 6, 1, 1}};
CHECK(layout.total_size<Kind::value>() == 22);
CHECK(layout.total_size<Kind::residual>() == 22);
CHECK(layout.offset<Kind::value, Density>() == 0);
CHECK(layout.offset<Kind::residual, Density>() == 9);
CHECK(layout.offset<Kind::value, Enthalpy>() == 14);
CHECK(layout.offset<Kind::residual, Enthalpy>() == 14);
CHECK(layout.offset<Kind::value, MassConstraint>() == 20);
CHECK(layout.offset<Kind::value, CentralConstraint>() == 21);
std::array<double, 22> values{}, residuals{};
for (std::size_t index = 0; index < values.size(); ++index)
{
values[index] = 100.0 + index;
residuals[index] = -200.0 - index;
}
const blocks::StateView<Layout> state(layout, values);
const blocks::ResidualView<Layout, const double> residual(layout, residuals);
CHECK(state.get<Density>().data() == values.data());
CHECK(state.get<Enthalpy>().data() == values.data() + 14);
CHECK(residual.get<Density>().data() == residuals.data() + 9);
CHECK(residual.get<Gradient>().data() == residuals.data());
state.get<MassConstraint>()[0] = 5.0;
state.get<CentralConstraint>()[0] = 7.0;
CHECK(values[20] == 5.0);
CHECK(values[21] == 7.0);
CHECK(residual.get<Density>()[0] == -209.0);
}
TEST_CASE("Block vector views reject mismatched storage and overflowing coordinate metadata", "[preconditioner][layout][validation]")
{
Layout layout{.state_sizes = {2, 3, 4, 5, 6, 1, 1}, .residual_sizes = {4, 5, 2, 3, 6, 1, 1}};
std::array<double, 21> short_values{};
CHECK_THROWS(blocks::StateView<Layout>(layout, short_values));
std::array<double, 22> values{};
blocks::StateView<Layout> state(layout, values);
layout.state_sizes[0] = 23;
CHECK_THROWS(state.get<Density>());
layout.state_sizes[0] = std::numeric_limits<std::size_t>::max();
CHECK_THROWS(layout.total_size<Kind::value>());
CHECK_THROWS(layout.offset<Kind::value, Gradient>());
CHECK_THROWS(blocks::StateView<Layout>(layout, values));
const blocks::SystemLayout<dependencies::KeyList<>, dependencies::KeyList<>> empty{};
CHECK(empty.total_size<Kind::value>() == 0);
CHECK(empty.total_size<Kind::residual>() == 0);
}
TEST_CASE("Linearized system views borrow the declared physical blocks without changing their identity", "[preconditioner][layout][unit]")
{
using DensityBlock = serif::operators::PhysicalBlock<Density, Density>;
using SurfaceBlock = serif::operators::PhysicalBlock<Shape, Enthalpy>;
const Layout layout{.state_sizes = {2, 3, 4, 5, 6, 1, 1}, .residual_sizes = {4, 5, 2, 3, 6, 1, 1}};
const auto sources = dependencies::make_dependency_context(dependencies::own<DensityBlock>(std::array{2.0, 3.0}), dependencies::own<SurfaceBlock>(std::array{5.0, 7.0}));
const serif::operators::LinearizedSystemView system(layout, sources);
CHECK(&system.layout() == &layout);
CHECK(&system.blocks() == &sources);
CHECK(&system.block<Density, Density>() == &sources.get<DensityBlock>());
CHECK(&system.block<Shape, Enthalpy>() == &sources.get<SurfaceBlock>());
}