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.
103 lines
4.3 KiB
C++
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>());
|
|
}
|