13#ifndef TAYLORHOODPRECONDITIONER_HH
14#define TAYLORHOODPRECONDITIONER_HH
16#include "dune/common/config.h"
24#include "dune/grid/common/rangegenerators.hh"
25#include "dune/istl/preconditioner.hh"
32 namespace TaylorHoodPreconditionerDetail
82 template <
int dim,
class Real=
double>
88 template <
class R,
int n>
105 template <
class R,
int nu>
113 std::vector<EntryA> D;
114 std::vector<int> idx;
201 :
public Dune::Preconditioner<X,X>
228 template <
class AGOP,
class VelocitySpace>
230 VelocitySpace
const& velocitySpace)
242 template <
class MatrixA,
class MatrixB,
class MatrixBt,
class VelocitySpace>
244 VelocitySpace
const& velocitySpace)
245 : dim(VelocitySpace::dim)
247 auto const& gridView = velocitySpace.gridView();
248 static_assert(MatrixA::block_type::rows==1,
"matrix blocks should have one row");
249 static_assert(MatrixA::block_type::cols==1,
"matrix blocks should have one col");
250 assert(A.N() % dim == 0);
251 assert(A.M() % dim == 0);
252 assert(A.M() == B.M());
255 patchDofs.resize(gridView.size(dim));
256 localInverse.resize(patchDofs.size());
259 assert(patches.size()==patchDofs.size());
262 velocityPatchCount.resize(A.N()/dim,0);
263 pressurePatchCount.resize(B.N(),0);
270 for (
size_t i=0; i<patches.size(); ++i)
273bool boundaryPatch =
false;
274for (
auto const& cell: patches[i])
275 for (
auto const& face: Dune::intersections(gridView,cell))
277 boundaryPatch =
true;
280 auto const& velocityDofs =
algebraicPatch(velocitySpace,patches[i]);
285 std::vector<size_t> vDofs;
286 vDofs.reserve(dim*velocityDofs.size());
287 for (
auto j: velocityDofs)
288 for (
int k=0; k<dim; ++k)
289 vDofs.push_back(dim*j+k);
291 int const nA = vDofs.size();
292 assert(nA==dim*velocityDofs.size());
297 std::vector<size_t> pressureDofs;
298 for (
size_t const i: vDofs)
299 for (
auto ci=Bt[i].begin(); ci!=Bt[i].end(); ++ci)
300 pressureDofs.push_back(ci.index());
302 std::sort(pressureDofs.begin(),pressureDofs.end());
303 pressureDofs.erase(std::unique(pressureDofs.begin(),pressureDofs.end()),
305 int nB = pressureDofs.size();
308 for (
size_t uIdx: velocityDofs)
309 ++velocityPatchCount[uIdx];
310 for (
size_t pIdx: pressureDofs)
311 ++pressurePatchCount[pIdx];
354 for (
int k=1; k<2; ++k)
356std::cout <<
"patch " << k <<
" indices: idxu=[";
357for(
int i=0; i<patchDofs[k][0].size(); ++i) std::cout << 2*patchDofs[k][0][i]+1 <<
' ' << 2*patchDofs[k][0][i]+2 <<
' ';
358std::cout <<
"]; idxp=[";
359for (
int i=0; i<patchDofs[k][1].size(); ++i) std::cout << patchDofs[k][1][i]+1 <<
' ';
364 std::vector<double> r(dim*patchDofs[k][0].size()+patchDofs[k][1].size());
366std::cout <<
"weighted urhs=[";
368 for (
int i=0; i<patchDofs[k][0].size(); ++i)
370 auto uIdx = patchDofs[k][0][i];
371 double w = weight(velocityPatchCount[uIdx],
prolongation,flavour);
372 for (
int j=0; j<dim; ++j)
374 r[i*dim+j] = component<0>(y)[uIdx][j] * w;
375std::cout << r[i*dim+j] <<
' ';
378std::cout <<
"];\nweighted prhs=[";
382 for (
int i=0; i<patchDofs[k][1].size(); ++i)
384 auto pIdx = patchDofs[k][1][i];
385 double w = weight(pressurePatchCount[pIdx],
prolongation,flavour);
386 r[dim*patchDofs[k][0].size()+i] = component<1>(y)[pIdx][0] * w;
387std::cout << r[dim*patchDofs[k][0].size()+i] <<
' ';
393 std::vector<double> z(r.size(),0.0);
401 for (
int i=0; i<patchDofs[k][0].size(); ++i)
403 auto uIdx = patchDofs[k][0][i];
404 double w = weight(velocityPatchCount[uIdx],
prolongation,flavour);
405 for (
int j=0; j<dim; ++j)
407 component<0>(x)[uIdx][j] += z[i*dim+j] * w;
408std::cout << z[i*dim+j] * w <<
' ';
411std::cout <<
"]; \np = [";
414 for (
int i=0; i<patchDofs[k][1].size(); ++i)
416 auto pIdx = patchDofs[k][1][i];
417 double w = weight(pressurePatchCount[pIdx],
prolongation,flavour);
418 component<1>(x)[pIdx][0] += z[dim*patchDofs[k][0].size()+i] * w;
419std::cout << z[dim*patchDofs[k][0].size()+i] * w <<
' ';
434 virtual Dune::SolverCategory::Category
category()
const override
436 return Dune::SolverCategory::sequential;
445 double w = 1.0/
count;
460 std::vector<std::array<std::vector<size_t>,2>> patchDofs;
463 std::vector<LocalSolver> localInverse;
466 std::vector<int> velocityPatchCount;
467 std::vector<int> pressurePatchCount;
480 template <
class AGOP>
483 typename AGOP::Domain>
488 static_assert(std::is_same_v<domain_type,range_type>,
"need a symmetric saddle point operator");
524 K->applyscaleadd(-1.0,z,r);
Interface for symmetric preconditioners.
Symmetric Taylor-Hood constraint preconditioner.
typename AGOP::Scalar field_type
SymmetricTaylorHoodPreconditioner(AGOP const &K_)
Constructor.
typename AGOP::Domain domain_type
void init(domain_type &x, range_type const &y) const
Computes an approximate solution satisfying the constraints.
virtual void apply(domain_type &x, range_type const &y) override
typename AGOP::Range range_type
Solves small Stokes systems even if incompressibility constraints are linearly dependent.
LocalStokesSolver(MatrixA A, MatrixB B, Real tol)
void apply(Vector< R, dim > &u, Vector< R, 1 > &p, Vector< R, dim > const &f, Vector< R, 1 > const &g) const
std::vector< int > const & constraintIndices() const
the indices of B rows that are actually retained in the reduced system
Matrix const & getInvK() const
Constraint preconditioner for Taylor-Hood discretizations of incompressibility problems.
virtual Dune::SolverCategory::Category category() const override
virtual void post(domain_type &x) override
virtual bool requiresInitializedInput() const
TaylorHoodPreconditioner(AGOP const &K, VelocitySpace const &velocitySpace)
Constructor.
void apply(domain_type &x, range_type const &y, TaylorHoodPreconditionerFlavour flavour) const
Applies the preconditioner either as presmoother, postsmoother, or in its symmetric flavour.
virtual void pre(domain_type &x, range_type &) override
X domain_type
The domain type of the saddle point system.
TaylorHoodPreconditioner(MatrixA const &A, MatrixB const &B, MatrixBt const &Bt, VelocitySpace const &velocitySpace)
Constructor.
virtual void apply(domain_type &x, range_type const &y) override
Appliess the symmetric preconditioner as .
typename X::field_type field_type
domain_type range_type
The range type of the saddle point system.
int count(Cell const &cell, int codim)
Computes the number of subentities of codimension c of a given entity.
std::vector< size_t > algebraicPatch(Space const &space, Range const &cells)
Computes the global indices of all ansatz functions whose support is a subset of the union of given c...
auto computePatches(GridView const &gridview)
Computes the patches around vertices of the grid view.
NumaBCRSMatrix< Dune::FieldMatrix< typename FineSpace::Scalar, 1, 1 >, SparseIndex > prolongation(CoarseSpace const &coarseSpace, FineSpace const &fineSpace)
Computes an interpolation-based prolongation matrix from a (supposedly) coarser space to a finer spac...
TaylorHoodPreconditionerFlavour
tag for controlling the TaylorHoodPreconditioner flavour