galerkin.hh

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

Generated on 12 Dec 2007 with Doxygen (ver 1.5.1)