version 3.11-dev
Loading...
Searching...
No Matches
istlsolvers.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// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_LINEAR_ISTL_SOLVERS_HH
13#define DUMUX_LINEAR_ISTL_SOLVERS_HH
14
15#include <memory>
16#include <type_traits>
17#include <variant>
18
19#include <dune/common/exceptions.hh>
20#include <dune/common/shared_ptr.hh>
21#include <dune/common/version.hh>
22#include <dune/common/parallel/indexset.hh>
23#include <dune/common/parallel/mpicommunication.hh>
24#include <dune/grid/common/capabilities.hh>
25#include <dune/istl/solvers.hh>
26#include <dune/istl/solverfactory.hh>
27#include <dune/istl/owneroverlapcopy.hh>
28#include <dune/istl/scalarproducts.hh>
29#include <dune/istl/paamg/amg.hh>
30#include <dune/istl/paamg/pinfo.hh>
31
32#include <dumux/io/format.hh>
42
43#include <dune/istl/foreach.hh>
44
46
53template<class M>
54constexpr std::size_t preconditionerBlockLevel() noexcept
55{
57}
58
59template<template<class,class,class,int> class Preconditioner, int blockLevel = 1>
61{
62public:
63 template<class OI, class M>
64 auto operator() (OI opInfo, const M& matrix, const Dune::ParameterTree& config)
65 {
66#if DUNE_VERSION_LT(DUNE_ISTL,2,11)
67 using Matrix = typename Dune::TypeListElement<0, decltype(opInfo)>::type;
68 using Domain = typename Dune::TypeListElement<1, decltype(opInfo)>::type;
69 using Range = typename Dune::TypeListElement<2, decltype(opInfo)>::type;
70#else
71 using OpInfo = std::decay_t<decltype(opInfo)>;
72 using Matrix = typename OpInfo::matrix_type;
73 using Domain = typename OpInfo::domain_type;
74 using Range = typename OpInfo::range_type;
75#endif
76 std::shared_ptr<Dune::Preconditioner<Domain, Range>> preconditioner
77 = std::make_shared<Preconditioner<Matrix, Domain, Range, blockLevel>>(matrix, config);
78 return preconditioner;
79 }
80};
81
82template<template<class,class,class> class Preconditioner>
84{
85 template<class OI, class M>
86 auto operator() (OI opInfo, const M& matrix, const Dune::ParameterTree& config)
87 {
88#if DUNE_VERSION_LT(DUNE_ISTL,2,11)
89 using Matrix = typename Dune::TypeListElement<0, decltype(opInfo)>::type;
90 using Domain = typename Dune::TypeListElement<1, decltype(opInfo)>::type;
91 using Range = typename Dune::TypeListElement<2, decltype(opInfo)>::type;
92#else
93 using OpInfo = std::decay_t<decltype(opInfo)>;
94 using Matrix = typename OpInfo::matrix_type;
95 using Domain = typename OpInfo::domain_type;
96 using Range = typename OpInfo::range_type;
97#endif
98 std::shared_ptr<Dune::Preconditioner<Domain, Range>> preconditioner
99 = std::make_shared<Preconditioner<Matrix, Domain, Range>>(matrix, config);
100 return preconditioner;
101 }
102};
103
104using IstlAmgPreconditionerFactory = Dune::AMGCreator;
105
106template<class M, bool convert = false>
107struct MatrixForSolver { using type = M; };
108
109template<class M>
110struct MatrixForSolver<M, true>
111{ using type = std::decay_t<decltype(MatrixConverter<M>::multiTypeToBCRSMatrix(std::declval<M>()))>; };
112
113template<class V, bool convert = false>
114struct VectorForSolver { using type = V; };
115
116template<class V>
117struct VectorForSolver<V, true>
118{ using type = std::decay_t<decltype(VectorConverter<V>::multiTypeToBlockVector(std::declval<V>()))>; };
119
120template<class LSTraits, class LATraits, bool convert, bool parallel = LSTraits::canCommunicate>
122
123template<class LSTraits, class LATraits, bool convert>
124struct MatrixOperator<LSTraits, LATraits, convert, true>
125{
128#if HAVE_MPI
129 using type = std::variant<
130 std::shared_ptr<typename LSTraits::template Sequential<M, V>::LinearOperator>,
131 std::shared_ptr<typename LSTraits::template ParallelOverlapping<M, V>::LinearOperator>,
132 std::shared_ptr<typename LSTraits::template ParallelNonoverlapping<M, V>::LinearOperator>
133 >;
134#else
135 using type = std::variant<
136 std::shared_ptr<typename LSTraits::template Sequential<M, V>::LinearOperator>
137 >;
138#endif
139};
140
141template<class LSTraits, class LATraits, bool convert>
142struct MatrixOperator<LSTraits, LATraits, convert, false>
143{
146 using type = std::variant<
147 std::shared_ptr<typename LSTraits::template Sequential<M, V>::LinearOperator>
148 >;
149};
150
151} // end namespace Dumux::Detail::IstlSolvers
152
153namespace Dumux::Detail {
154
155struct IstlSolverResult : public Dune::InverseOperatorResult
156{
157 IstlSolverResult() = default;
160
161 IstlSolverResult(const Dune::InverseOperatorResult& o) : InverseOperatorResult(o) {}
162 IstlSolverResult(Dune::InverseOperatorResult&& o) : InverseOperatorResult(std::move(o)) {}
163
164 operator bool() const { return this->converged; }
165};
166
171template<class LinearSolverTraits, class LinearAlgebraTraits,
172 class InverseOperator, class PreconditionerFactory,
173 bool convertMultiTypeLATypes = false>
175{
176 using Matrix = typename LinearAlgebraTraits::Matrix;
177 using XVector = typename LinearAlgebraTraits::Vector;
178 using BVector = typename LinearAlgebraTraits::Vector;
179 using Scalar = typename InverseOperator::real_type;
180
181 using ScalarProduct = Dune::ScalarProduct<typename InverseOperator::domain_type>;
182
183 static constexpr bool convertMultiTypeVectorAndMatrix
184 = convertMultiTypeLATypes && isMultiTypeBlockVector<XVector>::value;
188 // a variant type that can hold sequential, overlapping, and non-overlapping operators
189 using MatrixOperatorHolder = typename Detail::IstlSolvers::MatrixOperator<
190 LinearSolverTraits, LinearAlgebraTraits, convertMultiTypeVectorAndMatrix
191 >::type;
192
193#if HAVE_MPI
194 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>, int>;
195 using ParallelHelper = ParallelISTLHelper<LinearSolverTraits>;
196#endif
197
198 using ParameterInitializer = std::variant<std::string, Dune::ParameterTree>;
199public:
200
204 IstlIterativeLinearSolver(const ParameterInitializer& params = "")
205 {
206 if (Dune::MPIHelper::getCommunication().size() > 1)
207 DUNE_THROW(Dune::InvalidStateException, "Using sequential constructor for parallel run. Use signature with gridView and dofMapper!");
208
209 initializeParameters_(params);
210 solverCategory_ = Dune::SolverCategory::sequential;
211 scalarProduct_ = std::make_shared<ScalarProduct>();
212 }
213
217 template <class GridView, class DofMapper>
218 IstlIterativeLinearSolver(const GridView& gridView,
219 const DofMapper& dofMapper,
220 const ParameterInitializer& params = "")
221 {
222 initializeParameters_(params, gridView.comm());
223 configureCommunication_(gridView, dofMapper);
224 }
225
226#if HAVE_MPI
230 template <class GridView, class DofMapper>
231 IstlIterativeLinearSolver(std::shared_ptr<Comm> communication,
232 std::shared_ptr<ScalarProduct> scalarProduct,
233 const GridView& gridView,
234 const DofMapper& dofMapper,
235 const ParameterInitializer& params = "")
236 {
237 initializeParameters_(params, gridView.comm());
238 solverCategory_ = Detail::solverCategory(gridView);
239 scalarProduct_ = scalarProduct;
240 communication_ = communication;
241 if constexpr (LinearSolverTraits::canCommunicate)
242 {
243 if (solverCategory_ != Dune::SolverCategory::sequential)
244 buildParallelHelper_(gridView, dofMapper, *communication_);
245 }
246 }
247#endif
248
257 template <class GridView, class DofMapper>
258 void updateAfterGridAdaption(const GridView& gridView, const DofMapper& dofMapper)
259 { configureCommunication_(gridView, dofMapper); }
260
264 IstlSolverResult solve(Matrix& A, XVector& x, BVector& b)
265 { return solveSequentialOrParallel_(A, x, b); }
266
270 void setMatrix(std::shared_ptr<Matrix> A)
271 {
272 linearOperator_ = makeParallelOrSequentialLinearOperator_(std::move(A));
273 solver_ = constructPreconditionedSolver_(linearOperator_);
274 }
275
280 void setMatrix(Matrix& A)
281 { setMatrix(Dune::stackobject_to_shared_ptr(A)); }
282
286 IstlSolverResult solve(XVector& x, BVector& b) const
287 {
288 if (!solver_)
289 DUNE_THROW(Dune::InvalidStateException, "Called solve(x, b) but no linear operator has been set");
290
291 return solveSequentialOrParallel_(x, b, *solver_);
292 }
293
297 Scalar norm(const XVector& x) const
298 {
299#if HAVE_MPI
300 if constexpr (LinearSolverTraits::canCommunicate)
301 {
302 if (solverCategory_ == Dune::SolverCategory::nonoverlapping)
303 {
304 auto y(x); // make a copy because the vector needs to be made consistent
305 using GV = typename LinearSolverTraits::GridView;
306 using DM = typename LinearSolverTraits::DofMapper;
307 if constexpr (requires { LinearSolverTraits::dofCodims; })
308 {
309 MultiCodimParallelVectorHelper<GV, DM> vectorHelper(parallelHelper_->gridView(), parallelHelper_->dofMapper());
310 vectorHelper.makeNonOverlappingConsistent(y, LinearSolverTraits::dofCodims);
311 }
312 else
313 {
314 ParallelVectorHelper<GV, DM, LinearSolverTraits::dofCodim> vectorHelper(parallelHelper_->gridView(), parallelHelper_->dofMapper());
315 vectorHelper.makeNonOverlappingConsistent(y);
316 }
317 return scalarProduct_->norm(y);
318 }
319 }
320#endif
321 if constexpr (convertMultiTypeVectorAndMatrix)
322 {
324 return scalarProduct_->norm(y);
325 }
326 else
327 return scalarProduct_->norm(x);
328 }
329
333 const std::string& name() const
334 {
335 return name_;
336 }
337
341 void setResidualReduction(double residReduction)
342 {
343 params_["reduction"] = Fmt::format("{}", residReduction);
344
345 // reconstruct the solver with new parameters
346 if (solver_)
347 solver_ = constructPreconditionedSolver_(linearOperator_);
348 }
349
353 void setMaxIter(std::size_t maxIter)
354 {
355 params_["maxit"] = std::to_string(maxIter);
356
357 // reconstruct the solver with new parameters
358 if (solver_)
359 solver_ = constructPreconditionedSolver_(linearOperator_);
360 }
361
367 void setParams(const ParameterInitializer& params)
368 {
369#if HAVE_MPI
370 if (communication_)
371 initializeParameters_(params, communication_->communicator());
372 else
373 initializeParameters_(params);
374#else
375 initializeParameters_(params);
376#endif
377
378 // reconstruct the solver with new parameters
379 if (solver_)
380 solver_ = constructPreconditionedSolver_(linearOperator_);
381 }
382
383private:
384
385 void initializeParameters_(const ParameterInitializer& params)
386 {
387 if (std::holds_alternative<std::string>(params))
388 params_ = Dumux::LinearSolverParameters<LinearSolverTraits>::createParameterTree(std::get<std::string>(params));
389 else
390 params_ = std::get<Dune::ParameterTree>(params);
391 }
392
393 template <class Comm>
394 void initializeParameters_(const ParameterInitializer& params, const Comm& comm)
395 {
396 initializeParameters_(params);
397
398 // disable verbose output on all ranks except rank 0
399 if (comm.rank() != 0)
401 }
402
409 template <class GridView, class DofMapper>
410 void configureCommunication_(const GridView& gridView, const DofMapper& dofMapper)
411 {
412#if HAVE_MPI
413 solverCategory_ = Detail::solverCategory<LinearSolverTraits>(gridView);
414 if constexpr (LinearSolverTraits::canCommunicate)
415 {
416 if (solverCategory_ == Dune::SolverCategory::sequential)
417 scalarProduct_ = std::make_shared<ScalarProduct>();
418 else
419 {
420 communication_ = std::make_shared<Comm>(gridView.comm(), solverCategory_);
421 scalarProduct_ = Dune::createScalarProduct<XVector>(*communication_, solverCategory_);
422 buildParallelHelper_(gridView, dofMapper, *communication_);
423 }
424 }
425 else
426 scalarProduct_ = std::make_shared<ScalarProduct>();
427#else
428 solverCategory_ = Dune::SolverCategory::sequential;
429 scalarProduct_ = std::make_shared<ScalarProduct>();
430#endif
431 linearOperator_ = MatrixOperatorHolder{};
432 solver_ = nullptr;
433 }
434
435#if HAVE_MPI
437 template <class GridView, class DofMapper>
438 void buildParallelHelper_(const GridView& gridView, const DofMapper& dofMapper, Comm& comm)
439 {
440 parallelHelper_ = std::make_shared<ParallelISTLHelper<LinearSolverTraits>>(gridView, dofMapper);
441 parallelHelper_->createParallelIndexSet(comm);
442 }
443#endif
444
445 MatrixOperatorHolder makeSequentialLinearOperator_(std::shared_ptr<Matrix> A)
446 {
447 using SequentialTraits = typename LinearSolverTraits::template Sequential<MatrixForSolver, XVectorForSolver>;
448 if constexpr (convertMultiTypeVectorAndMatrix)
449 {
450 // create the BCRS matrix the IterativeSolver backend can handle
451 auto M = std::make_shared<MatrixForSolver>(MatrixConverter<Matrix>::multiTypeToBCRSMatrix(*A));
452 return std::make_shared<typename SequentialTraits::LinearOperator>(M);
453 }
454 else
455 {
456 return std::make_shared<typename SequentialTraits::LinearOperator>(A);
457 }
458 }
459
460 template<class ParallelTraits>
461 MatrixOperatorHolder makeParallelLinearOperator_(std::shared_ptr<Matrix> A, ParallelTraits = {})
462 {
463#if HAVE_MPI
464 // make matrix consistent
466 return std::make_shared<typename ParallelTraits::LinearOperator>(std::move(A), *communication_);
467#else
468 DUNE_THROW(Dune::InvalidStateException, "Calling makeParallelLinearOperator for sequential run");
469#endif
470 }
471
472 MatrixOperatorHolder makeParallelOrSequentialLinearOperator_(std::shared_ptr<Matrix> A)
473 {
474 return executeSequentialOrParallel_(
475 [&]{ return makeSequentialLinearOperator_(std::move(A)); },
476 [&](auto traits){ return makeParallelLinearOperator_(std::move(A), traits); }
477 );
478 }
479
480 MatrixOperatorHolder makeSequentialLinearOperator_(Matrix& A)
481 { return makeSequentialLinearOperator_(Dune::stackobject_to_shared_ptr<Matrix>(A)); }
482
483 MatrixOperatorHolder makeParallelOrSequentialLinearOperator_(Matrix& A)
484 { return makeParallelOrSequentialLinearOperator_(Dune::stackobject_to_shared_ptr<Matrix>(A)); }
485
486 template<class ParallelTraits>
487 MatrixOperatorHolder makeParallelLinearOperator_(Matrix& A, ParallelTraits = {})
488 { return makeParallelLinearOperator_<ParallelTraits>(Dune::stackobject_to_shared_ptr<Matrix>(A)); }
489
490 IstlSolverResult solveSequential_(Matrix& A, XVector& x, BVector& b)
491 {
492 // construct solver from linear operator
493 auto linearOperatorHolder = makeSequentialLinearOperator_(A);
494 auto solver = constructPreconditionedSolver_(linearOperatorHolder);
495
496 return solveSequential_(x, b, *solver);
497 }
498
499 IstlSolverResult solveSequential_(XVector& x, BVector& b, InverseOperator& solver) const
500 {
501 Dune::InverseOperatorResult result;
502 if constexpr (convertMultiTypeVectorAndMatrix)
503 {
504 // create the vector the IterativeSolver backend can handle
505 BVectorForSolver bTmp = VectorConverter<BVector>::multiTypeToBlockVector(b);
506
507 // create a block vector to which the linear solver writes the solution
508 XVectorForSolver y(bTmp.size());
509
510 // solve linear system
511 solver.apply(y, bTmp, result);
512
513 // copy back the result y into x
514 if (result.converged)
516 }
517 else
518 {
519 // solve linear system
520 solver.apply(x, b, result);
521 }
522
523 return result;
524 }
525
526 IstlSolverResult solveSequentialOrParallel_(Matrix& A, XVector& x, BVector& b)
527 {
528 return executeSequentialOrParallel_(
529 [&]{ return solveSequential_(A, x, b); },
530 [&](auto traits){ return solveParallel_(A, x, b, traits); }
531 );
532 }
533
534 IstlSolverResult solveSequentialOrParallel_(XVector& x, BVector& b, InverseOperator& solver) const
535 {
536 return executeSequentialOrParallel_(
537 [&]{ return solveSequential_(x, b, solver); },
538 [&](auto traits){ return solveParallel_(x, b, solver, traits); }
539 );
540 }
541
542 template<class ParallelTraits>
543 IstlSolverResult solveParallel_(Matrix& A, XVector& x, BVector& b, ParallelTraits = {})
544 {
545 // construct solver from linear operator
546 auto linearOperatorHolder = makeParallelLinearOperator_<ParallelTraits>(A);
547 auto solver = constructPreconditionedSolver_(linearOperatorHolder);
548 return solveParallel_<ParallelTraits>(x, b, *solver);
549 }
550
551 template<class ParallelTraits>
552 IstlSolverResult solveParallel_(XVector& x, BVector& b, InverseOperator& solver, ParallelTraits = {}) const
553 {
554#if HAVE_MPI
555 // make right hand side consistent
557
558 // solve linear system
559 Dune::InverseOperatorResult result;
560 solver.apply(x, b, result);
561 return result;
562#else
563 DUNE_THROW(Dune::InvalidStateException, "Calling makeParallelLinearOperator for sequential run");
564#endif
565 }
566
567
568 std::shared_ptr<InverseOperator> constructPreconditionedSolver_(MatrixOperatorHolder& ops)
569 {
570 return std::visit([&](auto&& op)
571 {
572 using LinearOperator = typename std::decay_t<decltype(op)>::element_type;
573 const auto& params = params_.sub("preconditioner");
574 using Prec = Dune::Preconditioner<typename LinearOperator::domain_type, typename LinearOperator::range_type>;
575#if DUNE_VERSION_GTE(DUNE_ISTL,2,11)
576 using OpTraits = Dune::OperatorTraits<LinearOperator>;
577 std::shared_ptr<Prec> prec = PreconditionerFactory{}(OpTraits{}, op, params);
578#else
579 using TL = Dune::TypeList<typename LinearOperator::matrix_type, typename LinearOperator::domain_type, typename LinearOperator::range_type>;
580 std::shared_ptr<Prec> prec = PreconditionerFactory{}(TL{}, op, params);
581#endif
582
583#if HAVE_MPI
584#if DUNE_VERSION_LT(DUNE_ISTL,2,11)
585 if (prec->category() != op->category() && prec->category() == Dune::SolverCategory::sequential)
586 prec = Dune::wrapPreconditioner4Parallel(prec, op);
587#else
588 if constexpr (OpTraits::isParallel)
589 {
590 using Comm = typename OpTraits::comm_type;
591 const Comm& comm = OpTraits::getCommOrThrow(op);
592 if (op->category() == Dune::SolverCategory::overlapping && prec->category() == Dune::SolverCategory::sequential)
593 prec = std::make_shared<Dune::BlockPreconditioner<typename OpTraits::domain_type, typename OpTraits::range_type,Comm> >(prec, comm);
594 else if (op->category() == Dune::SolverCategory::nonoverlapping && prec->category() == Dune::SolverCategory::sequential)
595 prec = std::make_shared<Dune::NonoverlappingBlockPreconditioner<Comm, Prec> >(prec, comm);
596 }
597#endif
598#endif
599 return std::make_shared<InverseOperator>(op, scalarProduct_, prec, params_);
600 }, ops);
601 }
602
603 template<class Seq, class Par>
604 decltype(auto) executeSequentialOrParallel_(Seq&& sequentialAction, Par&& parallelAction) const
605 {
606#if HAVE_MPI
607 // For Dune::MultiTypeBlockMatrix there is currently no generic way
608 // of handling parallelism, we therefore can only solve these types of systems sequentially
609 if constexpr (isMultiTypeBlockMatrix<Matrix>::value || !LinearSolverTraits::canCommunicate)
610 return sequentialAction();
611 else
612 {
613 switch (solverCategory_)
614 {
615 case Dune::SolverCategory::sequential:
616 return sequentialAction();
617 case Dune::SolverCategory::nonoverlapping:
618 using NOTraits = typename LinearSolverTraits::template ParallelNonoverlapping<Matrix, XVector>;
619 return parallelAction(NOTraits{});
620 case Dune::SolverCategory::overlapping:
621 using OTraits = typename LinearSolverTraits::template ParallelOverlapping<Matrix, XVector>;
622 return parallelAction(OTraits{});
623 default: DUNE_THROW(Dune::InvalidStateException, "Unknown solver category");
624 }
625 }
626#else
627 return sequentialAction();
628#endif
629 }
630
631#if HAVE_MPI
632 std::shared_ptr<const ParallelHelper> parallelHelper_;
633 std::shared_ptr<Comm> communication_;
634#endif
635
636 Dune::SolverCategory::Category solverCategory_;
637 std::shared_ptr<ScalarProduct> scalarProduct_;
638
639 // for stored solvers (reuse matrix)
640 MatrixOperatorHolder linearOperator_;
641 // for stored solvers (reuse matrix)
642 std::shared_ptr<InverseOperator> solver_;
643
644 Dune::ParameterTree params_;
645 std::string name_;
646};
647
648} // end namespace Dumux::Detail
649
650namespace Dumux {
651
668template<class LSTraits, class LATraits>
670 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
671 Dune::BiCGSTABSolver<typename LATraits::SingleTypeVector>,
673 // the Dune::ILU preconditioners don't accept multi-type matrices
674 /*convert multi-type istl types?*/ true
675 >;
676
693template<class LSTraits, class LATraits>
695 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
696 Dune::RestartedGMResSolver<typename LATraits::SingleTypeVector>,
698 // the Dune::ILU preconditioners don't accept multi-type matrices
699 /*convert multi-type istl types?*/ true
700 >;
701
719template<class LSTraits, class LATraits>
721 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
722 Dune::BiCGSTABSolver<typename LATraits::Vector>,
724 >;
725
742template<class LSTraits, class LATraits>
744 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
745 Dune::CGSolver<typename LATraits::Vector>,
747 >;
748
762template<class LSTraits, class LATraits>
764 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
765 Dune::BiCGSTABSolver<typename LATraits::SingleTypeVector>,
767 // the AMG preconditioner doesn't accept multi-type matrices
768 /*convert multi-type istl types?*/ true
769 >;
770
783template<class LSTraits, class LATraits>
785 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
786 Dune::CGSolver<typename LATraits::SingleTypeVector>,
788 // the AMG preconditioner doesn't accept multi-type matrices
789 /*convert multi-type istl types?*/ true
790 >;
791
807template<class LSTraits, class LATraits>
809 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
810 Dune::RestartedGMResSolver<typename LATraits::SingleTypeVector>,
812 // the AMG preconditioner doesn't accept multi-type matrices
813 /*convert multi-type istl types?*/ true
814 >;
815
830template<class LSTraits, class LATraits>
832 Detail::IstlIterativeLinearSolver<LSTraits, LATraits,
833 Dune::BiCGSTABSolver<typename LATraits::Vector>,
835 >;
836
837} // end namespace Dumux
838
839namespace Dumux::Detail {
840
845template<class LSTraits, class LATraits, template<class M> class Solver,
846 bool convertMultiTypeVectorAndMatrix = isMultiTypeBlockVector<typename LATraits::Vector>::value>
848{
849 using Matrix = typename LATraits::Matrix;
850 using XVector = typename LATraits::Vector;
851 using BVector = typename LATraits::Vector;
852
856 using InverseOperator = Dune::InverseOperator<XVectorForSolver, BVectorForSolver>;
857public:
859
863 IstlSolverResult solve(const Matrix& A, XVector& x, const BVector& b)
864 {
865 return solve_(A, x, b);
866 }
867
871 IstlSolverResult solve(XVector& x, const BVector& b)
872 {
873 if (!solver_)
874 DUNE_THROW(Dune::InvalidStateException, "Called solve(x, b) but no linear operator has been set");
875
876 return solve_(x, b, *solver_);
877 }
878
882 void setMatrix(std::shared_ptr<Matrix> A)
883 {
884 if constexpr (convertMultiTypeVectorAndMatrix)
885 matrix_ = std::make_shared<MatrixForSolver>(MatrixConverter<Matrix>::multiTypeToBCRSMatrix(A));
886 else
887 matrix_ = A;
888
889 solver_ = std::make_shared<Solver<MatrixForSolver>>(*matrix_);
890 }
891
896 void setMatrix(Matrix& A)
897 { setMatrix(Dune::stackobject_to_shared_ptr(A)); }
898
902 std::string name() const
903 {
904 return "Direct solver";
905 }
906
907private:
908 IstlSolverResult solve_(const Matrix& A, XVector& x, const BVector& b)
909 {
910 // support dune-istl multi-type block vector/matrix by copying
911 if constexpr (convertMultiTypeVectorAndMatrix)
912 {
914 Solver<MatrixForSolver> solver(AA, this->verbosity() > 0);
915 return solve_(x, b, solver);
916 }
917 else
918 {
919 Solver<MatrixForSolver> solver(A, this->verbosity() > 0);
920 return solve_(x, b, solver);
921 }
922 }
923
924 IstlSolverResult solve_(XVector& x, const BVector& b, InverseOperator& solver) const
925 {
926 Dune::InverseOperatorResult result;
927
928 if constexpr (convertMultiTypeVectorAndMatrix)
929 {
931 XVectorForSolver xx(bb.size());
932 solver.apply(xx, bb, result);
933 checkResult_(xx, result);
934 if (result.converged)
936 return result;
937 }
938 else
939 {
940 BVectorForSolver bTmp(b);
941 solver.apply(x, bTmp, result);
942 checkResult_(x, result);
943 return result;
944 }
945 }
946
947
948 void checkResult_(XVectorForSolver& x, Dune::InverseOperatorResult& result) const
949 {
950 flatVectorForEach(x, [&](auto&& entry, std::size_t){
951 using std::isnan, std::isinf;
952 if (isnan(entry) || isinf(entry))
953 result.converged = false;
954 });
955 }
956
958 std::shared_ptr<MatrixForSolver> matrix_;
960 std::shared_ptr<InverseOperator> solver_;
961};
962
963} // end namespace Dumux::Detail
964
965#if HAVE_SUPERLU
966#include <dune/istl/superlu.hh>
967
968namespace Dumux {
969
978template<class LSTraits, class LATraits>
980
981} // end namespace Dumux
982
983#endif // HAVE_SUPERLU
984
985#if HAVE_UMFPACK
986#include <dune/istl/umfpack.hh>
987
988namespace Dumux {
989
998template<class LSTraits, class LATraits>
1000
1001} // end namespace Dumux
1002
1003#endif // HAVE_UMFPACK
1004
1005#endif
Direct dune-istl linear solvers.
Definition istlsolvers.hh:848
void setMatrix(std::shared_ptr< Matrix > A)
Set the matrix A of the linear system Ax = b for reuse.
Definition istlsolvers.hh:882
IstlSolverResult solve(const Matrix &A, XVector &x, const BVector &b)
Solve the linear system Ax = b.
Definition istlsolvers.hh:863
std::string name() const
name of the linear solver
Definition istlsolvers.hh:902
void setMatrix(Matrix &A)
Set the matrix A of the linear system Ax = b for reuse.
Definition istlsolvers.hh:896
LinearSolver(const std::string &paramGroup="")
Construct the solver.
Definition solver.hh:43
IstlSolverResult solve(XVector &x, const BVector &b)
Solve the linear system Ax = b using the matrix set with setMatrix.
Definition istlsolvers.hh:871
Standard dune-istl iterative linear solvers.
Definition istlsolvers.hh:175
IstlIterativeLinearSolver(const ParameterInitializer &params="")
Constructor for sequential solvers.
Definition istlsolvers.hh:204
void setMatrix(Matrix &A)
Set the matrix A of the linear system Ax = b for reuse.
Definition istlsolvers.hh:280
void setResidualReduction(double residReduction)
Set the residual reduction tolerance.
Definition istlsolvers.hh:341
void setMaxIter(std::size_t maxIter)
Set the maximum number of linear solver iterations.
Definition istlsolvers.hh:353
IstlIterativeLinearSolver(const GridView &gridView, const DofMapper &dofMapper, const ParameterInitializer &params="")
Constructor for parallel and sequential solvers.
Definition istlsolvers.hh:218
const std::string & name() const
The name of the linear solver.
Definition istlsolvers.hh:333
void setParams(const ParameterInitializer &params)
Set the linear solver parameters.
Definition istlsolvers.hh:367
IstlSolverResult solve(Matrix &A, XVector &x, BVector &b)
Solve the linear system Ax = b.
Definition istlsolvers.hh:264
void updateAfterGridAdaption(const GridView &gridView, const DofMapper &dofMapper)
Update the solver after the grid and its dof distribution changed, e.g. after grid adaption or dynami...
Definition istlsolvers.hh:258
void setMatrix(std::shared_ptr< Matrix > A)
Set the matrix A of the linear system Ax = b for reuse.
Definition istlsolvers.hh:270
IstlSolverResult solve(XVector &x, BVector &b) const
Solve the linear system Ax = b where A has been set with setMatrix.
Definition istlsolvers.hh:286
IstlIterativeLinearSolver(std::shared_ptr< Comm > communication, std::shared_ptr< ScalarProduct > scalarProduct, const GridView &gridView, const DofMapper &dofMapper, const ParameterInitializer &params="")
Constructor with custom scalar product and communication.
Definition istlsolvers.hh:231
Scalar norm(const XVector &x) const
Compute the 2-norm of vector x.
Definition istlsolvers.hh:297
auto operator()(OI opInfo, const M &matrix, const Dune::ParameterTree &config)
Definition istlsolvers.hh:64
LinearSolver(const std::string &paramGroup="")
Construct the solver.
Definition solver.hh:43
int verbosity() const
the verbosity level
Definition solver.hh:82
static void disableVerbosity(Dune::ParameterTree &params)
Definition linearsolverparameters.hh:97
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:47
static auto multiTypeToBCRSMatrix(const MultiTypeBlockMatrix &A)
Converts the matrix to a type the IterativeSolverBackend can handle.
Definition matrixconverter.hh:46
Definition parallelhelpers.hh:580
void makeNonOverlappingConsistent(Dune::BlockVector< Block, Alloc > &v, const std::bitset< numCodims > &activeCodims) const
Make a vector consistent for non-overlapping domain decomposition methods.
Definition parallelhelpers.hh:588
Definition parallelhelpers.hh:522
void makeNonOverlappingConsistent(Dune::BlockVector< Block, Alloc > &v) const
Make a vector consistent for non-overlapping domain decomposition methods.
Definition parallelhelpers.hh:530
static void retrieveValues(MultiTypeBlockVector &x, const BlockVector &y)
Copies the entries of a Dune::BlockVector to a Dune::MultiTypeBlockVector.
Definition matrixconverter.hh:229
static auto multiTypeToBlockVector(const MultiTypeBlockVector &b)
Converts a Dune::MultiTypeBlockVector to a plain 1x1 Dune::BlockVector.
Definition matrixconverter.hh:203
Formatting based on the fmt-library which implements std::format of C++20.
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::BiCGSTABSolver< typename LATraits::Vector >, Detail::IstlSolvers::IstlDefaultBlockLevelPreconditionerFactory< Dumux::SeqUzawa > > UzawaBiCGSTABIstlSolver
An Uzawa preconditioned BiCGSTAB solver using dune-istl.
Definition istlsolvers.hh:831
constexpr std::size_t preconditionerBlockLevel() noexcept
Returns the block level for the preconditioner for a given matrix.
Definition istlsolvers.hh:54
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::RestartedGMResSolver< typename LATraits::SingleTypeVector >, Detail::IstlSolvers::IstlDefaultBlockLevelPreconditionerFactory< Dune::SeqILU >, true > ILURestartedGMResIstlSolver
An ILU preconditioned GMres solver using dune-istl.
Definition istlsolvers.hh:694
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::BiCGSTABSolver< typename LATraits::Vector >, Detail::IstlSolvers::IstlDefaultBlockLevelPreconditionerFactory< Dune::SeqSSOR > > SSORBiCGSTABIstlSolver
An SSOR-preconditioned BiCGSTAB solver using dune-istl.
Definition istlsolvers.hh:720
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::RestartedGMResSolver< typename LATraits::SingleTypeVector >, Detail::IstlSolvers::IstlAmgPreconditionerFactory, true > AMGRestartedGMResIstlSolver
An AMG preconditioned GMRes solver using dune-istl.
Definition istlsolvers.hh:808
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::BiCGSTABSolver< typename LATraits::SingleTypeVector >, Detail::IstlSolvers::IstlDefaultBlockLevelPreconditionerFactory< Dune::SeqILU >, true > ILUBiCGSTABIstlSolver
An ILU preconditioned BiCGSTAB solver using dune-istl.
Definition istlsolvers.hh:669
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::BiCGSTABSolver< typename LATraits::SingleTypeVector >, Detail::IstlSolvers::IstlAmgPreconditionerFactory, true > AMGBiCGSTABIstlSolver
An AMG preconditioned BiCGSTAB solver using dune-istl.
Definition istlsolvers.hh:763
Detail::ParallelISTLHelperImpl< LinearSolverTraits, LinearSolverTraits::canCommunicate > ParallelISTLHelper
A parallel helper class providing a parallel decomposition of all degrees of freedom.
Definition parallelhelpers.hh:514
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::CGSolver< typename LATraits::SingleTypeVector >, Detail::IstlSolvers::IstlAmgPreconditionerFactory, true > AMGCGIstlSolver
An AMG preconditioned CG solver using dune-istl.
Definition istlsolvers.hh:784
Detail::IstlIterativeLinearSolver< LSTraits, LATraits, Dune::CGSolver< typename LATraits::Vector >, Detail::IstlSolvers::IstlDefaultBlockLevelPreconditionerFactory< Dune::SeqSSOR > > SSORCGIstlSolver
An SSOR-preconditioned CG solver using dune-istl.
Definition istlsolvers.hh:743
Define traits for linear algebra backends.
Generates a parameter tree required for the linear solvers and precondioners of the Dune ISTL.
Type traits to be used with matrix types.
A helper class that converts a Dune::MultiTypeBlockMatrix into a plain Dune::BCRSMatrix.
Definition istlsolvers.hh:45
Dune::AMGCreator IstlAmgPreconditionerFactory
Definition istlsolvers.hh:104
Definition linearalgebratraits.hh:21
Definition cvfelocalresidual.hh:25
Dune::SolverCategory::Category solverCategory(const GridView &gridView)
Definition solvercategory.hh:20
Definition adapt.hh:17
void prepareMatrixParallel(Matrix &A, ParallelHelper &pHelper)
Prepare a matrix for parallel solvers.
Definition parallelhelpers.hh:1420
LinearSolverTraitsImpl< GridGeometry, typename GridGeometry::DiscretizationMethod > LinearSolverTraits
The type traits required for using the IstlFactoryBackend.
Definition linearsolvertraits.hh:39
void prepareVectorParallel(Vector &b, ParallelHelper &pHelper)
Prepare a vector for parallel solvers.
Definition parallelhelpers.hh:1451
Provides a helper class for nonoverlapping decomposition.
Dumux preconditioners for iterative solvers.
Base class for linear solvers.
Solver category.
Definition istlsolvers.hh:156
IstlSolverResult(IstlSolverResult &&)=default
IstlSolverResult(const Dune::InverseOperatorResult &o)
Definition istlsolvers.hh:161
IstlSolverResult(Dune::InverseOperatorResult &&o)
Definition istlsolvers.hh:162
IstlSolverResult(const IstlSolverResult &)=default
std::decay_t< decltype(MatrixConverter< M >::multiTypeToBCRSMatrix(std::declval< M >()))> type
Definition istlsolvers.hh:111
Definition istlsolvers.hh:107
M type
Definition istlsolvers.hh:107
typename VectorForSolver< typename LATraits::Vector, convert >::type V
Definition istlsolvers.hh:145
std::variant< std::shared_ptr< typename LSTraits::template Sequential< M, V >::LinearOperator > > type
Definition istlsolvers.hh:146
typename MatrixForSolver< typename LATraits::Matrix, convert >::type M
Definition istlsolvers.hh:144
typename VectorForSolver< typename LATraits::Vector, convert >::type V
Definition istlsolvers.hh:127
std::variant< std::shared_ptr< typename LSTraits::template Sequential< M, V >::LinearOperator >, std::shared_ptr< typename LSTraits::template ParallelOverlapping< M, V >::LinearOperator >, std::shared_ptr< typename LSTraits::template ParallelNonoverlapping< M, V >::LinearOperator > > type
Definition istlsolvers.hh:129
typename MatrixForSolver< typename LATraits::Matrix, convert >::type M
Definition istlsolvers.hh:126
Definition istlsolvers.hh:121
std::decay_t< decltype(VectorConverter< V >::multiTypeToBlockVector(std::declval< V >()))> type
Definition istlsolvers.hh:118
Definition istlsolvers.hh:114
V type
Definition istlsolvers.hh:114
Definition linearalgebratraits.hh:51
V Vector
Definition linearalgebratraits.hh:53
M Matrix
Definition linearalgebratraits.hh:52
Helper type to determine whether a given type is a Dune::MultiTypeBlockMatrix.
Definition matrix.hh:37
Helper type to determine whether a given type is a Dune::MultiTypeBlockVector.
Definition vector.hh:22
Type traits to be used with vector types.