1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_ISTL_GSETC_HH
4 #define DUNE_ISTL_GSETC_HH
5 
6 #include <cmath>
7 #include <complex>
8 #include <iostream>
9 #include <iomanip>
10 #include <string>
11 
12 #include <dune/common/hybridutilities.hh>
13 
14 #include "multitypeblockvector.hh"
15 #include "multitypeblockmatrix.hh"
16 
17 #include "istlexception.hh"
18 
19 
20 /*! \file
21    \brief Simple iterative methods like Jacobi, Gauss-Seidel, SOR, SSOR, etc.
22     in a generic way
23  */
24 
25 namespace Dune {
26 
27   /**
28    * @defgroup ISTL_Kernel Block Recursive Iterative Kernels
29    * @ingroup ISTL_SPMV
30    *
31    * Generic iterative kernels for the solvers which work on the block recursive
32    * structure of the matrices and vectors.
33    * @addtogroup ISTL_Kernel
34    * @{
35    */
36 
37   //============================================================
38   // parameter types
39   //============================================================
40 
41   //! compile-time parameter for block recursion depth
42   template<int l>
43   struct BL {
44     enum {recursion_level = l};
45   };
46 
47   enum WithDiagType {
48     withdiag=1,
49     nodiag=0
50   };
51 
52   enum WithRelaxType {
53     withrelax=1,
54     norelax=0
55   };
56 
57   //============================================================
58   // generic triangular solves
59   // consider block decomposition A = L + D + U
60   // we can invert L, L+D, U, U+D
61   // we can apply relaxation or not
62   // we can recurse over a fixed number of levels
63   //============================================================
64 
65   // template meta program for triangular solves
66   template<int I, WithDiagType diag, WithRelaxType relax>
67   struct algmeta_btsolve {
68     template<class M, class X, class Y, class K>
bltsolveDune::algmeta_btsolve69     static void bltsolve (const M& A, X& v, const Y& d, const K& w)
70     {
71       // iterator types
72       typedef typename M::ConstRowIterator rowiterator;
73       typedef typename M::ConstColIterator coliterator;
74       typedef typename Y::block_type bblock;
75 
76       // local solve at each block and immediate update
77       rowiterator endi=A.end();
78       for (rowiterator i=A.begin(); i!=endi; ++i)
79       {
80         bblock rhs(d[i.index()]);
81         coliterator j;
82         for (j=(*i).begin(); j.index()<i.index(); ++j)
83           (*j).mmv(v[j.index()],rhs);
84         algmeta_btsolve<I-1,diag,relax>::bltsolve(*j,v[i.index()],rhs,w);
85       }
86     }
87     template<class M, class X, class Y, class K>
butsolveDune::algmeta_btsolve88     static void butsolve (const M& A, X& v, const Y& d, const K& w)
89     {
90       // iterator types
91       typedef typename M::ConstRowIterator rowiterator;
92       typedef typename M::ConstColIterator coliterator;
93       typedef typename Y::block_type bblock;
94 
95       // local solve at each block and immediate update
96       rowiterator rendi=A.beforeBegin();
97       for (rowiterator i=A.beforeEnd(); i!=rendi; --i)
98       {
99         bblock rhs(d[i.index()]);
100         coliterator j;
101         for (j=(*i).beforeEnd(); j.index()>i.index(); --j)
102           (*j).mmv(v[j.index()],rhs);
103         algmeta_btsolve<I-1,diag,relax>::butsolve(*j,v[i.index()],rhs,w);
104       }
105     }
106   };
107 
108   // recursion end ...
109   template<>
110   struct algmeta_btsolve<0,withdiag,withrelax> {
111     template<class M, class X, class Y, class K>
bltsolveDune::algmeta_btsolve112     static void bltsolve (const M& A, X& v, const Y& d, const K& w)
113     {
114       A.solve(v,d);
115       v *= w;
116     }
117     template<class M, class X, class Y, class K>
butsolveDune::algmeta_btsolve118     static void butsolve (const M& A, X& v, const Y& d, const K& w)
119     {
120       A.solve(v,d);
121       v *= w;
122     }
123   };
124   template<>
125   struct algmeta_btsolve<0,withdiag,norelax> {
126     template<class M, class X, class Y, class K>
bltsolveDune::algmeta_btsolve127     static void bltsolve (const M& A, X& v, const Y& d, const K& /*w*/)
128     {
129       A.solve(v,d);
130     }
131     template<class M, class X, class Y, class K>
butsolveDune::algmeta_btsolve132     static void butsolve (const M& A, X& v, const Y& d, const K& /*w*/)
133     {
134       A.solve(v,d);
135     }
136   };
137   template<>
138   struct algmeta_btsolve<0,nodiag,withrelax> {
139     template<class M, class X, class Y, class K>
bltsolveDune::algmeta_btsolve140     static void bltsolve (const M& /*A*/, X& v, const Y& d, const K& w)
141     {
142       v = d;
143       v *= w;
144     }
145     template<class M, class X, class Y, class K>
butsolveDune::algmeta_btsolve146     static void butsolve (const M& /*A*/, X& v, const Y& d, const K& w)
147     {
148       v = d;
149       v *= w;
150     }
151   };
152   template<>
153   struct algmeta_btsolve<0,nodiag,norelax> {
154     template<class M, class X, class Y, class K>
bltsolveDune::algmeta_btsolve155     static void bltsolve (const M& /*A*/, X& v, const Y& d, const K& /*w*/)
156     {
157       v = d;
158     }
159     template<class M, class X, class Y, class K>
butsolveDune::algmeta_btsolve160     static void butsolve (const M& /*A*/, X& v, const Y& d, const K& /*w*/)
161     {
162       v = d;
163     }
164   };
165 
166 
167   // user calls
168 
169   // default block recursion level = 1
170 
171   //! block lower triangular solve
172   template<class M, class X, class Y>
bltsolve(const M & A,X & v,const Y & d)173   void bltsolve (const M& A, X& v, const Y& d)
174   {
175     typename X::field_type w=1;
176     algmeta_btsolve<1,withdiag,norelax>::bltsolve(A,v,d,w);
177   }
178   //! relaxed block lower triangular solve
179   template<class M, class X, class Y, class K>
bltsolve(const M & A,X & v,const Y & d,const K & w)180   void bltsolve (const M& A, X& v, const Y& d, const K& w)
181   {
182     algmeta_btsolve<1,withdiag,withrelax>::bltsolve(A,v,d,w);
183   }
184   //! unit block lower triangular solve
185   template<class M, class X, class Y>
ubltsolve(const M & A,X & v,const Y & d)186   void ubltsolve (const M& A, X& v, const Y& d)
187   {
188     typename X::field_type w=1;
189     algmeta_btsolve<1,nodiag,norelax>::bltsolve(A,v,d,w);
190   }
191   //! relaxed unit block lower triangular solve
192   template<class M, class X, class Y, class K>
ubltsolve(const M & A,X & v,const Y & d,const K & w)193   void ubltsolve (const M& A, X& v, const Y& d, const K& w)
194   {
195     algmeta_btsolve<1,nodiag,withrelax>::bltsolve(A,v,d,w);
196   }
197 
198   //! block upper triangular solve
199   template<class M, class X, class Y>
butsolve(const M & A,X & v,const Y & d)200   void butsolve (const M& A, X& v, const Y& d)
201   {
202     typename X::field_type w=1;
203     algmeta_btsolve<1,withdiag,norelax>::butsolve(A,v,d,w);
204   }
205   //! relaxed block upper triangular solve
206   template<class M, class X, class Y, class K>
butsolve(const M & A,X & v,const Y & d,const K & w)207   void butsolve (const M& A, X& v, const Y& d, const K& w)
208   {
209     algmeta_btsolve<1,withdiag,withrelax>::butsolve(A,v,d,w);
210   }
211   //! unit block upper triangular solve
212   template<class M, class X, class Y>
ubutsolve(const M & A,X & v,const Y & d)213   void ubutsolve (const M& A, X& v, const Y& d)
214   {
215     typename X::field_type w=1;
216     algmeta_btsolve<1,nodiag,norelax>::butsolve(A,v,d,w);
217   }
218   //! relaxed unit block upper triangular solve
219   template<class M, class X, class Y, class K>
ubutsolve(const M & A,X & v,const Y & d,const K & w)220   void ubutsolve (const M& A, X& v, const Y& d, const K& w)
221   {
222     algmeta_btsolve<1,nodiag,withrelax>::butsolve(A,v,d,w);
223   }
224 
225   // general block recursion level >= 0
226 
227   //! block lower triangular solve
228   template<class M, class X, class Y, int l>
bltsolve(const M & A,X & v,const Y & d,BL<l>)229   void bltsolve (const M& A, X& v, const Y& d, BL<l> /*bl*/)
230   {
231     typename X::field_type w=1;
232     algmeta_btsolve<l,withdiag,norelax>::bltsolve(A,v,d,w);
233   }
234   //! relaxed block lower triangular solve
235   template<class M, class X, class Y, class K, int l>
bltsolve(const M & A,X & v,const Y & d,const K & w,BL<l>)236   void bltsolve (const M& A, X& v, const Y& d, const K& w, BL<l> /*bl*/)
237   {
238     algmeta_btsolve<l,withdiag,withrelax>::bltsolve(A,v,d,w);
239   }
240   //! unit block lower triangular solve
241   template<class M, class X, class Y, int l>
ubltsolve(const M & A,X & v,const Y & d,BL<l>)242   void ubltsolve (const M& A, X& v, const Y& d, BL<l> /*bl*/)
243   {
244     typename X::field_type w=1;
245     algmeta_btsolve<l,nodiag,norelax>::bltsolve(A,v,d,w);
246   }
247   //! relaxed unit block lower triangular solve
248   template<class M, class X, class Y, class K, int l>
ubltsolve(const M & A,X & v,const Y & d,const K & w,BL<l>)249   void ubltsolve (const M& A, X& v, const Y& d, const K& w, BL<l> /*bl*/)
250   {
251     algmeta_btsolve<l,nodiag,withrelax>::bltsolve(A,v,d,w);
252   }
253 
254   //! block upper triangular solve
255   template<class M, class X, class Y, int l>
butsolve(const M & A,X & v,const Y & d,BL<l> bl)256   void butsolve (const M& A, X& v, const Y& d, BL<l> bl)
257   {
258     typename X::field_type w=1;
259     algmeta_btsolve<l,withdiag,norelax>::butsolve(A,v,d,w);
260   }
261   //! relaxed block upper triangular solve
262   template<class M, class X, class Y, class K, int l>
butsolve(const M & A,X & v,const Y & d,const K & w,BL<l> bl)263   void butsolve (const M& A, X& v, const Y& d, const K& w, BL<l> bl)
264   {
265     algmeta_btsolve<l,withdiag,withrelax>::butsolve(A,v,d,w);
266   }
267   //! unit block upper triangular solve
268   template<class M, class X, class Y, int l>
ubutsolve(const M & A,X & v,const Y & d,BL<l> bl)269   void ubutsolve (const M& A, X& v, const Y& d, BL<l> bl)
270   {
271     typename X::field_type w=1;
272     algmeta_btsolve<l,nodiag,norelax>::butsolve(A,v,d,w);
273   }
274   //! relaxed unit block upper triangular solve
275   template<class M, class X, class Y, class K, int l>
ubutsolve(const M & A,X & v,const Y & d,const K & w,BL<l> bl)276   void ubutsolve (const M& A, X& v, const Y& d, const K& w, BL<l> bl)
277   {
278     algmeta_btsolve<l,nodiag,withrelax>::butsolve(A,v,d,w);
279   }
280 
281 
282 
283   //============================================================
284   // generic block diagonal solves
285   // consider block decomposition A = L + D + U
286   // we can apply relaxation or not
287   // we can recurse over a fixed number of levels
288   //============================================================
289 
290   // template meta program for diagonal solves
291   template<int I, WithRelaxType relax>
292   struct algmeta_bdsolve {
293     template<class M, class X, class Y, class K>
bdsolveDune::algmeta_bdsolve294     static void bdsolve (const M& A, X& v, const Y& d, const K& w)
295     {
296       // iterator types
297       typedef typename M::ConstRowIterator rowiterator;
298       typedef typename M::ConstColIterator coliterator;
299 
300       // local solve at each block and immediate update
301       rowiterator rendi=A.beforeBegin();
302       for (rowiterator i=A.beforeEnd(); i!=rendi; --i)
303       {
304         coliterator ii=(*i).find(i.index());
305         algmeta_bdsolve<I-1,relax>::bdsolve(*ii,v[i.index()],d[i.index()],w);
306       }
307     }
308   };
309 
310   // recursion end ...
311   template<>
312   struct algmeta_bdsolve<0,withrelax> {
313     template<class M, class X, class Y, class K>
bdsolveDune::algmeta_bdsolve314     static void bdsolve (const M& A, X& v, const Y& d, const K& w)
315     {
316       A.solve(v,d);
317       v *= w;
318     }
319   };
320   template<>
321   struct algmeta_bdsolve<0,norelax> {
322     template<class M, class X, class Y, class K>
bdsolveDune::algmeta_bdsolve323     static void bdsolve (const M& A, X& v, const Y& d, const K& /*w*/)
324     {
325       A.solve(v,d);
326     }
327   };
328 
329   // user calls
330 
331   // default block recursion level = 1
332 
333   //! block diagonal solve, no relaxation
334   template<class M, class X, class Y>
bdsolve(const M & A,X & v,const Y & d)335   void bdsolve (const M& A, X& v, const Y& d)
336   {
337     typename X::field_type w=1;
338     algmeta_bdsolve<1,norelax>::bdsolve(A,v,d,w);
339   }
340   //! block diagonal solve, with relaxation
341   template<class M, class X, class Y, class K>
bdsolve(const M & A,X & v,const Y & d,const K & w)342   void bdsolve (const M& A, X& v, const Y& d, const K& w)
343   {
344     algmeta_bdsolve<1,withrelax>::bdsolve(A,v,d,w);
345   }
346 
347   // general block recursion level >= 0
348 
349   //! block diagonal solve, no relaxation
350   template<class M, class X, class Y, int l>
bdsolve(const M & A,X & v,const Y & d,BL<l>)351   void bdsolve (const M& A, X& v, const Y& d, BL<l> /*bl*/)
352   {
353     typename X::field_type w=1;
354     algmeta_bdsolve<l,norelax>::bdsolve(A,v,d,w);
355   }
356   //! block diagonal solve, with relaxation
357   template<class M, class X, class Y, class K, int l>
bdsolve(const M & A,X & v,const Y & d,const K & w,BL<l>)358   void bdsolve (const M& A, X& v, const Y& d, const K& w, BL<l> /*bl*/)
359   {
360     algmeta_bdsolve<l,withrelax>::bdsolve(A,v,d,w);
361   }
362 
363 
364   //============================================================
365   // generic steps of iteration methods
366   // Jacobi, Gauss-Seidel, SOR, SSOR
367   // work directly on Ax=b, ie solve M(x^{i+1}-x^i) = w (b-Ax^i)
368   // we can recurse over a fixed number of levels
369   //============================================================
370 
371   // template meta program for iterative solver steps
372   template<int I, typename M>
373   struct algmeta_itsteps {
374 
375     template<class X, class Y, class K>
dbgsDune::algmeta_itsteps376     static void dbgs (const M& A, X& x, const Y& b, const K& w)
377     {
378       typedef typename M::ConstRowIterator rowiterator;
379       typedef typename M::ConstColIterator coliterator;
380       typedef typename Y::block_type bblock;
381       bblock rhs;
382 
383       X xold(x);     // remember old x
384 
385       rowiterator endi=A.end();
386       for (rowiterator i=A.begin(); i!=endi; ++i)
387       {
388         rhs = b[i.index()];           // rhs = b_i
389         coliterator endj=(*i).end();
390         coliterator j=(*i).begin();
391         if constexpr (IsNumber<typename M::block_type>())
392         {
393           for (; j.index()<i.index(); ++j)
394             rhs -= (*j) * x[j.index()];
395           coliterator diag=j++;           // *diag = a_ii and increment coliterator j from a_ii to a_i+1,i to skip diagonal
396           for (; j != endj; ++j)
397             rhs -= (*j) * x[j.index()];
398           x[i.index()] = rhs / (*diag);
399         }
400         else
401         {
402           for (; j.index()<i.index(); ++j)           // iterate over a_ij with j < i
403             (*j).mmv(x[j.index()],rhs);               // rhs -= sum_{j<i} a_ij * xnew_j
404           coliterator diag=j++;           // *diag = a_ii and increment coliterator j from a_ii to a_i+1,i to skip diagonal
405           for (; j != endj; ++j)           // iterate over a_ij with j > i
406             (*j).mmv(x[j.index()],rhs);               // rhs -= sum_{j>i} a_ij * xold_j
407           algmeta_itsteps<I-1,typename M::block_type>::dbgs(*diag,x[i.index()],rhs,w);           // if I==1: xnew_i = rhs/a_ii
408         }
409       }
410       // next two lines: xnew_i = w / a_ii * (b_i - sum_{j<i} a_ij * xnew_j - sum_{j>=i} a_ij * xold_j) + (1-w)*xold;
411       x *= w;
412       x.axpy(K(1)-w,xold);
413     }
414 
415     template<class X, class Y, class K>
bsorfDune::algmeta_itsteps416     static void bsorf (const M& A, X& x, const Y& b, const K& w)
417     {
418       typedef typename M::ConstRowIterator rowiterator;
419       typedef typename M::ConstColIterator coliterator;
420       typedef typename Y::block_type bblock;
421       typedef typename X::block_type xblock;
422       bblock rhs;
423       xblock v;
424 
425       // Initialize nested data structure if there are entries
426       if(A.begin()!=A.end())
427         v=x[0];
428 
429       rowiterator endi=A.end();
430       for (rowiterator i=A.begin(); i!=endi; ++i)
431       {
432         rhs = b[i.index()];           // rhs = b_i
433         coliterator endj=(*i).end();           // iterate over a_ij with j < i
434         coliterator j=(*i).begin();
435         if constexpr (IsNumber<typename M::block_type>())
436         {
437           for (; j.index()<i.index(); ++j)
438             rhs -= (*j) * x[j.index()];               //  rhs -= sum_{j<i} a_ij * xnew_j
439           coliterator diag=j;           // *diag = a_ii
440           for (; j!=endj; ++j)
441             rhs -= (*j) * x[j.index()];               // rhs -= sum_{j<i} a_ij * xnew_j
442           v = rhs / (*diag);
443           x[i.index()] += w*v;           // x_i = w / a_ii * (b_i - sum_{j<i} a_ij * xnew_j - sum_{j>=i} a_ij * xold_j)
444         }
445         else
446         {
447           for (; j.index()<i.index(); ++j)
448             (*j).mmv(x[j.index()],rhs);               //  rhs -= sum_{j<i} a_ij * xnew_j
449           coliterator diag=j;           // *diag = a_ii
450           for (; j!=endj; ++j)
451             (*j).mmv(x[j.index()],rhs);               // rhs -= sum_{j<i} a_ij * xnew_j
452           algmeta_itsteps<I-1,typename M::block_type>::bsorf(*diag,v,rhs,w);           // if blocksize I==1: v = rhs/a_ii
453           x[i.index()].axpy(w,v);           // x_i = w / a_ii * (b_i - sum_{j<i} a_ij * xnew_j - sum_{j>=i} a_ij * xold_j)
454         }
455       }
456     }
457 
458     template<class X, class Y, class K>
bsorbDune::algmeta_itsteps459     static void bsorb (const M& A, X& x, const Y& b, const K& w)
460     {
461       typedef typename M::ConstRowIterator rowiterator;
462       typedef typename M::ConstColIterator coliterator;
463       typedef typename Y::block_type bblock;
464       typedef typename X::block_type xblock;
465       bblock rhs;
466       xblock v;
467 
468       // Initialize nested data structure if there are entries
469       if(A.begin()!=A.end())
470         v=x[0];
471 
472       rowiterator endi=A.beforeBegin();
473       for (rowiterator i=A.beforeEnd(); i!=endi; --i)
474       {
475         rhs = b[i.index()];
476         coliterator endj=(*i).end();
477         coliterator j=(*i).begin();
478         if constexpr (IsNumber<typename M::block_type>())
479         {
480           for (; j.index()<i.index(); ++j)
481             rhs -= (*j) * x[j.index()];
482           coliterator diag=j;
483           for (; j!=endj; ++j)
484             rhs -= (*j) * x[j.index()];
485           v = rhs / (*diag);
486           x[i.index()] += w*v;
487         }
488         else
489         {
490           for (; j.index()<i.index(); ++j)
491             j->mmv(x[j.index()],rhs);
492           coliterator diag=j;
493           for (; j!=endj; ++j)
494             j->mmv(x[j.index()],rhs);
495           algmeta_itsteps<I-1,typename M::block_type>::bsorb(*diag,v,rhs,w);
496           x[i.index()].axpy(w,v);
497         }
498       }
499     }
500 
501     template<class X, class Y, class K>
dbjacDune::algmeta_itsteps502     static void dbjac (const M& A, X& x, const Y& b, const K& w)
503     {
504       typedef typename M::ConstRowIterator rowiterator;
505       typedef typename M::ConstColIterator coliterator;
506       typedef typename Y::block_type bblock;
507       bblock rhs;
508 
509       X v(x);     // allocate with same size
510 
511       rowiterator endi=A.end();
512       for (rowiterator i=A.begin(); i!=endi; ++i)
513       {
514         rhs = b[i.index()];
515         coliterator endj=(*i).end();
516         coliterator j=(*i).begin();
517         if constexpr (IsNumber<typename M::block_type>())
518         {
519           for (; j.index()<i.index(); ++j)
520             rhs -= (*j) * x[j.index()];
521           coliterator diag=j;
522           for (; j!=endj; ++j)
523             rhs -= (*j) * x[j.index()];
524           v[i.index()] = rhs / (*diag);
525         }
526         else
527         {
528           for (; j.index()<i.index(); ++j)
529             j->mmv(x[j.index()],rhs);
530           coliterator diag=j;
531           for (; j!=endj; ++j)
532             j->mmv(x[j.index()],rhs);
533           algmeta_itsteps<I-1,typename M::block_type>::dbjac(*diag,v[i.index()],rhs,w);
534         }
535       }
536       x.axpy(w,v);
537     }
538   };
539   // end of recursion
540   template<typename M>
541   struct algmeta_itsteps<0,M> {
542     template<class X, class Y, class K>
dbgsDune::algmeta_itsteps543     static void dbgs (const M& A, X& x, const Y& b, const K& /*w*/)
544     {
545       A.solve(x,b);
546     }
547     template<class X, class Y, class K>
bsorfDune::algmeta_itsteps548     static void bsorf (const M& A, X& x, const Y& b, const K& /*w*/)
549     {
550       A.solve(x,b);
551     }
552     template<class X, class Y, class K>
bsorbDune::algmeta_itsteps553     static void bsorb (const M& A, X& x, const Y& b, const K& /*w*/)
554     {
555       A.solve(x,b);
556     }
557     template<class X, class Y, class K>
dbjacDune::algmeta_itsteps558     static void dbjac (const M& A, X& x, const Y& b, const K& /*w*/)
559     {
560       A.solve(x,b);
561     }
562   };
563 
564   template<int I, typename T1, typename... MultiTypeMatrixArgs>
565   struct algmeta_itsteps<I,MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>> {
566     template<
567         typename... MultiTypeVectorArgs,
568         class K>
dbgsDune::algmeta_itsteps569     static void dbgs (const MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>& A,
570                       MultiTypeBlockVector<MultiTypeVectorArgs...>& x,
571                       const MultiTypeBlockVector<MultiTypeVectorArgs...>& b,
572                       const K& w)
573     {
574       static const int N = MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>::N();
575       Dune::MultiTypeBlockMatrix_Solver<I,0,N>::dbgs(A, x, b, w);
576     }
577 
578     template<
579       typename... MultiTypeVectorArgs,
580       class K>
bsorfDune::algmeta_itsteps581     static void bsorf (const MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>& A,
582                        MultiTypeBlockVector<MultiTypeVectorArgs...>& x,
583                        const MultiTypeBlockVector<MultiTypeVectorArgs...>& b,
584                        const K& w)
585     {
586       static const int N = MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>::N();
587       Dune::MultiTypeBlockMatrix_Solver<I,0,N>::bsorf(A, x, b, w);
588     }
589 
590     template<
591       typename... MultiTypeVectorArgs,
592       class K>
bsorbDune::algmeta_itsteps593     static void bsorb (const MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>& A,
594                        MultiTypeBlockVector<MultiTypeVectorArgs...>& x,
595                        const MultiTypeBlockVector<MultiTypeVectorArgs...>& b,
596                        const K& w)
597     {
598       static const int N = MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>::N();
599       Dune::MultiTypeBlockMatrix_Solver<I,N-1,N>::bsorb(A, x, b, w);
600     }
601 
602     template<
603       typename... MultiTypeVectorArgs,
604       class K
605       >
dbjacDune::algmeta_itsteps606     static void dbjac (const MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>& A,
607                        MultiTypeBlockVector<MultiTypeVectorArgs...>& x,
608                        const MultiTypeBlockVector<MultiTypeVectorArgs...>& b,
609                        const K& w)
610     {
611       static const int N = MultiTypeBlockMatrix<T1, MultiTypeMatrixArgs...>::N();
612       Dune::MultiTypeBlockMatrix_Solver<I,0,N>::dbjac(A, x, b, w);
613     }
614   };
615 
616   // user calls
617 
618   //! GS step
619   template<class M, class X, class Y, class K>
dbgs(const M & A,X & x,const Y & b,const K & w)620   void dbgs (const M& A, X& x, const Y& b, const K& w)
621   {
622     algmeta_itsteps<1,M>::dbgs(A,x,b,w);
623   }
624   //! GS step
625   template<class M, class X, class Y, class K, int l>
dbgs(const M & A,X & x,const Y & b,const K & w,BL<l>)626   void dbgs (const M& A, X& x, const Y& b, const K& w, BL<l> /*bl*/)
627   {
628     algmeta_itsteps<l,M>::dbgs(A,x,b,w);
629   }
630   //! SOR step
631   template<class M, class X, class Y, class K>
bsorf(const M & A,X & x,const Y & b,const K & w)632   void bsorf (const M& A, X& x, const Y& b, const K& w)
633   {
634     algmeta_itsteps<1,M>::bsorf(A,x,b,w);
635   }
636   //! SOR step
637   template<class M, class X, class Y, class K, int l>
bsorf(const M & A,X & x,const Y & b,const K & w,BL<l>)638   void bsorf (const M& A, X& x, const Y& b, const K& w, BL<l> /*bl*/)
639   {
640     algmeta_itsteps<l,M>::bsorf(A,x,b,w);
641   }
642   //! SSOR step
643   template<class M, class X, class Y, class K>
bsorb(const M & A,X & x,const Y & b,const K & w)644   void bsorb (const M& A, X& x, const Y& b, const K& w)
645   {
646     algmeta_itsteps<1,M>::bsorb(A,x,b,w);
647   }
648   //! Backward SOR step
649   template<class M, class X, class Y, class K, int l>
bsorb(const M & A,X & x,const Y & b,const K & w,BL<l>)650   void bsorb (const M& A, X& x, const Y& b, const K& w, BL<l> /*bl*/)
651   {
652     algmeta_itsteps<l,typename std::remove_cv<M>::type>::bsorb(A,x,b,w);
653   }
654   //! Jacobi step
655   template<class M, class X, class Y, class K>
dbjac(const M & A,X & x,const Y & b,const K & w)656   void dbjac (const M& A, X& x, const Y& b, const K& w)
657   {
658     algmeta_itsteps<1,M>::dbjac(A,x,b,w);
659   }
660   //! Jacobi step
661   template<class M, class X, class Y, class K, int l>
dbjac(const M & A,X & x,const Y & b,const K & w,BL<l>)662   void dbjac (const M& A, X& x, const Y& b, const K& w, BL<l> /*bl*/)
663   {
664     algmeta_itsteps<l,M>::dbjac(A,x,b,w);
665   }
666 
667 
668   /** @} end documentation */
669 
670 } // end namespace
671 
672 #endif
673