dune-istl  2.2.0
galerkin.hh
Go to the documentation of this file.
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set ts=8 sw=2 et sts=2:
3 // $Id: galerkin.hh 1553 2012-04-26 12:18:19Z mblatt $
4 #ifndef DUNE_GALERKIN_HH
5 #define DUNE_GALERKIN_HH
6 
7 #include"aggregates.hh"
8 #include"pinfo.hh"
9 #include<dune/common/poolallocator.hh>
10 #include<dune/common/enumset.hh>
11 #include<set>
12 #include<limits>
13 #include<algorithm>
14 
15 namespace Dune
16 {
17  namespace Amg
18  {
30  template<class T>
32  {
36  typedef T Aggregate;
37 
41  typedef T Vertex;
42 
47 
52  };
53 
54 
55 
60  template<class M>
62  {
63  public:
69  SparsityBuilder(M& matrix);
70 
71  void insert(const typename M::size_type& index);
72 
73  void operator++();
74 
75  std::size_t minRowSize();
76 
77  std::size_t maxRowSize();
78 
79  std::size_t sumRowSize();
80  std::size_t index()
81  {
82  return row_.index();
83  }
84  private:
86  typename M::CreateIterator row_;
88  std::size_t minRowSize_;
90  std::size_t maxRowSize_;
91  std::size_t sumRowSize_;
92 #ifdef DUNE_ISTL_WITH_CHECKING
93  bool diagonalInserted;
94 #endif
95  };
96 
98  {
99  public:
108  template<class M, class V, class I, class O>
109  void calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
110  const I& pinfo, const O& copy);
111 
112  };
113 
114  template<class T>
116  : public BaseGalerkinProduct
117  {
118  public:
120 
131  template<class M, class G, class V, class Set>
132  M* build(const M& fine, G& fineGraph, V& visitedMap,
133  const ParallelInformation& pinfo,
135  const typename M::size_type& size,
136  const Set& copy);
137  private:
138 
145  template<class G, class I, class Set>
147  buildOverlapVertices(const G& graph, const I& pinfo,
149  const Set& overlap,
150  std::size_t& overlapCount);
151 
152  template<class A>
153  struct OVLess
154  {
155  bool operator()(const OverlapVertex<A>& o1, const OverlapVertex<A>& o2)
156  {
157  return *o1.aggregate < *o2.aggregate;
158  }
159  };
160  };
161 
162  template<>
164  : public BaseGalerkinProduct
165  {
166  public:
177  template<class M, class G, class V, class Set>
178  M* build(const M& fine, G& fineGraph, V& visitedMap,
179  const SequentialInformation& pinfo,
181  const typename M::size_type& size,
182  const Set& copy);
183  };
184 
186  {
187  template<class R, class G, class V>
188  static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
192 
196  template<class R, class G, class V>
197  static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
199  const typename G::VertexDescriptor& seed);
200 
201 
205  template<class G, class S, class V>
207  {
208  public:
212  typedef G Graph;
216  typedef typename Graph::ConstEdgeIterator ConstEdgeIterator;
217 
221  typedef S Set;
222 
226  typedef V VisitedMap;
227 
231  typedef typename Graph::VertexDescriptor Vertex;
232 
240  ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, Graph& graph,
241  VisitedMap& visitedMap, Set& connected);
242 
247  void operator()(const ConstEdgeIterator& edge);
248 
249  private:
253  const AggregatesMap<Vertex>& aggregates_;
254 
255  Graph& graph_;
256 
260  VisitedMap& visitedMap_;
261 
265  Set& connected_;
266  };
267 
268  };
269 
270  template<class G, class T>
272  {
273  typedef typename G::VertexDescriptor Vertex;
274 
275  template<class V, class O, class R>
276  static void examine(G& graph,
277  V& visitedMap,
278  const T& pinfo,
279  const AggregatesMap<Vertex>& aggregates,
280  const O& overlap,
281  const OverlapVertex<Vertex>* overlapVertices,
282  const OverlapVertex<Vertex>* overlapEnd,
283  R& row);
284  };
285 
286  template<class G>
288  {
289  typedef typename G::VertexDescriptor Vertex;
290 
291  template<class V, class R>
292  static void examine(G& graph,
293  V& visitedMap,
294  const SequentialInformation& pinfo,
295  const AggregatesMap<Vertex>& aggregates,
296  R& row);
297  };
298 
299  template<class T>
301  {
302  template<class M, class O>
303  static void set(M& coarse, const T& pinfo, const O& copy);
304  };
305 
306  template<>
308  {
309  template<class M, class O>
310  static void set(M& coarse, const SequentialInformation& pinfo, const O& copy);
311  };
312 
313  template<class R, class G, class V>
316  const typename G::VertexDescriptor& seed)
317  {
318  assert(row.index()==aggregates[seed]);
319  row.insert(aggregates[seed]);
320  ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
321  typedef typename G::VertexDescriptor Vertex;
322  typedef std::allocator<Vertex> Allocator;
323  typedef SLList<Vertex,Allocator> VertexList;
324  typedef typename AggregatesMap<Vertex>::DummyEdgeVisitor DummyVisitor;
325  VertexList vlist;
326  DummyVisitor dummy;
327  aggregates.template breadthFirstSearch<true,false>(seed,aggregates[seed], graph, vlist, dummy,
328  conBuilder, visitedMap);
329  }
330 
331  template<class R, class G, class V>
336  {
337  ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
338  const typename G::VertexDescriptor aggregate=*seed->aggregate;
339 
340  if (row.index()==*seed->aggregate){
341  while(seed != overlapEnd && aggregate == *seed->aggregate){
342  row.insert(*seed->aggregate);
343  // Walk over all neighbours and add them to the connected array.
344  visitNeighbours(graph, seed->vertex, conBuilder);
345  // Mark vertex as visited
346  put(visitedMap, seed->vertex, true);
347  ++seed;
348  }
349  }
350  }
351 
352  template<class G, class S, class V>
354  Graph& graph, VisitedMap& visitedMap,
355  Set& connected)
356  : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected)
357  {}
358 
359  template<class G, class S, class V>
361  {
362  typedef typename G::VertexDescriptor Vertex;
363  const Vertex& vertex = aggregates_[edge.target()];
364  assert(vertex!= AggregatesMap<Vertex>::UNAGGREGATED);
366  connected_.insert(vertex);
367  }
368 
369  template<class T>
370  template<class G, class I, class Set>
372  GalerkinProduct<T>::buildOverlapVertices(const G& graph, const I& pinfo,
374  const Set& overlap,
375  std::size_t& overlapCount)
376  {
377  // count the overlap vertices.
378  typedef typename G::ConstVertexIterator ConstIterator;
379  typedef typename I::GlobalLookupIndexSet GlobalLookup;
380  typedef typename GlobalLookup::IndexPair IndexPair;
381 
382  const ConstIterator end = graph.end();
383  overlapCount = 0;
384 
385  const GlobalLookup& lookup=pinfo.globalLookup();
386 
387  for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){
388  const IndexPair* pair = lookup.pair(*vertex);
389 
390  if(pair!=0 && overlap.contains(pair->local().attribute()))
391  ++overlapCount;
392  }
393  // Allocate space
394  typedef typename G::VertexDescriptor Vertex;
395 
396  OverlapVertex<Vertex>* overlapVertices = new OverlapVertex<Vertex>[overlapCount=0?1:overlapCount];
397  if(overlapCount==0)
398  return overlapVertices;
399 
400  // Initialize them
401  overlapCount=0;
402  for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){
403  const IndexPair* pair = lookup.pair(*vertex);
404 
405  if(pair!=0 && overlap.contains(pair->local().attribute())){
406  overlapVertices[overlapCount].aggregate = &aggregates[pair->local()];
407  overlapVertices[overlapCount].vertex = pair->local();
408  ++overlapCount;
409  }
410  }
411 
412  dverb << overlapCount<<" overlap vertices"<<std::endl;
413 
414  std::sort(overlapVertices, overlapVertices+overlapCount, OVLess<Vertex>());
415  // due to the sorting the isolated aggregates (to be skipped) are at the end.
416 
417  return overlapVertices;
418  }
419 
420  template<class G, class T>
421  template<class V, class O, class R>
423  V& visitedMap,
424  const T& pinfo,
425  const AggregatesMap<Vertex>& aggregates,
426  const O& overlap,
427  const OverlapVertex<Vertex>* overlapVertices,
428  const OverlapVertex<Vertex>* overlapEnd,
429  R& row)
430  {
431  typedef typename T::GlobalLookupIndexSet GlobalLookup;
432  const GlobalLookup& lookup = pinfo.globalLookup();
433 
434  typedef typename G::VertexIterator VertexIterator;
435 
436  VertexIterator vend=graph.end();
437 
438 #ifdef DUNE_ISTL_WITH_CHECKING
439  std::set<Vertex> examined;
440 #endif
441 
442  // The aggregates owned by the process have lower local indices
443  // then those not owned. We process them in the first pass.
444  // They represent the rows 0, 1, ..., n of the coarse matrix
445  for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex)
446  if(!get(visitedMap, *vertex)){
447  // In the first pass we only process owner nodes
448  typedef typename GlobalLookup::IndexPair IndexPair;
449  const IndexPair* pair = lookup.pair(*vertex);
450  if(pair==0 || !overlap.contains(pair->local().attribute())){
451 #ifdef DUNE_ISTL_WITH_CHECKING
452  assert(examined.find(aggregates[*vertex])==examined.end());
453  examined.insert(aggregates[*vertex]);
454 #endif
455  constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
456 
457  // only needed for ALU
458  // (ghosts with same global id as owners on the same process)
459  if (pinfo.getSolverCategory() == static_cast<int>(SolverCategory::nonoverlapping)){
460  if(overlapVertices != overlapEnd){
461  if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED){
462  constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);}
463  else{
464  ++overlapVertices;
465  }
466  }
467  }
468  ++row;
469  }
470  }
471 
472  dvverb<<"constructed "<<row.index()<<" non-overlapping rows"<<std::endl;
473 
474  // Now come the aggregates not owned by use.
475  // They represent the rows n+1, ..., N
476  while(overlapVertices != overlapEnd)
477  if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED){
478 
479 #ifdef DUNE_ISTL_WITH_CHECKING
480  typedef typename GlobalLookup::IndexPair IndexPair;
481  const IndexPair* pair = lookup.pair(overlapVertices->vertex);
482  assert(pair!=0 && overlap.contains(pair->local().attribute()));
483  assert(examined.find(aggregates[overlapVertices->vertex])==examined.end());
484  examined.insert(aggregates[overlapVertices->vertex]);
485 #endif
486  constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
487  ++row;
488  }else{
489  ++overlapVertices;
490  }
491  }
492 
493  template<class G>
494  template<class V, class R>
496  V& visitedMap,
497  const SequentialInformation& pinfo,
498  const AggregatesMap<Vertex>& aggregates,
499  R& row)
500  {
501  typedef typename G::VertexIterator VertexIterator;
502 
503  VertexIterator vend=graph.end();
504  for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex){
505  if(!get(visitedMap, *vertex)){
506  constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
507  ++row;
508  }
509  }
510 
511  }
512 
513  template<class M>
515  : row_(matrix.createbegin()),
516  minRowSize_(std::numeric_limits<std::size_t>::max()),
517  maxRowSize_(0), sumRowSize_(0)
518  {
519 #ifdef DUNE_ISTL_WITH_CHECKING
520  diagonalInserted = false;
521 #endif
522 }
523  template<class M>
525  {
526  return maxRowSize_;
527  }
528  template<class M>
530  {
531  return minRowSize_;
532  }
533 
534  template<class M>
536  {
537  return sumRowSize_;
538  }
539  template<class M>
541  {
542  sumRowSize_ += row_.size();
543  minRowSize_=std::min(minRowSize_, row_.size());
544  maxRowSize_=std::max(maxRowSize_, row_.size());
545  ++row_;
546 #ifdef DUNE_ISTL_WITH_CHECKING
547  assert(diagonalInserted);
548  diagonalInserted = false;
549 #endif
550  }
551 
552  template<class M>
553  void SparsityBuilder<M>::insert(const typename M::size_type& index)
554  {
555  row_.insert(index);
556 #ifdef DUNE_ISTL_WITH_CHECKING
557  diagonalInserted = diagonalInserted || row_.index()==index;
558 #endif
559  }
560 
561  template<class T>
562  template<class M, class G, class V, class Set>
563  M* GalerkinProduct<T>::build(const M& fine, G& fineGraph, V& visitedMap,
564  const ParallelInformation& pinfo,
566  const typename M::size_type& size,
567  const Set& overlap)
568  {
569 
571 
572  std::size_t count;
573 
574  const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph,
575  pinfo,
576  aggregates,
577  overlap,
578  count);
579  M* coarseMatrix = new M(size, size, M::row_wise);
580 
581  // Reset the visited flags of all vertices.
582  // As the isolated nodes will be skipped we simply mark them as visited
583 
584  typedef typename G::VertexIterator Vertex;
585  Vertex vend = fineGraph.end();
586  for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){
587  assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
588  put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
589  }
590 
591  SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
592 
593  ConnectivityConstructor<G,T>::examine(fineGraph, visitedMap, pinfo,
594  aggregates, overlap,
595  overlapVertices,
596  overlapVertices+count,
597  sparsityBuilder);
598 
599  dinfo<<pinfo.communicator().rank()<<": Matrix ("<<coarseMatrix->N()<<"x"<<coarseMatrix->M()<<" row: min="<<sparsityBuilder.minRowSize()<<" max="
600  <<sparsityBuilder.maxRowSize()<<" avg="
601  <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()
602  <<std::endl;
603 
604  delete[] overlapVertices;
605 
606  //calculate(fine, aggregates, *coarse, overlap);
607 
608  return coarseMatrix;
609  }
610 
611  template<class M, class G, class V, class Set>
612  M* GalerkinProduct<SequentialInformation>::build(const M& fine, G& fineGraph, V& visitedMap,
613  const SequentialInformation& pinfo,
615  const typename M::size_type& size,
616  const Set& overlap)
617  {
618  M* coarseMatrix = new M(size, size, M::row_wise);
619 
620  // Reset the visited flags of all vertices.
621  // As the isolated nodes will be skipped we simply mark them as visited
622 
623  typedef typename G::VertexIterator Vertex;
624  Vertex vend = fineGraph.end();
625  for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){
626  assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
627  put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
628  }
629 
630  SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
631 
632  ConnectivityConstructor<G,SequentialInformation>::examine(fineGraph, visitedMap, pinfo,
633  aggregates, sparsityBuilder);
634  dinfo<<"Matrix row: min="<<sparsityBuilder.minRowSize()<<" max="
635  <<sparsityBuilder.maxRowSize()<<" average="
636  <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()<<std::endl;
637  return coarseMatrix;
638  }
639 
640  template<class M, class V, class P, class O>
641  void BaseGalerkinProduct::calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
642  const P& pinfo, const O& copy)
643  {
644  coarse = static_cast<typename M::field_type>(0);
645 
646  typedef typename M::ConstIterator RowIterator;
647  RowIterator endRow = fine.end();
648 
649  for(RowIterator row = fine.begin(); row != endRow; ++row)
650  if(aggregates[row.index()] != AggregatesMap<V>::ISOLATED){
651  assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
652  typedef typename M::ConstColIterator ColIterator;
653  ColIterator endCol = row->end();
654 
655  for(ColIterator col = row->begin(); col != endCol; ++col)
656  if(aggregates[col.index()] != AggregatesMap<V>::ISOLATED){
657  assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
658  coarse[aggregates[row.index()]][aggregates[col.index()]]+=*col;
659  }
660  }
661 
662  // get the right diagonal matrix values on copy lines from owner processes
663  typedef typename M::block_type BlockType;
664  std::vector<BlockType> rowsize(coarse.N(),BlockType(0));
665  for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
666  rowsize[row.index()]=coarse[row.index()][row.index()];
667  pinfo.copyOwnerToAll(rowsize,rowsize);
668  for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
669  coarse[row.index()][row.index()] = rowsize[row.index()];
670 
671  // don't set dirichlet boundaries for copy lines to make novlp case work,
672  // the preconditioner yields slightly different results now.
673 
674  // Set the dirichlet border
675  //DirichletBoundarySetter<P>::template set<M>(coarse, pinfo, copy);
676 
677  }
678 
679  template<class T>
680  template<class M, class O>
681  void DirichletBoundarySetter<T>::set(M& coarse, const T& pinfo, const O& copy)
682  {
683  typedef typename T::ParallelIndexSet::const_iterator ConstIterator;
684  ConstIterator end = pinfo.indexSet().end();
685  typedef typename M::block_type Block;
686  Block identity=Block(0.0);
687  for(typename Block::RowIterator b=identity.begin(); b != identity.end(); ++b)
688  b->operator[](b.index())=1.0;
689 
690  for(ConstIterator index = pinfo.indexSet().begin();
691  index != end; ++index){
692  if(copy.contains(index->local().attribute())){
693  typedef typename M::ColIterator ColIterator;
694  typedef typename M::row_type Row;
695  Row row = coarse[index->local()];
696  ColIterator cend = row.find(index->local());
697  ColIterator col = row.begin();
698  for(; col != cend; ++col)
699  *col = 0;
700 
701  cend = row.end();
702 
703  assert(col != cend); // There should be a diagonal entry
704  *col = identity;
705 
706  for(++col; col != cend; ++col)
707  *col = 0;
708  }
709  }
710  }
711 
712  template<class M, class O>
714  const SequentialInformation& pinfo,
715  const O& overlap)
716  {
717  }
718 
719  }// namespace Amg
720 }// namespace Dune
721 #endif