12#ifndef DUMUX_LINEAR_PRECONDITIONERS_HH
13#define DUMUX_LINEAR_PRECONDITIONERS_HH
15#include <dune/common/exceptions.hh>
16#include <dune/common/float_cmp.hh>
17#include <dune/common/indices.hh>
18#include <dune/istl/preconditioners.hh>
19#include <dune/istl/paamg/amg.hh>
20#include <dune/istl/gsetc.hh>
23#include <dune/istl/umfpack.hh>
68template<
class M,
class X,
class Y,
int l = 1>
69class SeqUzawa :
public Dune::Preconditioner<X,Y>
72 static_assert(l== 1,
"SeqUzawa expects a block level of 1.");
74 using A = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_0][Dune::Indices::_0])>;
75 using U = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_0])>;
77 using Comm = Dune::Amg::SequentialInformation;
78 using LinearOperator = Dune::MatrixAdapter<A, U, U>;
79 using Smoother = Dune::SeqSSOR<A, U, U>;
80 using AMGSolverForA = Dune::Amg::AMG<LinearOperator, U, Smoother, Comm>;
100 SeqUzawa(
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& op,
const Dune::ParameterTree& params)
101 : matrix_(op->getmat())
102 , numIterations_(params.get<std::size_t>(
"iterations"))
104 , verbosity_(params.get<int>(
"verbosity"))
105 , paramGroup_(params.get<std::string>(
"ParameterGroup"))
106 , useDirectVelocitySolverForA_(
getParamFromGroup<bool>(paramGroup_,
"LinearSolver.Preconditioner.DirectSolverForA", false))
108 const bool determineRelaxationFactor = getParamFromGroup<bool>(paramGroup_,
"LinearSolver.Preconditioner.DetermineRelaxationFactor",
true);
111 if (determineRelaxationFactor || !useDirectVelocitySolverForA_)
114 if (useDirectVelocitySolverForA_)
117 if (determineRelaxationFactor)
118 relaxationFactor_ = estimateOmega_();
124 virtual void pre(X& x, Y& b) {}
132 virtual void apply(X& update,
const Y& currentDefect)
134 using namespace Dune::Indices;
136 auto& A = matrix_[_0][_0];
137 auto& B = matrix_[_0][_1];
138 auto& C = matrix_[_1][_0];
139 auto& D = matrix_[_1][_1];
141 const auto& f = currentDefect[_0];
142 const auto& g = currentDefect[_1];
143 auto& u = update[_0];
144 auto& p = update[_1];
148 for (std::size_t i = 0; i < D.N(); ++i)
150 const auto& block = D[i][i];
151 for (
auto rowIt = block.begin(); rowIt != block.end(); ++rowIt)
152 if (Dune::FloatCmp::eq<scalar_field_type>(rowIt->one_norm(), 1.0))
153 p[i][rowIt.index()] = g[i][rowIt.index()];
157 for (std::size_t k = 0; k < numIterations_; ++k)
164 applySolverForA_(uIncrement, uRhs);
169 C.mmv(u, pIncrement);
170 D.mmv(p, pIncrement);
171 pIncrement *= relaxationFactor_;
176 std::cout <<
"Uzawa iteration " << k
177 <<
", residual: " << uRhs.two_norm() + pIncrement.two_norm()/relaxationFactor_ << std::endl;
188 virtual Dune::SolverCategory::Category
category()
const
190 return Dune::SolverCategory::sequential;
195 void initAMG_(
const Dune::ParameterTree& params)
197 using namespace Dune::Indices;
198 auto linearOperator = std::make_shared<LinearOperator>(matrix_[_0][_0]);
199 amgSolverForA_ = std::make_unique<AMGSolverForA>(linearOperator, params);
205 using namespace Dune::Indices;
206 umfPackSolverForA_ = std::make_unique<Dune::UMFPack<A>>(matrix_[_0][_0]);
208 DUNE_THROW(Dune::InvalidStateException,
"UMFPack not available. Use LinearSolver.Preconditioner.DirectVelocitySolver = false.");
233 using namespace Dune::Indices;
234 auto& A = matrix_[_0][_0];
235 auto& B = matrix_[_0][_1];
236 auto& C = matrix_[_1][_0];
244 static const auto iterations = Dumux::getParamFromGroup<std::size_t>(paramGroup_,
"LinearSolver.Preconditioner.PowerLawIterations", 5);
247 for (std::size_t i = 0; i < iterations; ++i)
255 applySolverForA_(ainvbx, bx);
263 lambdaMax = x.dot(v)/(x.dot(x));
266 omega = 1.0/lambdaMax;
275 std::cout <<
"\n*** Uzawa Preconditioner ***" << std::endl;
276 std::cout <<
"Estimating relaxation factor based on Schur complement" << std::endl;
277 std::cout <<
"Largest estimated eigenvalue lambdaMax = " << lambdaMax << std::endl;
278 std::cout <<
"Relaxation factor omega = 1/lambdaMax = " << omega << std::endl;
284 template<
class Sol,
class Rhs>
285 void applySolverForA_(Sol& sol, Rhs& rhs)
const
287 if (useDirectVelocitySolverForA_)
290 Dune::InverseOperatorResult res;
291 umfPackSolverForA_->apply(sol, rhs, res);
296 amgSolverForA_->pre(sol, rhs);
297 amgSolverForA_->apply(sol, rhs);
298 amgSolverForA_->post(sol);
305 const std::size_t numIterations_;
309 const int verbosity_;
311 std::unique_ptr<AMGSolverForA> amgSolverForA_;
313 std::unique_ptr<Dune::UMFPack<A>> umfPackSolverForA_;
315 const std::string paramGroup_;
316 const bool useDirectVelocitySolverForA_;
329template<
class M,
class X,
class Y,
int l=1>
348 : _A_(A), numSteps_(n), relaxationFactor_(w)
349 { Dune::CheckIfDiagonalPresent<M,l>::check(_A_); }
351 ParMTJac (
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& A,
const Dune::ParameterTree& configuration)
352 :
ParMTJac(A->getmat(), configuration)
355 ParMTJac (
const M& A,
const Dune::ParameterTree& configuration)
359 void pre (X&, Y&)
override {}
361 void apply (X& update,
const Y& defect)
override
366 for (
int k=0; k<numSteps_; k++)
375 auto rhs = defect[i];
376 const auto endColIt = row.end();
377 auto colIt = row.begin();
379 for (; colIt.index()<i; ++colIt)
380 colIt->mmv(xOld[colIt.index()], rhs);
381 const auto diag = colIt;
382 for (; colIt != endColIt; ++colIt)
383 colIt->mmv(xOld[colIt.index()], rhs);
385 Dune::algmeta_itsteps<l-1, typename M::block_type>::dbjac(
386 *diag, v, rhs, relaxationFactor_
389 update[i].axpy(relaxationFactor_, v);
397 Dune::SolverCategory::Category
category()
const override
398 {
return Dune::SolverCategory::sequential; }
409namespace Detail::Preconditioners {
416 std::vector<int> colors(matrix.N(), -1);
417 std::vector<int> neighborColors; neighborColors.reserve(30);
418 std::vector<bool> colorUsed; colorUsed.reserve(30);
422 for (std::size_t i = 0; i < colors.size(); ++i)
424 neighborColors.clear();
425 auto& row = matrix[i];
426 const auto endColIt = row.end();
427 for (
auto colIt = row.begin(); colIt != endColIt; ++colIt)
428 neighborColors.push_back(colors[colIt.index()]);
430 const auto c = Detail::smallestAvailableColor(neighborColors, colorUsed);
434 if (c < coloredIndices.size())
435 coloredIndices[c].push_back(i);
437 coloredIndices.emplace_back(1, i);
442template<
bool forward,
int l,
class M,
class X,
class Y,
class K>
444 const std::deque<std::vector<std::size_t>>& coloredIndices)
446 for (
int color = 0; color < coloredIndices.size(); ++color)
448 const auto c = forward ? color : coloredIndices.size()-1-color;
449 const auto& rowIndices = coloredIndices[c];
452 const auto i = rowIndices[k];
456 const auto endColIt = row.end();
457 auto colIt = row.begin();
459 for (; colIt.index()<i; ++colIt)
460 colIt->mmv(update[colIt.index()], rhs);
461 const auto diag = colIt;
462 for (; colIt != endColIt; ++colIt)
463 colIt->mmv(update[colIt.index()], rhs);
465 if constexpr (forward)
466 Dune::algmeta_itsteps<l-1,typename M::block_type>::bsorf(
467 *diag, v, rhs, relaxationFactor
470 Dune::algmeta_itsteps<l-1,typename M::block_type>::bsorb(
471 *diag, v, rhs, relaxationFactor
474 update[i].axpy(relaxationFactor, v);
488template<
class M,
class X,
class Y,
int l=1>
507 : _A_(A), numSteps_(n), relaxationFactor_(w)
509 Dune::CheckIfDiagonalPresent<M,l>::check(_A_);
513 ParMTSOR (
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& A,
const Dune::ParameterTree& configuration)
514 :
ParMTSOR(A->getmat(), configuration)
517 ParMTSOR (
const M& A,
const Dune::ParameterTree& configuration)
521 void pre (X&, Y&)
override {}
523 void apply (X& v,
const Y& d)
override
525 this->
template apply<true>(v,d);
528 template<
bool forward>
531 for (
int i=0; i<numSteps_; i++)
532 Detail::Preconditioners::parallelBlockSOR_<forward, l>(_A_, v, d, relaxationFactor_, colors_);
538 Dune::SolverCategory::Category
category()
const override
539 {
return Dune::SolverCategory::sequential; }
547 std::deque<std::vector<std::size_t>> colors_;
560template<
class M,
class X,
class Y,
int l=1>
579 : _A_(A), numSteps_(n), relaxationFactor_(w)
581 Dune::CheckIfDiagonalPresent<M,l>::check(_A_);
585 ParMTSSOR (
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& A,
const Dune::ParameterTree& configuration)
589 ParMTSSOR (
const M& A,
const Dune::ParameterTree& configuration)
593 void pre (X&, Y&)
override {}
595 void apply (X& v,
const Y& d)
override
597 for (
int i=0; i<numSteps_; i++)
599 Detail::Preconditioners::parallelBlockSOR_<true, l>(_A_, v, d, relaxationFactor_, colors_);
600 Detail::Preconditioners::parallelBlockSOR_<false, l>(_A_, v, d, relaxationFactor_, colors_);
607 Dune::SolverCategory::Category
category()
const override
608 {
return Dune::SolverCategory::sequential; }
616 std::deque<std::vector<std::size_t>> colors_;
626template<
class M,
class X,
class Y,
int l>
627struct ConstructionTraits<
Dumux::ParMTJac<M,X,Y,l> >
629 using Arguments = DefaultConstructionArgs<SeqJac<M,X,Y,l> >;
632 return std::make_shared<Dumux::ParMTJac<M,X,Y,l>>(
633 args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor
639template<
class M,
class X,
class Y,
int l>
640struct ConstructionTraits<
Dumux::ParMTSOR<M,X,Y,l> >
642 using Arguments = DefaultConstructionArgs<SeqSOR<M,X,Y,l> >;
645 return std::make_shared<Dumux::ParMTSOR<M,X,Y,l>>(
646 args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor
651template<
class M,
class X,
class Y,
int l>
652struct SmootherApplier<
Dumux::ParMTSOR<M,X,Y,l> >
659 { smoother.template apply<true>(v,d); }
662 { smoother.template apply<false>(v,d); }
666template<
class M,
class X,
class Y,
int l>
667struct ConstructionTraits<
Dumux::ParMTSSOR<M,X,Y,l> >
669 using Arguments = DefaultConstructionArgs<SeqSSOR<M,X,Y,l> >;
672 return std::make_shared<Dumux::ParMTSSOR<M,X,Y,l>>(
673 args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor
Multi-threaded Jacobi preconditioner.
Definition: preconditioners.hh:331
ParMTJac(const M &A, const Dune::ParameterTree &configuration)
Definition: preconditioners.hh:355
ParMTJac(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &A, const Dune::ParameterTree &configuration)
Definition: preconditioners.hh:351
ParMTJac(const M &A, int n, real_field_type w)
Constructor.
Definition: preconditioners.hh:347
X::field_type field_type
The field type of the preconditioner.
Definition: preconditioners.hh:340
void pre(X &, Y &) override
Definition: preconditioners.hh:359
Dune::FieldTraits< scalar_field_type >::real_type real_field_type
real scalar type underlying the field_type
Definition: preconditioners.hh:344
void post(X &) override
Definition: preconditioners.hh:394
M matrix_type
The matrix type the preconditioner is for.
Definition: preconditioners.hh:334
Dune::Simd::Scalar< field_type > scalar_field_type
scalar type underlying the field_type
Definition: preconditioners.hh:342
Y range_type
The range type of the preconditioner.
Definition: preconditioners.hh:338
X domain_type
The domain type of the preconditioner.
Definition: preconditioners.hh:336
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category)
Definition: preconditioners.hh:397
void apply(X &update, const Y &defect) override
Definition: preconditioners.hh:361
Multi-threaded SOR preconditioner using coloring.
Definition: preconditioners.hh:490
ParMTSOR(const M &A, const Dune::ParameterTree &configuration)
Definition: preconditioners.hh:517
X domain_type
The domain type of the preconditioner.
Definition: preconditioners.hh:495
M matrix_type
The matrix type the preconditioner is for.
Definition: preconditioners.hh:493
void apply(X &v, const Y &d)
Definition: preconditioners.hh:529
ParMTSOR(const M &A, int n, real_field_type w)
Constructor.
Definition: preconditioners.hh:506
void apply(X &v, const Y &d) override
Definition: preconditioners.hh:523
Dune::Simd::Scalar< field_type > scalar_field_type
scalar type underlying the field_type
Definition: preconditioners.hh:501
void post(X &) override
Definition: preconditioners.hh:535
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category)
Definition: preconditioners.hh:538
Y range_type
The range type of the preconditioner.
Definition: preconditioners.hh:497
void pre(X &, Y &) override
Definition: preconditioners.hh:521
X::field_type field_type
The field type of the preconditioner.
Definition: preconditioners.hh:499
ParMTSOR(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &A, const Dune::ParameterTree &configuration)
Definition: preconditioners.hh:513
Dune::FieldTraits< scalar_field_type >::real_type real_field_type
real scalar type underlying the field_type
Definition: preconditioners.hh:503
Multithreaded SSOR preconditioner using coloring.
Definition: preconditioners.hh:562
ParMTSSOR(const M &A, int n, real_field_type w)
Constructor.
Definition: preconditioners.hh:578
Dune::Simd::Scalar< field_type > scalar_field_type
scalar type underlying the field_type
Definition: preconditioners.hh:573
ParMTSSOR(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &A, const Dune::ParameterTree &configuration)
Definition: preconditioners.hh:585
void pre(X &, Y &) override
Definition: preconditioners.hh:593
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category)
Definition: preconditioners.hh:607
void apply(X &v, const Y &d) override
Definition: preconditioners.hh:595
X domain_type
The domain type of the preconditioner.
Definition: preconditioners.hh:567
Dune::FieldTraits< scalar_field_type >::real_type real_field_type
real scalar type underlying the field_type
Definition: preconditioners.hh:575
ParMTSSOR(const M &A, const Dune::ParameterTree &configuration)
Definition: preconditioners.hh:589
M matrix_type
The matrix type the preconditioner is for.
Definition: preconditioners.hh:565
Y range_type
The range type of the preconditioner.
Definition: preconditioners.hh:569
void post(X &) override
Definition: preconditioners.hh:604
X::field_type field_type
The field type of the preconditioner.
Definition: preconditioners.hh:571
A preconditioner based on the Uzawa algorithm for saddle-point problems of the form .
Definition: preconditioners.hh:70
virtual Dune::SolverCategory::Category category() const
Category of the preconditioner (see SolverCategory::Category)
Definition: preconditioners.hh:188
M matrix_type
The matrix type the preconditioner is for.
Definition: preconditioners.hh:84
virtual void pre(X &x, Y &b)
Prepare the preconditioner.
Definition: preconditioners.hh:124
SeqUzawa(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &op, const Dune::ParameterTree ¶ms)
Constructor.
Definition: preconditioners.hh:100
virtual void post(X &x)
Clean up.
Definition: preconditioners.hh:185
Dune::Simd::Scalar< field_type > scalar_field_type
Scalar type underlying the field_type.
Definition: preconditioners.hh:92
typename X::field_type field_type
The field type of the preconditioner.
Definition: preconditioners.hh:90
X domain_type
The domain type of the preconditioner.
Definition: preconditioners.hh:86
Y range_type
The range type of the preconditioner.
Definition: preconditioners.hh:88
virtual void apply(X &update, const Y ¤tDefect)
Apply the preconditioner.
Definition: preconditioners.hh:132
Coloring schemes for shared-memory-parallel assembly.
void parallelFor(const std::size_t count, const FunctorType &functor)
A parallel for loop (multithreading)
Definition: parallel_for.hh:160
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition: parameters.hh:149
The specialized Dumux macro and tag for the ISTL registry to choose the solver and preconditioner at ...
Type traits to be used with matrix types.
void parallelBlockSOR_(const M &A, X &update, const Y &b, const K &relaxationFactor, const std::deque< std::vector< std::size_t > > &coloredIndices)
Definition: preconditioners.hh:443
void computeColorsForMatrixSweep_(const M &matrix, std::deque< std::vector< std::size_t > > &coloredIndices)
Definition: preconditioners.hh:413
DUMUX_REGISTER_PRECONDITIONER("uzawa", Dumux::MultiTypeBlockMatrixPreconditionerTag, Dune::defaultPreconditionerBlockLevelCreator< Dumux::SeqUzawa, 1 >())
Definition: preconditioners.hh:623
Parallel for loop (multithreading)
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Helper type to determine whether a given type is a Dune::MultiTypeBlockMatrix.
Definition: matrix.hh:37
DefaultConstructionArgs< SeqJac< M, X, Y, l > > Arguments
Definition: preconditioners.hh:629
static std::shared_ptr< Dumux::ParMTJac< M, X, Y, l > > construct(Arguments &args)
Definition: preconditioners.hh:630
static std::shared_ptr< Dumux::ParMTSOR< M, X, Y, l > > construct(Arguments &args)
Definition: preconditioners.hh:643
DefaultConstructionArgs< SeqSOR< M, X, Y, l > > Arguments
Definition: preconditioners.hh:642
DefaultConstructionArgs< SeqSSOR< M, X, Y, l > > Arguments
Definition: preconditioners.hh:669
static std::shared_ptr< Dumux::ParMTSSOR< M, X, Y, l > > construct(Arguments &args)
Definition: preconditioners.hh:670
static void preSmooth(Smoother &smoother, Domain &v, Range &d)
Definition: preconditioners.hh:658
Smoother::range_type Range
Definition: preconditioners.hh:655
Dumux::ParMTSOR< M, X, Y, l > Smoother
Definition: preconditioners.hh:654
Smoother::domain_type Domain
Definition: preconditioners.hh:656
static void postSmooth(Smoother &smoother, Domain &v, Range &d)
Definition: preconditioners.hh:661