GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/linear/istlsolverfactorybackend.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 75 82 91.5%
Functions: 101 125 80.8%
Branches: 132 358 36.9%

Line Branch Exec Source
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 // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup Linear
10 * \brief Provides a generic linear solver based on the ISTL that chooses the
11 * solver and preconditioner at runtime
12 */
13
14 #ifndef DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH
15 #define DUMUX_LINEAR_ISTL_SOLVERFACTORYBACKEND_HH
16
17 #include <memory>
18
19 #include <dune/common/parallel/mpihelper.hh>
20 #include <dune/common/parametertree.hh>
21
22 #include "linearsolverparameters.hh"
23
24 // preconditioners
25 #include <dune/istl/preconditioners.hh>
26 #include <dune/istl/paamg/amg.hh>
27 #include "preconditioners.hh"
28
29 // solvers
30 #include <dune/istl/solvers.hh>
31 #include <dune/istl/solverfactory.hh>
32
33 #include <dumux/common/typetraits/matrix.hh>
34 #include <dumux/common/typetraits/vector.hh>
35 #include <dumux/linear/solver.hh>
36 #include <dumux/linear/parallelhelpers.hh>
37 #include <dumux/linear/istlsolverregistry.hh>
38 #include <dumux/linear/solvercategory.hh>
39
40 namespace Dumux {
41
42 // initSolverFactoriesForMultiTypeBlockMatrix differs in different compilation units,
43 // so we have it in an anonymous namespace
44 namespace {
45
46 /*!
47 * \brief Initializes the direct solvers, preconditioners and iterative solvers in
48 * the factories with the corresponding Matrix and Vector types.
49 * \note We currently consider only direct solvers and preconditioners provided by
50 * Dumux which, unlike the ones implemented in Dune, also support MultiTypeBlockMatrices.
51 * \note This function could be removed once Dune::initSolverFactories supports MultiTypeBlockMatrices.
52 * \tparam LinearOperator the linear operator type
53 */
54 template<class LinearOperator>
55 1 int initSolverFactoriesForMultiTypeBlockMatrix()
56 {
57 using M = typename LinearOperator::matrix_type;
58 using X = typename LinearOperator::range_type;
59 using Y = typename LinearOperator::domain_type;
60 using TL = Dune::TypeList<M,X,Y>;
61 1 auto& dsfac = Dune::DirectSolverFactory<M,X,Y>::instance();
62 1 Dune::addRegistryToFactory<TL>(dsfac, Dumux::MultiTypeBlockMatrixDirectSolverTag{});
63 1 auto& pfac = Dune::PreconditionerFactory<LinearOperator,X,Y>::instance();
64 1 Dune::addRegistryToFactory<TL>(pfac, Dumux::MultiTypeBlockMatrixPreconditionerTag{});
65 using TLS = Dune::TypeList<X,Y>;
66 1 auto& isfac = Dune::IterativeSolverFactory<X,Y>::instance();
67 1 return Dune::addRegistryToFactory<TLS>(isfac, Dune::IterativeSolverTag{});
68 }
69 } // end namespace
70
71 /*!
72 * \brief Initialize the solver factories for regular matrices or MultiTypeBlockMatrices
73 * \tparam Matrix the matrix
74 * \tparam LinearOperator the linear operator
75 *
76 * \note This function could be removed once Dune::initSolverFactories supports MultiTypeBlockMatrices.
77 */
78 template<class Matrix, class LinearOperator>
79 void initSolverFactories()
80 {
81 if constexpr (isMultiTypeBlockMatrix<Matrix>::value)
82 1 initSolverFactoriesForMultiTypeBlockMatrix<LinearOperator>();
83 else
84 44 Dune::initSolverFactories<LinearOperator>();
85 }
86
87 /*!
88 * \ingroup Linear
89 * \brief A linear solver using the dune-istl solver factory
90 * to choose the solver and preconditioner at runtime.
91 * \note the solvers are configured via the input file
92 */
93 namespace Detail {
94
95 template <class LinearSolverTraits>
96 class OldIstlSolverFactoryBackend : public LinearSolver
97 {
98 public:
99
100 /*!
101 * \brief Update the solver after grid adaption
102 *
103 * \param gridView the grid view on which we are performing the multi-grid
104 * \param dofMapper an index mapper for dof entities
105 */
106 void updateAfterGridAdaption(const typename LinearSolverTraits::GridView& gridView,
107 const typename LinearSolverTraits::DofMapper& dofMapper)
108 {
109 #if HAVE_MPI
110 if (isParallel_)
111 parallelHelper_ = std::make_unique<ParallelISTLHelper<LinearSolverTraits>>(gridView, dofMapper);
112 #endif
113 }
114
115 /*!
116 * \brief Solve a linear system.
117 *
118 * \param A the matrix
119 * \param x the seeked solution vector, containing the initial solution upon entry
120 * \param b the right hand side vector
121 */
122 template<class Matrix, class Vector>
123 bool solve(Matrix& A, Vector& x, Vector& b)
124 {
125 #if HAVE_MPI
126 solveSequentialOrParallel_(A, x, b);
127 #else
128 solveSequential_(A, x, b);
129 #endif
130 firstCall_ = false;
131 return result_.converged;
132 }
133
134 const Dune::InverseOperatorResult& result() const
135 {
136 return result_;
137 }
138
139 const std::string& name() const
140 {
141 return name_;
142 }
143
144 private:
145
146 void initializeParameters_()
147 {
148 params_ = Dumux::LinearSolverParameters<LinearSolverTraits>::createParameterTree(paramGroup_);
149 checkMandatoryParameters_();
150 name_ = params_.get<std::string>("preconditioner.type") + "-preconditioned " + params_.get<std::string>("type");
151 if (params_.get<int>("verbose", 0) > 0)
152 std::cout << "Initialized linear solver of type: " << name_ << std::endl;
153 }
154
155 void checkMandatoryParameters_()
156 {
157 if (!params_.hasKey("type"))
158 DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Type\" parameter to select the solver");
159
160 if (!params_.hasKey("preconditioner.type"))
161 DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Preconditioner.Type\" parameter to select the preconditioner");
162 }
163
164 #if HAVE_MPI
165 template<class Matrix, class Vector>
166 void solveSequentialOrParallel_(Matrix& A, Vector& x, Vector& b)
167 {
168 // Dune::MultiTypeBlockMatrix does not provide a ColIterator which is needed by Dune::NonoverlappingSchwarzOperator.
169 // We therefore can only solve these types of systems sequentially.
170 // TODO: This can be adapted once the situation in Dune ISTL changes.
171 if constexpr (LinearSolverTraits::canCommunicate && !isMultiTypeBlockMatrix<Matrix>::value)
172 {
173 if (isParallel_)
174 {
175 if (LinearSolverTraits::isNonOverlapping(parallelHelper_->gridView()))
176 {
177 using PTraits = typename LinearSolverTraits::template ParallelNonoverlapping<Matrix, Vector>;
178 solveParallel_<PTraits>(A, x, b);
179 }
180 else
181 {
182 using PTraits = typename LinearSolverTraits::template ParallelOverlapping<Matrix, Vector>;
183 solveParallel_<PTraits>(A, x, b);
184 }
185 }
186 else
187 solveSequential_(A, x, b);
188 }
189 else
190 {
191 solveSequential_(A, x, b);
192 }
193 }
194
195 template<class ParallelTraits, class Matrix, class Vector>
196 void solveParallel_(Matrix& A, Vector& x, Vector& b)
197 {
198 using Comm = typename ParallelTraits::Comm;
199 using LinearOperator = typename ParallelTraits::LinearOperator;
200 using ScalarProduct = typename ParallelTraits::ScalarProduct;
201
202 if (firstCall_)
203 initSolverFactories<Matrix, LinearOperator>();
204
205 std::shared_ptr<Comm> comm;
206 std::shared_ptr<LinearOperator> linearOperator;
207 std::shared_ptr<ScalarProduct> scalarProduct;
208 prepareLinearAlgebraParallel<LinearSolverTraits, ParallelTraits>(A, b, comm, linearOperator, scalarProduct, *parallelHelper_);
209
210 // construct solver
211 auto solver = getSolverFromFactory_(linearOperator);
212
213 // solve linear system
214 solver->apply(x, b, result_);
215 }
216 #endif // HAVE_MPI
217
218 template<class Matrix, class Vector>
219 void solveSequential_(Matrix& A, Vector& x, Vector& b)
220 {
221 // construct linear operator
222 using Traits = typename LinearSolverTraits::template Sequential<Matrix, Vector>;
223 using LinearOperator = typename Traits::LinearOperator;
224 auto linearOperator = std::make_shared<LinearOperator>(A);
225
226 if (firstCall_)
227 initSolverFactories<Matrix, LinearOperator>();
228
229 // construct solver
230 auto solver = getSolverFromFactory_(linearOperator);
231
232 // solve linear system
233 solver->apply(x, b, result_);
234 }
235
236 template<class LinearOperator>
237 auto getSolverFromFactory_(std::shared_ptr<LinearOperator>& fop)
238 {
239 try { return Dune::getSolverFromFactory(fop, params_); }
240 catch(Dune::Exception& e)
241 {
242 std::cerr << "Could not create solver with factory" << std::endl;
243 std::cerr << e.what() << std::endl;
244 throw e;
245 }
246 }
247
248 const std::string paramGroup_;
249 #if HAVE_MPI
250 std::unique_ptr<ParallelISTLHelper<LinearSolverTraits>> parallelHelper_;
251 #endif
252 bool isParallel_ = false;
253 bool firstCall_;
254
255 Dune::InverseOperatorResult result_;
256 Dune::ParameterTree params_;
257 std::string name_;
258 };
259
260 template <class LinearSolverTraits, class LinearAlgebraTraits>
261 class IstlSolverFactoryBackend : public LinearSolver
262 {
263 using Matrix = typename LinearAlgebraTraits::Matrix;
264 using Vector = typename LinearAlgebraTraits::Vector;
265 using ScalarProduct = Dune::ScalarProduct<Vector>;
266 #if HAVE_MPI
267 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>, int>;
268 #endif
269 public:
270
271 /*!
272 * \brief Construct the backend for the sequential case only
273 *
274 * \param paramGroup the parameter group for parameter lookup
275 */
276 3 IstlSolverFactoryBackend(const std::string& paramGroup = "")
277 : paramGroup_(paramGroup)
278
14/42
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 3 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 3 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 3 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 3 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 3 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
6 , isParallel_(Dune::MPIHelper::getCommunication().size() > 1)
279 {
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (isParallel_)
281 DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!");
282
283 3 firstCall_ = true;
284
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 initializeParameters_();
285
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 scalarProduct_ = std::make_shared<ScalarProduct>();
286 3 solverCategory_ = Dune::SolverCategory::sequential;
287 3 }
288
289 /*!
290 * \brief Construct the backend for parallel or sequential runs
291 *
292 * \param gridView the grid view for parallel communication via the grid
293 * \param dofMapper an index mapper for dof entities
294 * \param paramGroup the parameter group for parameter lookup
295 */
296 42 IstlSolverFactoryBackend(const typename LinearSolverTraits::GridView& gridView,
297 const typename LinearSolverTraits::DofMapper& dofMapper,
298 const std::string& paramGroup = "")
299 : paramGroup_(paramGroup)
300 #if HAVE_MPI
301
15/45
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 42 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 42 times.
✓ Branch 12 taken 42 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 42 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 26 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 26 times.
✓ Branch 21 taken 16 times.
✓ Branch 22 taken 26 times.
✓ Branch 24 taken 42 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 42 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 42 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 42 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 26 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
84 , isParallel_(gridView.comm().size() > 1)
302 #endif
303 {
304 42 firstCall_ = true;
305
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 initializeParameters_();
306 #if HAVE_MPI
307
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
42 solverCategory_ = Detail::solverCategory<LinearSolverTraits>(gridView);
308
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 if (solverCategory_ != Dune::SolverCategory::sequential)
309 {
310
3/6
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
30 parallelHelper_ = std::make_unique<ParallelISTLHelper<LinearSolverTraits>>(gridView, dofMapper);
311
7/9
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 12 times.
✓ Branch 8 taken 18 times.
30 comm_ = std::make_shared<Comm>(gridView.comm(), solverCategory_);
312
4/8
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 30 times.
60 scalarProduct_ = Dune::createScalarProduct<Vector>(*comm_, solverCategory_);
313
3/6
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
90 parallelHelper_->createParallelIndexSet(*comm_);
314 }
315 else
316
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 scalarProduct_ = std::make_shared<ScalarProduct>();
317 #else
318 solverCategory_ = Dune::SolverCategory::sequential;
319 scalarProduct_ = std::make_shared<ScalarProduct>();
320 #endif
321 42 }
322
323 /*!
324 * \brief Solve a linear system.
325 *
326 * \param A the matrix
327 * \param x the seeked solution vector, containing the initial solution upon entry
328 * \param b the right hand side vector
329 */
330 bool solve(Matrix& A, Vector& x, Vector& b)
331 {
332 #if HAVE_MPI
333
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
1113 solveSequentialOrParallel_(A, x, b);
334 #else
335 solveSequential_(A, x, b);
336 #endif
337 1062 firstCall_ = false;
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
1062 return result_.converged;
339 }
340
341 const Dune::InverseOperatorResult& result() const
342 {
343 return result_;
344 }
345
346 const std::string& name() const
347 {
348 return name_;
349 }
350
351 186 Scalar norm(const Vector& x) const
352 {
353 #if HAVE_MPI
354 if constexpr (LinearSolverTraits::canCommunicate && !isMultiTypeBlockVector<Vector>::value)
355 {
356
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 136 times.
186 if (solverCategory_ == Dune::SolverCategory::nonoverlapping)
357 {
358
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
100 auto y(x); // make a copy because the vector needs to be made consistent
359 using GV = typename LinearSolverTraits::GridView;
360 using DM = typename LinearSolverTraits::DofMapper;
361
4/8
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 50 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 50 times.
✗ Branch 11 not taken.
200 ParallelVectorHelper<GV, DM, LinearSolverTraits::dofCodim> vectorHelper(parallelHelper_->gridView(), parallelHelper_->dofMapper());
362
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 vectorHelper.makeNonOverlappingConsistent(y);
363
3/6
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
100 return scalarProduct_->norm(y);
364 }
365 }
366 #endif
367
2/4
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
408 return scalarProduct_->norm(x);
368 }
369
370 private:
371
372 45 void initializeParameters_()
373 {
374 45 params_ = Dumux::LinearSolverParameters<LinearSolverTraits>::createParameterTree(paramGroup_);
375 45 checkMandatoryParameters_();
376
18/42
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 45 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 45 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 45 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 45 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 45 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 45 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 45 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 45 times.
✓ Branch 31 taken 45 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✓ Branch 34 taken 44 times.
✓ Branch 35 taken 1 times.
✓ Branch 36 taken 44 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 45 times.
✓ Branch 40 taken 45 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
181 name_ = params_.get<std::string>("preconditioner.type") + "-preconditioned " + params_.get<std::string>("type");
377
8/14
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 45 times.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 42 times.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 42 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
90 if (params_.get<int>("verbose", 0) > 0)
378 6 std::cout << "Initialized linear solver of type: " << name_ << std::endl;
379 45 }
380
381 45 void checkMandatoryParameters_()
382 {
383
6/14
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 45 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 45 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 45 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
90 if (!params_.hasKey("type"))
384 DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Type\" parameter to select the solver");
385
386
6/14
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 45 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 45 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 45 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 45 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 45 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
180 if (!params_.hasKey("preconditioner.type"))
387 DUNE_THROW(Dune::InvalidStateException, "Solver factory needs \"LinearSolver.Preconditioner.Type\" parameter to select the preconditioner");
388 45 }
389
390 #if HAVE_MPI
391 1011 void solveSequentialOrParallel_(Matrix& A, Vector& x, Vector& b)
392 {
393 // Dune::MultiTypeBlockMatrix does not provide a ColIterator which is needed by Dune::NonoverlappingSchwarzOperator.
394 // We therefore can only solve these types of systems sequentially.
395 // TODO: This can be adapted once the situation in Dune ISTL changes.
396 if constexpr (LinearSolverTraits::canCommunicate && !isMultiTypeBlockMatrix<Matrix>::value)
397 {
398
2/2
✓ Branch 0 taken 724 times.
✓ Branch 1 taken 287 times.
1011 if (isParallel_)
399 {
400
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 196 times.
✓ Branch 4 taken 98 times.
✓ Branch 5 taken 106 times.
1832 if (LinearSolverTraits::isNonOverlapping(parallelHelper_->gridView()))
401 {
402 using PTraits = typename LinearSolverTraits::template ParallelNonoverlapping<Matrix, Vector>;
403 286 solveParallel_<PTraits>(A, x, b);
404 }
405 else
406 {
407 using PTraits = typename LinearSolverTraits::template ParallelOverlapping<Matrix, Vector>;
408 438 solveParallel_<PTraits>(A, x, b);
409 }
410 }
411 else
412 287 solveSequential_(A, x, b);
413 }
414 else
415 {
416 51 solveSequential_(A, x, b);
417 }
418 1011 }
419
420 template<class ParallelTraits>
421 1448 void solveParallel_(Matrix& A, Vector& x, Vector& b)
422 {
423 using LinearOperator = typename ParallelTraits::LinearOperator;
424
425
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 694 times.
1448 if (firstCall_)
426 60 initSolverFactories<Matrix, LinearOperator>();
427
428 2896 prepareLinearAlgebraParallel<LinearSolverTraits, ParallelTraits>(A, b, *parallelHelper_);
429
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2896 auto linearOperator = std::make_shared<LinearOperator>(A, *comm_);
430
431 // construct solver
432
3/8
✓ Branch 1 taken 724 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 724 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 724 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
4344 auto solver = getSolverFromFactory_(linearOperator);
433
434 // solve linear system
435
2/4
✓ Branch 1 taken 724 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 724 times.
✗ Branch 5 not taken.
2896 solver->apply(x, b, result_);
436 1448 }
437 #endif // HAVE_MPI
438
439 338 void solveSequential_(Matrix& A, Vector& x, Vector& b)
440 {
441 // construct linear operator
442 using Traits = typename LinearSolverTraits::template Sequential<Matrix, Vector>;
443 using LinearOperator = typename Traits::LinearOperator;
444
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
338 auto linearOperator = std::make_shared<LinearOperator>(A);
445
446
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 323 times.
338 if (firstCall_)
447
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 initSolverFactories<Matrix, LinearOperator>();
448
449 // construct solver
450
3/8
✓ Branch 1 taken 338 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 338 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 338 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1014 auto solver = getSolverFromFactory_(linearOperator);
451
452 // solve linear system
453
2/4
✓ Branch 1 taken 338 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 338 times.
✗ Branch 5 not taken.
676 solver->apply(x, b, result_);
454 338 }
455
456 template<class LinearOperator>
457 1062 auto getSolverFromFactory_(std::shared_ptr<LinearOperator>& fop)
458 {
459
3/12
✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 51 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 51 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
3186 try { return Dune::getSolverFromFactory(fop, params_); }
460 catch(Dune::Exception& e)
461 {
462 std::cerr << "Could not create solver with factory" << std::endl;
463 std::cerr << e.what() << std::endl;
464 throw e;
465 }
466 }
467
468 const std::string paramGroup_;
469 #if HAVE_MPI
470 std::unique_ptr<ParallelISTLHelper<LinearSolverTraits>> parallelHelper_;
471 std::shared_ptr<Comm> comm_;
472 #endif
473 bool isParallel_ = false;
474 bool firstCall_;
475
476 std::shared_ptr<ScalarProduct> scalarProduct_;
477 Dune::SolverCategory::Category solverCategory_;
478 Dune::InverseOperatorResult result_;
479 Dune::ParameterTree params_;
480 std::string name_;
481 };
482
483 template<int i>
484 struct IstlSolverFactoryBackendImplHelper
485 {
486 template<class ...T>
487 using type = IstlSolverFactoryBackend<T...>;
488 };
489
490 template<>
491 struct IstlSolverFactoryBackendImplHelper<1>
492 {
493 template<class T>
494 using type = OldIstlSolverFactoryBackend<T>;
495 };
496
497 } // end namespace Detail
498
499 /*!
500 * \ingroup Linear
501 * \brief A linear solver using the dune-istl solver factory
502 * to choose the solver and preconditioner at runtime.
503 * \note the solvers are configured via the input file
504 * \note The template arguments are LinearSolverTraits, LinearAlgebraTraits
505 */
506 template<class ...T>
507 using IstlSolverFactoryBackend = typename Detail::IstlSolverFactoryBackendImplHelper<sizeof...(T)>::template type<T...>;
508
509 } // end namespace Dumux
510
511 #endif
512