Dune Core Modules (2.7.1)

multitypeblockmatrix.hh
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_MULTITYPEBLOCKMATRIX_HH
4 #define DUNE_ISTL_MULTITYPEBLOCKMATRIX_HH
5 
6 #include <cmath>
7 #include <iostream>
8 #include <tuple>
9 
10 #include <dune/common/hybridutilities.hh>
11 
12 #include "istlexception.hh"
13 
14 // forward declaration
15 namespace Dune
16 {
17  template<typename FirstRow, typename... Args>
18  class MultiTypeBlockMatrix;
19 
20  template<int I, int crow, int remain_row>
21  class MultiTypeBlockMatrix_Solver;
22 }
23 
24 #include "gsetc.hh"
25 
26 namespace Dune {
27 
41  template<typename FirstRow, typename... Args>
43  : public std::tuple<FirstRow, Args...>
44  {
45  public:
46 
50  typedef MultiTypeBlockMatrix<FirstRow, Args...> type;
51 
53  using size_type = std::size_t;
54 
55  typedef typename FirstRow::field_type field_type;
56 
58  static constexpr size_type N()
59  {
60  return 1+sizeof...(Args);
61  }
62 
64  static constexpr size_type size() DUNE_DEPRECATED_MSG("Use method 'N' instead")
65  {
66  return 1+sizeof...(Args);
67  }
68 
70  static constexpr size_type M()
71  {
72  return FirstRow::size();
73  }
74 
91  template< size_type index >
92  auto
93  operator[] ( const std::integral_constant< size_type, index > indexVariable ) -> decltype(std::get<index>(*this))
94  {
95  DUNE_UNUSED_PARAMETER(indexVariable);
96  return std::get<index>(*this);
97  }
98 
104  template< size_type index >
105  auto
106  operator[] ( const std::integral_constant< size_type, index > indexVariable ) const -> decltype(std::get<index>(*this))
107  {
108  DUNE_UNUSED_PARAMETER(indexVariable);
109  return std::get<index>(*this);
110  }
111 
115  template<typename T>
116  void operator= (const T& newval) {
117  using namespace Dune::Hybrid;
118  auto size = index_constant<1+sizeof...(Args)>();
119  // Since Dune::Hybrid::size(MultiTypeBlockMatrix) is not implemented,
120  // we cannot use a plain forEach(*this, ...). This could be achieved,
121  // e.g., by implementing a static size() method.
122  forEach(integralRange(size), [&](auto&& i) {
123  (*this)[i] = newval;
124  });
125  }
126 
127  //===== vector space arithmetic
128 
130  MultiTypeBlockMatrix& operator*= (const field_type& k)
131  {
132  auto size = index_constant<N()>();
133  Hybrid::forEach(Hybrid::integralRange(size), [&](auto&& i) {
134  (*this)[i] *= k;
135  });
136 
137  return *this;
138  }
139 
141  MultiTypeBlockMatrix& operator/= (const field_type& k)
142  {
143  auto size = index_constant<N()>();
144  Hybrid::forEach(Hybrid::integralRange(size), [&](auto&& i) {
145  (*this)[i] /= k;
146  });
147 
148  return *this;
149  }
150 
151 
158  {
159  auto size = index_constant<N()>();
160  Hybrid::forEach(Hybrid::integralRange(size), [&](auto&& i) {
161  (*this)[i] += b[i];
162  });
163 
164  return *this;
165  }
166 
173  {
174  auto size = index_constant<N()>();
175  Hybrid::forEach(Hybrid::integralRange(size), [&](auto&& i) {
176  (*this)[i] -= b[i];
177  });
178 
179  return *this;
180  }
181 
184  template<typename X, typename Y>
185  void mv (const X& x, Y& y) const {
186  static_assert(X::size() == M(), "length of x does not match row length");
187  static_assert(Y::size() == N(), "length of y does not match row count");
188  y = 0; //reset y (for mv uses umv)
189  umv(x,y);
190  }
191 
194  template<typename X, typename Y>
195  void umv (const X& x, Y& y) const {
196  static_assert(X::size() == M(), "length of x does not match row length");
197  static_assert(Y::size() == N(), "length of y does not match row count");
198  using namespace Dune::Hybrid;
199  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
200  using namespace Dune::Hybrid; // needed for icc, see issue #31
201  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
202  (*this)[i][j].umv(x[j], y[i]);
203  });
204  });
205  }
206 
209  template<typename X, typename Y>
210  void mmv (const X& x, Y& y) const {
211  static_assert(X::size() == M(), "length of x does not match row length");
212  static_assert(Y::size() == N(), "length of y does not match row count");
213  using namespace Dune::Hybrid;
214  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
215  using namespace Dune::Hybrid; // needed for icc, see issue #31
216  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
217  (*this)[i][j].mmv(x[j], y[i]);
218  });
219  });
220  }
221 
224  template<typename AlphaType, typename X, typename Y>
225  void usmv (const AlphaType& alpha, const X& x, Y& y) const {
226  static_assert(X::size() == M(), "length of x does not match row length");
227  static_assert(Y::size() == N(), "length of y does not match row count");
228  using namespace Dune::Hybrid;
229  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
230  using namespace Dune::Hybrid; // needed for icc, see issue #31
231  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
232  (*this)[i][j].usmv(alpha, x[j], y[i]);
233  });
234  });
235  }
236 
239  template<typename X, typename Y>
240  void mtv (const X& x, Y& y) const {
241  static_assert(X::size() == N(), "length of x does not match number of rows");
242  static_assert(Y::size() == M(), "length of y does not match number of columns");
243  y = 0;
244  umtv(x,y);
245  }
246 
249  template<typename X, typename Y>
250  void umtv (const X& x, Y& y) const {
251  static_assert(X::size() == N(), "length of x does not match number of rows");
252  static_assert(Y::size() == M(), "length of y does not match number of columns");
253  using namespace Dune::Hybrid;
254  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
255  using namespace Dune::Hybrid; // needed for icc, see issue #31
256  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
257  (*this)[j][i].umtv(x[j], y[i]);
258  });
259  });
260  }
261 
264  template<typename X, typename Y>
265  void mmtv (const X& x, Y& y) const {
266  static_assert(X::size() == N(), "length of x does not match number of rows");
267  static_assert(Y::size() == M(), "length of y does not match number of columns");
268  using namespace Dune::Hybrid;
269  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
270  using namespace Dune::Hybrid; // needed for icc, see issue #31
271  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
272  (*this)[j][i].mmtv(x[j], y[i]);
273  });
274  });
275  }
276 
279  template<typename X, typename Y>
280  void usmtv (const field_type& alpha, const X& x, Y& y) const {
281  static_assert(X::size() == N(), "length of x does not match number of rows");
282  static_assert(Y::size() == M(), "length of y does not match number of columns");
283  using namespace Dune::Hybrid;
284  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
285  using namespace Dune::Hybrid; // needed for icc, see issue #31
286  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
287  (*this)[j][i].usmtv(alpha, x[j], y[i]);
288  });
289  });
290  }
291 
294  template<typename X, typename Y>
295  void umhv (const X& x, Y& y) const {
296  static_assert(X::size() == N(), "length of x does not match number of rows");
297  static_assert(Y::size() == M(), "length of y does not match number of columns");
298  using namespace Dune::Hybrid;
299  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
300  using namespace Dune::Hybrid; // needed for icc, see issue #31
301  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
302  (*this)[j][i].umhv(x[j], y[i]);
303  });
304  });
305  }
306 
309  template<typename X, typename Y>
310  void mmhv (const X& x, Y& y) const {
311  static_assert(X::size() == N(), "length of x does not match number of rows");
312  static_assert(Y::size() == M(), "length of y does not match number of columns");
313  using namespace Dune::Hybrid;
314  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
315  using namespace Dune::Hybrid; // needed for icc, see issue #31
316  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
317  (*this)[j][i].mmhv(x[j], y[i]);
318  });
319  });
320  }
321 
324  template<typename X, typename Y>
325  void usmhv (const field_type& alpha, const X& x, Y& y) const {
326  static_assert(X::size() == N(), "length of x does not match number of rows");
327  static_assert(Y::size() == M(), "length of y does not match number of columns");
328  using namespace Dune::Hybrid;
329  forEach(integralRange(Hybrid::size(y)), [&](auto&& i) {
330  using namespace Dune::Hybrid; // needed for icc, see issue #31
331  forEach(integralRange(Hybrid::size(x)), [&](auto&& j) {
332  (*this)[j][i].usmhv(alpha, x[j], y[i]);
333  });
334  });
335  }
336 
337 
338  //===== norms
339 
341  auto frobenius_norm2 () const
342  {
343  using field_type = typename std::decay_t<decltype((*this)[Indices::_0][Indices::_0])>::field_type;
344  typename FieldTraits<field_type>::real_type sum=0;
345 
346  auto rows = index_constant<N()>();
347  Hybrid::forEach(Hybrid::integralRange(rows), [&](auto&& i) {
349  Hybrid::forEach(Hybrid::integralRange(cols), [&](auto&& j) {
350  sum += (*this)[i][j].frobenius_norm2();
351  });
352  });
353 
354  return sum;
355  }
356 
358  typename FieldTraits<field_type>::real_type frobenius_norm () const
359  {
360  return sqrt(frobenius_norm2());
361  }
362 
364  auto infinity_norm () const
365  {
366  using field_type = typename std::decay_t<decltype((*this)[Indices::_0][Indices::_0])>::field_type;
367  using std::max;
368  typename FieldTraits<field_type>::real_type norm=0;
369 
370  auto rows = index_constant<N()>();
371  Hybrid::forEach(Hybrid::integralRange(rows), [&](auto&& i) {
372 
373  typename FieldTraits<field_type>::real_type sum=0;
375  Hybrid::forEach(Hybrid::integralRange(cols), [&](auto&& j) {
376  sum += (*this)[i][j].infinity_norm();
377  });
378  norm = max(sum, norm);
379  });
380 
381  return norm;
382  }
383 
385  auto infinity_norm_real () const
386  {
387  using field_type = typename std::decay_t<decltype((*this)[Indices::_0][Indices::_0])>::field_type;
388  using std::max;
389  typename FieldTraits<field_type>::real_type norm=0;
390 
391  auto rows = index_constant<N()>();
392  Hybrid::forEach(Hybrid::integralRange(rows), [&](auto&& i) {
393 
394  typename FieldTraits<field_type>::real_type sum=0;
396  Hybrid::forEach(Hybrid::integralRange(cols), [&](auto&& j) {
397  sum += (*this)[i][j].infinity_norm_real();
398  });
399  norm = max(sum, norm);
400  });
401 
402  return norm;
403  }
404 
405  };
406 
412  template<typename T1, typename... Args>
413  std::ostream& operator<< (std::ostream& s, const MultiTypeBlockMatrix<T1,Args...>& m) {
416  using namespace Dune::Hybrid;
417  forEach(integralRange(N), [&](auto&& i) {
418  using namespace Dune::Hybrid; // needed for icc, see issue #31
419  forEach(integralRange(M), [&](auto&& j) {
420  s << "\t(" << i << ", " << j << "): \n" << m[i][j];
421  });
422  });
423  s << std::endl;
424  return s;
425  }
426 
427  //make algmeta_itsteps known
428  template<int I, typename M>
429  struct algmeta_itsteps;
430 
437  template<int I, int crow, int ccol, int remain_col> //MultiTypeBlockMatrix_Solver_Col: iterating over one row
438  class MultiTypeBlockMatrix_Solver_Col { //calculating b- A[i][j]*x[j]
439  public:
443  template <typename Trhs, typename TVector, typename TMatrix, typename K>
444  static void calc_rhs(const TMatrix& A, TVector& x, TVector& v, Trhs& b, const K& w) {
445  std::get<ccol>( std::get<crow>(A) ).mmv( std::get<ccol>(x), b );
447  }
448 
449  };
450  template<int I, int crow, int ccol> //MultiTypeBlockMatrix_Solver_Col recursion end
451  class MultiTypeBlockMatrix_Solver_Col<I,crow,ccol,0> {
452  public:
453  template <typename Trhs, typename TVector, typename TMatrix, typename K>
454  static void calc_rhs(const TMatrix&, TVector&, TVector&, Trhs&, const K&) {}
455  };
456 
457 
458 
465  template<int I, int crow, int remain_row>
467  public:
468 
472  template <typename TVector, typename TMatrix, typename K>
473  static void dbgs(const TMatrix& A, TVector& x, const TVector& b, const K& w) {
474  TVector xold(x);
475  xold=x; //store old x values
477  x *= w;
478  x.axpy(1-w,xold); //improve x
479  }
480  template <typename TVector, typename TMatrix, typename K>
481  static void dbgs(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) {
482  auto rhs = std::get<crow> (b);
483 
484  MultiTypeBlockMatrix_Solver_Col<I,crow,0, TMatrix::M()>::calc_rhs(A,x,v,rhs,w); // calculate right side of equation
485  //solve on blocklevel I-1
486  using M =
487  typename std::remove_cv<
488  typename std::remove_reference<
489  decltype(std::get<crow>( std::get<crow>(A)))
490  >::type
491  >::type;
492  algmeta_itsteps<I-1,M>::dbgs(std::get<crow>( std::get<crow>(A)), std::get<crow>(x),rhs,w);
494  }
495 
496 
497 
501  template <typename TVector, typename TMatrix, typename K>
502  static void bsorf(const TMatrix& A, TVector& x, const TVector& b, const K& w) {
503  TVector v;
504  v=x; //use latest x values in right side calculation
506 
507  }
508  template <typename TVector, typename TMatrix, typename K> //recursion over all matrix rows (A)
509  static void bsorf(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) {
510  auto rhs = std::get<crow> (b);
511 
512  MultiTypeBlockMatrix_Solver_Col<I,crow,0,TMatrix::M()>::calc_rhs(A,x,v,rhs,w); // calculate right side of equation
513  //solve on blocklevel I-1
514  using M =
515  typename std::remove_cv<
516  typename std::remove_reference<
517  decltype(std::get<crow>( std::get<crow>(A)))
518  >::type
519  >::type;
520  algmeta_itsteps<I-1,M>::bsorf(std::get<crow>( std::get<crow>(A)), std::get<crow>(v),rhs,w);
521  std::get<crow>(x).axpy(w,std::get<crow>(v));
523  }
524 
528  template <typename TVector, typename TMatrix, typename K>
529  static void bsorb(const TMatrix& A, TVector& x, const TVector& b, const K& w) {
530  TVector v;
531  v=x; //use latest x values in right side calculation
533 
534  }
535  template <typename TVector, typename TMatrix, typename K> //recursion over all matrix rows (A)
536  static void bsorb(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) {
537  auto rhs = std::get<crow> (b);
538 
539  MultiTypeBlockMatrix_Solver_Col<I,crow,0, TMatrix::M()>::calc_rhs(A,x,v,rhs,w); // calculate right side of equation
540  //solve on blocklevel I-1
541  using M =
542  typename std::remove_cv<
543  typename std::remove_reference<
544  decltype(std::get<crow>( std::get<crow>(A)))
545  >::type
546  >::type;
547  algmeta_itsteps<I-1,M>::bsorb(std::get<crow>( std::get<crow>(A)), std::get<crow>(v),rhs,w);
548  std::get<crow>(x).axpy(w,std::get<crow>(v));
550  }
551 
552 
556  template <typename TVector, typename TMatrix, typename K>
557  static void dbjac(const TMatrix& A, TVector& x, const TVector& b, const K& w) {
558  TVector v(x);
559  v=0; //calc new x in v
561  x.axpy(w,v); //improve x
562  }
563  template <typename TVector, typename TMatrix, typename K>
564  static void dbjac(const TMatrix& A, TVector& x, TVector& v, const TVector& b, const K& w) {
565  auto rhs = std::get<crow> (b);
566 
567  MultiTypeBlockMatrix_Solver_Col<I,crow,0, TMatrix::M()>::calc_rhs(A,x,v,rhs,w); // calculate right side of equation
568  //solve on blocklevel I-1
569  using M =
570  typename std::remove_cv<
571  typename std::remove_reference<
572  decltype(std::get<crow>( std::get<crow>(A)))
573  >::type
574  >::type;
575  algmeta_itsteps<I-1,M>::dbjac(std::get<crow>( std::get<crow>(A)), std::get<crow>(v),rhs,w);
577  }
578 
579 
580 
581 
582  };
583  template<int I, int crow> //recursion end for remain_row = 0
584  class MultiTypeBlockMatrix_Solver<I,crow,0> {
585  public:
586  template <typename TVector, typename TMatrix, typename K>
587  static void dbgs(const TMatrix&, TVector&, TVector&,
588  const TVector&, const K&) {}
589 
590  template <typename TVector, typename TMatrix, typename K>
591  static void bsorf(const TMatrix&, TVector&, TVector&,
592  const TVector&, const K&) {}
593 
594  template <typename TVector, typename TMatrix, typename K>
595  static void bsorb(const TMatrix&, TVector&, TVector&,
596  const TVector&, const K&) {}
597 
598  template <typename TVector, typename TMatrix, typename K>
599  static void dbjac(const TMatrix&, TVector&, TVector&,
600  const TVector&, const K&) {}
601  };
602 
603 } // end namespace
604 
605 #endif
part of solvers for MultiTypeBlockVector & MultiTypeBlockMatrix types
Definition: multitypeblockmatrix.hh:438
solver for MultiTypeBlockVector & MultiTypeBlockMatrix types
Definition: multitypeblockmatrix.hh:466
A Matrix class to support different block types.
Definition: multitypeblockmatrix.hh:44
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:51
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:28
#define DUNE_DEPRECATED_MSG(text)
Mark some entity as deprecated.
Definition: deprecated.hh:169
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:267
constexpr auto integralRange(const Begin &begin, const End &end)
Create an integral range.
Definition: hybridutilities.hh:183
void bsorb(const M &A, X &x, const Y &b, const K &w)
SSOR step.
Definition: gsetc.hh:640
void dbjac(const M &A, X &x, const Y &b, const K &w)
Jacobi step.
Definition: gsetc.hh:652
void dbgs(const M &A, X &x, const Y &b, const K &w)
GS step.
Definition: gsetc.hh:616
void bsorf(const M &A, X &x, const Y &b, const K &w)
SOR step.
Definition: gsetc.hh:628
MultiTypeBlockMatrix< FirstRow, Args... > type
Definition: multitypeblockmatrix.hh:50
static void dbjac(const TMatrix &A, TVector &x, const TVector &b, const K &w)
Definition: multitypeblockmatrix.hh:557
void mv(const X &x, Y &y) const
y = A x
Definition: multitypeblockmatrix.hh:185
void mmtv(const X &x, Y &y) const
y -= A^T x
Definition: multitypeblockmatrix.hh:265
void mmhv(const X &x, Y &y) const
y -= A^H x
Definition: multitypeblockmatrix.hh:310
static void dbgs(const TMatrix &A, TVector &x, const TVector &b, const K &w)
Definition: multitypeblockmatrix.hh:473
static void bsorb(const TMatrix &A, TVector &x, const TVector &b, const K &w)
Definition: multitypeblockmatrix.hh:529
MultiTypeBlockMatrix & operator/=(const field_type &k)
vector space division by scalar
Definition: multitypeblockmatrix.hh:141
void usmhv(const field_type &alpha, const X &x, Y &y) const
y += alpha A^H x
Definition: multitypeblockmatrix.hh:325
void usmv(const AlphaType &alpha, const X &x, Y &y) const
y += alpha A x
Definition: multitypeblockmatrix.hh:225
void umhv(const X &x, Y &y) const
y += A^H x
Definition: multitypeblockmatrix.hh:295
static constexpr size_type N()
Return the number of matrix rows.
Definition: multitypeblockmatrix.hh:58
void usmtv(const field_type &alpha, const X &x, Y &y) const
y += alpha A^T x
Definition: multitypeblockmatrix.hh:280
void operator=(const T &newval)
Definition: multitypeblockmatrix.hh:116
void umv(const X &x, Y &y) const
y += A x
Definition: multitypeblockmatrix.hh:195
static void calc_rhs(const TMatrix &A, TVector &x, TVector &v, Trhs &b, const K &w)
Definition: multitypeblockmatrix.hh:444
static void bsorf(const TMatrix &A, TVector &x, const TVector &b, const K &w)
Definition: multitypeblockmatrix.hh:502
static constexpr size_type size()
Return the number of matrix rows.
Definition: multitypeblockmatrix.hh:64
auto infinity_norm_real() const
Bastardized version of the infinity-norm / row-sum norm.
Definition: multitypeblockmatrix.hh:385
auto frobenius_norm2() const
square of frobenius norm, need for block recursion
Definition: multitypeblockmatrix.hh:341
std::size_t size_type
Type used for sizes.
Definition: multitypeblockmatrix.hh:53
auto infinity_norm() const
Bastardized version of the infinity-norm / row-sum norm.
Definition: multitypeblockmatrix.hh:364
FieldTraits< field_type >::real_type frobenius_norm() const
frobenius norm: sqrt(sum over squared values of entries)
Definition: multitypeblockmatrix.hh:358
MultiTypeBlockMatrix & operator+=(const MultiTypeBlockMatrix &b)
Add the entries of another matrix to this one.
Definition: multitypeblockmatrix.hh:157
auto operator[](const std::integral_constant< size_type, index > indexVariable) -> decltype(std::get< index >(*this))
Random-access operator.
Definition: multitypeblockmatrix.hh:93
void mtv(const X &x, Y &y) const
y = A^T x
Definition: multitypeblockmatrix.hh:240
static constexpr size_type M()
Return the number of matrix columns.
Definition: multitypeblockmatrix.hh:70
void mmv(const X &x, Y &y) const
y -= A x
Definition: multitypeblockmatrix.hh:210
void umtv(const X &x, Y &y) const
y += A^T x
Definition: multitypeblockmatrix.hh:250
MultiTypeBlockMatrix & operator*=(const field_type &k)
vector space multiplication with scalar
Definition: multitypeblockmatrix.hh:130
MultiTypeBlockMatrix & operator-=(const MultiTypeBlockMatrix &b)
Subtract the entries of another matrix from this one.
Definition: multitypeblockmatrix.hh:172
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
Simple iterative methods like Jacobi, Gauss-Seidel, SOR, SSOR, etc. in a generic way.
Dune namespace.
Definition: alignedallocator.hh:14
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 9, 22:29, 2024)