12#ifndef DUMUX_LINEAR_STOKES_SOLVER_HH
13#define DUMUX_LINEAR_STOKES_SOLVER_HH
22#include <dune/common/parametertree.hh>
23#include <dune/common/hybridutilities.hh>
24#include <dune/common/exceptions.hh>
26#include <dune/istl/matrixindexset.hh>
27#include <dune/istl/preconditioner.hh>
28#include <dune/istl/preconditioners.hh>
29#include <dune/istl/solvers.hh>
30#include <dune/istl/paamg/amg.hh>
33#include <dune/istl/owneroverlapcopy.hh>
34#include <dune/istl/schwarz.hh>
35#include <dune/istl/novlpschwarz.hh>
55template<
class Comm,
class Block>
58 using Attr = Dune::OwnerOverlapCopyAttributeSet;
59 for (
const auto& pair : comm.indexSet())
60 if (pair.local().attribute() != Attr::owner)
61 v[pair.local().local()] = 0.0;
65template<
class Comm,
class Block>
68 using Attr = Dune::OwnerOverlapCopyAttributeSet;
69 for (
const auto& pair : comm.indexSet())
70 if (pair.local().attribute() == Attr::overlap)
71 v[pair.local().local()] = 0.0;
80template<
class Comm,
class Block>
84 if (comm.category() == Dune::SolverCategory::overlapping)
91 comm.addOwnerCopyToOwnerCopy(y, y);
113template<
class M,
class X,
class Y,
int l = 2>
117 static_assert(l == 2,
"StokesPreconditioner expects a block level of 2 for Matrix type M.");
119 using A = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_0][Dune::Indices::_0])>;
120 using U = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_0])>;
122 using P = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_1][Dune::Indices::_1])>;
123 using V = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_1])>;
125 enum class Mode { symmetric, triangular, diagonal };
128 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>,
int>;
152 const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& fullLinearOperator,
153 const std::shared_ptr<const PressureLinearOperator>& pressureLinearOperator,
154 const Dune::ParameterTree& params
156 : matrix_(fullLinearOperator->getmat())
157 , pmatrix_(pressureLinearOperator->getmat())
158 , verbosity_(params.get<int>(
"verbosity"))
159 , paramGroup_(params.get<std::string>(
"ParameterGroup"))
162 initPreconditioner_(params);
175 const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& fullLinearOperator,
176 const std::shared_ptr<const PressureLinearOperator>& pressureLinearOperator,
177 const Dune::ParameterTree& params,
178 std::shared_ptr<Comm> velComm,
179 std::shared_ptr<Comm> presComm =
nullptr
181 : matrix_(fullLinearOperator->getmat())
182 , pmatrix_(pressureLinearOperator->getmat())
183 , verbosity_(params.get<int>(
"verbosity"))
184 , paramGroup_(params.get<std::string>(
"ParameterGroup"))
185 , velComm_(std::move(velComm))
186 , presComm_(std::move(presComm))
189 initPreconditioner_(params);
196 void pre(X& update, Y& currentDefect)
override
198 using namespace Dune::Indices;
199 preconditionerForA_->pre(update[_0], currentDefect[_0]);
200 preconditionerForP_->pre(update[_1], currentDefect[_1]);
214 void apply(X& update,
const Y& currentDefect)
override
216 using namespace Dune::Indices;
218 if (mode_ == Mode::symmetric)
220 update = applyRightBlock_(currentDefect);
221 update = applyDiagBlock_(update);
222 update = applyLeftBlock_(update);
224 else if (mode_ == Mode::triangular)
226 update = applyRightBlock_(currentDefect);
227 update = applyDiagBlock_(update);
230 update = applyDiagBlock_(currentDefect);
238 using namespace Dune::Indices;
239 preconditionerForA_->post(update[_0]);
240 preconditionerForP_->post(update[_1]);
244 Dune::SolverCategory::Category
category()
const override
246 return Dune::SolverCategory::sequential;
250 void initMode_(
const Dune::ParameterTree& params)
253 paramGroup_,
"LinearSolver.Preconditioner.Mode",
"Diagonal"
257 std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
258 if (lower ==
"symmetric")
259 mode_ = Mode::symmetric;
260 else if (lower ==
"triangular")
261 mode_ = Mode::triangular;
263 mode_ = Mode::diagonal;
266 X applyRightBlock_(
const Y& d)
268 using namespace Dune::Indices;
278 auto vTmp = d; vTmp = 0.0;
281 applyPreconditionerForA_(vTmp[_0], dTmp0);
284 matrix_[_1][_0].mv(vTmp[_0], vTmp[_1]);
297 X applyDiagBlock_(
const Y& d)
299 using namespace Dune::Indices;
306 if (mode_ == Mode::diagonal)
307 applyPreconditionerForA_(v[_0], dTmp[_0]);
314 applyPreconditionerForP_(v[_1], dTmp[_1]);
315 if (pressureDiagonal_)
316 for (std::size_t i = 0; i < v[_1].size(); ++i)
317 v[_1][i] += (*pressureDiagonal_)[i]*d[_1][i];
322 X applyLeftBlock_(
const Y& d)
324 using namespace Dune::Indices;
334 auto vTmp = d; vTmp = 0.0;
337 matrix_[_0][_1].umv(dTmp[_1], vTmp[_0]);
344 auto vTmp0 = vTmp[_0]; vTmp0 = 0.0;
345 applyPreconditionerForA_(vTmp0, vTmp[_0]);
354 void initPreconditioner_(
const Dune::ParameterTree& params)
356 using namespace Dune::Indices;
361 directSolverForA_ = std::make_shared<Dune::UMFPack<A>>(matrix_[_0][_0], verbosity_);
362 using Wrap = Dune::InverseOperator2Preconditioner<Dune::InverseOperator<U, U>>;
363 preconditionerForA_ = std::make_shared<Wrap>(*directSolverForA_);
365 DUNE_THROW(Dune::InvalidStateException,
"Selected direct solver but UMFPack is not available.");
373 auto ssor = std::make_shared<Dune::SeqSSOR<A,U,U>>(matrix_[_0][_0], sweeps, relaxation);
377 if (velComm_->category() == Dune::SolverCategory::nonoverlapping)
378 preconditionerForA_ = std::make_shared<Dune::NonoverlappingBlockPreconditioner<Comm, Dune::SeqSSOR<A,U,U>>>(ssor, *velComm_);
380 preconditionerForA_ = std::make_shared<Dune::BlockPreconditioner<U, U, Comm, Dune::SeqSSOR<A,U,U>>>(ssor, *velComm_);
384 preconditionerForA_ = ssor;
391 const bool nonov = (velComm_->category()
392 == Dune::SolverCategory::nonoverlapping);
395 using VelOp = Dune::NonoverlappingSchwarzOperator<A, U, U, Comm>;
396 using Smoother = Dune::NonoverlappingBlockPreconditioner<Comm, Dune::SeqSSOR<A,U,U>>;
397 auto lopV = std::make_shared<VelOp>(matrix_[_0][_0], *velComm_);
398 preconditionerForA_ = std::make_shared<
399 Dune::Amg::AMG<VelOp, U, Smoother, Comm>>(lopV, params, *velComm_);
403 using VelOp = Dune::OverlappingSchwarzOperator<A, U, U, Comm>;
404 using Smoother = Dune::BlockPreconditioner<U, U, Comm, Dune::SeqSSOR<A,U,U>>;
405 auto lopV = std::make_shared<VelOp>(matrix_[_0][_0], *velComm_);
406 preconditionerForA_ = std::make_shared<
407 Dune::Amg::AMG<VelOp, U, Smoother, Comm>>(lopV, params, *velComm_);
413 using VelLinearOperator = Dune::MatrixAdapter<A, U, U>;
414 auto lopV = std::make_shared<VelLinearOperator>(matrix_[_0][_0]);
415 preconditionerForA_ = std::make_shared<
416 Dune::Amg::AMG<VelLinearOperator, U, Dumux::ParMTSSOR<A,U,U>>
424 directSolverForP_ = std::make_shared<Dune::UMFPack<P>>(pmatrix_, verbosity_);
425 using Wrap = Dune::InverseOperator2Preconditioner<Dune::InverseOperator<V, V>>;
426 preconditionerForP_ = std::make_shared<Wrap>(*directSolverForP_);
428 DUNE_THROW(Dune::InvalidStateException,
"Selected direct solver but UMFPack is not available.");
437 if (presComm_->category() == Dune::SolverCategory::nonoverlapping)
439 using PressOp = Dune::NonoverlappingSchwarzOperator<P, V, V, Comm>;
440 using Smoother = Dune::NonoverlappingBlockPreconditioner<Comm, Dune::SeqSSOR<P,V,V>>;
441 auto lopP = std::make_shared<PressOp>(pmatrix_, *presComm_);
442 preconditionerForP_ = std::make_shared<
443 Dune::Amg::AMG<PressOp, V, Smoother, Comm>>(lopP, params, *presComm_);
447 using PressOp = Dune::OverlappingSchwarzOperator<P, V, V, Comm>;
448 using Smoother = Dune::BlockPreconditioner<V, V, Comm, Dune::SeqSSOR<P,V,V>>;
449 auto lopP = std::make_shared<PressOp>(pmatrix_, *presComm_);
450 preconditionerForP_ = std::make_shared<
451 Dune::Amg::AMG<PressOp, V, Smoother, Comm>>(lopP, params, *presComm_);
457 auto lopP = std::make_shared<PressureLinearOperator>(pmatrix_);
458 preconditionerForP_ = std::make_shared<
459 Dune::Amg::AMG<PressureLinearOperator, V, Dumux::ParMTSSOR<P,V,V>>
465 const std::size_t numIterations = pmatrix_.nonzeroes() == pmatrix_.N() ? 1 : 10;
469 const bool nonovP = (presComm_->category()
470 == Dune::SolverCategory::nonoverlapping);
471 auto seqJacP = std::make_shared<Dune::SeqJac<P,V,V>>(pmatrix_, numIterations, 1.0);
474 using PressJacobi = Dune::NonoverlappingBlockPreconditioner<Comm, Dune::SeqJac<P,V,V>>;
475 preconditionerForP_ = std::make_shared<PressJacobi>(seqJacP, *presComm_);
479 using PressJacobi = Dune::BlockPreconditioner<V, V, Comm, Dune::SeqJac<P,V,V>>;
480 preconditionerForP_ = std::make_shared<PressJacobi>(seqJacP, *presComm_);
486 using PressJacobi = Dumux::ParMTJac<P, V, V>;
487 preconditionerForP_ = std::make_shared<PressJacobi>(pmatrix_, numIterations, 1.0);
492 template<
class Sol,
class Rhs>
493 void applyPreconditionerForA_(Sol& sol, Rhs& rhs)
const
495 preconditionerForA_->apply(sol, rhs);
498 template<
class Sol,
class Rhs>
499 void applyPreconditionerForP_(Sol& sol, Rhs& rhs)
const
501 preconditionerForP_->apply(sol, rhs);
513 { pressureDiagonal_ = std::move(diagonal); }
516 std::shared_ptr<const V> pressureDiagonal_;
523 const int verbosity_;
525 std::shared_ptr<Dune::Preconditioner<U, U>> preconditionerForA_;
526 std::shared_ptr<Dune::Preconditioner<V, V>> preconditionerForP_;
527 std::shared_ptr<Dune::InverseOperator<U, U>> directSolverForA_;
528 std::shared_ptr<Dune::InverseOperator<V, V>> directSolverForP_;
530 const std::string paramGroup_;
534 std::shared_ptr<Comm> velComm_;
535 std::shared_ptr<Comm> presComm_;
547template<
class M,
class X,
class Y>
550 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>,
int>;
558 std::shared_ptr<Comm> vComm,
559 std::shared_ptr<Comm> pComm,
561 : A_(A), localOp_(A), vComm_(std::move(vComm)), pComm_(std::move(pComm))
562 , nonOverlapping_(nonOverlapping)
565 using namespace Dune::Indices;
567 velOp_ = std::make_shared<VelOp>(A_[_0][_0], *vComm_);
571 void apply(
const X& x, Y& y)
const override
573 using namespace Dune::Indices;
576 applyNonoverlapping_(x, y);
581 localOp_.apply(x, y);
589 using namespace Dune::Indices;
592 y[_0].axpy(alpha, Ax[_0]);
593 y[_1].axpy(alpha, Ax[_1]);
597 using A00t = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_0][Dune::Indices::_0])>;
598 using Ut = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_0])>;
599 using VelOp = Dune::NonoverlappingSchwarzOperator<A00t, Ut, Ut, Comm>;
604 void applyNonoverlapping_(
const X& x, Y& y)
const
606 using namespace Dune::Indices;
609 vComm_->copyOwnerToAll(xc[_0], xc[_0]);
610 pComm_->copyOwnerToAll(xc[_1], xc[_1]);
612 velOp_->apply(xc[_0], y[_0]);
614 Ut bv(y[_0]); bv = 0.0;
615 A_[_0][_1].umv(xc[_1], bv);
617 vComm_->addOwnerCopyToOwnerCopy(bv, bv);
622 A_[_1][_0].umv(xc[_0], y[_1]);
623 A_[_1][_1].umv(xc[_1], y[_1]);
625 pComm_->addOwnerCopyToOwnerCopy(y[_1], y[_1]);
634 Dune::SolverCategory::Category
category()
const override
636 return nonOverlapping_ ? Dune::SolverCategory::nonoverlapping
637 : Dune::SolverCategory::overlapping;
643 std::shared_ptr<Comm> vComm_, pComm_;
644 bool nonOverlapping_;
645 std::shared_ptr<VelOp> velOp_;
653template<
class SeqPrec,
class X,
class Y>
656 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>,
int>;
663 std::shared_ptr<Comm> vComm,
664 std::shared_ptr<Comm> pComm,
666 : seqPrec_(std::move(seqPrec))
667 , vComm_(std::move(vComm)), pComm_(std::move(pComm))
668 , nonOverlapping_(nonOverlapping)
671 void pre(X& v, Y& d)
override
674 communicateUpdate_(v);
677 void apply(X& v,
const Y& d)
override
679 seqPrec_->apply(v, d);
680 communicateUpdate_(v);
686 communicateUpdate_(v);
689 Dune::SolverCategory::Category
category()
const override
691 return nonOverlapping_ ? Dune::SolverCategory::nonoverlapping
692 : Dune::SolverCategory::overlapping;
696 void communicateUpdate_(X& v)
698 using namespace Dune::Indices;
701 vComm_->copyOwnerToAll(v[_0], v[_0]);
702 pComm_->copyOwnerToAll(v[_1], v[_1]);
705 std::shared_ptr<SeqPrec> seqPrec_;
706 std::shared_ptr<Comm> vComm_, pComm_;
707 bool nonOverlapping_;
718 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>,
int>;
722 using real_type =
typename Dune::FieldTraits<field_type>::real_type;
725 std::shared_ptr<Comm> pComm,
727 : vComm_(std::move(vComm)), pComm_(std::move(pComm))
728 , nonOverlapping_(nonOverlapping)
733 using namespace Dune::Indices;
734 using Attr = Dune::OwnerOverlapCopyAttributeSet;
740 for (std::size_t i = 0; i < x[_0].size(); ++i)
741 local += Dune::dot(x[_0][i], y[_0][i]);
742 for (
const auto& pair : vComm_->indexSet())
743 if (pair.local().attribute() != Attr::owner)
744 local -= Dune::dot(x[_0][pair.local()], y[_0][pair.local()]);
746 for (std::size_t i = 0; i < x[_1].size(); ++i)
747 local += Dune::dot(x[_1][i], y[_1][i]);
748 for (
const auto& pair : pComm_->indexSet())
749 if (pair.local().attribute() != Attr::owner)
750 local -= Dune::dot(x[_1][pair.local()], y[_1][pair.local()]);
752 return vComm_->communicator().sum(local);
758 return sqrt(std::real(
dot(x, x)));
761 Dune::SolverCategory::Category
category()
const override
763 return nonOverlapping_ ? Dune::SolverCategory::nonoverlapping
764 : Dune::SolverCategory::overlapping;
769 std::shared_ptr<Comm> vComm_, pComm_;
770 bool nonOverlapping_;
785template<
class Matrix,
class Vector,
class VelocityGG,
class PressureGG>
790 using PressureVector = std::decay_t<decltype(std::declval<Vector>()[Dune::Indices::_1])>;
795 using Comm = Dune::OwnerOverlapCopyCommunication<Dune::bigunsignedint<96>,
int>;
796 static constexpr bool canCommunicate_ = VTraits::canCommunicate && PTraits::canCommunicate;
812 std::shared_ptr<const PressureGG> pGridGeometry,
813 const Vector& dirichletDofs,
816 , vGridGeometry_(std::move(vGridGeometry))
817 , pGridGeometry_(std::move(pGridGeometry))
818 , dirichletDofs_(dirichletDofs)
829 const std::string group = this->
paramGroup() ==
"" ?
"Component" : this->
paramGroup() +
".Component";
831 <<
" LiquidDynamicViscosity or LiquidKinematicViscosity"
832 <<
" in parameter group [" << group <<
"]");
838 scalarProduct_ = std::make_shared<Dune::ScalarProduct<Vector>>();
840 if constexpr (canCommunicate_)
842 if (vGridGeometry_->gridView().comm().size() > 1)
843 initParallelInfrastructure_();
848 bool solve(
const Matrix& A, Vector& x,
const Vector& b)
853 return applyIterativeSolver_(ATmp, x, bTmp);
862 using namespace Dune::Indices;
864 keptComponents_ = {};
865 keptMatrix_ = std::make_shared<Matrix>(A);
866 eliminatedEntries_.reset();
868 if (symmetrizeDirichlet_())
872 auto unusedRhs = dirichletDofs_;
874 eliminatedEntries_ = std::make_shared<Matrix>(A);
875 *eliminatedEntries_ -= *keptMatrix_;
878 (*keptMatrix_)[_1] *= -1.0/density_;
881 if constexpr (canCommunicate_)
883 if (vGridGeometry_->gridView().comm().size() > 1 && isNonOverlapping_)
884 prepareParallelMatrix_(*keptMatrix_);
888 keptComponents_ = makeSolverComponents_(*keptMatrix_);
896 bool solve(Vector& x,
const Vector& b)
899 DUNE_THROW(Dune::InvalidStateException,
"Called solve(x, b) but no matrix has been set");
901 using namespace Dune::Indices;
903 if (eliminatedEntries_)
905 auto dirichletValues = b;
906 Dune::Hybrid::forEach(std::make_index_sequence<Vector::size()>{}, [&](
auto i)
908 for (std::size_t k = 0; k < dirichletValues[i].size(); ++k)
909 for (std::size_t c = 0; c < dirichletValues[i][k].size(); ++c)
910 dirichletValues[i][k][c] *= dirichletDofs_[i][k][c];
912 eliminatedEntries_->mmv(dirichletValues, bTmp);
915 bTmp[_1] *= -1.0/density_;
918 if constexpr (canCommunicate_)
920 if (vGridGeometry_->gridView().comm().size() > 1)
922 prepareParallelRhs_(bTmp);
923 const bool converged = runSolver_(keptComponents_.op, scalarProduct_, keptComponents_.preconditioner, x, bTmp);
929 return runSolver_(keptComponents_.op, scalarProduct_, keptComponents_.preconditioner, x, bTmp);
944 { pressureMatrix_ = std::move(matrix); }
948 { pressureDiagonal_ = std::move(diagonal); }
954 using namespace Dune::Indices;
955 if (vComm_ && pComm_)
957 vComm_->copyOwnerToAll(v[_0], v[_0]);
958 pComm_->copyOwnerToAll(v[_1], v[_1]);
967 using namespace Dune::Indices;
968 if (vComm_ && pComm_)
981 using namespace Dune::Indices;
982 if (vComm_ && pComm_ && vGridGeometry_->gridView().comm().size() > 1)
985 if (isNonOverlapping_)
987 vComm_->addOwnerCopyToOwnerCopy(bc[_0], bc[_0]);
988 pComm_->addOwnerCopyToOwnerCopy(bc[_1], bc[_1]);
995 return scalarProduct_->norm(bc);
998 return scalarProduct_->norm(b);
1003 return "Block-preconditioned Stokes solver";
1006 const Dune::InverseOperatorResult&
result()
const
1013 void initParallelInfrastructure_()
1016 isNonOverlapping_ = VTraits::isNonOverlapping(vGridGeometry_->gridView())
1017 && PTraits::isNonOverlapping(pGridGeometry_->gridView());
1019 const auto cat = isNonOverlapping_ ? Dune::SolverCategory::nonoverlapping
1020 : Dune::SolverCategory::overlapping;
1023 vDofMapper_ = std::make_shared<const typename VTraits::DofMapper>(VTraits::dofMapper(*vGridGeometry_));
1024 pDofMapper_ = std::make_shared<const typename PTraits::DofMapper>(PTraits::dofMapper(*pGridGeometry_));
1025 vParallelHelper_ = std::make_shared<ParallelISTLHelper<VTraits>>(vGridGeometry_->gridView(), *vDofMapper_);
1026 pParallelHelper_ = std::make_shared<ParallelISTLHelper<PTraits>>(pGridGeometry_->gridView(), *pDofMapper_);
1028 vComm_ = std::make_shared<Comm>(vGridGeometry_->gridView().comm(), cat);
1029 vParallelHelper_->createParallelIndexSet(*vComm_);
1031 pComm_ = std::make_shared<Comm>(pGridGeometry_->gridView().comm(), cat);
1032 pParallelHelper_->createParallelIndexSet(*pComm_);
1034 scalarProduct_ = std::make_shared<Detail::ParallelStokesScalarProduct<Vector>>(
1035 vComm_, pComm_, isNonOverlapping_);
1039 bool symmetrizeDirichlet_()
const
1042 bool applyIterativeSolver_(Matrix& A, Vector& x, Vector& b)
1045 if (symmetrizeDirichlet_())
1049 using namespace Dune::Indices;
1050 A[_1] *= -1.0/density_;
1051 b[_1] *= -1.0/density_;
1054 if constexpr (canCommunicate_)
1056 if (vGridGeometry_->gridView().comm().size() > 1)
1058 if (isNonOverlapping_)
1059 prepareParallelMatrix_(A);
1060 prepareParallelRhs_(b);
1061 const auto components = makeSolverComponents_(A);
1062 const bool converged = runSolver_(components.op, scalarProduct_, components.preconditioner, x, b);
1068 const auto components = makeSolverComponents_(A);
1069 return runSolver_(components.op, scalarProduct_, components.preconditioner, x, b);
1073 struct SolverComponents
1075 std::shared_ptr<Dune::LinearOperator<Vector, Vector>> op;
1076 std::shared_ptr<Dune::Preconditioner<Vector, Vector>> preconditioner;
1078 std::shared_ptr<typename Preconditioner::PressureLinearOperator> pressureOperator;
1081 SolverComponents makeSolverComponents_(
const Matrix& A)
1083 SolverComponents components;
1084 components.pressureOperator = makePressureLinearOperator_<typename Preconditioner::PressureLinearOperator>();
1085 auto assembledOperator = std::make_shared<Dumux::ParallelMultiTypeMatrixAdapter<Matrix, Vector, Vector>>(A);
1088 if constexpr (canCommunicate_)
1090 if (vGridGeometry_->gridView().comm().size() > 1)
1093 components.op = std::make_shared<Detail::ParallelStokesLinearOperator<Matrix, Vector, Vector>>(
1094 A, vComm_, pComm_, isNonOverlapping_);
1095 auto preconditioner = std::make_shared<Preconditioner>(
1096 assembledOperator, components.pressureOperator, params_.sub(
"preconditioner"), vComm_, pComm_);
1097 preconditioner->setPressureDiagonal(pressureDiagonal_);
1098 components.preconditioner = std::make_shared<Detail::ParallelStokesPreconditioner<Preconditioner, Vector, Vector>>(
1099 preconditioner, vComm_, pComm_, isNonOverlapping_);
1105 auto preconditioner = std::make_shared<Preconditioner>(assembledOperator, components.pressureOperator, params_.sub(
"preconditioner"));
1106 preconditioner->setPressureDiagonal(pressureDiagonal_);
1107 components.op = assembledOperator;
1108 components.preconditioner = preconditioner;
1113 void prepareParallelMatrix_(Matrix& A)
1115 using namespace Dune::Indices;
1116 using GridView =
typename VelocityGG::GridView;
1117 static constexpr int dim = GridView::dimension;
1118 static constexpr std::size_t numCodims = dim + 1;
1120 const auto& gv = vGridGeometry_->gridView();
1121 const auto velCodims = activeCodimsBitset_<VTraits, numCodims>();
1125 using VelBlock = std::decay_t<
decltype(A[_0][_0])>;
1126 MultiCodimParallelMatrixHelper<VelBlock, GridView, typename VTraits::DofMapper, numCodims>
1127 velHelper(gv, *vDofMapper_, velCodims);
1128 velHelper.extendMatrix(A[_0][_0], [](
auto){
return false; });
1129 velHelper.sumEntries(A[_0][_0]);
1133 void prepareParallelRhs_(Vector& b)
1135 using namespace Dune::Indices;
1136 if (isNonOverlapping_)
1138 using VelVec = std::decay_t<
decltype(b[_0])>;
1139 using PresVec = std::decay_t<
decltype(b[_1])>;
1140 using VNonoverlapping =
typename VTraits::template ParallelNonoverlapping<
1141 std::decay_t<decltype(std::declval<Matrix>()[_0][_0])>, VelVec>;
1142 using PNonoverlapping =
typename PTraits::template ParallelNonoverlapping<
1143 std::decay_t<decltype(std::declval<Matrix>()[_1][_1])>, PresVec>;
1153 template<
class Traits, std::
size_t numCodims>
1154 static std::bitset<numCodims> activeCodimsBitset_()
1156 if constexpr (
requires { Traits::dofCodims; })
1157 return Traits::dofCodims;
1160 std::bitset<numCodims> bits;
1161 bits.set(Traits::dofCodim);
1167 template<
class LinearOperator,
class SP,
class Prec>
1168 bool runSolver_(std::shared_ptr<LinearOperator> op,
1169 std::shared_ptr<SP> sp,
1170 std::shared_ptr<Prec> prec,
1171 Vector& x, Vector& b)
1173 std::unique_ptr<Dune::InverseOperator<Vector, Vector>> solver;
1174 if (solverType_ ==
"minres")
1175 solver = std::make_unique<Dune::MINRESSolver<Vector>>(op, sp, prec, params_);
1176 else if (solverType_ ==
"bicgstab")
1177 solver = std::make_unique<Dune::BiCGSTABSolver<Vector>>(op, sp, prec, params_);
1178 else if (solverType_ ==
"gmres")
1179 solver = std::make_unique<Dune::RestartedGMResSolver<Vector>>(op, sp, prec, params_);
1181 DUNE_THROW(Dune::NotImplemented,
"Solver choice " << solverType_ <<
" is not implemented");
1183 solver->apply(x, b, result_);
1184 return result_.converged;
1187 template<
class LinearOperator>
1188 std::shared_ptr<LinearOperator> makePressureLinearOperator_()
1190 if (pressureMatrix_)
1191 return std::make_shared<LinearOperator>(pressureMatrix_);
1193 using M =
typename LinearOperator::matrix_type;
1194 auto massMatrix = createMassMatrix_<M>();
1195 return std::make_shared<LinearOperator>(massMatrix);
1198 template<
class M,
class DM =
typename PressureGG::DiscretizationMethod>
1199 std::shared_ptr<M> createMassMatrix_()
1201 auto massMatrix = std::make_shared<M>();
1202 massMatrix->setBuildMode(M::random);
1203 const auto numDofs = pGridGeometry_->numDofs();
1207 Dune::MatrixIndexSet pattern;
1208 pattern.resize(numDofs, numDofs);
1209 for (
unsigned int globalI = 0; globalI < numDofs; ++globalI)
1210 pattern.add(globalI, globalI);
1211 pattern.exportIdx(*massMatrix);
1213 const auto& gv = pGridGeometry_->gridView();
1214 auto fvGeometry =
localView(*pGridGeometry_);
1215 for (
const auto& element : elements(gv))
1217 fvGeometry.bindElement(element);
1218 for (
const auto& scv :
scvs(fvGeometry))
1221 const auto dofIndex = scv.dofIndex();
1222 if (
element.partitionType() == Dune::GhostEntity)
1223 (*massMatrix)[dofIndex][dofIndex][0][0] = 1.0;
1225 (*massMatrix)[dofIndex][dofIndex][0][0] += weight_*Extrusion::volume(fvGeometry, scv)/(2.0*viscosity_);
1234 (*massMatrix) = 0.0;
1236 const auto& gv = pGridGeometry_->gridView();
1237 auto fvGeometry =
localView(*pGridGeometry_);
1238 std::vector<Dune::FieldVector<double, 1>> values;
1240 for (
const auto& element : elements(gv))
1242 const auto geometry =
element.geometry();
1243 const auto& localBasis = pGridGeometry_->feCache().get(
element.type()).localBasis();
1244 const auto numLocalDofs = localBasis.size();
1245 values.resize(numLocalDofs);
1247 fvGeometry.bindElement(element);
1248 for (
const auto& scvJ :
scvs(fvGeometry))
1251 const auto globalJ = scvJ.dofIndex();
1252 const auto qWeightJ = PressureGG::Extrusion::volume(fvGeometry, scvJ);
1253 const auto quadPos = geometry.local(scvJ.center());
1254 localBasis.evaluateFunction(quadPos, values);
1256 for (
const auto& scvI :
scvs(fvGeometry))
1258 const auto valueIJ = values[scvI.localDofIndex()]*qWeightJ/(2.0*viscosity_);
1259 (*massMatrix)[scvI.dofIndex()][globalJ][0][0] += valueIJ;
1266 if (pGridGeometry_->gridView().comm().size() > 1 && isNonOverlapping_ && pParallelHelper_)
1268 using PNonoverlapping =
typename PTraits::template ParallelNonoverlapping<
1269 M, std::decay_t<
decltype((*massMatrix)[0])>>;
1277 DUNE_THROW(Dune::NotImplemented,
"Mass matrix for discretization method not implemented");
1280 double density_, viscosity_, weight_;
1281 Dune::InverseOperatorResult result_;
1282 Dune::ParameterTree params_;
1283 std::shared_ptr<const VelocityGG> vGridGeometry_;
1284 std::shared_ptr<const PressureGG> pGridGeometry_;
1285 const Vector& dirichletDofs_;
1286 std::string solverType_;
1288 std::shared_ptr<Dune::ScalarProduct<Vector>> scalarProduct_;
1290 std::shared_ptr<const PressureMatrix> pressureMatrix_;
1291 std::shared_ptr<const PressureVector> pressureDiagonal_;
1292 std::shared_ptr<Matrix> keptMatrix_;
1293 std::shared_ptr<Matrix> eliminatedEntries_;
1294 SolverComponents keptComponents_;
1297 std::shared_ptr<const typename VTraits::DofMapper> vDofMapper_;
1298 std::shared_ptr<const typename PTraits::DofMapper> pDofMapper_;
1299 std::shared_ptr<ParallelISTLHelper<VTraits>> vParallelHelper_;
1300 std::shared_ptr<ParallelISTLHelper<PTraits>> pParallelHelper_;
1301 std::shared_ptr<Comm> vComm_, pComm_;
1302 bool isNonOverlapping_ =
true;
Dune::SolverCategory::Category category() const override
Definition stokes_solver.hh:634
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition stokes_solver.hh:587
void apply(const X &x, Y &y) const override
Definition stokes_solver.hh:571
X domain_type
Definition stokes_solver.hh:553
M matrix_type
Definition stokes_solver.hh:552
ParallelStokesLinearOperator(const M &A, std::shared_ptr< Comm > vComm, std::shared_ptr< Comm > pComm, bool nonOverlapping)
Definition stokes_solver.hh:557
Y range_type
Definition stokes_solver.hh:554
typename X::field_type field_type
Definition stokes_solver.hh:555
void apply(X &v, const Y &d) override
Definition stokes_solver.hh:677
void pre(X &v, Y &d) override
Definition stokes_solver.hh:671
void post(X &v) override
Definition stokes_solver.hh:683
ParallelStokesPreconditioner(std::shared_ptr< SeqPrec > seqPrec, std::shared_ptr< Comm > vComm, std::shared_ptr< Comm > pComm, bool nonOverlapping)
Definition stokes_solver.hh:662
Dune::SolverCategory::Category category() const override
Definition stokes_solver.hh:689
X domain_type
Definition stokes_solver.hh:658
Y range_type
Definition stokes_solver.hh:659
typename X::field_type field_type
Definition stokes_solver.hh:660
X domain_type
Definition stokes_solver.hh:720
typename Dune::FieldTraits< field_type >::real_type real_type
Definition stokes_solver.hh:722
ParallelStokesScalarProduct(std::shared_ptr< Comm > vComm, std::shared_ptr< Comm > pComm, bool nonOverlapping)
Definition stokes_solver.hh:724
field_type dot(const X &x, const X &y) const override
Definition stokes_solver.hh:731
Dune::SolverCategory::Category category() const override
Definition stokes_solver.hh:761
real_type norm(const X &x) const override
Definition stokes_solver.hh:755
typename X::field_type field_type
Definition stokes_solver.hh:721
A Stokes preconditioner (saddle-point problem) for the problem .
Definition stokes_solver.hh:115
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category).
Definition stokes_solver.hh:244
StokesPreconditioner(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &fullLinearOperator, const std::shared_ptr< const PressureLinearOperator > &pressureLinearOperator, const Dune::ParameterTree ¶ms, std::shared_ptr< Comm > velComm, std::shared_ptr< Comm > presComm=nullptr)
Constructor (parallel).
Definition stokes_solver.hh:174
X domain_type
The domain type of the preconditioner.
Definition stokes_solver.hh:135
void post(X &update) override
Clean up the preconditioners of the velocity and the pressure block.
Definition stokes_solver.hh:236
typename X::field_type field_type
The field type of the preconditioner.
Definition stokes_solver.hh:139
Dune::Simd::Scalar< field_type > scalar_field_type
Scalar type underlying the field_type.
Definition stokes_solver.hh:141
M matrix_type
The matrix type the preconditioner is for.
Definition stokes_solver.hh:133
Dune::MatrixAdapter< P, V, V > PressureLinearOperator
the type of the pressure operator
Definition stokes_solver.hh:143
void setPressureDiagonal(std::shared_ptr< const V > diagonal)
Add a diagonal to the inverse of the pressure block.
Definition stokes_solver.hh:512
Y range_type
The range type of the preconditioner.
Definition stokes_solver.hh:137
void pre(X &update, Y ¤tDefect) override
Prepare the preconditioners of the velocity and the pressure block.
Definition stokes_solver.hh:196
StokesPreconditioner(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &fullLinearOperator, const std::shared_ptr< const PressureLinearOperator > &pressureLinearOperator, const Dune::ParameterTree ¶ms)
Constructor (sequential).
Definition stokes_solver.hh:151
void apply(X &update, const Y ¤tDefect) override
Apply the preconditioner.
Definition stokes_solver.hh:214
const std::string & paramGroup() const
the parameter group for getting parameter from the parameter tree
Definition solver.hh:78
LinearSolver(const std::string ¶mGroup="")
Construct the solver.
Definition solver.hh:43
double Scalar
Definition solver.hh:31
Generates a parameter tree required for the linear solvers and precondioners of the Dune ISTL.
Definition linearsolverparameters.hh:40
Adapter to turn a multi-type matrix into a thread-parallel linear operator. Adapts a matrix to the as...
Definition parallelmatrixadapter.hh:28
Exception thrown if a run-time parameter is not specified correctly.
Definition exceptions.hh:48
void setMatrix(const Matrix &A)
Keep a copy of the matrix, and the operator and preconditioner built on it, for solve(x,...
Definition stokes_solver.hh:860
void makeConsistent(Vector &v) const
Give the copies of shared degrees of freedom the values of their owners.
Definition stokes_solver.hh:951
bool solve(Vector &x, const Vector &b)
Solve with the matrix kept by setMatrix.
Definition stokes_solver.hh:896
void setPressureDiagonal(std::shared_ptr< const PressureVector > diagonal)
Set the diagonal added to the inverse of the pressure block (see StokesPreconditioner::setPressureDia...
Definition stokes_solver.hh:947
const Dune::InverseOperatorResult & result() const
Definition stokes_solver.hh:1006
bool solve(const Matrix &A, Vector &x, const Vector &b)
Definition stokes_solver.hh:848
void makeUnique(Vector &v) const
Set the entries of shared degrees of freedom this process does not own to zero.
Definition stokes_solver.hh:964
StokesSolver(std::shared_ptr< const VelocityGG > vGridGeometry, std::shared_ptr< const PressureGG > pGridGeometry, const Vector &dirichletDofs, const std::string ¶mGroup="")
Constructor.
Definition stokes_solver.hh:811
std::string name() const
Definition stokes_solver.hh:1001
void setMatrix(std::shared_ptr< Matrix > A)
Keep a copy of the matrix, and the operator and preconditioner built on it, for solve(x,...
Definition stokes_solver.hh:892
void setPressureMatrix(std::shared_ptr< const PressureMatrix > matrix)
Use the given matrix in place of the pressure mass matrix in the preconditioner.
Definition stokes_solver.hh:943
typename Preconditioner::PressureLinearOperator::matrix_type PressureMatrix
The matrix type of the pressure operator of the preconditioner.
Definition stokes_solver.hh:801
Scalar norm(const Vector &b) const
Definition stokes_solver.hh:976
Some exceptions thrown in DuMux.
Helper classes to compute the integration elements.
Dune::MatrixIndexSet getJacobianPattern(const GridGeometry &gridGeometry)
Helper function to generate Jacobian pattern for cell-centered methods.
Definition jacobianpattern.hh:28
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:26
void symmetrizeConstraints(Dune::BCRSMatrix< MBlock > &A, Vector &b, const Vector &constrainedRows)
Symmetrize the constrained system Ax=b.
Definition symmetrize_constraints.hh:117
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
bool hasParamInGroup(const std::string ¶mGroup, const std::string ¶m)
Check whether a key exists in the parameter tree with a model group prefix.
Definition parameters.hh:181
Helper function to generate Jacobian pattern for different discretization methods.
Generates a parameter tree required for the linear solvers and precondioners of the Dune ISTL.
Define traits for linear solvers.
Define some often used mathematical functions.
Definition cvfelocalresidual.hh:25
void completeCouplingResult(const Comm &comm, Block &y)
Complete the product y = M x of an off-diagonal block M with a consistent x to the unique representat...
Definition stokes_solver.hh:81
void zeroOverlap(const Comm &comm, Block &v)
Set the entries of overlap dofs to zero.
Definition stokes_solver.hh:66
void makeUnique(const Comm &comm, Block &v)
Definition stokes_solver.hh:56
constexpr CCMpfa ccmpfa
Definition method.hh:175
constexpr FCDiamond fcdiamond
Definition method.hh:184
constexpr CCTpfa cctpfa
Definition method.hh:174
constexpr Box box
Definition method.hh:176
void prepareMatrixParallel(Matrix &A, ParallelHelper &pHelper)
Prepare a matrix for parallel solvers.
Definition parallelhelpers.hh:1410
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:1441
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:257
Provides a helper class for nonoverlapping decomposition.
A parallel version of a linear operator.
Dumux preconditioners for iterative solvers.
Base class for linear solvers.
Helper type to determine whether a given type is a Dune::MultiTypeBlockMatrix.
Definition matrix.hh:37
Helper function to symmetrize row-constraints in constrained linear systems.