Dune Core Modules (2.3.1)

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