DUNE-FEM (unstable)

istlmatrix.hh
1#ifndef DUNE_FEM_ISTLMATRIXWRAPPER_HH
2#define DUNE_FEM_ISTLMATRIXWRAPPER_HH
3
4#if HAVE_DUNE_ISTL
5
6//- system includes
7#include <vector>
8#include <iostream>
9#include <fstream>
10#include <algorithm>
11#include <set>
12#include <map>
13#include <string>
14
15//- Dune common includes
18
19//- Dune istl includes
20#include <dune/istl/bvector.hh>
23
24//- Dune fem includes
25#include <dune/fem/function/blockvectorfunction.hh>
26#include <dune/fem/operator/common/localmatrix.hh>
27#include <dune/fem/operator/common/localmatrixwrapper.hh>
28#include <dune/fem/operator/common/operator.hh>
29#include <dune/fem/operator/common/stencil.hh>
30#include <dune/fem/function/common/scalarproducts.hh>
31#include <dune/fem/io/parameter.hh>
32#include <dune/fem/operator/matrix/columnobject.hh>
33#include <dune/fem/storage/objectstack.hh>
34
35#include <dune/fem/operator/matrix/istlmatrixadapter.hh>
36#include <dune/fem/operator/matrix/istlpreconditioner.hh>
37#include <dune/fem/operator/matrix/functor.hh>
38
39namespace Dune
40{
41
42 namespace Fem
43 {
44
45
47 template< class MatrixObject >
48 class ISTLLocalMatrix;
49
50 template <class DomainSpaceImp, class RangeSpaceImp,
53 class ISTLMatrixObject;
54
56 // --ISTLMatrixHandle
58 template <class LittleBlockType, class RowDiscreteFunctionImp, class ColDiscreteFunctionImp = RowDiscreteFunctionImp>
59 class ImprovedBCRSMatrix : public BCRSMatrix<LittleBlockType>
60 {
61 friend struct MatrixDimension<ImprovedBCRSMatrix>;
62 public:
63 typedef RowDiscreteFunctionImp RowDiscreteFunctionType;
64 typedef ColDiscreteFunctionImp ColDiscreteFunctionType;
65
66 typedef BCRSMatrix<LittleBlockType> BaseType;
68 typedef BaseType MatrixBaseType;
69 typedef typename BaseType :: RowIterator RowIteratorType ;
70 typedef typename BaseType :: ColIterator ColIteratorType ;
71
72 typedef ImprovedBCRSMatrix< LittleBlockType, RowDiscreteFunctionImp, ColDiscreteFunctionImp > ThisType;
73
74 typedef typename BaseType :: size_type size_type;
75
76 //===== type definitions and constants
77
79 typedef typename BaseType::field_type field_type;
80
82 typedef typename BaseType::block_type block_type;
83
85 typedef typename BaseType:: allocator_type allocator_type;
86
88 typedef typename BaseType :: row_type row_type;
89
91 typedef typename BaseType :: ColIterator ColIterator;
92
94 typedef typename BaseType :: ConstColIterator ConstColIterator;
95
97 typedef typename BaseType :: RowIterator RowIterator;
98
100 typedef typename BaseType :: ConstRowIterator ConstRowIterator;
101
103 typedef typename ColDiscreteFunctionType :: DiscreteFunctionSpaceType RangeSpaceType;
104
106 typedef typename RowDiscreteFunctionType :: DofStorageType RowBlockVectorType;
107
109 typedef typename ColDiscreteFunctionType :: DofStorageType ColBlockVectorType;
110
112 typedef typename RangeSpaceType :: GridType :: Traits :: Communication CommunicationType ;
113
114 typedef typename BaseType :: BuildMode BuildMode ;
115
116 public:
118 ImprovedBCRSMatrix(size_type rows, size_type cols, size_type nnz, double overflowFraction) :
119 BaseType (rows, cols, nnz, overflowFraction, BaseType::implicit)
120 {}
121
123 ImprovedBCRSMatrix(size_type rows, size_type cols, size_type nz = 0 ) :
124 BaseType (rows, cols, BaseType :: row_wise)
125 {}
126
128 ImprovedBCRSMatrix( ) :
129 BaseType ()
130 {}
131
133 ImprovedBCRSMatrix(const ImprovedBCRSMatrix& org) :
134 BaseType(org)
135 {}
136
137 ConstRowIterator slicedBegin( const size_type row ) const
138 {
139 return ConstRowIterator( this->r, row );
140 }
141
142 ConstRowIterator slicedEnd( const size_type row ) const
143 {
144 return ConstRowIterator( this->r, row );
145 }
146
147 std::pair< size_type, size_type > sliceBeginEnd( const size_type thread, const size_type numThreads ) const
148 {
149 const size_type sliceSize = this->N() / numThreads ;
150 const size_type sliceBegin = thread * sliceSize ;
151 const size_type sliceEnd = ( thread == numThreads-1 ) ? this->N() : (sliceBegin + sliceSize) ;
152 return std::make_pair( sliceBegin, sliceEnd );
153 }
154
155 protected:
156 template <class X, class Y, bool isMV>
157 void mvThreadedImpl( [[maybe_unused]] const field_type& alpha,
158 const X& x, Y& y, std::integral_constant<bool, isMV> ) const
159 {
160 auto doMV = [this, &alpha, &x, &y] ()
161 {
162 // this is simply to avoid warnings since
163 // there exist no maybe_unused for lambda captures
164 if constexpr ( isMV )
165 {
166 [[maybe_unused]] field_type a = alpha;
167 }
168
169 const auto slice = sliceBeginEnd( MPIManager::thread(), MPIManager::numThreads() );
170 const ConstRowIterator endi = slicedEnd( slice.second );
171 for (ConstRowIterator i = slicedBegin(slice.first); i!=endi; ++i)
172 {
173 if constexpr ( isMV )
174 y[i.index()] = 0;
175
176 ConstColIterator endj = (*i).end();
177 for (ConstColIterator j=(*i).begin(); j!=endj; ++j)
178 {
179 auto&& xj = Dune::Impl::asVector(x[j.index()]);
180 auto&& yi = Dune::Impl::asVector(y[i.index()]);
181 if constexpr ( isMV )
182 Dune::Impl::asMatrix(*j).umv(xj, yi);
183 else
184 Dune::Impl::asMatrix(*j).usmv(alpha, xj, yi);
185 }
186 }
187 };
188
189 try {
190 // execute in parallel
191 MPIManager :: run ( doMV );
192 }
193 catch ( const SingleThreadModeError& e )
194 {
195 // serial version
196 if constexpr ( isMV )
197 this->mv( x, y );
198 else
199 {
200 DUNE_THROW(SingleThreadModeError,"ImprovedBCRSMatrix::usmvThreaded: Cannot recover from threading error. Disable threading!");
201 // this->usmv( alpha, x, y );
202 }
203 }
204 }
205
206 public:
207 template <class X, class Y>
208 void usmvThreaded( const field_type& alpha, const X& x, Y& y ) const
209 {
210 mvThreadedImpl(alpha, x, y, std::false_type() );
211 }
212
213 template <class X, class Y>
214 void mvThreaded( const X& x, Y& y ) const
215 {
216 mvThreadedImpl(1.0, x, y, std::true_type() );
217 }
218
219 template < class SparsityPattern >
220 void createEntries(const SparsityPattern& sparsityPattern)
221 {
222 const auto spEnd = sparsityPattern.end();
223
224 // insert map of indices into matrix
225 auto endcreate = this->createend();
226 for(auto create = this->createbegin(); create != endcreate; ++create)
227 {
228 const auto row = sparsityPattern.find( create.index() );
229 // if a row is empty then do nothing
230 if( row == spEnd ) continue;
231
232 // insert all indices for this row
233 for ( const auto& col : row->second )
234 create.insert( col );
235 }
236 }
237
239 void clear()
240 {
241 for (auto& row : *this)
242 for (auto& entry : row)
243 entry = 0;
244 }
245
247 void unitRow( const size_t row )
248 {
249 block_type idBlock( 0 );
250 for (int i = 0; i < idBlock.rows; ++i)
251 idBlock[i][i] = 1.0;
252
253 auto& matRow = (*this)[ row ];
254 auto colIt = matRow.begin();
255 const auto& colEndIt = matRow.end();
256 for (; colIt != colEndIt; ++colIt)
257 {
258 if( colIt.index() == row )
259 *colIt = idBlock;
260 else
261 *colIt = 0.0;
262 }
263 }
264
266 template <class HangingNodesType>
267 void setup(ThisType& oldMatrix, const HangingNodesType& hangingNodes)
268 {
269 // necessary because element traversal not necessarily is in ascending order
270 typedef std::set< std::pair<int, block_type> > LocalEntryType;
271 typedef std::map< int , LocalEntryType > EntriesType;
272 EntriesType entries;
273
274 // map of indices
275 std::map< int , std::set<int> > indices;
276 // not insert map of indices into matrix
277 auto rowend = oldMatrix.end();
278 for(auto it = oldMatrix.begin(); it != rowend; ++it)
279 {
280 const auto row = it.index();
281 auto& localIndices = indices[ row ];
282
283 if( hangingNodes.isHangingNode( row ) )
284 {
285 // insert columns into other columns
286 const auto& cols = hangingNodes.associatedDofs( row );
287 const auto colSize = cols.size();
288 for(auto i=0; i<colSize; ++i)
289 {
290 assert( ! hangingNodes.isHangingNode( cols[i].first ) );
291
292 // get local indices of col
293 auto& localColIndices = indices[ cols[i].first ];
294 auto& localEntry = entries[ cols[i].first ];
295
296 // copy from old matrix
297 auto endj = (*it).end();
298 for (auto j= (*it).begin(); j!=endj; ++j)
299 {
300 localColIndices.insert( j.index () );
301 localEntry.insert( std::make_pair( j.index(), (cols[i].second * (*j)) ));
302 }
303 }
304
305 // insert diagonal and hanging columns
306 localIndices.insert( row );
307 for(auto i=0; i<colSize; ++i)
308 localIndices.insert( cols[i].first );
309 }
310 else
311 {
312 // copy from old matrix
313 auto endj = (*it).end();
314 for (auto j= (*it).begin(); j!=endj; ++j)
315 localIndices.insert( j.index () );
316 }
317 }
318
319 // create matrix from entry map
320 createEntries( indices );
321
322 // not insert map of indices into matrix
323 auto rowit = oldMatrix.begin();
324
325 auto endcreate = this->end();
326 for(auto create = this->begin(); create != endcreate; ++create, ++rowit )
327 {
328 assert( rowit != oldMatrix.end() );
329
330 const auto row = create.index();
331 if( hangingNodes.isHangingNode( row ) )
332 {
333 const auto& cols = hangingNodes.associatedDofs( row );
334
335 std::map< const int , block_type > colMap;
336 // only working for block size 1 ath the moment
337 assert( block_type :: rows == 1 );
338 // insert columns into map
339 const auto colSize = cols.size();
340 for( auto i=0; i<colSize; ++i)
341 colMap[ cols[i].first ] = -cols[i].second;
342 // insert diagonal into map
343 colMap[ row ] = 1;
344
345 auto endj = (*create).end();
346 for (auto j= (*create).begin(); j!=endj; ++j)
347 {
348 assert( colMap.find( j.index() ) != colMap.end() );
349 (*j) = colMap[ j.index() ];
350 }
351 }
352 // if entries are equal, just copy
353 else if ( entries.find( row ) == entries.end() )
354 {
355 auto colit = (*rowit).begin();
356 auto endj = (*create).end();
357 for (auto j= (*create).begin(); j!=endj; ++j, ++colit )
358 {
359 assert( colit != (*rowit).end() );
360 (*j) = (*colit);
361 }
362 }
363 else
364 {
365 std::map< int , block_type > oldCols;
366
367 {
368 auto colend = (*rowit).end();
369 for(auto colit = (*rowit).begin(); colit != colend; ++colit)
370 oldCols[ colit.index() ] = 0;
371 }
372
373 auto entry = entries.find( row );
374 assert( entry != entries.end ());
375
376 {
377 auto endcol = (*entry).second.end();
378 for( auto co = (*entry).second.begin(); co != endcol; ++co)
379 oldCols[ (*co).first ] = 0;
380 }
381
382 {
383 auto colend = (*rowit).end();
384 for(auto colit = (*rowit).begin(); colit != colend; ++colit)
385 oldCols[ colit.index() ] += (*colit);
386 }
387
388 {
389 auto endcol = (*entry).second.end();
390 for( auto co = (*entry).second.begin(); co != endcol; ++co)
391 oldCols[ (*co).first ] += (*co).second;
392 }
393
394 auto endj = (*create).end();
395 for (auto j= (*create).begin(); j!=endj; ++j )
396 {
397 auto colEntry = oldCols.find( j.index() );
398 if( colEntry != oldCols.end() )
399 (*j) = (*colEntry).second;
400 else
401 abort();
402 }
403 }
404 }
405 }
406
408 void extractDiagonal( ColBlockVectorType& diag ) const
409 {
410 const auto endi = this->end();
411 for (auto i = this->begin(); i!=endi; ++i)
412 {
413 // get diagonal entry of matrix
414 const auto row = i.index();
415 auto entry = (*i).find( row );
416 const LittleBlockType& block = (*entry);
417 enum { blockSize = LittleBlockType :: rows };
418 for( auto l=0; l<blockSize; ++l )
419 diag[ row ][ l ] = block[ l ][ l ];
420 }
421 }
422
425 field_type operator()(const std::size_t row, const std::size_t col) const
426 {
427 const std::size_t blockRow(row/(LittleBlockType :: rows));
428 const std::size_t localRowIdx(row%(LittleBlockType :: rows));
429 const std::size_t blockCol(col/(LittleBlockType :: cols));
430 const std::size_t localColIdx(col%(LittleBlockType :: cols));
431
432 const auto& matrixRow(this->operator[](blockRow));
433 auto entry = matrixRow.find( blockCol );
434 const LittleBlockType& block = (*entry);
435 return block[localRowIdx][localColIdx];
436 }
437
440 void set(const std::size_t row, const std::size_t col, field_type value)
441 {
442 const std::size_t blockRow(row/(LittleBlockType :: rows));
443 const std::size_t localRowIdx(row%(LittleBlockType :: rows));
444 const std::size_t blockCol(col/(LittleBlockType :: cols));
445 const std::size_t localColIdx(col%(LittleBlockType :: cols));
446
447 auto& matrixRow(this->operator[](blockRow));
448 auto entry = matrixRow.find( blockCol );
449 LittleBlockType& block = (*entry);
450 block[localRowIdx][localColIdx] = value;
451 }
452
454 void print(std::ostream& s=std::cout, unsigned int offset=0) const
455 {
456 s.precision( 6 );
457 const auto endi=this->end();
458 for (auto i=this->begin(); i!=endi; ++i)
459 {
460 const auto endj = (*i).end();
461 for (auto j=(*i).begin(); j!=endj; ++j)
462 if( (*j).infinity_norm() > 1.e-15)
463 s << i.index()+offset << " " << j.index()+offset << " " << *j << std::endl;
464 }
465 }
466 };
467
468
469
470 // ISTLLocalMatrixTraits
471 // ---------------------
472
473 template< class MatrixObject >
474 struct ISTLLocalMatrixTraits
475 {
476 typedef typename MatrixObject::DomainSpaceType DomainSpaceType;
477 typedef typename MatrixObject::RangeSpaceType RangeSpaceType;
478 typedef typename DomainSpaceType::RangeFieldType RangeFieldType;
479
480 typedef ISTLLocalMatrix< MatrixObject > LocalMatrixType;
481 typedef typename MatrixObject::MatrixType::block_type LittleBlockType;
482 };
483
484
485 // ISTLLocalMatrix
486 // ---------------
487
488 template< class MatrixObject >
489 class ISTLLocalMatrix
490 : public LocalMatrixDefault< ISTLLocalMatrixTraits< MatrixObject > >
491 {
492 public:
494 typedef LocalMatrixDefault< ISTLLocalMatrixTraits< MatrixObject > > BaseType;
495
497 typedef MatrixObject MatrixObjectType;
499 typedef typename MatrixObjectType::MatrixType MatrixType;
501 typedef typename MatrixType::block_type LittleBlockType;
502 // type of row and column indices
503 typedef typename MatrixType :: size_type size_type;
504
505 typedef typename MatrixObjectType::DomainSpaceType DomainSpaceType;
506 typedef typename MatrixObjectType::RangeSpaceType RangeSpaceType;
507
508 typedef typename MatrixObjectType::DomainEntityType DomainEntityType;
509 typedef typename MatrixObjectType::RangeEntityType RangeEntityType;
510
512 typedef typename DomainSpaceType::RangeFieldType DofType;
513 typedef typename MatrixType::row_type RowType;
514
516 typedef typename DomainSpaceType::BlockMapperType ColMapperType;
518 typedef typename RangeSpaceType::BlockMapperType RowMapperType;
519
520 static const int littleCols = MatrixObjectType::littleCols;
521 static const int littleRows = MatrixObjectType::littleRows;
522
523 typedef typename MatrixType::size_type Index;
524
528 [[deprecated("Use TemporaryLocalMatrix,LocalContribution and {get,add,set}LocalMatrix")]]
529 ISTLLocalMatrix ( const MatrixObjectType& mObj, const DomainSpaceType& domainSpace, const RangeSpaceType& rangeSpace )
530 : BaseType( domainSpace, rangeSpace ),
531 rowMapper_( rangeSpace.blockMapper() ),
532 colMapper_( domainSpace.blockMapper() ),
533 numRows_( rowMapper_.maxNumDofs() ),
534 numCols_( colMapper_.maxNumDofs() ),
535 matrixObj_( mObj )
536 {}
537
541 [[deprecated("Use TemporaryLocalMatrix,LocalContribution and {get,add,set}LocalMatrix")]]
542 ISTLLocalMatrix ( const ISTLLocalMatrix& org )
543 : BaseType( org ),
544 rowMapper_(org.rowMapper_),
545 colMapper_(org.colMapper_),
546 numRows_( org.numRows_ ),
547 numCols_( org.numCols_ ),
548 matrices_(org.matrices_),
549 matrixObj_(org.matrixObj_)
550 {}
551
553 void init ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity )
554 {
555 // initialize base functions sets
556 BaseType :: init ( domainEntity, rangeEntity );
557
558 numRows_ = rowMapper_.numDofs( rangeEntity );
559 numCols_ = colMapper_.numDofs( domainEntity );
560
561 // resize matrix pointer storage for new row/col numbers
562 matrices_.resize( numRows_ );
563 for( auto& row : matrices_ )
564 {
565 row.resize( numCols_, nullptr );
566 }
567
568 if( matrixObj_.implicitModeActive() )
569 {
570 auto blockAccess = [ this ] ( const std::pair< Index, Index > &index ) -> LittleBlockType&
571 {
572 return matrixObj_.matrix().entry( index.first, index.second );
573 };
574 initBlocks( blockAccess, domainEntity, rangeEntity );
575 }
576 else
577 {
578 auto blockAccess = [ this ] ( const std::pair< Index, Index > &index ) -> LittleBlockType&
579 {
580 return matrixObj_.matrix()[ index.first ][ index.second ];
581 };
582 initBlocks( blockAccess, domainEntity, rangeEntity );
583 }
584 }
585
586 template <class BlockAccess>
587 void initBlocks( BlockAccess& blockAccess, const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity )
588 {
589 auto functor = [ this, &blockAccess ] ( std::pair< int, int > local, const std::pair< Index, Index > &index )
590 {
591 matrices_[ local.first ][ local.second ] = &blockAccess( index );
592 };
593
594 rowMapper_.mapEach( rangeEntity, makePairFunctor( colMapper_, domainEntity, functor ) );
595 }
596
597 private:
598 // check whether given (row,col) pair is valid
599 void check(int localRow, int localCol) const
600 {
601#ifndef NDEBUG
602 const std::size_t row = (int) localRow / littleRows;
603 const std::size_t col = (int) localCol / littleCols;
604 const int lRow = localRow%littleRows;
605 const int lCol = localCol%littleCols;
606 assert( row < matrices_.size() ) ;
607 assert( col < matrices_[row].size() );
608 assert( lRow < littleRows );
609 assert( lCol < littleCols );
610#endif
611 }
612
613 DofType& getValue(const int localRow, const int localCol)
614 {
615 const int row = (int) localRow / littleRows;
616 const int col = (int) localCol / littleCols;
617 const int lRow = localRow%littleRows;
618 const int lCol = localCol%littleCols;
619 return (*matrices_[row][col])[lRow][lCol];
620 }
621
622 public:
623 const DofType get(const int localRow, const int localCol) const
624 {
625 const int row = (int) localRow / littleRows;
626 const int col = (int) localCol / littleCols;
627 const int lRow = localRow%littleRows;
628 const int lCol = localCol%littleCols;
629 return (*matrices_[row][col])[lRow][lCol];
630 }
631
632 void scale (const DofType& scalar)
633 {
634 const size_type nrows = matrices_.size();
635 for(size_type i=0; i<nrows; ++i)
636 {
637 const size_type ncols = matrices_[i].size();
638 for(size_type j=0; j<ncols; ++j)
639 {
640 (*matrices_[i][j]) *= scalar;
641 }
642 }
643 }
644
645 void add(const int localRow, const int localCol , const DofType value)
646 {
647#ifndef NDEBUG
648 check(localRow,localCol);
649#endif
650 getValue(localRow,localCol) += value;
651 }
652
653 void set(const int localRow, const int localCol , const DofType value)
654 {
655#ifndef NDEBUG
656 check(localRow,localCol);
657#endif
658 getValue(localRow,localCol) = value;
659 }
660
662 void unitRow(const int localRow)
663 {
664 const int row = (int) localRow / littleRows;
665 const int lRow = localRow%littleRows;
666
667 // clear row
668 doClearRow( row, lRow );
669
670 // set diagonal entry to 1
671 (*matrices_[row][row])[lRow][lRow] = 1;
672 }
673
675 void clear ()
676 {
677 const size_type nrows = matrices_.size();
678 for(size_type i=0; i<nrows; ++i)
679 {
680 const size_type ncols = matrices_[i].size();
681 for(size_type j=0; j<ncols; ++j)
682 {
683 (*matrices_[i][j]) = (DofType) 0;
684 }
685 }
686 }
687
689 void clearRow ( const int localRow )
690 {
691 const int row = (int) localRow / littleRows;
692 const int lRow = localRow%littleRows;
693
694 // clear the row
695 doClearRow( row, lRow );
696 }
697
699 void resort ()
700 {}
701
702 protected:
704 void doClearRow ( const int row, const int lRow )
705 {
706 // get number of columns
707 const auto col = this->columns();
708 for(auto localCol=0; localCol<col; ++localCol)
709 {
710 const int col = (int) localCol / littleCols;
711 const int lCol = localCol%littleCols;
712 (*matrices_[row][col])[lRow][lCol] = 0;
713 }
714 }
715
716 private:
717 // special mapper omitting block size
718 const RowMapperType& rowMapper_;
719 const ColMapperType& colMapper_;
720
721 // number of local matrices
722 int numRows_;
723 int numCols_;
724
725 // dynamic matrix with pointers to block matrices
726 std::vector< std::vector< LittleBlockType* > > matrices_;
727
728 // matrix to build
729 const MatrixObjectType& matrixObj_;
730 };
731
732
734 template <class DomainSpaceImp, class RangeSpaceImp, class DomainBlock, class RangeBlock >
735 class ISTLMatrixObject
736 {
737 public:
739 typedef DomainSpaceImp DomainSpaceType;
741 typedef RangeSpaceImp RangeSpaceType;
742
744 typedef ISTLMatrixObject< DomainSpaceImp, RangeSpaceImp, DomainBlock, RangeBlock > ThisType;
745 typedef ThisType PreconditionMatrixType;
746
747 typedef typename DomainSpaceType::GridType GridType;
748
749 typedef typename RangeSpaceType :: EntityType RangeEntityType ;
750 typedef typename DomainSpaceType :: EntityType DomainEntityType ;
751
752 enum { littleCols = DomainSpaceType :: localBlockSize };
753 enum { littleRows = RangeSpaceType :: localBlockSize };
754
755 typedef FieldMatrix<typename DomainSpaceType :: RangeFieldType, littleRows, littleCols> LittleBlockType;
756 typedef LittleBlockType block_type;
757 typedef LittleBlockType MatrixBlockType;
758
759 typedef ISTLBlockVectorDiscreteFunction< RangeSpaceType, RangeBlock > RowDiscreteFunctionType;
760 typedef ISTLBlockVectorDiscreteFunction< DomainSpaceType, DomainBlock > ColumnDiscreteFunctionType;
761
762 typedef typename RowDiscreteFunctionType :: DofStorageType RowBlockVectorType;
763 typedef typename ColumnDiscreteFunctionType :: DofStorageType ColumnBlockVectorType;
764
765 typedef typename RangeSpaceType :: BlockMapperType RowMapperType;
766 typedef typename DomainSpaceType :: BlockMapperType ColMapperType;
767
769 typedef ImprovedBCRSMatrix< LittleBlockType , ColumnDiscreteFunctionType , RowDiscreteFunctionType > MatrixType;
770 typedef ISTLParallelMatrixAdapterInterface< MatrixType > MatrixAdapterType;
771
773 typedef ISTLLocalMatrix<ThisType> ObjectType;
774 friend class ISTLLocalMatrix<ThisType>;
775
776 typedef ThisType LocalMatrixFactoryType;
777 typedef ObjectStack< LocalMatrixFactoryType > LocalMatrixStackType;
779 typedef LocalMatrixWrapper< LocalMatrixStackType > LocalMatrixType;
780 typedef ColumnObject< ThisType > LocalColumnObjectType;
781
782 protected:
783 const DomainSpaceType& domainSpace_;
784 const RangeSpaceType& rangeSpace_;
785
786 // special row mapper
787 RowMapperType& rowMapper_;
788 // special col mapper
789 ColMapperType& colMapper_;
790
791 int size_;
792 int sequence_;
793
794 mutable std::unique_ptr< MatrixType > matrix_;
795
796 mutable LocalMatrixStackType localMatrixStack_;
797
798 mutable std::unique_ptr< MatrixAdapterType > matrixAdap_;
799 // overflow fraction for implicit build mode
800 const double overflowFraction_;
801 const bool threading_ ;
802
803 ISTLSolverParameter param_;
804 public:
805 ISTLMatrixObject(const ISTLMatrixObject&) = delete;
806
810 ISTLMatrixObject ( const DomainSpaceType &domainSpace, const RangeSpaceType &rangeSpace, const ISTLSolverParameter& param = ISTLSolverParameter() ) :
811 domainSpace_(domainSpace)
812 , rangeSpace_(rangeSpace)
813 , rowMapper_( rangeSpace.blockMapper() )
814 , colMapper_( domainSpace.blockMapper() )
815 , size_(-1)
816 , sequence_(-1)
817 , localMatrixStack_( *this )
818 , overflowFraction_( param.overflowFraction() )
819 , threading_( param.threading() )
820 , param_( param )
821 {}
822
823 protected:
826 MatrixType& matrix() const
827 {
828 assert( matrix_ );
829 return *matrix_;
830 }
831
832 public:
833 bool threading() const { return threading_; }
834
835 void printTexInfo(std::ostream& out) const
836 {
837 out << "ISTL MatrixObj: ";
838 out << "\\\\ \n";
839 }
840
842 std::string preconditionName() const
843 {
844 return "";
845 }
846
847 void createMatrixAdapter ( const ISTLSolverParameter& param ) const
848 {
849 if( !matrixAdap_ )
850 {
851 matrixAdap_ = ISTLMatrixAdapterFactory< ThisType > :: matrixAdapter( *this, param );
852 }
853 assert( matrixAdap_ );
854 }
855
857 MatrixAdapterType& matrixAdapter( const ISTLSolverParameter& parameter ) const
858 {
859 const ISTLSolverParameter* param = dynamic_cast< const ISTLSolverParameter* > (&parameter);
860 if( param )
861 createMatrixAdapter( *param );
862 else
863 {
864 ISTLSolverParameter newparam( parameter );
865 createMatrixAdapter( newparam );
866 }
867
868 finalizeAssembly();
869 return *matrixAdap_;
870 }
871
873 MatrixAdapterType& matrixAdapter() const
874 {
875 return matrixAdapter( param_ );
876 }
877
878 public:
879 MatrixType& exportMatrix() const
880 {
881 finalizeAssembly();
882 return matrix();
883 }
884
885 bool implicitModeActive() const
886 {
887 // implicit build mode is only active when the
888 // build mode of the matrix is implicit and the
889 // matrix is currently being build
890
891 if( matrix().buildMode() == MatrixType::implicit && matrix().buildStage() == MatrixType::building )
892 return true;
893 else
894 return false;
895 }
896
897 void finalizeAssembly() const
898 {
899 // finalize build mode
900 const_cast< ThisType& > (*this).compress();
901 }
902
903 // compress matrix if not already done before and only in implicit build mode
904 void compress( )
905 {
906 if( implicitModeActive() )
907 {
908 matrix().compress();
909 }
910 }
911
913 void clear()
914 {
915 matrix().clear();
916 // clean matrix adapter and other helper classes
917 removeObj();
918 }
919
920 void unitRow( const size_t row )
921 {
922 matrix().unitRow( row );
923 }
924
925 protected:
926 template <class Container> // could be std::set or std::vector
927 void setUnitRowImpl( const Container &rows, const double diagonal )
928 {
929 for (const auto& r : rows)
930 {
931 const std::size_t blockRow( r/(LittleBlockType :: rows) );
932 const std::size_t localRowIdx( r%(LittleBlockType :: rows) );
933 auto& row = matrix()[blockRow];
934 const auto endcol = row.end();
935#ifndef NDEBUG
936 bool set = false;
937#endif
938 for (auto col=row.begin(); col!=endcol; ++col)
939 {
940 for (auto& entry : (*col)[localRowIdx])
941 entry = 0;
942 if (col.index() == blockRow)
943 {
944 (*col)[localRowIdx][localRowIdx] = diagonal;
945#ifndef NDEBUG
946 set = true;
947#endif
948 }
949 }
950 assert(set);
951 }
952 }
953
954 public:
955 template <class Container>
956 void setUnitRows( const Container& unitRows, const Container& auxRows )
957 {
958 setUnitRowImpl( unitRows, 1.0 );
959 setUnitRowImpl( auxRows, 0.0 );
960 }
961
963 void reserve()
964 {
965 reserve( Stencil<DomainSpaceType,RangeSpaceType>(domainSpace_, rangeSpace_), true );
966 }
967
969 template <class Set>
970 void reserve (const std::vector< Set >& sparsityPattern )
971 {
972 reserve( StencilWrapper< DomainSpaceType,RangeSpaceType, Set >( sparsityPattern ), false );
973 }
974
976 template <class Stencil>
977 void reserve(const Stencil &stencil, const bool proposeImplicit = true )
978 {
979 // if grid sequence number changed, rebuild matrix
980 if(sequence_ != domainSpace().sequence())
981 {
982 removeObj();
983
984 // do not use implicit build mode when multi threading is enabled
985 const bool implicit = proposeImplicit && MPIManager::numThreads() == 1;
986 if( implicit )
987 {
988 auto nnz = stencil.maxNonZerosEstimate();
989 if( nnz == 0 )
990 {
991 if (domainSpace_.begin() != domainSpace_.end() && rangeSpace_.begin() != rangeSpace_.end())
992 {
993 Stencil tmpStencil( stencil );
994 tmpStencil.fill( *(domainSpace_.begin()), *(rangeSpace_.begin()) );
995 nnz = tmpStencil.maxNonZerosEstimate();
996 }
997 }
998 matrix_.reset( new MatrixType( rowMapper_.size(), colMapper_.size(), nnz, overflowFraction_ ) );
999 }
1000 else
1001 {
1002 matrix_.reset( new MatrixType( rowMapper_.size(), colMapper_.size() ) );
1003 matrix().createEntries( stencil.globalStencil() );
1004 }
1005
1006 sequence_ = domainSpace().sequence();
1007 }
1008 }
1009
1011 template <class HangingNodesType>
1012 void changeHangingNodes(const HangingNodesType& hangingNodes)
1013 {
1014 // create new matrix
1015 MatrixType* newMatrix = new MatrixType(rowMapper_.size(), colMapper_.size());
1016
1017 // setup with hanging rows
1018 newMatrix->setup( *matrix_ , hangingNodes );
1019
1020 // remove old matrix
1021 removeObj();
1022
1023 // store new matrix
1024 matrix_.reset( newMatrix );
1025 }
1026
1029 void extractDiagonal( ColumnDiscreteFunctionType& diag ) const
1030 {
1031 // extract diagonal entries
1032 matrix().extractDiagonal( diag.blockVector() );
1033 }
1034
1036 bool rightPrecondition() const
1037 {
1038 return false;
1039 }
1040
1042 void apply(const ColumnDiscreteFunctionType& arg, RowDiscreteFunctionType& dest) const
1043 {
1044 matrixAdapter().apply( arg.blockVector(), dest.blockVector() );
1045 }
1046
1048 template <class CDF, class RDF>
1049 void apply(const CDF& arg, RDF& dest) const
1050 {
1051 // this can happen when different storages are used for discrete
1052 // function and matrix/solver objects
1053 DUNE_THROW(NotImplemented,"ISTLMatrixObj::apply called for DiscreteFunctions not specified in the template list");
1054 }
1055
1057 void resort()
1058 {}
1059
1062 void createPreconditionMatrix()
1063 {}
1064
1066 void print(std::ostream & s) const
1067 {
1068 matrix().print(s);
1069 }
1070
1071 const DomainSpaceType& domainSpace() const
1072 {
1073 return domainSpace_;
1074 }
1075 const RangeSpaceType& rangeSpace() const
1076 {
1077 return rangeSpace_;
1078 }
1079
1080 const RowMapperType& rowMapper() const
1081 {
1082 return rowMapper_;
1083 }
1084 const ColMapperType& colMapper() const
1085 {
1086 return colMapper_;
1087 }
1088
1090 ObjectType* newObject() const
1091 {
1092 return new ObjectType(*this, domainSpace(), rangeSpace());
1093 }
1094
1099 [[deprecated("Use TemporaryLocalMatrix,LocalContribution and {get,add,set}LocalMatrix")]]
1100 LocalMatrixType localMatrix( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity ) const
1101 {
1102 return LocalMatrixType( localMatrixStack_, domainEntity, rangeEntity );
1103 }
1104
1109 [[deprecated("Use TemporaryLocalMatrix,LocalContribution and {get,add,set}LocalMatrix")]]
1110 LocalMatrixType localMatrix() const
1111 {
1112 return LocalMatrixType( localMatrixStack_ );
1113 }
1114
1115 LocalColumnObjectType localColumn( const DomainEntityType &domainEntity ) const
1116 {
1117 return LocalColumnObjectType ( *this, domainEntity );
1118 }
1119
1120 protected:
1121 template< class LocalBlock, class Operation >
1122 void applyToBlock ( const size_t row, const size_t col,
1123 const LocalBlock &localBlock,
1124 Operation& operation )
1125 {
1126 LittleBlockType& block = ( implicitModeActive() ) ? matrix().entry( row, col ) : matrix()[ row ][ col ];
1127 for( int i = 0; i < littleRows; ++i )
1128 for( int j = 0; j < littleCols; ++j )
1129 operation( block[ i ][ j ], localBlock[ i ][ j ] );
1130 }
1131
1132 template< class LocalBlock >
1133 void setBlock ( const size_t row, const size_t col,
1134 const LocalBlock &localBlock )
1135 {
1136 typedef typename DomainSpaceType :: RangeFieldType Field;
1137 auto copy = [] ( Field& a, const typename LocalBlock::field_type& b ) { a = b; };
1138 applyToBlock( row, col, localBlock, copy );
1139 }
1140
1141 template< class LocalBlock >
1142 void addBlock ( const size_t row, const size_t col,
1143 const LocalBlock &localBlock )
1144 {
1145 typedef typename DomainSpaceType :: RangeFieldType Field;
1146 auto add = [] ( Field& a, const typename LocalBlock::field_type& b ) { a += b; };
1147 applyToBlock( row, col, localBlock, add );
1148 }
1149
1150 public:
1151 template< class LocalMatrix, class Operation >
1152 void applyToLocalMatrix ( const DomainEntityType &domainEntity,
1153 const RangeEntityType &rangeEntity,
1154 const LocalMatrix &localMat,
1155 Operation& operation )
1156 {
1157 typedef typename MatrixType::size_type Index;
1158 if( implicitModeActive() )
1159 {
1160 auto blockAccess = [ this ] ( const std::pair< Index, Index > &index ) -> LittleBlockType&
1161 {
1162 return matrix().entry( index.first, index.second );
1163 };
1164 auto functor = [ &localMat, blockAccess, operation ] ( std::pair< int, int > local, const std::pair< Index, Index > &index )
1165 {
1166 LittleBlockType& block = blockAccess( index );
1167 for( int i = 0; i < littleRows; ++i )
1168 for( int j = 0; j < littleCols; ++j )
1169 operation( block[ i ][ j ], localMat.get( local.first * littleRows + i, local.second *littleCols + j ) );
1170 };
1171 rowMapper_.mapEach( rangeEntity, makePairFunctor( colMapper_, domainEntity, functor ) );
1172 }
1173 else
1174 {
1175 auto blockAccess = [ this ] ( const std::pair< Index, Index > &index ) -> LittleBlockType&
1176 {
1177 return matrix()[ index.first][ index.second ];
1178 };
1179 auto functor = [ &localMat, blockAccess, operation ] ( std::pair< int, int > local, const std::pair< Index, Index > &index )
1180 {
1181 LittleBlockType& block = blockAccess( index );
1182 for( int i = 0; i < littleRows; ++i )
1183 for( int j = 0; j < littleCols; ++j )
1184 operation( block[ i ][ j ], localMat.get( local.first * littleRows + i, local.second *littleCols + j ) );
1185 };
1186 rowMapper_.mapEach( rangeEntity, makePairFunctor( colMapper_, domainEntity, functor ) );
1187 }
1188 }
1189
1190 template< class LocalMatrix >
1191 void setLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat )
1192 {
1193 typedef typename DomainSpaceType :: RangeFieldType RangeFieldType;
1194 auto operation = [] ( RangeFieldType& a, const RangeFieldType& b )
1195 {
1196 a = b;
1197 };
1198 applyToLocalMatrix( domainEntity, rangeEntity, localMat, operation );
1199 }
1200
1201 template< class LocalMatrix >
1202 void addLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat )
1203 {
1204 typedef typename DomainSpaceType :: RangeFieldType RangeFieldType;
1205 auto operation = [] ( RangeFieldType& a, const RangeFieldType& b )
1206 {
1207 a += b;
1208 };
1209 applyToLocalMatrix( domainEntity, rangeEntity, localMat, operation );
1210 }
1211
1212 template< class LocalMatrix, class Scalar >
1213 void addScaledLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat, const Scalar &s )
1214 {
1215 typedef typename DomainSpaceType :: RangeFieldType RangeFieldType;
1216 auto operation = [ &s ] ( RangeFieldType& a, const RangeFieldType& b )
1217 {
1218 a += s * b;
1219 };
1220 applyToLocalMatrix( domainEntity, rangeEntity, localMat, operation );
1221 }
1222
1223 template< class LocalMatrix >
1224 void getLocalMatrix ( const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, LocalMatrix &localMat ) const
1225 {
1226 // make sure that matrix is in compressed state if build mode is implicit
1227 finalizeAssembly();
1228
1229 typedef typename MatrixType::size_type Index;
1230 auto functor = [ &localMat, this ] ( std::pair< int, int > local, const std::pair< Index, Index > &global )
1231 {
1232 for( std::size_t i = 0; i < littleRows; ++i )
1233 for( std::size_t j = 0; j < littleCols; ++j )
1234 localMat.set( local.first * littleRows + i, local.second *littleCols + j,
1235 matrix()[ global.first ][ global.second ][i][j] );
1236 };
1237
1238 rowMapper_.mapEach( rangeEntity, makePairFunctor( colMapper_, domainEntity, functor ) );
1239 }
1240
1241 protected:
1242 void preConErrorMsg(int preCon) const
1243 {
1244 exit(1);
1245 }
1246
1247 void removeObj ()
1248 {
1249 matrixAdap_.reset( nullptr );
1250 }
1251 };
1252
1253 } // namespace Fem
1254
1255} // namespace Dune
1256
1257#endif // #if HAVE_DUNE_ISTL
1258
1259#endif // #ifndef DUNE_FEM_ISTLMATRIXWRAPPER_HH
Implementation of the BCRSMatrix class.
This file implements a vector space as a tensor product of a given vector space. The number of compon...
vector space out of a tensor product of fields.
Definition: fvector.hh:97
A few common exception classes.
Implements a matrix constructed from a given type representing a field and compile-time given number ...
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
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
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
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22
Define general preconditioner interface.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 21, 12:01, 2026)