dune-istl  2.2.1
smoother.hh
Go to the documentation of this file.
1 #ifndef DUNE_AMGSMOOTHER_HH
2 #define DUNE_AMGSMOOTHER_HH
3 
7 #include<dune/istl/schwarz.hh>
9 #include<dune/common/propertymap.hh>
10 
11 namespace Dune
12 {
13  namespace Amg
14  {
15 
31  template<class T>
33  {
37  typedef T RelaxationFactor;
38 
47 
52  : iterations(1), relaxationFactor(1.0)
53  {}
54  };
55 
59  template<class T>
61  {
63 
64  };
65 
66  template<class X, class Y, class C, class T>
68  {
70 
71  };
72 
73  template<class C, class T>
75  {
77 
78  };
79 
83  template<class T>
85  {
86  typedef typename T::matrix_type Matrix;
87 
89 
91 
92  public:
94  {}
95 
96  void setMatrix(const Matrix& matrix)
97  {
98  matrix_=&matrix;
99  }
100  virtual void setMatrix(const Matrix& matrix, const AggregatesMap& amap)
101  {
102  setMatrix(matrix);
103  }
104 
105 
106  const Matrix& getMatrix() const
107  {
108  return *matrix_;
109  }
110 
111  void setArgs(const SmootherArgs& args)
112  {
113  args_=&args;
114  }
115 
116  template<class T1>
117  void setComm(T1& comm)
118  {}
119 
120  const SmootherArgs getArgs() const
121  {
122  return *args_;
123  }
124 
125  protected:
126  const Matrix* matrix_;
127  private:
128  const SmootherArgs* args_;
129  };
130 
131  template<class T>
133  : public DefaultConstructionArgs<T>
134  {};
135 
136  template<class T, class C=SequentialInformation>
138  : public ConstructionArgs<T>
139  {
140  public:
142  {}
143 
144  void setComm(const C& comm)
145  {
146  comm_ = &comm;
147  }
148 
149  const C& getComm() const
150  {
151  return *comm_;
152  }
153  private:
154  const C* comm_;
155  };
156 
157 
158  template<class T>
159  class ConstructionTraits;
160 
164  template<class M, class X, class Y, int l>
165  struct ConstructionTraits<SeqSSOR<M,X,Y,l> >
166  {
168 
169  static inline SeqSSOR<M,X,Y,l>* construct(Arguments& args)
170  {
171  return new SeqSSOR<M,X,Y,l>(args.getMatrix(), args.getArgs().iterations,
172  args.getArgs().relaxationFactor);
173  }
174 
175  static inline void deconstruct(SeqSSOR<M,X,Y,l>* ssor)
176  {
177  delete ssor;
178  }
179 
180  };
181 
182 
186  template<class M, class X, class Y, int l>
187  struct ConstructionTraits<SeqSOR<M,X,Y,l> >
188  {
190 
191  static inline SeqSOR<M,X,Y,l>* construct(Arguments& args)
192  {
193  return new SeqSOR<M,X,Y,l>(args.getMatrix(), args.getArgs().iterations,
194  args.getArgs().relaxationFactor);
195  }
196 
197  static inline void deconstruct(SeqSOR<M,X,Y,l>* sor)
198  {
199  delete sor;
200  }
201 
202  };
206  template<class M, class X, class Y, int l>
207  struct ConstructionTraits<SeqJac<M,X,Y,l> >
208  {
210 
211  static inline SeqJac<M,X,Y,l>* construct(Arguments& args)
212  {
213  return new SeqJac<M,X,Y,l>(args.getMatrix(), args.getArgs().iterations,
214  args.getArgs().relaxationFactor);
215  }
216 
217  static void deconstruct(SeqJac<M,X,Y,l>* jac)
218  {
219  delete jac;
220  }
221 
222  };
223 
224 
228  template<class M, class X, class Y>
229  struct ConstructionTraits<SeqILU0<M,X,Y> >
230  {
232 
233  static inline SeqILU0<M,X,Y>* construct(Arguments& args)
234  {
235  return new SeqILU0<M,X,Y>(args.getMatrix(),
236  args.getArgs().relaxationFactor);
237  }
238 
239  static void deconstruct(SeqILU0<M,X,Y>* ilu)
240  {
241  delete ilu;
242  }
243 
244  };
245 
246  template<class M, class X, class Y>
247  class ConstructionArgs<SeqILUn<M,X,Y> >
248  : public DefaultConstructionArgs<SeqILUn<M,X,Y> >
249  {
250  public:
252  : n_(n)
253  {}
254 
255  void setN(int n)
256  {
257  n_ = n;
258  }
259  int getN()
260  {
261  return n_;
262  }
263 
264  private:
265  int n_;
266  };
267 
268 
272  template<class M, class X, class Y>
273  struct ConstructionTraits<SeqILUn<M,X,Y> >
274  {
276 
277  static inline SeqILUn<M,X,Y>* construct(Arguments& args)
278  {
279  return new SeqILUn<M,X,Y>(args.getMatrix(), args.getN(),
280  args.getArgs().relaxationFactor);
281  }
282 
283  static void deconstruct(SeqILUn<M,X,Y>* ilu)
284  {
285  delete ilu;
286  }
287 
288  };
289 
293  template<class M, class X, class Y, class C>
294  struct ConstructionTraits<ParSSOR<M,X,Y,C> >
295  {
297 
298  static inline ParSSOR<M,X,Y,C>* construct(Arguments& args)
299  {
300  return new ParSSOR<M,X,Y,C>(args.getMatrix(), args.getArgs().iterations,
301  args.getArgs().relaxationFactor,
302  args.getComm());
303  }
304  static inline void deconstruct(ParSSOR<M,X,Y,C>* ssor)
305  {
306  delete ssor;
307  }
308  };
309 
310  template<class X, class Y, class C, class T>
312  {
316  {
318  args.getComm());
319  }
320 
322  {
323  SeqConstructionTraits::deconstruct(static_cast<T*>(&bp->preconditioner));
324  delete bp;
325  }
326 
327  };
328 
329  template<class C, class T>
331  {
335  {
337  args.getComm());
338  }
339 
341  {
342  SeqConstructionTraits::deconstruct(static_cast<T*>(&bp->preconditioner));
343  delete bp;
344  }
345 
346  };
347 
358  template<class T>
360  {
361  typedef T Smoother;
362  typedef typename Smoother::range_type Range;
363  typedef typename Smoother::domain_type Domain;
364 
372  static void preSmooth(Smoother& smoother, Domain& v, const Range& d)
373  {
374  smoother.apply(v,d);
375  }
376 
384  static void postSmooth(Smoother& smoother, Domain& v, const Range& d)
385  {
386  smoother.apply(v,d);
387  }
388  };
389 
390  template<class M, class X, class Y, int l>
391  struct SmootherApplier<SeqSOR<M,X,Y,l> >
392  {
394  typedef typename Smoother::range_type Range;
395  typedef typename Smoother::domain_type Domain;
396 
397  static void preSmooth(Smoother& smoother, Domain& v, Range& d)
398  {
399  smoother.template apply<true>(v,d);
400  }
401 
402 
403  static void postSmooth(Smoother& smoother, Domain& v, Range& d)
404  {
405  smoother.template apply<false>(v,d);
406  }
407  };
408 
409  template<class M, class X, class Y, class C, int l>
410  struct SmootherApplier<BlockPreconditioner<X,Y,C,SeqSOR<M,X,Y,l> > >
411  {
413  typedef typename Smoother::range_type Range;
414  typedef typename Smoother::domain_type Domain;
415 
416  static void preSmooth(Smoother& smoother, Domain& v, Range& d)
417  {
418  smoother.template apply<true>(v,d);
419  }
420 
421 
422  static void postSmooth(Smoother& smoother, Domain& v, Range& d)
423  {
424  smoother.template apply<false>(v,d);
425  }
426  };
427 
428  template<class M, class X, class Y, class C, int l>
430  {
432  typedef typename Smoother::range_type Range;
433  typedef typename Smoother::domain_type Domain;
434 
435  static void preSmooth(Smoother& smoother, Domain& v, Range& d)
436  {
437  smoother.template apply<true>(v,d);
438  }
439 
440 
441  static void postSmooth(Smoother& smoother, Domain& v, Range& d)
442  {
443  smoother.template apply<false>(v,d);
444  }
445  };
446 
447  }// end namespace Amg
448 
449  // forward declarations
450  template<class M, class X, class MO, class MS, class A>
451  class SeqOverlappingSchwarz;
452 
453  class MultiplicativeSchwarzMode;
454 
455  namespace Amg
456  {
457  template<class M, class X, class MS, class TA>
459  MS,TA> >
460  {
462  typedef typename Smoother::range_type Range;
463  typedef typename Smoother::domain_type Domain;
464 
465  static void preSmooth(Smoother& smoother, Domain& v, const Range& d)
466  {
467  smoother.template apply<true>(v,d);
468  }
469 
470 
471  static void postSmooth(Smoother& smoother, Domain& v, const Range& d)
472  {
473  smoother.template apply<false>(v,d);
474 
475  }
476  };
477 
478  // template<class M, class X, class TM, class TA>
479  // class SeqOverlappingSchwarz;
480 
481  template<class T>
483  : public DefaultSmootherArgs<T>
484  {
486 
488  bool onthefly;
489 
491  bool onthefly_=false)
492  : overlap(overlap_), onthefly(onthefly_)
493  {}
494  };
495 
496  template<class M, class X, class TM, class TS, class TA>
497  struct SmootherTraits<SeqOverlappingSchwarz<M,X,TM,TS,TA> >
498  {
500  };
501 
502  template<class M, class X, class TM, class TS, class TA>
504  : public DefaultConstructionArgs<SeqOverlappingSchwarz<M,X,TM,TS,TA> >
505  {
507 
508  public:
513  typedef typename Vector::value_type Subdomain;
514 
515  virtual void setMatrix(const M& matrix, const AggregatesMap& amap)
516  {
517  Father::setMatrix(matrix);
518 
519  std::vector<bool> visited(amap.noVertices(), false);
520  typedef IteratorPropertyMap<std::vector<bool>::iterator,IdentityMap> VisitedMapType;
521  VisitedMapType visitedMap(visited.begin());
522 
523  MatrixGraph<const M> graph(matrix);
524 
526 
527  switch(Father::getArgs().overlap){
528  case SmootherArgs::vertex:
529  {
530  VertexAdder visitor(subdomains, amap);
531  createSubdomains(matrix, graph, amap, visitor, visitedMap);
532  }
533  break;
534  case SmootherArgs::pairwise:
535  {
536  createPairDomains(graph);
537  }
538  break;
539  case SmootherArgs::aggregate:
540  {
541  AggregateAdder<VisitedMapType> visitor(subdomains, amap, graph, visitedMap);
542  createSubdomains(matrix, graph, amap, visitor, visitedMap);
543  }
544  break;
545  case SmootherArgs::none:
546  NoneAdder visitor;
547  createSubdomains(matrix, graph, amap, visitor, visitedMap);
548  break;
549  default:
550  DUNE_THROW(NotImplemented, "This overlapping scheme is not supported!");
551  }
552  }
553  void setMatrix(const M& matrix)
554  {
555  Father::setMatrix(matrix);
556 
557  /* Create aggregates map where each aggregate is just one vertex. */
558  AggregatesMap amap(matrix.N());
559  VertexDescriptor v=0;
560  for(typename AggregatesMap::iterator iter=amap.begin();
561  iter!=amap.end(); ++iter)
562  *iter=v++;
563 
564  std::vector<bool> visited(amap.noVertices(), false);
565  typedef IteratorPropertyMap<std::vector<bool>::iterator,IdentityMap> VisitedMapType;
566  VisitedMapType visitedMap(visited.begin());
567 
568  MatrixGraph<const M> graph(matrix);
569 
571 
572  switch(Father::getArgs().overlap){
573  case SmootherArgs::vertex:
574  {
575  VertexAdder visitor(subdomains, amap);
576  createSubdomains(matrix, graph, amap, visitor, visitedMap);
577  }
578  break;
579  case SmootherArgs::aggregate:
580  {
581  DUNE_THROW(NotImplemented, "Aggregate overlap is not supported yet");
582  /*
583  AggregateAdder<VisitedMapType> visitor(subdomains, amap, graph, visitedMap);
584  createSubdomains(matrix, graph, amap, visitor, visitedMap);
585  */
586  }
587  break;
588  case SmootherArgs::pairwise:
589  {
590  createPairDomains(graph);
591  }
592  break;
593  case SmootherArgs::none:
594  NoneAdder visitor;
595  createSubdomains(matrix, graph, amap, visitor, visitedMap);
596 
597  }
598  }
599 
600  const Vector& getSubDomains()
601  {
602  return subdomains;
603  }
604 
605  private:
606  struct VertexAdder
607  {
608  VertexAdder(Vector& subdomains_, const AggregatesMap& aggregates_)
609  : subdomains(subdomains_), max(-1), subdomain(-1), aggregates(aggregates_)
610  {}
611  template<class T>
612  void operator()(const T& edge)
613  {
614  if(aggregates[edge.target()]!=AggregatesMap::ISOLATED)
615  subdomains[subdomain].insert(edge.target());
616  }
617  int setAggregate(const AggregateDescriptor& aggregate_)
618  {
619  subdomain=aggregate_;
620  max = std::max(subdomain, aggregate_);
621  return subdomain;
622  }
623  int noSubdomains() const
624  {
625  return max+1;
626  }
627  private:
628  Vector& subdomains;
630  AggregateDescriptor subdomain;
631  const AggregatesMap& aggregates;
632  };
633  struct NoneAdder
634  {
635  template<class T>
636  void operator()(const T& edge)
637  {}
638  int setAggregate(const AggregateDescriptor& aggregate_)
639  {
640  return -1;
641  }
642  int noSubdomains() const
643  {
644  return -1;
645  }
646  };
647 
648  template<class VM>
649  struct AggregateAdder
650  {
651  AggregateAdder(Vector& subdomains_, const AggregatesMap& aggregates_,
652  const MatrixGraph<const M>& graph_, VM& visitedMap_)
653  : subdomains(subdomains_), subdomain(-1), aggregates(aggregates_),
654  adder(subdomains_, aggregates_), graph(graph_), visitedMap(visitedMap_)
655  {}
656  template<class T>
657  void operator()(const T& edge)
658  {
659  subdomains[subdomain].insert(edge.target());
660  // If we (the neighbouring vertex of the aggregate)
661  // are not isolated, add the aggregate we belong to
662  // to the same subdomain using the OneOverlapAdder
663  if(aggregates[edge.target()]!=AggregatesMap::ISOLATED){
664  assert(aggregates[edge.target()]!=aggregate);
665  typename AggregatesMap::VertexList vlist;
666  aggregates.template breadthFirstSearch<true,false>(edge.target(), aggregate,
667  graph, vlist, adder, adder,
668  visitedMap);
669  }
670  }
671 
672  int setAggregate(const AggregateDescriptor& aggregate_)
673  {
674  adder.setAggregate(aggregate_);
675  aggregate=aggregate_;
676  return ++subdomain;
677  }
678  int noSubdomains() const
679  {
680  return subdomain+1;
681  }
682 
683  private:
684  AggregateDescriptor aggregate;
685  Vector& subdomains;
686  int subdomain;
687  const AggregatesMap& aggregates;
688  VertexAdder adder;
689  const MatrixGraph<const M>& graph;
690  VM& visitedMap;
691  };
692 
693  void createPairDomains(const MatrixGraph<const M>& graph)
694  {
695  typedef typename MatrixGraph<const M>::ConstVertexIterator VIter;
696  typedef typename MatrixGraph<const M>::ConstEdgeIterator EIter;
697  typedef typename M::size_type size_type;
698 
699  std::set<std::pair<size_type,size_type> > pairs;
700  int total=0;
701  for(VIter v=graph.begin(), ve=graph.end(); ve != v; ++v)
702  for(EIter e = v.begin(), ee=v.end(); ee!=e; ++e)
703  {
704  ++total;
705  if(e.source()<e.target())
706  pairs.insert(std::make_pair(e.source(),e.target()));
707  else
708  pairs.insert(std::make_pair(e.target(),e.source()));
709  }
710 
711 
712  subdomains.resize(pairs.size());
713  Dune::dinfo <<std::endl<< "Created "<<pairs.size()<<" ("<<total<<") pair domains"<<std::endl<<std::endl;
714  typedef typename std::set<std::pair<size_type,size_type> >::const_iterator SIter;
715  typename Vector::iterator subdomain=subdomains.begin();
716 
717  for(SIter s=pairs.begin(), se =pairs.end(); se!=s; ++s)
718  {
719  subdomain->insert(s->first);
720  subdomain->insert(s->second);
721  ++subdomain;
722  }
723  std::size_t minsize=10000;
724  std::size_t maxsize=0;
725  int sum=0;
726  for(typename Vector::size_type i=0; i < subdomains.size(); ++i){
727  sum+=subdomains[i].size();
728  minsize=std::min(minsize, subdomains[i].size());
729  maxsize=std::max(maxsize, subdomains[i].size());
730  }
731  Dune::dinfo<<"Subdomain size: min="<<minsize<<" max="<<maxsize<<" avg="<<(sum/subdomains.size())
732  <<" no="<<subdomains.size()<<std::endl;
733  }
734 
735  template<class Visitor>
736  void createSubdomains(const M& matrix, const MatrixGraph<const M>& graph,
737  const AggregatesMap& amap, Visitor& overlapVisitor,
738  IteratorPropertyMap<std::vector<bool>::iterator,IdentityMap>& visitedMap )
739  {
740  // count number ag aggregates. We asume that the
741  // aggregates are numbered consecutively from 0 exept
742  // for the isolated ones. All isolated vertices form
743  // one aggregate, here.
744  int isolated=0;
745  AggregateDescriptor maxAggregate=0;
746 
747  for(std::size_t i=0; i < amap.noVertices(); ++i)
748  if(amap[i]==AggregatesMap::ISOLATED)
749  isolated++;
750  else
751  maxAggregate = std::max(maxAggregate, amap[i]);
752 
753  subdomains.resize(maxAggregate+1+isolated);
754 
755  // reset the subdomains
756  for(typename Vector::size_type i=0; i < subdomains.size(); ++i)
757  subdomains[i].clear();
758 
759  // Create the subdomains from the aggregates mapping.
760  // For each aggregate we mark all entries and the
761  // neighbouring vertices as belonging to the same subdomain
762  VertexAdder aggregateVisitor(subdomains, amap);
763 
764  for(VertexDescriptor i=0; i < amap.noVertices(); ++i)
765  if(!get(visitedMap, i)){
766  AggregateDescriptor aggregate=amap[i];
767 
768  if(amap[i]==AggregatesMap::ISOLATED){
769  // isolated vertex gets its own aggregate
770  subdomains.push_back(Subdomain());
771  aggregate=subdomains.size()-1;
772  }
773  overlapVisitor.setAggregate(aggregate);
774  aggregateVisitor.setAggregate(aggregate);
775  subdomains[aggregate].insert(i);
776  typename AggregatesMap::VertexList vlist;
777  amap.template breadthFirstSearch<false,false>(i, aggregate, graph, vlist, aggregateVisitor,
778  overlapVisitor, visitedMap);
779  }
780 
781  std::size_t minsize=10000;
782  std::size_t maxsize=0;
783  int sum=0;
784  for(typename Vector::size_type i=0; i < subdomains.size(); ++i){
785  sum+=subdomains[i].size();
786  minsize=std::min(minsize, subdomains[i].size());
787  maxsize=std::max(maxsize, subdomains[i].size());
788  }
789  Dune::dinfo<<"Subdomain size: min="<<minsize<<" max="<<maxsize<<" avg="<<(sum/subdomains.size())
790  <<" no="<<subdomains.size()<<" isolated="<<isolated<<std::endl;
791 
792 
793 
794  }
795  Vector subdomains;
796  };
797 
798 
799  template<class M, class X, class TM, class TS, class TA>
801  {
803 
805  {
807  args.getSubDomains(),
808  args.getArgs().relaxationFactor,
809  args.getArgs().onthefly);
810  }
811 
813  {
814  delete schwarz;
815  }
816  };
817 
818 
819  } // namespace Amg
820 } // namespace Dune
821 
822 
823 
824 #endif