241 void createCriterionAndHierarchies(std::shared_ptr<const Operator> matrixptr,
242 const PI& pinfo,
const Norm&,
243 const ParameterTree& configuration,
244 std::true_type compiles = std::true_type());
246 void createCriterionAndHierarchies(std::shared_ptr<const Operator> matrixptr,
247 const PI& pinfo,
const Norm&,
248 const ParameterTree& configuration,
255 void createHierarchies(C& criterion, std::shared_ptr<const Operator> matrixptr,
256 const PI& pinfo,
const ParameterTree& configuration);
264 void createHierarchies(C& criterion,
265 const std::shared_ptr<const Operator>& matrixptr,
283 typename OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator
matrix;
291 typename OperatorHierarchy::RedistributeInfoList::const_iterator
redist;
295 typename OperatorHierarchy::AggregatesMapList::const_iterator
aggregates;
319 void mgc(LevelContext& levelContext);
329 void moveToFineLevel(LevelContext& levelContext,
bool processedFineLevel);
335 bool moveToCoarseLevel(LevelContext& levelContext);
341 void initIteratorsWithFineLevel(LevelContext& levelContext);
344 std::shared_ptr<OperatorHierarchy> matrices_;
348 std::shared_ptr<Hierarchy<Smoother,A> > smoothers_;
350 std::shared_ptr<CoarseSolver> solver_;
352 std::shared_ptr<Hierarchy<Range,A>> rhs_;
354 std::shared_ptr<Hierarchy<Domain,A>> lhs_;
356 std::shared_ptr<Hierarchy<Domain,A>> update_;
360 std::shared_ptr<ScalarProduct> scalarProduct_;
364 std::size_t preSteps_;
366 std::size_t postSteps_;
367 bool buildHierarchy_;
369 bool coarsesolverconverged;
370 std::shared_ptr<Smoother> coarseSmoother_;
374 std::size_t verbosity_;
380 std::stringstream retval;
381 std::ostream_iterator<char> out(retval);
382 std::transform(str.begin(), str.end(), out,
384 return std::tolower(c, std::locale::classic());
391 template<
class M,
class X,
class S,
class PI,
class A>
393 : matrices_(amg.matrices_), smootherArgs_(amg.smootherArgs_),
394 smoothers_(amg.smoothers_), solver_(amg.solver_),
395 rhs_(), lhs_(), update_(),
396 scalarProduct_(amg.scalarProduct_), gamma_(amg.gamma_),
397 preSteps_(amg.preSteps_), postSteps_(amg.postSteps_),
398 buildHierarchy_(amg.buildHierarchy_),
399 additive(amg.additive), coarsesolverconverged(amg.coarsesolverconverged),
400 coarseSmoother_(amg.coarseSmoother_),
401 category_(amg.category_),
402 verbosity_(amg.verbosity_)
405 template<
class M,
class X,
class S,
class PI,
class A>
409 : matrices_(stackobject_to_shared_ptr(matrices)), smootherArgs_(smootherArgs),
411 rhs_(), lhs_(), update_(), scalarProduct_(0),
412 gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()),
413 postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(false),
414 additive(parms.getAdditive()), coarsesolverconverged(true),
418 verbosity_(parms.debugLevel())
420 assert(matrices_->isBuilt());
423 matrices_->coarsenSmoother(*smoothers_, smootherArgs_);
426 template<
class M,
class X,
class S,
class PI,
class A>
432 : smootherArgs_(smootherArgs),
434 rhs_(), lhs_(), update_(), scalarProduct_(),
435 gamma_(criterion.getGamma()), preSteps_(criterion.getNoPreSmoothSteps()),
436 postSteps_(criterion.getNoPostSmoothSteps()), buildHierarchy_(true),
437 additive(criterion.getAdditive()), coarsesolverconverged(true),
440 verbosity_(criterion.debugLevel())
447 auto matrixptr = stackobject_to_shared_ptr(matrix);
448 createHierarchies(criterion, matrixptr, pinfo);
451 template<
class M,
class X,
class S,
class PI,
class A>
453 const ParameterTree& configuration,
456 solver_(), rhs_(), lhs_(), update_(), scalarProduct_(), buildHierarchy_(true),
457 coarsesolverconverged(true), coarseSmoother_(),
461 if (configuration.hasKey (
"smootherIterations"))
462 smootherArgs_.iterations = configuration.get<
int>(
"smootherIterations");
464 if (configuration.hasKey (
"smootherRelaxation"))
465 smootherArgs_.relaxationFactor = configuration.get<
typename SmootherArgs::RelaxationFactor>(
"smootherRelaxation");
467 auto normName = ToLower()(configuration.get(
"strengthMeasure",
"diagonal"));
468 auto index = configuration.get<
int>(
"diagonalRowIndex", 0);
470 if ( normName ==
"diagonal")
473 using real_type =
typename FieldTraits<field_type>::real_type;
474 std::is_convertible<field_type, real_type> compiles;
479 createCriterionAndHierarchies(matrixptr, pinfo,
Diagonal<0>(), configuration, compiles);
482 createCriterionAndHierarchies(matrixptr, pinfo,
Diagonal<1>(), configuration, compiles);
485 createCriterionAndHierarchies(matrixptr, pinfo,
Diagonal<2>(), configuration, compiles);
488 createCriterionAndHierarchies(matrixptr, pinfo,
Diagonal<3>(), configuration, compiles);
491 createCriterionAndHierarchies(matrixptr, pinfo,
Diagonal<4>(), configuration, compiles);
494 DUNE_THROW(InvalidStateException,
"Currently strengthIndex>4 is not supported.");
497 else if (normName ==
"rowsum")
498 createCriterionAndHierarchies(matrixptr, pinfo,
RowSum(), configuration);
499 else if (normName ==
"frobenius")
500 createCriterionAndHierarchies(matrixptr, pinfo,
FrobeniusNorm(), configuration);
501 else if (normName ==
"one")
502 createCriterionAndHierarchies(matrixptr, pinfo,
AlwaysOneNorm(), configuration);
504 DUNE_THROW(Dune::NotImplemented,
"Wrong config file: strengthMeasure "<<normName<<
" is not supported by AMG");
507 template<
class M,
class X,
class S,
class PI,
class A>
511 DUNE_THROW(InvalidStateException,
"Strength of connection measure does not support this type ("
512 << className<typename M::field_type>() <<
") as it is lacking a conversion to"
513 << className<
typename FieldTraits<typename M::field_type>::real_type>() <<
".");
516 template<
class M,
class X,
class S,
class PI,
class A>
518 void AMG<M,X,S,PI,A>::createCriterionAndHierarchies(std::shared_ptr<const Operator> matrixptr,
const PI& pinfo,
const Norm&,
const ParameterTree& configuration, std::true_type)
520 if (configuration.get<
bool>(
"criterionSymmetric",
true))
525 createHierarchies(criterion, matrixptr, pinfo, configuration);
532 createHierarchies(criterion, matrixptr, pinfo, configuration);
536 template<
class M,
class X,
class S,
class PI,
class A>
538 void AMG<M,X,S,PI,A>::createHierarchies(C& criterion, std::shared_ptr<const Operator> matrixptr,
const PI& pinfo,
const ParameterTree& configuration)
540 if (configuration.hasKey (
"maxLevel"))
541 criterion.setMaxLevel(configuration.get<
int>(
"maxLevel"));
543 if (configuration.hasKey (
"minCoarseningRate"))
544 criterion.setMinCoarsenRate(configuration.get<
int>(
"minCoarseningRate"));
546 if (configuration.hasKey (
"coarsenTarget"))
547 criterion.setCoarsenTarget (configuration.get<
int>(
"coarsenTarget"));
549 if (configuration.hasKey (
"accumulationMode"))
551 std::string mode = ToLower()(configuration.get<std::string>(
"accumulationMode"));
554 else if ( mode ==
"atonce" )
556 else if ( mode ==
"successive")
559 DUNE_THROW(InvalidSolverFactoryConfiguration,
"Parameter accumulationMode does not allow value "
563 if (configuration.hasKey (
"prolongationDampingFactor"))
564 criterion.setProlongationDampingFactor (configuration.get<
double>(
"prolongationDampingFactor"));
566 if (configuration.hasKey(
"defaultAggregationSizeMode"))
568 auto mode = ToLower()(configuration.get<std::string>(
"defaultAggregationSizeMode"));
569 auto dim = configuration.get<std::size_t>(
"defaultAggregationDimension");
570 std::size_t maxDistance = 2;
571 if (configuration.hasKey(
"MaxAggregateDistance"))
572 maxDistance = configuration.get<std::size_t>(
"maxAggregateDistance");
573 if (mode ==
"isotropic")
574 criterion.setDefaultValuesIsotropic(dim, maxDistance);
575 else if(mode ==
"anisotropic")
576 criterion.setDefaultValuesAnisotropic(dim, maxDistance);
578 DUNE_THROW(InvalidSolverFactoryConfiguration,
"Parameter accumulationMode does not allow value "
582 if (configuration.hasKey(
"maxAggregateDistance"))
583 criterion.setMaxDistance(configuration.get<std::size_t>(
"maxAggregateDistance"));
585 if (configuration.hasKey(
"minAggregateSize"))
586 criterion.setMinAggregateSize(configuration.get<std::size_t>(
"minAggregateSize"));
588 if (configuration.hasKey(
"maxAggregateSize"))
589 criterion.setMaxAggregateSize(configuration.get<std::size_t>(
"maxAggregateSize"));
591 if (configuration.hasKey(
"maxAggregateConnectivity"))
592 criterion.setMaxConnectivity(configuration.get<std::size_t>(
"maxAggregateConnectivity"));
594 if (configuration.hasKey (
"alpha"))
595 criterion.setAlpha (configuration.get<
double> (
"alpha"));
597 if (configuration.hasKey (
"beta"))
598 criterion.setBeta (configuration.get<
double> (
"beta"));
600 if (configuration.hasKey (
"gamma"))
601 criterion.setGamma (configuration.get<std::size_t> (
"gamma"));
602 gamma_ = criterion.getGamma();
604 if (configuration.hasKey (
"additive"))
605 criterion.setAdditive (configuration.get<
bool>(
"additive"));
606 additive = criterion.getAdditive();
608 if (configuration.hasKey (
"preSteps"))
609 criterion.setNoPreSmoothSteps (configuration.get<std::size_t> (
"preSteps"));
610 preSteps_ = criterion.getNoPreSmoothSteps ();
612 if (configuration.hasKey (
"postSteps"))
613 criterion.setNoPostSmoothSteps (configuration.get<std::size_t> (
"postSteps"));
614 postSteps_ = criterion.getNoPostSmoothSteps ();
616 verbosity_ = configuration.get(
"verbosity", 0);
617 criterion.setDebugLevel (verbosity_);
619 createHierarchies(criterion, matrixptr, pinfo);
622 template <
class Matrix,
630#if DISABLE_AMG_DIRECTSOLVER
632#elif HAVE_SUITESPARSE_UMFPACK
640 template <
class M, SolverType>
646 DUNE_THROW(NotImplemented,
"DirectSolver not selected");
649 static std::string
name () {
return "None"; }
651#if HAVE_SUITESPARSE_UMFPACK
656 static type*
create(
const M&
mat,
bool verbose,
bool reusevector )
658 return new type(
mat, verbose, reusevector );
660 static std::string
name () {
return "UMFPack"; }
670 return new type(
mat, verbose, reusevector );
672 static std::string
name () {
return "SuperLU"; }
680 static std::string
name() {
return SelectedSolver :: name (); }
683 return SelectedSolver :: create(
mat, verbose, reusevector );
687 template<
class M,
class X,
class S,
class PI,
class A>
689 void AMG<M,X,S,PI,A>::createHierarchies(C& criterion,
690 const std::shared_ptr<const Operator>& matrixptr,
694 matrices_ = std::make_shared<OperatorHierarchy>(
695 std::const_pointer_cast<Operator>(matrixptr),
696 stackobject_to_shared_ptr(
const_cast<PI&
>(pinfo)));
698 matrices_->template build<NegateSet<typename PI::OwnerSet> >(criterion);
701 matrices_->coarsenSmoother(*smoothers_, smootherArgs_);
707 if(buildHierarchy_ && matrices_->levels()==matrices_->maxlevels()
708 && ( ! matrices_->redistributeInformation().back().isSetup() ||
709 matrices_->parallelInformation().coarsest().getRedistributed().communicator().size() ) )
712 SmootherArgs sargs(smootherArgs_);
713 sargs.iterations = 1;
716 cargs.setArgs(sargs);
717 if(matrices_->redistributeInformation().back().isSetup()) {
719 cargs.setMatrix(matrices_->matrices().coarsest().getRedistributed().getmat());
720 cargs.setComm(matrices_->parallelInformation().coarsest().getRedistributed());
722 cargs.setMatrix(matrices_->matrices().coarsest()->getmat());
723 cargs.setComm(*matrices_->parallelInformation().coarsest());
727 scalarProduct_ = createScalarProduct<X>(cargs.getComm(),category());
729 typedef DirectSolverSelector< typename M::matrix_type, X > SolverSelector;
732 if( SolverSelector::isDirectSolver &&
733 (std::is_same<ParallelInformation,SequentialInformation>::value
734 || matrices_->parallelInformation().coarsest()->communicator().size()==1
735 || (matrices_->parallelInformation().coarsest().isRedistributed()
736 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()==1
737 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()>0) )
740 if(matrices_->parallelInformation().coarsest().isRedistributed())
742 if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
745 solver_.reset(SolverSelector::create(matrices_->matrices().coarsest().getRedistributed().getmat(),
false,
false));
752 solver_.reset(SolverSelector::create(matrices_->matrices().coarsest()->getmat(),
false,
false));
754 if(verbosity_>0 && matrices_->parallelInformation().coarsest()->communicator().rank()==0)
755 std::cout<<
"Using a direct coarse solver (" << SolverSelector::name() <<
")" << std::endl;
759 if(matrices_->parallelInformation().coarsest().isRedistributed())
761 if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
766 solver_.reset(
new BiCGSTABSolver<X>(
const_cast<M&
>(matrices_->matrices().coarsest().getRedistributed()),
768 *coarseSmoother_, 1E-12, 1000, 0));
773 solver_.reset(
new BiCGSTABSolver<X>(
const_cast<M&
>(*matrices_->matrices().coarsest()),
775 *coarseSmoother_, 1E-12, 1000, 0));
794 if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0)
795 std::cout<<
"Building hierarchy of "<<matrices_->maxlevels()<<
" levels "
796 <<
"(including coarse solver) took "<<watch.elapsed()<<
" seconds."<<std::endl;
800 template<
class M,
class X,
class S,
class PI,
class A>
807 typedef typename M::matrix_type
Matrix;
814 const Matrix&
mat=matrices_->matrices().finest()->getmat();
815 for(RowIter row=
mat.begin(); row!=
mat.end(); ++row) {
816 bool isDirichlet =
true;
817 bool hasDiagonal =
false;
819 for(ColIter
col=row->begin();
col!=row->end(); ++
col) {
820 if(row.index()==
col.index()) {
828 if(isDirichlet && hasDiagonal)
830 auto&& xEntry = Impl::asVector(x[row.index()]);
831 auto&& bEntry = Impl::asVector(b[row.index()]);
832 Impl::asMatrix(diagonal).solve(xEntry, bEntry);
836 if(smoothers_->levels()>0)
837 smoothers_->finest()->pre(x,b);
840 matrices_->parallelInformation().coarsest()->copyOwnerToAll(x,x);
841 rhs_ = std::make_shared<Hierarchy<Range,A>>(std::make_shared<Range>(b));
842 lhs_ = std::make_shared<Hierarchy<Domain,A>>(std::make_shared<Domain>(x));
843 update_ = std::make_shared<Hierarchy<Domain,A>>(std::make_shared<Domain>(x));
844 matrices_->coarsenVector(*rhs_);
845 matrices_->coarsenVector(*lhs_);
846 matrices_->coarsenVector(*update_);
852 Iterator coarsest = smoothers_->coarsest();
853 Iterator smoother = smoothers_->finest();
854 RIterator rhs = rhs_->finest();
855 DIterator lhs = lhs_->finest();
856 if(smoothers_->levels()>1) {
858 assert(lhs_->levels()==rhs_->levels());
859 assert(smoothers_->levels()==lhs_->levels() || matrices_->levels()==matrices_->maxlevels());
860 assert(smoothers_->levels()+1==lhs_->levels() || matrices_->levels()<matrices_->maxlevels());
862 if(smoother!=coarsest)
863 for(++smoother, ++lhs, ++rhs; smoother != coarsest; ++smoother, ++lhs, ++rhs)
864 smoother->pre(*lhs,*rhs);
865 smoother->pre(*lhs,*rhs);
875 template<
class M,
class X,
class S,
class PI,
class A>
878 return matrices_->levels();
880 template<
class M,
class X,
class S,
class PI,
class A>
883 return matrices_->maxlevels();
887 template<
class M,
class X,
class S,
class PI,
class A>
890 LevelContext levelContext;
898 initIteratorsWithFineLevel(levelContext);
901 *levelContext.lhs = v;
902 *levelContext.rhs = d;
903 *levelContext.update=0;
904 levelContext.level=0;
908 if(postSteps_==0||matrices_->maxlevels()==1)
909 levelContext.pinfo->copyOwnerToAll(*levelContext.update, *levelContext.update);
911 v=*levelContext.update;
916 template<
class M,
class X,
class S,
class PI,
class A>
919 levelContext.smoother = smoothers_->finest();
920 levelContext.matrix = matrices_->matrices().finest();
921 levelContext.pinfo = matrices_->parallelInformation().finest();
922 levelContext.redist =
923 matrices_->redistributeInformation().begin();
924 levelContext.aggregates = matrices_->aggregatesMaps().begin();
925 levelContext.lhs = lhs_->finest();
926 levelContext.update = update_->finest();
927 levelContext.rhs = rhs_->finest();
930 template<
class M,
class X,
class S,
class PI,
class A>
932 ::moveToCoarseLevel(LevelContext& levelContext)
935 bool processNextLevel=
true;
937 if(levelContext.redist->isSetup()) {
938 levelContext.redist->redistribute(
static_cast<const Range&
>(*levelContext.rhs),
939 levelContext.rhs.getRedistributed());
940 processNextLevel = levelContext.rhs.getRedistributed().size()>0;
941 if(processNextLevel) {
943 typename Hierarchy<Range,A>::Iterator fineRhs = levelContext.rhs++;
944 ++levelContext.pinfo;
945 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
946 ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs,
947 static_cast<const Range&
>(fineRhs.getRedistributed()),
948 *levelContext.pinfo);
952 typename Hierarchy<Range,A>::Iterator fineRhs = levelContext.rhs++;
953 ++levelContext.pinfo;
954 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
955 ::restrictVector(*(*levelContext.aggregates),
956 *levelContext.rhs,
static_cast<const Range&
>(*fineRhs),
957 *levelContext.pinfo);
960 if(processNextLevel) {
963 ++levelContext.update;
964 ++levelContext.matrix;
965 ++levelContext.level;
966 ++levelContext.redist;
968 if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()<matrices_->maxlevels()) {
970 ++levelContext.smoother;
971 ++levelContext.aggregates;
974 *levelContext.update=0;
976 return processNextLevel;
979 template<
class M,
class X,
class S,
class PI,
class A>
981 ::moveToFineLevel(LevelContext& levelContext,
bool processNextLevel)
983 if(processNextLevel) {
984 if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()<matrices_->maxlevels()) {
986 --levelContext.smoother;
987 --levelContext.aggregates;
989 --levelContext.redist;
990 --levelContext.level;
992 --levelContext.matrix;
996 --levelContext.pinfo;
998 if(levelContext.redist->isSetup()) {
1000 levelContext.lhs.getRedistributed()=0;
1001 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
1002 ::prolongateVector(*(*levelContext.aggregates), *levelContext.update, *levelContext.lhs,
1003 levelContext.lhs.getRedistributed(),
1004 matrices_->getProlongationDampingFactor(),
1005 *levelContext.pinfo, *levelContext.redist);
1007 *levelContext.lhs=0;
1008 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
1009 ::prolongateVector(*(*levelContext.aggregates), *levelContext.update, *levelContext.lhs,
1010 matrices_->getProlongationDampingFactor(),
1011 *levelContext.pinfo);
1015 if(processNextLevel) {
1016 --levelContext.update;
1020 *levelContext.update += *levelContext.lhs;
1023 template<
class M,
class X,
class S,
class PI,
class A>