Skip to content

Commit f71c9f9

Browse files
committed
add L1 smoother to schwarz preconditioner
Signed-off-by: Marcel Koch <marcel.koch@kit.edu>
1 parent 980d0b6 commit f71c9f9

File tree

4 files changed

+91
-17
lines changed

4 files changed

+91
-17
lines changed

core/distributed/preconditioner/schwarz.cpp

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,26 @@
1717
#include <ginkgo/core/distributed/matrix.hpp>
1818
#include <ginkgo/core/matrix/csr.hpp>
1919
#include <ginkgo/core/matrix/dense.hpp>
20+
#include <ginkgo/core/matrix/identity.hpp>
2021

2122
#include "core/base/utils.hpp"
2223
#include "core/config/config_helper.hpp"
2324
#include "core/config/dispatch.hpp"
2425
#include "core/distributed/helpers.hpp"
26+
#include "core/matrix/csr_kernels.hpp"
2527

2628

2729
namespace gko {
2830
namespace experimental {
2931
namespace distributed {
3032
namespace preconditioner {
33+
namespace {
34+
35+
36+
GKO_REGISTER_OPERATION(row_wise_sum, csr::row_wise_sum);
37+
38+
39+
}
3140

3241

3342
template <typename ValueType, typename LocalIndexType, typename GlobalIndexType>
@@ -36,7 +45,7 @@ Schwarz<ValueType, LocalIndexType, GlobalIndexType>::parse(
3645
const config::pnode& config, const config::registry& context,
3746
const config::type_descriptor& td_for_child)
3847
{
39-
auto params = Schwarz<ValueType, LocalIndexType, GlobalIndexType>::build();
48+
auto params = Schwarz::build();
4049

4150
if (auto& obj = config.get("generated_local_solver")) {
4251
params.with_generated_local_solver(
@@ -47,7 +56,9 @@ Schwarz<ValueType, LocalIndexType, GlobalIndexType>::parse(
4756
gko::config::parse_or_get_factory<const LinOpFactory>(
4857
obj, context, td_for_child));
4958
}
50-
59+
if (auto& obj = config.get("l1_smoother")) {
60+
params.with_l1_smoother(obj.get_boolean());
61+
}
5162
return params;
5263
}
5364

@@ -76,7 +87,6 @@ template <typename VectorType>
7687
void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::apply_dense_impl(
7788
const VectorType* dense_b, VectorType* dense_x) const
7889
{
79-
using Vector = matrix::Dense<ValueType>;
8090
auto exec = this->get_executor();
8191
if (this->local_solver_ != nullptr) {
8292
this->local_solver_->apply(gko::detail::get_local(dense_b),
@@ -130,14 +140,47 @@ void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::generate(
130140
"Requires either a generated solver or an solver factory");
131141
}
132142

133-
if (parameters_.local_solver) {
134-
this->set_solver(gko::share(parameters_.local_solver->generate(
135-
as<experimental::distributed::Matrix<
136-
ValueType, LocalIndexType, GlobalIndexType>>(system_matrix)
137-
->get_local_matrix())));
143+
if (parameters_.generated_local_solver) {
144+
this->set_solver(parameters_.generated_local_solver);
145+
return;
146+
}
138147

148+
auto local_matrix =
149+
as<Matrix<ValueType, LocalIndexType, GlobalIndexType>>(system_matrix)
150+
->get_local_matrix();
151+
152+
if (parameters_.l1_smoother) {
153+
auto exec = this->get_executor();
154+
155+
using Csr = matrix::Csr<ValueType, LocalIndexType>;
156+
auto local_matrix_copy = share(Csr::create(exec));
157+
as<ConvertibleTo<Csr>>(local_matrix)->convert_to(local_matrix_copy);
158+
159+
auto non_local_matrix = copy_and_convert_to<Csr>(
160+
exec, as<Matrix<ValueType, LocalIndexType, GlobalIndexType>>(
161+
system_matrix)
162+
->get_non_local_matrix());
163+
164+
array<ValueType> l1_diag_arr{exec, local_matrix->get_size()[0]};
165+
166+
exec->run(make_row_wise_sum(non_local_matrix.get(), l1_diag_arr, true));
167+
168+
// compute local_matrix_copy <- diag(l1) + local_matrix_copy
169+
auto l1_diag = matrix::Diagonal<ValueType>::create(
170+
exec, local_matrix->get_size()[0], std::move(l1_diag_arr));
171+
auto l1_diag_csr = Csr::create(exec);
172+
l1_diag->move_to(l1_diag_csr);
173+
auto id = matrix::Identity<ValueType>::create(
174+
exec, local_matrix->get_size()[0]);
175+
auto one = initialize<matrix::Dense<ValueType>>(
176+
{::gko::one<ValueType>()}, exec);
177+
l1_diag_csr->apply(one, id, one, local_matrix_copy);
178+
179+
this->set_solver(
180+
gko::share(parameters_.local_solver->generate(local_matrix_copy)));
139181
} else {
140-
this->set_solver(parameters_.generated_local_solver);
182+
this->set_solver(
183+
gko::share(parameters_.local_solver->generate(local_matrix)));
141184
}
142185
}
143186

core/test/config/preconditioner.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ struct Schwarz
437437
config_map["generated_local_solver"] = pnode{"linop"};
438438
param.with_generated_local_solver(
439439
detail::registry_accessor::get_data<gko::LinOp>(reg, "linop"));
440+
config_map["l1_smoother"] = pnode{true};
441+
param.with_l1_smoother(true);
440442
}
441443

442444
template <bool from_reg, typename AnswerType>

include/ginkgo/core/distributed/preconditioner/schwarz.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
1+
// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
22
//
33
// SPDX-License-Identifier: BSD-3-Clause
44

@@ -89,6 +89,16 @@ class Schwarz
8989
*/
9090
std::shared_ptr<const LinOp> GKO_FACTORY_PARAMETER_SCALAR(
9191
generated_local_solver, nullptr);
92+
93+
/**
94+
* Enable l1 smoother.
95+
*
96+
* This creates a diagonal matrix from the row-wise absolute
97+
* sum of the non-local matrix entries. The diagonal matrix
98+
* is then added to the system matrix when generating the
99+
* local solver.
100+
*/
101+
bool GKO_FACTORY_PARAMETER_SCALAR(l1_smoother, false);
92102
};
93103
GKO_ENABLE_LIN_OP_FACTORY(Schwarz, parameters, Factory);
94104
GKO_ENABLE_BUILD_METHOD(Factory);

test/mpi/preconditioner/schwarz.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@
3232
#include "test/utils/mpi/common_fixture.hpp"
3333

3434

35-
#if GINKGO_DPCPP_SINGLE_MODE
36-
using solver_value_type = float;
37-
#else
38-
using solver_value_type = double;
39-
#endif // GINKGO_DPCPP_SINGLE_MODE
40-
41-
4235
template <typename ValueLocalGlobalIndexType>
4336
class SchwarzPreconditioner : public CommonMpiTestFixture {
4437
protected:
@@ -296,3 +289,29 @@ TYPED_TEST(SchwarzPreconditioner, CanAdvancedApplyPreconditioner)
296289
this->assert_equal_to_non_distributed_vector(this->dist_x,
297290
this->non_dist_x);
298291
}
292+
293+
294+
TYPED_TEST(SchwarzPreconditioner, CanApplyPreconditionerWithL1Smoother)
295+
{
296+
using value_type = typename TestFixture::value_type;
297+
using prec = typename TestFixture::dist_prec_type;
298+
using local_matrix_type = typename TestFixture::local_matrix_type;
299+
auto non_dist_diag_with_l1 =
300+
gko::share(gko::matrix::Diagonal<value_type>::create(
301+
this->exec, 8u,
302+
gko::array<value_type>(this->exec, {2, 3, 3, 3, 3, 2, 2, 2})));
303+
auto precond_factory = prec::build()
304+
.with_local_solver(this->local_solver_factory)
305+
.with_l1_smoother(true)
306+
.on(this->exec);
307+
auto local_precond = this->local_solver_factory->generate(
308+
gko::copy_and_convert_to<local_matrix_type>(this->exec,
309+
non_dist_diag_with_l1));
310+
auto precond = precond_factory->generate(this->dist_mat);
311+
312+
precond->apply(this->dist_b.get(), this->dist_x.get());
313+
local_precond->apply(this->non_dist_b.get(), this->non_dist_x.get());
314+
315+
this->assert_equal_to_non_distributed_vector(this->dist_x,
316+
this->non_dist_x);
317+
}

0 commit comments

Comments
 (0)