aggregates.hh

Go to the documentation of this file.
00001 // $Id: aggregates.hh 776 2007-05-10 11:12:19Z 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*sizeof(int)> 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                              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                              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     private:
00550       AggregatesMap(const AggregatesMap<V>& map)
00551       {
00552         throw "Auch!";
00553       }
00554       
00556       AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
00557       {
00558         throw "Auch!";
00559         return this;
00560       }
00561       
00565       AggregateDescriptor* aggregates_;
00566 
00570       std::size_t noVertices_;
00571     };
00572     
00573     
00578     template<class G>
00579     class Aggregate
00580     {
00581       
00582     public:
00583             
00584       /***
00585        * @brief The type of the matrix graph we work with.
00586        */
00587       typedef G MatrixGraph;
00591       typedef typename MatrixGraph::VertexDescriptor Vertex;
00592 
00597       typedef PoolAllocator<Vertex,100*sizeof(int)> Allocator;
00598       
00603       typedef SLList<Vertex,Allocator> VertexList;
00604 
00605       
00610       typedef std::set<Vertex> VertexSet;
00611 
00613       typedef typename VertexList::const_iterator const_iterator;
00614 
00618       typedef std::size_t* SphereMap;
00619       
00627       Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates, 
00628                 VertexSet& connectivity);
00629             
00636       void reconstruct(const Vertex& vertex);
00637       
00641       void seed(const Vertex& vertex);
00642       
00646       void add(const Vertex& vertex);
00647       
00651       void clear();
00652       
00656       typename VertexList::size_type size();
00657       
00661       int id();
00662       
00664       const_iterator begin() const;
00665       
00667       const_iterator end() const;
00668       
00669     private:
00673       VertexList vertices_;
00674       
00679       int id_;
00680 
00684       const MatrixGraph& graph_;
00685       
00689       AggregatesMap<Vertex>& aggregates_;
00690 
00694       VertexSet& connected_;
00695     };
00696     
00700     template<class G>
00701     class Aggregator
00702     {
00703     public:
00704             
00708       typedef G MatrixGraph;
00709 
00713       typedef typename MatrixGraph::VertexDescriptor Vertex;
00714       
00716       typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor;
00717 
00721       Aggregator();
00722       
00726       ~Aggregator();
00727       
00740       template<class M, class C>
00741       Tuple<int,int,int> build(const M& m, G& graph, 
00742                                AggregatesMap<Vertex>& aggregates, const C& c);
00743     private:
00748       typedef PoolAllocator<Vertex,100*sizeof(int)> Allocator;
00749       
00753       typedef SLList<Vertex,Allocator> VertexList;
00754 
00758       typedef std::set<Vertex> VertexSet;
00759 
00763       typedef std::size_t* SphereMap;
00764       
00768       MatrixGraph* graph_;
00769       
00773       Aggregate<MatrixGraph>* aggregate_;
00774       
00778       VertexList front_;
00779 
00783       VertexSet connected_;
00784             
00788       int size_;
00789       
00793       class Stack
00794       {
00795       public:
00796         static const Vertex NullEntry;
00797         
00798         Stack(const MatrixGraph& graph, 
00799               const Aggregator<G>& aggregatesBuilder,
00800               const AggregatesMap<Vertex>& aggregates);
00801         ~Stack();
00802         bool push(const Vertex& v);
00803         void fill();
00804         Vertex pop();
00805       private:
00806         enum{ N = 256000 };
00807         
00809         const MatrixGraph& graph_;
00811         const Aggregator<G>& aggregatesBuilder_;
00813         const AggregatesMap<Vertex>& aggregates_;
00815         int size_;
00816         int maxSize_;
00818         int head_;
00819         int filled_;
00820         
00822         Vertex* vals_;
00823 
00824         void localPush(const Vertex& v);
00825       };
00826 
00827       friend class Stack;
00828       
00832       template<class C>
00833       void buildDependency(MatrixGraph& graph,
00834                            const typename C::Matrix& matrix,
00835                            C criterion);
00836 
00847       template<class V>
00848       void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,  
00849                                     const AggregatesMap<Vertex>& aggregates,
00850                                     V& visitor) const;
00851 
00856       template<class V>
00857       class AggregateVisitor
00858       {
00859       public:
00863         typedef V Visitor;
00871         AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
00872                          Visitor& visitor);
00873         
00880         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00881         
00882       private:
00884         const AggregatesMap<Vertex>& aggregates_;
00886         AggregateDescriptor aggregate_;
00888         Visitor* visitor_;
00889       };
00890 
00894       class Counter
00895       {
00896       public:
00898         Counter();
00900         int value();
00901         
00902       protected:
00904         void increment();
00906         void decrement();
00907         
00908       private:
00909         int count_;
00910       };
00911 
00912       
00917       class FrontNeighbourCounter : public Counter
00918       {
00919       public:
00924         FrontNeighbourCounter(const MatrixGraph& front);
00925         
00926         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00927         
00928       private:
00929         const MatrixGraph& graph_;
00930       };
00931       
00936       int noFrontNeighbours(const Vertex& vertex) const;
00937       
00941       class TwoWayCounter : public Counter
00942       {
00943       public:
00944         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00945       };
00946 
00958       int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,  
00959                              const AggregatesMap<Vertex>& aggregates) const;
00960 
00964       class OneWayCounter : public Counter
00965       {
00966       public:
00967         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00968       };        
00969 
00981       int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,  
00982                             const AggregatesMap<Vertex>& aggregates) const;
00983       
00990       class ConnectivityCounter : public Counter
00991       {
00992       public:
00999         ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
01000 
01001         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01002 
01003       private:
01005         const VertexSet& connected_;
01007         const AggregatesMap<Vertex>& aggregates_;
01008         
01009       };
01010 
01022       int connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01023       
01031       class DependencyCounter: public Counter
01032       {
01033       public:
01037         DependencyCounter();
01038         
01039         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01040       };
01041       
01048       class FrontMarker
01049       {
01050       public:
01057         FrontMarker(VertexList& front, MatrixGraph& graph);
01058         
01059         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01060         
01061       private:
01063         VertexList& front_;
01065         MatrixGraph& graph_;
01066       };
01067 
01074       void markFront(const AggregatesMap<Vertex>& aggregates);
01075       
01079       void unmarkFront();
01080       
01095       int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01096 
01110       std::pair<int,int> neighbours(const Vertex& vertex, 
01111                                     const AggregateDescriptor& aggregate,
01112                                     const AggregatesMap<Vertex>& aggregates) const;
01129       int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01130       
01138       bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01139       
01146       void seedFromFront(Stack& stack,  bool isolated);
01147         
01155       std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
01156 
01165       Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01166 
01174       template<class C>
01175       void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
01176     };
01177 
01178     template<class M, class N>
01179     inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
01180     {
01181       matrix_ = matrix;
01182     }
01183     
01184     template<class M, class N>
01185     inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
01186     {
01187       maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01188       row_ = index;
01189       diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01190     }
01191 
01192     template<class M, class N>
01193     inline void SymmetricDependency<M,N>::examine(const ColIter& col)
01194     {
01195       maxValue_ = std::max(maxValue_, 
01196                            (norm_(*col) * norm_(matrix_->operator[](col.index())[row_]))/
01197                            //(norm_(matrix_->operator[](col.index())[col.index()]) * diagonal_));
01198                            (diagonal_*diagonal_));
01199     }
01200     
01201     template<class M, class N>
01202     template<class G>
01203     inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01204     {      
01205       if(norm_(matrix_->operator[](edge.target())[edge.source()]) * norm_(*col)/
01206          //(norm_(matrix_->operator[](edge.target())[edge.target()]) * diagonal_) > alpha() * maxValue_){
01207          (diagonal_ * diagonal_) > alpha() * maxValue_){
01208         edge.properties().setDepends();
01209         edge.properties().setInfluences();
01210 
01211         typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
01212         other.setInfluences();
01213         other.setDepends();
01214       }
01215     }
01216     
01217     template<class M, class N>
01218     inline bool SymmetricDependency<M,N>::isIsolated()
01219     {
01220       return maxValue_  < beta();
01221     }
01222     
01223     
01224     template<class M, class N>
01225     inline void Dependency<M,N>::init(const Matrix* matrix)
01226     {
01227       matrix_ = matrix;
01228     }
01229     
01230     template<class M, class N>
01231     inline void Dependency<M,N>::initRow(const Row& row, int index)
01232     {
01233       maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01234       row_ = index;
01235       diagonal_ = matrix_->operator[](row_)[row_];
01236     }
01237 
01238     template<class M, class N>
01239     inline void Dependency<M,N>::examine(const ColIter& col)
01240     {
01241       maxValue_ = std::max(maxValue_, 
01242                            -*col);
01243     }
01244     
01245     template<class M, class N>
01246     template<class G>
01247     inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01248     {      
01249       if(-*col >= maxValue_ * alpha()){
01250         edge.properties().setDepends();
01251         edge.properties().setInfluences();
01252       }
01253     }
01254     
01255     template<class M, class N>
01256     inline bool Dependency<M,N>::isIsolated()
01257     {
01258       return maxValue_  < beta() * diagonal_;
01259     }
01260     
01261     template<class G>
01262     Aggregate<G>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
01263                             VertexSet& connected)
01264       : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
01265         connected_(connected)
01266     {}
01267     
01268     template<class G>
01269     void Aggregate<G>::reconstruct(const Vertex& vertex)
01270     {
01271       vertices_.push_back(vertex);
01272       typedef typename VertexList::const_iterator iterator;
01273       iterator begin = vertices_.begin();
01274       iterator end   = vertices_.end();
01275       throw "Not yet implemented";
01276 
01277       while(begin!=end){
01278         //for();
01279       }
01280       
01281     }
01282     
01283     template<class G>
01284     inline void Aggregate<G>::seed(const Vertex& vertex)
01285     {
01286       dvverb<<"Connected cleared"<<std::endl;
01287       connected_.clear();
01288       vertices_.clear();
01289       connected_.insert(vertex);
01290       dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
01291       id_ = vertex;
01292       add(vertex);
01293     }
01294     
01295 
01296     template<class G>
01297     inline void Aggregate<G>::add(const Vertex& vertex)
01298     {
01299       vertices_.push_back(vertex);
01300       aggregates_[vertex]=id_;
01301 
01302       typedef typename MatrixGraph::ConstEdgeIterator iterator;
01303       const iterator end = graph_.endEdges(vertex);
01304       for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){
01305         dvverb << " Inserting "<<aggregates_[edge.target()];
01306         connected_.insert(aggregates_[edge.target()]);
01307         dvverb <<" size="<<connected_.size();
01308       }
01309       dvverb <<std::endl;
01310     }
01311     template<class G>
01312     inline void Aggregate<G>::clear()
01313     {
01314       vertices_.clear();
01315       connected_.clear();
01316       id_=-1;
01317     }
01318     
01319     template<class G>
01320     inline typename Aggregate<G>::VertexList::size_type 
01321     Aggregate<G>::size()
01322     {
01323       return vertices_.size();
01324     }
01325     
01326     template<class G>
01327     inline int Aggregate<G>::id()
01328     {
01329       return id_;
01330     }
01331 
01332     template<class G>
01333     inline typename Aggregate<G>::const_iterator Aggregate<G>::begin() const
01334     {
01335       return vertices_.begin();
01336     }
01337     
01338     template<class G>
01339     inline typename Aggregate<G>::const_iterator Aggregate<G>::end() const
01340     {
01341       return vertices_.end();
01342     }
01343 
01344     template<class V> 
01345     const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
01346     
01347     template<class V> 
01348     const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
01349     
01350     template<class V>
01351     AggregatesMap<V>::AggregatesMap()
01352       : aggregates_(0)
01353     {}
01354 
01355     template<class V>
01356     AggregatesMap<V>::~AggregatesMap()
01357     {
01358       if(aggregates_!=0)
01359         delete[] aggregates_;
01360     }
01361     
01362 
01363     template<class V>
01364     inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
01365     {
01366       allocate(noVertices);
01367     }
01368 
01369     template<class V>
01370     inline std::size_t AggregatesMap<V>::AggregatesMap::noVertices() const
01371     {
01372       return noVertices_;
01373     }
01374     
01375     template<class V>
01376     inline void AggregatesMap<V>::allocate(std::size_t noVertices)
01377     {
01378       aggregates_ = new AggregateDescriptor[noVertices];
01379       noVertices_ = noVertices;
01380       
01381       for(std::size_t i=0; i < noVertices; i++)
01382         aggregates_[i]=UNAGGREGATED;
01383     }
01384 
01385     template<class V>
01386     inline void AggregatesMap<V>::free()
01387     {
01388       assert(aggregates_ != 0);
01389       delete[] aggregates_;
01390       aggregates_=0;
01391     }
01392     
01393     template<class V>
01394     inline typename AggregatesMap<V>::AggregateDescriptor& 
01395     AggregatesMap<V>::operator[](const VertexDescriptor& v)
01396     {
01397       return aggregates_[v];
01398     }
01399 
01400     template<class V>
01401     inline const typename AggregatesMap<V>::AggregateDescriptor& 
01402     AggregatesMap<V>::operator[](const VertexDescriptor& v) const
01403     {
01404       return aggregates_[v];
01405     }
01406 
01407     template<class V>
01408     template<bool reset, class G, class F,class VM>
01409     inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01410                                                     const AggregateDescriptor& aggregate, 
01411                                                     G& graph, F& aggregateVisitor,
01412                                                     VM& visitedMap) const
01413     {
01414       VertexList vlist;
01415       DummyEdgeVisitor dummy;
01416       return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
01417     }
01418       
01419     template<class V>
01420     template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
01421     std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01422                                              const AggregateDescriptor& aggregate, 
01423                                              G& graph,
01424                                              L& visited,
01425                                              F1& aggregateVisitor,
01426                                              F2& nonAggregateVisitor,
01427                                              VM& visitedMap) const
01428     {
01429       typedef typename L::const_iterator ListIterator;
01430       int visitedSpheres = 0;
01431       
01432       visited.push_back(start);
01433       put(visitedMap, start, true);
01434       
01435       ListIterator current = visited.begin();
01436       ListIterator end = visited.end();
01437       std::size_t i=0, size=visited.size();
01438       
01439       // visit the neighbours of all vertices of the
01440       // current sphere.
01441       while(current != end){
01442         
01443         for(;i<size; ++current, ++i){
01444           typedef typename G::ConstEdgeIterator EdgeIterator;
01445           const EdgeIterator endEdge = graph.endEdges(*current);
01446           
01447           for(EdgeIterator edge = graph.beginEdges(*current);
01448               edge != endEdge; ++edge){
01449           
01450             if(aggregates_[edge.target()]==aggregate){
01451               if(!get(visitedMap, edge.target())){
01452                 put(visitedMap, edge.target(), true);
01453                 visited.push_back(edge.target());
01454                 aggregateVisitor(edge);
01455               }
01456             }else
01457               nonAggregateVisitor(edge);
01458           }
01459         }       
01460         end = visited.end();
01461         size = visited.size();
01462         if(current != end)
01463           visitedSpheres++;
01464       }
01465       
01466       if(reset)
01467         for(current = visited.begin(); current != end; ++current)
01468           put(visitedMap, *current, false);
01469       
01470         
01471       if(remove)
01472         visited.clear();
01473       
01474       return visitedSpheres;
01475     }
01476     
01477     template<class G>
01478     Aggregator<G>::Aggregator()
01479       : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
01480     {}
01481     
01482     template<class G>
01483     Aggregator<G>::~Aggregator()
01484     {
01485       size_=-1;
01486     }
01487     
01488     template<class G>
01489     template<class C>
01490     void Aggregator<G>::buildDependency(MatrixGraph& graph,
01491                                         const typename C::Matrix& matrix,
01492                                         C criterion)
01493     {
01494       // The Criterion we use for building the dependency.
01495       typedef C Criterion;
01496      
01497       //      assert(graph.isBuilt());
01498       typedef typename C::Matrix Matrix;
01499       typedef typename MatrixGraph::VertexIterator VertexIterator;
01500       
01501       criterion.init(&matrix);
01502       
01503       for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){
01504         typedef typename Matrix::row_type Row;
01505         
01506         Row row = matrix[*vertex];
01507         
01508         // Tell the criterion what row we will examine now
01509         // This might for example be used for calculating the
01510         // maximum offdiagonal value
01511         criterion.initRow(row, *vertex);
01512         
01513         // On a first path all columns are examined. After this 
01514         // the calculator should know whether the vertex is isolated.
01515         typedef typename Matrix::ConstColIterator ColIterator;
01516         ColIterator end = row.end();
01517         for(ColIterator col = row.begin(); col != end; ++col)
01518           if(col.index()!=*vertex)
01519             criterion.examine(col);
01520         
01521         // reset the vertex properties
01522         vertex.properties().reset();
01523                 
01524         // Check whether the vertex is isolated.
01525         if(criterion.isIsolated()){
01526           vertex.properties().setIsolated();
01527         }else{
01528           // Examine all the edges beginning at this vertex.
01529           typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01530           typedef typename Matrix::ConstColIterator ColIterator;
01531           EdgeIterator end = vertex.end();
01532           ColIterator col = matrix[*vertex].begin();
01533           
01534           for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01535             // Move to the right column.
01536             while(col.index()!=edge.target())
01537               ++col;
01538             criterion.examine(graph, edge, col);
01539           }
01540         }
01541         
01542       }
01543     }
01544 
01545     
01546     template<class G>
01547     template<class V>
01548     inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates, 
01549                                                         const AggregateDescriptor& aggregate, V& visitor)
01550       : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01551     {}
01552     
01553     template<class G>
01554     template<class V>
01555     inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01556     {
01557       if(aggregates_[edge.target()]==aggregate_)
01558         visitor_->operator()(edge);
01559     }
01560     
01561     template<class G>
01562     template<class V>
01563     inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01564                                                         const AggregateDescriptor& aggregate, 
01565                                                         const AggregatesMap<Vertex>& aggregates,
01566                                                         V& visitor) const
01567     {  
01568       // Only evaluates for edge pointing to the aggregate
01569       AggregateVisitor<V> v(aggregates, aggregate, visitor);
01570       visitNeighbours(*graph_, vertex, v);
01571     }
01572     
01573     
01574     template<class G>
01575     inline Aggregator<G>::Counter::Counter()
01576       : count_(0)
01577     {}
01578     
01579     template<class G>
01580     inline void Aggregator<G>::Counter::increment()
01581     {
01582       ++count_;
01583     }
01584 
01585     template<class G>
01586     inline void Aggregator<G>::Counter::decrement()
01587     {
01588       --count_;
01589     }
01590     template<class G>
01591     inline int Aggregator<G>::Counter::value()
01592     {
01593       return count_;
01594     }
01595     
01596     template<class G>
01597     inline void  Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01598     {
01599       if(edge.properties().isTwoWay())
01600         Counter::increment();
01601     }
01602     
01603     template<class G>
01604     int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01605                                          const AggregatesMap<Vertex>& aggregates) const
01606     {
01607       TwoWayCounter counter;
01608       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01609       return counter.value();
01610     }
01611     
01612     template<class G>
01613     int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01614                                          const AggregatesMap<Vertex>& aggregates) const
01615     {
01616       OneWayCounter counter;
01617       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01618       return counter.value();
01619     }
01620     
01621     template<class G>
01622     inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01623     {
01624       if(edge.properties().isOneWay())
01625         Counter::increment();
01626     }
01627     
01628     template<class G>
01629     inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01630                                                                    const AggregatesMap<Vertex>& aggregates)
01631       : Counter(), connected_(connected), aggregates_(aggregates)
01632     {}
01633     
01634     
01635     template<class G>
01636     inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01637     {
01638       if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01639         // Would be a new connection
01640         Counter::increment();
01641       else{
01642         Counter::increment();
01643         Counter::increment();
01644       }
01645     }
01646     
01647     template<class G>
01648     inline int Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01649     {
01650       ConnectivityCounter counter(connected_, aggregates);
01651       visitNeighbours(*graph_, vertex, counter);
01652       return counter.value();
01653     }
01654     
01655     template<class G>
01656     inline Aggregator<G>::DependencyCounter::DependencyCounter()
01657       : Counter()
01658     {}
01659     
01660     template<class G>
01661     inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01662     {
01663       if(edge.properties().depends())
01664         Counter::increment();
01665       if(edge.properties().influences())
01666         Counter::increment();
01667     }
01668     
01669     template<class G>
01670     int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01671     {
01672       return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01673     }
01674     
01675     template<class G>
01676     std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01677                                                  const AggregateDescriptor& aggregate,
01678                                                  const AggregatesMap<Vertex>& aggregates) const
01679     {
01680       DependencyCounter unused, aggregated;
01681       typedef AggregateVisitor<DependencyCounter> Counter;
01682       CombinedFunctor<Counter,Counter> visitors(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated));
01683       return std::make_pair(unused.value(), aggregated.value());
01684 }
01685       
01686       
01687     template<class G>
01688     int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01689     {
01690       DependencyCounter counter;
01691       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01692       return counter.value();
01693     }
01694     
01695     template<class G>
01696     std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01697     {
01698       typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01699       VertexList vlist;
01700       typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01701       return aggregates.template breadthFirstSearch<true,true>(vertex, 
01702                                                       aggregate_->id(), *graph_, 
01703                                            vlist, dummy, dummy, visitedMap);
01704     }
01705     
01706     template<class G>
01707     inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01708       : front_(front), graph_(graph)
01709     {}
01710     
01711     template<class G>
01712     inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01713     {
01714       Vertex target = edge.target();
01715       
01716       if(!graph_.getVertexProperties(target).front()){
01717         front_.push_back(target);
01718         graph_.getVertexProperties(target).setFront();
01719       }
01720     }
01721         
01722 
01723     template<class G>
01724     void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01725     {
01726       assert(front_.size()==0);
01727       FrontMarker frontBuilder(front_, *graph_);
01728       typedef typename Aggregate<G>::const_iterator Iterator;
01729       
01730       for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01731         visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01732       
01733     }
01734 
01735     template<class G>
01736     inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01737     {
01738       // Todo
01739       Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01740       
01741       return true;
01742     }
01743     
01744     template<class G>
01745     void Aggregator<G>::unmarkFront()
01746     {      
01747       typedef typename VertexList::const_iterator Iterator;
01748       
01749       for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01750         graph_->getVertexProperties(*vertex).resetFront();      
01751       
01752       front_.clear();
01753     }
01754 
01755     template<class G>
01756     inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01757     {
01758       typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01759       
01760       Iterator end = graph_->endEdges(vertex);
01761       for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01762         if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01763            graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01764           if( graph_->getVertexProperties(vertex).isolated() || 
01765               ((edge.properties().depends() || edge.properties().influences())
01766                && admissible(vertex, aggregates[edge.target()], aggregates)))
01767             return edge.target();
01768         }
01769       }
01770       return AggregatesMap<Vertex>::UNAGGREGATED;
01771     }
01772     
01773     template<class G>
01774     Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01775       : Counter(), graph_(graph)
01776     {}
01777 
01778     template<class G>
01779     void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01780     {
01781       if(graph_.getVertexProperties(edge.target()).front())
01782         Counter::increment();
01783     }
01784     
01785     template<class G>
01786     int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01787     {
01788       FrontNeighbourCounter counter(*graph_);
01789       visitNeighbours(*graph_, vertex, counter);
01790       return counter.value();
01791     }
01792     
01793     template<class G>
01794     template<class C>
01795     void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01796     {
01797       while(aggregate_->size() < c.minAggregateSize()){
01798         int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1, maxCon=-std::numeric_limits<int>::max();
01799                 
01800         Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01801         
01802         unmarkFront();
01803         markFront(aggregates);
01804 
01805         typedef typename VertexList::const_iterator Iterator;
01806           
01807         for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01808           // Only nonisolated nodes are considered
01809           if(graph_->getVertexProperties(*vertex).isolated())
01810             continue;
01811           
01812           int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01813           
01814           /* The case of two way connections. */
01815           if( maxTwoCons == twoWayCons && twoWayCons > 0){
01816             int con = connectivity(*vertex, aggregates);
01817 
01818             if(con == maxCon){
01819               int neighbours = noFrontNeighbours(*vertex);
01820               
01821               if(neighbours > maxNeighbours){
01822                 maxNeighbours = neighbours;
01823                 
01824                 std::size_t distance_ = distance(*vertex, aggregates);
01825 
01826                 if(c.maxDistance() >= distance_){
01827                   candidate = *vertex;
01828                 }
01829               }
01830             }else if( con > maxCon){
01831               maxCon = con;
01832               maxNeighbours = noFrontNeighbours(*vertex);
01833               std::size_t distance_ = distance(*vertex, aggregates);
01834 
01835               if(c.maxDistance() >= distance_){
01836                 candidate = *vertex;
01837               }
01838             }
01839           }else if(twoWayCons > maxTwoCons){
01840             maxTwoCons = twoWayCons;
01841             maxCon = connectivity(*vertex, aggregates);
01842             maxNeighbours = noFrontNeighbours(*vertex);
01843             std::size_t distance_ = distance(*vertex, aggregates);
01844             
01845             if(c.maxDistance() >= distance_){
01846               candidate = *vertex;
01847             }
01848             
01849             // two way connections preceed
01850             maxOneCons = std::numeric_limits<int>::max();
01851           }
01852           
01853           if(twoWayCons > 0)
01854             continue; // THis is a two-way node, skip tests for one way nodes
01855 
01856           /* The one way case */
01857           int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01858           
01859           if(oneWayCons==0)
01860             continue; // No strong connections, skip the tests.
01861 
01862           if(!admissible(*vertex, aggregate_->id(), aggregates))
01863             continue;
01864           
01865           if( maxOneCons == oneWayCons && oneWayCons > 0){
01866             int con = connectivity(*vertex, aggregates);
01867 
01868             if(con == maxCon){
01869               int neighbours = noFrontNeighbours(*vertex);
01870               
01871               if(neighbours > maxNeighbours){
01872                 maxNeighbours = neighbours;
01873                 std::size_t distance_ = distance(*vertex, aggregates);
01874                 
01875                 if(c.maxDistance() >= distance_){
01876                   candidate = *vertex;
01877                 }
01878               }
01879             }else if( con > maxCon){
01880               maxCon = con;
01881               maxNeighbours = noFrontNeighbours(*vertex);
01882               std::size_t distance_ = distance(*vertex, aggregates);
01883               if(c.maxDistance() >= distance_){
01884                 candidate = *vertex;
01885               }
01886             }
01887           }else if(oneWayCons > maxOneCons){
01888             maxOneCons = oneWayCons;
01889             maxCon = connectivity(*vertex, aggregates);
01890             maxNeighbours = noFrontNeighbours(*vertex);
01891             std::size_t distance_ = distance(*vertex, aggregates);
01892                 
01893             if(c.maxDistance() >= distance_){
01894               candidate = *vertex;
01895             }
01896           }
01897         }
01898         
01899         
01900         if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01901           break; // No more candidates found
01902 
01903         aggregate_->add(candidate);
01904       }
01905     }
01906       
01907     template<typename V>
01908     template<typename M, typename G, typename C>
01909     Tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01910     {
01911       Aggregator<G> aggregator;
01912       return aggregator.build(matrix, graph, *this, criterion);
01913     }
01914     
01915     template<class G>
01916     template<class M, class C>
01917     Tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01918     {
01919       // Stack for fast vertex access
01920       Stack stack_(graph, *this, aggregates);
01921       
01922       graph_ = &graph;
01923             
01924       aggregate_ = new Aggregate<G>(graph, aggregates, connected_);
01925       
01926       // Allocate the mapping to aggregate.
01927       size_ = graph.maxVertex();
01928 
01929       Timer watch;
01930       watch.reset();
01931 
01932       buildDependency(graph, m, c);
01933 
01934       dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01935       int noAggregates, conAggregates, isoAggregates, oneAggregates;
01936       noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01937       
01938       while(true){
01939         Vertex seed = stack_.pop();
01940         
01941         if(seed == Stack::NullEntry)
01942           // No more unaggregated vertices. We are finished!
01943           break;
01944         
01945         // Debugging output
01946         if((noAggregates+1)%10000 == 0)
01947           Dune::dverb<<"c";
01948         
01949         aggregate_->seed(seed);
01950         
01951         
01952         if(graph.getVertexProperties(seed).isolated()){
01953           // isolated vertices are not aggregated but skipped on the coarser levels.
01954           aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01955           ++isoAggregates;
01956           // skip rest as no agglomeration is done.
01957           continue;
01958         }else
01959           growAggregate(seed, aggregates, c);
01960         
01961         
01962         /* The rounding step. */
01963         while(aggregate_->size() < c.maxAggregateSize()){
01964           
01965           unmarkFront();
01966           markFront(aggregates);
01967           
01968           Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01969           
01970           typedef typename VertexList::const_iterator Iterator;
01971           
01972           for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01973 
01974             if(graph.getVertexProperties(*vertex).isolated())
01975               continue; // No isolated nodes here
01976 
01977             if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 && 
01978                (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 || 
01979                 !admissible( *vertex, aggregate_->id(), aggregates) ))
01980               continue;
01981           
01982             std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
01983                                                      aggregates);
01984             
01985             //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
01986             // continue;
01987             
01988             if(neighbourPair.first >= neighbourPair.second)
01989               continue;
01990                     
01991             if(distance(*vertex, aggregates) > c.maxDistance())
01992               continue; // Distance too far
01993             candidate = *vertex;
01994             break;
01995           }
01996                   
01997           if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break; // no more candidates found.
01998           
01999           aggregate_->add(candidate);
02000           
02001         }
02002         
02003         // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
02004         if(aggregate_->size()==1)
02005           if(!graph.getVertexProperties(seed).isolated()){
02006             Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02007 
02008             if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02009               aggregates[seed] = aggregates[mergedNeighbour];
02010               /* // Reconstruct aggregate. Needed for markFront
02011               this->template breadthFirstSearch<
02012               visitAggregateNeighbours(seed, aggregates[seed], aggregates,)
02013               if(aggregate_->size()==2)
02014                 // Was a one node aggregate formerly
02015                 --oneAggregates;
02016               */
02017             }else{
02018               ++oneAggregates;
02019               ++conAggregates;
02020             }
02021             
02022           }else{
02023             ++oneAggregates;
02024             ++isoAggregates;
02025           }
02026         else{
02027           if(graph.getVertexProperties(seed).isolated())
02028             ++isoAggregates;
02029           else
02030             ++conAggregates;
02031         }
02032         unmarkFront();
02033         markFront(aggregates);
02034         seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02035         unmarkFront();
02036       }
02037       
02038       Dune::dinfo<<"connected aggregates: "<<conAggregates;
02039       Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02040       Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02041       
02042       delete aggregate_;
02043       return Tuple<int,int,int>(conAggregates,isoAggregates,oneAggregates);
02044     }
02045     
02046     template<class G>
02047     inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02048     {
02049       typedef typename VertexList::const_iterator Iterator;
02050       
02051       Iterator end= front_.end();
02052       int count=0;
02053       for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02054         stack_.push(*vertex);
02055       /*
02056       if(MINIMAL_DEBUG_LEVEL<=2 && count==0 && !isolated)
02057         Dune::dverb<< " no vertices pushed for nonisolated aggregate!"<<std::endl;
02058       */
02059     }
02060 
02061     template<class G>
02062     Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02063                                 const AggregatesMap<Vertex>& aggregates)
02064       : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02065     {
02066       vals_ = new  Vertex[N];
02067     }
02068     
02069     template<class G>
02070     Aggregator<G>::Stack::~Stack()
02071     {
02072       Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02073       delete[] vals_;
02074     }
02075     
02076     template<class G> 
02077     const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry 
02078     = std::numeric_limits<typename G::VertexDescriptor>::max();
02079 
02080     template<class G>
02081     inline bool Aggregator<G>::Stack::push(const Vertex& v)
02082     {
02083       if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02084         localPush(v);
02085         return true;
02086       }else
02087         return false;
02088     }
02089     
02090     template<class G>
02091     inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02092     {
02093       vals_[head_] = v;
02094       size_ = std::min<int>(size_+1, N);
02095       head_ = (head_+N+1)%N;
02096     }
02097     
02098     template<class G>
02099     void Aggregator<G>::Stack::fill()
02100     {
02101       int isolated = 0, connected=0;
02102       int isoumin, umin;
02103       filled_++;
02104       
02105       head_ = size_ = 0;
02106       isoumin = umin = std::numeric_limits<int>::max();
02107       
02108       typedef typename MatrixGraph::ConstVertexIterator Iterator;
02109       
02110       const Iterator end = graph_.end();
02111       
02112       for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02113         // Skip already aggregated vertices
02114         if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02115           continue;
02116         
02117         if(vertex.properties().isolated()){
02118           isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02119           isolated++;
02120         }else{
02121           umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02122           connected++;
02123         }
02124       }
02125       
02126       if(connected + isolated == 0)
02127         // No unaggregated vertices.
02128         return;
02129         
02130       if(connected > 0){
02131         // Connected vertices have higher priority.
02132          for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02133            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated() 
02134               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02135              localPush(*vertex);
02136       }else{
02137         for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02138            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated() 
02139               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02140              localPush(*vertex);
02141       }
02142       maxSize_ = std::max(size_, maxSize_);
02143     }
02144 
02145     template<class G>
02146     inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02147     {
02148       while(size_>0){
02149         head_ = (head_ + N -1) % N;
02150         size_--;
02151         Vertex v = vals_[head_];
02152         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02153           return v;
02154       }
02155       // Stack is empty try to fill it
02156       fill();
02157       
02158       // try again
02159       while(size_>0){
02160         head_ = (head_ + N -1) % N;
02161         size_--;
02162         Vertex v = vals_[head_];
02163         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02164           return v;
02165       }
02166       return NullEntry;
02167     }
02168 
02169     template<class V>
02170     void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m,  std::ostream& os)
02171     {
02172       std::ios_base::fmtflags oldOpts=os.flags();
02173       
02174       os.setf(std::ios_base::right, std::ios_base::adjustfield);
02175       
02176       V max=0;
02177       int width=1;
02178 
02179       for(int i=0; i< n*m; i++)
02180         max=std::max(max, aggregates[i]);
02181       
02182       for(int i=10; i < 1000000; i*=10)
02183         if(max/i>0)
02184           width++;
02185         else
02186           break;
02187       
02188       for(int j=0, entry=0; j < m; j++){
02189         for(int i=0; i<n; i++, entry++){
02190           os.width(width);
02191           os<<aggregates[entry]<<" ";
02192         }
02193         
02194         os<<std::endl;
02195       }
02196       os<<std::endl;
02197       os.flags(oldOpts);
02198     }
02199     
02200     
02201   }// namespace Amg
02202   
02203 }// namespace Dune
02204 
02205 
02206 #endif

Generated on 12 Dec 2007 with Doxygen (ver 1.5.1)