aggregates.hh

Go to the documentation of this file.
00001 // $Id: aggregates.hh 814 2007-09-21 18:17:51Z 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       double 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           //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
01527           vertex.properties().setIsolated();
01528         }else{
01529           // Examine all the edges beginning at this vertex.
01530           typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01531           typedef typename Matrix::ConstColIterator ColIterator;
01532           EdgeIterator end = vertex.end();
01533           ColIterator col = matrix[*vertex].begin();
01534           
01535           for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01536             // Move to the right column.
01537             while(col.index()!=edge.target())
01538               ++col;
01539             criterion.examine(graph, edge, col);
01540           }
01541         }
01542         
01543       }
01544     }
01545 
01546     
01547     template<class G>
01548     template<class V>
01549     inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates, 
01550                                                         const AggregateDescriptor& aggregate, V& visitor)
01551       : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01552     {}
01553     
01554     template<class G>
01555     template<class V>
01556     inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01557     {
01558       if(aggregates_[edge.target()]==aggregate_)
01559         visitor_->operator()(edge);
01560     }
01561     
01562     template<class G>
01563     template<class V>
01564     inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01565                                                         const AggregateDescriptor& aggregate, 
01566                                                         const AggregatesMap<Vertex>& aggregates,
01567                                                         V& visitor) const
01568     {  
01569       // Only evaluates for edge pointing to the aggregate
01570       AggregateVisitor<V> v(aggregates, aggregate, visitor);
01571       visitNeighbours(*graph_, vertex, v);
01572     }
01573     
01574     
01575     template<class G>
01576     inline Aggregator<G>::Counter::Counter()
01577       : count_(0)
01578     {}
01579     
01580     template<class G>
01581     inline void Aggregator<G>::Counter::increment()
01582     {
01583       ++count_;
01584     }
01585 
01586     template<class G>
01587     inline void Aggregator<G>::Counter::decrement()
01588     {
01589       --count_;
01590     }
01591     template<class G>
01592     inline int Aggregator<G>::Counter::value()
01593     {
01594       return count_;
01595     }
01596     
01597     template<class G>
01598     inline void  Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01599     {
01600       if(edge.properties().isTwoWay())
01601         Counter::increment();
01602     }
01603     
01604     template<class G>
01605     int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01606                                          const AggregatesMap<Vertex>& aggregates) const
01607     {
01608       TwoWayCounter counter;
01609       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01610       return counter.value();
01611     }
01612     
01613     template<class G>
01614     int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01615                                          const AggregatesMap<Vertex>& aggregates) const
01616     {
01617       OneWayCounter counter;
01618       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01619       return counter.value();
01620     }
01621     
01622     template<class G>
01623     inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01624     {
01625       if(edge.properties().isOneWay())
01626         Counter::increment();
01627     }
01628     
01629     template<class G>
01630     inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01631                                                                    const AggregatesMap<Vertex>& aggregates)
01632       : Counter(), connected_(connected), aggregates_(aggregates)
01633     {}
01634     
01635     
01636     template<class G>
01637     inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01638     {
01639       if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01640         // Would be a new connection
01641         Counter::increment();
01642       else{
01643         Counter::increment();
01644         Counter::increment();
01645       }
01646     }
01647     
01648     template<class G>
01649     inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01650     {
01651       ConnectivityCounter counter(connected_, aggregates);
01652       double noNeighbours=visitNeighbours(*graph_, vertex, counter);
01653       return (double)counter.value()/noNeighbours;
01654     }
01655     
01656     template<class G>
01657     inline Aggregator<G>::DependencyCounter::DependencyCounter()
01658       : Counter()
01659     {}
01660     
01661     template<class G>
01662     inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01663     {
01664       if(edge.properties().depends())
01665         Counter::increment();
01666       if(edge.properties().influences())
01667         Counter::increment();
01668     }
01669     
01670     template<class G>
01671     int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01672     {
01673       return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01674     }
01675     
01676     template<class G>
01677     std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01678                                                  const AggregateDescriptor& aggregate,
01679                                                  const AggregatesMap<Vertex>& aggregates) const
01680     {
01681       DependencyCounter unused, aggregated;
01682       typedef AggregateVisitor<DependencyCounter> Counter;
01683       typedef tuple<Counter,Counter> CounterTuple;
01684       CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
01685       return std::make_pair(unused.value(), aggregated.value());
01686 }
01687       
01688       
01689     template<class G>
01690     int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01691     {
01692       DependencyCounter counter;
01693       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01694       return counter.value();
01695     }
01696     
01697     template<class G>
01698     std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01699     {
01700       typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01701       VertexList vlist;
01702       typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01703       return aggregates.template breadthFirstSearch<true,true>(vertex, 
01704                                                       aggregate_->id(), *graph_, 
01705                                            vlist, dummy, dummy, visitedMap);
01706     }
01707     
01708     template<class G>
01709     inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01710       : front_(front), graph_(graph)
01711     {}
01712     
01713     template<class G>
01714     inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01715     {
01716       Vertex target = edge.target();
01717       
01718       if(!graph_.getVertexProperties(target).front()){
01719         front_.push_back(target);
01720         graph_.getVertexProperties(target).setFront();
01721       }
01722     }
01723         
01724 
01725     template<class G>
01726     void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01727     {
01728       assert(front_.size()==0);
01729       FrontMarker frontBuilder(front_, *graph_);
01730       typedef typename Aggregate<G>::const_iterator Iterator;
01731       
01732       for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01733         visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01734       
01735     }
01736 
01737     template<class G>
01738     inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01739     {
01740       // Todo
01741       Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01742       
01743       return true;
01744     }
01745     
01746     template<class G>
01747     void Aggregator<G>::unmarkFront()
01748     {      
01749       typedef typename VertexList::const_iterator Iterator;
01750       
01751       for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01752         graph_->getVertexProperties(*vertex).resetFront();      
01753       
01754       front_.clear();
01755     }
01756 
01757     template<class G>
01758     inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01759     {
01760       typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01761       
01762       Iterator end = graph_->endEdges(vertex);
01763       for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01764         if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01765            graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01766           if( graph_->getVertexProperties(vertex).isolated() || 
01767               ((edge.properties().depends() || edge.properties().influences())
01768                && admissible(vertex, aggregates[edge.target()], aggregates)))
01769             return edge.target();
01770         }
01771       }
01772       return AggregatesMap<Vertex>::UNAGGREGATED;
01773     }
01774     
01775     template<class G>
01776     Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01777       : Counter(), graph_(graph)
01778     {}
01779 
01780     template<class G>
01781     void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01782     {
01783       if(graph_.getVertexProperties(edge.target()).front())
01784         Counter::increment();
01785     }
01786     
01787     template<class G>
01788     int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01789     {
01790       FrontNeighbourCounter counter(*graph_);
01791       visitNeighbours(*graph_, vertex, counter);
01792       return counter.value();
01793     }
01794     
01795     template<class G>
01796     template<class C>
01797     void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01798     {
01799       while(aggregate_->size() < c.minAggregateSize()){
01800         int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
01801         double maxCon=-1;
01802                 
01803         Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01804         
01805         unmarkFront();
01806         markFront(aggregates);
01807 
01808         typedef typename VertexList::const_iterator Iterator;
01809           
01810         for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01811           // Only nonisolated nodes are considered
01812           if(graph_->getVertexProperties(*vertex).isolated())
01813             continue;
01814           
01815           int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01816           
01817           /* The case of two way connections. */
01818           if( maxTwoCons == twoWayCons && twoWayCons > 0){
01819             double con = connectivity(*vertex, aggregates);
01820 
01821             if(con == maxCon){
01822               int neighbours = noFrontNeighbours(*vertex);
01823               
01824               if(neighbours > maxNeighbours){
01825                 maxNeighbours = neighbours;
01826                 
01827                 std::size_t distance_ = distance(*vertex, aggregates);
01828 
01829                 if(c.maxDistance() >= distance_){
01830                   candidate = *vertex;
01831                 }
01832               }
01833             }else if( con > maxCon){
01834               maxCon = con;
01835               maxNeighbours = noFrontNeighbours(*vertex);
01836               std::size_t distance_ = distance(*vertex, aggregates);
01837 
01838               if(c.maxDistance() >= distance_){
01839                 candidate = *vertex;
01840               }
01841             }
01842           }else if(twoWayCons > maxTwoCons){
01843             maxTwoCons = twoWayCons;
01844             maxCon = connectivity(*vertex, aggregates);
01845             maxNeighbours = noFrontNeighbours(*vertex);
01846             std::size_t distance_ = distance(*vertex, aggregates);
01847             
01848             if(c.maxDistance() >= distance_){
01849               candidate = *vertex;
01850             }
01851             
01852             // two way connections preceed
01853             maxOneCons = std::numeric_limits<int>::max();
01854           }
01855           
01856           if(twoWayCons > 0)
01857             continue; // THis is a two-way node, skip tests for one way nodes
01858 
01859           /* The one way case */
01860           int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01861           
01862           if(oneWayCons==0)
01863             continue; // No strong connections, skip the tests.
01864 
01865           if(!admissible(*vertex, aggregate_->id(), aggregates))
01866             continue;
01867           
01868           if( maxOneCons == oneWayCons && oneWayCons > 0){
01869             double con = connectivity(*vertex, aggregates);
01870 
01871             if(con == maxCon){
01872               int neighbours = noFrontNeighbours(*vertex);
01873               
01874               if(neighbours > maxNeighbours){
01875                 maxNeighbours = neighbours;
01876                 std::size_t distance_ = distance(*vertex, aggregates);
01877                 
01878                 if(c.maxDistance() >= distance_){
01879                   candidate = *vertex;
01880                 }
01881               }
01882             }else if( con > maxCon){
01883               maxCon = con;
01884               maxNeighbours = noFrontNeighbours(*vertex);
01885               std::size_t distance_ = distance(*vertex, aggregates);
01886               if(c.maxDistance() >= distance_){
01887                 candidate = *vertex;
01888               }
01889             }
01890           }else if(oneWayCons > maxOneCons){
01891             maxOneCons = oneWayCons;
01892             maxCon = connectivity(*vertex, aggregates);
01893             maxNeighbours = noFrontNeighbours(*vertex);
01894             std::size_t distance_ = distance(*vertex, aggregates);
01895                 
01896             if(c.maxDistance() >= distance_){
01897               candidate = *vertex;
01898             }
01899           }
01900         }
01901         
01902         
01903         if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01904           break; // No more candidates found
01905 
01906         aggregate_->add(candidate);
01907       }
01908     }
01909       
01910     template<typename V>
01911     template<typename M, typename G, typename C>
01912     Tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01913     {
01914       Aggregator<G> aggregator;
01915       return aggregator.build(matrix, graph, *this, criterion);
01916     }
01917     
01918     template<class G>
01919     template<class M, class C>
01920     Tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01921     {
01922       // Stack for fast vertex access
01923       Stack stack_(graph, *this, aggregates);
01924       
01925       graph_ = &graph;
01926             
01927       aggregate_ = new Aggregate<G>(graph, aggregates, connected_);
01928       
01929       // Allocate the mapping to aggregate.
01930       size_ = graph.maxVertex();
01931 
01932       Timer watch;
01933       watch.reset();
01934 
01935       buildDependency(graph, m, c);
01936 
01937       dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01938       int noAggregates, conAggregates, isoAggregates, oneAggregates;
01939       noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01940       
01941       while(true){
01942         Vertex seed = stack_.pop();
01943         
01944         if(seed == Stack::NullEntry)
01945           // No more unaggregated vertices. We are finished!
01946           break;
01947         
01948         // Debugging output
01949         if((noAggregates+1)%10000 == 0)
01950           Dune::dverb<<"c";
01951         
01952         aggregate_->seed(seed);
01953         
01954         
01955         if(graph.getVertexProperties(seed).isolated()){
01956           // isolated vertices are not aggregated but skipped on the coarser levels.
01957           aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01958           ++isoAggregates;
01959           // skip rest as no agglomeration is done.
01960           continue;
01961         }else
01962           growAggregate(seed, aggregates, c);
01963         
01964         
01965         /* The rounding step. */
01966         while(aggregate_->size() < c.maxAggregateSize()){
01967           
01968           unmarkFront();
01969           markFront(aggregates);
01970           
01971           Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01972           
01973           typedef typename VertexList::const_iterator Iterator;
01974           
01975           for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01976 
01977             if(graph.getVertexProperties(*vertex).isolated())
01978               continue; // No isolated nodes here
01979 
01980             if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 && 
01981                (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 || 
01982                 !admissible( *vertex, aggregate_->id(), aggregates) ))
01983               continue;
01984           
01985             std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
01986                                                      aggregates);
01987             
01988             //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
01989             // continue;
01990             
01991             if(neighbourPair.first >= neighbourPair.second)
01992               continue;
01993                     
01994             if(distance(*vertex, aggregates) > c.maxDistance())
01995               continue; // Distance too far
01996             candidate = *vertex;
01997             break;
01998           }
01999                   
02000           if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break; // no more candidates found.
02001           
02002           aggregate_->add(candidate);
02003           
02004         }
02005         
02006         // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
02007         if(aggregate_->size()==1)
02008           if(!graph.getVertexProperties(seed).isolated()){
02009             Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02010 
02011             if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02012               aggregates[seed] = aggregates[mergedNeighbour];
02013               /* // Reconstruct aggregate. Needed for markFront
02014               this->template breadthFirstSearch<
02015               visitAggregateNeighbours(seed, aggregates[seed], aggregates,)
02016               if(aggregate_->size()==2)
02017                 // Was a one node aggregate formerly
02018                 --oneAggregates;
02019               */
02020             }else{
02021               ++oneAggregates;
02022               ++conAggregates;
02023             }
02024             
02025           }else{
02026             ++oneAggregates;
02027             ++isoAggregates;
02028           }
02029         else{
02030           if(graph.getVertexProperties(seed).isolated())
02031             ++isoAggregates;
02032           else
02033             ++conAggregates;
02034         }
02035         unmarkFront();
02036         markFront(aggregates);
02037         seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02038         unmarkFront();
02039       }
02040       
02041       Dune::dinfo<<"connected aggregates: "<<conAggregates;
02042       Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02043       Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02044       
02045       delete aggregate_;
02046       return Tuple<int,int,int>(conAggregates,isoAggregates,oneAggregates);
02047     }
02048     
02049     template<class G>
02050     inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02051     {
02052       typedef typename VertexList::const_iterator Iterator;
02053       
02054       Iterator end= front_.end();
02055       int count=0;
02056       for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02057         stack_.push(*vertex);
02058       /*
02059       if(MINIMAL_DEBUG_LEVEL<=2 && count==0 && !isolated)
02060         Dune::dverb<< " no vertices pushed for nonisolated aggregate!"<<std::endl;
02061       */
02062     }
02063 
02064     template<class G>
02065     Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02066                                 const AggregatesMap<Vertex>& aggregates)
02067       : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02068     {
02069       vals_ = new  Vertex[N];
02070     }
02071     
02072     template<class G>
02073     Aggregator<G>::Stack::~Stack()
02074     {
02075       Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02076       delete[] vals_;
02077     }
02078     
02079     template<class G> 
02080     const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry 
02081     = std::numeric_limits<typename G::VertexDescriptor>::max();
02082 
02083     template<class G>
02084     inline bool Aggregator<G>::Stack::push(const Vertex& v)
02085     {
02086       if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02087         localPush(v);
02088         return true;
02089       }else
02090         return false;
02091     }
02092     
02093     template<class G>
02094     inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02095     {
02096       vals_[head_] = v;
02097       size_ = std::min<int>(size_+1, N);
02098       head_ = (head_+N+1)%N;
02099     }
02100     
02101     template<class G>
02102     void Aggregator<G>::Stack::fill()
02103     {
02104       int isolated = 0, connected=0;
02105       int isoumin, umin;
02106       filled_++;
02107       
02108       head_ = size_ = 0;
02109       isoumin = umin = std::numeric_limits<int>::max();
02110       
02111       typedef typename MatrixGraph::ConstVertexIterator Iterator;
02112       
02113       const Iterator end = graph_.end();
02114       
02115       for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02116         // Skip already aggregated vertices
02117         if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02118           continue;
02119         
02120         if(vertex.properties().isolated()){
02121           isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02122           isolated++;
02123         }else{
02124           umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02125           connected++;
02126         }
02127       }
02128       
02129       if(connected + isolated == 0)
02130         // No unaggregated vertices.
02131         return;
02132         
02133       if(connected > 0){
02134         // Connected vertices have higher priority.
02135          for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02136            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated() 
02137               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02138              localPush(*vertex);
02139       }else{
02140         for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02141            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated() 
02142               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02143              localPush(*vertex);
02144       }
02145       maxSize_ = std::max(size_, maxSize_);
02146     }
02147 
02148     template<class G>
02149     inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02150     {
02151       while(size_>0){
02152         head_ = (head_ + N -1) % N;
02153         size_--;
02154         Vertex v = vals_[head_];
02155         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02156           return v;
02157       }
02158       // Stack is empty try to fill it
02159       fill();
02160       
02161       // try again
02162       while(size_>0){
02163         head_ = (head_ + N -1) % N;
02164         size_--;
02165         Vertex v = vals_[head_];
02166         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02167           return v;
02168       }
02169       return NullEntry;
02170     }
02171 
02172     template<class V>
02173     void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m,  std::ostream& os)
02174     {
02175       std::ios_base::fmtflags oldOpts=os.flags();
02176       
02177       os.setf(std::ios_base::right, std::ios_base::adjustfield);
02178       
02179       V max=0;
02180       int width=1;
02181 
02182       for(int i=0; i< n*m; i++)
02183         max=std::max(max, aggregates[i]);
02184       
02185       for(int i=10; i < 1000000; i*=10)
02186         if(max/i>0)
02187           width++;
02188         else
02189           break;
02190       
02191       for(int j=0, entry=0; j < m; j++){
02192         for(int i=0; i<n; i++, entry++){
02193           os.width(width);
02194           os<<aggregates[entry]<<" ";
02195         }
02196         
02197         os<<std::endl;
02198       }
02199       os<<std::endl;
02200       os.flags(oldOpts);
02201     }
02202     
02203     
02204   }// namespace Amg
02205   
02206 }// namespace Dune
02207 
02208 
02209 #endif

Generated on 9 Apr 2008 with Doxygen (ver 1.5.2) [logfile].