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.
This commit is contained in:
58
tests/preconditioner/parity.cpp
Normal file
58
tests/preconditioner/parity.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#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<mfem::DenseMatrix> matrix(const int rows, const int columns, const std::initializer_list<double> entries)
|
||||
{
|
||||
REQUIRE(entries.size() == static_cast<std::size_t>(rows * columns));
|
||||
auto result = std::make_shared<mfem::DenseMatrix>(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<std::array<double, 2>, 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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user