galerkin.hh

Go to the documentation of this file.
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set ts=8 sw=2 et sts=2:
00003 // $Id$
00004 #ifndef DUNE_GALERKIN_HH
00005 #define DUNE_GALERKIN_HH
00006 
00007 #include"aggregates.hh"
00008 #include"pinfo.hh"
00009 #include<dune/common/poolallocator.hh>
00010 #include<dune/common/enumset.hh>
00011 #include<set>
00012 #include<limits>
00013 #include<algorithm>
00014 
00015 namespace Dune
00016 {
00017   namespace Amg
00018   {
00030     template<class T>
00031     struct OverlapVertex
00032     {
00036       typedef T Aggregate;
00037       
00041       typedef T Vertex;
00042         
00046       Aggregate* aggregate;
00047       
00051       Vertex vertex;
00052     };
00053 
00054 
00055 
00060       template<class M>
00061       class SparsityBuilder
00062       {
00063       public:
00069         SparsityBuilder(M& matrix);
00070         
00071         void insert(const typename M::size_type& index);
00072         
00073         void operator++();
00074 
00075         std::size_t minRowSize();
00076         
00077         std::size_t maxRowSize();
00078         
00079         std::size_t sumRowSize();
00080         std::size_t index()
00081         {
00082           return row_.index();
00083         }
00084       private:
00086         typename M::CreateIterator row_;
00088         std::size_t minRowSize_;
00090         std::size_t maxRowSize_;
00091         std::size_t sumRowSize_;
00092 #ifdef DUNE_ISTL_WITH_CHECKING
00093         bool diagonalInserted;
00094 #endif
00095       };
00096 
00097     class BaseGalerkinProduct
00098     {
00099     public:
00108       template<class M, class V, class I, class O>
00109       void calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
00110                      const I& pinfo, const O& copy);
00111       
00112     };
00113     
00114     template<class T>
00115     class GalerkinProduct
00116       : public BaseGalerkinProduct
00117     {
00118     public:
00119       typedef T ParallelInformation;
00120       
00131       template<class M, class G, class V, class Set>
00132       M* build(const M& fine, G& fineGraph, V& visitedMap, 
00133                const ParallelInformation& pinfo,
00134                AggregatesMap<typename G::VertexDescriptor>& aggregates,
00135                const typename M::size_type& size,
00136                const Set& copy);
00137     private:
00138 
00145       template<class G, class I, class Set>
00146       const OverlapVertex<typename G::VertexDescriptor>*
00147       buildOverlapVertices(const G& graph,  const I& pinfo,
00148                            AggregatesMap<typename G::VertexDescriptor>& aggregates,
00149                            const Set& overlap,
00150                            std::size_t& overlapCount);
00151       
00152       template<class A>
00153       struct OVLess
00154       {
00155         bool operator()(const OverlapVertex<A>& o1, const OverlapVertex<A>& o2)
00156         {
00157           return *o1.aggregate < *o2.aggregate;
00158         }
00159       };
00160     };
00161     
00162     template<>
00163     class GalerkinProduct<SequentialInformation> 
00164       : public BaseGalerkinProduct
00165     {
00166     public:
00177       template<class M, class G, class V, class Set>
00178       M* build(const M& fine, G& fineGraph, V& visitedMap, 
00179                const SequentialInformation& pinfo, 
00180                const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00181                const typename M::size_type& size,
00182                const Set& copy);
00183     };
00184     
00185     struct BaseConnectivityConstructor
00186     {
00187       template<class R, class G, class V>
00188       static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
00189                                                const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00190                                                const OverlapVertex<typename G::VertexDescriptor>*& seed,
00191                                                const OverlapVertex<typename G::VertexDescriptor>* overlapEnd);
00192       
00196       template<class R, class G, class V>
00197       static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
00198                                                   const AggregatesMap<typename G::VertexDescriptor>& aggregates, 
00199                                                   const typename G::VertexDescriptor& seed);
00200 
00201                   
00205       template<class G, class S, class V>
00206       class ConnectedBuilder
00207       {
00208       public:
00212         typedef G Graph;
00216         typedef typename Graph::ConstEdgeIterator ConstEdgeIterator;
00217         
00221         typedef S Set;
00222         
00226         typedef V VisitedMap;
00227         
00231         typedef typename Graph::VertexDescriptor Vertex;
00232         
00240         ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, Graph& graph, 
00241                          VisitedMap& visitedMap, Set& connected);
00242         
00247         void operator()(const ConstEdgeIterator& edge);
00248                 
00249       private:
00253         const AggregatesMap<Vertex>& aggregates_;
00254         
00255         Graph& graph_;
00256 
00260         VisitedMap& visitedMap_;
00261 
00265         Set& connected_;
00266       };
00267 
00268     };
00269 
00270     template<class G, class T>
00271     struct ConnectivityConstructor: public BaseConnectivityConstructor
00272     {
00273       typedef typename G::VertexDescriptor Vertex;
00274       
00275       template<class V, class O, class R>
00276       static void examine(G& graph, 
00277                           V& visitedMap, 
00278                           const T& pinfo,
00279                           const AggregatesMap<Vertex>& aggregates,
00280                           const O& overlap,
00281                           const OverlapVertex<Vertex>* overlapVertices,
00282                           const OverlapVertex<Vertex>* overlapEnd,
00283                           R& row);
00284     };
00285     
00286     template<class G>
00287     struct ConnectivityConstructor<G,SequentialInformation> : public BaseConnectivityConstructor
00288     {
00289       typedef typename G::VertexDescriptor Vertex;
00290       
00291       template<class V, class R>
00292       static void examine(G& graph, 
00293                           V& visitedMap, 
00294                           const SequentialInformation& pinfo,
00295                           const AggregatesMap<Vertex>& aggregates,
00296                           R& row);
00297     };
00298     
00299     template<class T>
00300     struct DirichletBoundarySetter
00301     {
00302       template<class M, class O>
00303       static void set(M& coarse, const T& pinfo, const O& copy);
00304     };
00305     
00306     template<>
00307     struct DirichletBoundarySetter<SequentialInformation>
00308     {
00309       template<class M, class O>
00310       static void set(M& coarse, const SequentialInformation& pinfo, const O& copy);
00311     };
00312 
00313     template<class R, class G, class V>
00314     void BaseConnectivityConstructor::constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
00315                                                                       const AggregatesMap<typename G::VertexDescriptor>& aggregates, 
00316                                                                       const typename G::VertexDescriptor& seed)
00317     {
00318       assert(row.index()==aggregates[seed]);
00319       row.insert(aggregates[seed]);
00320       ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
00321       typedef typename G::VertexDescriptor Vertex;
00322       typedef std::allocator<Vertex> Allocator;
00323       typedef SLList<Vertex,Allocator> VertexList;
00324       typedef typename AggregatesMap<Vertex>::DummyEdgeVisitor DummyVisitor;
00325       VertexList vlist;
00326       DummyVisitor dummy;
00327       aggregates.template breadthFirstSearch<true,false>(seed,aggregates[seed], graph, vlist, dummy, 
00328                                                         conBuilder, visitedMap);
00329     }
00330     
00331     template<class R, class G, class V>
00332     void BaseConnectivityConstructor::constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
00333                                                                    const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00334                                                                    const OverlapVertex<typename G::VertexDescriptor>*& seed,
00335                                                                    const OverlapVertex<typename G::VertexDescriptor>* overlapEnd)
00336     {
00337       ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
00338       const typename G::VertexDescriptor aggregate=*seed->aggregate;
00339       assert(row.index()==*seed->aggregate);
00340 
00341       while(seed != overlapEnd && aggregate == *seed->aggregate){
00342         row.insert(*seed->aggregate);
00343         // Walk over all neighbours and add them to the connected array.
00344         visitNeighbours(graph, seed->vertex, conBuilder);
00345         // Mark vertex as visited
00346         put(visitedMap, seed->vertex, true);
00347         ++seed;
00348       }
00349     }
00350     
00351     template<class G, class S, class V>
00352     BaseConnectivityConstructor::ConnectedBuilder<G,S,V>::ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, 
00353                                                              Graph& graph, VisitedMap& visitedMap,
00354                                                              Set& connected)
00355       : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected)
00356     {}
00357           
00358     template<class G, class S, class V>
00359     void BaseConnectivityConstructor::ConnectedBuilder<G,S,V>::operator()(const ConstEdgeIterator& edge)
00360     {
00361       typedef typename G::VertexDescriptor Vertex;
00362       const Vertex& vertex = aggregates_[edge.target()];
00363       assert(vertex!= AggregatesMap<Vertex>::UNAGGREGATED);
00364       if(vertex!= AggregatesMap<Vertex>::ISOLATED)
00365         connected_.insert(vertex);
00366     }
00367     
00368     template<class T>
00369     template<class G, class I, class Set>
00370     const OverlapVertex<typename G::VertexDescriptor>*
00371     GalerkinProduct<T>::buildOverlapVertices(const G& graph, const I& pinfo,
00372                                              AggregatesMap<typename G::VertexDescriptor>& aggregates,
00373                                              const Set& overlap,
00374                                              std::size_t& overlapCount)
00375     {
00376       // count the overlap vertices.
00377       typedef typename G::ConstVertexIterator ConstIterator;
00378       typedef typename I::GlobalLookupIndexSet GlobalLookup;
00379       typedef typename GlobalLookup::IndexPair IndexPair;
00380       
00381       const ConstIterator end = graph.end();
00382       overlapCount = 0;
00383       
00384       const GlobalLookup& lookup=pinfo.globalLookup();
00385       
00386       for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){
00387         const IndexPair* pair = lookup.pair(*vertex);
00388         
00389         if(pair!=0 && overlap.contains(pair->local().attribute()))
00390           ++overlapCount;
00391       }
00392       // Allocate space
00393       typedef typename G::VertexDescriptor Vertex;
00394       
00395       OverlapVertex<Vertex>* overlapVertices = new OverlapVertex<Vertex>[overlapCount=0?1:overlapCount];
00396       if(overlapCount==0)
00397         return overlapVertices;
00398       
00399       // Initialize them
00400       overlapCount=0;
00401       for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){
00402         const IndexPair* pair = lookup.pair(*vertex);
00403         
00404         if(pair!=0 && overlap.contains(pair->local().attribute())){
00405           overlapVertices[overlapCount].aggregate = &aggregates[pair->local()];
00406           overlapVertices[overlapCount].vertex = pair->local();
00407           ++overlapCount;
00408         }
00409       }
00410       
00411       dverb << overlapCount<<" overlap vertices"<<std::endl;
00412       
00413       std::sort(overlapVertices, overlapVertices+overlapCount, OVLess<Vertex>());
00414       // due to the sorting the isolated aggregates (to be skipped) are at the end.
00415 
00416       return overlapVertices;
00417     }
00418 
00419     template<class G, class T>
00420     template<class V, class O, class R>
00421     void ConnectivityConstructor<G,T>::examine(G& graph, 
00422                                                V& visitedMap, 
00423                                                const T& pinfo,
00424                                                const AggregatesMap<Vertex>& aggregates,
00425                                                const O& overlap,
00426                                                const OverlapVertex<Vertex>* overlapVertices,
00427                                                const OverlapVertex<Vertex>* overlapEnd,
00428                                                R& row)
00429     {     
00430       typedef typename T::GlobalLookupIndexSet GlobalLookup;
00431       const GlobalLookup& lookup = pinfo.globalLookup();
00432 
00433       typedef typename G::VertexIterator VertexIterator;
00434       
00435       VertexIterator vend=graph.end();
00436 
00437 #ifdef DUNE_ISTL_WITH_CHECKING
00438       std::set<Vertex> examined;
00439 #endif
00440 
00441       // The aggregates owned by the process have lower local indices
00442       // then those not owned. We process them in the first pass.
00443       // They represent the rows 0, 1, ..., n of the coarse matrix
00444       for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex)
00445         if(!get(visitedMap, *vertex)){
00446           // In the first pass we only process owner nodes
00447           typedef typename GlobalLookup::IndexPair IndexPair;
00448           const IndexPair* pair = lookup.pair(*vertex);
00449           if(pair==0 || !overlap.contains(pair->local().attribute())){
00450 #ifdef DUNE_ISTL_WITH_CHECKING
00451             assert(examined.find(aggregates[*vertex])==examined.end());
00452             examined.insert(aggregates[*vertex]);
00453 #endif
00454             constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
00455             ++row;
00456           }
00457         }
00458 
00459 #ifdef DUNE_ISTL_WITH_CHECKING
00460       std::cout<<"constructed "<<row.index()<<" non-overlapping rows"<<std::endl;
00461 #endif
00462 
00463       // Now come the aggregates not owned by use.
00464       // They represent the rows n+1, ..., N
00465       while(overlapVertices != overlapEnd)
00466         if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED){
00467 
00468 #ifdef DUNE_ISTL_WITH_CHECKING
00469           typedef typename GlobalLookup::IndexPair IndexPair;
00470           const IndexPair* pair = lookup.pair(overlapVertices->vertex);
00471           assert(pair!=0 && overlap.contains(pair->local().attribute()));
00472           assert(examined.find(aggregates[overlapVertices->vertex])==examined.end());
00473           examined.insert(aggregates[overlapVertices->vertex]);
00474 #endif
00475           constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
00476           ++row;
00477         }else{
00478           ++overlapVertices;
00479         }
00480     }
00481     
00482     template<class G>
00483     template<class V, class R>
00484     void ConnectivityConstructor<G,SequentialInformation>::examine(G& graph, 
00485                                                                    V& visitedMap, 
00486                                                                    const SequentialInformation& pinfo,
00487                                                                    const AggregatesMap<Vertex>& aggregates,
00488                                                                    R& row)
00489     {     
00490       typedef typename G::VertexIterator VertexIterator;
00491       
00492       VertexIterator vend=graph.end();
00493       for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex){
00494         if(!get(visitedMap, *vertex)){
00495           constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
00496           ++row;
00497         }
00498       }
00499       
00500     }
00501 
00502     template<class M>
00503     SparsityBuilder<M>::SparsityBuilder(M& matrix)
00504       : row_(matrix.createbegin()),
00505         minRowSize_(std::numeric_limits<std::size_t>::max()),
00506         maxRowSize_(0), sumRowSize_(0)
00507     {
00508 #ifdef DUNE_ISTL_WITH_CHECKING
00509       diagonalInserted = false;
00510 #endif
00511 }
00512     template<class M>
00513     std::size_t SparsityBuilder<M>::maxRowSize()
00514     {
00515       return maxRowSize_;
00516     }
00517     template<class M>
00518     std::size_t SparsityBuilder<M>::minRowSize()
00519     {
00520       return minRowSize_;
00521     }
00522 
00523     template<class M>
00524     std::size_t SparsityBuilder<M>::sumRowSize()
00525     {
00526       return sumRowSize_;
00527     }
00528     template<class M>
00529     void SparsityBuilder<M>::operator++()
00530     {
00531       sumRowSize_ += row_.size();
00532       minRowSize_=std::min(minRowSize_, row_.size());
00533       maxRowSize_=std::max(maxRowSize_, row_.size());
00534       ++row_;
00535 #ifdef DUNE_ISTL_WITH_CHECKING
00536       assert(diagonalInserted);
00537       diagonalInserted = false;
00538 #endif
00539     }
00540     
00541     template<class M>
00542     void SparsityBuilder<M>::insert(const typename M::size_type& index)
00543     {
00544       row_.insert(index);
00545 #ifdef DUNE_ISTL_WITH_CHECKING
00546       diagonalInserted = diagonalInserted || row_.index()==index;
00547 #endif
00548     }
00549     
00550     template<class T>
00551     template<class M, class G, class V, class Set>
00552     M* GalerkinProduct<T>::build(const M& fine, G& fineGraph, V& visitedMap,
00553                                  const ParallelInformation& pinfo, 
00554                                  AggregatesMap<typename G::VertexDescriptor>& aggregates,
00555                                  const typename M::size_type& size,
00556                                  const Set& overlap)
00557     {
00558       
00559       typedef OverlapVertex<typename G::VertexDescriptor> OverlapVertex;
00560       
00561       std::size_t count;
00562       
00563       const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph,
00564                                                                   pinfo,
00565                                                                   aggregates,
00566                                                                   overlap,
00567                                                                   count);
00568       M* coarseMatrix = new M(size, size, M::row_wise);
00569 
00570       // Reset the visited flags of all vertices.
00571       // As the isolated nodes will be skipped we simply mark them as visited
00572 
00573       typedef typename G::VertexIterator Vertex;
00574       Vertex vend = fineGraph.end();
00575       for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){
00576         assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
00577         put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
00578       }
00579       
00580       SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
00581 
00582       ConnectivityConstructor<G,T>::examine(fineGraph, visitedMap, pinfo, 
00583                                             aggregates, overlap,
00584                                             overlapVertices,
00585                                             overlapVertices+count,
00586                                             sparsityBuilder);
00587 
00588       dinfo<<pinfo.communicator().rank()<<": Matrix ("<<coarseMatrix->N()<<"x"<<coarseMatrix->M()<<" row: min="<<sparsityBuilder.minRowSize()<<" max="
00589            <<sparsityBuilder.maxRowSize()<<" avg="
00590            <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()
00591            <<std::endl; 
00592       
00593       delete[] overlapVertices;
00594       
00595       //calculate(fine, aggregates, *coarse, overlap);
00596       
00597       return coarseMatrix;
00598     }
00599 
00600     template<class M, class G, class V, class Set>
00601     M* GalerkinProduct<SequentialInformation>::build(const M& fine, G& fineGraph, V& visitedMap,
00602                                                      const SequentialInformation& pinfo, 
00603                                                      const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00604                                                      const typename M::size_type& size,
00605                                                      const Set& overlap)
00606     {     
00607       M* coarseMatrix = new M(size, size, M::row_wise);
00608       
00609       // Reset the visited flags of all vertices.
00610       // As the isolated nodes will be skipped we simply mark them as visited
00611 
00612       typedef typename G::VertexIterator Vertex;
00613       Vertex vend = fineGraph.end();
00614       for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){
00615         assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
00616         put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
00617       }
00618       
00619       SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
00620 
00621       ConnectivityConstructor<G,SequentialInformation>::examine(fineGraph, visitedMap, pinfo, 
00622                                                                 aggregates, sparsityBuilder);
00623       dinfo<<"Matrix row: min="<<sparsityBuilder.minRowSize()<<" max="
00624            <<sparsityBuilder.maxRowSize()<<" average="
00625            <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()<<std::endl;
00626       return coarseMatrix;
00627     }
00628 
00629     template<class M, class V, class P, class O>
00630     void BaseGalerkinProduct::calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse, 
00631                                     const P& pinfo, const O& copy)
00632     {
00633        coarse = static_cast<typename M::field_type>(0);
00634       
00635       typedef typename M::ConstIterator RowIterator;
00636       RowIterator endRow = fine.end();
00637       
00638       for(RowIterator row = fine.begin(); row != endRow; ++row)
00639         if(aggregates[row.index()] != AggregatesMap<V>::ISOLATED){
00640           assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
00641           typedef typename M::ConstColIterator ColIterator;
00642           ColIterator endCol = row->end();
00643           
00644           for(ColIterator col = row->begin(); col != endCol; ++col)
00645             if(aggregates[col.index()] != AggregatesMap<V>::ISOLATED){
00646               assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
00647               coarse[aggregates[row.index()]][aggregates[col.index()]]+=*col;
00648             } 
00649         }
00650 
00651       // get the right diagonal matrix values on copy lines from owner processes  
00652       typedef typename M::block_type BlockType;
00653       std::vector<BlockType> rowsize(coarse.N(),BlockType(0));
00654       for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
00655         rowsize[row.index()]=coarse[row.index()][row.index()];
00656       pinfo.copyOwnerToAll(rowsize,rowsize);
00657       for (RowIterator row = coarse.begin(); row != coarse.end(); ++row)
00658         coarse[row.index()][row.index()] = rowsize[row.index()];
00659       
00660       // don't set dirichlet boundaries for copy lines to make novlp case work,
00661       // the preconditioner yields slightly different results now.
00662 
00663       // Set the dirichlet border      
00664       //DirichletBoundarySetter<P>::template set<M>(coarse, pinfo, copy);
00665     
00666     }
00667 
00668     template<class T>
00669     template<class M, class O>
00670     void DirichletBoundarySetter<T>::set(M& coarse, const T& pinfo, const O& copy)
00671     {
00672       typedef typename T::ParallelIndexSet::const_iterator ConstIterator;
00673       ConstIterator end = pinfo.indexSet().end();
00674       typedef typename M::block_type Block;
00675       Block identity=Block(0.0);
00676       for(typename Block::RowIterator b=identity.begin(); b !=  identity.end(); ++b)
00677         b->operator[](b.index())=1.0;
00678 
00679       for(ConstIterator index = pinfo.indexSet().begin();
00680           index != end; ++index){
00681         if(copy.contains(index->local().attribute())){
00682           typedef typename M::ColIterator ColIterator;
00683           typedef typename M::row_type Row;
00684           Row row = coarse[index->local()];
00685           ColIterator cend = row.find(index->local());
00686           ColIterator col  = row.begin();
00687           for(; col != cend; ++col)
00688             *col = 0;
00689           
00690           cend = row.end();
00691           
00692           assert(col != cend); // There should be a diagonal entry
00693           *col = identity;
00694           
00695           for(++col; col != cend; ++col)
00696             *col = 0;
00697         }
00698       }
00699     }
00700 
00701     template<class M, class O>
00702     void DirichletBoundarySetter<SequentialInformation>::set(M& coarse, 
00703                                                              const SequentialInformation& pinfo,
00704                                                              const O& overlap)
00705     {
00706     }
00707     
00708   }// namespace Amg
00709 }// namespace Dune
00710 #endif

Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].