opm-simulators
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 
33 namespace Dune
34 {
35 namespace Amg
36 {
37 
47 template<class FO, class CO>
49 {
50 public:
55  typedef FO FineOperatorType;
59  typedef typename FineOperatorType::range_type FineRangeType;
63  typedef typename FineOperatorType::domain_type FineDomainType;
68  typedef CO CoarseOperatorType;
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 
156 template<class O, class C>
158  : public LevelTransferPolicyCpr<O,O>
159 {
160  typedef Dune::Amg::AggregatesMap<typename O::matrix_type::size_type> AggregatesMap;
161 public:
163  typedef C Criterion;
164  typedef SequentialInformation ParallelInformation;
165 
166  explicit AggregationLevelTransferPolicyCpr(const Criterion& crit)
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());
194  ParallelInformation pinfo;
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 
229 private:
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 
267 template<class O, class S, class C>
269 {
270 public:
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  {}
296 private:
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 
347 public:
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 
370 private:
372  std::shared_ptr<Operator> coarseOperator_;
374  SmootherArgs smootherArgs_;
376  Criterion criterion_;
377 };
378 
384 template<class FO, class CSP, class S>
386  public Preconditioner<typename FO::domain_type, typename FO::range_type>
387 {
388 public:
392  typedef typename CoarseLevelSolverPolicy::CoarseLevelSolver CoarseLevelSolver;
397  typedef FO FineOperatorType;
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 
437  std::shared_ptr<SmootherType> smoother,
439  CoarseOperatorType>& policy,
440  CoarseLevelSolverPolicy& coarsePolicy,
441  std::size_t preSteps = 1, std::size_t postSteps = 1)
442  : operator_(&op), smoother_(smoother),
443  preSteps_(preSteps), postSteps_(postSteps)
444  {
445  policy_ = policy.clone();
446  policy_->createCoarseLevelSystem(*operator_);
447  coarseSolver_=coarsePolicy.createCoarseLevelSolver(*policy_);
448  }
449 
451  : operator_(other.operator_), coarseSolver_(new CoarseLevelSolver(*other.coarseSolver_)),
452  smoother_(other.smoother_), policy_(other.policy_->clone()),
453  preSteps_(other.preSteps_), postSteps_(other.postSteps_)
454  {}
455 
457  {
458  // Each instance has its own policy.
459  delete policy_;
460  delete coarseSolver_;
461  }
462 
463  void updatePreconditioner(FineOperatorType& /* op */,
464  std::shared_ptr<SmootherType> smoother,
465  CoarseLevelSolverPolicy& coarsePolicy)
466  {
467  updatePreconditioner(smoother, coarsePolicy);
468  }
469 
470  void updatePreconditioner(std::shared_ptr<SmootherType> smoother,
471  CoarseLevelSolverPolicy& coarsePolicy)
472  {
473  smoother_ = smoother;
474  // We assume the matrix has the same sparsity structure and memory locations throughout, only the values are changed.
475  smoother_->update();
476  if (coarseSolver_) {
477  policy_->calculateCoarseEntries(*operator_);
478  coarsePolicy.setCoarseOperator(*policy_);
479  coarseSolver_->updatePreconditioner();
480  } else {
481  // we should probably not be heere
482  policy_->createCoarseLevelSystem(*operator_);
483  coarseSolver_ = coarsePolicy.createCoarseLevelSolver(*policy_);
484  }
485  }
486 
487  void pre(FineDomainType& x, FineRangeType& b)
488  {
489  if (x.dim() != u_.dim()) {
490  u_.resize(x.dim());
491  }
492  if (b.dim() != rhs_.dim()) {
493  rhs_.resize(b.dim());
494  }
495  smoother_->pre(x,b);
496  }
497 
498  void post([[maybe_unused]] FineDomainType& x)
499  {
500  }
501 
502  bool hasPerfectUpdate() const
503  {
504  // The two-level method has perfect update if both the finesmoother and coarse solver do.
505  return smoother_->hasPerfectUpdate() && coarseSolver_->hasPerfectUpdate();
506  }
507 
508  void apply(FineDomainType& v, const FineRangeType& d)
509  {
510  u_ = v;
511  rhs_ = d;
512  LevelContext context;
513  SequentialInformation info;
514  context.pinfo=&info;
515  context.lhs=&u_;
516  context.update=&v;
517  context.smoother=smoother_;
518  context.rhs=&rhs_;
519  context.matrix=operator_;
520  // Presmoothing
521  presmooth(context, preSteps_);
522  //Coarse grid correction
523  policy_->moveToCoarseLevel(*context.rhs);
524  InverseOperatorResult res;
525  coarseSolver_->apply(policy_->getCoarseLevelLhs(), policy_->getCoarseLevelRhs(), res);
526  *context.lhs=0;
527  policy_->moveToFineLevel(*context.lhs);
528  *context.update += *context.lhs;
529  // Postsmoothing
530  postsmooth(context, postSteps_);
531 
532  }
533 // //! Category of the preconditioner (see SolverCategory::Category)
534  virtual SolverCategory::Category category() const
535  {
536  return SolverCategory::sequential;
537  }
538 
539 private:
543  struct LevelContext
544  {
546  typedef S SmootherType;
548  std::shared_ptr<SmootherType> smoother;
550  FineDomainType* lhs;
551  /*
552  * @brief The right hand side holding the current residual.
553  *
554  * This is passed to the smoother as the right hand side.
555  */
556  FineRangeType* rhs;
562  FineDomainType* update;
564  SequentialInformation* pinfo;
570  const FineOperatorType* matrix;
571  };
572  const FineOperatorType* operator_;
574  CoarseLevelSolver* coarseSolver_;
576  std::shared_ptr<S> smoother_;
578  LevelTransferPolicyCpr<FO,typename CSP::Operator>* policy_;
580  std::size_t preSteps_;
582  std::size_t postSteps_;
584  mutable FineDomainType u_;
586  mutable FineRangeType rhs_;
587 };
588 }// end namespace Amg
589 }// end namespace Dune
590 
592 #endif
C Criterion
The type of the crition used for the aggregation within AMG.
Definition: twolevelmethodcpr.hh:276
CoarseOperatorType::domain_type CoarseDomainType
The type of the domain of the coarse level operator.
Definition: twolevelmethodcpr.hh:418
virtual void moveToCoarseLevel(const FineRangeType &fineRhs)=0
Transfers the data to the coarse level.
CoarseRangeType & getCoarseLevelRhs()
Get the coarse level right hand side.
Definition: twolevelmethodcpr.hh:89
AMGInverseOperator CoarseLevelSolver
The type of solver constructed for the coarse level.
Definition: twolevelmethodcpr.hh:349
std::shared_ptr< CoarseOperatorType > operator_
the coarse level linear operator.
Definition: twolevelmethodcpr.hh:148
FineOperatorType::domain_type FineDomainType
The type of the domain of the fine level operator.
Definition: twolevelmethodcpr.hh:63
CoarseLevelSolverPolicy::CoarseLevelSolver CoarseLevelSolver
The type of the coarse level solver.
Definition: twolevelmethodcpr.hh:392
void moveToFineLevel(typename FatherType::FineDomainType &fineLhs)
Updates the fine level linear system after the correction of the coarse levels system.
Definition: twolevelmethodcpr.hh:217
O::range_type X
The type of the range and domain of the operator.
Definition: twolevelmethodcpr.hh:274
Definition: fvbaseprimaryvariables.hh:161
virtual void calculateCoarseEntries(const FineOperatorType &fineOperator)=0
???.
CSP::Operator CoarseOperatorType
The linear operator of the finel level system.
Definition: twolevelmethodcpr.hh:410
A LeveTransferPolicy that used aggregation to construct the coarse level system.
Definition: twolevelmethodcpr.hh:157
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:436
std::shared_ptr< CoarseOperatorType > & getCoarseLevelOperator()
Get the coarse level operator.
Definition: twolevelmethodcpr.hh:81
O Operator
The type of the linear operator used.
Definition: twolevelmethodcpr.hh:272
Definition: twolevelmethodcpr.hh:385
virtual void moveToFineLevel(FineDomainType &fineLhs)=0
Updates the fine level linear system after the correction of the coarse levels system.
CoarseOperatorType::range_type CoarseRangeType
The type of the range of the coarse level operator.
Definition: twolevelmethodcpr.hh:414
OneStepAMGCoarseSolverPolicyCpr(const SmootherArgs &args, const Criterion &c)
Constructs the coarse solver policy.
Definition: twolevelmethodcpr.hh:288
CO CoarseOperatorType
The linear operator of the finel level system.
Definition: twolevelmethodcpr.hh:68
FO FineOperatorType
The linear operator of the finel level system.
Definition: twolevelmethodcpr.hh:397
A policy class for solving the coarse level system using one step of AMG.
Definition: twolevelmethodcpr.hh:268
CSP CoarseLevelSolverPolicy
The type of the policy for constructing the coarse level solver.
Definition: twolevelmethodcpr.hh:390
CoarseOperatorType::domain_type CoarseDomainType
The type of the domain of the coarse level operator.
Definition: twolevelmethodcpr.hh:76
FineOperatorType::domain_type FineDomainType
The type of the domain of the fine level operator.
Definition: twolevelmethodcpr.hh:405
FineOperatorType::range_type FineRangeType
The type of the range of the fine level operator.
Definition: twolevelmethodcpr.hh:401
Dune::Amg::SmootherTraits< S >::Arguments SmootherArgs
The type of the arguments used for constructing the smoother.
Definition: twolevelmethodcpr.hh:280
AggregationLevelTransferPolicyCpr * clone() const
Clone the current object.
Definition: twolevelmethodcpr.hh:224
OneStepAMGCoarseSolverPolicyCpr(const OneStepAMGCoarseSolverPolicyCpr &other)
Copy constructor.
Definition: twolevelmethodcpr.hh:292
virtual void createCoarseLevelSystem(const FineOperatorType &fineOperator)=0
Algebraically creates the coarse level system.
S SmootherType
The type of the fine level smoother.
Definition: twolevelmethodcpr.hh:422
S Smoother
The type of the smoother used in AMG.
Definition: twolevelmethodcpr.hh:278
virtual LevelTransferPolicyCpr * clone() const =0
Clone the current object.
FO FineOperatorType
The linear operator of the finel level system.
Definition: twolevelmethodcpr.hh:55
Abstract base class for transfer between levels and creation of the coarse level system.
Definition: twolevelmethodcpr.hh:48
FineOperatorType::range_type FineRangeType
The type of the range of the fine level operator.
Definition: twolevelmethodcpr.hh:59
CoarseRangeType rhs_
The coarse level rhs.
Definition: twolevelmethodcpr.hh:144
virtual ~LevelTransferPolicyCpr()
Destructor.
Definition: twolevelmethodcpr.hh:140
CoarseDomainType lhs_
The coarse level lhs.
Definition: twolevelmethodcpr.hh:146
CoarseOperatorType::range_type CoarseRangeType
The type of the range of the coarse level operator.
Definition: twolevelmethodcpr.hh:72
AMG< Operator, X, Smoother > AMGType
The type of the AMG construct on the coarse level.
Definition: twolevelmethodcpr.hh:282
CoarseDomainType & getCoarseLevelLhs()
Get the coarse level left hand side.
Definition: twolevelmethodcpr.hh:98
void createCoarseLevelSystem(const O &fineOperator)
Algebraically creates the coarse level system.
Definition: twolevelmethodcpr.hh:170
CoarseLevelSolver * createCoarseLevelSolver(P &transferPolicy)
Constructs a coarse level solver.
Definition: twolevelmethodcpr.hh:359