diff --git a/.gitignore b/.gitignore index 58d305f00f1..dd5ef0f582f 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ GSYMS GTAGS GPATH .gitignore +.cache ### OS # temporary and backup files diff --git a/core/distributed/preconditioner/schwarz.cpp b/core/distributed/preconditioner/schwarz.cpp index e93b229157b..cd4c2500a5c 100644 --- a/core/distributed/preconditioner/schwarz.cpp +++ b/core/distributed/preconditioner/schwarz.cpp @@ -192,7 +192,7 @@ void Schwarz::generate( } if (!parameters_.local_solver && !parameters_.generated_local_solver) { GKO_INVALID_STATE( - "Requires either a generated solver or an solver factory"); + "Requires either a generated solver or a solver factory"); } if (parameters_.generated_local_solver) { this->set_solver(parameters_.generated_local_solver); @@ -234,6 +234,8 @@ void Schwarz::generate( exec, local_matrix->get_size()[0]); auto one = initialize>( {::gko::one()}, exec); + local_matrix_copy->sort_by_column_index(); // spgeam requires sorting + // for some backends l1_diag_csr->apply(one, id, one, local_matrix_copy); this->set_solver( diff --git a/test/mpi/preconditioner/schwarz.cpp b/test/mpi/preconditioner/schwarz.cpp index 8cacfa1ec9f..7218b676543 100644 --- a/test/mpi/preconditioner/schwarz.cpp +++ b/test/mpi/preconditioner/schwarz.cpp @@ -31,6 +31,7 @@ #include "core/test/utils.hpp" #include "core/test/utils/matrix_generator.hpp" #include "core/utils/matrix_utils.hpp" +#include "ginkgo/core/base/math.hpp" #include "test/utils/mpi/common_fixture.hpp" @@ -145,7 +146,9 @@ class SchwarzPreconditioner : public CommonMpiTestFixture { void assert_equal_to_non_distributed_vector( std::shared_ptr dist_vec, - std::shared_ptr local_vec) + std::shared_ptr local_vec, + gko::remove_complex mult = + gko::one>()) { auto host_row_part = row_part->clone(ref); auto l_dist_vec = dist_vec->get_local_vector(); @@ -156,7 +159,8 @@ class SchwarzPreconditioner : public CommonMpiTestFixture { local_vec->get_const_values() + host_row_part->get_range_bounds()[comm.rank()]), l_dist_vec->get_size()[1]); - GKO_ASSERT_MTX_NEAR(l_dist_vec, vec_view.get(), r::value); + GKO_ASSERT_MTX_NEAR(l_dist_vec, vec_view.get(), + mult * r::value); } }; @@ -381,3 +385,51 @@ TYPED_TEST(SchwarzPreconditioner, CanApplyPreconditionerWithL1Smoother) this->assert_equal_to_non_distributed_vector(this->dist_x, this->non_dist_x); } + + +TYPED_TEST(SchwarzPreconditioner, CanApplyPreconditionedSolverWithL1Smoother) +{ + using value_type = typename TestFixture::value_type; + using csr = typename TestFixture::local_matrix_type; + using cg = typename TestFixture::solver_type; + using prec = typename TestFixture::dist_prec_type; + using local_matrix_type = typename TestFixture::local_matrix_type; + constexpr double tolerance = 1e-20; + auto iter_stop = gko::share( + gko::stop::Iteration::build().with_max_iters(200u).on(this->exec)); + auto tol_stop = gko::share( + gko::stop::ResidualNorm::build() + .with_reduction_factor( + static_cast>(tolerance)) + .on(this->exec)); + auto non_dist_diag_with_l1 = + gko::share(gko::matrix::Diagonal::create( + this->exec, 8u, + gko::array(this->exec, {2, 3, 3, 3, 3, 2, 2, 2}))); + this->dist_solver_factory = + cg::build() + .with_preconditioner( + prec::build() + .with_local_solver(this->local_solver_factory) + .with_l1_smoother(true) + .on(this->exec)) + .with_criteria(iter_stop, tol_stop) + .on(this->exec); + auto dist_solver = this->dist_solver_factory->generate(this->dist_mat); + this->non_dist_solver_factory = + cg::build() + .with_generated_preconditioner(this->local_solver_factory->generate( + gko::copy_and_convert_to( + this->exec, non_dist_diag_with_l1))) + .with_criteria(iter_stop, tol_stop) + .on(this->exec); + auto non_dist_solver = + this->non_dist_solver_factory->generate(this->non_dist_mat); + + dist_solver->apply(this->dist_b.get(), this->dist_x.get()); + non_dist_solver->apply(this->non_dist_b.get(), this->non_dist_x.get()); + + this->assert_equal_to_non_distributed_vector( + this->dist_x, this->non_dist_x, + 2); // mult = 2 is needed for the gko::half to work +}