Dune Core Modules (2.7.0)

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
15namespace 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
26namespace 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()>();
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()>();
145 (*this)[i] /= k;
146 });
147
148 return *this;
149 }
150
151
158 {
159 auto size = index_constant<N()>();
161 (*this)[i] += b[i];
162 });
163
164 return *this;
165 }
166
173 {
174 auto size = index_constant<N()>();
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
MultiTypeBlockMatrix & operator+=(const MultiTypeBlockMatrix &b)
Add the entries of another matrix to this one.
Definition: multitypeblockmatrix.hh:157
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
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
MultiTypeBlockMatrix & operator/=(const field_type &k)
vector space division by scalar
Definition: multitypeblockmatrix.hh:141
void umhv(const X &x, Y &y) const
y += A^H x
Definition: multitypeblockmatrix.hh:295
FieldTraits< field_type >::real_type frobenius_norm() const
frobenius norm: sqrt(sum over squared values of entries)
Definition: multitypeblockmatrix.hh:358
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
MultiTypeBlockMatrix & operator-=(const MultiTypeBlockMatrix &b)
Subtract the entries of another matrix from this one.
Definition: multitypeblockmatrix.hh:172
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
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.111.3 (Jul 15, 22:36, 2024)