Dune Core Modules (unstable)

matrixmatrix.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 #ifndef DUNE_ISTL_MATRIXMATRIX_HH
6 #define DUNE_ISTL_MATRIXMATRIX_HH
7 
8 #include <tuple>
9 
10 #include <dune/istl/bcrsmatrix.hh>
11 #include <dune/common/fmatrix.hh>
12 #include <dune/common/timer.hh>
13 namespace Dune
14 {
15 
26  namespace
27  {
28 
37  template<int b>
38  struct NonzeroPatternTraverser
39  {};
40 
41 
42  template<>
43  struct NonzeroPatternTraverser<0>
44  {
45  template<class T,class A1, class A2, class F, int n, int m, int k>
46  static void traverse(const Dune::BCRSMatrix<Dune::FieldMatrix<T,n,k>,A1>& A,
48  F& func)
49  {
50  if(A.M()!=B.N())
51  DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<<A.M()<<"!="<<B.N());
52 
53  typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,n,k>,A1>::ConstRowIterator Row;
54  typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,n,k>,A1>::ConstColIterator Col;
55  typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,m>,A2>::ConstColIterator BCol;
56  for(Row row= A.begin(); row != A.end(); ++row) {
57  // Loop over all column entries
58  for(Col col = row->begin(); col != row->end(); ++col) {
59  // entry at i,k
60  // search for all nonzeros in row k
61  for(BCol bcol = B[col.index()].begin(); bcol != B[col.index()].end(); ++bcol) {
62  func(*col, *bcol, row.index(), bcol.index());
63  }
64  }
65  }
66  }
67 
68  };
69 
70  template<>
71  struct NonzeroPatternTraverser<1>
72  {
73  template<class T, class A1, class A2, class F, int n, int m, int k>
74  static void traverse(const Dune::BCRSMatrix<Dune::FieldMatrix<T,k,n>,A1>& A,
76  F& func)
77  {
78 
79  if(A.N()!=B.N())
80  DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<<A.N()<<"!="<<B.N());
81 
82  typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,n>,A1>::ConstRowIterator Row;
83  typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,n>,A1>::ConstColIterator Col;
84  typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,m>,A2>::ConstColIterator BCol;
85 
86  for(Row row=A.begin(); row!=A.end(); ++row) {
87  for(Col col=row->begin(); col!=row->end(); ++col) {
88  for(BCol bcol = B[row.index()].begin(); bcol != B[row.index()].end(); ++bcol) {
89  func(*col, *bcol, col.index(), bcol.index());
90  }
91  }
92  }
93  }
94  };
95 
96  template<>
97  struct NonzeroPatternTraverser<2>
98  {
99  template<class T, class A1, class A2, class F, int n, int m, int k>
100  static void traverse(const BCRSMatrix<FieldMatrix<T,n,m>,A1>& mat,
101  const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt,
102  F& func)
103  {
104  if(mat.M()!=matt.M())
105  DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<<mat.M()<<"!="<<matt.M());
106 
107  typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A1>::ConstRowIterator row_iterator;
108  typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A1>::ConstColIterator col_iterator;
109  typedef typename BCRSMatrix<FieldMatrix<T,k,m>,A2>::ConstRowIterator row_iterator_t;
110  typedef typename BCRSMatrix<FieldMatrix<T,k,m>,A2>::ConstColIterator col_iterator_t;
111 
112  for(row_iterator mrow=mat.begin(); mrow != mat.end(); ++mrow) {
113  //iterate over the column entries
114  // mt is a transposed matrix crs therefore it is treated as a ccs matrix
115  // and the row_iterator iterates over the columns of the transposed matrix.
116  // search the row of the transposed matrix for an entry with the same index
117  // as the mcol iterator
118 
119  for(row_iterator_t mtcol=matt.begin(); mtcol != matt.end(); ++mtcol) {
120  //Search for col entries in mat that have a corresponding row index in matt
121  // (i.e. corresponding col index in the as this is the transposed matrix
122  col_iterator_t mtrow=mtcol->begin();
123  bool funcCalled = false;
124  for(col_iterator mcol=mrow->begin(); mcol != mrow->end(); ++mcol) {
125  // search
126  // TODO: This should probably be substituted by a binary search
127  for( ; mtrow != mtcol->end(); ++mtrow)
128  if(mtrow.index()>=mcol.index())
129  break;
130  if(mtrow != mtcol->end() && mtrow.index()==mcol.index()) {
131  func(*mcol, *mtrow, mtcol.index());
132  funcCalled = true;
133  // In some cases we only search for one pair, then we break here
134  // and continue with the next column.
135  if(F::do_break)
136  break;
137  }
138  }
139  // move on with func only if func was called, otherwise they might
140  // get out of sync
141  if (funcCalled)
142  func.nextCol();
143  }
144  func.nextRow();
145  }
146  }
147  };
148 
149 
150 
151  template<class T, class A, int n, int m>
152  class SparsityPatternInitializer
153  {
154  public:
155  enum {do_break=true};
156  typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A>::CreateIterator CreateIterator;
157  typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A>::size_type size_type;
158 
159  SparsityPatternInitializer(CreateIterator iter)
160  : rowiter(iter)
161  {}
162 
163  template<class T1, class T2>
164  void operator()(const T1&, const T2&, size_type j)
165  {
166  rowiter.insert(j);
167  }
168 
169  void nextRow()
170  {
171  ++rowiter;
172  }
173  void nextCol()
174  {}
175 
176  private:
177  CreateIterator rowiter;
178  };
179 
180 
181  template<int transpose, class T, class TA, int n, int m>
182  class MatrixInitializer
183  {
184  public:
185  enum {do_break=true};
186  typedef typename Dune::BCRSMatrix<FieldMatrix<T,n,m>,TA> Matrix;
187  typedef typename Matrix::CreateIterator CreateIterator;
188  typedef typename Matrix::size_type size_type;
189 
190  MatrixInitializer(Matrix& A_, size_type)
191  : count(0), A(A_)
192  {}
193  template<class T1, class T2>
194  void operator()(const T1&, const T2&, int)
195  {
196  ++count;
197  }
198 
199  void nextCol()
200  {}
201 
202  void nextRow()
203  {}
204 
205  std::size_t nonzeros()
206  {
207  return count;
208  }
209 
210  template<class A1, class A2, int n2, int m2, int n3, int m3>
211  void initPattern(const BCRSMatrix<FieldMatrix<T,n2,m2>,A1>& mat1,
212  const BCRSMatrix<FieldMatrix<T,n3,m3>,A2>& mat2)
213  {
214  SparsityPatternInitializer<T, TA, n, m> sparsity(A.createbegin());
215  NonzeroPatternTraverser<transpose>::traverse(mat1,mat2,sparsity);
216  }
217 
218  private:
219  std::size_t count;
220  Matrix& A;
221  };
222 
223  template<class T, class TA, int n, int m>
224  class MatrixInitializer<1,T,TA,n,m>
225  {
226  public:
227  enum {do_break=false};
229  typedef typename Matrix::CreateIterator CreateIterator;
230  typedef typename Matrix::size_type size_type;
231 
232  MatrixInitializer(Matrix& A_, size_type rows)
233  : A(A_), entries(rows)
234  {}
235 
236  template<class T1, class T2>
237  void operator()(const T1&, const T2&, size_type i, size_type j)
238  {
239  entries[i].insert(j);
240  }
241 
242  void nextCol()
243  {}
244 
245  size_type nonzeros()
246  {
247  size_type nnz=0;
248  typedef typename std::vector<std::set<size_t> >::const_iterator Iter;
249  for(Iter iter = entries.begin(); iter != entries.end(); ++iter)
250  nnz+=(*iter).size();
251  return nnz;
252  }
253  template<class A1, class A2, int n2, int m2, int n3, int m3>
254  void initPattern(const BCRSMatrix<FieldMatrix<T,n2,m2>,A1>&,
255  const BCRSMatrix<FieldMatrix<T,n3,m3>,A2>&)
256  {
257  typedef typename std::vector<std::set<size_t> >::const_iterator Iter;
258  CreateIterator citer = A.createbegin();
259  for(Iter iter = entries.begin(); iter != entries.end(); ++iter, ++citer) {
260  typedef std::set<size_t>::const_iterator SetIter;
261  for(SetIter index=iter->begin(); index != iter->end(); ++index)
262  citer.insert(*index);
263  }
264  }
265 
266  private:
267  Matrix& A;
268  std::vector<std::set<size_t> > entries;
269  };
270 
271  template<class T, class TA, int n, int m>
272  struct MatrixInitializer<0,T,TA,n,m>
273  : public MatrixInitializer<1,T,TA,n,m>
274  {
275  MatrixInitializer(Dune::BCRSMatrix<Dune::FieldMatrix<T,n,m>,TA>& A_,
276  typename Dune::BCRSMatrix<Dune::FieldMatrix<T,n,m>,TA>::size_type rows)
277  : MatrixInitializer<1,T,TA,n,m>(A_,rows)
278  {}
279  };
280 
281 
282  template<class T, class T1, class T2, int n, int m, int k>
283  void addMatMultTransposeMat(FieldMatrix<T,n,k>& res, const FieldMatrix<T1,n,m>& mat,
284  const FieldMatrix<T2,k,m>& matt)
285  {
286  typedef typename FieldMatrix<T,n,k>::size_type size_type;
287 
288  for(size_type row=0; row<n; ++row)
289  for(size_type col=0; col<k; ++col) {
290  for(size_type i=0; i < m; ++i)
291  res[row][col]+=mat[row][i]*matt[col][i];
292  }
293  }
294 
295  template<class T, class T1, class T2, int n, int m, int k>
296  void addTransposeMatMultMat(FieldMatrix<T,n,k>& res, const FieldMatrix<T1,m,n>& mat,
297  const FieldMatrix<T2,m,k>& matt)
298  {
299  typedef typename FieldMatrix<T,n,k>::size_type size_type;
300  for(size_type i=0; i<m; ++i)
301  for(size_type row=0; row<n; ++row) {
302  for(size_type col=0; col < k; ++col)
303  res[row][col]+=mat[i][row]*matt[i][col];
304  }
305  }
306 
307  template<class T, class T1, class T2, int n, int m, int k>
308  void addMatMultMat(FieldMatrix<T,n,m>& res, const FieldMatrix<T1,n,k>& mat,
309  const FieldMatrix<T2,k,m>& matt)
310  {
311  typedef typename FieldMatrix<T,n,k>::size_type size_type;
312  for(size_type row=0; row<n; ++row)
313  for(size_type col=0; col<m; ++col) {
314  for(size_type i=0; i < k; ++i)
315  res[row][col]+=mat[row][i]*matt[i][col];
316  }
317  }
318 
319 
320  template<class T, class A, int n, int m>
321  class EntryAccumulatorFather
322  {
323  public:
324  enum {do_break=false};
325  typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
326  typedef typename Matrix::RowIterator Row;
327  typedef typename Matrix::ColIterator Col;
328 
329  EntryAccumulatorFather(Matrix& mat_)
330  : mat(mat_), row(mat.begin())
331  {
332  mat=0;
333  col=row->begin();
334  }
335  void nextRow()
336  {
337  ++row;
338  if(row!=mat.end())
339  col=row->begin();
340  }
341 
342  void nextCol()
343  {
344  ++this->col;
345  }
346  protected:
347  Matrix& mat;
348  private:
349  Row row;
350  protected:
351  Col col;
352  };
353 
354  template<class T, class A, int n, int m, int transpose>
355  class EntryAccumulator
356  : public EntryAccumulatorFather<T,A,n,m>
357  {
358  public:
359  typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
360  typedef typename Matrix::size_type size_type;
361 
362  EntryAccumulator(Matrix& mat_)
363  : EntryAccumulatorFather<T,A,n,m>(mat_)
364  {}
365 
366  template<class T1, class T2>
367  void operator()(const T1& t1, const T2& t2, size_type i)
368  {
369  assert(this->col.index()==i);
370  addMatMultMat(*(this->col),t1,t2);
371  }
372  };
373 
374  template<class T, class A, int n, int m>
375  class EntryAccumulator<T,A,n,m,0>
376  : public EntryAccumulatorFather<T,A,n,m>
377  {
378  public:
379  typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
380  typedef typename Matrix::size_type size_type;
381 
382  EntryAccumulator(Matrix& mat_)
383  : EntryAccumulatorFather<T,A,n,m>(mat_)
384  {}
385 
386  template<class T1, class T2>
387  void operator()(const T1& t1, const T2& t2, size_type i, size_type j)
388  {
389  addMatMultMat(this->mat[i][j], t1, t2);
390  }
391  };
392 
393  template<class T, class A, int n, int m>
394  class EntryAccumulator<T,A,n,m,1>
395  : public EntryAccumulatorFather<T,A,n,m>
396  {
397  public:
398  typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
399  typedef typename Matrix::size_type size_type;
400 
401  EntryAccumulator(Matrix& mat_)
402  : EntryAccumulatorFather<T,A,n,m>(mat_)
403  {}
404 
405  template<class T1, class T2>
406  void operator()(const T1& t1, const T2& t2, size_type i, size_type j)
407  {
408  addTransposeMatMultMat(this->mat[i][j], t1, t2);
409  }
410  };
411 
412  template<class T, class A, int n, int m>
413  class EntryAccumulator<T,A,n,m,2>
414  : public EntryAccumulatorFather<T,A,n,m>
415  {
416  public:
417  typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix;
418  typedef typename Matrix::size_type size_type;
419 
420  EntryAccumulator(Matrix& mat_)
421  : EntryAccumulatorFather<T,A,n,m>(mat_)
422  {}
423 
424  template<class T1, class T2>
425  void operator()(const T1& t1, const T2& t2, [[maybe_unused]] size_type i)
426  {
427  assert(this->col.index()==i);
428  addMatMultTransposeMat(*this->col,t1,t2);
429  }
430  };
431 
432 
433  template<int transpose>
434  struct SizeSelector
435  {};
436 
437  template<>
438  struct SizeSelector<0>
439  {
440  template<class M1, class M2>
441  static std::tuple<typename M1::size_type, typename M2::size_type>
442  size(const M1& m1, const M2& m2)
443  {
444  return std::make_tuple(m1.N(), m2.M());
445  }
446  };
447 
448  template<>
449  struct SizeSelector<1>
450  {
451  template<class M1, class M2>
452  static std::tuple<typename M1::size_type, typename M2::size_type>
453  size(const M1& m1, const M2& m2)
454  {
455  return std::make_tuple(m1.M(), m2.M());
456  }
457  };
458 
459 
460  template<>
461  struct SizeSelector<2>
462  {
463  template<class M1, class M2>
464  static std::tuple<typename M1::size_type, typename M2::size_type>
465  size(const M1& m1, const M2& m2)
466  {
467  return std::make_tuple(m1.N(), m2.N());
468  }
469  };
470 
471  template<int transpose, class T, class A, class A1, class A2, int n1, int m1, int n2, int m2, int n3, int m3>
472  void matMultMat(BCRSMatrix<FieldMatrix<T,n1,m1>,A>& res, const BCRSMatrix<FieldMatrix<T,n2,m2>,A1>& mat1,
473  const BCRSMatrix<FieldMatrix<T,n3,m3>,A2>& mat2)
474  {
475  // First step is to count the number of nonzeros
476  typename BCRSMatrix<FieldMatrix<T,n1,m1>,A>::size_type rows, cols;
477  std::tie(rows,cols)=SizeSelector<transpose>::size(mat1, mat2);
478  MatrixInitializer<transpose,T,A,n1,m1> patternInit(res, rows);
479  Timer timer;
480  NonzeroPatternTraverser<transpose>::traverse(mat1,mat2,patternInit);
481  res.setSize(rows, cols, patternInit.nonzeros());
482  res.setBuildMode(BCRSMatrix<FieldMatrix<T,n1,m1>,A>::row_wise);
483 
484  //std::cout<<"Counting nonzeros took "<<timer.elapsed()<<std::endl;
485  timer.reset();
486 
487  // Second step is to allocate the storage for the result and initialize the nonzero pattern
488  patternInit.initPattern(mat1, mat2);
489 
490  //std::cout<<"Setting up sparsity pattern took "<<timer.elapsed()<<std::endl;
491  timer.reset();
492  // As a last step calculate the entries
493  res = 0.0;
494  EntryAccumulator<T,A,n1,m1, transpose> entriesAccu(res);
495  NonzeroPatternTraverser<transpose>::traverse(mat1,mat2,entriesAccu);
496  //std::cout<<"Calculating entries took "<<timer.elapsed()<<std::endl;
497  }
498 
499  }
500 
508  template<typename M1, typename M2>
510  {};
511 
512  template<typename T, int n, int k, int m>
513  struct MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >
514  {
515  typedef FieldMatrix<T,n,m> type;
516  };
517 
518  template<typename T, typename A, typename A1, int n, int k, int m>
519  struct MatMultMatResult<BCRSMatrix<FieldMatrix<T,n,k>,A >,BCRSMatrix<FieldMatrix<T,k,m>,A1 > >
520  {
521  typedef BCRSMatrix<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type,
522  std::allocator<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type> > type;
523  };
524 
525 
533  template<typename M1, typename M2>
535  {};
536 
537  template<typename T, int n, int k, int m>
538  struct TransposedMatMultMatResult<FieldMatrix<T,k,n>,FieldMatrix<T,k,m> >
539  {
540  typedef FieldMatrix<T,n,m> type;
541  };
542 
543  template<typename T, typename A, typename A1, int n, int k, int m>
544  struct TransposedMatMultMatResult<BCRSMatrix<FieldMatrix<T,k,n>,A >,BCRSMatrix<FieldMatrix<T,k,m>,A1 > >
545  {
546  typedef BCRSMatrix<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type,
547  std::allocator<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type> > type;
548  };
549 
550 
559  template<class T, class A, class A1, class A2, int n, int m, int k>
561  const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, [[maybe_unused]] bool tryHard=false)
562  {
563  matMultMat<2>(res,mat, matt);
564  }
565 
574  template<class T, class A, class A1, class A2, int n, int m, int k>
576  const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, bool tryHard=false)
577  {
578  matMultMat<0>(res,mat, matt);
579  }
580 
589  template<class T, class A, class A1, class A2, int n, int m, int k>
591  const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, [[maybe_unused]] bool tryHard=false)
592  {
593  matMultMat<1>(res,mat, matt);
594  }
595 
596 }
597 #endif
Implementation of the BCRSMatrix class.
void insert(size_type j)
put column index in row
Definition: bcrsmatrix.hh:1061
A sparse block matrix with compressed row storage.
Definition: bcrsmatrix.hh:466
friend class CreateIterator
allow CreateIterator to access internal data
Definition: bcrsmatrix.hh:1091
Iterator RowIterator
rename the iterators for easier access
Definition: bcrsmatrix.hh:697
Iterator end()
Get iterator to one beyond last row.
Definition: bcrsmatrix.hh:677
row_type::Iterator ColIterator
Iterator for the entries of each row.
Definition: bcrsmatrix.hh:700
A::size_type size_type
The type for the index access and the size.
Definition: bcrsmatrix.hh:497
CreateIterator createbegin()
get initial create iterator
Definition: bcrsmatrix.hh:1094
A dense n x m matrix.
Definition: fmatrix.hh:117
Implements a matrix constructed from a given type representing a field and compile-time given number ...
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
void matMultMat(BCRSMatrix< FieldMatrix< T, n, m >, A > &res, const BCRSMatrix< FieldMatrix< T, n, k >, A1 > &mat, const BCRSMatrix< FieldMatrix< T, k, m >, A2 > &matt, bool tryHard=false)
Calculate product of two sparse matrices ( ).
Definition: matrixmatrix.hh:575
void matMultTransposeMat(BCRSMatrix< FieldMatrix< T, n, k >, A > &res, const BCRSMatrix< FieldMatrix< T, n, m >, A1 > &mat, const BCRSMatrix< FieldMatrix< T, k, m >, A2 > &matt, [[maybe_unused]] bool tryHard=false)
Calculate product of a sparse matrix with a transposed sparse matrices ( ).
Definition: matrixmatrix.hh:560
void transposeMatMultMat(BCRSMatrix< FieldMatrix< T, n, m >, A > &res, const BCRSMatrix< FieldMatrix< T, k, n >, A1 > &mat, const BCRSMatrix< FieldMatrix< T, k, m >, A2 > &matt, [[maybe_unused]] bool tryHard=false)
Calculate product of a transposed sparse matrix with another sparse matrices ( ).
Definition: matrixmatrix.hh:590
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Helper TMP to get the result type of a sparse matrix matrix multiplication ( )
Definition: matrixmatrix.hh:510
Helper TMP to get the result type of a sparse matrix matrix multiplication ( )
Definition: matrixmatrix.hh:535
A simple timing class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 27, 22:29, 2024)