SolverWrapper.hpp 2.72 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#pragma once

#include <memory>
#include <utility>

#include <dune/common/shared_ptr.hh>
#include <dune/istl/operators.hh>
#include <dune/istl/preconditioner.hh>
#include <dune/istl/scalarproducts.hh>
#include <dune/istl/solver.hh>
#include <dune/istl/solvercategory.hh>

#include <amdis/common/TypeTraits.hpp>

namespace AMDiS
{
  /// Wrapper around dune-istl inverse operator, like Dune::IterativeSolver,
  /// to store a shared_ptr instead of a reference.
  template <class S>
  class IterativeSolverWrapper
      : public Dune::InverseOperator<typename S::domain_type, typename S::range_type>
  {
    using Solver = S;

  public:
    using domain_type = typename S::domain_type;
    using range_type = typename S::range_type;

    using LinOp = Dune::LinearOperator<domain_type,range_type>;
    using Prec = Dune::Preconditioner<domain_type,range_type>;
    using ScalProd = Dune::ScalarProduct<domain_type>;

  public:
    template <class... Args>
    IterativeSolverWrapper(LinOp& linOp, Prec& prec, Args&&... args)
      : linOp_(Dune::stackobject_to_shared_ptr(linOp))
      , prec_(Dune::stackobject_to_shared_ptr(prec))
      , solver_(*linOp_, *prec_, FWD(args)...)
    {}

    template <class... Args>
    IterativeSolverWrapper(std::shared_ptr<LinOp> linOp, std::shared_ptr<Prec> prec, Args&&... args)
      : linOp_(std::move(linOp))
      , prec_(std::move(prec))
      , solver_(*linOp_, *prec_, FWD(args)...)
    {}

    template <class... Args>
    IterativeSolverWrapper(LinOp& linOp, ScalProd& sp, Prec& prec, Args&&... args)
      : linOp_(Dune::stackobject_to_shared_ptr(linOp))
      , sp_(Dune::stackobject_to_shared_ptr(sp))
      , prec_(Dune::stackobject_to_shared_ptr(prec))
      , solver_(*linOp_, *sp_, *prec_, FWD(args)...)
    {}

    template <class... Args>
    IterativeSolverWrapper(std::shared_ptr<LinOp> linOp, std::shared_ptr<ScalProd> sp, std::shared_ptr<Prec> prec, Args&&... args)
      : linOp_(std::move(linOp))
      , sp_(std::move(sp))
      , prec_(std::move(prec))
      , solver_(*linOp_, *sp_, *prec_, FWD(args)...)
    {}

    /// \brief Apply inverse operator
    void apply(domain_type& x, range_type& b, Dune::InverseOperatorResult& res) override
    {
      solver_.apply(x, b, res);
    }

    /// \brief Apply inverse operator with given reduction factor.
    void apply(domain_type& x, range_type& b, double reduction, Dune::InverseOperatorResult& res) override
    {
      solver_.apply(x, b, reduction, res);
    }

    /// Category of the solver
    Dune::SolverCategory::Category category() const override
    {
      return solver_.category();
    }

  private:
    std::shared_ptr<LinOp> linOp_;
    std::shared_ptr<ScalProd> sp_;
    std::shared_ptr<Prec> prec_;

    Solver solver_;
  };

} // end namespace AMDiS