diff --git a/core/test/multigrid/amgx_pgm.cpp b/core/test/multigrid/amgx_pgm.cpp index 5982402402b..33e196c11aa 100644 --- a/core/test/multigrid/amgx_pgm.cpp +++ b/core/test/multigrid/amgx_pgm.cpp @@ -45,4 +45,235 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "core/test/utils.hpp" -namespace {} // namespace +namespace { + + +template +class AmgxPgm : public ::testing::Test { +protected: + using value_type = + typename std::tuple_element<0, decltype(ValueIndexType())>::type; + using index_type = + typename std::tuple_element<1, decltype(ValueIndexType())>::type; + using Mtx = gko::matrix::Csr; + using Vec = gko::matrix::Dense; + using RestrictProlong = gko::multigrid::AmgxPgm; + using T = value_type; + AmgxPgm() + : exec(gko::ReferenceExecutor::create()), + amgxpgm_factory(RestrictProlong::build() + .with_max_iterations(2u) + .with_max_unassigned_percentage(0.1) + .on(exec)), + mtx(Mtx::create(exec, gko::dim<2>(5, 5), 15, + std::make_shared())), + agg(exec, 5), + coarse(Mtx::create(exec, gko::dim<2>(2, 2), 4, + std::make_shared())) + + { + this->create_mtx(mtx.get(), &agg, coarse.get()); + rstr_prlg = amgxpgm_factory->generate(mtx); + } + + void create_mtx(Mtx *fine, gko::Array *agg, Mtx *coarse) + { + auto f_vals = fine->get_values(); + auto f_cols = fine->get_col_idxs(); + auto f_rows = fine->get_row_ptrs(); + auto c_vals = coarse->get_values(); + auto c_cols = coarse->get_col_idxs(); + auto c_rows = coarse->get_row_ptrs(); + auto agg_val = agg->get_data(); + /* this matrix is stored: + * 5 -3 -3 0 0 + * -3 5 0 -2 -1 + * -3 0 5 0 -1 + * 0 -3 0 5 0 + * 0 -2 -2 0 5 + */ + f_vals[0] = 5; + f_vals[1] = -3; + f_vals[2] = -3; + f_vals[3] = -3; + f_vals[4] = 5; + f_vals[5] = -2; + f_vals[6] = -1; + f_vals[7] = -3; + f_vals[8] = 5; + f_vals[9] = -1; + f_vals[10] = -3; + f_vals[11] = 5; + f_vals[12] = -2; + f_vals[13] = -2; + f_vals[14] = 5; + + f_rows[0] = 0; + f_rows[1] = 3; + f_rows[2] = 7; + f_rows[3] = 10; + f_rows[4] = 12; + f_rows[5] = 15; + + f_cols[0] = 0; + f_cols[1] = 1; + f_cols[2] = 2; + f_cols[3] = 0; + f_cols[4] = 1; + f_cols[5] = 3; + f_cols[6] = 4; + f_cols[7] = 0; + f_cols[8] = 2; + f_cols[9] = 4; + f_cols[10] = 1; + f_cols[11] = 3; + f_cols[12] = 1; + f_cols[13] = 2; + f_cols[14] = 4; + + agg_val[0] = 0; + agg_val[1] = 1; + agg_val[2] = 0; + agg_val[3] = 1; + agg_val[4] = 0; + /* this coarse is stored: + * 6 -5 + * -4 5 + */ + c_vals[0] = 6; + c_vals[1] = -5; + c_vals[2] = -4; + c_vals[3] = 5; + + c_rows[0] = 0; + c_rows[1] = 2; + c_rows[2] = 4; + + c_cols[0] = 0; + c_cols[1] = 1; + c_cols[2] = 0; + c_cols[3] = 1; + } + + static void assert_same_matrices(const Mtx *m1, const Mtx *m2) + { + ASSERT_EQ(m1->get_size()[0], m2->get_size()[0]); + ASSERT_EQ(m1->get_size()[1], m2->get_size()[1]); + ASSERT_EQ(m1->get_num_stored_elements(), m2->get_num_stored_elements()); + for (gko::size_type i = 0; i < m1->get_size() + 1; i++) { + ASSERT_EQ(m1->get_const_row_ptrs()[i], m2->get_const_row_ptrs()[i]); + } + for (gko::size_type i = 0; i < m1->get_num_stored_elements(); ++i) { + EXPECT_EQ(m1->get_const_values()[i], m2->get_const_values()[i]); + EXPECT_EQ(m1->get_const_col_idxs()[i], m2->get_const_col_idxs()[i]); + } + } + + static void assert_same_agg(const index_type *m1, const index_type *m2, + gko::size_type len) + { + for (gko::size_type i = 0; i < len; ++i) { + EXPECT_EQ(m1[i], m2[i]); + } + } + + std::shared_ptr exec; + std::shared_ptr mtx; + std::shared_ptr coarse; + gko::Array agg; + std::unique_ptr amgxpgm_factory; + std::unique_ptr rstr_prlg; +}; + +TYPED_TEST_CASE(AmgxPgm, gko::test::ValueIndexTypes); + + +TYPED_TEST(AmgxPgm, FactoryKnowsItsExecutor) +{ + ASSERT_EQ(this->amgxpgm_factory->get_executor(), this->exec); +} + + +TYPED_TEST(AmgxPgm, CanBeCopied) +{ + using Mtx = typename TestFixture::Mtx; + using RestrictProlong = typename TestFixture::RestrictProlong; + auto copy = this->amgxpgm_factory->generate(Mtx::create(this->exec)); + + // copy->copy_from(this->rstr_prlg.get()); + + // auto copy_mtx = + // static_cast(copy.get())->get_system_matrix(); + // auto copy_agg = static_cast(copy.get())->get_const_agg(); auto copy_coarse = + // copy->get_coarse_operator(); + + // this->assert_same_matrices(static_cast(copy_mtx.get()), + // this->mtx.get()); + // this->assert_same_agg(copy_agg, this->agg.get_data(), + // this->agg.get_num_elems()); this->assert_same_matrices(static_cast(copy_coarse.get()), this->coarse.get()); +} + + +TYPED_TEST(AmgxPgm, CanBeMoved) +{ + using Mtx = typename TestFixture::Mtx; + using RestrictProlong = typename TestFixture::RestrictProlong; + auto copy = this->amgxpgm_factory->generate(Mtx::create(this->exec)); + + copy->copy_from(std::move(this->rstr_prlg)); + + auto copy_mtx = + static_cast(copy.get())->get_system_matrix(); + auto copy_agg = static_cast(copy.get())->get_const_agg(); + auto copy_coarse = copy->get_coarse_operator(); + + this->assert_same_matrices(static_cast(copy_mtx.get()), + this->mtx.get()); + this->assert_same_agg(copy_agg, this->agg.get_data(), + this->agg.get_num_elems()); + this->assert_same_matrices(static_cast(copy_coarse.get()), + this->coarse.get()); +} + + +TYPED_TEST(AmgxPgm, CanBeCloned) +{ + using Mtx = typename TestFixture::Mtx; + using RestrictProlong = typename TestFixture::RestrictProlong; + auto copy = this->amgxpgm_factory->generate(Mtx::create(this->exec)); + + auto clone = this->rstr_prlg->clone(); + + auto clone_mtx = + static_cast(clone.get())->get_system_matrix(); + auto clone_agg = + static_cast(clone.get())->get_const_agg(); + auto clone_coarse = clone->get_coarse_operator(); + + this->assert_same_matrices(static_cast(clone_mtx.get()), + this->mtx.get()); + this->assert_same_agg(clone_agg, this->agg.get_data(), + this->agg.get_num_elems()); + this->assert_same_matrices(static_cast(clone_coarse.get()), + this->coarse.get()); +} + + +TYPED_TEST(AmgxPgm, CanBeCleared) +{ + using RestrictProlong = typename TestFixture::RestrictProlong; + this->rstr_prlg->clear(); + + auto mtx = static_cast(this->rstr_prlg.get()) + ->get_system_matrix(); + auto coarse = this->rstr_prlg->get_coarse_operator(); + auto agg = static_cast(this->rstr_prlg.get())->get_agg(); + ASSERT_EQ(mtx, nullptr); + ASSERT_EQ(coarse, nullptr); + ASSERT_EQ(agg, nullptr); +} + + +} // namespace diff --git a/include/ginkgo/core/multigrid/amgx_pgm.hpp b/include/ginkgo/core/multigrid/amgx_pgm.hpp index d3da801110f..ecac15c6f0b 100644 --- a/include/ginkgo/core/multigrid/amgx_pgm.hpp +++ b/include/ginkgo/core/multigrid/amgx_pgm.hpp @@ -51,7 +51,8 @@ namespace multigrid { /** * Amgx parallel graph match (AmgxPgm) is the aggregate method introduced in the * paper M. Naumov et al., "AmgX: A Library for GPU Accelerated Algebraic - * Multigrid and Preconditioned Iterative Methods" + * Multigrid and Preconditioned Iterative Methods". Current implemenation only + * contains size = 2 version. * * AmgxPgm creates the aggreagate group according to the matrix value not the * structure. @@ -134,7 +135,10 @@ class AmgxPgm : public EnableRestrictProlong> { system_matrix_{std::move(system_matrix)}, agg_(factory->get_executor(), system_matrix_->get_size()[0]) { - this->generate(); + if (system_matrix_->get_size()[0] != 0) { + // generate on the existed matrix + this->generate(); + } } void generate(); diff --git a/reference/test/multigrid/amgx_pgm_kernels.cpp b/reference/test/multigrid/amgx_pgm_kernels.cpp index ff9507e2639..ea16d233de3 100644 --- a/reference/test/multigrid/amgx_pgm_kernels.cpp +++ b/reference/test/multigrid/amgx_pgm_kernels.cpp @@ -66,11 +66,11 @@ class AmgxPgm : public ::testing::Test { typename std::tuple_element<1, decltype(ValueIndexType())>::type; using Mtx = gko::matrix::Csr; using Vec = gko::matrix::Dense; - using Multigrid = gko::multigrid::AmgxPgm; + using RestrictProlong = gko::multigrid::AmgxPgm; using T = value_type; AmgxPgm() : exec(gko::ReferenceExecutor::create()), - AmgxPgm_factory(Multigrid::build() + Amgxpgm_factory(RestrictProlong::build() .with_max_iterations(2u) .with_max_unassigned_percentage(0.1) .on(exec)), @@ -174,7 +174,7 @@ class AmgxPgm : public ::testing::Test { std::shared_ptr restrict_ans; std::shared_ptr prolong_ans; std::shared_ptr fine_x; - std::unique_ptr AmgxPgm_factory; + std::unique_ptr Amgxpgm_factory; }; TYPED_TEST_CASE(AmgxPgm, gko::test::ValueIndexTypes); @@ -269,7 +269,7 @@ TYPED_TEST(AmgxPgm, Renumber) TYPED_TEST(AmgxPgm, Generate) { - auto coarse_fine = this->AmgxPgm_factory->generate(this->mtx); + auto coarse_fine = this->Amgxpgm_factory->generate(this->mtx); auto agg_result = coarse_fine->get_const_agg(); @@ -284,7 +284,7 @@ TYPED_TEST(AmgxPgm, Generate) TYPED_TEST(AmgxPgm, CoarseFineRestrictApply) { std::unique_ptr amgx_pgm{ - this->AmgxPgm_factory->generate(this->mtx)}; + this->Amgxpgm_factory->generate(this->mtx)}; // fine->coarse using Vec = typename TestFixture::Vec; @@ -299,7 +299,7 @@ TYPED_TEST(AmgxPgm, CoarseFineRestrictApply) TYPED_TEST(AmgxPgm, CoarseFineProlongApplyadd) { std::unique_ptr amgx_pgm{ - this->AmgxPgm_factory->generate(this->mtx)}; + this->Amgxpgm_factory->generate(this->mtx)}; using value_type = typename TestFixture::value_type; auto x = gko::clone(this->fine_x);