1#ifndef DUNE_COPASI_SOLVER_ISTL_BLOCK_JACOBI_HH
2#define DUNE_COPASI_SOLVER_ISTL_BLOCK_JACOBI_HH
7#include <dune/pdelab/common/algebra.hh>
9#include <dune/istl/preconditioner.hh>
10#include <dune/istl/solver.hh>
16template<Concept::AssembledLinearOperator O,
class Alloc = std::allocator<
void>>
17class BlockJacobi final :
public Preconditioner<typename O::domain_type, typename O::range_type>
19 using M =
typename O::matrix_type;
20 using X =
typename O::domain_type;
21 using Y =
typename O::range_type;
30 , _parallel{ _config.
get(
"parallel",
false) }
31 , _iterations{ _config.
get(
"iterations", std::
size_t{ 1 }) }
32 , _weight{ _config.
get(
"relaxation", 1.) }
39 this->
pre(PDELab::Execution::par,
x,
b);
41 this->
pre(PDELab::Execution::seq,
x,
b);
49 spdlog::warn(
"'diagona_solver' contains sub-sections that will be ignored");
50 if (
sub_solver.get(
"type",
"DenseInverse") !=
"DenseInverse")
51 spdlog::warn(
"Block jacobi at this level is scalar, meaning that the diagonal solver can only be 'DenseInverse'");
54 const M&
mat = _op->getmat();
56 _diag_inv.resize(
mat.M());
57 PDELab::forEach(
policy,
mat, [&](
const auto& row,
auto i) {
64 _diag_inv[
i] = 1. / (*row_it);
66 auto i_str = fmt::format(
"{}",
i);
71 MatrixAdapter<typename M::block_type, typename X::value_type, typename Y::value_type>;
84 this->
apply(PDELab::Execution::par,
v,
rhs);
86 this->
apply(PDELab::Execution::seq,
v,
rhs);
93 std::optional<X>
x_tmp;
94 const M&
mat = _op->getmat();
96 using Xi =
typename X::value_type;
98 X&
x = (
v.size() > 1) ?
x_tmp.emplace(
v) :
v;
100 for (std::size_t
it = 0;
it != _iterations; ++
it) {
101 PDELab::forEach(
policy,
mat, [=, &
b, &
x, &
diag_inv = _diag_inv](
const auto& row,
auto i)
mutable {
104 for (
auto col = row.begin(); col != row.end(); ++col)
105 b[
i] -= (*col) *
v[col.index()];
111 for (
auto col = row.begin(); col != row.end(); ++col)
112 col->mmv(
v[col.index()],
b[
i]);
118 PDELab::axpy(
x[
i], _weight,
vir);
128 SolverCategory::Category
category()
const override {
return SolverCategory::sequential; }
132 return [](
const std::shared_ptr<LinearOperator<X, Y>>&
op,
134 const Alloc&
alloc) -> std::shared_ptr<Preconditioner<X, Y>> {
140 auto aop = std::dynamic_pointer_cast<O>(
op);
149 using DiagInverse = std::conditional_t<
150 IsNumber<typename M::block_type>::value,
151 typename M::block_type,
152 std::shared_ptr<InverseOperator<typename X::value_type, typename Y::value_type>>>;
154 using DiagInverseAlloc =
158 std::shared_ptr<const O> _op;
159 std::vector<DiagInverse, DiagInverseAlloc> _diag_inv;
162 std::size_t _iterations;
Definition block_jacobi.hh:18
void apply(auto policy, X &v, const Y &rhs)
Definition block_jacobi.hh:89
void pre(X &x, Y &b) override
Definition block_jacobi.hh:36
void apply(X &v, const Y &rhs) override
Definition block_jacobi.hh:81
BlockJacobi(const std::shared_ptr< const O > &op, const ParameterTree &config, const Alloc &alloc=Alloc())
Definition block_jacobi.hh:24
void pre(auto policy, X &, Y &)
Definition block_jacobi.hh:44
void post(X &) override
Definition block_jacobi.hh:126
static auto factory()
Definition block_jacobi.hh:130
SolverCategory::Category category() const override
Definition block_jacobi.hh:128
Definition block_jacobi.hh:14
std::shared_ptr< InverseOperator< typename Op::domain_type, typename Op::range_type > > makeInverseOperator(const std::shared_ptr< Op > &op, const ParameterTree &config, const Alloc &alloc=Alloc())
Definition inverse.hh:65
auto format_exception(Exception &&e, fmt::format_string< Args... > format, Args &&... args)
Definition exceptions.hh:23
constexpr bool is_bitflags_v
Alias for Bitflag indicator.
Definition bit_flags.hh:24