DUNE-FEM (2.10)

spmatrix.hh
1#ifndef DUNE_FEM_SPMATRIX_HH
2#define DUNE_FEM_SPMATRIX_HH
3
4// system includes
5#include <algorithm>
6#include <array>
7#include <cstdlib>
8#include <iostream>
9#include <limits>
10#include <string>
11#include <utility>
12#include <vector>
13
14// local includes
15#include <dune/fem/function/adaptivefunction/adaptivefunction.hh>
16#include <dune/fem/misc/functor.hh>
17#include <dune/fem/operator/common/localmatrix.hh>
18#include <dune/fem/operator/common/localmatrixwrapper.hh>
19#include <dune/fem/io/file/asciiparser.hh>
20#include <dune/fem/io/parameter.hh>
21#include <dune/fem/operator/common/operator.hh>
22#include <dune/fem/operator/matrix/columnobject.hh>
23#include <dune/fem/space/mapper/nonblockmapper.hh>
24#include <dune/fem/storage/objectstack.hh>
25#include <dune/fem/operator/common/stencil.hh>
26#include <dune/fem/operator/matrix/functor.hh>
27#include <dune/fem/solver/parameter.hh>
28
29namespace Dune
30{
31
32 namespace Fem
33 {
34
36 template <class T, class IndexT = std::size_t,
37 class ValuesVector = std::vector< T >,
38 class IndicesVector = std::vector< IndexT > >
40 {
41 public:
43 typedef T field_type;
45 typedef IndexT size_type;
50
51 static const size_type defaultCol = std::numeric_limits<size_type>::max();
52 static const size_type zeroCol = std::numeric_limits<size_type>::max()-1;
53 static const int firstCol = 0;
54
55 SparseRowMatrix(const ThisType& ) = delete;
56
58 explicit SparseRowMatrix( const bool threading = true ) :
59 values_(0), columns_(0), rows_(0), dim_({{0,0}}), maxNzPerRow_(0), compressed_( false ), threading_( threading )
60 {}
61
64 SparseRowMatrix(const size_type rows, const size_type cols, const size_type nz, const bool threading = true ) :
65 values_(0), columns_(0), rows_(0), dim_({{0,0}}), maxNzPerRow_(0), compressed_( false ), threading_( threading )
66 {
67 reserve(rows,cols,nz);
68 }
69
71 void reserve(const size_type rows, const size_type cols, const size_type nz)
72 {
73 // if( (rows != dim_[0]) || (cols != dim_[1]) || (nz != maxNzPerRow_))
74 resize(rows,cols,nz);
75 clear();
76 }
77
79 template <class Stencil>
80 void fillPattern(const Stencil& stencil,
81 const size_type rowBlockSize,
82 const size_type colBlockSize )
83 {
84 const auto& sparsityPattern = stencil.globalStencil();
85 for( const auto& entry : sparsityPattern )
86 {
87 const auto& blockRow = entry.first;
88 const auto& blockColumnSet = entry.second;
89
90 // blocking of rows
91 const size_type nextRow = (blockRow + 1) * rowBlockSize;
92 for( size_type row = blockRow * rowBlockSize; row < nextRow; ++row )
93 {
94 size_type column = startRow( row );
95 for( const auto& blockColEntry : blockColumnSet )
96 {
97 size_type col = blockColEntry * colBlockSize;
98 for( size_type c = 0; c<colBlockSize; ++c, ++col, ++column )
99 {
100 assert( column < endRow( row ) );
101 columns_[ column ] = col ;
102 }
103 }
104 }
105 }
106 }
107
110 {
111 return dim_[0];
112 }
113
116 {
117 return dim_[1];
118 }
119
121 void set(const size_type row, const size_type col, const field_type val)
122 {
123 assert((col>=0) && (col < dim_[1]));
124 assert((row>=0) && (row < dim_[0]));
125
126 const size_type column = colIndex(row,col) ;
127 assert( column != defaultCol && column != zeroCol );
128
129 values_ [ column ] = val;
130 columns_[ column ] = col;
131 }
132
134 void add(const size_type row, const size_type col, const field_type val)
135 {
136 assert((col>=0) && (col < dim_[1]));
137 assert((row>=0) && (row < dim_[0]));
138
139 const size_type column = colIndex(row,col) ;
140 assert( column != defaultCol && column != zeroCol );
141
142 values_ [ column ] += val;
143 columns_[ column ] = col;
144 }
145
147 template<class ArgDFType, class DestDFType>
148 void apply(const ArgDFType& f, DestDFType& ret ) const
149 {
150 bool runParallel = threading_;
151
152 auto doApply = [this, &f, &ret]()
153 {
154 constexpr auto blockSize = ArgDFType::DiscreteFunctionSpaceType::localBlockSize;
155
156 // compute slice of rows to be worked on
157 const auto slice = sliceBeginEnd( MPIManager::thread(), MPIManager::numThreads(), std::true_type() );
158
159 // same as begin just with a row not necessarily zero
160 auto ret_it = ret.dofVector().find( slice.first );
161
162 const auto& fDofVec = f.dofVector();
163 for(size_type row = slice.first; row<slice.second; ++row)
164 {
165 const size_type endrow = endRow( row );
166 (*ret_it) = 0.0;
167 for(size_type col = startRow( row ); col<endrow; ++col)
168 {
169 const auto realCol = columns_[ col ];
170
171 if( ! compressed_ && ((realCol == defaultCol) || (realCol == zeroCol)) )
172 continue;
173
174 const auto blockNr = realCol / blockSize ;
175 const auto dofNr = realCol % blockSize ;
176 (*ret_it) += values_[ col ] * fDofVec[ blockNr ][ dofNr ];
177 }
178
179 ++ret_it;
180 }
181 };
182
183 if( runParallel )
184 {
185 try {
186 // execute in parallel
187 MPIManager :: run ( doApply );
188 }
189 catch ( const SingleThreadModeError& e )
190 {
191 runParallel = false;
192 }
193 }
194
195 // run serial if threading disabled or something else went wrong
196 if( ! runParallel )
197 {
198 doApply();
199 }
200 }
201
203 field_type get(const size_type row, const size_type col) const
204 {
205 assert((col>=0) && (col < dim_[1]));
206 assert((row>=0) && (row < dim_[0]));
207
208 const size_type endrow = endRow( row );
209 for( size_type i = startRow( row ); i<endrow; ++i )
210 {
211 if(columns_[ i ] == col)
212 return values_[ i ];
213 }
214 return 0;
215 }
216
218 void clear()
219 {
220 std::fill( values_.begin(), values_.end(), 0 );
221 for (auto &c : columns_) c = defaultCol;
222 }
223
225 void clearRow(const size_type row)
226 {
227 assert((row>=0) && (row < dim_[0]));
228
229 const size_type endrow = endRow( row );
230 for(size_type idx = startRow( row ); idx<endrow; ++idx )
231 {
232 values_[ idx ] = 0;
233 // if ( !compressed_ )
234 // columns_[idx] = zeroCol;
235 }
236 }
237
239 void scale(const size_type row, const size_type col, const field_type val)
240 {
241 assert((row>=0) && (row < rows()) );
242 assert((col>=0) && (col < cols()) );
243
244 const size_type column = colIndex(row,col) ;
245 assert( column != defaultCol && column != zeroCol );
246
247 // scale value
248 values_ [ column ] *= val;
249 }
250
254 {
255 return maxNzPerRow_;
256 }
257
261 {
262 return dim_[0] > 0 ? rows_[ dim_[0] ] : 0;
263 }
264
268 {
269 assert( row >= 0 && row < dim_[0] );
270 return endRow( row ) - startRow( row );
271 }
272
275 std::pair<const field_type, size_type> realValue(size_type index) const
276 {
277 return std::pair<const field_type, size_type>(values_[index], columns_[index]);
278 }
279
281 void print(std::ostream& s=std::cout, unsigned int offset=0) const
282 {
283 for(size_type row=0; row<dim_[0]; ++row)
284 {
285 const size_type endrow = endRow( row );
286 for( size_type pos = startRow( row ); pos<endrow; ++pos )
287 {
288 const auto rv(realValue(pos));
289 const auto column(rv.second);
290 const auto value(rv.first);
291 if((std::abs(value) > 1.e-15) && (column != defaultCol))
292 s << row+offset << " " << column+offset << " " << value << std::endl;
293 }
294 }
295 }
296
297 template <class SizeT, class NumericT >
298 void fillCSRStorage( std::vector< std::map<SizeT, NumericT> >& matrix ) const
299 {
300 matrix.resize( dim_[0] );
301
302 size_type thisCol = 0;
303 for(size_type row = 0; row<dim_[ 0 ]; ++row )
304 {
305 auto& matRow = matrix[ row ];
306 const size_type endrow = endRow( row );
307 for(size_type col = startRow( row ); col<endrow; ++col)
308 {
309 const size_type realCol = columns_[ col ];
310
311 if( ! compressed_ && (realCol == defaultCol || realCol == zeroCol) )
312 continue;
313
314 matRow[ realCol ] = values_[ thisCol ];
315 }
316 }
317 }
318
319 void compress ()
320 {
321 if( ! compressed_ && (dim_[0] != 0) && (dim_[1] != 0))
322 {
323 // determine first row nonZeros
324 size_type newpos = 0 ;
325 for( newpos = startRow( 0 ); newpos < endRow( 0 ); ++newpos )
326 {
327 if( columns_[ newpos ] == defaultCol )
328 break;
329 }
330
331 for( size_type row = 1; row<dim_[0]; ++row )
332 {
333 const size_type endrow = endRow( row );
334 size_type col = startRow( row );
335 // update new row start position
336 rows_[ row ] = newpos;
337 for(; col<endrow; ++col, ++newpos )
338 {
339 if( columns_[ col ] == defaultCol )
340 break ;
341
342 assert( newpos <= col );
343 values_ [ newpos ] = values_ [ col ];
344 columns_[ newpos ] = columns_[ col ];
345 }
346 }
347 rows_[ dim_[0] ] = newpos ;
348
349 // values_.resize( newpos );
350 // columns_.resize( newpos );
351 compressed_ = true ;
352 }
353 }
354
355 size_type startRow ( const size_type row ) const
356 {
357 return rows_[ row ];
358 }
359
360 size_type endRow ( const size_type row ) const
361 {
362 return rows_[ row+1 ];
363 }
364
365 std::tuple< ValuesVector&, IndicesVector&, IndicesVector& > exportCRS()
366 {
367 // only return internal data in compressed status
368 compress();
369 return std::tie(values_,columns_,rows_);
370 }
371
373 template<class DiagType, class ArgDFType, class DestDFType, class WType>
374 void forwardIterative(const DiagType& diagInv, const ArgDFType& b, const DestDFType& xold, DestDFType& xnew, const WType& w ) const
375 {
376 parallelIterative(diagInv, b, xold, xnew, w, std::true_type() );
377 }
378
380 template<class DiagType, class ArgDFType, class DestDFType, class WType>
381 void backwardIterative(const DiagType& diagInv, const ArgDFType& b, const DestDFType& xold, DestDFType& xnew, const WType& w ) const
382 {
383 parallelIterative(diagInv, b, xold, xnew, w, std::false_type() );
384 }
385
386 protected:
387 // return slice of rows for given thread in forward direction
388 std::pair< size_type, size_type > sliceBeginEnd(const size_type thread, const size_type numThreads, std::true_type ) const
389 {
390 const size_type sliceSize = this->rows() / numThreads;
391 const size_type sliceBegin = (thread * sliceSize) ;
392 const size_type sliceEnd = (thread == numThreads-1 ) ? this->rows(): (sliceBegin + sliceSize);
393 return std::make_pair( sliceBegin, sliceEnd );
394 }
395
396 // return slice of rows for given thread in backward direction
397 std::pair< size_type, size_type > sliceBeginEnd(const size_type thread, const size_type numThreads, std::false_type ) const
398 {
399 std::pair< size_type, size_type > beginEnd = sliceBeginEnd( thread, numThreads, std::true_type() );
400 return std::make_pair( beginEnd.second-1, beginEnd.first-1 );
401 }
402
403 template<class DiagType, class ArgDFType, class DestDFType, class WType, bool forward >
404 void parallelIterative(const DiagType& diagInv, const ArgDFType& b, const DestDFType& xold, DestDFType& xnew,
405 const WType& w, std::integral_constant<bool, forward> direction ) const
406 {
407 bool runParallel = threading_ && (&xold != &xnew) ; // only for Jacobi
408
409 auto doIterate = [this, &diagInv, &b, &xold, &xnew, &w, &direction, &runParallel] ()
410 {
411 // compute slice to be worked on depending on direction depending on parallel mode
412 const auto slice = runParallel ?
413 sliceBeginEnd( MPIManager::thread(), MPIManager::numThreads(), direction ) :
414 sliceBeginEnd( 0, 1, direction ) ;
415
416 doParallelIterative( diagInv.dofVector().find( slice.first ), // still O(1) operation just like for begin()
417 b.dofVector().find( slice.first ),
418 xold,
419 xnew.dofVector().find( slice.first ),
420 w,
421 slice.first, // row begin
422 slice.second, // row end
423 direction );
424 };
425
426 if( runParallel )
427 {
428 try {
429 // execute in parallel
430 MPIManager :: run ( doIterate );
431 }
432 catch ( const SingleThreadModeError& e )
433 {
434 runParallel = false;
435 }
436 }
437
438 // run serial if threading disabled or something else went wrong
439 if( ! runParallel )
440 {
441 doIterate();
442 }
443 }
444
446 template<class DiagIt, class ArgDFIt, class DestDFType, class DestDFIt,
447 class WType, bool forward>
448 void doParallelIterative(DiagIt diag, ArgDFIt bit, const DestDFType& xold, DestDFIt xit,
449 const WType& w,
450 size_type row, const size_type end,
451 std::integral_constant<bool, forward> ) const
452 {
453 constexpr auto blockSize = DestDFType::DiscreteFunctionSpaceType::localBlockSize;
454
455 const auto nextRow = [&diag, &xit, &bit](size_type &row)
456 {
457 if constexpr ( forward )
458 {
459 ++diag; ++xit; ++bit; ++row;
460 }
461 else
462 {
463 --diag; --xit; --bit; --row;
464 }
465 };
466
467 const auto& xOldVec = xold.dofVector();
468 for(; row != end; nextRow(row))
469 {
470 auto rhs = (*bit);
471
472 const size_type endrow = endRow( row );
473 for(size_type col = startRow( row ); col<endrow; ++col)
474 {
475 const auto realCol = columns_[ col ];
476
477 if( (realCol == row ) || (! compressed_ && ((realCol == defaultCol) || (realCol == zeroCol))) )
478 continue;
479
480 const auto blockNr = realCol / blockSize ;
481 const auto dofNr = realCol % blockSize ;
482
483 rhs -= values_[ col ] * xOldVec[ blockNr ][ dofNr ] ;
484 }
485
486 (*xit) = w * (rhs * (*diag));
487 }
488 }
491 {
492 constexpr auto colVal = defaultCol;
493 values_.resize( rows*nz , 0 );
494 columns_.resize( rows*nz , colVal );
495 rows_.resize( rows+1 , 0 );
496 rows_[ 0 ] = 0;
497 for( size_type i=1; i <= rows; ++i )
498 {
499 rows_[ i ] = rows_[ i-1 ] + nz ;
500 }
501 compressed_ = false;
502
503 dim_[0] = rows;
504 dim_[1] = cols;
505 maxNzPerRow_ = nz+firstCol;
506 }
507
510 {
511 assert((col>=0) && (col < dim_[1]));
512 assert((row>=0) && (row < dim_[0]));
513
514 const size_type endR = endRow( row );
515 size_type i = startRow( row );
516 // find local column or empty spot
517 for( ; i < endR; ++i )
518 {
519 if( columns_[ i ] == defaultCol || columns_[ i ] == zeroCol || columns_[ i ] == col )
520 {
521 return i;
522 }
523 }
524
525 assert(0);
526 DUNE_THROW( InvalidStateException, "Could not store entry in sparse matrix - no space available" );
527
528 // TODO: implement resize with 2*nz
529 std::abort();
530 return defaultCol;
531
532 /*
533 if(columns_[ i ] == col)
534 return i; // column already in matrix
535 else if( columns_[ i ] == defaultCol )
536 { // add this column at end of this row
537 ++nonZeros_[row];
538 return i;
539 }
540 else
541 {
542 std::abort();
543 // TODO re-implement
544 //
545 ++nonZeros_[row];
546 // must shift this row to add col at the position i
547 auto j = nz_-1; // last column
548 if (columns_[row*nz_+j] != defaultCol)
549 { // new space available - so resize
550 resize( rows(), cols(), (2 * nz_) );
551 j++;
552 }
553 for(;j>i;--j)
554 {
555 columns_[row*nz_+j] = columns_[row*nz_+j-1];
556 values_[row*nz_+j] = values_[row*nz_+j-1];
557 }
558 columns_[row*nz_+i] = col;
559 values_[row*nz_+i] = 0;
560 return i;
561 }
562 */
563 }
564
565 ValuesVector values_;
566 IndicesVector columns_;
567 IndicesVector rows_;
568
569 std::array<size_type,2> dim_;
570 size_type maxNzPerRow_;
571 bool compressed_;
572 const bool threading_;
573 };
574
575
576
578 template< class DomainSpace, class RangeSpace,
581 {
582 protected:
583 template< class MatrixObject >
584 struct LocalMatrixTraits;
585
586 template< class MatrixObject >
587 class LocalMatrix;
588
589 public:
590 typedef DomainSpace DomainSpaceType;
591 typedef RangeSpace RangeSpaceType;
592 typedef typename DomainSpaceType::EntityType DomainEntityType;
593 typedef typename RangeSpaceType::EntityType RangeEntityType;
594 typedef typename DomainSpaceType::EntityType ColumnEntityType;
595 typedef typename RangeSpaceType::EntityType RowEntityType;
596
597 typedef typename DomainSpaceType::BlockMapperType DomainBlockMapperType;
599 typedef typename RangeSpaceType::BlockMapperType RangeBlockMapperType;
601 typedef Matrix MatrixType;
602 typedef typename MatrixType::size_type size_type;
603 typedef typename MatrixType::field_type field_type;
604
606
607 static const size_type domainLocalBlockSize = DomainSpaceType::dimRange;
608 static const size_type rangeLocalBlockSize = RangeSpaceType::dimRange;
609
612
614
618 typedef LocalMatrixWrapper< LocalMatrixStackType > LocalMatrixType;
619 typedef ColumnObject< ThisType > LocalColumnObjectType;
620
622 SparseRowMatrixObject( const DomainSpaceType &domainSpace,
623 const RangeSpaceType &rangeSpace,
624 const SolverParameter& param = SolverParameter() )
625 : domainSpace_( domainSpace ),
626 rangeSpace_( rangeSpace ),
627 domainMapper_( domainSpace_.blockMapper() ),
628 rangeMapper_( rangeSpace_.blockMapper() ),
629 sequence_( -1 ),
630 matrix_( param.threading() ),
631 localMatrixStack_( *this )
632 {}
633
635 const DomainSpaceType& domainSpace() const
636 {
637 return domainSpace_;
638 }
639
641 const RangeSpaceType& rangeSpace() const
642 {
643 return rangeSpace_;
644 }
645
646 protected:
649 {
650 return matrix_;
651 }
652
653 void finalizeAssembly() const { const_cast< ThisType& > (*this).compress(); }
654
655 public:
658 {
659 finalizeAssembly();
660 return matrix_;
661 }
662
663
666 {
667 return new ObjectType( *this, domainSpace_, rangeSpace_, domainMapper_, rangeMapper_ );
668 }
669
674 [[deprecated("Use TemporaryLocalMatrix,LocalContribution and {get,add,set}LocalMatrix")]]
675 LocalMatrixType localMatrix( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity ) const
676 {
677 return LocalMatrixType( localMatrixStack_, domainEntity, rangeEntity );
678 }
679
684 [[deprecated("Use TemporaryLocalMatrix,LocalContribution and {get,add,set}LocalMatrix")]]
685 LocalMatrixType localMatrix() const
686 {
687 return LocalMatrixType( localMatrixStack_ );
688 }
689
691 LocalColumnObjectType localColumn( const DomainEntityType &domainEntity ) const
692 {
693 return LocalColumnObjectType( *this, domainEntity );
694 }
695
696 void unitRow( const size_type row )
697 {
698 for( unsigned int i=0, r = row * domainLocalBlockSize; i<domainLocalBlockSize; ++i, ++r )
699 {
700 matrix_.clearRow( r );
701 matrix_.set( r, r, 1.0 );
702 }
703 }
704
705 template <class LocalBlock>
706 void addBlock( const size_type row, const size_type col, const LocalBlock& block )
707 {
708 std::array< size_type, rangeLocalBlockSize > rows;
709 std::array< size_type, domainLocalBlockSize > cols;
710 for( unsigned int i=0, r = row * domainLocalBlockSize, c = col * domainLocalBlockSize; i<domainLocalBlockSize; ++i, ++r, ++c )
711 {
712 rows[ i ] = r;
713 cols[ i ] = c;
714 }
715
716 for( unsigned int i=0; i<domainLocalBlockSize; ++i )
717 {
718 for( unsigned int j=0; j<domainLocalBlockSize; ++j )
719 {
720 matrix_.add( rows[ i ], cols[ j ], block[ i ][ j ]);
721 }
722 }
723 }
724
725 template <class LocalBlock>
726 void setBlock( const size_type row, const size_type col, const LocalBlock& block )
727 {
728 std::array< size_type, rangeLocalBlockSize > rows;
729 std::array< size_type, domainLocalBlockSize > cols;
730 for( unsigned int i=0, r = row * domainLocalBlockSize, c = col * domainLocalBlockSize; i<domainLocalBlockSize; ++i, ++r, ++c )
731 {
732 rows[ i ] = r;
733 cols[ i ] = c;
734 }
735
736 for( unsigned int i=0; i<domainLocalBlockSize; ++i )
737 {
738 for( unsigned int j=0; j<domainLocalBlockSize; ++j )
739 {
740 matrix_.set( rows[ i ], cols[ j ], block[ i ][ j ]);
741 }
742 }
743 }
744
745 template< class LocalMatrix >
746 void addLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat )
747 {
748 auto functor = [ &localMat, this ] ( std::pair< int, int > local, const std::pair< size_type, size_type >& global )
749 {
750 matrix_.add( global.first, global.second, localMat.get( local.first, local.second ) );
751 };
752
753 rangeMapper_.mapEach( rangeEntity, makePairFunctor( domainMapper_, domainEntity, functor ) );
754 }
755
756 template< class LocalMatrix, class Scalar >
757 void addScaledLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat, const Scalar &s )
758 {
759 auto functor = [ &localMat, &s, this ] ( std::pair< int, int > local, const std::pair< size_type, size_type >& global )
760 {
761 matrix_.add( global.first, global.second, s * localMat.get( local.first, local.second ) );
762 };
763
764 rangeMapper_.mapEach( rangeEntity, makePairFunctor( domainMapper_, domainEntity, functor ) );
765 }
766
767 template< class LocalMatrix >
768 void setLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat )
769 {
770 auto functor = [ &localMat, this ] ( std::pair< int, int > local, const std::pair< size_type, size_type >& global )
771 {
772 matrix_.set( global.first, global.second, localMat.get( local.first, local.second ) );
773 };
774
775 rangeMapper_.mapEach( rangeEntity, makePairFunctor( domainMapper_, domainEntity, functor ) );
776 }
777
778 template< class LocalMatrix >
779 void getLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, LocalMatrix &localMat ) const
780 {
781 auto functor = [ &localMat, this ] ( std::pair< int, int > local, const std::pair< size_type, size_type >& global )
782 {
783 localMat.set( local.first, local.second, matrix_.get( global.first, global.second ) );
784 };
785
786 rangeMapper_.mapEach( rangeEntity, makePairFunctor( domainMapper_, domainEntity, functor ) );
787 }
788
790 void clear()
791 {
792 matrix_.clear();
793 }
794
796 void compress() { matrix_.compress(); }
797
798 template <class Set>
799 void reserve (const std::vector< Set >& sparsityPattern )
800 {
801 reserve( StencilWrapper< DomainSpaceType,RangeSpaceType, Set >( sparsityPattern ) );
802 }
803
805 template <class Stencil>
806 void reserve(const Stencil &stencil, bool verbose = false )
807 {
808 if( sequence_ != domainSpace_.sequence() )
809 {
810 // if empty grid do nothing (can appear in parallel runs)
811 if( (domainSpace_.begin() != domainSpace_.end()) && (rangeSpace_.begin() != rangeSpace_.end()) )
812 {
813 // output some info
814 if( verbose )
815 {
816 std::cout << "Reserve Matrix with (" << rangeSpace_.size() << "," << domainSpace_.size()<< ")" << std::endl;
817 std::cout << "Max number of base functions = (" << rangeMapper_.maxNumDofs() << ","
818 << domainMapper_.maxNumDofs() << ")" << std::endl;
819 }
820
821 // reserve matrix
822 const auto nonZeros = std::max( static_cast<size_type>(stencil.maxNonZerosEstimate()*DomainSpaceType::localBlockSize),
823 matrix_.maxNzPerRow() );
824 matrix_.reserve( rangeSpace_.size(), domainSpace_.size(), nonZeros );
825 matrix_.fillPattern( stencil, RangeSpaceType::localBlockSize, DomainSpaceType::localBlockSize );
826 }
827 sequence_ = domainSpace_.sequence();
828 }
829 }
830
832 template< class DomainFunction, class RangeFunction >
833 void apply( const DomainFunction &arg, RangeFunction &dest ) const
834 {
835 // do matrix vector multiplication
836 matrix_.apply( arg, dest );
837 // communicate data
838 dest.communicate();
839 }
840
843 template < class DiscreteFunctionType >
845 {
846 assert( matrix_.rows() == matrix_.cols() );
847 const auto dofEnd = diag.dend();
848 size_type row = 0;
849 for( auto dofIt = diag.dbegin(); dofIt != dofEnd; ++dofIt, ++row )
850 {
851 assert( row < matrix_.rows() );
852 (*dofIt) = matrix_.get( row, row );
853 }
854 }
855
856 template <class Container>
857 void setUnitRows( const Container& unitRows, const Container& auxRows )
858 {
859 for (const auto& r : unitRows )
860 {
861 matrix_.clearRow(r);
862 matrix_.set(r, r, 1.0);
863 }
864
865 for (const auto& r : auxRows )
866 {
867 matrix_.clearRow(r);
868 // not sure if this is really needed,
869 // but for consistency with previous code
870 // matrix_.set(r, r, 0.0);
871 }
872 }
873
875 void resort()
876 {
877 DUNE_THROW(NotImplemented,"SpMatrixObject::resort is not implemented");
878 // this method does not even exist on SpMatrix!!!
879 // matrix_.resort();
880 }
881
882 protected:
883 const DomainSpaceType &domainSpace_;
884 const RangeSpaceType &rangeSpace_;
885 DomainMapperType domainMapper_ ;
886 RangeMapperType rangeMapper_ ;
887 int sequence_;
888 mutable MatrixType matrix_;
889 mutable LocalMatrixStackType localMatrixStack_;
890 };
891
892
893
895 template< class DomainSpace, class RangeSpace, class Matrix >
896 template< class MatrixObject >
897 struct SparseRowMatrixObject< DomainSpace, RangeSpace, Matrix >::LocalMatrixTraits
898 {
899 typedef DomainSpace DomainSpaceType;
900 typedef RangeSpace RangeSpaceType;
901
903
904 typedef typename SparseRowMatrixObjectType::template LocalMatrix< MatrixObject > LocalMatrixType;
905
906 typedef typename RangeSpaceType::RangeFieldType RangeFieldType;
907 typedef RangeFieldType LittleBlockType;
908
911 };
912
913
914
916 template< class DomainSpace, class RangeSpace, class Matrix >
917 template< class MatrixObject >
918 class SparseRowMatrixObject< DomainSpace, RangeSpace, Matrix >::LocalMatrix
919 : public LocalMatrixDefault< LocalMatrixTraits< MatrixObject > >
920 {
921 public:
923 typedef MatrixObject MatrixObjectType;
924
927
928 private:
930
931 public:
933 typedef typename MatrixObjectType::MatrixType MatrixType;
934
936 typedef typename Traits::RangeFieldType RangeFieldType;
937
940
942 typedef typename Traits::LittleBlockType LittleBlockType;
943
948
949 typedef std::vector< typename RangeMapperType::SizeType > RowIndicesType;
950 typedef std::vector< typename DomainMapperType::SizeType > ColumnIndicesType;
951
953 LocalMatrix( const MatrixObjectType &matrixObject,
954 const DomainSpaceType &domainSpace,
955 const RangeSpaceType &rangeSpace,
956 const DomainMapperType& domainMapper,
957 const RangeMapperType& rangeMapper )
959 matrix_( matrixObject.matrix() ),
960 domainMapper_( domainMapper ),
961 rangeMapper_( rangeMapper )
962 {}
963
964 LocalMatrix( const LocalMatrix & ) = delete;
965
966 void init( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity )
967 {
968 // initialize base functions sets
969 BaseType::init( domainEntity, rangeEntity );
970 // rows are determined by the range space
971 rowIndices_.resize( rangeMapper_.numDofs( rangeEntity ) );
972 rangeMapper_.mapEach( rangeEntity, AssignFunctor< RowIndicesType >( rowIndices_ ) );
973 // columns are determined by the domain space
974 columnIndices_.resize( domainMapper_.numDofs( domainEntity ) );
975 domainMapper_.mapEach( domainEntity, AssignFunctor< ColumnIndicesType >( columnIndices_ ) );
976 }
977
979 size_type rows() const
980 {
981 return rowIndices_.size();
982 }
983
985 size_type columns() const
986 {
987 return columnIndices_.size();
988 }
989
991 void add(size_type localRow, size_type localCol, DofType value)
992 {
993 assert( value == value );
994 assert( (localRow >= 0) && (localRow < rows()) );
995 assert( (localCol >= 0) && (localCol < columns()) );
996 matrix_.add( rowIndices_[ localRow ], columnIndices_[ localCol ], value );
997 }
998
1000 DofType get(size_type localRow, size_type localCol) const
1001 {
1002 assert( (localRow >= 0) && (localRow < rows()) );
1003 assert( (localCol >= 0) && (localCol < columns()) );
1004 return matrix_.get( rowIndices_[ localRow ], columnIndices_[ localCol ] );
1005 }
1006
1008 void set(size_type localRow, size_type localCol, DofType value)
1009 {
1010 assert( (localRow >= 0) && (localRow < rows()) );
1011 assert( (localCol >= 0) && (localCol < columns()) );
1012 matrix_.set( rowIndices_[ localRow ], columnIndices_[ localCol ], value );
1013 }
1014
1016 void unitRow(size_type localRow)
1017 {
1018 assert( (localRow >= 0) && (localRow < rows()) );
1019 matrix_.unitRow( rowIndices_[ localRow ] );
1020 }
1021
1023 void clearRow( size_type localRow )
1024 {
1025 assert( (localRow >= 0) && (localRow < rows()) );
1026 matrix_.clearRow( rowIndices_[localRow]);
1027 }
1028
1030 void clearCol( size_type localCol )
1031 {
1032 assert( (localCol >= 0) && (localCol < columns()) );
1033 matrix_.clearCol( columnIndices_[localCol] );
1034 }
1035
1037 void clear()
1038 {
1039 const size_type nrows = rows();
1040 for(size_type i=0; i < nrows; ++i )
1041 matrix_.clearRow( rowIndices_[ i ] );
1042 }
1043
1045 void resort()
1046 {
1047 DUNE_THROW(NotImplemented,"SpMatrixObject::LocalMatrix::resort is not implemented");
1048 //const size_type nrows = rows();
1049 //for(size_type i=0; i < nrows; ++i )
1050 //matrix_.resortRow( rowIndices_[ i ] );
1051 }
1052
1054 void scale( const DofType& value )
1055 {
1056 const size_type nrows = rows();
1057 const size_type ncols = columns();
1058 for(size_type i=0; i < nrows; ++i )
1059 {
1060 for( size_type j=0; j < ncols; ++j )
1061 {
1062 scale(i, j, value );
1063 }
1064 }
1065 }
1066
1067 protected:
1069 void scale(size_type localRow, size_type localCol, DofType value)
1070 {
1071 assert( (localRow >= 0) && (localRow < rows()) );
1072 assert( (localCol >= 0) && (localCol < columns()) );
1073 matrix_.scale( rowIndices_[ localRow ], columnIndices_[ localCol ], value );
1074 }
1075
1076 protected:
1077 MatrixType &matrix_;
1078 const DomainMapperType& domainMapper_;
1079 const RangeMapperType& rangeMapper_;
1080 RowIndicesType rowIndices_;
1081 ColumnIndicesType columnIndices_;
1082 };
1083
1084 } // namespace Fem
1085
1086} // namespace Dune
1087
1088#endif // #ifndef DUNE_FEM_SPMATRIX_HH
ConstDofIteratorType dbegin() const
Obtain the constant iterator pointing to the first dof.
Definition: discretefunction.hh:761
ConstDofIteratorType dend() const
Obtain the constant iterator pointing to the last dof.
Definition: discretefunction.hh:773
Default implementation for local matrix classes.
Definition: localmatrix.hh:287
Exception thrown when a code segment that is supposed to be only accessed in single thread mode is ac...
Definition: mpimanager.hh:43
LocalMatrix.
Definition: spmatrix.hh:920
void clearRow(size_type localRow)
set matrix row to zero
Definition: spmatrix.hh:1023
void add(size_type localRow, size_type localCol, DofType value)
add value to matrix entry
Definition: spmatrix.hh:991
MatrixObjectType::MatrixType MatrixType
type of matrix
Definition: spmatrix.hh:933
void clearCol(size_type localCol)
set matrix column to zero
Definition: spmatrix.hh:1030
void resort()
resort all global rows of matrix to have ascending numbering
Definition: spmatrix.hh:1045
size_type columns() const
return number of columns
Definition: spmatrix.hh:985
size_type rows() const
return number of rows
Definition: spmatrix.hh:979
Traits::RangeFieldType RangeFieldType
type of entries of little blocks
Definition: spmatrix.hh:936
DofType get(size_type localRow, size_type localCol) const
get matrix entry
Definition: spmatrix.hh:1000
MatrixObject MatrixObjectType
type of matrix object
Definition: spmatrix.hh:923
Traits::DomainMapperType DomainMapperType
type of nonblocked domain mapper
Definition: spmatrix.hh:945
Traits::RangeMapperType RangeMapperType
type of nonblocked domain mapper
Definition: spmatrix.hh:947
LocalMatrixTraits< MatrixObjectType > Traits
type of the traits
Definition: spmatrix.hh:926
LocalMatrix(const MatrixObjectType &matrixObject, const DomainSpaceType &domainSpace, const RangeSpaceType &rangeSpace, const DomainMapperType &domainMapper, const RangeMapperType &rangeMapper)
constructor
Definition: spmatrix.hh:953
void scale(const DofType &value)
scale local matrix with a certain value
Definition: spmatrix.hh:1054
RangeFieldType DofType
type of the DoFs
Definition: spmatrix.hh:939
void scale(size_type localRow, size_type localCol, DofType value)
scale matrix entry with value
Definition: spmatrix.hh:1069
void clear()
clear all entries belonging to local matrix
Definition: spmatrix.hh:1037
Traits::LittleBlockType LittleBlockType
type of little blocks
Definition: spmatrix.hh:942
void set(size_type localRow, size_type localCol, DofType value)
set matrix entry to value
Definition: spmatrix.hh:1008
void unitRow(size_type localRow)
set matrix row to zero except diagonla entry
Definition: spmatrix.hh:1016
SparseRowMatrixObject.
Definition: spmatrix.hh:581
const DomainSpaceType & domainSpace() const
get domain space (i.e. space that builds the rows)
Definition: spmatrix.hh:635
LocalMatrixType localMatrix() const
Definition: spmatrix.hh:685
MatrixType & exportMatrix() const
get reference to storage object
Definition: spmatrix.hh:657
void apply(const DomainFunction &arg, RangeFunction &dest) const
apply matrix to discrete function
Definition: spmatrix.hh:833
SparseRowMatrixObject(const DomainSpaceType &domainSpace, const RangeSpaceType &rangeSpace, const SolverParameter &param=SolverParameter())
construct matrix object
Definition: spmatrix.hh:622
LocalColumnObjectType localColumn(const DomainEntityType &domainEntity) const
get local column
Definition: spmatrix.hh:691
void extractDiagonal(DiscreteFunctionType &diag) const
Definition: spmatrix.hh:844
LocalMatrixType localMatrix(const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity) const
Definition: spmatrix.hh:675
ObjectType * newObject() const
interface method from LocalMatrixFactory
Definition: spmatrix.hh:665
void reserve(const Stencil &stencil, bool verbose=false)
reserve memory
Definition: spmatrix.hh:806
void compress()
compress matrix to a real CRS format
Definition: spmatrix.hh:796
void resort()
resort row numbering in matrix to have ascending numbering
Definition: spmatrix.hh:875
void clear()
clear matrix
Definition: spmatrix.hh:790
const RangeSpaceType & rangeSpace() const
get range space (i.e. space that builds the columns)
Definition: spmatrix.hh:641
MatrixType & matrix() const
get reference to storage object, for internal use
Definition: spmatrix.hh:648
SparseRowMatrix.
Definition: spmatrix.hh:40
void print(std::ostream &s=std::cout, unsigned int offset=0) const
print matrix
Definition: spmatrix.hh:281
size_type colIndex(size_type row, size_type col)
returns local col index for given global (row,col)
Definition: spmatrix.hh:509
std::pair< const field_type, size_type > realValue(size_type index) const
Definition: spmatrix.hh:275
SparseRowMatrix(const bool threading=true)
construct matrix of zero size
Definition: spmatrix.hh:58
void clearRow(const size_type row)
set all entries in row to zero
Definition: spmatrix.hh:225
IndexT size_type
matrix index type
Definition: spmatrix.hh:45
void add(const size_type row, const size_type col, const field_type val)
add value to row,col entry
Definition: spmatrix.hh:134
void apply(const ArgDFType &f, DestDFType &ret) const
ret = A*f
Definition: spmatrix.hh:148
size_type numNonZeros(size_type row) const
Definition: spmatrix.hh:267
void reserve(const size_type rows, const size_type cols, const size_type nz)
reserve memory for given rows, columns and number of non zeros
Definition: spmatrix.hh:71
void clear()
set all matrix entries to zero
Definition: spmatrix.hh:218
size_type numNonZeros() const
Definition: spmatrix.hh:260
void forwardIterative(const DiagType &diagInv, const ArgDFType &b, const DestDFType &xold, DestDFType &xnew, const WType &w) const
Apply Jacobi/SOR method.
Definition: spmatrix.hh:374
field_type get(const size_type row, const size_type col) const
return value of entry (row,col)
Definition: spmatrix.hh:203
void doParallelIterative(DiagIt diag, ArgDFIt bit, const DestDFType &xold, DestDFIt xit, const WType &w, size_type row, const size_type end, std::integral_constant< bool, forward >) const
Apply Jacobi/SOR method.
Definition: spmatrix.hh:448
void set(const size_type row, const size_type col, const field_type val)
set entry to value (also setting 0 will result in an entry)
Definition: spmatrix.hh:121
void resize(size_type rows, size_type cols, size_type nz)
resize matrix
Definition: spmatrix.hh:490
size_type rows() const
return number of rows
Definition: spmatrix.hh:109
size_type cols() const
return number of columns
Definition: spmatrix.hh:115
void scale(const size_type row, const size_type col, const field_type val)
scale all entries in row with a given value
Definition: spmatrix.hh:239
size_type maxNzPerRow() const
Definition: spmatrix.hh:253
void backwardIterative(const DiagType &diagInv, const ArgDFType &b, const DestDFType &xold, DestDFType &xnew, const WType &w) const
Apply Jacobi/SOR method.
Definition: spmatrix.hh:381
SparseRowMatrix(const size_type rows, const size_type cols, const size_type nz, const bool threading=true)
Definition: spmatrix.hh:64
ThisType MatrixBaseType
Definition: spmatrix.hh:49
void fillPattern(const Stencil &stencil, const size_type rowBlockSize, const size_type colBlockSize)
reserve memory for given rows, columns and number of non zeros
Definition: spmatrix.hh:80
T field_type
matrix field type
Definition: spmatrix.hh:43
a simple wrapper class for sparsity patterns provide as vector< set< size_t > >
Definition: stencil.hh:234
default implementation for a general operator stencil
Definition: stencil.hh:35
const GlobalStencilType & globalStencil() const
Return the full stencil.
Definition: stencil.hh:116
int maxNonZerosEstimate() const
Return an upper bound for the maximum number of non-zero entries in all rows.
Definition: stencil.hh:123
forward declaration
Definition: discretefunction.hh:51
A dense n x m matrix.
Definition: fmatrix.hh:117
Default exception if a function was called while the object is not in a valid state for that function...
Definition: exceptions.hh:281
A generic dynamic dense matrix.
Definition: matrix.hh:561
A::size_type size_type
Type for indices and sizes.
Definition: matrix.hh:577
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:565
Default exception for dummy implementations.
Definition: exceptions.hh:263
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition: interface.hh:235
Dune namespace.
Definition: alignedallocator.hh:13
LocalMatrixTraits.
Definition: spmatrix.hh:898
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 5, 23:02, 2025)