twolevelmethodcpr.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_ISTL_TWOLEVELMETHODCPR_HH
4#define DUNE_ISTL_TWOLEVELMETHODCPR_HH
5
6// NOTE: This file is a modified version of dune/istl/paamg/twolevelmethod.hh from
7// dune-istl release 2.6.0. Modifications have been kept as minimal as possible.
8
9#include <dune/istl/operators.hh>
10//#include "amg.hh"
11//#include"galerkin.hh"
12#include <dune/istl/paamg/amg.hh>
13#include <dune/istl/paamg/galerkin.hh>
14#include <dune/istl/solver.hh>
15
16#include <dune/common/unused.hh>
17#include <dune/common/version.hh>
18
19#include <algorithm>
20#include <cstddef>
21#include <iostream>
22#include <memory>
23#include <tuple>
24#include <vector>
25
33namespace Dune
34{
35namespace Amg
36{
37
47template<class FO, class CO>
49{
50public:
55 typedef FO FineOperatorType;
59 typedef typename FineOperatorType::range_type FineRangeType;
63 typedef typename FineOperatorType::domain_type FineDomainType;
72 typedef typename CoarseOperatorType::range_type CoarseRangeType;
76 typedef typename CoarseOperatorType::domain_type CoarseDomainType;
81 std::shared_ptr<CoarseOperatorType>& getCoarseLevelOperator()
82 {
83 return operator_;
84 }
90 {
91 return rhs_;
92 }
93
99 {
100 return lhs_;
101 }
111 virtual void moveToCoarseLevel(const FineRangeType& fineRhs)=0;
121 virtual void moveToFineLevel(FineDomainType& fineLhs)=0;
129 virtual void createCoarseLevelSystem(const FineOperatorType& fineOperator)=0;
130
134 virtual void calculateCoarseEntries(const FineOperatorType& fineOperator) = 0;
135
137 virtual LevelTransferPolicyCpr* clone() const =0;
138
141
142 protected:
148 std::shared_ptr<CoarseOperatorType> operator_;
149};
150
156template<class O, class C>
158 : public LevelTransferPolicyCpr<O,O>
159{
160 typedef Dune::Amg::AggregatesMap<typename O::matrix_type::size_type> AggregatesMap;
161public:
163 typedef C Criterion;
164 typedef SequentialInformation ParallelInformation;
165
167 : criterion_(crit)
168 {}
169
170 void createCoarseLevelSystem(const O& fineOperator)
171 {
172 prolongDamp_ = criterion_.getProlongationDampingFactor();
173 GalerkinProduct<ParallelInformation> productBuilder;
174 typedef typename Dune::Amg::MatrixGraph<const typename O::matrix_type> MatrixGraph;
175 typedef typename Dune::Amg::PropertiesGraph<MatrixGraph,Dune::Amg::VertexProperties,
176 Dune::Amg::EdgeProperties,Dune::IdentityMap,Dune::IdentityMap> PropertiesGraph;
177 MatrixGraph mg(fineOperator.getmat());
178 PropertiesGraph pg(mg,Dune::IdentityMap(),Dune::IdentityMap());
179 typedef NegateSet<typename ParallelInformation::OwnerSet> OverlapFlags;
180
181 aggregatesMap_.reset(new AggregatesMap(pg.maxVertex()+1));
182
183 int noAggregates, isoAggregates, oneAggregates, skippedAggregates;
184
185 std::tie(noAggregates, isoAggregates, oneAggregates, skippedAggregates) =
186 aggregatesMap_->buildAggregates(fineOperator.getmat(), pg, criterion_, true);
187 std::cout<<"no aggregates="<<noAggregates<<" iso="<<isoAggregates<<" one="<<oneAggregates<<" skipped="<<skippedAggregates<<std::endl;
188 // misuse coarsener to renumber aggregates
189 Dune::Amg::IndicesCoarsener<Dune::Amg::SequentialInformation,int> renumberer;
190 typedef std::vector<bool>::iterator Iterator;
191 typedef Dune::IteratorPropertyMap<Iterator, Dune::IdentityMap> VisitedMap;
192 std::vector<bool> excluded(fineOperator.getmat().N(), false);
193 VisitedMap vm(excluded.begin(), Dune::IdentityMap());
195
196 std::size_t aggregates = coarsen(renumberer, pinfo, pg, vm,*aggregatesMap_, noAggregates, true);
197
198 std::fill(excluded.begin(), excluded.end(), false);
199 matrix_.reset(productBuilder.build(mg, vm,
200 SequentialInformation(),
201 *aggregatesMap_,
202 aggregates,
203 OverlapFlags()));
204 productBuilder.calculate(fineOperator.getmat(), *aggregatesMap_, *matrix_, pinfo, OverlapFlags());
205 this->lhs_.resize(this->matrix_->M());
206 this->rhs_.resize(this->matrix_->N());
207 this->operator_.reset(new O(*matrix_));
208 }
209
210 void moveToCoarseLevel(const typename FatherType::FineRangeType& fineRhs)
211 {
212 Transfer<std::size_t,typename FatherType::FineRangeType,ParallelInformation>
213 ::restrictVector(*aggregatesMap_, this->rhs_, fineRhs, ParallelInformation());
214 this->lhs_=0;
215 }
216
218 {
219 Transfer<std::size_t,typename FatherType::FineRangeType,ParallelInformation>
220 ::prolongateVector(*aggregatesMap_, this->lhs_, fineLhs,
221 prolongDamp_, ParallelInformation());
222 }
223
225 {
226 return new AggregationLevelTransferPolicyCpr(*this);
227 }
228
229private:
230 // trailing return type with decltype used for detecting the signature of coarsen member function by overloading this coarsen function
231 template <typename RN, typename PI, typename PG, typename VM, typename AM>
232 auto coarsen(RN& renumberer,
233 PI& pinfo,
234 PG& pg,
235 VM& vm,
236 AM& aggregatesMap,
237 int noAggregates,
238 bool useFixedOrder) ->
239 decltype(renumberer.coarsen(pinfo, pg, vm, aggregatesMap, pinfo, noAggregates, useFixedOrder))
240 {
241 return renumberer.coarsen(pinfo, pg, vm, aggregatesMap, pinfo, noAggregates, useFixedOrder);
242 }
243
244 template <typename RN, typename PI, typename PG, typename VM, typename AM>
245 auto coarsen(RN& renumberer,
246 PI& pinfo,
247 PG& pg,
248 VM& vm,
249 AM& aggregatesMap,
250 int noAggregates, ...)
251 {
252 return renumberer.coarsen(pinfo, pg, vm, aggregatesMap, pinfo, noAggregates);
253 }
254
255 typename O::matrix_type::field_type prolongDamp_;
256 std::shared_ptr<AggregatesMap> aggregatesMap_;
257 Criterion criterion_;
258 std::shared_ptr<typename O::matrix_type> matrix_;
259};
260
267template<class O, class S, class C>
269{
270public:
272 typedef O Operator;
274 typedef typename O::range_type X;
276 typedef C Criterion;
278 typedef S Smoother;
280 typedef typename Dune::Amg::SmootherTraits<S>::Arguments SmootherArgs;
282 typedef AMG<Operator,X,Smoother> AMGType;
289 : smootherArgs_(args), criterion_(c)
290 {}
293 : coarseOperator_(other.coarseOperator_), smootherArgs_(other.smootherArgs_),
294 criterion_(other.criterion_)
295 {}
296private:
303 struct AMGInverseOperator : public InverseOperator<X,X>
304 {
305 AMGInverseOperator(const typename AMGType::Operator& op,
306 const Criterion& crit,
307 const typename AMGType::SmootherArgs& args)
308 : amg_(op, crit,args), first_(true)
309 {}
310
311 void apply(X& x, X& b, [[maybe_unused]] double reduction, [[maybe_unused]] InverseOperatorResult& res)
312 {
313 if(first_)
314 {
315 amg_.pre(x,b);
316 first_=false;
317 x_=x;
318 }
319 amg_.apply(x,b);
320 }
321
322 void apply(X& x, X& b, InverseOperatorResult& res)
323 {
324 return apply(x,b,1e-8,res);
325 }
326
327 virtual SolverCategory::Category category() const
328 {
329 return amg_.category();
330 }
331
332 ~AMGInverseOperator()
333 {
334 if(!first_)
335 amg_.post(x_);
336 }
337 AMGInverseOperator(const AMGInverseOperator& other)
338 : x_(other.x_), amg_(other.amg_), first_(other.first_)
339 {
340 }
341 private:
342 X x_;
343 AMGType amg_;
344 bool first_;
345 };
346
347public:
349 typedef AMGInverseOperator CoarseLevelSolver;
350
358 template<class P>
360 {
361 coarseOperator_=transferPolicy.getCoarseLevelOperator();
362 AMGInverseOperator* inv = new AMGInverseOperator(*coarseOperator_,
363 criterion_,
364 smootherArgs_);
365
366 return inv; //std::shared_ptr<InverseOperator<X,X> >(inv);
367
368 }
369
370private:
372 std::shared_ptr<Operator> coarseOperator_;
374 SmootherArgs smootherArgs_;
376 Criterion criterion_;
377};
378
384template<class FO, class CSP, class S>
386 public Preconditioner<typename FO::domain_type, typename FO::range_type>
387{
388public:
392 typedef typename CoarseLevelSolverPolicy::CoarseLevelSolver CoarseLevelSolver;
401 typedef typename FineOperatorType::range_type FineRangeType;
405 typedef typename FineOperatorType::domain_type FineDomainType;
410 typedef typename CSP::Operator CoarseOperatorType;
414 typedef typename CoarseOperatorType::range_type CoarseRangeType;
418 typedef typename CoarseOperatorType::domain_type CoarseDomainType;
422 typedef S SmootherType;
423
439 std::shared_ptr<SmootherType> smoother,
441 CoarseOperatorType>& policy,
442 CoarseLevelSolverPolicy& coarsePolicy,
443 std::size_t preSteps=1, std::size_t postSteps=1)
444 : operator_(&op), smoother_(smoother),
445 preSteps_(preSteps), postSteps_(postSteps)
446 {
447 policy_ = policy.clone();
448 policy_->createCoarseLevelSystem(*operator_);
449 coarseSolver_=coarsePolicy.createCoarseLevelSolver(*policy_);
450 }
451
453 : operator_(other.operator_), coarseSolver_(new CoarseLevelSolver(*other.coarseSolver_)),
454 smoother_(other.smoother_), policy_(other.policy_->clone()),
455 preSteps_(other.preSteps_), postSteps_(other.postSteps_)
456 {}
457
459 {
460 // Each instance has its own policy.
461 delete policy_;
462 delete coarseSolver_;
463 }
464
466 std::shared_ptr<SmootherType> smoother,
467 CoarseLevelSolverPolicy& coarsePolicy)
468 {
469 updatePreconditioner(smoother, coarsePolicy);
470 }
471
472 void updatePreconditioner(std::shared_ptr<SmootherType> smoother,
473 CoarseLevelSolverPolicy& coarsePolicy)
474 {
475 smoother_ = smoother;
476 // We assume the matrix has the same sparsity structure and memory locations throughout, only the values are changed.
477 smoother_->update();
478 if (coarseSolver_) {
479 policy_->calculateCoarseEntries(*operator_);
480 coarsePolicy.setCoarseOperator(*policy_);
481 coarseSolver_->updatePreconditioner();
482 } else {
483 // we should probably not be heere
484 policy_->createCoarseLevelSystem(*operator_);
485 coarseSolver_ = coarsePolicy.createCoarseLevelSolver(*policy_);
486 }
487 }
488
490 {
491 smoother_->pre(x,b);
492 }
493
494 void post([[maybe_unused]] FineDomainType& x)
495 {
496 }
497
498 bool hasPerfectUpdate() const
499 {
500 // The two-level method has perfect update if both the finesmoother and coarse solver do.
501 return smoother_->hasPerfectUpdate() && coarseSolver_->hasPerfectUpdate();
502 }
503
505 {
506 FineDomainType u(v);
507 FineRangeType rhs(d);
508 LevelContext context;
509 SequentialInformation info;
510 context.pinfo=&info;
511 context.lhs=&u;
512 context.update=&v;
513 context.smoother=smoother_;
514 context.rhs=&rhs;
515 context.matrix=operator_;
516 // Presmoothing
517 presmooth(context, preSteps_);
518 //Coarse grid correction
519 policy_->moveToCoarseLevel(*context.rhs);
521 coarseSolver_->apply(policy_->getCoarseLevelLhs(), policy_->getCoarseLevelRhs(), res);
522 *context.lhs=0;
523 policy_->moveToFineLevel(*context.lhs);
524 *context.update += *context.lhs;
525 // Postsmoothing
526 postsmooth(context, postSteps_);
527
528 }
529// //! Category of the preconditioner (see SolverCategory::Category)
530 virtual SolverCategory::Category category() const
531 {
532 return SolverCategory::sequential;
533 }
534
535private:
539 struct LevelContext
540 {
542 typedef S SmootherType;
544 std::shared_ptr<SmootherType> smoother;
546 FineDomainType* lhs;
547 /*
548 * @brief The right hand side holding the current residual.
549 *
550 * This is passed to the smoother as the right hand side.
551 */
552 FineRangeType* rhs;
558 FineDomainType* update;
560 SequentialInformation* pinfo;
566 const FineOperatorType* matrix;
567 };
568 const FineOperatorType* operator_;
570 CoarseLevelSolver* coarseSolver_;
572 std::shared_ptr<S> smoother_;
574 LevelTransferPolicyCpr<FO,typename CSP::Operator>* policy_;
576 std::size_t preSteps_;
578 std::size_t postSteps_;
579};
580}// end namespace Amg
581}// end namespace Dune
582
584#endif
A LeveTransferPolicy that used aggregation to construct the coarse level system.
Definition: twolevelmethodcpr.hh:159
SequentialInformation ParallelInformation
Definition: twolevelmethodcpr.hh:164
void moveToFineLevel(typename FatherType::FineDomainType &fineLhs)
Updates the fine level linear system after the correction of the coarse levels system.
Definition: twolevelmethodcpr.hh:217
void moveToCoarseLevel(const typename FatherType::FineRangeType &fineRhs)
Definition: twolevelmethodcpr.hh:210
AggregationLevelTransferPolicyCpr(const Criterion &crit)
Definition: twolevelmethodcpr.hh:166
LevelTransferPolicyCpr< O, O > FatherType
Definition: twolevelmethodcpr.hh:162
void createCoarseLevelSystem(const O &fineOperator)
Algebraically creates the coarse level system.
Definition: twolevelmethodcpr.hh:170
C Criterion
Definition: twolevelmethodcpr.hh:163
AggregationLevelTransferPolicyCpr * clone() const
Clone the current object.
Definition: twolevelmethodcpr.hh:224
Abstract base class for transfer between levels and creation of the coarse level system.
Definition: twolevelmethodcpr.hh:49
CoarseOperatorType::range_type CoarseRangeType
The type of the range of the coarse level operator.
Definition: twolevelmethodcpr.hh:72
CoarseDomainType & getCoarseLevelLhs()
Get the coarse level left hand side.
Definition: twolevelmethodcpr.hh:98
virtual LevelTransferPolicyCpr * clone() const =0
Clone the current object.
FO FineOperatorType
The linear operator of the finel level system. Has to be derived from AssembledLinearOperator.
Definition: twolevelmethodcpr.hh:55
virtual void createCoarseLevelSystem(const FineOperatorType &fineOperator)=0
Algebraically creates the coarse level system.
virtual void moveToCoarseLevel(const FineRangeType &fineRhs)=0
Transfers the data to the coarse level.
CoarseOperatorType::domain_type CoarseDomainType
The type of the domain of the coarse level operator.
Definition: twolevelmethodcpr.hh:76
FineOperatorType::range_type FineRangeType
The type of the range of the fine level operator.
Definition: twolevelmethodcpr.hh:59
CoarseRangeType & getCoarseLevelRhs()
Get the coarse level right hand side.
Definition: twolevelmethodcpr.hh:89
virtual ~LevelTransferPolicyCpr()
Destructor.
Definition: twolevelmethodcpr.hh:140
virtual void moveToFineLevel(FineDomainType &fineLhs)=0
Updates the fine level linear system after the correction of the coarse levels system.
virtual void calculateCoarseEntries(const FineOperatorType &fineOperator)=0
???.
CoarseDomainType lhs_
The coarse level lhs.
Definition: twolevelmethodcpr.hh:146
CoarseRangeType rhs_
The coarse level rhs.
Definition: twolevelmethodcpr.hh:144
FineOperatorType::domain_type FineDomainType
The type of the domain of the fine level operator.
Definition: twolevelmethodcpr.hh:63
CO CoarseOperatorType
The linear operator of the finel level system. Has to be derived from AssembledLinearOperator.
Definition: twolevelmethodcpr.hh:68
std::shared_ptr< CoarseOperatorType > & getCoarseLevelOperator()
Get the coarse level operator.
Definition: twolevelmethodcpr.hh:81
std::shared_ptr< CoarseOperatorType > operator_
the coarse level linear operator.
Definition: twolevelmethodcpr.hh:148
A policy class for solving the coarse level system using one step of AMG.
Definition: twolevelmethodcpr.hh:269
AMG< Operator, X, Smoother > AMGType
The type of the AMG construct on the coarse level.
Definition: twolevelmethodcpr.hh:282
OneStepAMGCoarseSolverPolicyCpr(const OneStepAMGCoarseSolverPolicyCpr &other)
Copy constructor.
Definition: twolevelmethodcpr.hh:292
AMGInverseOperator CoarseLevelSolver
The type of solver constructed for the coarse level.
Definition: twolevelmethodcpr.hh:349
S Smoother
The type of the smoother used in AMG.
Definition: twolevelmethodcpr.hh:278
C Criterion
The type of the crition used for the aggregation within AMG.
Definition: twolevelmethodcpr.hh:276
Dune::Amg::SmootherTraits< S >::Arguments SmootherArgs
The type of the arguments used for constructing the smoother.
Definition: twolevelmethodcpr.hh:280
CoarseLevelSolver * createCoarseLevelSolver(P &transferPolicy)
Constructs a coarse level solver.
Definition: twolevelmethodcpr.hh:359
O::range_type X
The type of the range and domain of the operator.
Definition: twolevelmethodcpr.hh:274
OneStepAMGCoarseSolverPolicyCpr(const SmootherArgs &args, const Criterion &c)
Constructs the coarse solver policy.
Definition: twolevelmethodcpr.hh:288
O Operator
The type of the linear operator used.
Definition: twolevelmethodcpr.hh:272
Definition: twolevelmethodcpr.hh:387
void updatePreconditioner(FineOperatorType &, std::shared_ptr< SmootherType > smoother, CoarseLevelSolverPolicy &coarsePolicy)
Definition: twolevelmethodcpr.hh:465
virtual SolverCategory::Category category() const
Definition: twolevelmethodcpr.hh:530
S SmootherType
The type of the fine level smoother.
Definition: twolevelmethodcpr.hh:422
FineOperatorType::range_type FineRangeType
The type of the range of the fine level operator.
Definition: twolevelmethodcpr.hh:401
TwoLevelMethodCpr(const FineOperatorType &op, std::shared_ptr< SmootherType > smoother, const LevelTransferPolicyCpr< FineOperatorType, CoarseOperatorType > &policy, CoarseLevelSolverPolicy &coarsePolicy, std::size_t preSteps=1, std::size_t postSteps=1)
Constructs a two level method.
Definition: twolevelmethodcpr.hh:438
FineOperatorType::domain_type FineDomainType
The type of the domain of the fine level operator.
Definition: twolevelmethodcpr.hh:405
void apply(FineDomainType &v, const FineRangeType &d)
Definition: twolevelmethodcpr.hh:504
~TwoLevelMethodCpr()
Definition: twolevelmethodcpr.hh:458
void pre(FineDomainType &x, FineRangeType &b)
Definition: twolevelmethodcpr.hh:489
CoarseOperatorType::domain_type CoarseDomainType
The type of the domain of the coarse level operator.
Definition: twolevelmethodcpr.hh:418
TwoLevelMethodCpr(const TwoLevelMethodCpr &other)
Definition: twolevelmethodcpr.hh:452
CSP::Operator CoarseOperatorType
The linear operator of the finel level system. Has to be derived from AssembledLinearOperator.
Definition: twolevelmethodcpr.hh:410
void post(FineDomainType &x)
Definition: twolevelmethodcpr.hh:494
CSP CoarseLevelSolverPolicy
The type of the policy for constructing the coarse level solver.
Definition: twolevelmethodcpr.hh:390
bool hasPerfectUpdate() const
Definition: twolevelmethodcpr.hh:498
CoarseLevelSolverPolicy::CoarseLevelSolver CoarseLevelSolver
The type of the coarse level solver.
Definition: twolevelmethodcpr.hh:392
CoarseOperatorType::range_type CoarseRangeType
The type of the range of the coarse level operator.
Definition: twolevelmethodcpr.hh:414
FO FineOperatorType
The linear operator of the finel level system. Has to be derived from AssembledLinearOperator.
Definition: twolevelmethodcpr.hh:397
void updatePreconditioner(std::shared_ptr< SmootherType > smoother, CoarseLevelSolverPolicy &coarsePolicy)
Definition: twolevelmethodcpr.hh:472
Definition: fvbaseprimaryvariables.hh:141
Dune::InverseOperatorResult InverseOperatorResult
Definition: GpuBridge.hpp:32