3#ifndef DUNE_ISTL_FASTAMG_HH
4#define DUNE_ISTL_FASTAMG_HH
21#include "fastamgsmoother.hh"
57 template<
class M,
class X,
class PI=SequentialInformation,
class A=std::allocator<X> >
137 std::size_t levels();
139 std::size_t maxlevels();
168 void createHierarchies(C& criterion,
169 const std::shared_ptr<const Operator>& matrixptr,
191 typename OperatorHierarchy::RedistributeInfoList::const_iterator
redist;
195 typename OperatorHierarchy::AggregatesMapList::const_iterator
aggregates;
215 void mgc(LevelContext& levelContext,
Domain& x,
const Range& b);
223 void presmooth(LevelContext& levelContext,
Domain& x,
const Range& b);
231 void postsmooth(LevelContext& levelContext,
Domain& x,
const Range& b);
239 void moveToFineLevel(LevelContext& levelContext,
bool processedFineLevel,
246 bool moveToCoarseLevel(LevelContext& levelContext);
252 void initIteratorsWithFineLevel(LevelContext& levelContext);
255 std::shared_ptr<OperatorHierarchy> matrices_;
257 std::shared_ptr<CoarseSolver> solver_;
259 std::shared_ptr<Hierarchy<Range,A>> rhs_;
261 std::shared_ptr<Hierarchy<Domain,A>> lhs_;
263 std::shared_ptr<Hierarchy<Domain,A>> residual_;
268 std::shared_ptr<ScalarProduct> scalarProduct_;
272 std::size_t preSteps_;
274 std::size_t postSteps_;
276 bool buildHierarchy_;
278 bool coarsesolverconverged;
280 typedef std::shared_ptr<Smoother> SmootherPointer;
281 SmootherPointer coarseSmoother_;
283 std::size_t verbosity_;
286 template<
class M,
class X,
class PI,
class A>
288 : matrices_(amg.matrices_), solver_(amg.solver_),
289 rhs_(), lhs_(), residual_(), scalarProduct_(amg.scalarProduct_),
290 gamma_(amg.gamma_), preSteps_(amg.preSteps_), postSteps_(amg.postSteps_),
291 symmetric(amg.symmetric), coarsesolverconverged(amg.coarsesolverconverged),
292 coarseSmoother_(amg.coarseSmoother_), verbosity_(amg.verbosity_)
295 template<
class M,
class X,
class PI,
class A>
299 rhs_(), lhs_(), residual_(), scalarProduct_(),
300 gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()),
301 postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(false),
302 symmetric(symmetric_), coarsesolverconverged(true),
303 coarseSmoother_(), verbosity_(parms.debugLevel())
305 if(preSteps_>1||postSteps_>1)
307 std::cerr<<
"WARNING only one step of smoothing is supported!"<<std::endl;
308 preSteps_=postSteps_=0;
310 assert(matrices_->isBuilt());
311 static_assert(std::is_same<PI,SequentialInformation>::value,
312 "Currently only sequential runs are supported");
314 template<
class M,
class X,
class PI,
class A>
321 : solver_(), rhs_(), lhs_(), residual_(), scalarProduct_(), gamma_(parms.getGamma()),
322 preSteps_(parms.getNoPreSmoothSteps()), postSteps_(parms.getNoPostSmoothSteps()),
323 buildHierarchy_(true),
324 symmetric(symmetric_), coarsesolverconverged(true),
325 coarseSmoother_(), verbosity_(criterion.debugLevel())
327 if(preSteps_>1||postSteps_>1)
329 std::cerr<<
"WARNING only one step of smoothing is supported!"<<std::endl;
330 preSteps_=postSteps_=1;
332 static_assert(std::is_same<PI,SequentialInformation>::value,
333 "Currently only sequential runs are supported");
338 createHierarchies(criterion, matrixptr, pinfo);
341 template<
class M,
class X,
class PI,
class A>
344 const std::shared_ptr<const Operator>& matrixptr,
348 matrices_ = std::make_shared<OperatorHierarchy>(
349 std::const_pointer_cast<Operator>(matrixptr),
352 matrices_->template build<NegateSet<typename PI::OwnerSet> >(criterion);
354 if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0)
355 std::cout<<
"Building Hierarchy of "<<matrices_->maxlevels()<<
" levels took "<<watch.
elapsed()<<
" seconds."<<std::endl;
357 if(buildHierarchy_ && matrices_->levels()==matrices_->maxlevels()) {
361 sargs.iterations = 1;
364 cargs.setArgs(sargs);
365 if(matrices_->redistributeInformation().back().isSetup()) {
367 cargs.setMatrix(matrices_->matrices().coarsest().getRedistributed().getmat());
368 cargs.setComm(matrices_->parallelInformation().coarsest().getRedistributed());
370 cargs.setMatrix(matrices_->matrices().coarsest()->getmat());
371 cargs.setComm(*matrices_->parallelInformation().coarsest());
375 scalarProduct_ = createScalarProduct<X>(cargs.getComm(),category());
377#if HAVE_SUPERLU|| HAVE_SUITESPARSE_UMFPACK
378#if HAVE_SUITESPARSE_UMFPACK
379#define DIRECTSOLVER UMFPack
381#define DIRECTSOLVER SuperLU
384 if(std::is_same<ParallelInformation,SequentialInformation>::value
385 || matrices_->parallelInformation().coarsest()->communicator().size()==1
386 || (matrices_->parallelInformation().coarsest().isRedistributed()
387 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()==1
388 && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()>0)) {
389 if(verbosity_>0 && matrices_->parallelInformation().coarsest()->communicator().rank()==0)
390 std::cout<<
"Using superlu"<<std::endl;
391 if(matrices_->parallelInformation().coarsest().isRedistributed())
393 if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
395 solver_.reset(
new DIRECTSOLVER<typename M::matrix_type>(matrices_->matrices().coarsest().getRedistributed().getmat(),
false,
false));
399 solver_.reset(
new DIRECTSOLVER<typename M::matrix_type>(matrices_->matrices().coarsest()->getmat(),
false,
false));
404 if(matrices_->parallelInformation().coarsest().isRedistributed())
406 if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
408 solver_.reset(
new BiCGSTABSolver<X>(
const_cast<M&
>(matrices_->matrices().coarsest().getRedistributed()),
410 *coarseSmoother_, 1E-2, 1000, 0));
414 solver_.reset(
new BiCGSTABSolver<X>(
const_cast<M&
>(*matrices_->matrices().coarsest()),
416 *coarseSmoother_, 1E-2, 1000, 0));
420 if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0)
421 std::cout<<
"Building Hierarchy of "<<matrices_->maxlevels()<<
" levels took "<<watch.
elapsed()<<
" seconds."<<std::endl;
425 template<
class M,
class X,
class PI,
class A>
433 typedef typename M::matrix_type
Matrix;
440 const Matrix& mat=matrices_->matrices().finest()->getmat();
441 for(RowIter row=mat.begin(); row!=mat.end(); ++row) {
442 bool isDirichlet =
true;
443 bool hasDiagonal =
false;
445 for(ColIter col=row->begin(); col!=row->end(); ++col) {
446 if(row.index()==col.index()) {
448 hasDiagonal = (*col != zero);
454 if(isDirichlet && hasDiagonal)
455 diag->solve(x[row.index()], b[row.index()]);
458 std::cout<<
" Preprocessing Dirichlet took "<<watch1.
elapsed()<<std::endl;
461 matrices_->parallelInformation().coarsest()->copyOwnerToAll(x,x);
462 rhs_ = std::make_shared<Hierarchy<Range,A>>(std::make_shared<Range>(b));
463 lhs_ = std::make_shared<Hierarchy<Domain,A>>(std::make_shared<Domain>(x));
464 residual_ = std::make_shared<Hierarchy<Domain,A>>(std::make_shared<Domain>(x));
465 matrices_->coarsenVector(*rhs_);
466 matrices_->coarsenVector(*lhs_);
467 matrices_->coarsenVector(*residual_);
474 template<
class M,
class X,
class PI,
class A>
477 return matrices_->levels();
479 template<
class M,
class X,
class PI,
class A>
480 std::size_t FastAMG<M,X,PI,A>::maxlevels()
482 return matrices_->maxlevels();
486 template<
class M,
class X,
class PI,
class A>
489 LevelContext levelContext;
491 initIteratorsWithFineLevel(levelContext);
493 assert(v.two_norm()==0);
496 if(matrices_->maxlevels()==1){
499 mgc(levelContext, v, b);
501 mgc(levelContext, v, d);
502 if(postSteps_==0||matrices_->maxlevels()==1)
503 levelContext.pinfo->copyOwnerToAll(v, v);
506 template<
class M,
class X,
class PI,
class A>
509 levelContext.matrix = matrices_->matrices().finest();
510 levelContext.pinfo = matrices_->parallelInformation().finest();
511 levelContext.redist =
512 matrices_->redistributeInformation().begin();
513 levelContext.aggregates = matrices_->aggregatesMaps().begin();
514 levelContext.lhs = lhs_->finest();
515 levelContext.residual = residual_->finest();
516 levelContext.rhs = rhs_->finest();
517 levelContext.level=0;
520 template<
class M,
class X,
class PI,
class A>
521 bool FastAMG<M,X,PI,A>
522 ::moveToCoarseLevel(LevelContext& levelContext)
524 bool processNextLevel=
true;
526 if(levelContext.redist->isSetup()) {
528 levelContext.redist->redistribute(
static_cast<const Range&
>(*levelContext.residual),
529 levelContext.residual.getRedistributed());
530 processNextLevel = levelContext.residual.getRedistributed().size()>0;
531 if(processNextLevel) {
533 ++levelContext.pinfo;
534 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
535 ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs,
536 static_cast<const Range&
>(levelContext.residual.getRedistributed()),
537 *levelContext.pinfo);
542 ++levelContext.pinfo;
543 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
544 ::restrictVector(*(*levelContext.aggregates), *levelContext.rhs,
545 static_cast<const Range&
>(*levelContext.residual), *levelContext.pinfo);
548 if(processNextLevel) {
550 ++levelContext.residual;
552 ++levelContext.matrix;
553 ++levelContext.level;
554 ++levelContext.redist;
556 if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()<matrices_->maxlevels()) {
558 ++levelContext.aggregates;
562 *levelContext.residual=0;
564 return processNextLevel;
567 template<
class M,
class X,
class PI,
class A>
568 void FastAMG<M,X,PI,A>
569 ::moveToFineLevel(LevelContext& levelContext,
bool processNextLevel, Domain& x)
571 if(processNextLevel) {
572 if(levelContext.matrix != matrices_->matrices().coarsest() || matrices_->levels()<matrices_->maxlevels()) {
574 --levelContext.aggregates;
576 --levelContext.redist;
577 --levelContext.level;
579 --levelContext.matrix;
580 --levelContext.residual;
585 if(levelContext.redist->isSetup()) {
588 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
589 ::prolongateVector(*(*levelContext.aggregates), *coarseLhs, x,
590 levelContext.lhs.getRedistributed(),
591 matrices_->getProlongationDampingFactor(),
592 *levelContext.pinfo, *levelContext.redist);
594 Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
595 ::prolongateVector(*(*levelContext.aggregates), *coarseLhs, x,
596 matrices_->getProlongationDampingFactor(), *levelContext.pinfo);
602 if(processNextLevel) {
609 template<
class M,
class X,
class PI,
class A>
610 void FastAMG<M,X,PI,A>
611 ::presmooth(LevelContext& levelContext, Domain& x,
const Range& b)
615 *levelContext.residual,
619 template<
class M,
class X,
class PI,
class A>
620 void FastAMG<M,X,PI,A>
621 ::postsmooth(LevelContext& levelContext, Domain& x,
const Range& b)
624 ::apply(levelContext.matrix->getmat(), x, *levelContext.residual, b);
628 template<
class M,
class X,
class PI,
class A>
631 return IsDirectSolver< CoarseSolver>::value;
634 template<
class M,
class X,
class PI,
class A>
637 if(levelContext.matrix == matrices_->matrices().coarsest() && levels()==maxlevels()) {
641 if(levelContext.redist->isSetup()) {
642 levelContext.redist->redistribute(b, levelContext.rhs.getRedistributed());
643 if(levelContext.rhs.getRedistributed().size()>0) {
645 levelContext.pinfo.getRedistributed().copyOwnerToAll(levelContext.rhs.getRedistributed(),
646 levelContext.rhs.getRedistributed());
647 solver_->apply(levelContext.lhs.getRedistributed(), levelContext.rhs.getRedistributed(), res);
649 levelContext.redist->redistributeBackward(v, levelContext.lhs.getRedistributed());
650 levelContext.pinfo->copyOwnerToAll(v, v);
652 levelContext.pinfo->copyOwnerToAll(b, b);
653 solver_->apply(v,
const_cast<Range&
>(b), res);
659 coarsesolverconverged =
false;
665#ifndef DUNE_AMG_NO_COARSEGRIDCORRECTION
666 bool processNextLevel = moveToCoarseLevel(levelContext);
668 if(processNextLevel) {
670 for(std::size_t i=0; i<gamma_; i++)
671 mgc(levelContext, *levelContext.lhs, *levelContext.rhs);
674 moveToFineLevel(levelContext, processNextLevel, v);
679 if(levelContext.matrix == matrices_->matrices().finest()) {
680 coarsesolverconverged = matrices_->parallelInformation().finest()->communicator().prod(coarsesolverconverged);
681 if(!coarsesolverconverged)
682 DUNE_THROW(MathError,
"Coarse solver did not converge");
691 template<
class M,
class X,
class PI,
class A>
700 template<
class M,
class X,
class PI,
class A>
704 matrices_->getCoarsestAggregatesOnFinest(cont);
A fast (sequential) algebraic multigrid based on agglomeration that saves memory bandwidth.
Definition: fastamg.hh:59
LevelIterator< Hierarchy< ParallelInformation, Allocator >, ParallelInformation > Iterator
Type of the mutable iterator.
Definition: hierarchy.hh:215
LevelIterator< const Hierarchy< MatrixOperator, Allocator >, const MatrixOperator > ConstIterator
Type of the const iterator.
Definition: hierarchy.hh:218
The hierarchies build by the coarsening process.
Definition: matrixhierarchy.hh:59
All parameters for AMG.
Definition: parameters.hh:391
ConstIterator class for sequential access.
Definition: matrix.hh:401
A generic dynamic dense matrix.
Definition: matrix.hh:558
typename Imp::BlockTraits< T >::field_type field_type
Export the type representing the underlying field.
Definition: matrix.hh:562
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:586
T block_type
Export the type representing the components.
Definition: matrix.hh:565
The negation of a set. An item is contained in the set if and only if it is not contained in the nega...
Definition: enumset.hh:95
Base class for matrix free definition of preconditioners.
Definition: preconditioner.hh:30
Base class for scalar product and norm computation.
Definition: scalarproducts.hh:48
Sequential SSOR preconditioner.
Definition: preconditioners.hh:138
A simple stop watch.
Definition: timer.hh:41
void reset() noexcept
Reset timer while keeping the running/stopped state.
Definition: timer.hh:55
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:75
A few common exception classes.
Some generic functions for pretty printing vectors and matrices.
decltype(auto) apply(F &&f, ArgTuple &&args)
Apply function with arguments given as tuple.
Definition: apply.hh:46
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix
The iterator over the matrices.
Definition: fastamg.hh:183
void getCoarsestAggregateNumbers(std::vector< std::size_t, A1 > &cont)
Get the aggregate number of each unknown on the coarsest level.
Definition: fastamg.hh:702
ParallelInformationHierarchy::Iterator pinfo
The iterator over the parallel information.
Definition: fastamg.hh:187
void recalculateHierarchy()
Recalculate the matrix hierarchy.
Definition: fastamg.hh:149
void post(Domain &x)
Clean up.
Definition: fastamg.hh:692
X Domain
The domain type.
Definition: fastamg.hh:76
Hierarchy< Domain, A >::Iterator residual
The iterator over the residuals.
Definition: fastamg.hh:203
virtual SolverCategory::Category category() const
Category of the preconditioner (see SolverCategory::Category)
Definition: fastamg.hh:122
MatrixHierarchy< M, ParallelInformation, A > OperatorHierarchy
The operator hierarchy type.
Definition: fastamg.hh:71
OperatorHierarchy::RedistributeInfoList::const_iterator redist
The iterator over the redistribution information.
Definition: fastamg.hh:191
X Range
The range type.
Definition: fastamg.hh:78
PI ParallelInformation
The type of the parallel information. Either OwnerOverlapCommunication or another type describing the...
Definition: fastamg.hh:69
M Operator
The matrix operator type.
Definition: fastamg.hh:62
InverseOperator< X, X > CoarseSolver
the type of the coarse solver.
Definition: fastamg.hh:80
bool usesDirectCoarseLevelSolver() const
Check whether the coarse solver used is a direct solver.
Definition: fastamg.hh:629
Hierarchy< Domain, A >::Iterator lhs
The iterator over the left hand side.
Definition: fastamg.hh:199
Hierarchy< Range, A >::Iterator rhs
The iterator over the right hand sided.
Definition: fastamg.hh:207
std::size_t level
The level index.
Definition: fastamg.hh:211
void apply(Domain &v, const Range &d)
Apply one step of the preconditioner to the system A(v)=d.
Definition: fastamg.hh:487
OperatorHierarchy::ParallelInformationHierarchy ParallelInformationHierarchy
The parallal data distribution hierarchy type.
Definition: fastamg.hh:73
void pre(Domain &x, Range &b)
Prepare the preconditioner.
Definition: fastamg.hh:426
FastAMG(OperatorHierarchy &matrices, CoarseSolver &coarseSolver, const Parameters &parms, bool symmetric=true)
Construct a new amg with a specific coarse solver.
Definition: fastamg.hh:296
OperatorHierarchy::AggregatesMapList::const_iterator aggregates
The iterator over the aggregates maps.
Definition: fastamg.hh:195
void presmooth(LevelContext &levelContext, size_t steps)
Apply pre smoothing on the current level.
Definition: smoother.hh:468
const void * Arguments
A type holding all the arguments needed to call the constructor.
Definition: construction.hh:44
static std::shared_ptr< T > construct(Arguments &args)
Construct an object with the specified arguments.
Definition: construction.hh:52
void postsmooth(LevelContext &levelContext, size_t steps)
Apply post smoothing on the current level.
Definition: smoother.hh:490
Provides a classes representing the hierarchies in AMG.
Dune namespace.
Definition: alignedallocator.hh:14
shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:75
Define general preconditioner interface.
Define base class for scalar product and norm.
Classes for the generic construction and application of the smoothers.
Implementations of the inverse operator interface.
Templates characterizing the type of a solver.
Traits class for getting the attribute class of a smoother.
Definition: smoother.hh:65
Statistics about the application of an inverse operator.
Definition: solver.hh:46
bool converged
True if convergence criterion has been met.
Definition: solver.hh:71
Category
Definition: solvercategory.hh:21
@ sequential
Category for sequential solvers.
Definition: solvercategory.hh:23
Classes for using SuperLU with ISTL matrices.
Prolongation and restriction for amg.
Traits for type conversions and type information.
Classes for using UMFPack with ISTL matrices.
Definition of the DUNE_UNUSED macro for the case that config.h is not available.