3.2-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
istlsolverfactorybackend.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program 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 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
26#ifndef DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH
27#define DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH
28
29#include <memory>
30#include <dune/common/version.hh>
31#if DUNE_VERSION_GTE(DUNE_ISTL,2,7)
32
33#include <dune/common/version.hh>
34#include <dune/common/parallel/mpihelper.hh>
35#include <dune/common/parametertree.hh>
36
38
39// preconditioners
40#include <dune/istl/preconditioners.hh>
41#include <dune/istl/paamg/amg.hh>
42#include "preconditioners.hh"
43
44// solvers
45#include <dune/istl/solvers.hh>
46#include <dune/istl/solverfactory.hh>
47
51
52namespace Dumux {
53
54// initSolverFactoriesForMultiTypeBlockMatrix differs in different compilation units,
55// so we have it in an anonymous namespace
56namespace {
57
66template<class LinearOperator>
67int initSolverFactoriesForMultiTypeBlockMatrix()
68{
69 using M = typename LinearOperator::matrix_type;
70 using X = typename LinearOperator::range_type;
71 using Y = typename LinearOperator::domain_type;
72 using TL = Dune::TypeList<M,X,Y>;
73 auto& dsfac = Dune::DirectSolverFactory<M,X,Y>::instance();
74 Dune::addRegistryToFactory<TL>(dsfac, Dumux::MultiTypeBlockMatrixDirectSolverTag{});
75#if DUNE_VERSION_GT(DUNE_ISTL,2,7)
76 auto& pfac = Dune::PreconditionerFactory<LinearOperator,X,Y>::instance();
77#else
78 auto& pfac = Dune::PreconditionerFactory<M,X,Y>::instance();
79#endif
80 Dune::addRegistryToFactory<TL>(pfac, Dumux::MultiTypeBlockMatrixPreconditionerTag{});
81 using TLS = Dune::TypeList<X,Y>;
82 auto& isfac = Dune::IterativeSolverFactory<X,Y>::instance();
83 return Dune::addRegistryToFactory<TLS>(isfac, Dune::IterativeSolverTag{});
84}
85} // end namespace
86
94template<class Matrix, class LinearOperator>
95void initSolverFactories()
96{
97 if constexpr (isMultiTypeBlockMatrix<Matrix>::value)
98 initSolverFactoriesForMultiTypeBlockMatrix<LinearOperator>();
99 else
100#if DUNE_VERSION_GT(DUNE_ISTL,2,7)
101 Dune::initSolverFactories<LinearOperator>();
102#else
103 {
104 using X = typename LinearOperator::range_type;
105 using Y = typename LinearOperator::domain_type;
106 Dune::initSolverFactories<Matrix, X, Y>();
107 }
108#endif
109}
110
118template <class LinearSolverTraits>
119class IstlSolverFactoryBackend : public LinearSolver
120{
121public:
122
128 IstlSolverFactoryBackend(const std::string& paramGroup = "")
129 : paramGroup_(paramGroup)
130 , isParallel_(Dune::MPIHelper::getCollectiveCommunication().size() > 1)
131 {
132 if (isParallel_)
133 DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!");
134
135 reset();
136 }
137
145 IstlSolverFactoryBackend(const typename LinearSolverTraits::GridView& gridView,
146 const typename LinearSolverTraits::DofMapper& dofMapper,
147 const std::string& paramGroup = "")
148 : paramGroup_(paramGroup)
149#if HAVE_MPI
150 , parallelHelper_(std::make_unique<ParallelISTLHelper<LinearSolverTraits>>(gridView, dofMapper))
151 , isParallel_(Dune::MPIHelper::getCollectiveCommunication().size() > 1)
152#endif
153 {
154 reset();
155 }
156
164 template<class Matrix, class Vector>
165 bool solve(Matrix& A, Vector& x, Vector& b)
166 {
167#if HAVE_MPI
168 solveSequentialOrParallel_(A, x, b);
169#else
170 solveSequential_(A, x, b);
171#endif
172 firstCall_ = false;
173 return result_.converged;
174 }
175
177 void reset()
178 {
179 firstCall_ = true;
181 checkMandatoryParameters_();
182 name_ = params_.get<std::string>("preconditioner.type") + "-preconditioned " + params_.get<std::string>("type");
183 if (params_.get<int>("verbose", 0) > 0)
184 std::cout << "Initialized linear solver of type: " << name_ << std::endl;
185 }
186
187 const Dune::InverseOperatorResult& result() const
188 {
189 return result_;
190 }
191
192 const std::string& name() const
193 {
194 return name_;
195 }
196
197private:
198
199 void checkMandatoryParameters_()
200 {
201 if (!params_.hasKey("type"))
202 DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Type\" parameter to select the solver");
203
204 if (!params_.hasKey("preconditioner.type"))
205 DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Preconditioner.Type\" parameter to select the preconditioner");
206 }
207
208#if HAVE_MPI
209 template<class Matrix, class Vector>
210 void solveSequentialOrParallel_(Matrix& A, Vector& x, Vector& b)
211 {
212 // Dune::MultiTypeBlockMatrix does not provide a ColIterator which is needed by Dune::NonoverlappingSchwarzOperator.
213 // We therefore can only solve these types of systems sequentially.
214 // TODO: This can be adapted once the situation in Dune ISTL changes.
215 if constexpr (LinearSolverTraits::canCommunicate && !isMultiTypeBlockMatrix<Matrix>::value)
216 {
217 if (isParallel_)
218 {
219 if (LinearSolverTraits::isNonOverlapping(parallelHelper_->gridView()))
220 {
221 using PTraits = typename LinearSolverTraits::template ParallelNonoverlapping<Matrix, Vector>;
222 solveParallel_<PTraits>(A, x, b);
223 }
224 else
225 {
226 using PTraits = typename LinearSolverTraits::template ParallelOverlapping<Matrix, Vector>;
227 solveParallel_<PTraits>(A, x, b);
228 }
229 }
230 else
231 solveSequential_(A, x, b);
232 }
233 else
234 {
235 solveSequential_(A, x, b);
236 }
237 }
238
239 template<class ParallelTraits, class Matrix, class Vector>
240 void solveParallel_(Matrix& A, Vector& x, Vector& b)
241 {
242#if DUNE_VERSION_GT_REV(DUNE_ISTL,2,7,0)
243 using Comm = typename ParallelTraits::Comm;
244 using LinearOperator = typename ParallelTraits::LinearOperator;
245 using ScalarProduct = typename ParallelTraits::ScalarProduct;
246
247 if (firstCall_)
248 {
249 initSolverFactories<Matrix, LinearOperator>();
250 parallelHelper_->initGhostsAndOwners();
251 }
252
253 std::shared_ptr<Comm> comm;
254 std::shared_ptr<LinearOperator> linearOperator;
255 std::shared_ptr<ScalarProduct> scalarProduct;
256 prepareLinearAlgebraParallel<LinearSolverTraits, ParallelTraits>(A, b, comm, linearOperator, scalarProduct, *parallelHelper_);
257
258 // construct solver
259 auto solver = getSolverFromFactory_(linearOperator);
260
261 // solve linear system
262 solver->apply(x, b, result_);
263#else
264 DUNE_THROW(Dune::NotImplemented, "Parallel solvers only available for dune-istl > 2.7.0");
265#endif
266 }
267#endif // HAVE_MPI
268
269 template<class Matrix, class Vector>
270 void solveSequential_(Matrix& A, Vector& x, Vector& b)
271 {
272 // construct linear operator
273 using Traits = typename LinearSolverTraits::template Sequential<Matrix, Vector>;
274 using LinearOperator = typename Traits::LinearOperator;
275 auto linearOperator = std::make_shared<LinearOperator>(A);
276
277 if (firstCall_)
278 initSolverFactories<Matrix, LinearOperator>();
279
280 // construct solver
281 auto solver = getSolverFromFactory_(linearOperator);
282
283 // solve linear system
284 solver->apply(x, b, result_);
285 }
286
287 template<class LinearOperator>
288 auto getSolverFromFactory_(std::shared_ptr<LinearOperator>& fop)
289 {
290 try { return Dune::getSolverFromFactory(fop, params_); }
291 catch(Dune::Exception& e)
292 {
293 std::cerr << "Could not create solver with factory" << std::endl;
294 std::cerr << e.what() << std::endl;
295 throw e;
296 }
297 }
298
299 const std::string paramGroup_;
300#if HAVE_MPI
301 std::unique_ptr<ParallelISTLHelper<LinearSolverTraits>> parallelHelper_;
302#endif
303 bool isParallel_ = false;
304 bool firstCall_;
305
306 Dune::InverseOperatorResult result_;
307 Dune::ParameterTree params_;
308 std::string name_;
309};
310
311} // end namespace Dumux
312
313#else
314#warning "Generic dune-istl solver factory backend needs dune-istl >= 2.7!"
315#endif // DUNE version check
316#endif // header guard
Type traits to be used with matrix types.
Generates a parameter tree required for the linear solvers and precondioners of the Dune ISTL.
Provides a helper class for nonoverlapping decomposition.
Dumux preconditioners for iterative solvers.
Base class for linear solvers.
Definition: adapt.hh:29
LinearSolverTraitsImpl< GridGeometry, GridGeometry::discMethod > LinearSolverTraits
The type traits required for using the IstlFactoryBackend.
Definition: linearsolvertraits.hh:72
Definition: common/pdesolver.hh:35
static Dune::ParameterTree createParameterTree(const std::string &paramGroup="")
Create a tree containing parameters required for the linear solvers and precondioners of the Dune IST...
Definition: linearsolverparameters.hh:46