12#ifndef DUMUX_LINEAR_PRECONDITIONERS_HH
13#define DUMUX_LINEAR_PRECONDITIONERS_HH
15#include <dune/common/exceptions.hh>
16#include <dune/common/version.hh>
17#include <dune/common/float_cmp.hh>
18#include <dune/common/indices.hh>
19#include <dune/istl/preconditioners.hh>
20#include <dune/istl/paamg/amg.hh>
21#include <dune/istl/gsetc.hh>
24#include <dune/istl/umfpack.hh>
69template<
class M,
class X,
class Y,
int l = 1>
70class SeqUzawa :
public Dune::Preconditioner<X,Y>
73 static_assert(l== 1,
"SeqUzawa expects a block level of 1.");
75 using A = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_0][Dune::Indices::_0])>;
76 using U = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_0])>;
78 using Comm = Dune::Amg::SequentialInformation;
79 using LinearOperator = Dune::MatrixAdapter<A, U, U>;
80 using Smoother = Dune::SeqSSOR<A, U, U>;
81 using AMGSolverForA = Dune::Amg::AMG<LinearOperator, U, Smoother, Comm>;
101 SeqUzawa(
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& op,
const Dune::ParameterTree& params)
102 : matrix_(op->getmat())
103 , numIterations_(params.get<std::size_t>(
"iterations"))
105 , verbosity_(params.get<int>(
"verbosity"))
106 , paramGroup_(params.get<std::string>(
"ParameterGroup"))
107 , useDirectVelocitySolverForA_(
getParamFromGroup<bool>(paramGroup_,
"LinearSolver.Preconditioner.DirectSolverForA", false))
109 const bool determineRelaxationFactor =
getParamFromGroup<bool>(paramGroup_,
"LinearSolver.Preconditioner.DetermineRelaxationFactor",
true);
112 if (determineRelaxationFactor || !useDirectVelocitySolverForA_)
115 if (useDirectVelocitySolverForA_)
118 if (determineRelaxationFactor)
119 relaxationFactor_ = estimateOmega_();
125 virtual void pre(X& x, Y& b) {}
133 virtual void apply(X& update,
const Y& currentDefect)
135 using namespace Dune::Indices;
137 auto& A = matrix_[_0][_0];
138 auto& B = matrix_[_0][_1];
139 auto& C = matrix_[_1][_0];
140 auto& D = matrix_[_1][_1];
142 const auto& f = currentDefect[_0];
143 const auto& g = currentDefect[_1];
144 auto&
u = update[_0];
145 auto& p = update[_1];
149 for (std::size_t i = 0; i < D.N(); ++i)
151 const auto& block = D[i][i];
152 for (
auto rowIt = block.begin(); rowIt != block.end(); ++rowIt)
153 if (Dune::FloatCmp::eq<scalar_field_type>(rowIt->one_norm(), 1.0))
154 p[i][rowIt.index()] = g[i][rowIt.index()];
158 for (std::size_t k = 0; k < numIterations_; ++k)
165 applySolverForA_(uIncrement, uRhs);
170 C.mmv(
u, pIncrement);
171 D.mmv(p, pIncrement);
172 pIncrement *= relaxationFactor_;
177 std::cout <<
"Uzawa iteration " << k
178 <<
", residual: " << uRhs.two_norm() + pIncrement.two_norm()/relaxationFactor_ << std::endl;
189 virtual Dune::SolverCategory::Category
category()
const
191 return Dune::SolverCategory::sequential;
196 void initAMG_(
const Dune::ParameterTree& params)
198 using namespace Dune::Indices;
199 auto linearOperator = std::make_shared<LinearOperator>(matrix_[_0][_0]);
200 amgSolverForA_ = std::make_unique<AMGSolverForA>(linearOperator, params);
206 using namespace Dune::Indices;
207 umfPackSolverForA_ = std::make_unique<Dune::UMFPack<A>>(matrix_[_0][_0]);
209 DUNE_THROW(Dune::InvalidStateException,
"UMFPack not available. Use LinearSolver.Preconditioner.DirectVelocitySolver = false.");
234 using namespace Dune::Indices;
235 auto& A = matrix_[_0][_0];
236 auto& B = matrix_[_0][_1];
237 auto& C = matrix_[_1][_0];
248 for (std::size_t i = 0; i < iterations; ++i)
256 applySolverForA_(ainvbx, bx);
264 lambdaMax = x.dot(v)/(x.dot(x));
267 omega = 1.0/lambdaMax;
276 std::cout <<
"\n*** Uzawa Preconditioner ***" << std::endl;
277 std::cout <<
"Estimating relaxation factor based on Schur complement" << std::endl;
278 std::cout <<
"Largest estimated eigenvalue lambdaMax = " << lambdaMax << std::endl;
279 std::cout <<
"Relaxation factor omega = 1/lambdaMax = " << omega << std::endl;
285 template<
class Sol,
class Rhs>
286 void applySolverForA_(Sol& sol, Rhs& rhs)
const
288 if (useDirectVelocitySolverForA_)
291 Dune::InverseOperatorResult res;
292 umfPackSolverForA_->apply(sol, rhs, res);
297 amgSolverForA_->pre(sol, rhs);
298 amgSolverForA_->apply(sol, rhs);
299 amgSolverForA_->post(sol);
306 const std::size_t numIterations_;
310 const int verbosity_;
312 std::unique_ptr<AMGSolverForA> amgSolverForA_;
314 std::unique_ptr<Dune::UMFPack<A>> umfPackSolverForA_;
316 const std::string paramGroup_;
317 const bool useDirectVelocitySolverForA_;
320#if DUNE_VERSION_LT(DUNE_ISTL,2,11)
321DUMUX_REGISTER_PRECONDITIONER(
"uzawa", Dumux::MultiTypeBlockMatrixPreconditionerTag, Dune::defaultPreconditionerBlockLevelCreator<Dumux::SeqUzawa, 1>());
332 return [](
auto opInfo,
const auto& linearOperator,
const Dune::ParameterTree& config)
334 using OpInfo = std::decay_t<
decltype(opInfo)>;
335 using Matrix =
typename OpInfo::matrix_type;
336 using Domain =
typename OpInfo::domain_type;
337 using Range =
typename OpInfo::range_type;
338 std::shared_ptr<Dune::Preconditioner<Domain, Range>> preconditioner;
339 if constexpr (OpInfo::isAssembled)
342 DUNE_THROW(Dune::NoAssembledOperator,
"The Uzawa preconditioner requires an assembled linear operator.");
343 return preconditioner;
360template<
class M,
class X,
class Y,
int l=1>
379 : _A_(A), numSteps_(n), relaxationFactor_(
w)
380 { Dune::CheckIfDiagonalPresent<M,l>::check(_A_); }
382 ParMTJac (
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& A,
const Dune::ParameterTree& configuration)
383 :
ParMTJac(A->getmat(), configuration)
386 ParMTJac (
const M& A,
const Dune::ParameterTree& configuration)
390 void pre (X&, Y&)
override {}
392 void apply (X& update,
const Y& defect)
override
397 for (
int k=0; k<numSteps_; k++)
406 auto rhs = defect[i];
407 const auto endColIt = row.end();
408 auto colIt = row.begin();
410 for (; colIt.index()<i; ++colIt)
411 colIt->mmv(xOld[colIt.index()], rhs);
412 const auto diag = colIt;
413 for (; colIt != endColIt; ++colIt)
414 colIt->mmv(xOld[colIt.index()], rhs);
416 Dune::algmeta_itsteps<l-1, typename M::block_type>::dbjac(
417 *diag, v, rhs, relaxationFactor_
420 update[i].axpy(relaxationFactor_, v);
428 Dune::SolverCategory::Category
category()
const override
429 {
return Dune::SolverCategory::sequential; }
447 std::vector<int> colors(matrix.N(), -1);
448 std::vector<int> neighborColors; neighborColors.reserve(30);
449 std::vector<bool> colorUsed; colorUsed.reserve(30);
453 for (std::size_t i = 0; i < colors.size(); ++i)
455 neighborColors.clear();
456 auto& row = matrix[i];
457 const auto endColIt = row.end();
458 for (
auto colIt = row.begin(); colIt != endColIt; ++colIt)
459 neighborColors.push_back(colors[colIt.index()]);
461 const auto c = Detail::smallestAvailableColor(neighborColors, colorUsed);
465 if (c < coloredIndices.size())
466 coloredIndices[c].push_back(i);
468 coloredIndices.emplace_back(1, i);
473template<
bool forward,
int l,
class M,
class X,
class Y,
class K>
475 const std::deque<std::vector<std::size_t>>& coloredIndices)
477 for (
int color = 0; color < coloredIndices.size(); ++color)
479 const auto c = forward ? color : coloredIndices.size()-1-color;
480 const auto& rowIndices = coloredIndices[c];
483 const auto i = rowIndices[k];
487 const auto endColIt = row.end();
488 auto colIt = row.begin();
490 for (; colIt.index()<i; ++colIt)
491 colIt->mmv(update[colIt.index()], rhs);
492 const auto diag = colIt;
493 for (; colIt != endColIt; ++colIt)
494 colIt->mmv(update[colIt.index()], rhs);
496 if constexpr (forward)
497 Dune::algmeta_itsteps<l-1,typename M::block_type>::bsorf(
498 *diag, v, rhs, relaxationFactor
501 Dune::algmeta_itsteps<l-1,typename M::block_type>::bsorb(
502 *diag, v, rhs, relaxationFactor
505 update[i].axpy(relaxationFactor, v);
519template<
class M,
class X,
class Y,
int l=1>
538 : _A_(A), numSteps_(n), relaxationFactor_(
w)
540 Dune::CheckIfDiagonalPresent<M,l>::check(_A_);
544 ParMTSOR (
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& A,
const Dune::ParameterTree& configuration)
545 :
ParMTSOR(A->getmat(), configuration)
548 ParMTSOR (
const M& A,
const Dune::ParameterTree& configuration)
552 void pre (X&, Y&)
override {}
554 void apply (X& v,
const Y& d)
override
559 template<
bool forward>
562 for (
int i=0; i<numSteps_; i++)
569 Dune::SolverCategory::Category
category()
const override
570 {
return Dune::SolverCategory::sequential; }
578 std::deque<std::vector<std::size_t>> colors_;
591template<
class M,
class X,
class Y,
int l=1>
610 : _A_(A), numSteps_(n), relaxationFactor_(
w)
612 Dune::CheckIfDiagonalPresent<M,l>::check(_A_);
616 ParMTSSOR (
const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& A,
const Dune::ParameterTree& configuration)
620 ParMTSSOR (
const M& A,
const Dune::ParameterTree& configuration)
624 void pre (X&, Y&)
override {}
626 void apply (X& v,
const Y& d)
override
628 for (
int i=0; i<numSteps_; i++)
638 Dune::SolverCategory::Category
category()
const override
639 {
return Dune::SolverCategory::sequential; }
647 std::deque<std::vector<std::size_t>> colors_;
657template<
class M,
class X,
class Y,
int l>
658struct ConstructionTraits<
Dumux::ParMTJac<M,X,Y,l> >
660 using Arguments = DefaultConstructionArgs<SeqJac<M,X,Y,l> >;
663 return std::make_shared<Dumux::ParMTJac<M,X,Y,l>>(
664 args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor
670template<
class M,
class X,
class Y,
int l>
671struct ConstructionTraits<
Dumux::ParMTSOR<M,X,Y,l> >
673 using Arguments = DefaultConstructionArgs<SeqSOR<M,X,Y,l> >;
676 return std::make_shared<Dumux::ParMTSOR<M,X,Y,l>>(
677 args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor
682template<
class M,
class X,
class Y,
int l>
683struct SmootherApplier<
Dumux::ParMTSOR<M,X,Y,l> >
690 { smoother.template apply<true>(v,d); }
693 { smoother.template apply<false>(v,d); }
697template<
class M,
class X,
class Y,
int l>
698struct ConstructionTraits<
Dumux::ParMTSSOR<M,X,Y,l> >
700 using Arguments = DefaultConstructionArgs<SeqSSOR<M,X,Y,l> >;
703 return std::make_shared<Dumux::ParMTSSOR<M,X,Y,l>>(
704 args.getMatrix(), args.getArgs().iterations, args.getArgs().relaxationFactor
ParMTJac(const M &A, const Dune::ParameterTree &configuration)
Definition preconditioners.hh:386
ParMTJac(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &A, const Dune::ParameterTree &configuration)
Definition preconditioners.hh:382
ParMTJac(const M &A, int n, real_field_type w)
Constructor.
Definition preconditioners.hh:378
X::field_type field_type
The field type of the preconditioner.
Definition preconditioners.hh:371
void pre(X &, Y &) override
Definition preconditioners.hh:390
Dune::FieldTraits< scalar_field_type >::real_type real_field_type
real scalar type underlying the field_type
Definition preconditioners.hh:375
void post(X &) override
Definition preconditioners.hh:425
M matrix_type
The matrix type the preconditioner is for.
Definition preconditioners.hh:365
Dune::Simd::Scalar< field_type > scalar_field_type
scalar type underlying the field_type
Definition preconditioners.hh:373
Y range_type
The range type of the preconditioner.
Definition preconditioners.hh:369
X domain_type
The domain type of the preconditioner.
Definition preconditioners.hh:367
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category).
Definition preconditioners.hh:428
void apply(X &update, const Y &defect) override
Definition preconditioners.hh:392
Multi-threaded SOR preconditioner using coloring.
Definition preconditioners.hh:521
ParMTSOR(const M &A, const Dune::ParameterTree &configuration)
Definition preconditioners.hh:548
X domain_type
The domain type of the preconditioner.
Definition preconditioners.hh:526
M matrix_type
The matrix type the preconditioner is for.
Definition preconditioners.hh:524
void apply(X &v, const Y &d)
Definition preconditioners.hh:560
ParMTSOR(const M &A, int n, real_field_type w)
Constructor.
Definition preconditioners.hh:537
void apply(X &v, const Y &d) override
Definition preconditioners.hh:554
Dune::Simd::Scalar< field_type > scalar_field_type
scalar type underlying the field_type
Definition preconditioners.hh:532
void post(X &) override
Definition preconditioners.hh:566
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category).
Definition preconditioners.hh:569
Y range_type
The range type of the preconditioner.
Definition preconditioners.hh:528
void pre(X &, Y &) override
Definition preconditioners.hh:552
X::field_type field_type
The field type of the preconditioner.
Definition preconditioners.hh:530
ParMTSOR(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &A, const Dune::ParameterTree &configuration)
Definition preconditioners.hh:544
Dune::FieldTraits< scalar_field_type >::real_type real_field_type
real scalar type underlying the field_type
Definition preconditioners.hh:534
ParMTSSOR(const M &A, int n, real_field_type w)
Constructor.
Definition preconditioners.hh:609
Dune::Simd::Scalar< field_type > scalar_field_type
scalar type underlying the field_type
Definition preconditioners.hh:604
ParMTSSOR(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &A, const Dune::ParameterTree &configuration)
Definition preconditioners.hh:616
void pre(X &, Y &) override
Definition preconditioners.hh:624
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category).
Definition preconditioners.hh:638
void apply(X &v, const Y &d) override
Definition preconditioners.hh:626
X domain_type
The domain type of the preconditioner.
Definition preconditioners.hh:598
Dune::FieldTraits< scalar_field_type >::real_type real_field_type
real scalar type underlying the field_type
Definition preconditioners.hh:606
ParMTSSOR(const M &A, const Dune::ParameterTree &configuration)
Definition preconditioners.hh:620
M matrix_type
The matrix type the preconditioner is for.
Definition preconditioners.hh:596
Y range_type
The range type of the preconditioner.
Definition preconditioners.hh:600
void post(X &) override
Definition preconditioners.hh:635
X::field_type field_type
The field type of the preconditioner.
Definition preconditioners.hh:602
A preconditioner based on the Uzawa algorithm for saddle-point problems of the form ...
Definition preconditioners.hh:71
virtual Dune::SolverCategory::Category category() const
Category of the preconditioner (see SolverCategory::Category).
Definition preconditioners.hh:189
M matrix_type
The matrix type the preconditioner is for.
Definition preconditioners.hh:85
virtual void pre(X &x, Y &b)
Prepare the preconditioner.
Definition preconditioners.hh:125
SeqUzawa(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &op, const Dune::ParameterTree ¶ms)
Constructor.
Definition preconditioners.hh:101
virtual void post(X &x)
Clean up.
Definition preconditioners.hh:186
Dune::Simd::Scalar< field_type > scalar_field_type
Scalar type underlying the field_type.
Definition preconditioners.hh:93
typename X::field_type field_type
The field type of the preconditioner.
Definition preconditioners.hh:91
X domain_type
The domain type of the preconditioner.
Definition preconditioners.hh:87
Y range_type
The range type of the preconditioner.
Definition preconditioners.hh:89
virtual void apply(X &update, const Y ¤tDefect)
Apply the preconditioner.
Definition preconditioners.hh:133
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:165
The specialized Dumux macro and tag for the ISTL registry to choose the solver and preconditioner at ...
#define DUMUX_REGISTER_PRECONDITIONER(name, tag,...)
Register a Dumux preconditioner.
Definition istlsolverregistry.hh:31
Type traits to be used with matrix types.
Definition preconditioners.hh:440
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:474
void computeColorsForMatrixSweep_(const M &matrix, std::deque< std::vector< std::size_t > > &coloredIndices)
Definition preconditioners.hh:444
Definition cvfelocalresidual.hh:25
auto uzawaPreconditionerCreator()
Creator of the Uzawa preconditioner for the solver factory.
Definition preconditioners.hh:330
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::w
Definition pengrobinsonmixture.hh:140
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::u
Definition pengrobinsonmixture.hh:138
Definition preconditioners.hh:654
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:660
static std::shared_ptr< Dumux::ParMTJac< M, X, Y, l > > construct(Arguments &args)
Definition preconditioners.hh:661
static std::shared_ptr< Dumux::ParMTSOR< M, X, Y, l > > construct(Arguments &args)
Definition preconditioners.hh:674
DefaultConstructionArgs< SeqSOR< M, X, Y, l > > Arguments
Definition preconditioners.hh:673
DefaultConstructionArgs< SeqSSOR< M, X, Y, l > > Arguments
Definition preconditioners.hh:700
static std::shared_ptr< Dumux::ParMTSSOR< M, X, Y, l > > construct(Arguments &args)
Definition preconditioners.hh:701
static void preSmooth(Smoother &smoother, Domain &v, Range &d)
Definition preconditioners.hh:689
Smoother::range_type Range
Definition preconditioners.hh:686
Dumux::ParMTSOR< M, X, Y, l > Smoother
Definition preconditioners.hh:685
Smoother::domain_type Domain
Definition preconditioners.hh:687
static void postSmooth(Smoother &smoother, Domain &v, Range &d)
Definition preconditioners.hh:692