aggregates.hh

Go to the documentation of this file.
00001 // $Id: aggregates.hh 987 2009-01-31 15:06:03Z mblatt $ 
00002 #ifndef DUNE_AMG_AGGREGATES_HH
00003 #define DUNE_AMG_AGGREGATES_HH
00004 
00005 #include"graph.hh"
00006 #include"properties.hh"
00007 #include"combinedfunctor.hh"
00008 
00009 #include<dune/common/timer.hh>
00010 #include<dune/common/tuples.hh>
00011 #include<dune/common/stdstreams.hh>
00012 #include<dune/common/poolallocator.hh>
00013 #include<dune/common/sllist.hh>
00014 
00015 #include<utility>
00016 #include<set>
00017 #include<algorithm>
00018 #include<limits>
00019 #include<ostream>
00020 
00021 namespace Dune
00022 {
00023   namespace Amg
00024   {
00025     
00039     template<class T>
00040     class AggregationCriterion : public T
00041     {
00042 
00043     public:
00047       typedef T DependencyPolicy;
00048       
00052       AggregationCriterion()
00053         : maxDistance_(2), minAggregateSize_(4), maxAggregateSize_(6), 
00054           connectivity_(15), debugLevel_(3)
00055       {}
00056       
00057       
00065       std::size_t maxDistance() const { return maxDistance_;}
00066 
00075       void setMaxDistance(std::size_t distance) { maxDistance_ = distance;}
00076 
00081       std::size_t minAggregateSize() const { return minAggregateSize_;}
00082     
00089       void setMinAggregateSize(std::size_t size){ minAggregateSize_=size;}
00090 
00095       std::size_t maxAggregateSize() const{ return maxAggregateSize_;}
00096 
00103       void setMaxAggregateSize(std::size_t size){ maxAggregateSize_ = size;}
00104 
00112       std::size_t maxConnectivity() const{ return connectivity_;}
00113 
00121       void setMaxConnectivity(std::size_t connectivity){ connectivity_ = connectivity;}
00122 
00128       void setDebugLevel(int level)
00129       {
00130         debugLevel_ = level;
00131       }
00132       
00138       int debugLevel() const
00139       {
00140         return debugLevel_;
00141       }
00142       
00143       
00144     private:
00145       std::size_t maxDistance_, minAggregateSize_, maxAggregateSize_, connectivity_;
00146       int debugLevel_;
00147     };
00148     
00149     template<class T>
00150     std::ostream& operator<<(std::ostream& os, const AggregationCriterion<T>& criterion)
00151     {
00152       os<<"{ maxdistance="<<criterion.maxDistance()<<" minAggregateSize="
00153         <<criterion.minAggregateSize()<< " maxAggregateSize="<<criterion.maxAggregateSize()
00154         <<" connectivity="<<criterion.connectivity()<<" debugLevel="<<criterion.debugLevel()<<"}";
00155       return os;
00156     }
00157 
00161     class DependencyParameters
00162     {
00163     public:
00165       DependencyParameters()
00166         : alpha_(1.0/3.0), beta_(1.0E-5)
00167       {}
00168       
00173       void setBeta(double b)
00174       {
00175         beta_ = b;
00176       }
00177       
00183       double beta() const
00184       {
00185         return beta_;
00186       }
00187       
00192       void setAlpha(double a)
00193       {
00194         alpha_ = a;
00195       }
00196 
00201       double alpha() const
00202       {
00203         return alpha_;
00204       }
00205       
00206     private:
00207       double alpha_, beta_;
00208     };
00209     
00210     
00214     template<class M, class N>
00215     class Dependency : public DependencyParameters
00216     {
00217     public:
00221       typedef M Matrix;
00222       
00226       typedef N Norm;
00227 
00231       typedef typename Matrix::row_type Row;
00232 
00236       typedef typename Matrix::ConstColIterator ColIter;
00237       
00238       void init(const Matrix* matrix);
00239       
00240       void initRow(const Row& row, int index);
00241 
00242       void examine(const ColIter& col);
00243       
00244       template<class G>
00245       void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
00246 
00247       bool isIsolated();
00248     private:
00250       const Matrix* matrix_;
00252       typename Matrix::field_type maxValue_;
00254       Norm norm_;      
00256       int row_;
00258       typename Matrix::field_type diagonal_;
00259     };
00260         
00264     template<class M, class N>
00265     class SymmetricDependency : public DependencyParameters
00266     {
00267     public:
00271       typedef M Matrix;
00272       
00276       typedef N Norm;
00277 
00281       typedef typename Matrix::row_type Row;
00282 
00286       typedef typename Matrix::ConstColIterator ColIter;
00287       
00288       void init(const Matrix* matrix);
00289       
00290       void initRow(const Row& row, int index);
00291 
00292       void examine(const ColIter& col);
00293       
00294       template<class G>
00295       void examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col);
00296 
00297       bool isIsolated();
00298     private:
00300       const Matrix* matrix_;
00302       typename Matrix::field_type maxValue_;
00304       Norm norm_;      
00306       int row_;
00308       typename Matrix::field_type diagonal_;
00309     };
00310 
00315     class FirstDiagonal
00316     {
00317     public:
00322       template<class M>
00323       typename M::field_type operator()(const M& m) const
00324       {
00325         return m[0][0];
00326       }
00327     };
00328     
00334     struct RowSum
00335     {
00340       template<class M>
00341       typename M::field_type operator()(const M& m) const
00342       {
00343         return m.infinity_norm();
00344       }
00345     };
00346 
00356     template<class M, class Norm>
00357     class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
00358     {};
00359 
00360     
00372     template<class M, class Norm>
00373     class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
00374     {};
00375     // forward declaration
00376     template<class G> class Aggregator;
00377 
00378     
00386     template<class V>
00387     class AggregatesMap
00388     {
00389     public:
00390 
00394       static const V UNAGGREGATED;
00395       
00399       static const V ISOLATED;
00403       typedef V VertexDescriptor;
00404       
00408       typedef V AggregateDescriptor;
00409 
00414       typedef PoolAllocator<VertexDescriptor,100> Allocator;
00415       
00420       typedef SLList<VertexDescriptor,Allocator> VertexList;
00421 
00425       class DummyEdgeVisitor
00426       {
00427       public:
00428         template<class EdgeIterator>
00429         void operator()(const EdgeIterator& egde) const
00430         {}
00431       };
00432       
00433         
00437       AggregatesMap();
00438       
00444       AggregatesMap(std::size_t noVertices);
00445 
00449       ~AggregatesMap();
00450 
00458       template<class M, class G, class C>
00459       tuple<int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion);
00460       
00480       template<bool reset, class G, class F, class VM>
00481       std::size_t breadthFirstSearch(const VertexDescriptor& start,
00482                              const AggregateDescriptor& aggregate, 
00483                              const G& graph,
00484                              F& aggregateVisitor,
00485                                      VM& visitedMap) const;
00486       
00510       template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
00511       std::size_t breadthFirstSearch(const VertexDescriptor& start, 
00512                              const AggregateDescriptor& aggregate, 
00513                              const G& graph, L& visited, F1& aggregateVisitor,
00514                              F2& nonAggregateVisitor,
00515                              VM& visitedMap) const;
00516 
00522       void allocate(std::size_t noVertices);
00523       
00527       std::size_t noVertices() const;
00528       
00532       void free();
00533             
00539       AggregateDescriptor& operator[](const VertexDescriptor& v);
00540       
00546       const AggregateDescriptor& operator[](const VertexDescriptor& v) const;
00547 
00548       typedef const AggregateDescriptor* const_iterator;
00549       
00550       const_iterator begin() const
00551       {
00552         return aggregates_;
00553       }
00554       
00555       const_iterator end() const
00556       {
00557         return aggregates_+noVertices();
00558       }
00559       
00560       typedef AggregateDescriptor* iterator;
00561       
00562       iterator begin()
00563       {
00564         return aggregates_;
00565       }
00566       
00567       iterator end()
00568       {
00569         return aggregates_+noVertices();
00570       }
00571     private:
00573       AggregatesMap(const AggregatesMap<V>& map)
00574       {
00575         throw "Auch!";
00576       }
00577       
00579       AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
00580       {
00581         throw "Auch!";
00582         return this;
00583       }
00584       
00588       AggregateDescriptor* aggregates_;
00589 
00593       std::size_t noVertices_;
00594     };
00595     
00596     
00601     template<class G, class S>
00602     class Aggregate
00603     {
00604       
00605     public:
00606             
00607       /***
00608        * @brief The type of the matrix graph we work with.
00609        */
00610       typedef G MatrixGraph;
00614       typedef typename MatrixGraph::VertexDescriptor Vertex;
00615 
00620       typedef PoolAllocator<Vertex,100> Allocator;
00621       
00626       typedef SLList<Vertex,Allocator> VertexList;
00627 
00628       
00633       typedef S VertexSet;
00634 
00636       typedef typename VertexList::const_iterator const_iterator;
00637 
00641       typedef std::size_t* SphereMap;
00642       
00650       Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates, 
00651                 VertexSet& connectivity);
00652             
00659       void reconstruct(const Vertex& vertex);
00660       
00664       void seed(const Vertex& vertex);
00665       
00669       void add(const Vertex& vertex);
00670       
00674       void clear();
00675       
00679       typename VertexList::size_type size();
00680       
00684       int id();
00685       
00687       const_iterator begin() const;
00688       
00690       const_iterator end() const;
00691       
00692     private:
00696       VertexList vertices_;
00697       
00702       int id_;
00703 
00707       const MatrixGraph& graph_;
00708       
00712       AggregatesMap<Vertex>& aggregates_;
00713 
00717       VertexSet& connected_;
00718     };
00719     
00723     template<class G>
00724     class Aggregator
00725     {
00726     public:
00727             
00731       typedef G MatrixGraph;
00732 
00736       typedef typename MatrixGraph::VertexDescriptor Vertex;
00737       
00739       typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor;
00740 
00744       Aggregator();
00745       
00749       ~Aggregator();
00750       
00763       template<class M, class C>
00764       tuple<int,int,int> build(const M& m, G& graph, 
00765                                AggregatesMap<Vertex>& aggregates, const C& c);
00766     private:
00771       typedef PoolAllocator<Vertex,1> Allocator;
00772       
00776       typedef SLList<Vertex,Allocator> VertexList;
00777 
00781       typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
00782 
00786       typedef std::size_t* SphereMap;
00787       
00791       MatrixGraph* graph_;
00792       
00796       Aggregate<MatrixGraph,VertexSet>* aggregate_;
00797       
00801       VertexList front_;
00802 
00806       VertexSet connected_;
00807             
00811       int size_;
00812       
00816       class Stack
00817       {
00818       public:
00819         static const Vertex NullEntry;
00820         
00821         Stack(const MatrixGraph& graph, 
00822               const Aggregator<G>& aggregatesBuilder,
00823               const AggregatesMap<Vertex>& aggregates);
00824         ~Stack();
00825         bool push(const Vertex& v);
00826         void fill();
00827         Vertex pop();
00828       private:
00829         enum{ N = 256000 };
00830         
00832         const MatrixGraph& graph_;
00834         const Aggregator<G>& aggregatesBuilder_;
00836         const AggregatesMap<Vertex>& aggregates_;
00838         int size_;
00839         int maxSize_;
00841         int head_;
00842         int filled_;
00843         
00845         Vertex* vals_;
00846 
00847         void localPush(const Vertex& v);
00848       };
00849 
00850       friend class Stack;
00851       
00855       template<class C>
00856       void buildDependency(MatrixGraph& graph,
00857                            const typename C::Matrix& matrix,
00858                            C criterion);
00859 
00870       template<class V>
00871       void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,  
00872                                     const AggregatesMap<Vertex>& aggregates,
00873                                     V& visitor) const;
00874 
00879       template<class V>
00880       class AggregateVisitor
00881       {
00882       public:
00886         typedef V Visitor;
00894         AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
00895                          Visitor& visitor);
00896         
00903         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00904         
00905       private:
00907         const AggregatesMap<Vertex>& aggregates_;
00909         AggregateDescriptor aggregate_;
00911         Visitor* visitor_;
00912       };
00913 
00917       class Counter
00918       {
00919       public:
00921         Counter();
00923         int value();
00924         
00925       protected:
00927         void increment();
00929         void decrement();
00930         
00931       private:
00932         int count_;
00933       };
00934 
00935       
00940       class FrontNeighbourCounter : public Counter
00941       {
00942       public:
00947         FrontNeighbourCounter(const MatrixGraph& front);
00948         
00949         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00950         
00951       private:
00952         const MatrixGraph& graph_;
00953       };
00954       
00959       int noFrontNeighbours(const Vertex& vertex) const;
00960       
00964       class TwoWayCounter : public Counter
00965       {
00966       public:
00967         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00968       };
00969 
00981       int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,  
00982                              const AggregatesMap<Vertex>& aggregates) const;
00983 
00987       class OneWayCounter : public Counter
00988       {
00989       public:
00990         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00991       };        
00992 
01004       int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,  
01005                             const AggregatesMap<Vertex>& aggregates) const;
01006       
01013       class ConnectivityCounter : public Counter
01014       {
01015       public:
01022         ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
01023 
01024         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01025 
01026       private:
01028         const VertexSet& connected_;
01030         const AggregatesMap<Vertex>& aggregates_;
01031         
01032       };
01033 
01045       double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01046       
01054       class DependencyCounter: public Counter
01055       {
01056       public:
01060         DependencyCounter();
01061         
01062         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01063       };
01064       
01071       class FrontMarker
01072       {
01073       public:
01080         FrontMarker(VertexList& front, MatrixGraph& graph);
01081         
01082         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01083         
01084       private:
01086         VertexList& front_;
01088         MatrixGraph& graph_;
01089       };
01090 
01097       void markFront(const AggregatesMap<Vertex>& aggregates);
01098       
01102       void unmarkFront();
01103       
01118       int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01119 
01133       std::pair<int,int> neighbours(const Vertex& vertex, 
01134                                     const AggregateDescriptor& aggregate,
01135                                     const AggregatesMap<Vertex>& aggregates) const;
01152       int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01153       
01161       bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01162       
01169       void seedFromFront(Stack& stack,  bool isolated);
01170         
01178       std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
01179 
01188       Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01189 
01197       template<class C>
01198       void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
01199     };
01200 
01201     template<class M, class N>
01202     inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
01203     {
01204       matrix_ = matrix;
01205     }
01206     
01207     template<class M, class N>
01208     inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
01209     {
01210       maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01211       row_ = index;
01212       diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01213     }
01214 
01215     template<class M, class N>
01216     inline void SymmetricDependency<M,N>::examine(const ColIter& col)
01217     {
01218       maxValue_ = std::max(maxValue_, 
01219                            (norm_(*col) * norm_(matrix_->operator[](col.index())[row_]))/
01220                            (norm_(matrix_->operator[](col.index())[col.index()]) * diagonal_));
01221       //(diagonal_*diagonal_));
01222     }
01223     
01224     template<class M, class N>
01225     template<class G>
01226     inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01227     {      
01228       if(norm_(matrix_->operator[](edge.target())[edge.source()]) * norm_(*col)/
01229          (norm_(matrix_->operator[](edge.target())[edge.target()]) * diagonal_) > alpha() * maxValue_){
01230         edge.properties().setDepends();
01231         edge.properties().setInfluences();
01232 
01233         typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
01234         other.setInfluences();
01235         other.setDepends();
01236       }
01237     }
01238     
01239     template<class M, class N>
01240     inline bool SymmetricDependency<M,N>::isIsolated()
01241     {
01242       return maxValue_  < beta();
01243     }
01244     
01245     
01246     template<class M, class N>
01247     inline void Dependency<M,N>::init(const Matrix* matrix)
01248     {
01249       matrix_ = matrix;
01250     }
01251     
01252     template<class M, class N>
01253     inline void Dependency<M,N>::initRow(const Row& row, int index)
01254     {
01255       maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01256       row_ = index;
01257       diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01258     }
01259 
01260     template<class M, class N>
01261     inline void Dependency<M,N>::examine(const ColIter& col)
01262     {
01263       maxValue_ = std::max(maxValue_, 
01264                            -norm_(*col));
01265     }
01266     
01267     template<class M, class N>
01268     template<class G>
01269     inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01270     {      
01271       if(-norm_(*col) >= maxValue_ * alpha()){
01272         edge.properties().setDepends();
01273         edge.properties().setInfluences();
01274       }
01275     }
01276     
01277     template<class M, class N>
01278     inline bool Dependency<M,N>::isIsolated()
01279     {
01280       return maxValue_  < beta() * diagonal_;
01281     }
01282     
01283     template<class G,class S>
01284     Aggregate<G,S>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
01285                             VertexSet& connected)
01286       : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
01287         connected_(connected)
01288     {}
01289     
01290     template<class G,class S>
01291     void Aggregate<G,S>::reconstruct(const Vertex& vertex)
01292     {
01293       vertices_.push_back(vertex);
01294       typedef typename VertexList::const_iterator iterator;
01295       iterator begin = vertices_.begin();
01296       iterator end   = vertices_.end();
01297       throw "Not yet implemented";
01298 
01299       while(begin!=end){
01300         //for();
01301       }
01302       
01303     }
01304     
01305     template<class G,class S>
01306     inline void Aggregate<G,S>::seed(const Vertex& vertex)
01307     {
01308       dvverb<<"Connected cleared"<<std::endl;
01309       connected_.clear();
01310       vertices_.clear();
01311       connected_.insert(vertex);
01312       dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
01313       id_ = vertex;
01314       add(vertex);
01315     }
01316     
01317 
01318     template<class G,class S>
01319     inline void Aggregate<G,S>::add(const Vertex& vertex)
01320     {
01321       vertices_.push_back(vertex);
01322       aggregates_[vertex]=id_;
01323 
01324       typedef typename MatrixGraph::ConstEdgeIterator iterator;
01325       const iterator end = graph_.endEdges(vertex);
01326       for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){
01327         dvverb << " Inserting "<<aggregates_[edge.target()];
01328         connected_.insert(aggregates_[edge.target()]);
01329         dvverb <<" size="<<connected_.size();
01330       }
01331       dvverb <<std::endl;
01332     }
01333     template<class G,class S>
01334     inline void Aggregate<G,S>::clear()
01335     {
01336       vertices_.clear();
01337       connected_.clear();
01338       id_=-1;
01339     }
01340     
01341     template<class G,class S>
01342     inline typename Aggregate<G,S>::VertexList::size_type 
01343     Aggregate<G,S>::size()
01344     {
01345       return vertices_.size();
01346     }
01347     
01348     template<class G,class S>
01349     inline int Aggregate<G,S>::id()
01350     {
01351       return id_;
01352     }
01353 
01354     template<class G,class S>
01355     inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::begin() const
01356     {
01357       return vertices_.begin();
01358     }
01359     
01360     template<class G,class S>
01361     inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
01362     {
01363       return vertices_.end();
01364     }
01365 
01366     template<class V> 
01367     const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
01368     
01369     template<class V> 
01370     const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
01371     
01372     template<class V>
01373     AggregatesMap<V>::AggregatesMap()
01374       : aggregates_(0)
01375     {}
01376 
01377     template<class V>
01378     AggregatesMap<V>::~AggregatesMap()
01379     {
01380       if(aggregates_!=0)
01381         delete[] aggregates_;
01382     }
01383     
01384 
01385     template<class V>
01386     inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
01387     {
01388       allocate(noVertices);
01389     }
01390 
01391     template<class V>
01392     inline std::size_t AggregatesMap<V>::AggregatesMap::noVertices() const
01393     {
01394       return noVertices_;
01395     }
01396     
01397     template<class V>
01398     inline void AggregatesMap<V>::allocate(std::size_t noVertices)
01399     {
01400       aggregates_ = new AggregateDescriptor[noVertices];
01401       noVertices_ = noVertices;
01402       
01403       for(std::size_t i=0; i < noVertices; i++)
01404         aggregates_[i]=UNAGGREGATED;
01405     }
01406 
01407     template<class V>
01408     inline void AggregatesMap<V>::free()
01409     {
01410       assert(aggregates_ != 0);
01411       delete[] aggregates_;
01412       aggregates_=0;
01413     }
01414     
01415     template<class V>
01416     inline typename AggregatesMap<V>::AggregateDescriptor& 
01417     AggregatesMap<V>::operator[](const VertexDescriptor& v)
01418     {
01419       return aggregates_[v];
01420     }
01421 
01422     template<class V>
01423     inline const typename AggregatesMap<V>::AggregateDescriptor& 
01424     AggregatesMap<V>::operator[](const VertexDescriptor& v) const
01425     {
01426       return aggregates_[v];
01427     }
01428 
01429     template<class V>
01430     template<bool reset, class G, class F,class VM>
01431     inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01432                                                     const AggregateDescriptor& aggregate, 
01433                                                     const G& graph, F& aggregateVisitor,
01434                                                             VM& visitedMap) const
01435     {
01436       VertexList vlist;
01437       
01438       DummyEdgeVisitor dummy;
01439       return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
01440     }
01441       
01442     template<class V>
01443     template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
01444     std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01445                                              const AggregateDescriptor& aggregate, 
01446                                              const G& graph,
01447                                              L& visited,
01448                                              F1& aggregateVisitor,
01449                                              F2& nonAggregateVisitor,
01450                                              VM& visitedMap) const
01451     {
01452       typedef typename L::const_iterator ListIterator;
01453       int visitedSpheres = 0;
01454       
01455       visited.push_back(start);
01456       put(visitedMap, start, true);
01457       
01458       ListIterator current = visited.begin();
01459       ListIterator end = visited.end();
01460       std::size_t i=0, size=visited.size();
01461       
01462       // visit the neighbours of all vertices of the
01463       // current sphere.
01464       while(current != end){
01465         
01466         for(;i<size; ++current, ++i){
01467           typedef typename G::ConstEdgeIterator EdgeIterator;
01468           const EdgeIterator endEdge = graph.endEdges(*current);
01469           
01470           for(EdgeIterator edge = graph.beginEdges(*current);
01471               edge != endEdge; ++edge){
01472           
01473             if(aggregates_[edge.target()]==aggregate){
01474               if(!get(visitedMap, edge.target())){
01475                 put(visitedMap, edge.target(), true);
01476                 visited.push_back(edge.target());
01477                 aggregateVisitor(edge);
01478               }
01479             }else
01480               nonAggregateVisitor(edge);
01481           }
01482         }       
01483         end = visited.end();
01484         size = visited.size();
01485         if(current != end)
01486           visitedSpheres++;
01487       }
01488       
01489       if(reset)
01490         for(current = visited.begin(); current != end; ++current)
01491           put(visitedMap, *current, false);
01492       
01493         
01494       if(remove)
01495         visited.clear();
01496       
01497       return visitedSpheres;
01498     }
01499     
01500     template<class G>
01501     Aggregator<G>::Aggregator()
01502       : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
01503     {}
01504     
01505     template<class G>
01506     Aggregator<G>::~Aggregator()
01507     {
01508       size_=-1;
01509     }
01510     
01511     template<class G>
01512     template<class C>
01513     void Aggregator<G>::buildDependency(MatrixGraph& graph,
01514                                         const typename C::Matrix& matrix,
01515                                         C criterion)
01516     {
01517       // The Criterion we use for building the dependency.
01518       typedef C Criterion;
01519      
01520       //      assert(graph.isBuilt());
01521       typedef typename C::Matrix Matrix;
01522       typedef typename MatrixGraph::VertexIterator VertexIterator;
01523       
01524       criterion.init(&matrix);
01525       
01526       for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){
01527         typedef typename Matrix::row_type Row;
01528         
01529         const Row& row = matrix[*vertex];
01530         
01531         // Tell the criterion what row we will examine now
01532         // This might for example be used for calculating the
01533         // maximum offdiagonal value
01534         criterion.initRow(row, *vertex);
01535         
01536         // On a first path all columns are examined. After this 
01537         // the calculator should know whether the vertex is isolated.
01538         typedef typename Matrix::ConstColIterator ColIterator;
01539         ColIterator end = row.end();
01540         for(ColIterator col = row.begin(); col != end; ++col)
01541           if(col.index()!=*vertex)
01542             criterion.examine(col);
01543         
01544         // reset the vertex properties
01545         //vertex.properties().reset();
01546                 
01547         // Check whether the vertex is isolated.
01548         if(criterion.isIsolated()){
01549           //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
01550           vertex.properties().setIsolated();
01551         }else{
01552           // Examine all the edges beginning at this vertex.
01553           typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01554           typedef typename Matrix::ConstColIterator ColIterator;
01555           EdgeIterator end = vertex.end();
01556           ColIterator col = matrix[*vertex].begin();
01557           
01558           for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01559             // Move to the right column.
01560             while(col.index()!=edge.target())
01561               ++col;
01562             criterion.examine(graph, edge, col);
01563           }
01564         }
01565         
01566       }
01567     }
01568 
01569     
01570     template<class G>
01571     template<class V>
01572     inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates, 
01573                                                         const AggregateDescriptor& aggregate, V& visitor)
01574       : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01575     {}
01576     
01577     template<class G>
01578     template<class V>
01579     inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01580     {
01581       if(aggregates_[edge.target()]==aggregate_)
01582         visitor_->operator()(edge);
01583     }
01584     
01585     template<class G>
01586     template<class V>
01587     inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01588                                                         const AggregateDescriptor& aggregate, 
01589                                                         const AggregatesMap<Vertex>& aggregates,
01590                                                         V& visitor) const
01591     {  
01592       // Only evaluates for edge pointing to the aggregate
01593       AggregateVisitor<V> v(aggregates, aggregate, visitor);
01594       visitNeighbours(*graph_, vertex, v);
01595     }
01596     
01597     
01598     template<class G>
01599     inline Aggregator<G>::Counter::Counter()
01600       : count_(0)
01601     {}
01602     
01603     template<class G>
01604     inline void Aggregator<G>::Counter::increment()
01605     {
01606       ++count_;
01607     }
01608 
01609     template<class G>
01610     inline void Aggregator<G>::Counter::decrement()
01611     {
01612       --count_;
01613     }
01614     template<class G>
01615     inline int Aggregator<G>::Counter::value()
01616     {
01617       return count_;
01618     }
01619     
01620     template<class G>
01621     inline void  Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01622     {
01623       if(edge.properties().isTwoWay())
01624         Counter::increment();
01625     }
01626     
01627     template<class G>
01628     int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01629                                          const AggregatesMap<Vertex>& aggregates) const
01630     {
01631       TwoWayCounter counter;
01632       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01633       return counter.value();
01634     }
01635     
01636     template<class G>
01637     int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01638                                          const AggregatesMap<Vertex>& aggregates) const
01639     {
01640       OneWayCounter counter;
01641       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01642       return counter.value();
01643     }
01644     
01645     template<class G>
01646     inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01647     {
01648       if(edge.properties().isOneWay())
01649         Counter::increment();
01650     }
01651     
01652     template<class G>
01653     inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01654                                                                    const AggregatesMap<Vertex>& aggregates)
01655       : Counter(), connected_(connected), aggregates_(aggregates)
01656     {}
01657     
01658     
01659     template<class G>
01660     inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01661     {
01662       if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01663         // Would be a new connection
01664         Counter::increment();
01665       else{
01666         Counter::increment();
01667         Counter::increment();
01668       }
01669     }
01670     
01671     template<class G>
01672     inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01673     {
01674       ConnectivityCounter counter(connected_, aggregates);
01675       double noNeighbours=visitNeighbours(*graph_, vertex, counter);
01676       return (double)counter.value()/noNeighbours;
01677     }
01678     
01679     template<class G>
01680     inline Aggregator<G>::DependencyCounter::DependencyCounter()
01681       : Counter()
01682     {}
01683     
01684     template<class G>
01685     inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01686     {
01687       if(edge.properties().depends())
01688         Counter::increment();
01689       if(edge.properties().influences())
01690         Counter::increment();
01691     }
01692     
01693     template<class G>
01694     int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01695     {
01696       return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01697     }
01698     
01699     template<class G>
01700     std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01701                                                  const AggregateDescriptor& aggregate,
01702                                                  const AggregatesMap<Vertex>& aggregates) const
01703     {
01704       DependencyCounter unused, aggregated;
01705       typedef AggregateVisitor<DependencyCounter> Counter;
01706       typedef tuple<Counter,Counter> CounterTuple;
01707       CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
01708       return std::make_pair(unused.value(), aggregated.value());
01709 }
01710       
01711       
01712     template<class G>
01713     int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01714     {
01715       DependencyCounter counter;
01716       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01717       return counter.value();
01718     }
01719     
01720     template<class G>
01721     std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01722     {
01723       typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01724       VertexList vlist;
01725       typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01726       return aggregates.template breadthFirstSearch<true,true>(vertex, 
01727                                                       aggregate_->id(), *graph_, 
01728                                            vlist, dummy, dummy, visitedMap);
01729     }
01730     
01731     template<class G>
01732     inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01733       : front_(front), graph_(graph)
01734     {}
01735     
01736     template<class G>
01737     inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01738     {
01739       Vertex target = edge.target();
01740       
01741       if(!graph_.getVertexProperties(target).front()){
01742         front_.push_back(target);
01743         graph_.getVertexProperties(target).setFront();
01744       }
01745     }
01746         
01747 
01748     template<class G>
01749     void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01750     {
01751       assert(front_.size()==0);
01752       FrontMarker frontBuilder(front_, *graph_);
01753       typedef typename Aggregate<G,VertexSet>::const_iterator Iterator;
01754       
01755       for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01756         visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01757       
01758     }
01759 
01760     template<class G>
01761     inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01762     {
01763       // Todo
01764       Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01765       
01766       return true;
01767     }
01768     
01769     template<class G>
01770     void Aggregator<G>::unmarkFront()
01771     {      
01772       typedef typename VertexList::const_iterator Iterator;
01773       
01774       for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01775         graph_->getVertexProperties(*vertex).resetFront();      
01776       
01777       front_.clear();
01778     }
01779 
01780     template<class G>
01781     inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01782     {
01783       typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01784       
01785       Iterator end = graph_->endEdges(vertex);
01786       for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01787         if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01788            graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01789           if( graph_->getVertexProperties(vertex).isolated() || 
01790               ((edge.properties().depends() || edge.properties().influences())
01791                && admissible(vertex, aggregates[edge.target()], aggregates)))
01792             return edge.target();
01793         }
01794       }
01795       return AggregatesMap<Vertex>::UNAGGREGATED;
01796     }
01797     
01798     template<class G>
01799     Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01800       : Counter(), graph_(graph)
01801     {}
01802 
01803     template<class G>
01804     void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01805     {
01806       if(graph_.getVertexProperties(edge.target()).front())
01807         Counter::increment();
01808     }
01809     
01810     template<class G>
01811     int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01812     {
01813       FrontNeighbourCounter counter(*graph_);
01814       visitNeighbours(*graph_, vertex, counter);
01815       return counter.value();
01816     }
01817     
01818     template<class G>
01819     template<class C>
01820     void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01821     {
01822       while(aggregate_->size() < c.minAggregateSize()){
01823         int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
01824         double maxCon=-1;
01825                 
01826         Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01827         
01828         unmarkFront();
01829         markFront(aggregates);
01830 
01831         typedef typename VertexList::const_iterator Iterator;
01832           
01833         for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01834           // Only nonisolated nodes are considered
01835           if(graph_->getVertexProperties(*vertex).isolated())
01836             continue;
01837           
01838           int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01839           
01840           /* The case of two way connections. */
01841           if( maxTwoCons == twoWayCons && twoWayCons > 0){
01842             double con = connectivity(*vertex, aggregates);
01843 
01844             if(con == maxCon){
01845               int neighbours = noFrontNeighbours(*vertex);
01846               
01847               if(neighbours > maxNeighbours){
01848                 maxNeighbours = neighbours;
01849                 
01850                 std::size_t distance_ = distance(*vertex, aggregates);
01851 
01852                 if(c.maxDistance() >= distance_){
01853                   candidate = *vertex;
01854                 }
01855               }
01856             }else if( con > maxCon){
01857               maxCon = con;
01858               maxNeighbours = noFrontNeighbours(*vertex);
01859               std::size_t distance_ = distance(*vertex, aggregates);
01860 
01861               if(c.maxDistance() >= distance_){
01862                 candidate = *vertex;
01863               }
01864             }
01865           }else if(twoWayCons > maxTwoCons){
01866             maxTwoCons = twoWayCons;
01867             maxCon = connectivity(*vertex, aggregates);
01868             maxNeighbours = noFrontNeighbours(*vertex);
01869             std::size_t distance_ = distance(*vertex, aggregates);
01870             
01871             if(c.maxDistance() >= distance_){
01872               candidate = *vertex;
01873             }
01874             
01875             // two way connections preceed
01876             maxOneCons = std::numeric_limits<int>::max();
01877           }
01878           
01879           if(twoWayCons > 0)
01880             continue; // THis is a two-way node, skip tests for one way nodes
01881 
01882           /* The one way case */
01883           int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01884           
01885           if(oneWayCons==0)
01886             continue; // No strong connections, skip the tests.
01887 
01888           if(!admissible(*vertex, aggregate_->id(), aggregates))
01889             continue;
01890           
01891           if( maxOneCons == oneWayCons && oneWayCons > 0){
01892             double con = connectivity(*vertex, aggregates);
01893 
01894             if(con == maxCon){
01895               int neighbours = noFrontNeighbours(*vertex);
01896               
01897               if(neighbours > maxNeighbours){
01898                 maxNeighbours = neighbours;
01899                 std::size_t distance_ = distance(*vertex, aggregates);
01900                 
01901                 if(c.maxDistance() >= distance_){
01902                   candidate = *vertex;
01903                 }
01904               }
01905             }else if( con > maxCon){
01906               maxCon = con;
01907               maxNeighbours = noFrontNeighbours(*vertex);
01908               std::size_t distance_ = distance(*vertex, aggregates);
01909               if(c.maxDistance() >= distance_){
01910                 candidate = *vertex;
01911               }
01912             }
01913           }else if(oneWayCons > maxOneCons){
01914             maxOneCons = oneWayCons;
01915             maxCon = connectivity(*vertex, aggregates);
01916             maxNeighbours = noFrontNeighbours(*vertex);
01917             std::size_t distance_ = distance(*vertex, aggregates);
01918                 
01919             if(c.maxDistance() >= distance_){
01920               candidate = *vertex;
01921             }
01922           }
01923         }
01924         
01925         
01926         if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01927           break; // No more candidates found
01928 
01929         aggregate_->add(candidate);
01930       }
01931     }
01932       
01933     template<typename V>
01934     template<typename M, typename G, typename C>
01935     tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01936     {
01937       Aggregator<G> aggregator;
01938       return aggregator.build(matrix, graph, *this, criterion);
01939     }
01940     
01941     template<class G>
01942     template<class M, class C>
01943     tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01944     {
01945       // Stack for fast vertex access
01946       Stack stack_(graph, *this, aggregates);
01947       
01948       graph_ = &graph;
01949             
01950       aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_);
01951       
01952       // Allocate the mapping to aggregate.
01953       size_ = graph.maxVertex();
01954 
01955       Timer watch;
01956       watch.reset();
01957 
01958       buildDependency(graph, m, c);
01959 
01960       dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01961       int noAggregates, conAggregates, isoAggregates, oneAggregates;
01962       noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01963       
01964       while(true){
01965         Vertex seed = stack_.pop();
01966         
01967         if(seed == Stack::NullEntry)
01968           // No more unaggregated vertices. We are finished!
01969           break;
01970         
01971         // Debugging output
01972         if((noAggregates+1)%10000 == 0)
01973           Dune::dverb<<"c";
01974         
01975         aggregate_->seed(seed);
01976         
01977         
01978         if(graph.getVertexProperties(seed).isolated()){
01979           // isolated vertices are not aggregated but skipped on the coarser levels.
01980           aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01981           ++isoAggregates;
01982           // skip rest as no agglomeration is done.
01983           continue;
01984         }else
01985           growAggregate(seed, aggregates, c);
01986         
01987         
01988         /* The rounding step. */
01989         while(aggregate_->size() < c.maxAggregateSize()){
01990           
01991           unmarkFront();
01992           markFront(aggregates);
01993           
01994           Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01995           
01996           typedef typename VertexList::const_iterator Iterator;
01997           
01998           for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01999 
02000             if(graph.getVertexProperties(*vertex).isolated())
02001               continue; // No isolated nodes here
02002 
02003             if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 && 
02004                (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 || 
02005                 !admissible( *vertex, aggregate_->id(), aggregates) ))
02006               continue;
02007           
02008             std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
02009                                                      aggregates);
02010             
02011             //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
02012             // continue;
02013             
02014             if(neighbourPair.first >= neighbourPair.second)
02015               continue;
02016                     
02017             if(distance(*vertex, aggregates) > c.maxDistance())
02018               continue; // Distance too far
02019             candidate = *vertex;
02020             break;
02021           }
02022                   
02023           if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break; // no more candidates found.
02024           
02025           aggregate_->add(candidate);
02026           
02027         }
02028         
02029         // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
02030         if(aggregate_->size()==1)
02031           if(!graph.getVertexProperties(seed).isolated()){
02032             Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02033 
02034             if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02035               aggregates[seed] = aggregates[mergedNeighbour];
02036               /* // Reconstruct aggregate. Needed for markFront
02037               this->template breadthFirstSearch<
02038               visitAggregateNeighbours(seed, aggregates[seed], aggregates,)
02039               if(aggregate_->size()==2)
02040                 // Was a one node aggregate formerly
02041                 --oneAggregates;
02042               */
02043             }else{
02044               ++oneAggregates;
02045               ++conAggregates;
02046             }
02047             
02048           }else{
02049             ++oneAggregates;
02050             ++isoAggregates;
02051           }
02052         else{
02053           if(graph.getVertexProperties(seed).isolated())
02054             ++isoAggregates;
02055           else
02056             ++conAggregates;
02057         }
02058         unmarkFront();
02059         markFront(aggregates);
02060         seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02061         unmarkFront();
02062       }
02063       
02064       Dune::dinfo<<"connected aggregates: "<<conAggregates;
02065       Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02066       Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02067       
02068       delete aggregate_;
02069       return make_tuple(conAggregates,isoAggregates,oneAggregates);
02070     }
02071     
02072     template<class G>
02073     inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02074     {
02075       typedef typename VertexList::const_iterator Iterator;
02076       
02077       Iterator end= front_.end();
02078       int count=0;
02079       for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02080         stack_.push(*vertex);
02081       /*
02082       if(MINIMAL_DEBUG_LEVEL<=2 && count==0 && !isolated)
02083         Dune::dverb<< " no vertices pushed for nonisolated aggregate!"<<std::endl;
02084       */
02085     }
02086 
02087     template<class G>
02088     Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02089                                 const AggregatesMap<Vertex>& aggregates)
02090       : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02091     {
02092       vals_ = new  Vertex[N];
02093     }
02094     
02095     template<class G>
02096     Aggregator<G>::Stack::~Stack()
02097     {
02098       Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02099       delete[] vals_;
02100     }
02101     
02102     template<class G> 
02103     const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry 
02104     = std::numeric_limits<typename G::VertexDescriptor>::max();
02105 
02106     template<class G>
02107     inline bool Aggregator<G>::Stack::push(const Vertex& v)
02108     {
02109       if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02110         localPush(v);
02111         return true;
02112       }else
02113         return false;
02114     }
02115     
02116     template<class G>
02117     inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02118     {
02119       vals_[head_] = v;
02120       size_ = std::min<int>(size_+1, N);
02121       head_ = (head_+N+1)%N;
02122     }
02123     
02124     template<class G>
02125     void Aggregator<G>::Stack::fill()
02126     {
02127       int isolated = 0, connected=0;
02128       int isoumin, umin;
02129       filled_++;
02130       
02131       head_ = size_ = 0;
02132       isoumin = umin = std::numeric_limits<int>::max();
02133       
02134       typedef typename MatrixGraph::ConstVertexIterator Iterator;
02135       
02136       const Iterator end = graph_.end();
02137       
02138       for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02139         // Skip already aggregated vertices
02140         if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02141           continue;
02142         
02143         if(vertex.properties().isolated()){
02144           isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02145           isolated++;
02146         }else{
02147           umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02148           connected++;
02149         }
02150       }
02151       
02152       if(connected + isolated == 0)
02153         // No unaggregated vertices.
02154         return;
02155         
02156       if(connected > 0){
02157         // Connected vertices have higher priority.
02158          for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02159            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated() 
02160               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02161              localPush(*vertex);
02162       }else{
02163         for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02164            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated() 
02165               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02166              localPush(*vertex);
02167       }
02168       maxSize_ = std::max(size_, maxSize_);
02169     }
02170 
02171     template<class G>
02172     inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02173     {
02174       while(size_>0){
02175         head_ = (head_ + N -1) % N;
02176         size_--;
02177         Vertex v = vals_[head_];
02178         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02179           return v;
02180       }
02181       // Stack is empty try to fill it
02182       fill();
02183       
02184       // try again
02185       while(size_>0){
02186         head_ = (head_ + N -1) % N;
02187         size_--;
02188         Vertex v = vals_[head_];
02189         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02190           return v;
02191       }
02192       return NullEntry;
02193     }
02194 
02195     template<class V>
02196     void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m,  std::ostream& os)
02197     {
02198       std::ios_base::fmtflags oldOpts=os.flags();
02199       
02200       os.setf(std::ios_base::right, std::ios_base::adjustfield);
02201       
02202       V max=0;
02203       int width=1;
02204 
02205       for(int i=0; i< n*m; i++)
02206         max=std::max(max, aggregates[i]);
02207       
02208       for(int i=10; i < 1000000; i*=10)
02209         if(max/i>0)
02210           width++;
02211         else
02212           break;
02213       
02214       for(int j=0, entry=0; j < m; j++){
02215         for(int i=0; i<n; i++, entry++){
02216           os.width(width);
02217           os<<aggregates[entry]<<" ";
02218         }
02219         
02220         os<<std::endl;
02221       }
02222       os<<std::endl;
02223       os.flags(oldOpts);
02224     }
02225     
02226     
02227   }// namespace Amg
02228   
02229 }// namespace Dune
02230 
02231 
02232 #endif

Generated on Thu Apr 2 10:40:13 2009 for dune-istl by  doxygen 1.5.6