dune-istl 2.11
Loading...
Searching...
No Matches
amg.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5#ifndef DUNE_AMG_AMG_HH
6#define DUNE_AMG_AMG_HH
7
8#include <memory>
9#include <sstream>
10#include <dune/common/exceptions.hh>
14#include <dune/istl/solvers.hh>
16#include <dune/istl/superlu.hh>
17#include <dune/istl/umfpack.hh>
20#include <dune/common/typetraits.hh>
21#include <dune/common/exceptions.hh>
22#include <dune/common/scalarvectorview.hh>
23#include <dune/common/scalarmatrixview.hh>
24#include <dune/common/parametertree.hh>
25
26namespace Dune
27{
28 namespace Amg
29 {
35
41
46
47 template<class M, class X, class S, class P, class K, class A>
48 class KAMG;
49
50 template<class T>
51 class KAmgTwoGrid;
52
63 template<class M, class X, class S, class PI=SequentialInformation,
64 class A=std::allocator<X> >
65 class AMG : public Preconditioner<X,X>
66 {
67 template<class M1, class X1, class S1, class P1, class K1, class A1>
68 friend class KAMG;
69
70 friend class KAmgTwoGrid<AMG>;
71
72 public:
74 typedef M Operator;
86
88 typedef X Domain;
90 typedef X Range;
98 typedef S Smoother;
99
102
112 AMG(OperatorHierarchy& matrices, CoarseSolver& coarseSolver,
113 const SmootherArgs& smootherArgs, const Parameters& parms);
114
126 template<class C>
127 AMG(const Operator& fineOperator, const C& criterion,
128 const SmootherArgs& smootherArgs=SmootherArgs(),
130
181 AMG(std::shared_ptr<const Operator> fineOperator, const ParameterTree& configuration, const ParallelInformation& pinfo=ParallelInformation());
182
186 AMG(const AMG& amg);
187
189 void pre(Domain& x, Range& b);
190
192 void apply(Domain& v, const Range& d);
193
196 {
197 return category_;
198 }
199
201 void post(Domain& x);
202
207 template<class A1>
208 void getCoarsestAggregateNumbers(std::vector<std::size_t,A1>& cont);
209
210 std::size_t levels();
211
212 std::size_t maxlevels();
213
223 {
224 matrices_->recalculateGalerkin(NegateSet<typename PI::OwnerSet>());
225 }
226
232
233 private:
234 /*
235 * @brief Helper function to create hierarchies with parameter tree.
236 *
237 * Will create the coarsen criterion with the norm and create the
238 * Hierarchies
239 * \tparam Norm Type of the norm to use.
240 */
241 template<class Norm>
242 void createCriterionAndHierarchies(std::shared_ptr<const Operator> matrixptr,
243 const PI& pinfo, const Norm&,
244 const ParameterTree& configuration,
245 std::true_type compiles = std::true_type());
246 template<class Norm>
247 void createCriterionAndHierarchies(std::shared_ptr<const Operator> matrixptr,
248 const PI& pinfo, const Norm&,
249 const ParameterTree& configuration,
250 std::false_type);
255 template<class C>
256 void createHierarchies(C& criterion, std::shared_ptr<const Operator> matrixptr,
257 const PI& pinfo, const ParameterTree& configuration);
264 template<class C>
265 void createHierarchies(C& criterion,
266 const std::shared_ptr<const Operator>& matrixptr,
267 const PI& pinfo);
274 struct LevelContext
275 {
284 typename OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix;
292 typename OperatorHierarchy::RedistributeInfoList::const_iterator redist;
296 typename OperatorHierarchy::AggregatesMapList::const_iterator aggregates;
312 std::size_t level;
313 };
314
315
320 void mgc(LevelContext& levelContext);
321
322 void additiveMgc();
323
330 void moveToFineLevel(LevelContext& levelContext,bool processedFineLevel);
331
336 bool moveToCoarseLevel(LevelContext& levelContext);
337
342 void initIteratorsWithFineLevel(LevelContext& levelContext);
343
345 std::shared_ptr<OperatorHierarchy> matrices_;
347 SmootherArgs smootherArgs_;
349 std::shared_ptr<Hierarchy<Smoother,A> > smoothers_;
351 std::shared_ptr<CoarseSolver> solver_;
353 std::shared_ptr<Hierarchy<Range,A>> rhs_;
355 std::shared_ptr<Hierarchy<Domain,A>> lhs_;
357 std::shared_ptr<Hierarchy<Domain,A>> update_;
359 using ScalarProduct = Dune::ScalarProduct<X>;
361 std::shared_ptr<ScalarProduct> scalarProduct_;
363 std::size_t gamma_;
365 std::size_t preSteps_;
367 std::size_t postSteps_;
368 bool buildHierarchy_;
369 bool additive;
370 bool coarsesolverconverged;
371 std::shared_ptr<Smoother> coarseSmoother_;
373 SolverCategory::Category category_;
375 std::size_t verbosity_;
376
377 struct ToLower
378 {
379 std::string operator()(const std::string& str)
380 {
381 std::stringstream retval;
382 std::ostream_iterator<char> out(retval);
383 std::transform(str.begin(), str.end(), out,
384 [](char c){
385 return std::tolower(c, std::locale::classic());
386 });
387 return retval.str();
388 }
389 };
390 };
391
392 template<class M, class X, class S, class PI, class A>
393 inline AMG<M,X,S,PI,A>::AMG(const AMG& amg)
394 : matrices_(amg.matrices_), smootherArgs_(amg.smootherArgs_),
395 smoothers_(amg.smoothers_), solver_(amg.solver_),
396 rhs_(), lhs_(), update_(),
397 scalarProduct_(amg.scalarProduct_), gamma_(amg.gamma_),
398 preSteps_(amg.preSteps_), postSteps_(amg.postSteps_),
399 buildHierarchy_(amg.buildHierarchy_),
400 additive(amg.additive), coarsesolverconverged(amg.coarsesolverconverged),
401 coarseSmoother_(amg.coarseSmoother_),
402 category_(amg.category_),
403 verbosity_(amg.verbosity_)
404 {}
405
406 template<class M, class X, class S, class PI, class A>
408 const SmootherArgs& smootherArgs,
409 const Parameters& parms)
410 : matrices_(stackobject_to_shared_ptr(matrices)), smootherArgs_(smootherArgs),
411 smoothers_(new Hierarchy<Smoother,A>), solver_(&coarseSolver),
412 rhs_(), lhs_(), update_(), scalarProduct_(0),
413 gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()),
414 postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(false),
415 additive(parms.getAdditive()), coarsesolverconverged(true),
416 coarseSmoother_(),
417// #warning should category be retrieved from matrices?
418 category_(SolverCategory::category(*smoothers_->coarsest())),
419 verbosity_(parms.debugLevel())
420 {
421 assert(matrices_->isBuilt());
422
423 // build the necessary smoother hierarchies
424 matrices_->coarsenSmoother(*smoothers_, smootherArgs_);
425 }
426
427 template<class M, class X, class S, class PI, class A>
428 template<class C>
430 const C& criterion,
431 const SmootherArgs& smootherArgs,
432 const PI& pinfo)
433 : smootherArgs_(smootherArgs),
434 smoothers_(new Hierarchy<Smoother,A>), solver_(),
435 rhs_(), lhs_(), update_(), scalarProduct_(),
436 gamma_(criterion.getGamma()), preSteps_(criterion.getNoPreSmoothSteps()),
437 postSteps_(criterion.getNoPostSmoothSteps()), buildHierarchy_(true),
438 additive(criterion.getAdditive()), coarsesolverconverged(true),
439 coarseSmoother_(),
440 category_(SolverCategory::category(pinfo)),
441 verbosity_(criterion.debugLevel())
442 {
444 DUNE_THROW(InvalidSolverCategory, "Matrix and Communication must have the same SolverCategory!");
445 // TODO: reestablish compile time checks.
446 //static_assert(static_cast<int>(PI::category)==static_cast<int>(S::category),
447 // "Matrix and Solver must match in terms of category!");
448 auto matrixptr = stackobject_to_shared_ptr(matrix);
449 createHierarchies(criterion, matrixptr, pinfo);
450 }
451
452 template<class M, class X, class S, class PI, class A>
453 AMG<M,X,S,PI,A>::AMG(std::shared_ptr<const Operator> matrixptr,
454 const ParameterTree& configuration,
455 const ParallelInformation& pinfo) :
456 smoothers_(new Hierarchy<Smoother,A>),
457 solver_(), rhs_(), lhs_(), update_(), scalarProduct_(), buildHierarchy_(true),
458 coarsesolverconverged(true), coarseSmoother_(),
459 category_(SolverCategory::category(pinfo))
460 {
461
462 if (configuration.hasKey ("smootherIterations"))
463 smootherArgs_.iterations = configuration.get<int>("smootherIterations");
464
465 if (configuration.hasKey ("smootherRelaxation"))
466 smootherArgs_.relaxationFactor = configuration.get<typename SmootherArgs::RelaxationFactor>("smootherRelaxation");
467
468 auto normName = ToLower()(configuration.get("strengthMeasure", "diagonal"));
469 auto index = configuration.get<int>("diagonalRowIndex", 0);
470
471 if ( normName == "diagonal")
472 {
473 using field_type = typename M::field_type;
474 using real_type = typename FieldTraits<field_type>::real_type;
475 std::is_convertible<field_type, real_type> compiles;
476
477 switch (index)
478 {
479 case 0:
480 createCriterionAndHierarchies(matrixptr, pinfo, Diagonal<0>(), configuration, compiles);
481 break;
482 case 1:
483 createCriterionAndHierarchies(matrixptr, pinfo, Diagonal<1>(), configuration, compiles);
484 break;
485 case 2:
486 createCriterionAndHierarchies(matrixptr, pinfo, Diagonal<2>(), configuration, compiles);
487 break;
488 case 3:
489 createCriterionAndHierarchies(matrixptr, pinfo, Diagonal<3>(), configuration, compiles);
490 break;
491 case 4:
492 createCriterionAndHierarchies(matrixptr, pinfo, Diagonal<4>(), configuration, compiles);
493 break;
494 default:
495 DUNE_THROW(InvalidStateException, "Currently strengthIndex>4 is not supported.");
496 }
497 }
498 else if (normName == "rowsum")
499 createCriterionAndHierarchies(matrixptr, pinfo, RowSum(), configuration);
500 else if (normName == "frobenius")
501 createCriterionAndHierarchies(matrixptr, pinfo, FrobeniusNorm(), configuration);
502 else if (normName == "one")
503 createCriterionAndHierarchies(matrixptr, pinfo, AlwaysOneNorm(), configuration);
504 else
505 DUNE_THROW(Dune::NotImplemented, "Wrong config file: strengthMeasure "<<normName<<" is not supported by AMG");
506 }
507
508 template<class M, class X, class S, class PI, class A>
509 template<class Norm>
510 void AMG<M,X,S,PI,A>::createCriterionAndHierarchies(std::shared_ptr<const Operator> matrixptr, const PI& pinfo, const Norm&, const ParameterTree& configuration, std::false_type)
511 {
512 DUNE_THROW(InvalidStateException, "Strength of connection measure does not support this type ("
513 << className<typename M::field_type>() << ") as it is lacking a conversion to"
514 << className<typename FieldTraits<typename M::field_type>::real_type>() << ".");
515 }
516
517 template<class M, class X, class S, class PI, class A>
518 template<class Norm>
519 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 {
521 if (configuration.get<bool>("criterionSymmetric", true))
522 {
523 using Criterion = Dune::Amg::CoarsenCriterion<
525 Criterion criterion;
526 createHierarchies(criterion, matrixptr, pinfo, configuration);
527 }
528 else
529 {
530 using Criterion = Dune::Amg::CoarsenCriterion<
532 Criterion criterion;
533 createHierarchies(criterion, matrixptr, pinfo, configuration);
534 }
535 }
536
537 template<class M, class X, class S, class PI, class A>
538 template<class C>
539 void AMG<M,X,S,PI,A>::createHierarchies(C& criterion, std::shared_ptr<const Operator> matrixptr, const PI& pinfo, const ParameterTree& configuration)
540 {
541 if (configuration.hasKey ("maxLevel"))
542 criterion.setMaxLevel(configuration.get<int>("maxLevel"));
543
544 if (configuration.hasKey ("minCoarseningRate"))
545 criterion.setMinCoarsenRate(configuration.get<int>("minCoarseningRate"));
546
547 if (configuration.hasKey ("coarsenTarget"))
548 criterion.setCoarsenTarget (configuration.get<int>("coarsenTarget"));
549
550 if (configuration.hasKey ("accumulationMode"))
551 {
552 std::string mode = ToLower()(configuration.get<std::string>("accumulationMode"));
553 if ( mode == "none")
554 criterion.setAccumulate(AccumulationMode::noAccu);
555 else if ( mode == "atonce" )
556 criterion.setAccumulate(AccumulationMode::atOnceAccu);
557 else if ( mode == "successive")
558 criterion.setCoarsenTarget (AccumulationMode::successiveAccu);
559 else
560 DUNE_THROW(InvalidSolverFactoryConfiguration, "Parameter accumulationMode does not allow value "
561 << mode <<".");
562 }
563
564 if (configuration.hasKey ("prolongationDampingFactor"))
565 criterion.setProlongationDampingFactor (configuration.get<double>("prolongationDampingFactor"));
566
567 if (configuration.hasKey("defaultAggregationSizeMode"))
568 {
569 auto mode = ToLower()(configuration.get<std::string>("defaultAggregationSizeMode"));
570 auto dim = configuration.get<std::size_t>("defaultAggregationDimension");
571 std::size_t maxDistance = 2;
572 if (configuration.hasKey("MaxAggregateDistance"))
573 maxDistance = configuration.get<std::size_t>("maxAggregateDistance");
574 if (mode == "isotropic")
575 criterion.setDefaultValuesIsotropic(dim, maxDistance);
576 else if(mode == "anisotropic")
577 criterion.setDefaultValuesAnisotropic(dim, maxDistance);
578 else
579 DUNE_THROW(InvalidSolverFactoryConfiguration, "Parameter accumulationMode does not allow value "
580 << mode <<".");
581 }
582
583 if (configuration.hasKey("maxAggregateDistance"))
584 criterion.setMaxDistance(configuration.get<std::size_t>("maxAggregateDistance"));
585
586 if (configuration.hasKey("minAggregateSize"))
587 criterion.setMinAggregateSize(configuration.get<std::size_t>("minAggregateSize"));
588
589 if (configuration.hasKey("maxAggregateSize"))
590 criterion.setMaxAggregateSize(configuration.get<std::size_t>("maxAggregateSize"));
591
592 if (configuration.hasKey("maxAggregateConnectivity"))
593 criterion.setMaxConnectivity(configuration.get<std::size_t>("maxAggregateConnectivity"));
594
595 if (configuration.hasKey ("alpha"))
596 criterion.setAlpha (configuration.get<double> ("alpha"));
597
598 if (configuration.hasKey ("beta"))
599 criterion.setBeta (configuration.get<double> ("beta"));
600
601 if (configuration.hasKey ("gamma"))
602 criterion.setGamma (configuration.get<std::size_t> ("gamma"));
603 gamma_ = criterion.getGamma();
604
605 if (configuration.hasKey ("additive"))
606 criterion.setAdditive (configuration.get<bool>("additive"));
607 additive = criterion.getAdditive();
608
609 if (configuration.hasKey ("preSteps"))
610 criterion.setNoPreSmoothSteps (configuration.get<std::size_t> ("preSteps"));
611 preSteps_ = criterion.getNoPreSmoothSteps ();
612
613 if (configuration.hasKey ("postSteps"))
614 criterion.setNoPostSmoothSteps (configuration.get<std::size_t> ("postSteps"));
615 postSteps_ = criterion.getNoPostSmoothSteps ();
616
617 verbosity_ = configuration.get("verbosity", 0);
618 criterion.setDebugLevel (verbosity_);
619
620 createHierarchies(criterion, matrixptr, pinfo);
621 }
622
623 template <class Matrix,
624 class Vector>
626 {
627 typedef typename Matrix :: field_type field_type;
629
630 static constexpr SolverType solver =
631#if DISABLE_AMG_DIRECTSOLVER
632 none;
633#elif HAVE_SUITESPARSE_UMFPACK
635#elif HAVE_SUPERLU
636 superlu ;
637#else
638 none;
639#endif
640
641 template <class M, SolverType>
642 struct Solver
643 {
645 static type* create(const M& mat, bool verbose, bool reusevector )
646 {
647 DUNE_THROW(NotImplemented,"DirectSolver not selected");
648 return nullptr;
649 }
650 static std::string name () { return "None"; }
651 };
652#if HAVE_SUITESPARSE_UMFPACK
653 template <class M>
654 struct Solver< M, umfpack >
655 {
656 typedef UMFPack< M > type;
657 static type* create(const M& mat, bool verbose, bool reusevector )
658 {
659 return new type(mat, verbose, reusevector );
660 }
661 static std::string name () { return "UMFPack"; }
662 };
663#endif
664#if HAVE_SUPERLU
665 template <class M>
666 struct Solver< M, superlu >
667 {
669 static type* create(const M& mat, bool verbose, bool reusevector )
670 {
671 return new type(mat, verbose, reusevector );
672 }
673 static std::string name () { return "SuperLU"; }
674 };
675#endif
676
677 // define direct solver type to be used
679 typedef typename SelectedSolver :: type DirectSolver;
680 static constexpr bool isDirectSolver = solver != none;
681 static std::string name() { return SelectedSolver :: name (); }
682 static DirectSolver* create(const Matrix& mat, bool verbose, bool reusevector )
683 {
684 return SelectedSolver :: create( mat, verbose, reusevector );
685 }
686 };
687
688 template<class M, class X, class S, class PI, class A>
689 template<class C>
690 void AMG<M,X,S,PI,A>::createHierarchies(C& criterion,
691 const std::shared_ptr<const Operator>& matrixptr,
692 const PI& pinfo)
693 {
694 Timer watch;
695 matrices_ = std::make_shared<OperatorHierarchy>(
696 std::const_pointer_cast<Operator>(matrixptr),
697 stackobject_to_shared_ptr(const_cast<PI&>(pinfo)));
698
699 matrices_->template build<NegateSet<typename PI::OwnerSet> >(criterion);
700
701 // build the necessary smoother hierarchies
702 matrices_->coarsenSmoother(*smoothers_, smootherArgs_);
703
704 // test whether we should solve on the coarse level. That is the case if we
705 // have that level and if there was a redistribution on this level then our
706 // communicator has to be valid (size()>0) as the smoother might try to communicate
707 // in the constructor.
708 if(buildHierarchy_ && matrices_->levels()==matrices_->maxlevels()
709 && ( ! matrices_->redistributeInformation().back().isSetup() ||
710 matrices_->parallelInformation().coarsest().getRedistributed().communicator().size() ) )
711 {
712 // We have the carsest level. Create the coarse Solver
713 SmootherArgs sargs(smootherArgs_);
714 sargs.iterations = 1;
715
717 cargs.setArgs(sargs);
718 if(matrices_->redistributeInformation().back().isSetup()) {
719 // Solve on the redistributed partitioning
720 cargs.setMatrix(matrices_->matrices().coarsest().getRedistributed().getmat());
721 cargs.setComm(matrices_->parallelInformation().coarsest().getRedistributed());
722 }else{
723 cargs.setMatrix(matrices_->matrices().coarsest()->getmat());
724 cargs.setComm(*matrices_->parallelInformation().coarsest());
725 }
726
727 coarseSmoother_ = ConstructionTraits<Smoother>::construct(cargs);
728 scalarProduct_ = createScalarProduct<X>(cargs.getComm(),category());
729
731
732 // Use superlu if we are purely sequential or with only one processor on the coarsest level.
733 if( SolverSelector::isDirectSolver &&
734 (std::is_same<ParallelInformation,SequentialInformation>::value // sequential mode
735 || matrices_->parallelInformation().coarsest()->communicator().size()==1 //parallel mode and only one processor
736 || (matrices_->parallelInformation().coarsest().isRedistributed()
737 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()==1
738 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()>0) )
739 )
740 { // redistribute and 1 proc
741 if(matrices_->parallelInformation().coarsest().isRedistributed())
742 {
743 if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
744 {
745 // We are still participating on this level
746 solver_.reset(SolverSelector::create(matrices_->matrices().coarsest().getRedistributed().getmat(), false, false));
747 }
748 else
749 solver_.reset();
750 }
751 else
752 {
753 solver_.reset(SolverSelector::create(matrices_->matrices().coarsest()->getmat(), false, false));
754 }
755 if(verbosity_>0 && matrices_->parallelInformation().coarsest()->communicator().rank()==0)
756 std::cout<< "Using a direct coarse solver (" << SolverSelector::name() << ")" << std::endl;
757 }
758 else
759 {
760 if(matrices_->parallelInformation().coarsest().isRedistributed())
761 {
762 if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
763 // We are still participating on this level
764
765 // we have to allocate these types using the rebound allocator
766 // in order to ensure that we fulfill the alignment requirements
767 solver_.reset(new BiCGSTABSolver<X>(const_cast<M&>(matrices_->matrices().coarsest().getRedistributed()),
768 *scalarProduct_,
769 *coarseSmoother_, 1E-2, 1000, 0));
770 else
771 solver_.reset();
772 }else
773 {
774 solver_.reset(new BiCGSTABSolver<X>(const_cast<M&>(*matrices_->matrices().coarsest()),
775 *scalarProduct_,
776 *coarseSmoother_, 1E-2, 1000, 0));
777 // // we have to allocate these types using the rebound allocator
778 // // in order to ensure that we fulfill the alignment requirements
779 // using Alloc = typename std::allocator_traits<A>::template rebind_alloc<BiCGSTABSolver<X>>;
780 // Alloc alloc;
781 // auto p = alloc.allocate(1);
782 // std::allocator_traits<Alloc>::construct(alloc, p,
783 // const_cast<M&>(*matrices_->matrices().coarsest()),
784 // *scalarProduct_,
785 // *coarseSmoother_, 1E-2, 1000, 0);
786 // solver_.reset(p,[](BiCGSTABSolver<X>* p){
787 // Alloc alloc;
788 // std::allocator_traits<Alloc>::destroy(alloc, p);
789 // alloc.deallocate(p,1);
790 // });
791 }
792 }
793 }
794
795 if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0)
796 std::cout<<"Building hierarchy of "<<matrices_->maxlevels()<<" levels "
797 <<"(including coarse solver) took "<<watch.elapsed()<<" seconds."<<std::endl;
798 }
799
800
801 template<class M, class X, class S, class PI, class A>
803 {
804 // Detect Matrix rows where all offdiagonal entries are
805 // zero and set x such that A_dd*x_d=b_d
806 // Thus users can be more careless when setting up their linear
807 // systems.
808 typedef typename M::matrix_type Matrix;
809 typedef typename Matrix::ConstRowIterator RowIter;
810 typedef typename Matrix::ConstColIterator ColIter;
811 typedef typename Matrix::block_type Block;
812 Block zero;
813 zero=typename Matrix::field_type();
814
815 const Matrix& mat=matrices_->matrices().finest()->getmat();
816 for(RowIter row=mat.begin(); row!=mat.end(); ++row) {
817 bool isDirichlet = true;
818 bool hasDiagonal = false;
819 Block diagonal{};
820 for(ColIter col=row->begin(); col!=row->end(); ++col) {
821 if(row.index()==col.index()) {
822 diagonal = *col;
823 hasDiagonal = true;
824 }else{
825 if(*col!=zero)
826 isDirichlet = false;
827 }
828 }
829 if(isDirichlet && hasDiagonal)
830 {
831 auto&& xEntry = Impl::asVector(x[row.index()]);
832 auto&& bEntry = Impl::asVector(b[row.index()]);
833 Impl::asMatrix(diagonal).solve(xEntry, bEntry);
834 }
835 }
836
837 if(smoothers_->levels()>0)
838 smoothers_->finest()->pre(x,b);
839 else
840 // No smoother to make x consistent! Do it by hand
841 matrices_->parallelInformation().coarsest()->copyOwnerToAll(x,x);
842 rhs_ = std::make_shared<Hierarchy<Range,A>>(std::make_shared<Range>(b));
843 lhs_ = std::make_shared<Hierarchy<Domain,A>>(std::make_shared<Domain>(x));
844 update_ = std::make_shared<Hierarchy<Domain,A>>(std::make_shared<Domain>(x));
845 matrices_->coarsenVector(*rhs_);
846 matrices_->coarsenVector(*lhs_);
847 matrices_->coarsenVector(*update_);
848
849 // Preprocess all smoothers
850 typedef typename Hierarchy<Smoother,A>::Iterator Iterator;
851 typedef typename Hierarchy<Range,A>::Iterator RIterator;
852 typedef typename Hierarchy<Domain,A>::Iterator DIterator;
853 Iterator coarsest = smoothers_->coarsest();
854 Iterator smoother = smoothers_->finest();
855 RIterator rhs = rhs_->finest();
856 DIterator lhs = lhs_->finest();
857 if(smoothers_->levels()>1) {
858
859 assert(lhs_->levels()==rhs_->levels());
860 assert(smoothers_->levels()==lhs_->levels() || matrices_->levels()==matrices_->maxlevels());
861 assert(smoothers_->levels()+1==lhs_->levels() || matrices_->levels()<matrices_->maxlevels());
862
863 if(smoother!=coarsest)
864 for(++smoother, ++lhs, ++rhs; smoother != coarsest; ++smoother, ++lhs, ++rhs)
865 smoother->pre(*lhs,*rhs);
866 smoother->pre(*lhs,*rhs);
867 }
868
869
870 // The preconditioner might change x and b. So we have to
871 // copy the changes to the original vectors.
872 x = *lhs_->finest();
873 b = *rhs_->finest();
874
875 }
876 template<class M, class X, class S, class PI, class A>
878 {
879 return matrices_->levels();
880 }
881 template<class M, class X, class S, class PI, class A>
883 {
884 return matrices_->maxlevels();
885 }
886
888 template<class M, class X, class S, class PI, class A>
890 {
891 LevelContext levelContext;
892
893 if(additive) {
894 *(rhs_->finest())=d;
895 additiveMgc();
896 v=*lhs_->finest();
897 }else{
898 // Init all iterators for the current level
899 initIteratorsWithFineLevel(levelContext);
900
901
902 *levelContext.lhs = v;
903 *levelContext.rhs = d;
904 *levelContext.update=0;
905 levelContext.level=0;
906
907 mgc(levelContext);
908
909 if(postSteps_==0||matrices_->maxlevels()==1)
910 levelContext.pinfo->copyOwnerToAll(*levelContext.update, *levelContext.update);
911
912 v=*levelContext.update;
913 }
914
915 }
916
917 template<class M, class X, class S, class PI, class A>
918 void AMG<M,X,S,PI,A>::initIteratorsWithFineLevel(LevelContext& levelContext)
919 {
920 levelContext.smoother = smoothers_->finest();
921 levelContext.matrix = matrices_->matrices().finest();
922 levelContext.pinfo = matrices_->parallelInformation().finest();
923 levelContext.redist =
924 matrices_->redistributeInformation().begin();
925 levelContext.aggregates = matrices_->aggregatesMaps().begin();
926 levelContext.lhs = lhs_->finest();
927 levelContext.update = update_->finest();
928 levelContext.rhs = rhs_->finest();
929 }
930
931 template<class M, class X, class S, class PI, class A>
932 bool AMG<M,X,S,PI,A>
933 ::moveToCoarseLevel(LevelContext& levelContext)
934 {
935
936 bool processNextLevel=true;
937
938 if(levelContext.redist->isSetup()) {
939 levelContext.redist->redistribute(static_cast<const Range&>(*levelContext.rhs),
940 levelContext.rhs.getRedistributed());
941 processNextLevel = levelContext.rhs.getRedistributed().size()>0;
942 if(processNextLevel) {
943 //restrict defect to coarse level right hand side.
944 typename Hierarchy<Range,A>::Iterator fineRhs = levelContext.rhs++;
945 ++levelContext.pinfo;
946 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
947 ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs,
948 static_cast<const Range&>(fineRhs.getRedistributed()),
949 *levelContext.pinfo);
950 }
951 }else{
952 //restrict defect to coarse level right hand side.
953 typename Hierarchy<Range,A>::Iterator fineRhs = levelContext.rhs++;
954 ++levelContext.pinfo;
956 ::restrictVector(*(*levelContext.aggregates),
957 *levelContext.rhs, static_cast<const Range&>(*fineRhs),
958 *levelContext.pinfo);
959 }
960
961 if(processNextLevel) {
962 // prepare coarse system
963 ++levelContext.lhs;
964 ++levelContext.update;
965 ++levelContext.matrix;
966 ++levelContext.level;
967 ++levelContext.redist;
968
969 if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()<matrices_->maxlevels()) {
970 // next level is not the globally coarsest one
971 ++levelContext.smoother;
972 ++levelContext.aggregates;
973 }
974 // prepare the update on the next level
975 *levelContext.update=0;
976 }
977 return processNextLevel;
978 }
979
980 template<class M, class X, class S, class PI, class A>
981 void AMG<M,X,S,PI,A>
982 ::moveToFineLevel(LevelContext& levelContext, bool processNextLevel)
983 {
984 if(processNextLevel) {
985 if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()<matrices_->maxlevels()) {
986 // previous level is not the globally coarsest one
987 --levelContext.smoother;
988 --levelContext.aggregates;
989 }
990 --levelContext.redist;
991 --levelContext.level;
992 //prolongate and add the correction (update is in coarse left hand side)
993 --levelContext.matrix;
994
995 //typename Hierarchy<Domain,A>::Iterator coarseLhs = lhs--;
996 --levelContext.lhs;
997 --levelContext.pinfo;
998 }
999 if(levelContext.redist->isSetup()) {
1000 // Need to redistribute during prolongateVector
1001 levelContext.lhs.getRedistributed()=0;
1003 ::prolongateVector(*(*levelContext.aggregates), *levelContext.update, *levelContext.lhs,
1004 levelContext.lhs.getRedistributed(),
1005 matrices_->getProlongationDampingFactor(),
1006 *levelContext.pinfo, *levelContext.redist);
1007 }else{
1008 *levelContext.lhs=0;
1010 ::prolongateVector(*(*levelContext.aggregates), *levelContext.update, *levelContext.lhs,
1011 matrices_->getProlongationDampingFactor(),
1012 *levelContext.pinfo);
1013 }
1014
1015
1016 if(processNextLevel) {
1017 --levelContext.update;
1018 --levelContext.rhs;
1019 }
1020
1021 *levelContext.update += *levelContext.lhs;
1022 }
1023
1024 template<class M, class X, class S, class PI, class A>
1029
1030 template<class M, class X, class S, class PI, class A>
1031 void AMG<M,X,S,PI,A>::mgc(LevelContext& levelContext){
1032 if(levelContext.matrix == matrices_->matrices().coarsest() && levels()==maxlevels()) {
1033 // Solve directly
1035 res.converged=true; // If we do not compute this flag will not get updated
1036 if(levelContext.redist->isSetup()) {
1037 levelContext.redist->redistribute(*levelContext.rhs, levelContext.rhs.getRedistributed());
1038 if(levelContext.rhs.getRedistributed().size()>0) {
1039 // We are still participating in the computation
1040 levelContext.pinfo.getRedistributed().copyOwnerToAll(levelContext.rhs.getRedistributed(),
1041 levelContext.rhs.getRedistributed());
1042 solver_->apply(levelContext.update.getRedistributed(),
1043 levelContext.rhs.getRedistributed(), res);
1044 }
1045 levelContext.redist->redistributeBackward(*levelContext.update, levelContext.update.getRedistributed());
1046 levelContext.pinfo->copyOwnerToAll(*levelContext.update, *levelContext.update);
1047 }else{
1048 levelContext.pinfo->copyOwnerToAll(*levelContext.rhs, *levelContext.rhs);
1049 solver_->apply(*levelContext.update, *levelContext.rhs, res);
1050 }
1051
1052 if (!res.converged)
1053 coarsesolverconverged = false;
1054 }else{
1055 // presmoothing
1056 presmooth(levelContext, preSteps_);
1057
1058#ifndef DUNE_AMG_NO_COARSEGRIDCORRECTION
1059 bool processNextLevel = moveToCoarseLevel(levelContext);
1060
1061 if(processNextLevel) {
1062 // next level
1063 for(std::size_t i=0; i<gamma_; i++){
1064 mgc(levelContext);
1065 if (levelContext.matrix == matrices_->matrices().coarsest() && levels()==maxlevels())
1066 break;
1067 if(i+1 < gamma_){
1068 levelContext.matrix->applyscaleadd(-1., *levelContext.lhs, *levelContext.rhs);
1069 }
1070 }
1071 }
1072
1073 moveToFineLevel(levelContext, processNextLevel);
1074#else
1075 *lhs=0;
1076#endif
1077
1078 if(levelContext.matrix == matrices_->matrices().finest()) {
1079 coarsesolverconverged = matrices_->parallelInformation().finest()->communicator().prod(coarsesolverconverged);
1080 if(!coarsesolverconverged)
1081 DUNE_THROW(MathError, "Coarse solver did not converge");
1082 }
1083 // postsmoothing
1084 postsmooth(levelContext, postSteps_);
1085
1086 }
1087 }
1088
1089 template<class M, class X, class S, class PI, class A>
1090 void AMG<M,X,S,PI,A>::additiveMgc(){
1091
1092 // restrict residual to all levels
1093 typename ParallelInformationHierarchy::Iterator pinfo=matrices_->parallelInformation().finest();
1094 typename Hierarchy<Range,A>::Iterator rhs=rhs_->finest();
1095 typename Hierarchy<Domain,A>::Iterator lhs = lhs_->finest();
1096 typename OperatorHierarchy::AggregatesMapList::const_iterator aggregates=matrices_->aggregatesMaps().begin();
1097
1098 for(typename Hierarchy<Range,A>::Iterator fineRhs=rhs++; fineRhs != rhs_->coarsest(); fineRhs=rhs++, ++aggregates) {
1099 ++pinfo;
1101 ::restrictVector(*(*aggregates), *rhs, static_cast<const Range&>(*fineRhs), *pinfo);
1102 }
1103
1104 // pinfo is invalid, set to coarsest level
1105 //pinfo = matrices_->parallelInformation().coarsest
1106 // calculate correction for all levels
1107 lhs = lhs_->finest();
1108 typename Hierarchy<Smoother,A>::Iterator smoother = smoothers_->finest();
1109
1110 for(rhs=rhs_->finest(); rhs != rhs_->coarsest(); ++lhs, ++rhs, ++smoother) {
1111 // presmoothing
1112 *lhs=0;
1113 smoother->apply(*lhs, *rhs);
1114 }
1115
1116 // Coarse level solve
1117#ifndef DUNE_AMG_NO_COARSEGRIDCORRECTION
1118 InverseOperatorResult res;
1119 pinfo->copyOwnerToAll(*rhs, *rhs);
1120 solver_->apply(*lhs, *rhs, res);
1121
1122 if(!res.converged)
1123 DUNE_THROW(MathError, "Coarse solver did not converge");
1124#else
1125 *lhs=0;
1126#endif
1127 // Prologate and add up corrections from all levels
1128 --pinfo;
1129 --aggregates;
1130
1131 for(typename Hierarchy<Domain,A>::Iterator coarseLhs = lhs--; coarseLhs != lhs_->finest(); coarseLhs = lhs--, --aggregates, --pinfo) {
1133 ::prolongateVector(*(*aggregates), *coarseLhs, *lhs, 1.0, *pinfo);
1134 }
1135 }
1136
1137
1139 template<class M, class X, class S, class PI, class A>
1140 void AMG<M,X,S,PI,A>::post([[maybe_unused]] Domain& x)
1141 {
1142 // Postprocess all smoothers
1143 typedef typename Hierarchy<Smoother,A>::Iterator Iterator;
1144 typedef typename Hierarchy<Domain,A>::Iterator DIterator;
1145 Iterator coarsest = smoothers_->coarsest();
1146 Iterator smoother = smoothers_->finest();
1147 DIterator lhs = lhs_->finest();
1148 if(smoothers_->levels()>0) {
1149 if(smoother != coarsest || matrices_->levels()<matrices_->maxlevels())
1150 smoother->post(*lhs);
1151 if(smoother!=coarsest)
1152 for(++smoother, ++lhs; smoother != coarsest; ++smoother, ++lhs)
1153 smoother->post(*lhs);
1154 smoother->post(*lhs);
1155 }
1156 lhs_ = nullptr;
1157 update_ = nullptr;
1158 rhs_ = nullptr;
1159 }
1160
1161 template<class M, class X, class S, class PI, class A>
1162 template<class A1>
1163 void AMG<M,X,S,PI,A>::getCoarsestAggregateNumbers(std::vector<std::size_t,A1>& cont)
1164 {
1165 matrices_->getCoarsestAggregatesOnFinest(cont);
1166 }
1167
1168 } // end namespace Amg
1169
1171 template<class> struct isValidMatrix : std::false_type{};
1172 template<class T, int n, int m, class A> struct isValidMatrix<BCRSMatrix<FieldMatrix<T,n,m>, A>> : std::true_type{};
1173
1174 template<class OP>
1175 std::shared_ptr<Dune::Preconditioner<typename OP::element_type::domain_type, typename OP::element_type::range_type> >
1176 makeAMG(const OP& op, const std::string& smoother, const Dune::ParameterTree& config) const
1177 {
1178 DUNE_THROW(Dune::Exception, "Operator type not supported by AMG");
1179 }
1180
1181 template<class M, class X, class Y>
1182 std::shared_ptr<Dune::Preconditioner<X,Y> >
1183 makeAMG(const std::shared_ptr<MatrixAdapter<M,X,Y>>& op, const std::string& smoother,
1184 const Dune::ParameterTree& config) const
1185 {
1186 using OP = MatrixAdapter<M,X,Y>;
1187
1188 if(smoother == "ssor")
1189 return std::make_shared<Amg::AMG<OP, X, SeqSSOR<M,X,Y>>>(op, config);
1190 if(smoother == "sor")
1191 return std::make_shared<Amg::AMG<OP, X, SeqSOR<M,X,Y>>>(op, config);
1192 if(smoother == "jac")
1193 return std::make_shared<Amg::AMG<OP, X, SeqJac<M,X,Y>>>(op, config);
1194 if(smoother == "gs")
1195 return std::make_shared<Amg::AMG<OP, X, SeqGS<M,X,Y>>>(op, config);
1196 if(smoother == "ilu")
1197 return std::make_shared<Amg::AMG<OP, X, SeqILU<M,X,Y>>>(op, config);
1198 else
1199 DUNE_THROW(Dune::Exception, "Unknown smoother for AMG");
1200 }
1201
1202 template<class M, class X, class Y, class C>
1203 std::shared_ptr<Dune::Preconditioner<X,Y> >
1204 makeAMG(const std::shared_ptr<OverlappingSchwarzOperator<M,X,Y,C>>& op, const std::string& smoother,
1205 const Dune::ParameterTree& config) const
1206 {
1208
1209 auto cop = std::static_pointer_cast<const OP>(op);
1210
1211 if(smoother == "ssor")
1212 return std::make_shared<Amg::AMG<OP, X, BlockPreconditioner<X,Y,C,SeqSSOR<M,X,Y>>,C>>(cop, config, op->getCommunication());
1213 if(smoother == "sor")
1214 return std::make_shared<Amg::AMG<OP, X, BlockPreconditioner<X,Y,C,SeqSOR<M,X,Y>>,C>>(cop, config, op->getCommunication());
1215 if(smoother == "jac")
1216 return std::make_shared<Amg::AMG<OP, X, BlockPreconditioner<X,Y,C,SeqJac<M,X,Y>>,C>>(cop, config, op->getCommunication());
1217 if(smoother == "gs")
1218 return std::make_shared<Amg::AMG<OP, X, BlockPreconditioner<X,Y,C,SeqGS<M,X,Y>>,C>>(cop, config, op->getCommunication());
1219 if(smoother == "ilu")
1220 return std::make_shared<Amg::AMG<OP, X, BlockPreconditioner<X,Y,C,SeqILU<M,X,Y>>,C>>(cop, config, op->getCommunication());
1221 else
1222 DUNE_THROW(Dune::Exception, "Unknown smoother for AMG");
1223 }
1224
1225 template<class M, class X, class Y, class C>
1226 std::shared_ptr<Dune::Preconditioner<X,Y> >
1227 makeAMG(const std::shared_ptr<NonoverlappingSchwarzOperator<M,X,Y,C>>& op, const std::string& smoother,
1228 const Dune::ParameterTree& config) const
1229 {
1231
1232 if(smoother == "ssor")
1233 return std::make_shared<Amg::AMG<OP, X, NonoverlappingBlockPreconditioner<C,SeqSSOR<M,X,Y>>,C>>(op, config, op->getCommunication());
1234 if(smoother == "sor")
1235 return std::make_shared<Amg::AMG<OP, X, NonoverlappingBlockPreconditioner<C,SeqSOR<M,X,Y>>,C>>(op, config, op->getCommunication());
1236 if(smoother == "jac")
1237 return std::make_shared<Amg::AMG<OP, X, NonoverlappingBlockPreconditioner<C,SeqJac<M,X,Y>>,C>>(op, config, op->getCommunication());
1238 if(smoother == "gs")
1239 return std::make_shared<Amg::AMG<OP, X, NonoverlappingBlockPreconditioner<C,SeqGS<M,X,Y>>,C>>(op, config, op->getCommunication());
1240 if(smoother == "ilu")
1241 return std::make_shared<Amg::AMG<OP, X, NonoverlappingBlockPreconditioner<C,SeqILU<M,X,Y>>,C>>(op, config, op->getCommunication());
1242 else
1243 DUNE_THROW(Dune::Exception, "Unknown smoother for AMG");
1244 }
1245
1246 template<typename OpTraits, typename OP>
1247 std::shared_ptr<Dune::Preconditioner<typename OpTraits::domain_type,
1248 typename OpTraits::range_type>>
1249 operator() (OpTraits opTraits, const std::shared_ptr<OP>& op, const Dune::ParameterTree& config,
1250 std::enable_if_t<isValidMatrix<typename OpTraits::matrix_type>::value,int> = 0) const
1251 {
1252 using field_type = typename OpTraits::matrix_type::field_type;
1253 using real_type = typename FieldTraits<field_type>::real_type;
1254 if (!std::is_convertible<field_type, real_type>())
1255 DUNE_THROW(UnsupportedType, "AMG needs field_type(" <<
1256 className<field_type>() <<
1257 ") to be convertible to its real_type (" <<
1258 className<real_type>() <<
1259 ").");
1260 std::string smoother = config.get("smoother", "ssor");
1261 // we can irgnore the OpTraits here. As the AMG can only work
1262 // with actual matrices, the operator op must be of type
1263 // MatrixAdapter or *SchwarzOperator. In any case these
1264 // operators provide all necessary information about matrix,
1265 // domain and range type
1266 return makeAMG(op, smoother, config);
1267 }
1268
1269 template<typename OpTraits, typename OP>
1270 std::shared_ptr<Dune::Preconditioner<typename OpTraits::domain_type,
1271 typename OpTraits::range_type>>
1272 operator() (OpTraits opTraits, const std::shared_ptr<OP>& op, const Dune::ParameterTree& config,
1273 std::enable_if_t<!isValidMatrix<typename OpTraits::matrix_type>::value,int> = 0) const
1274 {
1275 DUNE_THROW(UnsupportedType, "AMG needs a FieldMatrix as Matrix block_type");
1276 }
1277 };
1278
1280} // end namespace Dune
1281
1282#endif
Implementations of the inverse operator interface.
Provides a classes representing the hierarchies in AMG.
Prolongation and restriction for amg.
Classes for the generic construction and application of the smoothers.
Classes for using SuperLU with ISTL matrices.
Templates characterizing the type of a solver.
Define base class for scalar product and norm.
Classes for using UMFPack with ISTL matrices.
#define DUNE_REGISTER_PRECONDITIONER(name,...)
Definition solverregistry.hh:13
AMG(const AMG &amg)
Copy constructor.
Definition amg.hh:393
void pre(Domain &x, Range &b)
Prepare the preconditioner.
Definition amg.hh:802
static DirectSolver * create(const Matrix &mat, bool verbose, bool reusevector)
Definition amg.hh:682
std::shared_ptr< Dune::Preconditioner< typename OpTraits::domain_type, typename OpTraits::range_type > > operator()(OpTraits opTraits, const std::shared_ptr< OP > &op, const Dune::ParameterTree &config, std::enable_if_t< isValidMatrix< typename OpTraits::matrix_type >::value, int >=0) const
Definition amg.hh:1249
static std::string name()
Definition amg.hh:681
DefaultSmootherArgs< typename T::matrix_type::field_type > Arguments
Definition smoother.hh:67
Hierarchy< Domain, A >::Iterator update
The iterator over the updates.
Definition amg.hh:304
Hierarchy< Range, A >::Iterator rhs
The iterator over the right hand sided.
Definition amg.hh:308
static std::string name()
Definition amg.hh:673
bool usesDirectCoarseLevelSolver() const
Check whether the coarse solver used is a direct solver.
Definition amg.hh:1025
X Domain
The domain type.
Definition amg.hh:88
static std::shared_ptr< T > construct(Arguments &)
Construct an object with the specified arguments.
Definition construction.hh:52
static type * create(const M &mat, bool verbose, bool reusevector)
Definition amg.hh:645
AMG(OperatorHierarchy &matrices, CoarseSolver &coarseSolver, const SmootherArgs &smootherArgs, const Parameters &parms)
Construct a new amg with a specific coarse solver.
Definition amg.hh:407
AMG(std::shared_ptr< const Operator > fineOperator, const ParameterTree &configuration, const ParallelInformation &pinfo=ParallelInformation())
Constructor an AMG via ParameterTree.
Definition amg.hh:453
ParallelInformationHierarchy::Iterator pinfo
The iterator over the parallel information.
Definition amg.hh:288
SolverType
Definition amg.hh:628
OperatorHierarchy::AggregatesMapList::const_iterator aggregates
The iterator over the aggregates maps.
Definition amg.hh:296
SmootherTraits< Smoother >::Arguments SmootherArgs
The argument type for the construction of the smoother.
Definition amg.hh:101
Solver< Matrix, solver > SelectedSolver
Definition amg.hh:678
std::shared_ptr< Dune::Preconditioner< X, Y > > makeAMG(const std::shared_ptr< MatrixAdapter< M, X, Y > > &op, const std::string &smoother, const Dune::ParameterTree &config) const
Definition amg.hh:1183
std::string operator()(const std::string &str)
Definition amg.hh:379
std::shared_ptr< Dune::Preconditioner< typename OP::element_type::domain_type, typename OP::element_type::range_type > > makeAMG(const OP &op, const std::string &smoother, const Dune::ParameterTree &config) const
Definition amg.hh:1176
S Smoother
The type of the smoother.
Definition amg.hh:98
static std::string name()
Definition amg.hh:650
Hierarchy< Smoother, A >::Iterator smoother
The iterator over the smoothers.
Definition amg.hh:280
M Operator
The matrix operator type.
Definition amg.hh:74
OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix
The iterator over the matrices.
Definition amg.hh:284
static type * create(const M &mat, bool verbose, bool reusevector)
Definition amg.hh:669
OperatorHierarchy::RedistributeInfoList::const_iterator redist
The iterator over the redistribution information.
Definition amg.hh:292
X Range
The range type.
Definition amg.hh:90
void presmooth(LevelContext &levelContext, size_t steps)
Apply pre smoothing on the current level.
Definition smoother.hh:406
void getCoarsestAggregateNumbers(std::vector< std::size_t, A1 > &cont)
Get the aggregate number of each unknown on the coarsest level.
Definition amg.hh:1163
std::size_t levels()
Definition amg.hh:877
InverseOperator< Vector, Vector > type
Definition amg.hh:644
std::shared_ptr< Dune::Preconditioner< X, Y > > makeAMG(const std::shared_ptr< OverlappingSchwarzOperator< M, X, Y, C > > &op, const std::string &smoother, const Dune::ParameterTree &config) const
Definition amg.hh:1204
Hierarchy< Domain, A >::Iterator lhs
The iterator over the left hand side.
Definition amg.hh:300
const void * Arguments
A type holding all the arguments needed to call the constructor.
Definition construction.hh:44
static constexpr SolverType solver
Definition amg.hh:630
static constexpr bool isDirectSolver
Definition amg.hh:680
void recalculateHierarchy()
Recalculate the matrix hierarchy.
Definition amg.hh:222
FieldTraits< T >::real_type RelaxationFactor
The type of the relaxation factor.
Definition smoother.hh:42
Matrix::field_type field_type
Definition amg.hh:627
SelectedSolver::type DirectSolver
Definition amg.hh:679
OperatorHierarchy::ParallelInformationHierarchy ParallelInformationHierarchy
The parallal data distribution hierarchy type.
Definition amg.hh:85
InverseOperator< X, X > CoarseSolver
the type of the coarse solver.
Definition amg.hh:92
void post(Domain &x)
Clean up.
Definition amg.hh:1140
std::size_t maxlevels()
Definition amg.hh:882
std::shared_ptr< Dune::Preconditioner< X, Y > > makeAMG(const std::shared_ptr< NonoverlappingSchwarzOperator< M, X, Y, C > > &op, const std::string &smoother, const Dune::ParameterTree &config) const
Definition amg.hh:1227
void postsmooth(LevelContext &levelContext, size_t steps)
Apply post smoothing on the current level.
Definition smoother.hh:428
std::size_t level
The level index.
Definition amg.hh:312
AMG(const Operator &fineOperator, const C &criterion, const SmootherArgs &smootherArgs=SmootherArgs(), const ParallelInformation &pinfo=ParallelInformation())
Construct an AMG with an inexact coarse solver based on the smoother.
Definition amg.hh:429
void apply(Domain &v, const Range &d)
Apply one step of the preconditioner to the system A(v)=d.
Definition amg.hh:889
Smoother SmootherType
Definition amg.hh:276
MatrixHierarchy< M, ParallelInformation, A > OperatorHierarchy
The operator hierarchy type.
Definition amg.hh:83
virtual SolverCategory::Category category() const
Category of the preconditioner (see SolverCategory::Category).
Definition amg.hh:195
friend class KAMG
Definition amg.hh:68
PI ParallelInformation
The type of the parallel information. Either OwnerOverlapCommunication or another type describing the...
Definition amg.hh:81
@ none
Definition amg.hh:628
@ umfpack
Definition amg.hh:628
@ superlu
Definition amg.hh:628
@ atOnceAccu
Accumulate data to one process at once.
Definition parameters.hh:243
@ noAccu
No data accumulution.
Definition parameters.hh:237
@ successiveAccu
Successively accumulate to fewer processes.
Definition parameters.hh:247
Definition allocator.hh:11
std::shared_ptr< ScalarProduct< X > > createScalarProduct(const Comm &comm, SolverCategory::Category category)
Definition scalarproducts.hh:242
MatrixSparsityPatternGatherScatter< M, I >::ColIter MatrixSparsityPatternGatherScatter< M, I >::col
Definition matrixredistribute.hh:591
const Dtype_t BaseGetSuperLUType< T >::type
Definition supermatrix.hh:135
Definition novlpschwarz.hh:256
A sparse block matrix with compressed row storage.
Definition bcrsmatrix.hh:467
A generic dynamic dense matrix.
Definition matrix.hh:561
MatrixImp::DenseMatrixBase< T, A >::ConstIterator ConstRowIterator
Const iterator over the matrix rows.
Definition matrix.hh:586
RowIterator end()
Get iterator to one beyond last row.
Definition matrix.hh:616
RowIterator begin()
Get iterator to first row.
Definition matrix.hh:610
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition matrix.hh:565
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition matrix.hh:589
T block_type
Export the type representing the components.
Definition matrix.hh:568
Definition matrixutils.hh:27
A nonoverlapping operator with communication object.
Definition novlpschwarz.hh:61
Adapter to turn a matrix into a linear operator.
Definition operators.hh:135
Norm that uses only the [N][N] entry of the block to determine couplings.
Definition aggregates.hh:381
Functor using the row sum (infinity) norm to determine strong couplings.
Definition aggregates.hh:465
Definition aggregates.hh:486
Definition aggregates.hh:502
Criterion taking advantage of symmetric matrices.
Definition aggregates.hh:525
Criterion suitable for unsymmetric matrices.
Definition aggregates.hh:545
an algebraic multigrid method using a Krylov-cycle.
Definition kamg.hh:140
Two grid operator for AMG with Krylov cycle.
Definition kamg.hh:33
Parallel algebraic multigrid based on agglomeration.
Definition amg.hh:66
Definition amg.hh:626
Definition amg.hh:1170
Definition amg.hh:1171
An overlapping Schwarz operator.
Definition schwarz.hh:75
A hierarchy of containers (e.g. matrices or vectors).
Definition hierarchy.hh:40
LevelIterator< Hierarchy< T, A >, T > Iterator
Type of the mutable iterator.
Definition hierarchy.hh:220
The hierarchies build by the coarsening process.
Definition matrixhierarchy.hh:61
Dune::Amg::Hierarchy< ParallelInformation, Allocator > ParallelInformationHierarchy
Definition matrixhierarchy.hh:82
The criterion describing the stop criteria for the coarsening process.
Definition matrixhierarchy.hh:283
All parameters for AMG.
Definition parameters.hh:416
Definition pinfo.hh:28
Definition transfer.hh:32
Base class for matrix free definition of preconditioners.
Definition preconditioner.hh:33
X::field_type field_type
Definition preconditioner.hh:40
Base class for scalar product and norm computation.
Definition scalarproducts.hh:52
Statistics about the application of an inverse operator.
Definition solver.hh:50
bool converged
True if convergence criterion has been met.
Definition solver.hh:75
Abstract base class for all solvers.
Definition solver.hh:101
Categories for the solvers.
Definition solvercategory.hh:22
Category
Definition solvercategory.hh:23
static Category category(const OP &op, decltype(op.category()) *=nullptr)
Helperfunction to extract the solver category either from an enum, or from the newly introduced virtu...
Definition solvercategory.hh:34
Definition solvercategory.hh:54
Definition solverregistry.hh:97
@ value
Whether this is a direct solver.
Definition solvertype.hh:24
SuperLu Solver.
Definition superlu.hh:271
Definition umfpack.hh:53
The UMFPack direct sparse solver.
Definition umfpack.hh:265