DUNE-FEM (unstable)

istlpreconditioner.hh
1#ifndef DUNE_FEM_ISTLPRECONDITIONERWRAPPER_HH
2#define DUNE_FEM_ISTLPRECONDITIONERWRAPPER_HH
3
4#include <memory>
5#include <type_traits>
6
7// standard diagonal preconditioner
8#include <dune/fem/solver/diagonalpreconditioner.hh>
9
10#if HAVE_DUNE_ISTL
12
15
17#include <dune/istl/paamg/pinfo.hh>
18#endif
19
20#include <dune/fem/solver/parameter.hh> // SolverParameter
21#include <dune/fem/operator/matrix/istlmatrixadapter.hh>
22#include <dune/fem/misc/fmatrixconverter.hh>
23#include <dune/fem/function/blockvectors/defaultblockvectors.hh>
24
25namespace Dune
26{
27
28 namespace Fem
29 {
30
31 struct ISTLPreconditionMethods
32 {
33 static std::vector< int > supportedPreconditionMethods() {
34 return std::vector< int > ({ SolverParameter::none, // no preconditioner
35 SolverParameter::ssor, // SSOR preconditioner
36 SolverParameter::sor , // SOR preconditioner
37 SolverParameter::ilu , // ILU preconditioner
38 SolverParameter::gauss_seidel,// Gauss-Seidel preconditioner
39 SolverParameter::jacobi, // Jacobi preconditioner
40 SolverParameter::amg_ilu, // AMG with ILU-0 smoother (deprecated)
41 SolverParameter::amg_jacobi, // AMG with Jacobi smoother
42 SolverParameter::ildl // ILDL from istl
43 });
44 }
45 };
46
47
48 template <class MatrixImp>
49 class LagrangeParallelMatrixAdapter;
50
51 template <class MatrixImp>
52 class LagrangeParallelMatrixAdapter;
53
54 template <class MatrixImp>
55 class DGParallelMatrixAdapter;
56
57 struct ISTLSolverParameter : public LocalParameter< SolverParameter, ISTLSolverParameter >
58 {
59 typedef LocalParameter< SolverParameter, ISTLSolverParameter > BaseType;
60 public:
61 using BaseType :: parameter ;
62 using BaseType :: keyPrefix ;
63
64 ISTLSolverParameter( const ParameterReader &parameter = Parameter::container() )
65 : BaseType( parameter )
66 {}
67
68 ISTLSolverParameter( const std::string &keyPrefix, const ParameterReader &parameter = Parameter::container() )
69 : BaseType( keyPrefix, parameter )
70 {}
71
72 ISTLSolverParameter( const SolverParameter& sp )
73 : ISTLSolverParameter( sp.keyPrefix(), sp.parameter() )
74 {}
75
76 virtual double overflowFraction () const
77 {
78 return parameter().getValue< double >( keyPrefix() + "matrix.overflowfraction", 1.0 );
79 }
80
81 virtual bool fastILUStorage () const
82 {
83 return parameter().getValue< bool >( keyPrefix() + "preconditioning.fastilustorage", true );
84 }
85 };
86
87#if HAVE_DUNE_ISTL
96 template< class MatrixObject, class X, class Y, int method, int l=1 >
97 class ParallelIterative : public Preconditioner<X,Y>
98 {
99 public:
100 typedef typename MatrixObject :: ColumnDiscreteFunctionType DiscreteFunctionType ;
101
102 protected:
103 typedef typename X::field_type field_type;
104 typedef typename MatrixObject::MatrixType MatrixType;
105 typedef MatrixType M;
106 typedef typename M::block_type MatrixBlockType;
107
108 typedef typename DiscreteFunctionType :: DiscreteFunctionSpaceType DiscreteFunctionSpaceType ;
109 typedef typename DiscreteFunctionSpaceType:: DomainFieldType DomainFieldType;
110
111 static const bool isNumber = (M::block_type::rows == M::block_type::cols) && (M::block_type::rows == 1);
112
113 typedef FieldVector< field_type, MatrixBlockType::rows*MatrixBlockType::cols > FlatMatrixBlock;
114 // BlockVector from dune-istl
115 typedef BlockVector< FlatMatrixBlock > DiagonalType;
116
117 typedef FieldMatrixConverter< FlatMatrixBlock, MatrixBlockType > MatrixConverterType;
118
119 // Implementation of SOR and Jacobi's method
120 // Note: for SOR we have xnew == xold
121 template <class rowiterator, bool forward>
122 void iterate (const M& A, X& xnew, const X& xold, const Y& b, const field_type& w,
123 const DiagonalType& diagInv,
124 rowiterator i,
125 const rowiterator endi,
126 const std::integral_constant<bool, forward> fb ) const
127 {
128 typedef typename M::ConstColIterator coliterator;
129
130 typedef typename Y::block_type bblock;
131 typedef typename X::block_type xblock;
132
133 bblock rhs;
134 xblock v;
135
136 // Initialize nested data structure if there are entries
137 if( i != endi )
138 v=xnew[0];
139
140 const bool hasDiagInv = diagInv.size() > 0 ;
141
142 const auto nextRow = [&i]()
143 {
144 // increment/decrement iterator
145 if constexpr ( forward )
146 ++i;
147 else
148 --i;
149 };
150
151 for (; i!=endi; nextRow() )
152 {
153 const coliterator endj=(*i).end(); // iterate over a_ij with j < i
154 coliterator j=(*i).begin();
155 const auto rowIdx = i.index();
156
157 // treat missing rows as unit rows
158 if( j == endj )
159 {
160 xnew[rowIdx] += w*b[rowIdx];
161 continue ;
162 }
163
164 rhs = b[rowIdx]; // rhs = b_i
165 if constexpr (isNumber)
166 {
167 // note that for SOR xnew == xold
168 for (; j.index()<rowIdx; ++j)
169 rhs -= (*j) * xold[j.index()]; // rhs -= sum_{j<i} a_ij * x_j
170
171 // not needed, since we store the diagonal separately
172 coliterator diag=j; // *diag = a_ii
173 for (; j!=endj; ++j)
174 rhs -= (*j) * xold[j.index()]; // rhs -= sum_{j<i} a_ij * x_j
175
176 // v = rhs / diag
177 if( hasDiagInv )
178 v = rhs * diagInv[ rowIdx ];
179 else
180 v = rhs / (*diag);
181
182 xnew[ rowIdx ] += w*v; // x_i = w / a_ii * (b_i - sum_{j<i} a_ij * xnew_j - sum_{j>=i} a_ij * xold_j)
183 }
184 else
185 {
186 // note that for SOR xnew == xold
187 for (; j.index()<rowIdx; ++j)
188 (*j).mmv(xold[j.index()],rhs); // rhs -= sum_{j<i} a_ij * x_j
189 coliterator diag=j; // *diag = a_ii
190 for (; j!=endj; ++j)
191 (*j).mmv(xold[j.index()],rhs); // rhs -= sum_{j<i} a_ij * x_j
192
193 // v = rhs / diag
194 if( hasDiagInv )
195 {
196 MatrixConverterType m( diagInv[ rowIdx ] );
197 m.solve( v, rhs );
198 }
199 else
200 (*diag).solve(v, rhs);
201 xnew[rowIdx].axpy(w,v); // x_i = w / a_ii * (b_i - sum_{j<i} a_ij * xnew_j - sum_{j>=i} a_ij * xold_j)
202 }
203 }
204 }
205
206 // Implementation of SOR and Jacobi's method
207 // Note: for SOR we have xnew == xold
208 void forwardIterate (const M& A, X& xnew, const X& xold, const Y& b, const field_type& w,
209 const DiagonalType& diagInv ) const
210 {
211 bool runParallel = threading_ && (&xnew != &xold); // Jacobi only
212
213 if( runParallel )
214 {
215 auto doIterate = [this, &A, &xnew, &xold, &b, &w, &diagInv] ()
216 {
217 const auto slice = A.sliceBeginEnd( MPIManager::thread(), MPIManager::numThreads() );
218 // standard forwards iteration
219 iterate( A, xnew, xold, b, w, diagInv,
220 A.slicedBegin( slice.first ), A.slicedEnd( slice.second ), std::true_type() );
221 };
222
223 try {
224 // execute in parallel
225 MPIManager :: run ( doIterate );
226 }
227 catch ( const SingleThreadModeError& e )
228 {
229 runParallel = false;
230 }
231 }
232
233 if( ! runParallel )
234 {
235 // serial version
236 iterate( A, xnew, xold, b, w, diagInv, A.begin(), A.end(), std::true_type() );
237 }
238 }
239
240 // Implementation of SOR and Jacobi's method
241 // Note: for SOR we have xnew == xold
242 void backwardIterate (const M& A, X& xnew, const X& xold, const Y& b, const field_type& w,
243 const DiagonalType& diagInv ) const
244 {
245 // backwards iteration (use r-iterators)
246 iterate( A, xnew, xold, b, w, diagInv, A.beforeEnd(), A.beforeBegin(), std::false_type() );
247 }
248
249 protected:
250 const MatrixObject& mObj_;
251 const MatrixType& _A_;
252 const int _n;
253 const double _w;
254
255 DiagonalType diagonalInv_;
256
257 const bool threading_;
258
259 public:
260 ParallelIterative( const MatrixObject& mObj, int n=1, double relax=1.0, const bool verbose=false )
261 : mObj_( mObj ),
262 _A_( mObj.exportMatrix() ),
263 _n( n ), _w(relax),
264 threading_( mObj.threading() )
265 {
266 if ( verbose )
267 {
268 std::string name = SolverParameter::preconditionMethodTable( method );
269 std::cout << "Using ParallelIterative(" << name << "): it = " << n << ", w = "<< relax << std::endl;
270 }
271
273
274 const auto& space = mObj_.domainSpace();
275 if( space.continuous() )
276 {
277 // create BlockVectorWrapper for BlockVector
278 ISTLBlockVector< FlatMatrixBlock > diagonalInv( &diagonalInv_ );
279
280 diagonalInv.resize(space.blockMapper().size());
281 assert( space.blockMapper().size() == _A_.N() );
282 diagonalInv.clear();
283
284 // extract diagonal elements from matrix object
285 {
286 const auto end = _A_.end();
287 for( auto row = _A_.begin(); row != end; ++row )
288 {
289 // get diagonal entry of matrix if existent
290 auto diag = (*row).find( row.index() );
291 if( diag != (*row).end() )
292 {
293 MatrixConverterType m( diagonalInv[ row.index() ] );
294 m = (*diag);
295 }
296 }
297 }
298
299 // make diagonal consistent (communicate at border dofs)
300 // get default communication operation type
301 typename DiscreteFunctionSpaceType :: template
302 CommDataHandle< DiscreteFunctionType > :: OperationType operation;
303 space.communicate( diagonalInv, operation );
304
305 // In general: store 1/diag if diagonal is number
306 //
307 // note: We set near-zero entries to 1 to avoid NaNs. Such entries occur
308 // if DoFs are excluded from matrix setup
309 if constexpr( isNumber )
310 {
311 const double eps = 16.*std::numeric_limits< double >::epsilon();
312 for( auto& diag : diagonalInv )
313 {
314 diag = (std::abs( diag ) < eps ? 1. : 1. / diag );
315 }
316 }
317 }
318 }
319
320 ParallelIterative( const ParallelIterative& org )
321 : mObj_( org.mObj_ ),
322 _A_( org._A_ ),
323 _n( org._n ), _w( org._w ),
324 diagonalInv_( org.diagonalInv_ )
325 {
326 }
327
329 void pre (X& x, Y& b) override {}
330
332 void apply (X& v, const Y& d) override
333 {
334 const auto& space = mObj_.domainSpace();
335 const bool continuous = space.continuous();
336
337 // for communication
338 DiscreteFunctionType tmp("ParIt::apply", space, v );
339
340 static constexpr bool jacobi = (method == SolverParameter::jacobi);
341
342 std::unique_ptr< X > xTmp;
343 if constexpr ( jacobi )
344 xTmp.reset( new X(v) );
345
346 X& x = (jacobi) ? (*xTmp) : v;
347
348 for (int i=0; i<_n; ++i)
349 {
350 forwardIterate(_A_, v, x, d, _w, diagonalInv_ );
351
352 if constexpr ( method == SolverParameter::ssor )
353 {
354 // seems not to be necessary
355 // communicate border unknowns
356 //tmp.communicate();
357
358 // create symmetry by iterating backwards
359 backwardIterate(_A_, v, x, d, _w, diagonalInv_ );
360 }
361
362 // communicate border unknowns
363 tmp.communicate();
364
365 // for Jacobi now update the result
366 if constexpr ( jacobi )
367 {
368 x = v;
369 // for Jacobi skip last communication since this
370 // is already in consistent state at this point
371 if( continuous && i == _n-1)
372 continue ;
373 }
374 }
375 }
376
378 void post (X& x) override {}
379
381 SolverCategory::Category category () const override { return SolverCategory::sequential; }
382 };
383
384 template< class MatrixObject, class X, class Y >
385 using ParallelSOR = ParallelIterative< MatrixObject, X, Y, SolverParameter::sor>;
386
387 template< class MatrixObject, class X, class Y >
388 using ParallelSSOR = ParallelIterative< MatrixObject, X, Y, SolverParameter::ssor>;
389
390 template< class MatrixObject, class X, class Y >
391 using ParallelJacobi = ParallelIterative< MatrixObject, X, Y, SolverParameter::jacobi>;
392
393 template< class X, class Y >
394 class IdentityPreconditionerWrapper : public Preconditioner<X,Y>
395 {
396 public:
398 typedef X domain_type;
400 typedef Y range_type;
402 typedef typename X::field_type field_type;
403
405 IdentityPreconditionerWrapper(){}
406
408 void pre (X& x, Y& b) override {}
409
411 void apply (X& v, const Y& d) override
412 {
413 if constexpr ( std::is_same< X, Y> :: value )
414 {
415 v = d;
416 }
417 }
418
420 void post (X& x) override {}
421
422 SolverCategory::Category category () const override { return SolverCategory::sequential; }
423 };
424
425
429 template<class MatrixImp>
430 class PreconditionerWrapper
431 : public Preconditioner<typename MatrixImp :: RowBlockVectorType,
432 typename MatrixImp :: ColBlockVectorType>
433 {
434 typedef MatrixImp MatrixType;
435 typedef typename MatrixType :: RowBlockVectorType X;
436 typedef typename MatrixType :: ColBlockVectorType Y;
437
438 // use BCRSMatrix type because of specializations in dune-istl
439 typedef typename MatrixType :: BaseType ISTLMatrixType ;
440
441 typedef typename MatrixType :: CommunicationType
442 CommunicationType;
443
444 // matrix adapter for AMG
445 //#if HAVE_MPI
446 // typedef Dune::OverlappingSchwarzOperator<
447 // ISTLMatrixType, X, Y, CommunicationType> OperatorType ;
448 //#else
449 typedef MatrixAdapter< ISTLMatrixType, X, Y > OperatorType;
450 //#endif
451 mutable std::shared_ptr< OperatorType > op_;
452
453 // auto pointer to preconditioning object
454 typedef Preconditioner<X,Y> PreconditionerInterfaceType;
455 mutable std::shared_ptr<PreconditionerInterfaceType> preconder_;
456
457 // flag whether we have preconditioning, and if yes if it is AMG
458 const int preEx_;
459 const bool verbose_;
460
461 template <class XImp, class YImp>
462 struct Apply
463 {
464 inline static void apply(PreconditionerInterfaceType& preconder,
465 XImp& v, const YImp& d)
466 {
467 }
468
469 inline static void copy(XImp& v, const YImp& d)
470 {
471 }
472 };
473
474 template <class XImp>
475 struct Apply<XImp,XImp>
476 {
477 inline static void apply(PreconditionerInterfaceType& preconder,
478 XImp& v, const XImp& d)
479 {
480 preconder.apply( v ,d );
481 }
482
483 inline static void copy(X& v, const Y& d)
484 {
485 v = d;
486 }
487 };
488 public:
490 typedef X domain_type;
492 typedef Y range_type;
494 typedef typename X::field_type field_type;
495
497 PreconditionerWrapper (const PreconditionerWrapper& org, bool verbose)
498 : op_( org.op_ )
499 , preconder_(org.preconder_)
500 , preEx_(org.preEx_)
501 , verbose_( verbose )
502 {
503 }
504
506 PreconditionerWrapper(bool verbose)
507 : op_()
508 , preconder_()
509 , preEx_( 0 )
510 , verbose_( verbose )
511 {}
512
514 template <class PreconditionerType>
515 PreconditionerWrapper(MatrixType & matrix,
516 int iter,
517 field_type relax,
518 bool verbose,
519 const PreconditionerType* p)
520 : op_()
521 , preconder_( new PreconditionerType( matrix, iter, relax ) )
522 , preEx_( 1 )
523 , verbose_( verbose )
524 {
525 }
526
527
530 template <class PreconditionerType>
531 PreconditionerWrapper(MatrixType & matrix, bool verbose,
532 PreconditionerType* p)
533 : op_()
534 , preconder_( p )
535 , preEx_( 1 )
536 , verbose_( verbose )
537 {
538 }
539
541 template <class PreconditionerType>
542 PreconditionerWrapper(MatrixType & matrix,
543 int iter,
544 field_type relax,
545 bool verbose,
546 const PreconditionerType* p ,
547 const CommunicationType& comm)
548 //#if HAVE_MPI
549 // : op_( new OperatorType( matrix, comm ) )
550 //#else
551 : op_( new OperatorType( matrix ) )
552 //#endif
553 , preconder_( createAMGPreconditioner(comm, iter, relax, p) )
554 , preEx_( 2 )
555 , verbose_( verbose )
556 {
557 }
558
560 void pre (X& x, Y& b) override
561 {
562 // all the sequentiel implemented Preconditioners do nothing in pre and post
563 // apply preconditioner
564 if( preEx_ > 1 )
565 {
566 //X tmp (x);
567 preconder_->pre(x,b);
568 //assert( std::abs( x.two_norm() - tmp.two_norm() ) < 1e-15);
569 }
570 }
571
573 void apply (X& v, const Y& d) override
574 {
575 if( preEx_ )
576 {
577 // apply preconditioner
578 Apply<X,Y>::apply( *preconder_ , v, d );
579 }
580 else
581 {
582 Apply<X,Y>::copy( v, d );
583 }
584 }
585
587 void post (X& x) override
588 {
589 // all the implemented Preconditioners do nothing in pre and post
590 // apply preconditioner
591 if( preEx_ > 1 )
592 {
593 preconder_->post(x);
594 }
595 }
596
598 SolverCategory::Category category () const override
599 {
600 return (preconder_ ? preconder_->category() : SolverCategory::sequential);
601 }
602
603 protected:
604 template <class Smoother>
605 PreconditionerInterfaceType*
606 createAMGPreconditioner(const CommunicationType& comm,
607 int iter, field_type relax, const Smoother* )
608 {
609 typedef typename Dune::FieldTraits< field_type>::real_type real_type;
610 typedef typename std::conditional< std::is_convertible<field_type,real_type>::value,
614
615 typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs;
616
617 SmootherArgs smootherArgs;
618
619 smootherArgs.iterations = iter;
620 smootherArgs.relaxationFactor = relax ;
621
622 int coarsenTarget=1200;
623 Criterion criterion(15,coarsenTarget);
624 criterion.setDefaultValuesIsotropic(2);
625 criterion.setAlpha(.67);
626 criterion.setBeta(1.0e-8);
627 criterion.setMaxLevel(10);
628 if( verbose_ && Parameter :: verbose() )
629 criterion.setDebugLevel( 1 );
630 else
631 criterion.setDebugLevel( 0 );
632
633 /*
634 if( comm.size() > 1 )
635 {
636 typedef Dune::OwnerOverlapCopyCommunication<int> ParallelInformation;
637 ParallelInformation pinfo(MPI_COMM_WORLD);
638 typedef Dune::Amg::AMG<OperatorType, X, Smoother, ParallelInformation> AMG;
639 return new AMG(*op_, criterion, smootherArgs, pinfo);
640 }
641 else
642 */
643 {
644 // X == Y is needed for AMG
646 return new AMG(*op_, criterion, smootherArgs);
647 //return new AMG(*op_, criterion, smootherArgs, 1, 1, 1, false);
648 }
649 }
650 };
651
652
653 // ISTLPreconditionerFactory
654 // -------------------------
655
656 template < class MatrixObject >
657 class ISTLMatrixAdapterFactory ;
658
659 template < class DomainSpace, class RangeSpace, class DomainBlock, class RangeBlock,
660 template <class, class, class, class> class MatrixObject >
661 class ISTLMatrixAdapterFactory< MatrixObject< DomainSpace, RangeSpace, DomainBlock, RangeBlock > >
662 {
663 typedef DomainSpace DomainSpaceType ;
664 typedef RangeSpace RangeSpaceType;
665
666 public:
667 typedef MatrixObject< DomainSpaceType, RangeSpaceType, DomainBlock, RangeBlock > MatrixObjectType;
668 typedef typename MatrixObjectType :: MatrixType MatrixType;
669 typedef ISTLParallelMatrixAdapterInterface< MatrixType > MatrixAdapterInterfaceType;
670
672 static std::unique_ptr< MatrixAdapterInterfaceType >
673 matrixAdapter( const MatrixObjectType& matrixObj,
674 const ISTLSolverParameter& param)
675 {
676 std::unique_ptr< MatrixAdapterInterfaceType > ptr;
677 if( matrixObj.domainSpace().continuous() )
678 {
679 typedef LagrangeParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
680 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *) nullptr, param ) );
681 }
682 else
683 {
684 typedef DGParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
685 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *) nullptr, param ) );
686 }
687 return ptr;
688 }
689
690 protected:
691 template <class MatrixAdapterType>
692 static MatrixAdapterType*
693 matrixAdapterObject( const MatrixObjectType& matrixObj,
694 const MatrixAdapterType*,
695 const ISTLSolverParameter& param )
696 {
697 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
698 return new MatrixAdapterType( matrixObj.exportMatrix(),
699 matrixObj.domainSpace(), matrixObj.rangeSpace(), PreConType(param.verbose()),
700 matrixObj.threading() );
701 }
702
703 };
704
705#ifndef DISABLE_ISTL_PRECONDITIONING
707 template < class Space, class DomainBlock, class RangeBlock,
708 template <class, class, class, class> class MatrixObject >
709 class ISTLMatrixAdapterFactory< MatrixObject< Space, Space, DomainBlock, RangeBlock > >
710 {
711 public:
712 typedef Space DomainSpaceType ;
713 typedef Space RangeSpaceType;
714
715 typedef MatrixObject< DomainSpaceType, RangeSpaceType, DomainBlock, RangeBlock > MatrixObjectType;
716 typedef typename MatrixObjectType :: MatrixType MatrixType;
717 typedef typename MatrixType :: BaseType ISTLMatrixType ;
718 typedef Fem::PreconditionerWrapper< MatrixType > PreconditionAdapterType;
719
720 protected:
721 template <class MatrixAdapterType, class PreconditionerType>
722 static MatrixAdapterType*
723 createMatrixAdapter(const MatrixAdapterType*,
724 const PreconditionerType* preconditioning,
725 MatrixType& matrix,
726 const DomainSpaceType& domainSpace,
727 const RangeSpaceType& rangeSpace,
728 const double relaxFactor,
729 std::size_t numIterations,
730 bool verbose)
731 {
732 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
733 PreConType preconAdapter(matrix, numIterations, relaxFactor, verbose, preconditioning );
734 return new MatrixAdapterType(matrix, domainSpace, rangeSpace, preconAdapter );
735 }
736
737 template <class MatrixAdapterType, class PreconditionerType>
738 static MatrixAdapterType*
739 createAMGMatrixAdapter(const MatrixAdapterType*,
740 const PreconditionerType* preconditioning,
741 MatrixType& matrix,
742 const DomainSpaceType& domainSpace,
743 const RangeSpaceType& rangeSpace,
744 const double relaxFactor,
745 std::size_t numIterations,
746 bool solverVerbose)
747 {
748 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
749 PreConType preconAdapter(matrix, numIterations, relaxFactor, solverVerbose,
750 preconditioning, domainSpace.gridPart().comm() );
751 return new MatrixAdapterType(matrix, domainSpace, rangeSpace, preconAdapter );
752 }
753
754 template <class MatrixAdapterType>
755 static MatrixAdapterType*
756 matrixAdapterObject( const MatrixObjectType& matrixObj,
757 const MatrixAdapterType*,
758 const ISTLSolverParameter& param )
759 {
760 int preconditioning = param.preconditionMethod(
761 ISTLPreconditionMethods::supportedPreconditionMethods() );
762 const double relaxFactor = param.relaxation();
763 const size_t numIterations = param.preconditionerIteration();
764
765 const DomainSpaceType& domainSpace = matrixObj.domainSpace();
766 const RangeSpaceType& rangeSpace = matrixObj.rangeSpace();
767
768 MatrixType& matrix = matrixObj.exportMatrix();
769 const auto procs = domainSpace.gridPart().comm().size();
770
771 const bool verbose = param.verbose();// && Parameter::verbose();
772
773 typedef typename MatrixType :: BaseType ISTLMatrixType;
774 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
775
776 typedef typename MatrixObjectType :: RowBlockVectorType RowBlockVectorType;
777 typedef typename MatrixObjectType :: ColumnBlockVectorType ColumnBlockVectorType;
778
779 // no preconditioner
780 if( preconditioning == SolverParameter::none )
781 {
782 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, PreConType(param.verbose()) );
783 }
784 // SSOR
785 else if( preconditioning == SolverParameter::ssor )
786 {
787 typedef ParallelSSOR<MatrixObjectType, RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
788 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
789 PreConType preconAdapter( matrix, verbose, new PreconditionerType( matrixObj, numIterations, relaxFactor, verbose ) );
790 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
791 }
792 // SOR and Gauss-Seidel
793 else if(preconditioning == SolverParameter::sor || preconditioning == SolverParameter::gauss_seidel)
794 {
795 typedef ParallelSOR<MatrixObjectType, RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
796 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
797 PreConType preconAdapter( matrix, verbose, new PreconditionerType( matrixObj, numIterations,
798 (preconditioning == SolverParameter::gauss_seidel) ? 1.0 : relaxFactor, verbose ) );
799 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
800 }
801 // ILU
802 else if(preconditioning == SolverParameter::ilu)
803 {
804 if( procs > 1 )
805 DUNE_THROW(InvalidStateException,"ISTL::SeqILU not working in parallel computations");
806
807 typedef SeqILU<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
808 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
809 // might need to set verbosity here?
810 PreConType preconAdapter( matrix, verbose, new PreconditionerType( matrix, numIterations, relaxFactor, param.fastILUStorage()) );
811 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
812 }
813 // Jacobi
814 else if(preconditioning == SolverParameter::jacobi)
815 {
816 typedef ParallelJacobi<MatrixObjectType, RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
817 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
818 PreConType preconAdapter( matrix, verbose, new PreconditionerType( matrixObj, numIterations, relaxFactor, verbose ) );
819 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
820 }
821 // AMG ILU-0
822 else if(preconditioning == SolverParameter::amg_ilu)
823 {
824 // use original SeqILU because of some AMG traits classes.
825 typedef SeqILU<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
826 return createAMGMatrixAdapter( (MatrixAdapterType *)nullptr,
827 (PreconditionerType*)nullptr,
828 matrix, domainSpace, rangeSpace, relaxFactor, numIterations,
829 verbose);
830 }
831 // AMG Jacobi
832 else if(preconditioning == SolverParameter::amg_jacobi)
833 {
834 typedef SeqJac<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType,1> PreconditionerType;
835 return createAMGMatrixAdapter( (MatrixAdapterType *)nullptr,
836 (PreconditionerType*)nullptr,
837 matrix, domainSpace, rangeSpace, relaxFactor, numIterations,
838 verbose);
839 }
840 // ILDL
841 else if(preconditioning == SolverParameter::ildl)
842 {
843 if( procs > 1 )
844 DUNE_THROW(InvalidStateException,"ISTL::SeqILDL not working in parallel computations");
845
846 PreConType preconAdapter( matrix, verbose, new SeqILDL<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType>( matrix , relaxFactor ) );
847 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
848 }
849 else
850 {
851 preConErrorMsg(preconditioning);
852 }
853 return new MatrixAdapterType(matrix, domainSpace, rangeSpace, PreConType(verbose) );
854 }
855
856 typedef ISTLParallelMatrixAdapterInterface< MatrixType > MatrixAdapterInterfaceType;
857
858 static void preConErrorMsg(int preCon)
859 {
860 // TODO: re-write
861 std::cerr << "ERROR: Wrong precoditioning number (p = " << preCon;
862 std::cerr <<") in ISTLMatrixObject! \n";
863 std::cerr <<"Valid values are: \n";
864 std::cerr <<"0 == no \n";
865 std::cerr <<"1 == SSOR \n";
866 std::cerr <<"2 == SOR \n";
867 std::cerr <<"3 == ILU-0 \n";
868 std::cerr <<"4 == ILU-n \n";
869 std::cerr <<"5 == Gauss-Seidel \n";
870 std::cerr <<"6 == Jacobi \n";
871
872 assert( false );
873 DUNE_THROW(NotImplemented,"Wrong precoditioning selected");
874 }
875
876 public:
878 static std::unique_ptr< MatrixAdapterInterfaceType >
879 matrixAdapter( const MatrixObjectType& matrixObj,
880 const ISTLSolverParameter& param)
881 {
882 const ISTLSolverParameter* parameter = dynamic_cast< const ISTLSolverParameter* > (&param);
883 std::unique_ptr< ISTLSolverParameter > paramPtr;
884 if( ! parameter )
885 {
886 paramPtr.reset( new ISTLSolverParameter( param ) );
887 parameter = paramPtr.operator->();
888 }
889
890 std::unique_ptr< MatrixAdapterInterfaceType > ptr;
891 if( matrixObj.domainSpace().continuous() )
892 {
893 typedef LagrangeParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
894 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *) nullptr, *parameter ) );
895 }
896 else
897 {
898 typedef DGParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
899 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *) nullptr, *parameter ) );
900 }
901 return ptr;
902 }
903
904 }; // end specialization of ISTLMatrixAdapterFactor for domainSpace == rangeSpace
905#endif
906
907#endif // end HAVE_DUNE_ISTL
908
909 } // namespace Fem
910
911} // namespace Dune
912
913#endif // #ifndef DUNE_FEM_PRECONDITIONERWRAPPER_HH
The AMG preconditioner.
Parallel algebraic multigrid based on agglomeration.
Definition: amg.hh:66
The criterion describing the stop criteria for the coarsening process.
Definition: matrixhierarchy.hh:283
Norm that uses only the [0][0] entry of the block to determine couplings.
Definition: aggregates.hh:455
Criterion suitable for unsymmetric matrices.
Definition: aggregates.hh:539
static bool verbose()
obtain the cached value for fem.verbose with default verbosity level 2
Definition: parameter.hh:466
forward declaration
Definition: discretefunction.hh:51
TupleDiscreteFunctionSpace< typename DiscreteFunctions::DiscreteFunctionSpaceType ... > DiscreteFunctionSpaceType
type for the discrete function space this function lives in
Definition: discretefunction.hh:69
Various macros to work with Dune module version numbers.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr GeometryType none(unsigned int dim)
Returns a GeometryType representing a singular of dimension dim.
Definition: type.hh:471
int iterations
The number of iterations to perform.
Definition: smoother.hh:47
Dune namespace.
Definition: alignedallocator.hh:13
Define general, extensible interface for operators. The available implementation wraps a matrix.
Define general preconditioner interface.
The default class for the smoother arguments.
Definition: smoother.hh:38
Functor using the row sum (infinity) norm to determine strong couplings.
Definition: aggregates.hh:463
static void check(const Matrix &mat)
Check whether the a matrix has diagonal values on blocklevel recursion levels.
Definition: matrixutils.hh:53
Category
Definition: solvercategory.hh:23
@ sequential
Category for sequential solvers.
Definition: solvercategory.hh:25
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)