KASKADE 7 development version
blockDiagonalSchurPreconditioner.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2018 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef BLOCK_DIAGONAL_SCHUR_PRECONDITIONER_HH
14#define BLOCK_DIAGONAL_SCHUR_PRECONDITIONER_HH
15
16#include <cmath>
17#include <vector>
18
19#include <boost/fusion/include/at_c.hpp>
20
21#include <dune/istl/solvers.hh>
22#include <dune/istl/preconditioners.hh>
23#include <dune/istl/solvercategory.hh>
24
25#include "fem/istlinterface.hh"
26#include "linalg/direct.hh"
27#include "linalg/triplet.hh"
28#include "linalg/iluprecond.hh"
30
31
32namespace Kaskade
33{
34 namespace SchurPreconditionerDetail
35 {
36 template <class Operator, class Block>
38 {
39 typedef typename Operator::Assembler::AnsatzVariableSetDescription::template CoefficientVectorRepresentation<Block::firstCol,Block::lastCol>::type Domain;
40 typedef typename Operator::Assembler::TestVariableSetDescription::template CoefficientVectorRepresentation<Block::firstRow,Block::lastRow>::type Range;
41 };
42
43
44 template <class Scalar_>
46 {
47 typedef Scalar_ Scalar;
49
50 public:
51 JacobiIteration() = default;
52
53 template <class Operator>
54 explicit JacobiIteration(Operator const& A_)
55 : A(A_.template get<Matrix>(false)), diag(A.nrows(),0)
56 {
57 for(size_t i=0; i<A.ridx.size(); ++i) if(A.ridx[i] == A.cidx[i]) diag[A.ridx[i]] = A.data[i];
58 }
59
60 explicit JacobiIteration(Matrix const& A_)
61 : A(A_), diag(A.nrows(),0)
62 {
63 for(size_t i=0; i<A.ridx.size(); ++i) if(A.ridx[i] == A.cidx[i]) diag[A.ridx[i]] = A.data[i];
64 }
65
66 template <class Domain, class Range>
67 void apply(Domain& x, Range const& y, size_t nIter = 1) const
68 {
69 std::vector<Scalar> tmpx(x.dim()), tmpy;
70 IstlInterfaceDetail::toVector(y,tmpy);
71 for(size_t i=0; i<diag.size(); ++i) tmpx[i] = tmpy[i]/diag[i];
72
73 for(size_t iter=0; iter < nIter; ++iter)
74 {
75 for(size_t i=0; i<A.ridx.size(); ++i) if(A.ridx[i] != A.cidx[i]) tmpy[A.ridx[i]] -= A.data[i]*tmpx[A.cidx[i]];
76 for(size_t i=0; i<diag.size(); ++i) tmpx[i] += tmpy[i]/diag[i];
77 }
78 IstlInterfaceDetail::fromVector(tmpx,x);
79 }
80
81 private:
82 Matrix const& A;
83 std::vector<Scalar> diag;
84 };
85
86 template <class Scalar_>
88 {
89 typedef Scalar_ Scalar;
91
92 public:
93 InvertLumpedMatrix() = default;
94
95 template <class Operator, typename... Args>
96 explicit InvertLumpedMatrix(Operator const& A_, Args...)
97 {
98 Matrix A = A_.template get<Matrix>();
99 diag.resize(A.nrows());
100 for(size_t i=0; i<A.ridx.size(); ++i) if(A.ridx[i] == A.cidx[i]) diag[A.ridx[i]] = A.data[i];
101 }
102
103 template <typename... Args>
104 explicit InvertLumpedMatrix(Matrix const& A, Args...)
105 : diag(A.nrows(),0)
106 {
107 for(size_t i=0; i<A.ridx.size(); ++i) if(A.ridx[i] == A.cidx[i]) diag[A.ridx[i]] = A.data[i];
108 }
109
110 template <class Domain, class Range>
111 void apply(Domain& x, Range const& y) const
112 {
113 tmpx.resize(x.dim());
114 IstlInterfaceDetail::toVector(y,tmpy);
115 for(size_t i=0; i<diag.size(); ++i) tmpx[i] = tmpy[i]/diag[i];
116 IstlInterfaceDetail::fromVector(tmpx,x);
117 }
118
119 private:
120 std::vector<Scalar> diag;
121 mutable std::vector<Scalar> tmpx, tmpy;
122 };
123
124
125 template <class Domain, class Range>
127 {
128
129 public:
130 ApplyDirectSolver() = default;
131
132 template <class Operator>
134 : solver(DirectSolver<Domain,Range>(A,directType,property))
135 {}
136
138 : solver(DirectSolver<Domain,Range>(A,directType,property))
139 {}
140
141 void apply(Domain& x, Range const& y) const
142 {
143 solver.apply(y,x);
144 }
145
146 private:
148 };
149 } /* end of namespace PreconditionerDetail */
150
151
153
157 template <class Scalar_, class Domain_, class Range_,
158 class BlockK = IstlInterfaceDetail::BlockInfo<2,3,0,1>,
159 class BlockM = IstlInterfaceDetail::BlockInfo<0,1,0,1>,
160 class LinearSolver = SchurPreconditionerDetail::ApplyDirectSolver<Domain_,Range_>
161 >
163 {
164 public:
165 typedef Scalar_ Scalar;
166 typedef Domain_ Domain;
167 typedef Range_ Range;
169
175 template <class Assembler>
176 ApproximateSchurComplement(Assembler const& assembler, Scalar alpha, bool symmetricK_ = false, bool symmetricM_ = false)
177 : symmetricK(symmetricK_ && symmetricM_), symmetricM(symmetricM_), propertyK(symmetricK ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL), propertyM(symmetricM ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL)
178 {
179 updateMatrices(assembler,alpha);
180 }
181
182
183 template <class Matrix>
184 ApproximateSchurComplement(Matrix const& M_, Matrix const& K_, Scalar alpha, bool symmetricK_ = false, bool symmetricM_ = false)
185 : sqrtOfAlpha(sqrt(alpha)), symmetricK(symmetricK_ && symmetricM_), symmetricM(symmetricM_),
186 propertyK(symmetricK ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL), propertyM(symmetricM ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL),
187 M(M_), K(K_), N(M_)
188 {
189 N /= sqrtOfAlpha;
190 N += K;
191 initSolver();
192 }
193
197 template <class Assembler>
198 void updateMatrices(Assembler const& assembler, Scalar alpha)
199 {
200 sqrtOfAlpha = sqrt(alpha);
201 M = assembler.template get<Matrix,BlockM::firstRow,BlockM::lastRow,BlockM::firstCol,BlockM::lastCol>(symmetricM);
202 N = M.get();
203 N /= sqrtOfAlpha;
204 K = assembler.template get<Matrix,BlockK::firstRow,BlockK::lastRow,BlockK::firstCol,BlockK::lastCol>(symmetricK);
205 N += K;
206
207 initSolver();
208 }
209
210 template <class Matrix>
211 void updateMatrices(Matrix const& M_, Matrix const& K_, Scalar alpha)
212 {
213 M = M_;
214 K = K_;
215 N = M.get();
216 N /= sqrtOfAlpha;
217 N += K;
218 }
219
221 void solve(Domain& x, Range& y) const
222 {
223 solver.apply(x,y);
224 M.apply(x,y);
225 solver.apply(x,y);
226 }
227
228 Matrix const& getMassMatrix() const
229 {
230 return M.get();
231 }
232
234 {
235 return K;
236 }
237
238 private:
239 void initSolver()
240 {
241 DirectType directType = DirectType::MUMPS;
242 MatrixProperties property = (symmetricK && symmetricM) ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL;
243 solver = LinearSolver(N,directType,property);
244 }
245
247 Scalar sqrtOfAlpha;
248 bool symmetricK, symmetricM;
249 MatrixProperties propertyK, propertyM;
253 MatrixAsTriplet<Scalar> K;
255
261
262 LinearSolver solver;
263 };
264
265
267
271 template <class Scalar_,
272 class BlockK = IstlInterfaceDetail::BlockInfo<2,3,0,1>,
273 class BlockM = IstlInterfaceDetail::BlockInfo<0,1,0,1>
274 >
276 {
277 public:
278 typedef Scalar_ Scalar;
280
286 template <class Assembler>
287 ApproximateSchurComplement2(Assembler const& assembler, Scalar /*alpha*/, bool symmetricK_ = false, bool symmetricM_ = false)
288 : symmetricK(symmetricK_ && symmetricM_), symmetricM(symmetricM_), propertyK(symmetricK ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL), propertyM(symmetricM ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL)
289 {
290 updateMatrices(assembler);
291 }
292
296 template <class Assembler>
297 void updateMatrices(Assembler const& assembler)
298 {
299 M = assembler.template get<Matrix,BlockM::firstRow,BlockM::lastRow,BlockM::firstCol,BlockM::lastCol>(symmetricM);
300 L = M;
301 K = assembler.template get<Matrix,BlockK::firstRow,BlockK::lastRow,BlockK::firstCol,BlockK::lastCol>(symmetricK);
302 L += K;
303 }
304
305
306 template <class Domain, class Range>
307 void solve(Domain& x, Range const& y, size_t nIter) const
308 {
310
311 Kinv.apply(y,x);
312
313 std::vector<Scalar> tmpx, tmpy;
314 IstlInterfaceDetail::toVector(x,tmpx);
315 L.mv(tmpx,tmpy);
316 Range tmp(y);
317 IstlInterfaceDetail::fromVector(tmpy,tmp);
318
319 Kinv.apply(tmp,x);
320 }
321
323 {
324 return M;
325 }
326
328 {
329 return K;
330 }
331
332 private:
339 bool symmetricK, symmetricM;
340 MatrixProperties propertyK, propertyM;
341 };
342
343
350 template <class Operator, template <class,class,class,class,class,class> class SchurComplement = ApproximateSchurComplement,
351 class BlockK = IstlInterfaceDetail::BlockInfo<2,3,0,1>,
352 class BlockM = IstlInterfaceDetail::BlockInfo<0,1,0,1>,
353 class LinearSolver = SchurPreconditionerDetail::ApplyDirectSolver<typename SchurPreconditionerDetail::ExtractDomainAndRange<Operator,BlockM>::Domain, typename SchurPreconditionerDetail::ExtractDomainAndRange<Operator,BlockM>::Range>,
354 class LinearSolver_SchurComplement = LinearSolver
355 >
356 class BlockDiagonalSchurPreconditioner: public Dune::Preconditioner<typename Operator::Domain,typename Operator::Range>
357 {
360 typedef typename Operator::Assembler Assembler;
362
363 public:
364 typedef typename Operator::Scalar Scalar;
365 typedef typename Operator::Domain Domain;
366 typedef typename Operator::Range Range;
367
368 static int const category = Dune::SolverCategory::sequential;
369
370 explicit BlockDiagonalSchurPreconditioner(Operator const& A_,Scalar alpha_, bool symmetricK = false, bool symmetricM = false)
371 : A(A_), alpha(alpha_), schurComplement(A.getAssembler(), alpha, symmetricK, symmetricM),
372 propertyM(symmetricM ? MatrixProperties::SYMMETRIC : MatrixProperties::GENERAL), solver(schurComplement.getMassMatrix(),DirectType::MUMPS,propertyM)
373 {}
374
376
377 virtual void apply (Domain& x, Range const& y)
378 {
379 using namespace boost::fusion;
380
381 Range0 y0(at_c<0>(y.data));
382 Domain0 x0(at_c<0>(x.data));
383
384 std::cout << at_c<0>(x.data).dim() << std::endl;
385 solver.apply(x0,y0);
386 x0 *= 1./alpha;
387 at_c<0>(x.data) = at_c<0>(x0.data);
388
389 at_c<0>(y0.data) = at_c<1>(y.data);
390 solver.apply(x0,y0);
391// x0 *= 1./alpha;
392 at_c<1>(x.data) = at_c<0>(x0.data);
393
394 at_c<0>(y0.data) = at_c<2>(y.data);
395 schurComplement.solve(x0,y0);
396 at_c<2>(x.data) = at_c<0>(x0.data);
397 }
398
399 virtual void pre (Domain&, Range&) {}
400 virtual void post (Domain&) {}
401
402 private:
403 Operator const& A;
404 Scalar alpha;
405 SchurComplement<Scalar,Domain0,Range0,BlockK,BlockM,LinearSolver_SchurComplement> schurComplement;
406 MatrixProperties propertyM;
407 LinearSolver solver;
408 };
409} // namespace Kaskade
410#endif
Approximation of the schur complement.
ApproximateSchurComplement2(Assembler const &assembler, Scalar, bool symmetricK_=false, bool symmetricM_=false)
MatrixAsTriplet< Scalar > const & massMatrix() const
MatrixAsTriplet< Scalar > const & stiffnessMatrix() const
void solve(Domain &x, Range const &y, size_t nIter) const
Approximation of the schur complement according to Pearson/Wathen '10.
ApproximateSchurComplement(Matrix const &M_, Matrix const &K_, Scalar alpha, bool symmetricK_=false, bool symmetricM_=false)
void solve(Domain &x, Range &y) const
compute , overrides y
void updateMatrices(Assembler const &assembler, Scalar alpha)
ApproximateSchurComplement(Assembler const &assembler, Scalar alpha, bool symmetricK_=false, bool symmetricM_=false)
void updateMatrices(Matrix const &M_, Matrix const &K_, Scalar alpha)
BlockDiagonalSchurPreconditioner(Operator const &A_, Scalar alpha_, bool symmetricK=false, bool symmetricM=false)
Dune::LinearOperator interface for inverse operators.
Definition: direct.hh:553
virtual void apply(Domain const &x, Range &y) const
Definition: direct.hh:564
SparseIndexInt nrows() const
Returns number of rows (computes them, if not known)
Definition: triplet.hh:202
std::vector< SparseIndexInt > ridx
row indices
Definition: triplet.hh:669
std::vector< SparseIndexInt > cidx
column indices
Definition: triplet.hh:671
std::vector< Scalar > data
data
Definition: triplet.hh:673
ApplyDirectSolver(MatrixAsTriplet< typename Domain::Scalar > const &A, DirectType directType=DirectType::MUMPS, MatrixProperties property=MatrixProperties::GENERAL)
ApplyDirectSolver(Operator const &A, DirectType directType=DirectType::MUMPS, MatrixProperties property=MatrixProperties::GENERAL)
void apply(Domain &x, Range const &y, size_t nIter=1) const
Defines a linear operator with matrix representation .
Definition: concepts.hh:478
DirectType
Available direct solvers for linear equation systems.
Definition: enums.hh:35
@ MUMPS
MUMPS sparse solver.
MatrixProperties
Characterizations of sparse matrix properties.
Definition: enums.hh:76
Operator::Assembler::TestVariableSetDescription::template CoefficientVectorRepresentation< Block::firstRow, Block::lastRow >::type Range
Operator::Assembler::AnsatzVariableSetDescription::template CoefficientVectorRepresentation< Block::firstCol, Block::lastCol >::type Domain