opm-simulators
PreconditionerWithUpdate.hpp
1 /*
2  Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_PRECONDITIONERWITHUPDATE_HEADER_INCLUDED
21 #define OPM_PRECONDITIONERWITHUPDATE_HEADER_INCLUDED
22 
23 #include <dune/istl/preconditioner.hh>
24 #include <memory>
25 #include <tuple>
26 #include <utility>
27 
28 namespace Dune
29 {
30 
32 template <class X, class Y>
33 class PreconditionerWithUpdate : public Preconditioner<X, Y>
34 {
35 public:
36  virtual void update() = 0;
37 
38  // Force derived classes to define if preconditioner has perfect update
39  virtual bool hasPerfectUpdate() const = 0;
40 };
41 
42 template <class OriginalPreconditioner>
43 class DummyUpdatePreconditioner : public PreconditionerWithUpdate<typename OriginalPreconditioner::domain_type,
44  typename OriginalPreconditioner::range_type>
45 {
46 public:
47  template <class... Args>
48  explicit DummyUpdatePreconditioner(Args&&... args)
49  : orig_precond_(std::forward<Args>(args)...)
50  {
51  }
52 
53  using X = typename OriginalPreconditioner::domain_type;
54  using Y = typename OriginalPreconditioner::range_type;
55 
56  virtual void pre(X& x, Y& b) override
57  {
58  orig_precond_.pre(x, b);
59  }
60 
61  virtual void apply(X& v, const Y& d) override
62  {
63  orig_precond_.apply(v, d);
64  }
65 
66  virtual void post(X& x) override
67  {
68  orig_precond_.post(x);
69  }
70 
71  virtual SolverCategory::Category category() const override
72  {
73  return orig_precond_.category();
74  }
75 
76  // The update() function does nothing for a wrapped preconditioner.
77  virtual void update() override
78  {
79  }
80 
81  virtual bool hasPerfectUpdate() const override {
82  return true;
83  }
84 
85 private:
86  OriginalPreconditioner orig_precond_;
87 };
88 
89 template <class OriginalPreconditioner, class... Args>
90 std::shared_ptr<DummyUpdatePreconditioner<OriginalPreconditioner>>
91 getDummyUpdateWrapper(Args&&... args)
92 {
93  return std::make_shared<DummyUpdatePreconditioner<OriginalPreconditioner>>(std::forward<Args>(args)...);
94 }
95 
98 template <class OriginalPreconditioner>
100  virtual std::unique_ptr<
101  Preconditioner<typename OriginalPreconditioner::domain_type, typename OriginalPreconditioner::range_type>>
102  make() = 0;
103  virtual ~GeneralPreconditionerMaker() = default;
104 };
105 
110 template <class OriginalPreconditioner, class... Args>
111 struct PreconditionerMaker : public GeneralPreconditionerMaker<OriginalPreconditioner> {
112  using GenericPreconditioner = Preconditioner<typename OriginalPreconditioner::domain_type, typename OriginalPreconditioner::range_type>;
113 
114  explicit PreconditionerMaker(Args... args)
115  : args_(args...)
116  {
117  }
118 
119  std::unique_ptr<GenericPreconditioner>
120  make() override
121  {
122  // return std::unique_ptr<GenericPreconditioner> {new auto(std::make_from_tuple<OriginalPreconditioner>(args_))};
123  return std::apply(
124  [](auto&&... args) {
125  return std::make_unique<OriginalPreconditioner>(std::forward<Args>(args)...);
126  }, args_);
127  }
128 
129  std::tuple<Args...> args_;
130 };
131 
134 template <class OriginalPreconditioner>
135 class RebuildOnUpdatePreconditioner : public PreconditionerWithUpdate<typename OriginalPreconditioner::domain_type,
136  typename OriginalPreconditioner::range_type>
137 {
138 public:
139  template<class... Args>
140  explicit RebuildOnUpdatePreconditioner(Args... args)
141  : preconditioner_maker_(std::make_unique<PreconditionerMaker<OriginalPreconditioner, Args...>>(args...))
142  {
143  update();
144  }
145 
146  using X = typename OriginalPreconditioner::domain_type;
147  using Y = typename OriginalPreconditioner::range_type;
148 
149  void pre(X& x, Y& b) override
150  {
151  orig_precond_->pre(x, b);
152  }
153 
154  void apply(X& v, const Y& d) override
155  {
156  orig_precond_->apply(v, d);
157  }
158 
159  void post(X& x) override
160  {
161  orig_precond_->post(x);
162  }
163 
164  SolverCategory::Category category() const override
165  {
166  return orig_precond_->category();
167  }
168 
169  // Rebuild the preconditioner on update
170  void update() override
171  {
172  orig_precond_ = preconditioner_maker_->make();
173  }
174 
175  bool hasPerfectUpdate() const override
176  {
177  return true;
178  }
179 
180 private:
182  using GenericPreconditioner = Preconditioner<typename OriginalPreconditioner::domain_type, typename OriginalPreconditioner::range_type>;
183 
184  std::unique_ptr<AbstractMakerType> preconditioner_maker_;
185  std::unique_ptr<GenericPreconditioner> orig_precond_;
186 };
187 
193 template <class OriginalPreconditioner, class... Args>
194 auto
195 getRebuildOnUpdateWrapper(Args... args)
196 {
197  return std::make_shared<RebuildOnUpdatePreconditioner<OriginalPreconditioner>>(args...);
198 }
199 
200 } // namespace Dune
201 
202 #endif // OPM_PRECONDITIONERWITHUPDATE_HEADER_INCLUDED
Interface class ensuring make function is overriden.
Definition: PreconditionerWithUpdate.hpp:99
Definition: fvbaseprimaryvariables.hh:161
Struct implementing a make function which creates a preconditioner Can create arbitrary preconditione...
Definition: PreconditionerWithUpdate.hpp:111
Interface class adding the update() method to the preconditioner interface.
Definition: PreconditionerWithUpdate.hpp:33
Wrapper class of preconditioners that should be reconstructed on update.
Definition: PreconditionerWithUpdate.hpp:135
Definition: PreconditionerWithUpdate.hpp:43