-
Notifications
You must be signed in to change notification settings - Fork 99
Add a two-level Schwarz preconditioner #1431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 19 commits
0b8348d
03f49b5
8f99547
06f52d8
30ba1b4
cbb4e5b
2505bf5
19c2608
fe09944
713d009
e5f176e
ad1d8d3
057fbcc
973ea02
1b4a421
a70c5b4
30d85fa
9d9b829
01262e8
abb8584
d6c3ebc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -18,6 +18,7 @@ | |||||
#include <ginkgo/core/matrix/csr.hpp> | ||||||
#include <ginkgo/core/matrix/dense.hpp> | ||||||
#include <ginkgo/core/matrix/identity.hpp> | ||||||
#include <ginkgo/core/multigrid/multigrid_level.hpp> | ||||||
|
||||||
#include "core/base/utils.hpp" | ||||||
#include "core/config/config_helper.hpp" | ||||||
|
@@ -59,6 +60,20 @@ Schwarz<ValueType, LocalIndexType, GlobalIndexType>::parse( | |||||
if (auto& obj = config.get("l1_smoother")) { | ||||||
params.with_l1_smoother(obj.get_boolean()); | ||||||
} | ||||||
if (auto& obj = config.get("coarse_level")) { | ||||||
yhmtsai marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
params.with_coarse_level( | ||||||
gko::config::parse_or_get_factory<const LinOpFactory>( | ||||||
obj, context, td_for_child)); | ||||||
} | ||||||
if (auto& obj = config.get("coarse_solver")) { | ||||||
params.with_coarse_solver( | ||||||
gko::config::parse_or_get_factory<const LinOpFactory>( | ||||||
obj, context, td_for_child)); | ||||||
} | ||||||
if (auto& obj = config.get("coarse_weight")) { | ||||||
params.with_coarse_weight(gko::config::get_value<ValueType>(obj)); | ||||||
} | ||||||
|
||||||
return params; | ||||||
} | ||||||
|
||||||
|
@@ -87,8 +102,46 @@ template <typename VectorType> | |||||
void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::apply_dense_impl( | ||||||
const VectorType* dense_b, VectorType* dense_x) const | ||||||
{ | ||||||
using Vector = matrix::Dense<ValueType>; | ||||||
using dist_vec = experimental::distributed::Vector<ValueType>; | ||||||
auto exec = this->get_executor(); | ||||||
if (this->local_solver_ != nullptr) { | ||||||
|
||||||
// Two-level | ||||||
pratikvn marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if (this->coarse_solver_ != nullptr && this->coarse_level_ != nullptr) { | ||||||
this->local_solver_->apply(gko::detail::get_local(dense_b), | ||||||
gko::detail::get_local(dense_x)); | ||||||
|
||||||
auto coarse_level = | ||||||
as<gko::multigrid::MultigridLevel>(this->coarse_level_); | ||||||
auto restrict_op = coarse_level->get_restrict_op(); | ||||||
auto prolong_op = coarse_level->get_prolong_op(); | ||||||
auto coarse_op = | ||||||
as<experimental::distributed::Matrix<ValueType, LocalIndexType, | ||||||
GlobalIndexType>>( | ||||||
coarse_level->get_coarse_op()); | ||||||
|
||||||
// Coarse solve vector cache init | ||||||
// Should allocate only in the first apply call if the number of rhs is | ||||||
// unchanged. | ||||||
auto cs_ncols = dense_x->get_size()[1]; | ||||||
auto cs_local_nrows = coarse_op->get_local_matrix()->get_size()[0]; | ||||||
auto cs_global_nrows = coarse_op->get_size()[0]; | ||||||
auto cs_local_size = dim<2>(cs_local_nrows, cs_ncols); | ||||||
auto cs_global_size = dim<2>(cs_global_nrows, cs_ncols); | ||||||
auto comm = coarse_op->get_communicator(); | ||||||
csol_cache_.init(exec, comm, cs_global_size, cs_local_size); | ||||||
crhs_cache_.init(exec, comm, cs_global_size, cs_local_size); | ||||||
|
||||||
// Additive apply of coarse correction | ||||||
restrict_op->apply(dense_b, crhs_cache_.get()); | ||||||
// TODO: Does it make sense to restrict dense_x (to csol_cache) to | ||||||
// provide a good initial guess for the coarse solver ? | ||||||
pratikvn marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if (this->coarse_solver_->apply_uses_initial_guess()) { | ||||||
csol_cache_->copy_from(crhs_cache_.get()); | ||||||
} | ||||||
this->coarse_solver_->apply(crhs_cache_.get(), csol_cache_.get()); | ||||||
prolong_op->apply(this->coarse_weight_, csol_cache_.get(), | ||||||
this->local_weight_, dense_x); | ||||||
} else if (this->local_solver_ != nullptr) { | ||||||
this->local_solver_->apply(gko::detail::get_local(dense_b), | ||||||
gko::detail::get_local(dense_x)); | ||||||
} | ||||||
|
@@ -130,24 +183,29 @@ template <typename ValueType, typename LocalIndexType, typename GlobalIndexType> | |||||
void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::generate( | ||||||
std::shared_ptr<const LinOp> system_matrix) | ||||||
{ | ||||||
using Vector = matrix::Dense<ValueType>; | ||||||
using dist_vec = experimental::distributed::Vector<ValueType>; | ||||||
if (parameters_.local_solver && parameters_.generated_local_solver) { | ||||||
GKO_INVALID_STATE( | ||||||
"Provided both a generated solver and a solver factory"); | ||||||
} | ||||||
|
||||||
if (!parameters_.local_solver && !parameters_.generated_local_solver) { | ||||||
GKO_INVALID_STATE( | ||||||
"Requires either a generated solver or an solver factory"); | ||||||
} | ||||||
|
||||||
if (parameters_.generated_local_solver) { | ||||||
this->set_solver(parameters_.generated_local_solver); | ||||||
return; | ||||||
} | ||||||
if ((parameters_.coarse_level && !parameters_.coarse_solver) || | ||||||
(!parameters_.coarse_level && parameters_.coarse_solver)) { | ||||||
GKO_INVALID_STATE( | ||||||
"Requires both coarse solver and coarse level to be set."); | ||||||
} | ||||||
yhmtsai marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
auto local_matrix = | ||||||
as<Matrix<ValueType, LocalIndexType, GlobalIndexType>>(system_matrix) | ||||||
->get_local_matrix(); | ||||||
auto dist_mat = | ||||||
as<Matrix<ValueType, LocalIndexType, GlobalIndexType>>(system_matrix); | ||||||
auto local_matrix = dist_mat->get_local_matrix(); | ||||||
|
||||||
if (parameters_.l1_smoother) { | ||||||
auto exec = this->get_executor(); | ||||||
|
@@ -183,6 +241,34 @@ void Schwarz<ValueType, LocalIndexType, GlobalIndexType>::generate( | |||||
this->set_solver( | ||||||
gko::share(parameters_.local_solver->generate(local_matrix))); | ||||||
} | ||||||
|
||||||
gko::remove_complex<ValueType> cweight = | ||||||
gko::detail::real_impl(parameters_.coarse_weight); | ||||||
if (cweight > 0.0 && cweight <= 1.0) { | ||||||
|
if (cweight > 0.0 && cweight <= 1.0) { | |
if (cweight >= 0.0 && cweight <= 1.0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw an error or assert if coarse_level_ or coarse_solver are nullptr.
Do you need the fallback option?
For example, the problem is small enough or different reason such that multigrid level does not generate proper one.
User seems to easily have a wrong expectation. we do not perform the two-level schwarz.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that is out of scope of what Schwarz should do. I think the user has to ensure that the coarse level has valid inputs. The fallback option will be that there is no coarse level solve.
Uh oh!
There was an error while loading. Please reload this page.