galerkin.hh

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