12#ifndef DUMUX_LINEAR_STOKES_SOLVER_HH
13#define DUMUX_LINEAR_STOKES_SOLVER_HH
19#include <dune/common/parametertree.hh>
20#include <dune/common/hybridutilities.hh>
21#include <dune/common/exceptions.hh>
23#include <dune/istl/matrixindexset.hh>
24#include <dune/istl/preconditioner.hh>
25#include <dune/istl/preconditioners.hh>
26#include <dune/istl/solvers.hh>
27#include <dune/istl/paamg/amg.hh>
58template<
class M,
class X,
class Y,
int l = 2>
62 static_assert(l == 2,
"StokesPreconditioner expects a block level of 2 for Matrix type M.");
64 using A = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_0][Dune::Indices::_0])>;
65 using U = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_0])>;
67 using P = std::decay_t<decltype(std::declval<M>()[Dune::Indices::_1][Dune::Indices::_1])>;
68 using V = std::decay_t<decltype(std::declval<X>()[Dune::Indices::_1])>;
70 enum class Mode { symmetric, triangular, diagonal };
93 const std::shared_ptr<
const Dune::AssembledLinearOperator<M,X,Y>>& fullLinearOperator,
94 const std::shared_ptr<const PressureLinearOperator>& pressureLinearOperator,
95 const Dune::ParameterTree& params
97 : matrix_(fullLinearOperator->getmat())
98 , pmatrix_(pressureLinearOperator->getmat())
99 , verbosity_(params.get<int>(
"verbosity"))
100 , paramGroup_(params.get<std::string>(
"ParameterGroup"))
102 const auto mode = getParamFromGroup<std::string>(
103 paramGroup_,
"LinearSolver.Preconditioner.Mode",
"Diagonal"
106 if (mode ==
"Symmetric")
107 mode_ = Mode::symmetric;
108 else if (mode ==
"Triangular")
109 mode_ = Mode::triangular;
111 mode_ = Mode::diagonal;
113 initPreconditioner_(params);
119 void pre(X& update, Y& currentDefect)
override {}
132 void apply(X& update,
const Y& currentDefect)
override
134 using namespace Dune::Indices;
136 if (mode_ == Mode::symmetric)
138 update = applyRightBlock_(currentDefect);
139 update = applyDiagBlock_(update);
140 update = applyLeftBlock_(update);
142 else if (mode_ == Mode::triangular)
144 update = applyRightBlock_(currentDefect);
145 update = applyDiagBlock_(update);
148 update = applyDiagBlock_(currentDefect);
154 void post(X& update)
override {}
157 Dune::SolverCategory::Category
category()
const override
159 return Dune::SolverCategory::sequential;
163 X applyRightBlock_(
const Y& d)
165 using namespace Dune::Indices;
175 auto vTmp = d; vTmp = 0.0;
178 applyPreconditionerForA_(vTmp[_0], dTmp0);
181 matrix_[_1][_0].mv(vTmp[_0], vTmp[_1]);
190 X applyDiagBlock_(
const Y& d)
192 using namespace Dune::Indices;
199 if (mode_ == Mode::diagonal)
200 applyPreconditionerForA_(v[_0], dTmp[_0]);
207 applyPreconditionerForP_(v[_1], dTmp[_1]);
212 X applyLeftBlock_(
const Y& d)
214 using namespace Dune::Indices;
224 auto vTmp = d; vTmp = 0.0;
227 matrix_[_0][_1].umv(dTmp[_1], vTmp[_0]);
230 auto vTmp0 = vTmp[_0]; vTmp0 = 0.0;
231 applyPreconditionerForA_(vTmp0, vTmp[_0]);
240 void initPreconditioner_(
const Dune::ParameterTree& params)
242 using namespace Dune::Indices;
244 if (getParamFromGroup<bool>(paramGroup_,
"LinearSolver.DirectSolverForVelocity",
false))
247 directSolver_ = std::make_shared<Dune::UMFPack<A>>(matrix_[_0][_0], verbosity_);
248 using Wrap = Dune::InverseOperator2Preconditioner<Dune::InverseOperator<U, U>>;
249 preconditionerForA_ = std::make_shared<Wrap>(*directSolver_);
251 DUNE_THROW(Dune::InvalidStateException,
"Selected direct solver but UMFPack is not available.");
256 using VelLinearOperator = Dune::MatrixAdapter<A, U, U>;
257 auto lopV = std::make_shared<VelLinearOperator>(matrix_[_0][_0]);
258 preconditionerForA_ = std::make_shared<
259 Dune::Amg::AMG<VelLinearOperator, U, Dumux::ParMTSSOR<A,U,U>>
264 preconditionerForP_ = std::make_shared<PressJacobi>(pmatrix_, 1, 1.0);
267 template<
class Sol,
class Rhs>
268 void applyPreconditionerForA_(Sol& sol, Rhs& rhs)
const
270 preconditionerForA_->pre(sol, rhs);
271 preconditionerForA_->apply(sol, rhs);
272 preconditionerForA_->post(sol);
275 template<
class Sol,
class Rhs>
276 void applyPreconditionerForP_(Sol& sol, Rhs& rhs)
const
278 preconditionerForP_->pre(sol, rhs);
279 preconditionerForP_->apply(sol, rhs);
280 preconditionerForP_->post(sol);
288 const int verbosity_;
290 std::shared_ptr<Dune::Preconditioner<U, U>> preconditionerForA_;
291 std::shared_ptr<Dune::Preconditioner<V, V>> preconditionerForP_;
292 std::shared_ptr<Dune::InverseOperator<U, U>> directSolver_;
294 const std::string paramGroup_;
308template<
class Matrix,
class Vector,
class VelocityGG,
class PressureGG>
323 std::shared_ptr<const PressureGG> pGridGeometry,
324 const Vector& dirichletDofs,
327 , vGridGeometry_(std::move(vGridGeometry))
328 , pGridGeometry_(std::move(pGridGeometry))
329 , dirichletDofs_(dirichletDofs)
332 density_ = getParamFromGroup<double>(this->
paramGroup(),
"Component.LiquidDensity");
333 viscosity_ = getParamFromGroup<double>(this->
paramGroup(),
"Component.LiquidDynamicViscosity");
334 weight_ = getParamFromGroup<double>(this->
paramGroup(),
"LinearSolver.Preconditioner.MassMatrixWeight", 1.0);
335 solverType_ = getParamFromGroup<std::string>(this->
paramGroup(),
"LinearSolver.Type",
"gmres");
336 scalarProduct_ = std::make_shared<Dune::ScalarProduct<Vector>>();
339 bool solve(
const Matrix& A, Vector& x,
const Vector& b)
344 return applyIterativeSolver_(ATmp, x, bTmp);
349 return scalarProduct_->norm(b);
354 return "Block-preconditioned Stokes solver";
357 const Dune::InverseOperatorResult&
result()
const
363 bool applyIterativeSolver_(Matrix& A, Vector& x, Vector& b)
366 if (getParamFromGroup<bool>(this->
paramGroup(),
"LinearSolver.SymmetrizeDirichlet",
true))
370 using namespace Dune::Indices;
371 A[_1] *= -1.0/density_;
372 b[_1] *= -1.0/density_;
374 auto op = std::make_shared<Dumux::ParallelMultiTypeMatrixAdapter<Matrix, Vector, Vector>>(A);
375 auto pop = makePressureLinearOperator_<typename Preconditioner::PressureLinearOperator>();
376 auto preconditioner = std::make_shared<Preconditioner>(op, pop, params_.sub(
"preconditioner"));
377 params_[
"verbose"] = pGridGeometry_->gridView().comm().rank() == 0 ? params_[
"verbose"] :
"0";
380 std::unique_ptr<Dune::InverseOperator<Vector, Vector>> solver;
381 if (solverType_ ==
"minres")
382 solver = std::make_unique<Dune::MINRESSolver<Vector>>(op, scalarProduct_, preconditioner, params_);
383 else if (solverType_ ==
"bicgstab")
384 solver = std::make_unique<Dune::BiCGSTABSolver<Vector>>(op, scalarProduct_, preconditioner, params_);
385 else if (solverType_ ==
"gmres")
386 solver = std::make_unique<Dune::RestartedGMResSolver<Vector>>(op, scalarProduct_, preconditioner, params_);
388 DUNE_THROW(Dune::NotImplemented,
"Solver choice " << solverType_ <<
" is not implemented");
390 solver->apply(x, b, result_);
392 return result_.converged;
395 template<
class LinearOperator>
396 std::shared_ptr<LinearOperator> makePressureLinearOperator_()
398 using M =
typename LinearOperator::matrix_type;
399 auto massMatrix = createMassMatrix_<M>();
400 return std::make_shared<LinearOperator>(massMatrix);
404 std::shared_ptr<M> createMassMatrix_()
406 auto massMatrix = std::make_shared<M>();
407 massMatrix->setBuildMode(M::random);
408 const auto numDofs = pGridGeometry_->numDofs();
410 Dune::MatrixIndexSet pattern;
411 pattern.resize(numDofs, numDofs);
412 for (
unsigned int globalI = 0; globalI < numDofs; ++globalI)
413 pattern.add(globalI, globalI);
414 pattern.exportIdx(*massMatrix);
416 const auto& gv = pGridGeometry_->gridView();
417 auto fvGeometry =
localView(*pGridGeometry_);
418 for (
const auto& element : elements(gv))
420 fvGeometry.bindElement(element);
421 for (
const auto& scv : scvs(fvGeometry))
423 using Extrusion = Extrusion_t<PressureGG>;
424 const auto dofIndex = scv.dofIndex();
425 if (
element.partitionType() == Dune::GhostEntity)
426 (*massMatrix)[dofIndex][dofIndex] = 1.0;
428 (*massMatrix)[dofIndex][dofIndex] += weight_*
Extrusion::volume(fvGeometry, scv)/(2.0*viscosity_);
435 double density_, viscosity_, weight_;
436 Dune::InverseOperatorResult result_;
437 Dune::ParameterTree params_;
438 std::shared_ptr<const VelocityGG> vGridGeometry_;
439 std::shared_ptr<const PressureGG> pGridGeometry_;
440 const Vector& dirichletDofs_;
441 std::string solverType_;
443 std::shared_ptr<Dune::ScalarProduct<Vector>> scalarProduct_;
A Stokes preconditioner (saddle-point problem) for the problem .
Definition: stokes_solver.hh:60
Dune::SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category)
Definition: stokes_solver.hh:157
X domain_type
The domain type of the preconditioner.
Definition: stokes_solver.hh:76
void post(X &update) override
Clean up.
Definition: stokes_solver.hh:154
typename X::field_type field_type
The field type of the preconditioner.
Definition: stokes_solver.hh:80
Dune::Simd::Scalar< field_type > scalar_field_type
Scalar type underlying the field_type.
Definition: stokes_solver.hh:82
M matrix_type
The matrix type the preconditioner is for.
Definition: stokes_solver.hh:74
Dune::MatrixAdapter< P, V, V > PressureLinearOperator
the type of the pressure operator
Definition: stokes_solver.hh:84
Y range_type
The range type of the preconditioner.
Definition: stokes_solver.hh:78
void pre(X &update, Y ¤tDefect) override
Prepare the preconditioner.
Definition: stokes_solver.hh:119
StokesPreconditioner(const std::shared_ptr< const Dune::AssembledLinearOperator< M, X, Y > > &fullLinearOperator, const std::shared_ptr< const PressureLinearOperator > &pressureLinearOperator, const Dune::ParameterTree ¶ms)
Constructor.
Definition: stokes_solver.hh:92
void apply(X &update, const Y ¤tDefect) override
Apply the preconditioner.
Definition: stokes_solver.hh:132
Base class for linear solvers.
Definition: solver.hh:27
const std::string & paramGroup() const
the parameter group for getting parameter from the parameter tree
Definition: solver.hh:78
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
Multi-threaded Jacobi preconditioner.
Definition: preconditioners.hh:331
Preconditioned iterative solver for the incompressible Stokes problem.
Definition: stokes_solver.hh:311
const Dune::InverseOperatorResult & result() const
Definition: stokes_solver.hh:357
bool solve(const Matrix &A, Vector &x, const Vector &b)
Definition: stokes_solver.hh:339
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:322
std::string name() const
Definition: stokes_solver.hh:352
Scalar norm(const Vector &b) const
Definition: stokes_solver.hh:347
Helper classes to compute the integration elements.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
auto volume(const Geometry &geo, unsigned int integrationOrder=4)
The volume of a given geometry.
Definition: volume.hh:159
void symmetrizeConstraints(Dune::BCRSMatrix< MBlock > &A, Vector &b, const Vector &constrainedRows)
Symmetrize the constrained system Ax=b.
Definition: symmetrize_constraints.hh:117
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.
Distance implementation details.
Definition: cvfelocalresidual.hh:25
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.