1#ifndef DUNE_FEM_ISTLPRECONDITIONERWRAPPER_HH
2#define DUNE_FEM_ISTLPRECONDITIONERWRAPPER_HH
8#include <dune/fem/solver/diagonalpreconditioner.hh>
17#include <dune/istl/paamg/pinfo.hh>
20#include <dune/fem/solver/parameter.hh>
21#include <dune/fem/operator/matrix/istlmatrixadapter.hh>
22#include <dune/fem/misc/fmatrixconverter.hh>
23#include <dune/fem/function/blockvectors/defaultblockvectors.hh>
31 struct ISTLPreconditionMethods
33 static std::vector< int > supportedPreconditionMethods() {
35 SolverParameter::ssor,
36 SolverParameter::sor ,
37 SolverParameter::ilu ,
38 SolverParameter::gauss_seidel,
39 SolverParameter::jacobi,
40 SolverParameter::amg_ilu,
41 SolverParameter::amg_jacobi,
48 template <
class MatrixImp>
49 class LagrangeParallelMatrixAdapter;
51 template <
class MatrixImp>
52 class LagrangeParallelMatrixAdapter;
54 template <
class MatrixImp>
55 class DGParallelMatrixAdapter;
57 struct ISTLSolverParameter :
public LocalParameter< SolverParameter, ISTLSolverParameter >
59 typedef LocalParameter< SolverParameter, ISTLSolverParameter > BaseType;
61 using BaseType :: parameter ;
62 using BaseType :: keyPrefix ;
64 ISTLSolverParameter(
const ParameterReader ¶meter = Parameter::container() )
65 : BaseType( parameter )
68 ISTLSolverParameter(
const std::string &keyPrefix,
const ParameterReader ¶meter = Parameter::container() )
69 : BaseType( keyPrefix, parameter )
72 ISTLSolverParameter(
const SolverParameter& sp )
73 : ISTLSolverParameter( sp.keyPrefix(), sp.parameter() )
76 virtual double overflowFraction ()
const
78 return parameter().getValue<
double >( keyPrefix() +
"matrix.overflowfraction", 1.0 );
81 virtual bool fastILUStorage ()
const
83 return parameter().getValue<
bool >( keyPrefix() +
"preconditioning.fastilustorage", true );
96 template<
class MatrixObject,
class X,
class Y,
int method,
int l=1 >
97 class ParallelIterative :
public Preconditioner<X,Y>
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;
109 typedef typename DiscreteFunctionSpaceType:: DomainFieldType DomainFieldType;
111 static const bool isNumber = (M::block_type::rows == M::block_type::cols) && (M::block_type::rows == 1);
113 typedef FieldVector< field_type, MatrixBlockType::rows*MatrixBlockType::cols > FlatMatrixBlock;
115 typedef BlockVector< FlatMatrixBlock > DiagonalType;
117 typedef FieldMatrixConverter< FlatMatrixBlock, MatrixBlockType > MatrixConverterType;
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,
125 const rowiterator endi,
126 const std::integral_constant<bool, forward> fb )
const
128 typedef typename M::ConstColIterator coliterator;
130 typedef typename Y::block_type bblock;
131 typedef typename X::block_type xblock;
140 const bool hasDiagInv = diagInv.size() > 0 ;
142 const auto nextRow = [&i]()
145 if constexpr ( forward )
151 for (; i!=endi; nextRow() )
153 const coliterator endj=(*i).end();
154 coliterator j=(*i).begin();
155 const auto rowIdx = i.index();
160 xnew[rowIdx] += w*b[rowIdx];
165 if constexpr (isNumber)
168 for (; j.index()<rowIdx; ++j)
169 rhs -= (*j) * xold[j.index()];
174 rhs -= (*j) * xold[j.index()];
178 v = rhs * diagInv[ rowIdx ];
182 xnew[ rowIdx ] += w*v;
187 for (; j.index()<rowIdx; ++j)
188 (*j).mmv(xold[j.index()],rhs);
191 (*j).mmv(xold[j.index()],rhs);
196 MatrixConverterType m( diagInv[ rowIdx ] );
200 (*diag).solve(v, rhs);
201 xnew[rowIdx].axpy(w,v);
208 void forwardIterate (
const M& A, X& xnew,
const X& xold,
const Y& b,
const field_type& w,
209 const DiagonalType& diagInv )
const
211 bool runParallel = threading_ && (&xnew != &xold);
215 auto doIterate = [
this, &A, &xnew, &xold, &b, &w, &diagInv] ()
217 const auto slice = A.sliceBeginEnd( MPIManager::thread(), MPIManager::numThreads() );
219 iterate( A, xnew, xold, b, w, diagInv,
220 A.slicedBegin( slice.first ), A.slicedEnd( slice.second ), std::true_type() );
225 MPIManager :: run ( doIterate );
227 catch (
const SingleThreadModeError& e )
236 iterate( A, xnew, xold, b, w, diagInv, A.begin(), A.end(), std::true_type() );
242 void backwardIterate (
const M& A, X& xnew,
const X& xold,
const Y& b,
const field_type& w,
243 const DiagonalType& diagInv )
const
246 iterate( A, xnew, xold, b, w, diagInv, A.beforeEnd(), A.beforeBegin(), std::false_type() );
250 const MatrixObject& mObj_;
251 const MatrixType& _A_;
255 DiagonalType diagonalInv_;
257 const bool threading_;
260 ParallelIterative(
const MatrixObject& mObj,
int n=1,
double relax=1.0,
const bool verbose=
false )
262 _A_( mObj.exportMatrix() ),
264 threading_( mObj.threading() )
268 std::string name = SolverParameter::preconditionMethodTable( method );
269 std::cout <<
"Using ParallelIterative(" << name <<
"): it = " << n <<
", w = "<< relax << std::endl;
274 const auto& space = mObj_.domainSpace();
275 if( space.continuous() )
278 ISTLBlockVector< FlatMatrixBlock > diagonalInv( &diagonalInv_ );
280 diagonalInv.resize(space.blockMapper().size());
281 assert( space.blockMapper().size() == _A_.N() );
286 const auto end = _A_.end();
287 for(
auto row = _A_.begin(); row != end; ++row )
290 auto diag = (*row).find( row.index() );
291 if( diag != (*row).end() )
293 MatrixConverterType m( diagonalInv[ row.index() ] );
301 typename DiscreteFunctionSpaceType :: template
302 CommDataHandle< DiscreteFunctionType > :: OperationType operation;
303 space.communicate( diagonalInv, operation );
309 if constexpr( isNumber )
311 const double eps = 16.*std::numeric_limits< double >::epsilon();
312 for(
auto& diag : diagonalInv )
314 diag = (std::abs( diag ) < eps ? 1. : 1. / diag );
320 ParallelIterative(
const ParallelIterative& org )
321 : mObj_( org.mObj_ ),
323 _n( org._n ), _w( org._w ),
324 diagonalInv_( org.diagonalInv_ )
329 void pre (X& x, Y& b)
override {}
332 void apply (X& v,
const Y& d)
override
334 const auto& space = mObj_.domainSpace();
335 const bool continuous = space.continuous();
340 static constexpr bool jacobi = (method == SolverParameter::jacobi);
342 std::unique_ptr< X > xTmp;
343 if constexpr ( jacobi )
344 xTmp.reset(
new X(v) );
346 X& x = (jacobi) ? (*xTmp) : v;
348 for (
int i=0; i<_n; ++i)
350 forwardIterate(_A_, v, x, d, _w, diagonalInv_ );
352 if constexpr ( method == SolverParameter::ssor )
359 backwardIterate(_A_, v, x, d, _w, diagonalInv_ );
366 if constexpr ( jacobi )
371 if( continuous && i == _n-1)
378 void post (X& x)
override {}
384 template<
class MatrixObject,
class X,
class Y >
385 using ParallelSOR = ParallelIterative< MatrixObject, X, Y, SolverParameter::sor>;
387 template<
class MatrixObject,
class X,
class Y >
388 using ParallelSSOR = ParallelIterative< MatrixObject, X, Y, SolverParameter::ssor>;
390 template<
class MatrixObject,
class X,
class Y >
391 using ParallelJacobi = ParallelIterative< MatrixObject, X, Y, SolverParameter::jacobi>;
393 template<
class X,
class Y >
394 class IdentityPreconditionerWrapper :
public Preconditioner<X,Y>
398 typedef X domain_type;
400 typedef Y range_type;
402 typedef typename X::field_type field_type;
405 IdentityPreconditionerWrapper(){}
408 void pre (X& x, Y& b)
override {}
411 void apply (X& v,
const Y& d)
override
413 if constexpr ( std::is_same< X, Y> :: value )
420 void post (X& x)
override {}
429 template<
class MatrixImp>
430 class PreconditionerWrapper
431 :
public Preconditioner<typename MatrixImp :: RowBlockVectorType,
432 typename MatrixImp :: ColBlockVectorType>
434 typedef MatrixImp MatrixType;
435 typedef typename MatrixType :: RowBlockVectorType X;
436 typedef typename MatrixType :: ColBlockVectorType Y;
439 typedef typename MatrixType :: BaseType ISTLMatrixType ;
441 typedef typename MatrixType :: CommunicationType
449 typedef MatrixAdapter< ISTLMatrixType, X, Y > OperatorType;
451 mutable std::shared_ptr< OperatorType > op_;
454 typedef Preconditioner<X,Y> PreconditionerInterfaceType;
455 mutable std::shared_ptr<PreconditionerInterfaceType> preconder_;
461 template <
class XImp,
class YImp>
464 inline static void apply(PreconditionerInterfaceType& preconder,
465 XImp& v,
const YImp& d)
469 inline static void copy(XImp& v,
const YImp& d)
474 template <
class XImp>
475 struct Apply<XImp,XImp>
477 inline static void apply(PreconditionerInterfaceType& preconder,
478 XImp& v,
const XImp& d)
480 preconder.apply( v ,d );
483 inline static void copy(X& v,
const Y& d)
490 typedef X domain_type;
492 typedef Y range_type;
494 typedef typename X::field_type field_type;
497 PreconditionerWrapper (
const PreconditionerWrapper& org,
bool verbose)
499 , preconder_(org.preconder_)
501 , verbose_( verbose )
506 PreconditionerWrapper(
bool verbose)
510 , verbose_( verbose )
514 template <
class PreconditionerType>
515 PreconditionerWrapper(MatrixType & matrix,
519 const PreconditionerType* p)
521 , preconder_( new PreconditionerType( matrix, iter, relax ) )
523 , verbose_( verbose )
530 template <
class PreconditionerType>
531 PreconditionerWrapper(MatrixType & matrix,
bool verbose,
532 PreconditionerType* p)
536 , verbose_( verbose )
541 template <
class PreconditionerType>
542 PreconditionerWrapper(MatrixType & matrix,
546 const PreconditionerType* p ,
547 const CommunicationType& comm)
551 : op_( new OperatorType( matrix ) )
553 , preconder_( createAMGPreconditioner(comm, iter, relax, p) )
555 , verbose_( verbose )
560 void pre (X& x, Y& b)
override
567 preconder_->pre(x,b);
573 void apply (X& v,
const Y& d)
override
578 Apply<X,Y>::apply( *preconder_ , v, d );
582 Apply<X,Y>::copy( v, d );
587 void post (X& x)
override
604 template <
class Smoother>
605 PreconditionerInterfaceType*
606 createAMGPreconditioner(
const CommunicationType& comm,
607 int iter, field_type relax,
const Smoother* )
609 typedef typename Dune::FieldTraits< field_type>::real_type real_type;
610 typedef typename std::conditional< std::is_convertible<field_type,real_type>::value,
617 SmootherArgs smootherArgs;
620 smootherArgs.relaxationFactor = relax ;
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);
629 criterion.setDebugLevel( 1 );
631 criterion.setDebugLevel( 0 );
646 return new AMG(*op_, criterion, smootherArgs);
656 template <
class MatrixObject >
657 class ISTLMatrixAdapterFactory ;
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 > >
663 typedef DomainSpace DomainSpaceType ;
664 typedef RangeSpace RangeSpaceType;
667 typedef MatrixObject< DomainSpaceType, RangeSpaceType, DomainBlock, RangeBlock > MatrixObjectType;
668 typedef typename MatrixObjectType :: MatrixType MatrixType;
669 typedef ISTLParallelMatrixAdapterInterface< MatrixType > MatrixAdapterInterfaceType;
672 static std::unique_ptr< MatrixAdapterInterfaceType >
673 matrixAdapter(
const MatrixObjectType& matrixObj,
674 const ISTLSolverParameter& param)
676 std::unique_ptr< MatrixAdapterInterfaceType > ptr;
677 if( matrixObj.domainSpace().continuous() )
679 typedef LagrangeParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
680 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *)
nullptr, param ) );
684 typedef DGParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
685 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *)
nullptr, param ) );
691 template <
class MatrixAdapterType>
692 static MatrixAdapterType*
693 matrixAdapterObject(
const MatrixObjectType& matrixObj,
694 const MatrixAdapterType*,
695 const ISTLSolverParameter& param )
697 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
698 return new MatrixAdapterType( matrixObj.exportMatrix(),
699 matrixObj.domainSpace(), matrixObj.rangeSpace(), PreConType(param.verbose()),
700 matrixObj.threading() );
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 > >
712 typedef Space DomainSpaceType ;
713 typedef Space RangeSpaceType;
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;
721 template <
class MatrixAdapterType,
class PreconditionerType>
722 static MatrixAdapterType*
723 createMatrixAdapter(
const MatrixAdapterType*,
724 const PreconditionerType* preconditioning,
726 const DomainSpaceType& domainSpace,
727 const RangeSpaceType& rangeSpace,
728 const double relaxFactor,
729 std::size_t numIterations,
732 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
733 PreConType preconAdapter(matrix, numIterations, relaxFactor, verbose, preconditioning );
734 return new MatrixAdapterType(matrix, domainSpace, rangeSpace, preconAdapter );
737 template <
class MatrixAdapterType,
class PreconditionerType>
738 static MatrixAdapterType*
739 createAMGMatrixAdapter(
const MatrixAdapterType*,
740 const PreconditionerType* preconditioning,
742 const DomainSpaceType& domainSpace,
743 const RangeSpaceType& rangeSpace,
744 const double relaxFactor,
745 std::size_t numIterations,
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 );
754 template <
class MatrixAdapterType>
755 static MatrixAdapterType*
756 matrixAdapterObject(
const MatrixObjectType& matrixObj,
757 const MatrixAdapterType*,
758 const ISTLSolverParameter& param )
760 int preconditioning = param.preconditionMethod(
761 ISTLPreconditionMethods::supportedPreconditionMethods() );
762 const double relaxFactor = param.relaxation();
763 const size_t numIterations = param.preconditionerIteration();
765 const DomainSpaceType& domainSpace = matrixObj.domainSpace();
766 const RangeSpaceType& rangeSpace = matrixObj.rangeSpace();
768 MatrixType& matrix = matrixObj.exportMatrix();
769 const auto procs = domainSpace.gridPart().comm().size();
771 const bool verbose = param.verbose();
773 typedef typename MatrixType :: BaseType ISTLMatrixType;
774 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
776 typedef typename MatrixObjectType :: RowBlockVectorType RowBlockVectorType;
777 typedef typename MatrixObjectType :: ColumnBlockVectorType ColumnBlockVectorType;
782 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, PreConType(param.verbose()) );
785 else if( preconditioning == SolverParameter::ssor )
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 );
793 else if(preconditioning == SolverParameter::sor || preconditioning == SolverParameter::gauss_seidel)
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 );
802 else if(preconditioning == SolverParameter::ilu)
805 DUNE_THROW(InvalidStateException,
"ISTL::SeqILU not working in parallel computations");
807 typedef SeqILU<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
808 typedef typename MatrixAdapterType :: PreconditionAdapterType PreConType;
810 PreConType preconAdapter( matrix, verbose,
new PreconditionerType( matrix, numIterations, relaxFactor, param.fastILUStorage()) );
811 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
814 else if(preconditioning == SolverParameter::jacobi)
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 );
822 else if(preconditioning == SolverParameter::amg_ilu)
825 typedef SeqILU<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType> PreconditionerType;
826 return createAMGMatrixAdapter( (MatrixAdapterType *)
nullptr,
827 (PreconditionerType*)
nullptr,
828 matrix, domainSpace, rangeSpace, relaxFactor, numIterations,
832 else if(preconditioning == SolverParameter::amg_jacobi)
834 typedef SeqJac<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType,1> PreconditionerType;
835 return createAMGMatrixAdapter( (MatrixAdapterType *)
nullptr,
836 (PreconditionerType*)
nullptr,
837 matrix, domainSpace, rangeSpace, relaxFactor, numIterations,
841 else if(preconditioning == SolverParameter::ildl)
844 DUNE_THROW(InvalidStateException,
"ISTL::SeqILDL not working in parallel computations");
846 PreConType preconAdapter( matrix, verbose,
new SeqILDL<ISTLMatrixType,RowBlockVectorType,ColumnBlockVectorType>( matrix , relaxFactor ) );
847 return new MatrixAdapterType( matrix, domainSpace, rangeSpace, preconAdapter );
851 preConErrorMsg(preconditioning);
853 return new MatrixAdapterType(matrix, domainSpace, rangeSpace, PreConType(verbose) );
856 typedef ISTLParallelMatrixAdapterInterface< MatrixType > MatrixAdapterInterfaceType;
858 static void preConErrorMsg(
int preCon)
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";
873 DUNE_THROW(NotImplemented,
"Wrong precoditioning selected");
878 static std::unique_ptr< MatrixAdapterInterfaceType >
879 matrixAdapter(
const MatrixObjectType& matrixObj,
880 const ISTLSolverParameter& param)
882 const ISTLSolverParameter* parameter =
dynamic_cast< const ISTLSolverParameter*
> (¶m);
883 std::unique_ptr< ISTLSolverParameter > paramPtr;
886 paramPtr.reset(
new ISTLSolverParameter( param ) );
887 parameter = paramPtr.operator->();
890 std::unique_ptr< MatrixAdapterInterfaceType > ptr;
891 if( matrixObj.domainSpace().continuous() )
893 typedef LagrangeParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
894 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *)
nullptr, *parameter ) );
898 typedef DGParallelMatrixAdapter< MatrixType > MatrixAdapterImplementation;
899 ptr.reset( matrixAdapterObject( matrixObj, (MatrixAdapterImplementation *)
nullptr, *parameter ) );
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