OwningTwoLevelPreconditioner.hpp
Go to the documentation of this file.
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_OWNINGTWOLEVELPRECONDITIONER_HEADER_INCLUDED
21#define OPM_OWNINGTWOLEVELPRECONDITIONER_HEADER_INCLUDED
22
26
27#include <opm/common/ErrorMacros.hpp>
28
29#include <dune/common/fmatrix.hh>
30#include <dune/istl/bcrsmatrix.hh>
31#include <dune/istl/paamg/amg.hh>
32
33#include <fstream>
34#include <type_traits>
35
36
37namespace Opm
38{
39// Circular dependency between PreconditionerFactory [which can make an OwningTwoLevelPreconditioner]
40// and OwningTwoLevelPreconditioner [which uses PreconditionerFactory to choose the fine-level smoother]
41// must be broken, accomplished by forward-declaration here.
42template <class Operator, class Comm = Dune::Amg::SequentialInformation>
43class PreconditionerFactory;
44}
45
46namespace Dune
47{
48
49
50// Must forward-declare FlexibleSolver as we want to use it as solver for the pressure system.
51template <class Operator>
52class FlexibleSolver;
53
54template <typename T, typename A, int i>
55std::ostream& operator<<(std::ostream& out,
56 const BlockVector< FieldVector< T, i >, A >& vector)
57{
58 Dune::writeMatrixMarket(vector, out);
59 return out;
60}
61
62 template <typename T, typename A, int i>
63 std::istream& operator>>(std::istream& input,
64 BlockVector< FieldVector< T, i >, A >& vector)
65{
66 Dune::readMatrixMarket(vector, input);
67 return input;
68}
69
74template <class OperatorType,
75 class VectorType,
76 class LevelTransferPolicy,
77 class Communication = Dune::Amg::SequentialInformation>
79{
80public:
81 using MatrixType = typename OperatorType::matrix_type;
83 using AbstractOperatorType = Dune::AssembledLinearOperator<MatrixType, VectorType, VectorType>;
84
85 OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const Opm::PropertyTree& prm,
86 const std::function<VectorType()> weightsCalculator,
87 std::size_t pressureIndex)
88 : linear_operator_(linearoperator)
89 , finesmoother_(PrecFactory::create(linearoperator,
90 prm.get_child_optional("finesmoother") ?
91 prm.get_child("finesmoother") : Opm::PropertyTree(),
92 std::function<VectorType()>(), pressureIndex))
93 , comm_(nullptr)
94 , weightsCalculator_(weightsCalculator)
95 , weights_(weightsCalculator())
96 , levelTransferPolicy_(dummy_comm_, weights_, prm, pressureIndex)
97 , coarseSolverPolicy_(prm.get_child_optional("coarsesolver") ? prm.get_child("coarsesolver") : Opm::PropertyTree())
98 , twolevel_method_(linearoperator,
99 finesmoother_,
100 levelTransferPolicy_,
101 coarseSolverPolicy_,
102 prm.get<int>("pre_smooth", 0),
103 prm.get<int>("post_smooth", 1))
104 , prm_(prm)
105 {
106 if (prm.get<int>("verbosity", 0) > 10) {
107 std::string filename = prm.get<std::string>("weights_filename", "impes_weights.txt");
108 std::ofstream outfile(filename);
109 if (!outfile) {
110 OPM_THROW(std::ofstream::failure,
111 "Could not write weights to file " + filename + ".");
112 }
113 Dune::writeMatrixMarket(weights_, outfile);
114 }
115 }
116
117 OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const Opm::PropertyTree& prm,
118 const std::function<VectorType()> weightsCalculator,
119 std::size_t pressureIndex, const Communication& comm)
120 : linear_operator_(linearoperator)
121 , finesmoother_(PrecFactory::create(linearoperator,
122 prm.get_child_optional("finesmoother") ?
123 prm.get_child("finesmoother"): Opm::PropertyTree(),
124 std::function<VectorType()>(),
125 comm, pressureIndex))
126 , comm_(&comm)
127 , weightsCalculator_(weightsCalculator)
128 , weights_(weightsCalculator())
129 , levelTransferPolicy_(*comm_, weights_, prm, pressureIndex)
130 , coarseSolverPolicy_(prm.get_child_optional("coarsesolver") ? prm.get_child("coarsesolver") : Opm::PropertyTree())
131 , twolevel_method_(linearoperator,
132 finesmoother_,
133 levelTransferPolicy_,
134 coarseSolverPolicy_,
135 prm.get<int>("pre_smooth", 0),
136 prm.get<int>("post_smooth", 1))
137 , prm_(prm)
138 {
139 if (prm.get<int>("verbosity", 0) > 10 && comm.communicator().rank() == 0) {
140 auto filename = prm.get<std::string>("weights_filename", "impes_weights.txt");
141 std::ofstream outfile(filename);
142 if (!outfile) {
143 OPM_THROW(std::ofstream::failure,
144 "Could not write weights to file " + filename + ".");
145 }
146 Dune::writeMatrixMarket(weights_, outfile);
147 }
148 }
149
150 virtual void pre(VectorType& x, VectorType& b) override
151 {
152 twolevel_method_.pre(x, b);
153 }
154
155 virtual void apply(VectorType& v, const VectorType& d) override
156 {
157 twolevel_method_.apply(v, d);
158 }
159
160 virtual void post(VectorType& x) override
161 {
162 twolevel_method_.post(x);
163 }
164
165 virtual void update() override
166 {
167 weights_ = weightsCalculator_();
168 updateImpl(comm_);
169 }
170
171 virtual Dune::SolverCategory::Category category() const override
172 {
173 return linear_operator_.category();
174 }
175
176private:
177 using CoarseOperator = typename LevelTransferPolicy::CoarseOperator;
178 using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperator,
180 LevelTransferPolicy>;
181 using TwoLevelMethod
183
184 // Handling parallel vs serial instantiation of preconditioner factory.
185 template <class Comm>
186 void updateImpl(const Comm*)
187 {
188 // Parallel case.
189 auto child = prm_.get_child_optional("finesmoother");
190 finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : Opm::PropertyTree(), *comm_);
191 twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_);
192 }
193
194 void updateImpl(const Dune::Amg::SequentialInformation*)
195 {
196 // Serial case.
197 auto child = prm_.get_child_optional("finesmoother");
198 finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : Opm::PropertyTree());
199 twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_);
200 }
201
202 const OperatorType& linear_operator_;
203 std::shared_ptr<Dune::Preconditioner<VectorType, VectorType>> finesmoother_;
204 const Communication* comm_;
205 std::function<VectorType()> weightsCalculator_;
206 VectorType weights_;
207 LevelTransferPolicy levelTransferPolicy_;
208 CoarseSolverPolicy coarseSolverPolicy_;
209 TwoLevelMethod twolevel_method_;
211 Communication dummy_comm_;
212};
213
214} // namespace Dune
215
216
217
218
219#endif // OPM_OWNINGTWOLEVELPRECONDITIONER_HEADER_INCLUDED
Dune::OwnerOverlapCopyCommunication< int, int > Comm
Definition: FlexibleSolver_impl.hpp:270
Definition: PressureSolverPolicy.hpp:35
Definition: twolevelmethodcpr.hh:387
void updatePreconditioner(FineOperatorType &, std::shared_ptr< SmootherType > smoother, CoarseLevelSolverPolicy &coarsePolicy)
Definition: twolevelmethodcpr.hh:465
void apply(FineDomainType &v, const FineRangeType &d)
Definition: twolevelmethodcpr.hh:497
void pre(FineDomainType &x, FineRangeType &b)
Definition: twolevelmethodcpr.hh:488
void post(FineDomainType &x)
Definition: twolevelmethodcpr.hh:493
Definition: FlexibleSolver.hpp:45
Definition: OwningTwoLevelPreconditioner.hpp:79
virtual void apply(VectorType &v, const VectorType &d) override
Definition: OwningTwoLevelPreconditioner.hpp:155
typename OperatorType::matrix_type MatrixType
Definition: OwningTwoLevelPreconditioner.hpp:81
OwningTwoLevelPreconditioner(const OperatorType &linearoperator, const Opm::PropertyTree &prm, const std::function< VectorType()> weightsCalculator, std::size_t pressureIndex)
Definition: OwningTwoLevelPreconditioner.hpp:85
virtual void post(VectorType &x) override
Definition: OwningTwoLevelPreconditioner.hpp:160
virtual void pre(VectorType &x, VectorType &b) override
Definition: OwningTwoLevelPreconditioner.hpp:150
OwningTwoLevelPreconditioner(const OperatorType &linearoperator, const Opm::PropertyTree &prm, const std::function< VectorType()> weightsCalculator, std::size_t pressureIndex, const Communication &comm)
Definition: OwningTwoLevelPreconditioner.hpp:117
virtual void update() override
Definition: OwningTwoLevelPreconditioner.hpp:165
Dune::AssembledLinearOperator< MatrixType, VectorType, VectorType > AbstractOperatorType
Definition: OwningTwoLevelPreconditioner.hpp:83
virtual Dune::SolverCategory::Category category() const override
Definition: OwningTwoLevelPreconditioner.hpp:171
Interface class adding the update() method to the preconditioner interface.
Definition: PreconditionerWithUpdate.hpp:32
Definition: PreconditionerFactory.hpp:64
static PrecPtr create(const Operator &op, const PropertyTree &prm, const std::function< Vector()> &weightsCalculator={}, std::size_t pressureIndex=std::numeric_limits< std::size_t >::max())
Definition: PreconditionerFactory_impl.hpp:702
Definition: PropertyTree.hpp:37
T get(const std::string &key) const
std::optional< PropertyTree > get_child_optional(const std::string &key) const
Definition: SupportsFaceTag.hpp:27
std::istream & operator>>(std::istream &input, BlockVector< FieldVector< T, i >, A > &vector)
Definition: OwningTwoLevelPreconditioner.hpp:63
std::ostream & operator<<(std::ostream &out, const BlockVector< FieldVector< T, i >, A > &vector)
Definition: OwningTwoLevelPreconditioner.hpp:55
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: BlackoilPhases.hpp:27
Algebraic twolevel methods.