HyprePrecon.hpp 4.8 KB
Newer Older
1
2
#pragma once

Praetorius, Simon's avatar
Praetorius, Simon committed
3
4
5
#if AMDIS_HAS_HYPRE && HAVE_MPI

#include <HYPRE.h>
6
7

#include <dune/common/unused.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
8
#include <amdis/linearalgebra/mtl/PreconditionerInterface.hpp>
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
#include <amdis/linearalgebra/mtl/itl/hypre.hpp>

namespace AMDiS
{
  /// \brief Interface to the HYPRE BoomerAMG preconditioner [...]
  /**
   * Parameters provided by AMDiS:
   *
   * [PRECON]->cycle mode:
   * 	1...V-cycle
   *	2...W-cycle
   *
   * [PRECON]->interpolation type:
   *  0...classical modified interpolation
   *	1...LS interpolation (for use with GSMG)
   * 	2...classical modified interpolation for hyperbolic PDEs
   * 	3...direct interpolation (with separation of weights)
   * 	4...multipass interpolation
   * 	5...multipass interpolation (with separation of weights)
   * 	6...extended+i interpolation
   * 	7...extended+i (if no common C neighbor) interpolation
   * 	8...standard interpolation
   * 	9...standard interpolation (with separation of weights)
   * 	10..classical block interpolation (for use with nodal systems version only)
   * 	11..classical block interpolation (for use with nodal systems version only)
   * 		with diagonalized diagonal blocks
   * 	12..FF interpolation
   * 	13..FF1 interpolation
   * 	14..extended interpolation
   *
   *  [PRECON]->info:
   * 	0...no printout (default)
   * 	1...print setup information
   * 	2...print solve information
   * 	3...print both setup and solve information
   *
   *  [PRECON]->relax type:
   * 	0...Jacobi
   * 	1...Gauss-Seidel, sequential (very slow!)
   * 	2...Gauss-Seidel, interior points in parallel, boundary sequential (slow!)
   * 	3...hybrid Gauss-Seidel or SOR, forward solve
   * 	4...hybrid Gauss-Seidel or SOR, backward solve
   * 	5...hybrid chaotic Gauss-Seidel (works only with OpenMP)
   * 	6...hybrid symmetric Gauss-Seidel or SSOR
   * 	9...Gaussian elimination (only on coarsest level)
   **/
Praetorius, Simon's avatar
Praetorius, Simon committed
55
  template <class Mat, class Vec>
56
  class HyprePrecon
Praetorius, Simon's avatar
Praetorius, Simon committed
57
      : public PreconditionerInterface<Mat, Vec>
58
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
59
60
61
62
    using M = typename Mat::BaseMatrix;
    using X = typename Vec::BaseVector;
    using Y = typename Vec::BaseVector;

63
    using Self = HyprePrecon;
Praetorius, Simon's avatar
Praetorius, Simon committed
64
    using Super = PreconditionerInterface<Mat, Vec>;
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
91
92
93
94

  public:
    /// A creator to be used instead of the constructor.
    struct Creator : CreatorInterfaceName<Super>
    {
      std::unique_ptr<Super> createWithString(std::string prefix) override
      {
        return std::make_unique<Self>(prefix);
      }
    };

  public:
    HyprePrecon(std::string const& prefix)
    {
      // read HYPRE parameters
      int maxIter = 1, cycleMode = -1, interpolation = -1, relaxation = -1, info = 1;
      Parameters::get(prefix + "->max iteration", maxIter);
      Parameters::get(prefix + "->cycle mode", cycleMode);
      Parameters::get(prefix + "->interpolation type", interpolation);
      Parameters::get(prefix + "->relax type", relaxation);
      Parameters::get(prefix + "->info", info);

      config_.maxIter(maxIter);
      config_.interpolationType(interpolation);
      config_.relaxType(relaxation);
      config_.cycle(cycleMode);
      config_.printLevel(info);
    }

    /// Implementation of \ref PreconditionerBase::init()
Praetorius, Simon's avatar
Praetorius, Simon committed
95
    void init(M const& mat) override
96
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
97
      hypreMatrix_.init(mat);
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
      HYPRE_IJMatrixGetObject(hypreMatrix_, (void**)(&matrix_));
      HYPRE_BoomerAMGCreate(&solver_);

      // apply solver parameters
      config_(solver_);

      mtl::dense_vector<double> swap(1, 0.0);
      mtl::HypreParVector x(swap);
      HYPRE_BoomerAMGSetup(solver_, matrix_, x, x);

      solverCreated_ = true;
    }

    /// Implementation of \ref PreconditionerInterface::exit()
    void exit() override
    {
      if (solverCreated_)
	      HYPRE_BoomerAMGDestroy(solver_);
      solverCreated_ = false;
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
119
120
    /// Implementation of \ref PreconditionerInterface::solve()
    void solve(X const& in, Y& out) const override
121
122
    {
      assert(solverCreated_);
Praetorius, Simon's avatar
Praetorius, Simon committed
123
124
      mtl::HypreParVector x(in); // use b as initial guess
      mtl::HypreParVector b(in);
125
126
127
128
129

      DUNE_UNUSED int error = HYPRE_BoomerAMGSolve(solver_, matrix_, b, x);
      assert(error != 0);

      // write output back to MTL vector
Praetorius, Simon's avatar
Praetorius, Simon committed
130
      mtl::convert(x.getHypreVector(), out);
131
132
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
133
134
    /// Implementation of \ref PreconditionerInterface::adjoint_solve()
    void adjoint_solve(X const& in, Y& out) const override
135
136
    {
      assert(solverCreated_);
Praetorius, Simon's avatar
Praetorius, Simon committed
137
138
      mtl::HypreParVector x(in); // use b as initial guess
      mtl::HypreParVector b(in);
139
140
141
142
143

      DUNE_UNUSED int error = HYPRE_BoomerAMGSolveT(solver_, matrix_, b, x);
      assert(error != 0);

      // write output back to MTL vector
Praetorius, Simon's avatar
Praetorius, Simon committed
144
      mtl::convert(x.getHypreVector(), out);
145
146
147
148
149
150
151
152
153
154
155
156
157
    }

  private:
    mtl::HypreMatrix hypreMatrix_;
    HYPRE_ParCSRMatrix matrix_;
    HYPRE_Solver solver_;

    mtl::AMGConfigurator config_;
    bool solverCreated_ = false;
  };

} // end namespace AMDiS

Praetorius, Simon's avatar
Praetorius, Simon committed
158
#endif // AMDIS_HAS_HYPRE && HAVE_MPI