From b4a3d66af7ff9fb2bd5b245982cac8bbeaae2016 Mon Sep 17 00:00:00 2001 From: Marcel Koch Date: Tue, 25 Jun 2024 17:46:06 +0200 Subject: [PATCH] [prec] add SOR core + ref tests --- core/test/preconditioner/CMakeLists.txt | 1 + core/test/preconditioner/sor.cpp | 58 +++++ reference/test/preconditioner/CMakeLists.txt | 1 + reference/test/preconditioner/sor_kernels.cpp | 205 ++++++++++++++++++ 4 files changed, 265 insertions(+) create mode 100644 core/test/preconditioner/sor.cpp create mode 100644 reference/test/preconditioner/sor_kernels.cpp diff --git a/core/test/preconditioner/CMakeLists.txt b/core/test/preconditioner/CMakeLists.txt index 41db021e030..87996a79e32 100644 --- a/core/test/preconditioner/CMakeLists.txt +++ b/core/test/preconditioner/CMakeLists.txt @@ -3,3 +3,4 @@ ginkgo_create_test(ic) ginkgo_create_test(ilu) ginkgo_create_test(isai) ginkgo_create_test(jacobi) +ginkgo_create_test(sor) diff --git a/core/test/preconditioner/sor.cpp b/core/test/preconditioner/sor.cpp new file mode 100644 index 00000000000..5e089622721 --- /dev/null +++ b/core/test/preconditioner/sor.cpp @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// +// SPDX-License-Identifier: BSD-3-Clause + +#include + +#include + +#include +#include +#include + +#include "core/test/utils.hpp" + + +class SorFactory : public ::testing::Test { +public: + using sor_type = gko::preconditioner::Sor; + using l_isai_type = gko::preconditioner::LowerIsai; + using u_isai_type = gko::preconditioner::UpperIsai; + + std::shared_ptr exec = + gko::ReferenceExecutor::create(); +}; + + +TEST_F(SorFactory, CanDefaultBuild) +{ + auto factory = sor_type::build().on(exec); + + auto params = factory->get_parameters(); + ASSERT_EQ(params.skip_sorting, false); + ASSERT_EQ(params.relaxation_factor, 1.0); + ASSERT_EQ(params.symmetric, false); + ASSERT_EQ(params.l_solver, nullptr); + ASSERT_EQ(params.u_solver, nullptr); +} + + +TEST_F(SorFactory, CanBuildWithParameters) +{ + auto factory = sor_type::build() + .with_skip_sorting(true) + .with_relaxation_factor(0.5) + .with_symmetric(true) + .with_l_solver(l_isai_type::build()) + .with_u_solver(u_isai_type::build()) + .on(exec); + + auto params = factory->get_parameters(); + ASSERT_EQ(params.skip_sorting, true); + ASSERT_EQ(params.relaxation_factor, 0.5); + ASSERT_EQ(params.symmetric, true); + ASSERT_NE(params.l_solver, nullptr); + GKO_ASSERT_DYNAMIC_TYPE(params.l_solver, l_isai_type::Factory); + ASSERT_NE(params.u_solver, nullptr); + GKO_ASSERT_DYNAMIC_TYPE(params.u_solver, u_isai_type::Factory); +} diff --git a/reference/test/preconditioner/CMakeLists.txt b/reference/test/preconditioner/CMakeLists.txt index c8b945e2913..09c88608d65 100644 --- a/reference/test/preconditioner/CMakeLists.txt +++ b/reference/test/preconditioner/CMakeLists.txt @@ -4,3 +4,4 @@ ginkgo_create_test(ic) ginkgo_create_test(isai_kernels) ginkgo_create_test(jacobi) ginkgo_create_test(jacobi_kernels) +ginkgo_create_test(sor_kernels) diff --git a/reference/test/preconditioner/sor_kernels.cpp b/reference/test/preconditioner/sor_kernels.cpp new file mode 100644 index 00000000000..185cfdb2025 --- /dev/null +++ b/reference/test/preconditioner/sor_kernels.cpp @@ -0,0 +1,205 @@ +// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// +// SPDX-License-Identifier: BSD-3-Clause + +#include "core/preconditioner/sor_kernels.hpp" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/test/utils.hpp" + + +template +class Sor : public ::testing::Test { +public: + using value_type = + typename std::tuple_element<0, decltype(ValueIndexType())>::type; + using index_type = + typename std::tuple_element<1, decltype(ValueIndexType())>::type; + using csr_type = gko::matrix::Csr; + using sor_type = gko::preconditioner::Sor; + + std::shared_ptr exec = + gko::ReferenceExecutor::create(); + gko::remove_complex diag_value = + static_cast>(1.5); + std::shared_ptr mtx = + gko::initialize({{diag_value, 2, 0, 3, 4}, + {-2, diag_value, 5, 0, 0}, + {0, -5, diag_value, 0, 6}, + {-3, 0, 0, diag_value, 7}, + {-4, 0, -6, -7, diag_value}}, + exec); + std::shared_ptr expected_l = + gko::initialize({{diag_value, 0, 0, 0, 0}, + {-2, diag_value, 0, 0, 0}, + {0, -5, diag_value, 0, 0}, + {-3, 0, 0, diag_value, 0}, + {-4, 0, -6, -7, diag_value}}, + exec); + std::shared_ptr expected_u = + gko::initialize({{diag_value, 2, 0, 3, 4}, + {0, diag_value, 5, 0, 0}, + {0, 0, diag_value, 0, 6}, + {0, 0, 0, diag_value, 7}, + {0, 0, 0, 0, diag_value}}, + exec); +}; + +TYPED_TEST_SUITE(Sor, gko::test::ValueIndexTypes, PairTypenameNameGenerator); + + +TYPED_TEST(Sor, CanInitializeLFactor) +{ + using value_type = typename TestFixture::value_type; + auto result = gko::clone(this->expected_l); + result->scale( + gko::initialize>({0.0}, this->exec)); + + gko::kernels::reference::sor::initialize_weighted_l( + this->exec, this->mtx.get(), 1.0, result.get()); + + GKO_ASSERT_MTX_NEAR(result, this->expected_l, 0.0); +} + + +TYPED_TEST(Sor, CanInitializeLFactorWithWeight) +{ + using value_type = typename TestFixture::value_type; + using csr_type = typename TestFixture::csr_type; + auto result = gko::clone(this->expected_l); + result->scale( + gko::initialize>({0.0}, this->exec)); + std::shared_ptr expected_l = + gko::initialize({{1, 0, 0, 0, 0}, + {-2, 1, 0, 0, 0}, + {0, -5, 1, 0, 0}, + {-3, 0, 0, 1, 0}, + {-4, 0, -6, -7, 1}}, + this->exec); + + gko::kernels::reference::sor::initialize_weighted_l( + this->exec, this->mtx.get(), this->diag_value, result.get()); + + GKO_ASSERT_MTX_NEAR(result, expected_l, r::value); +} + + +TYPED_TEST(Sor, CanInitializeLAndUFactor) +{ + using value_type = typename TestFixture::value_type; + auto result_l = gko::clone(this->expected_l); + auto result_u = gko::clone(this->expected_u); + result_l->scale( + gko::initialize>({0.0}, this->exec)); + result_u->scale( + gko::initialize>({0.0}, this->exec)); + + gko::kernels::reference::sor::initialize_weighted_l_u( + this->exec, this->mtx.get(), 1.0, result_l.get(), result_u.get()); + + GKO_ASSERT_MTX_NEAR(result_l, this->expected_l, 0.0); + GKO_ASSERT_MTX_NEAR(result_u, this->expected_u, 0.0); +} + + +TYPED_TEST(Sor, CanInitializeLAndUFactorWithWeight) +{ + using value_type = typename TestFixture::value_type; + using csr_type = typename TestFixture::csr_type; + auto result_l = gko::clone(this->expected_l); + auto result_u = gko::clone(this->expected_u); + result_l->scale( + gko::initialize>({0.0}, this->exec)); + result_u->scale( + gko::initialize>({0.0}, this->exec)); + auto diag_weight = static_cast>( + 1.0 / (2 - this->diag_value)); + auto off_diag_weight = this->diag_value * diag_weight; + std::shared_ptr expected_l = + gko::initialize({{1, 0, 0, 0, 0}, + {-2, 1, 0, 0, 0}, + {0, -5, 1, 0, 0}, + {-3, 0, 0, 1, 0}, + {-4, 0, -6, -7, 1}}, + this->exec); + std::shared_ptr expected_u = gko::initialize( + {{this->diag_value * diag_weight, 2 * off_diag_weight, 0, + 3 * off_diag_weight, 4 * off_diag_weight}, + {0, this->diag_value * diag_weight, 5 * off_diag_weight, 0, 0}, + {0, 0, this->diag_value * diag_weight, 0, 6 * off_diag_weight}, + {0, 0, 0, this->diag_value * diag_weight, 7 * off_diag_weight}, + {0, 0, 0, 0, this->diag_value * diag_weight}}, + this->exec); + + gko::kernels::reference::sor::initialize_weighted_l_u( + this->exec, this->mtx.get(), this->diag_value, result_l.get(), + result_u.get()); + + GKO_ASSERT_MTX_NEAR(result_l, expected_l, r::value); + GKO_ASSERT_MTX_NEAR(result_u, expected_u, r::value); +} + + +TYPED_TEST(Sor, CanGenerateNonSymmetric) +{ + using value_type = typename TestFixture::value_type; + using index_type = typename TestFixture::index_type; + using sor_type = typename TestFixture::sor_type; + using composition_type = typename sor_type::composition_type; + using trs_type = gko::solver::LowerTrs; + + auto sor_pre = sor_type::build().on(this->exec)->generate(this->mtx); + + testing::StaticAssertTypeEq>(); + const auto& ops = sor_pre->get_operators(); + ASSERT_EQ(ops.size(), 1); + GKO_ASSERT_DYNAMIC_TYPE(ops[0], trs_type); + auto result_l = gko::as(ops[0])->get_system_matrix(); + GKO_ASSERT_MTX_NEAR(result_l, this->expected_l, 0.0); +} + + +TYPED_TEST(Sor, CanGenerateSymmetric) +{ + using value_type = typename TestFixture::value_type; + using index_type = typename TestFixture::index_type; + using sor_type = typename TestFixture::sor_type; + using composition_type = typename sor_type::composition_type; + using l_trs_type = gko::solver::LowerTrs; + using u_trs_type = gko::solver::UpperTrs; + + auto sor_pre = sor_type::build() + .with_symmetric(true) + .on(this->exec) + ->generate(this->mtx); + + testing::StaticAssertTypeEq>(); + const auto& ops = sor_pre->get_operators(); + ASSERT_EQ(ops.size(), 2); + GKO_ASSERT_DYNAMIC_TYPE(ops[0], u_trs_type); + GKO_ASSERT_DYNAMIC_TYPE(ops[1], l_trs_type); + auto result_u = gko::as(ops[0])->get_system_matrix(); + auto result_l = gko::as(ops[1])->get_system_matrix(); + GKO_ASSERT_MTX_NEAR(result_l, this->expected_l, 0.0); + auto expected_u = gko::clone(this->expected_u); + expected_u->inv_scale(gko::initialize>( + {this->diag_value}, this->exec)); + GKO_ASSERT_MTX_NEAR(result_u, expected_u, r::value); +}