#include #include #include #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; using Residuals = dependencies::KeyList; using Layout = blocks::SystemLayout; } // 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() == 22); CHECK(layout.total_size() == 22); CHECK(layout.offset() == 0); CHECK(layout.offset() == 9); CHECK(layout.offset() == 14); CHECK(layout.offset() == 14); CHECK(layout.offset() == 20); CHECK(layout.offset() == 21); std::array 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 state(layout, values); const blocks::ResidualView residual(layout, residuals); CHECK(state.get().data() == values.data()); CHECK(state.get().data() == values.data() + 14); CHECK(residual.get().data() == residuals.data() + 9); CHECK(residual.get().data() == residuals.data()); state.get()[0] = 5.0; state.get()[0] = 7.0; CHECK(values[20] == 5.0); CHECK(values[21] == 7.0); CHECK(residual.get()[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 short_values{}; CHECK_THROWS(blocks::StateView(layout, short_values)); std::array values{}; blocks::StateView state(layout, values); layout.state_sizes[0] = 23; CHECK_THROWS(state.get()); layout.state_sizes[0] = std::numeric_limits::max(); CHECK_THROWS(layout.total_size()); CHECK_THROWS(layout.offset()); CHECK_THROWS(blocks::StateView(layout, values)); const blocks::SystemLayout, dependencies::KeyList<>> empty{}; CHECK(empty.total_size() == 0); CHECK(empty.total_size() == 0); } TEST_CASE("Linearized system views borrow the declared physical blocks without changing their identity", "[preconditioner][layout][unit]") { using DensityBlock = serif::operators::PhysicalBlock; using SurfaceBlock = serif::operators::PhysicalBlock; 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(std::array{2.0, 3.0}), dependencies::own(std::array{5.0, 7.0})); const serif::operators::LinearizedSystemView system(layout, sources); CHECK(&system.layout() == &layout); CHECK(&system.blocks() == &sources); CHECK(&system.block() == &sources.get()); CHECK(&system.block() == &sources.get()); }