#include #include #include #include #include #include "mfem/linalg/densemat.hpp" #include "serif/backend/mfem/solver/preconditioner/coupling.hpp" #include "serif/backend/mfem/solver/preconditioner/inverse/diagonal.hpp" namespace { namespace backend = serif::solver::preconditioner::backend::mfem; using Order = serif::solver::preconditioner::strategies::coupling::CouplingOrder; /** @brief Express the original small physical couplings in row-major order. */ std::shared_ptr matrix(const int rows, const int columns, const std::initializer_list entries) { REQUIRE(entries.size() == static_cast(rows * columns)); auto result = std::make_shared(rows, columns); auto entry = entries.begin(); for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) { (*result)(row, column) = *entry++; } } return result; } /** @brief Prepare the original signed scalar inverse without another test-only numerical implementation. */ backend::Inverse scalar_inverse(const double diagonal) { const auto inverse = backend::try_diagonal_inverse(std::array{diagonal}); REQUIRE(inverse); return *inverse; } } // namespace TEST_CASE("Generic coupling preserves the original material-gravity factorization tolerances", "[preconditioner][parity][unit]") { const auto material = scalar_inverse(2.0); const auto gravity = scalar_inverse(5.0); const backend::TwoBlockCouplings cross{.first_from_second = matrix(1, 1, {7.0}), .second_from_first = matrix(1, 1, {3.0})}; const std::array orders{Order::independent, Order::second_then_first, Order::lower_diagonal_upper}; const std::array, 3> expected{{{5.5, 2.6}, {-3.6, 2.6}, {7.95, -0.7}}}; mfem::Vector rhs(2), result(2); rhs[0] = 11.0; rhs[1] = 13.0; for (std::size_t policy = 0; policy < orders.size(); ++policy) { const auto inverse = backend::try_coupled_inverse(material, gravity, cross, orders[policy]); REQUIRE(inverse); inverse->action->Mult(rhs, result); CHECK(result[0] == Catch::Approx(expected[policy][0]).margin(2.0e-14)); CHECK(result[1] == Catch::Approx(expected[policy][1]).margin(2.0e-14)); } }