aggregates.hh

Go to the documentation of this file.
00001 // $Id: aggregates.hh 1051 2009-07-28 15:59:27Z mnolte $ 
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:
00318       enum{ /* @brief We preserve the sign.*/
00319         is_sign_preserving = true
00320       };
00321       
00326       template<class M>
00327       typename M::field_type operator()(const M& m) const
00328       {
00329         return m[0][0];
00330       }
00331     };
00332     
00338     struct RowSum
00339     {
00340       
00341       enum{ /* @brief We preserve the sign.*/
00342         is_sign_preserving = false
00343       };
00348       template<class M>
00349       typename M::field_type operator()(const M& m) const
00350       {
00351         return m.infinity_norm();
00352       }
00353     };
00354 
00364     template<class M, class Norm>
00365     class SymmetricCriterion : public AggregationCriterion<SymmetricDependency<M,Norm> >
00366     {};
00367 
00368     
00380     template<class M, class Norm>
00381     class UnSymmetricCriterion : public AggregationCriterion<Dependency<M,Norm> >
00382     {};
00383     // forward declaration
00384     template<class G> class Aggregator;
00385 
00386     
00394     template<class V>
00395     class AggregatesMap
00396     {
00397     public:
00398 
00402       static const V UNAGGREGATED;
00403       
00407       static const V ISOLATED;
00411       typedef V VertexDescriptor;
00412       
00416       typedef V AggregateDescriptor;
00417 
00422       typedef PoolAllocator<VertexDescriptor,100> Allocator;
00423       
00428       typedef SLList<VertexDescriptor,Allocator> VertexList;
00429 
00433       class DummyEdgeVisitor
00434       {
00435       public:
00436         template<class EdgeIterator>
00437         void operator()(const EdgeIterator& egde) const
00438         {}
00439       };
00440       
00441         
00445       AggregatesMap();
00446       
00452       AggregatesMap(std::size_t noVertices);
00453 
00457       ~AggregatesMap();
00458 
00466       template<class M, class G, class C>
00467       tuple<int,int,int> buildAggregates(const M& matrix, G& graph, const C& criterion);
00468       
00488       template<bool reset, class G, class F, class VM>
00489       std::size_t breadthFirstSearch(const VertexDescriptor& start,
00490                              const AggregateDescriptor& aggregate, 
00491                              const G& graph,
00492                              F& aggregateVisitor,
00493                                      VM& visitedMap) const;
00494       
00518       template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
00519       std::size_t breadthFirstSearch(const VertexDescriptor& start, 
00520                              const AggregateDescriptor& aggregate, 
00521                              const G& graph, L& visited, F1& aggregateVisitor,
00522                              F2& nonAggregateVisitor,
00523                              VM& visitedMap) const;
00524 
00530       void allocate(std::size_t noVertices);
00531       
00535       std::size_t noVertices() const;
00536       
00540       void free();
00541             
00547       AggregateDescriptor& operator[](const VertexDescriptor& v);
00548       
00554       const AggregateDescriptor& operator[](const VertexDescriptor& v) const;
00555 
00556       typedef const AggregateDescriptor* const_iterator;
00557       
00558       const_iterator begin() const
00559       {
00560         return aggregates_;
00561       }
00562       
00563       const_iterator end() const
00564       {
00565         return aggregates_+noVertices();
00566       }
00567       
00568       typedef AggregateDescriptor* iterator;
00569       
00570       iterator begin()
00571       {
00572         return aggregates_;
00573       }
00574       
00575       iterator end()
00576       {
00577         return aggregates_+noVertices();
00578       }
00579     private:
00581       AggregatesMap(const AggregatesMap<V>& map)
00582       {
00583         throw "Auch!";
00584       }
00585       
00587       AggregatesMap<V>& operator=(const AggregatesMap<V>& map)
00588       {
00589         throw "Auch!";
00590         return this;
00591       }
00592       
00596       AggregateDescriptor* aggregates_;
00597 
00601       std::size_t noVertices_;
00602     };
00603     
00604     
00609     template<class G, class S>
00610     class Aggregate
00611     {
00612       
00613     public:
00614             
00615       /***
00616        * @brief The type of the matrix graph we work with.
00617        */
00618       typedef G MatrixGraph;
00622       typedef typename MatrixGraph::VertexDescriptor Vertex;
00623 
00628       typedef PoolAllocator<Vertex,100> Allocator;
00629       
00634       typedef SLList<Vertex,Allocator> VertexList;
00635 
00636       
00641       typedef S VertexSet;
00642 
00644       typedef typename VertexList::const_iterator const_iterator;
00645 
00649       typedef std::size_t* SphereMap;
00650       
00658       Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates, 
00659                 VertexSet& connectivity);
00660             
00667       void reconstruct(const Vertex& vertex);
00668       
00672       void seed(const Vertex& vertex);
00673       
00677       void add(const Vertex& vertex);
00678       
00682       void clear();
00683       
00687       typename VertexList::size_type size();
00688       
00692       int id();
00693       
00695       const_iterator begin() const;
00696       
00698       const_iterator end() const;
00699       
00700     private:
00704       VertexList vertices_;
00705       
00710       int id_;
00711 
00715       const MatrixGraph& graph_;
00716       
00720       AggregatesMap<Vertex>& aggregates_;
00721 
00725       VertexSet& connected_;
00726     };
00727     
00731     template<class G>
00732     class Aggregator
00733     {
00734     public:
00735             
00739       typedef G MatrixGraph;
00740 
00744       typedef typename MatrixGraph::VertexDescriptor Vertex;
00745       
00747       typedef typename MatrixGraph::VertexDescriptor AggregateDescriptor;
00748 
00752       Aggregator();
00753       
00757       ~Aggregator();
00758       
00771       template<class M, class C>
00772       tuple<int,int,int> build(const M& m, G& graph, 
00773                                AggregatesMap<Vertex>& aggregates, const C& c);
00774     private:
00779       typedef PoolAllocator<Vertex,1> Allocator;
00780       
00784       typedef SLList<Vertex,Allocator> VertexList;
00785 
00789       typedef std::set<Vertex,std::less<Vertex>,Allocator> VertexSet;
00790 
00794       typedef std::size_t* SphereMap;
00795       
00799       MatrixGraph* graph_;
00800       
00804       Aggregate<MatrixGraph,VertexSet>* aggregate_;
00805       
00809       VertexList front_;
00810 
00814       VertexSet connected_;
00815             
00819       int size_;
00820       
00824       class Stack
00825       {
00826       public:
00827         static const Vertex NullEntry;
00828         
00829         Stack(const MatrixGraph& graph, 
00830               const Aggregator<G>& aggregatesBuilder,
00831               const AggregatesMap<Vertex>& aggregates);
00832         ~Stack();
00833         bool push(const Vertex& v);
00834         void fill();
00835         Vertex pop();
00836       private:
00837         enum{ N = 256000 };
00838         
00840         const MatrixGraph& graph_;
00842         const Aggregator<G>& aggregatesBuilder_;
00844         const AggregatesMap<Vertex>& aggregates_;
00846         int size_;
00847         int maxSize_;
00849         int head_;
00850         int filled_;
00851         
00853         Vertex* vals_;
00854 
00855         void localPush(const Vertex& v);
00856       };
00857 
00858       friend class Stack;
00859       
00863       template<class C>
00864       void buildDependency(MatrixGraph& graph,
00865                            const typename C::Matrix& matrix,
00866                            C criterion);
00867 
00878       template<class V>
00879       void visitAggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate,  
00880                                     const AggregatesMap<Vertex>& aggregates,
00881                                     V& visitor) const;
00882 
00887       template<class V>
00888       class AggregateVisitor
00889       {
00890       public:
00894         typedef V Visitor;
00902         AggregateVisitor(const AggregatesMap<Vertex>& aggregates, const AggregateDescriptor& aggregate,
00903                          Visitor& visitor);
00904         
00911         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00912         
00913       private:
00915         const AggregatesMap<Vertex>& aggregates_;
00917         AggregateDescriptor aggregate_;
00919         Visitor* visitor_;
00920       };
00921 
00925       class Counter
00926       {
00927       public:
00929         Counter();
00931         int value();
00932         
00933       protected:
00935         void increment();
00937         void decrement();
00938         
00939       private:
00940         int count_;
00941       };
00942 
00943       
00948       class FrontNeighbourCounter : public Counter
00949       {
00950       public:
00955         FrontNeighbourCounter(const MatrixGraph& front);
00956         
00957         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00958         
00959       private:
00960         const MatrixGraph& graph_;
00961       };
00962       
00967       int noFrontNeighbours(const Vertex& vertex) const;
00968       
00972       class TwoWayCounter : public Counter
00973       {
00974       public:
00975         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00976       };
00977 
00989       int twoWayConnections(const Vertex&, const AggregateDescriptor& aggregate,  
00990                              const AggregatesMap<Vertex>& aggregates) const;
00991 
00995       class OneWayCounter : public Counter
00996       {
00997       public:
00998         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
00999       };        
01000 
01012       int oneWayConnections(const Vertex&, const AggregateDescriptor& aggregate,  
01013                             const AggregatesMap<Vertex>& aggregates) const;
01014       
01021       class ConnectivityCounter : public Counter
01022       {
01023       public:
01030         ConnectivityCounter(const VertexSet& connected, const AggregatesMap<Vertex>& aggregates);
01031 
01032         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01033 
01034       private:
01036         const VertexSet& connected_;
01038         const AggregatesMap<Vertex>& aggregates_;
01039         
01040       };
01041 
01053       double connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01054       
01062       class DependencyCounter: public Counter
01063       {
01064       public:
01068         DependencyCounter();
01069         
01070         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01071       };
01072       
01079       class FrontMarker
01080       {
01081       public:
01088         FrontMarker(VertexList& front, MatrixGraph& graph);
01089         
01090         void operator()(const typename MatrixGraph::ConstEdgeIterator& edge);
01091         
01092       private:
01094         VertexList& front_;
01096         MatrixGraph& graph_;
01097       };
01098 
01105       void markFront(const AggregatesMap<Vertex>& aggregates);
01106       
01110       void unmarkFront();
01111       
01126       int unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01127 
01141       std::pair<int,int> neighbours(const Vertex& vertex, 
01142                                     const AggregateDescriptor& aggregate,
01143                                     const AggregatesMap<Vertex>& aggregates) const;
01160       int aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01161       
01169       bool admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const;
01170       
01177       void seedFromFront(Stack& stack,  bool isolated);
01178         
01186       std::size_t distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates);
01187 
01196       Vertex mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const;
01197 
01205       template<class C>
01206       void growAggregate(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates, const C& c);
01207     };
01208 
01209     template<class M, class N>
01210     inline void SymmetricDependency<M,N>::init(const Matrix* matrix)
01211     {
01212       matrix_ = matrix;
01213     }
01214     
01215     template<class M, class N>
01216     inline void SymmetricDependency<M,N>::initRow(const Row& row, int index)
01217     {
01218       maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01219       row_ = index;
01220       diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01221     }
01222 
01223     template<class M, class N>
01224     inline void SymmetricDependency<M,N>::examine(const ColIter& col)
01225     {
01226       typename Matrix::field_type eij = norm_(*col);
01227       typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]);
01228       
01229       // skip positve offdiagonals if norm preserves sign of them.
01230       if(!N::is_sign_preserving || eij<0 || eji<0)
01231         maxValue_ = std::max(maxValue_, 
01232                              eij /diagonal_ * eji/
01233                              norm_(matrix_->operator[](col.index())[col.index()]));
01234     }
01235     
01236     template<class M, class N>
01237     template<class G>
01238     inline void SymmetricDependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01239     {      
01240       typename Matrix::field_type eij = norm_(*col);
01241       typename Matrix::field_type eji = norm_(matrix_->operator[](col.index())[row_]);
01242       
01243       // skip positve offdiagonals if norm preserves sign of them.
01244       if(!N::is_sign_preserving || (eij<0 || eji<0))
01245         if(eji / norm_(matrix_->operator[](edge.target())[edge.target()]) * 
01246            eij/ diagonal_ > alpha() * maxValue_){
01247         edge.properties().setDepends();
01248         edge.properties().setInfluences();
01249 
01250         typename G::EdgeProperties& other = graph.getEdgeProperties(edge.target(), edge.source());
01251         other.setInfluences();
01252         other.setDepends();
01253       }
01254     }
01255     
01256     template<class M, class N>
01257     inline bool SymmetricDependency<M,N>::isIsolated()
01258     {
01259       return maxValue_  < beta();
01260     }
01261     
01262     
01263     template<class M, class N>
01264     inline void Dependency<M,N>::init(const Matrix* matrix)
01265     {
01266       matrix_ = matrix;
01267     }
01268     
01269     template<class M, class N>
01270     inline void Dependency<M,N>::initRow(const Row& row, int index)
01271     {
01272       maxValue_ = std::min(- std::numeric_limits<typename Matrix::field_type>::max(), std::numeric_limits<typename Matrix::field_type>::min());
01273       row_ = index;
01274       diagonal_ = norm_(matrix_->operator[](row_)[row_]);
01275     }
01276 
01277     template<class M, class N>
01278     inline void Dependency<M,N>::examine(const ColIter& col)
01279     {
01280       maxValue_ = std::max(maxValue_, 
01281                            -norm_(*col));
01282     }
01283     
01284     template<class M, class N>
01285     template<class G>
01286     inline void Dependency<M,N>::examine(G& graph, const typename G::EdgeIterator& edge, const ColIter& col)
01287     {      
01288       if(-norm_(*col) >= maxValue_ * alpha()){
01289         edge.properties().setDepends();
01290         edge.properties().setInfluences();
01291       }
01292     }
01293     
01294     template<class M, class N>
01295     inline bool Dependency<M,N>::isIsolated()
01296     {
01297       return maxValue_  < beta() * diagonal_;
01298     }
01299     
01300     template<class G,class S>
01301     Aggregate<G,S>::Aggregate(const MatrixGraph& graph, AggregatesMap<Vertex>& aggregates,
01302                             VertexSet& connected)
01303       : vertices_(), id_(-1), graph_(graph), aggregates_(aggregates),
01304         connected_(connected)
01305     {}
01306     
01307     template<class G,class S>
01308     void Aggregate<G,S>::reconstruct(const Vertex& vertex)
01309     {
01310       vertices_.push_back(vertex);
01311       typedef typename VertexList::const_iterator iterator;
01312       iterator begin = vertices_.begin();
01313       iterator end   = vertices_.end();
01314       throw "Not yet implemented";
01315 
01316       while(begin!=end){
01317         //for();
01318       }
01319       
01320     }
01321     
01322     template<class G,class S>
01323     inline void Aggregate<G,S>::seed(const Vertex& vertex)
01324     {
01325       dvverb<<"Connected cleared"<<std::endl;
01326       connected_.clear();
01327       vertices_.clear();
01328       connected_.insert(vertex);
01329       dvverb << " Inserting "<<vertex<<" size="<<connected_.size();
01330       id_ = vertex;
01331       add(vertex);
01332     }
01333     
01334 
01335     template<class G,class S>
01336     inline void Aggregate<G,S>::add(const Vertex& vertex)
01337     {
01338       vertices_.push_back(vertex);
01339       aggregates_[vertex]=id_;
01340 
01341       typedef typename MatrixGraph::ConstEdgeIterator iterator;
01342       const iterator end = graph_.endEdges(vertex);
01343       for(iterator edge = graph_.beginEdges(vertex); edge != end; ++edge){
01344         dvverb << " Inserting "<<aggregates_[edge.target()];
01345         connected_.insert(aggregates_[edge.target()]);
01346         dvverb <<" size="<<connected_.size();
01347       }
01348       dvverb <<std::endl;
01349     }
01350     template<class G,class S>
01351     inline void Aggregate<G,S>::clear()
01352     {
01353       vertices_.clear();
01354       connected_.clear();
01355       id_=-1;
01356     }
01357     
01358     template<class G,class S>
01359     inline typename Aggregate<G,S>::VertexList::size_type 
01360     Aggregate<G,S>::size()
01361     {
01362       return vertices_.size();
01363     }
01364     
01365     template<class G,class S>
01366     inline int Aggregate<G,S>::id()
01367     {
01368       return id_;
01369     }
01370 
01371     template<class G,class S>
01372     inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::begin() const
01373     {
01374       return vertices_.begin();
01375     }
01376     
01377     template<class G,class S>
01378     inline typename Aggregate<G,S>::const_iterator Aggregate<G,S>::end() const
01379     {
01380       return vertices_.end();
01381     }
01382 
01383     template<class V> 
01384     const V AggregatesMap<V>::UNAGGREGATED = std::numeric_limits<V>::max();
01385     
01386     template<class V> 
01387     const V AggregatesMap<V>::ISOLATED = std::numeric_limits<V>::max()-1;
01388     
01389     template<class V>
01390     AggregatesMap<V>::AggregatesMap()
01391       : aggregates_(0)
01392     {}
01393 
01394     template<class V>
01395     AggregatesMap<V>::~AggregatesMap()
01396     {
01397       if(aggregates_!=0)
01398         delete[] aggregates_;
01399     }
01400     
01401 
01402     template<class V>
01403     inline AggregatesMap<V>::AggregatesMap(std::size_t noVertices)
01404     {
01405       allocate(noVertices);
01406     }
01407 
01408     template<class V>
01409     inline std::size_t AggregatesMap<V>::AggregatesMap::noVertices() const
01410     {
01411       return noVertices_;
01412     }
01413     
01414     template<class V>
01415     inline void AggregatesMap<V>::allocate(std::size_t noVertices)
01416     {
01417       aggregates_ = new AggregateDescriptor[noVertices];
01418       noVertices_ = noVertices;
01419       
01420       for(std::size_t i=0; i < noVertices; i++)
01421         aggregates_[i]=UNAGGREGATED;
01422     }
01423 
01424     template<class V>
01425     inline void AggregatesMap<V>::free()
01426     {
01427       assert(aggregates_ != 0);
01428       delete[] aggregates_;
01429       aggregates_=0;
01430     }
01431     
01432     template<class V>
01433     inline typename AggregatesMap<V>::AggregateDescriptor& 
01434     AggregatesMap<V>::operator[](const VertexDescriptor& v)
01435     {
01436       return aggregates_[v];
01437     }
01438 
01439     template<class V>
01440     inline const typename AggregatesMap<V>::AggregateDescriptor& 
01441     AggregatesMap<V>::operator[](const VertexDescriptor& v) const
01442     {
01443       return aggregates_[v];
01444     }
01445 
01446     template<class V>
01447     template<bool reset, class G, class F,class VM>
01448     inline std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01449                                                     const AggregateDescriptor& aggregate, 
01450                                                     const G& graph, F& aggregateVisitor,
01451                                                             VM& visitedMap) const
01452     {
01453       VertexList vlist;
01454       
01455       DummyEdgeVisitor dummy;
01456       return breadthFirstSearch<true,reset>(start, aggregate, graph, vlist, aggregateVisitor, dummy, visitedMap);
01457     }
01458       
01459     template<class V>
01460     template<bool remove, bool reset, class G, class L, class F1, class F2, class VM>
01461     std::size_t AggregatesMap<V>::breadthFirstSearch(const V& start,
01462                                              const AggregateDescriptor& aggregate, 
01463                                              const G& graph,
01464                                              L& visited,
01465                                              F1& aggregateVisitor,
01466                                              F2& nonAggregateVisitor,
01467                                              VM& visitedMap) const
01468     {
01469       typedef typename L::const_iterator ListIterator;
01470       int visitedSpheres = 0;
01471       
01472       visited.push_back(start);
01473       put(visitedMap, start, true);
01474       
01475       ListIterator current = visited.begin();
01476       ListIterator end = visited.end();
01477       std::size_t i=0, size=visited.size();
01478       
01479       // visit the neighbours of all vertices of the
01480       // current sphere.
01481       while(current != end){
01482         
01483         for(;i<size; ++current, ++i){
01484           typedef typename G::ConstEdgeIterator EdgeIterator;
01485           const EdgeIterator endEdge = graph.endEdges(*current);
01486           
01487           for(EdgeIterator edge = graph.beginEdges(*current);
01488               edge != endEdge; ++edge){
01489           
01490             if(aggregates_[edge.target()]==aggregate){
01491               if(!get(visitedMap, edge.target())){
01492                 put(visitedMap, edge.target(), true);
01493                 visited.push_back(edge.target());
01494                 aggregateVisitor(edge);
01495               }
01496             }else
01497               nonAggregateVisitor(edge);
01498           }
01499         }       
01500         end = visited.end();
01501         size = visited.size();
01502         if(current != end)
01503           visitedSpheres++;
01504       }
01505       
01506       if(reset)
01507         for(current = visited.begin(); current != end; ++current)
01508           put(visitedMap, *current, false);
01509       
01510         
01511       if(remove)
01512         visited.clear();
01513       
01514       return visitedSpheres;
01515     }
01516     
01517     template<class G>
01518     Aggregator<G>::Aggregator()
01519       : graph_(0), aggregate_(0), front_(), connected_(), size_(-1)
01520     {}
01521     
01522     template<class G>
01523     Aggregator<G>::~Aggregator()
01524     {
01525       size_=-1;
01526     }
01527     
01528     template<class G>
01529     template<class C>
01530     void Aggregator<G>::buildDependency(MatrixGraph& graph,
01531                                         const typename C::Matrix& matrix,
01532                                         C criterion)
01533     {
01534       // The Criterion we use for building the dependency.
01535       typedef C Criterion;
01536      
01537       //      assert(graph.isBuilt());
01538       typedef typename C::Matrix Matrix;
01539       typedef typename MatrixGraph::VertexIterator VertexIterator;
01540       
01541       criterion.init(&matrix);
01542       
01543       for(VertexIterator vertex = graph.begin(); vertex != graph.end(); ++vertex){
01544         typedef typename Matrix::row_type Row;
01545         
01546         const Row& row = matrix[*vertex];
01547         
01548         // Tell the criterion what row we will examine now
01549         // This might for example be used for calculating the
01550         // maximum offdiagonal value
01551         criterion.initRow(row, *vertex);
01552         
01553         // On a first path all columns are examined. After this 
01554         // the calculator should know whether the vertex is isolated.
01555         typedef typename Matrix::ConstColIterator ColIterator;
01556         ColIterator end = row.end();
01557         for(ColIterator col = row.begin(); col != end; ++col)
01558           if(col.index()!=*vertex)
01559             criterion.examine(col);
01560         
01561         // reset the vertex properties
01562         //vertex.properties().reset();
01563                 
01564         // Check whether the vertex is isolated.
01565         if(criterion.isIsolated()){
01566           //std::cout<<"ISOLATED: "<<*vertex<<std::endl;
01567           vertex.properties().setIsolated();
01568         }else{
01569           // Examine all the edges beginning at this vertex.
01570           typedef typename MatrixGraph::EdgeIterator EdgeIterator;
01571           typedef typename Matrix::ConstColIterator ColIterator;
01572           EdgeIterator end = vertex.end();
01573           ColIterator col = matrix[*vertex].begin();
01574           
01575           for(EdgeIterator edge = vertex.begin(); edge!= end; ++edge, ++col){
01576             // Move to the right column.
01577             while(col.index()!=edge.target())
01578               ++col;
01579             criterion.examine(graph, edge, col);
01580           }
01581         }
01582         
01583       }
01584     }
01585 
01586     
01587     template<class G>
01588     template<class V>
01589     inline Aggregator<G>::AggregateVisitor<V>::AggregateVisitor(const AggregatesMap<Vertex>& aggregates, 
01590                                                         const AggregateDescriptor& aggregate, V& visitor)
01591       : aggregates_(aggregates), aggregate_(aggregate), visitor_(&visitor)
01592     {}
01593     
01594     template<class G>
01595     template<class V>
01596     inline void Aggregator<G>::AggregateVisitor<V>::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01597     {
01598       if(aggregates_[edge.target()]==aggregate_)
01599         visitor_->operator()(edge);
01600     }
01601     
01602     template<class G>
01603     template<class V>
01604     inline void Aggregator<G>::visitAggregateNeighbours(const Vertex& vertex,
01605                                                         const AggregateDescriptor& aggregate, 
01606                                                         const AggregatesMap<Vertex>& aggregates,
01607                                                         V& visitor) const
01608     {  
01609       // Only evaluates for edge pointing to the aggregate
01610       AggregateVisitor<V> v(aggregates, aggregate, visitor);
01611       visitNeighbours(*graph_, vertex, v);
01612     }
01613     
01614     
01615     template<class G>
01616     inline Aggregator<G>::Counter::Counter()
01617       : count_(0)
01618     {}
01619     
01620     template<class G>
01621     inline void Aggregator<G>::Counter::increment()
01622     {
01623       ++count_;
01624     }
01625 
01626     template<class G>
01627     inline void Aggregator<G>::Counter::decrement()
01628     {
01629       --count_;
01630     }
01631     template<class G>
01632     inline int Aggregator<G>::Counter::value()
01633     {
01634       return count_;
01635     }
01636     
01637     template<class G>
01638     inline void  Aggregator<G>::TwoWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01639     {
01640       if(edge.properties().isTwoWay())
01641         Counter::increment();
01642     }
01643     
01644     template<class G>
01645     int Aggregator<G>::twoWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01646                                          const AggregatesMap<Vertex>& aggregates) const
01647     {
01648       TwoWayCounter counter;
01649       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01650       return counter.value();
01651     }
01652     
01653     template<class G>
01654     int Aggregator<G>::oneWayConnections(const Vertex& vertex, const AggregateDescriptor& aggregate,
01655                                          const AggregatesMap<Vertex>& aggregates) const
01656     {
01657       OneWayCounter counter;
01658       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01659       return counter.value();
01660     }
01661     
01662     template<class G>
01663     inline void Aggregator<G>::OneWayCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01664     {
01665       if(edge.properties().isOneWay())
01666         Counter::increment();
01667     }
01668     
01669     template<class G>
01670     inline Aggregator<G>::ConnectivityCounter::ConnectivityCounter(const VertexSet& connected,
01671                                                                    const AggregatesMap<Vertex>& aggregates)
01672       : Counter(), connected_(connected), aggregates_(aggregates)
01673     {}
01674     
01675     
01676     template<class G>
01677     inline void Aggregator<G>::ConnectivityCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01678     {
01679       if(connected_.find(aggregates_[edge.target()]) == connected_.end() || aggregates_[edge.target()]==AggregatesMap<Vertex>::UNAGGREGATED)
01680         // Would be a new connection
01681         Counter::increment();
01682       else{
01683         Counter::increment();
01684         Counter::increment();
01685       }
01686     }
01687     
01688     template<class G>
01689     inline double Aggregator<G>::connectivity(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01690     {
01691       ConnectivityCounter counter(connected_, aggregates);
01692       double noNeighbours=visitNeighbours(*graph_, vertex, counter);
01693       return (double)counter.value()/noNeighbours;
01694     }
01695     
01696     template<class G>
01697     inline Aggregator<G>::DependencyCounter::DependencyCounter()
01698       : Counter()
01699     {}
01700     
01701     template<class G>
01702     inline void Aggregator<G>::DependencyCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01703     {
01704       if(edge.properties().depends())
01705         Counter::increment();
01706       if(edge.properties().influences())
01707         Counter::increment();
01708     }
01709     
01710     template<class G>
01711     int Aggregator<G>::unusedNeighbours(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01712     {
01713       return aggregateNeighbours(vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates);
01714     }
01715     
01716     template<class G>
01717     std::pair<int,int> Aggregator<G>::neighbours(const Vertex& vertex,
01718                                                  const AggregateDescriptor& aggregate,
01719                                                  const AggregatesMap<Vertex>& aggregates) const
01720     {
01721       DependencyCounter unused, aggregated;
01722       typedef AggregateVisitor<DependencyCounter> Counter;
01723       typedef tuple<Counter,Counter> CounterTuple;
01724       CombinedFunctor<CounterTuple> visitors(CounterTuple(Counter(aggregates, AggregatesMap<Vertex>::UNAGGREGATED, unused), Counter(aggregates, aggregate, aggregated)));
01725       return std::make_pair(unused.value(), aggregated.value());
01726 }
01727       
01728       
01729     template<class G>
01730     int Aggregator<G>::aggregateNeighbours(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01731     {
01732       DependencyCounter counter;
01733       visitAggregateNeighbours(vertex, aggregate, aggregates, counter);
01734       return counter.value();
01735     }
01736     
01737     template<class G>
01738     std::size_t Aggregator<G>::distance(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates)
01739     {
01740       typename PropertyMapTypeSelector<VertexVisitedTag,G>::Type visitedMap = get(VertexVisitedTag(), *graph_);
01741       VertexList vlist;
01742       typename AggregatesMap<Vertex>::DummyEdgeVisitor dummy;
01743       return aggregates.template breadthFirstSearch<true,true>(vertex, 
01744                                                       aggregate_->id(), *graph_, 
01745                                            vlist, dummy, dummy, visitedMap);
01746     }
01747     
01748     template<class G>
01749     inline Aggregator<G>::FrontMarker::FrontMarker(VertexList& front, MatrixGraph& graph)
01750       : front_(front), graph_(graph)
01751     {}
01752     
01753     template<class G>
01754     inline void Aggregator<G>::FrontMarker::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01755     {
01756       Vertex target = edge.target();
01757       
01758       if(!graph_.getVertexProperties(target).front()){
01759         front_.push_back(target);
01760         graph_.getVertexProperties(target).setFront();
01761       }
01762     }
01763         
01764 
01765     template<class G>
01766     void Aggregator<G>::markFront(const AggregatesMap<Vertex>& aggregates)
01767     {
01768       assert(front_.size()==0);
01769       FrontMarker frontBuilder(front_, *graph_);
01770       typedef typename Aggregate<G,VertexSet>::const_iterator Iterator;
01771       
01772       for(Iterator vertex=aggregate_->begin(); vertex != aggregate_->end(); ++vertex)
01773         visitAggregateNeighbours(*vertex, AggregatesMap<Vertex>::UNAGGREGATED, aggregates, frontBuilder);
01774       
01775     }
01776 
01777     template<class G>
01778     inline bool Aggregator<G>::admissible(const Vertex& vertex, const AggregateDescriptor& aggregate, const AggregatesMap<Vertex>& aggregates) const
01779     {
01780       // Todo
01781       Dune::dvverb<<" Admissible not yet implemented!"<<std::endl;
01782       
01783       return true;
01784     }
01785     
01786     template<class G>
01787     void Aggregator<G>::unmarkFront()
01788     {      
01789       typedef typename VertexList::const_iterator Iterator;
01790       
01791       for(Iterator vertex=front_.begin(); vertex != front_.end(); ++vertex)
01792         graph_->getVertexProperties(*vertex).resetFront();      
01793       
01794       front_.clear();
01795     }
01796 
01797     template<class G>
01798     inline typename G::VertexDescriptor Aggregator<G>::mergeNeighbour(const Vertex& vertex, const AggregatesMap<Vertex>& aggregates) const
01799     {
01800       typedef typename MatrixGraph::ConstEdgeIterator Iterator;
01801       
01802       Iterator end = graph_->endEdges(vertex);
01803       for(Iterator edge = graph_->beginEdges(vertex); edge != end; ++edge){
01804         if(aggregates[edge.target()] != AggregatesMap<Vertex>::UNAGGREGATED &&
01805            graph_->getVertexProperties(edge.target()).isolated() == graph_->getVertexProperties(edge.source()).isolated()){
01806           if( graph_->getVertexProperties(vertex).isolated() || 
01807               ((edge.properties().depends() || edge.properties().influences())
01808                && admissible(vertex, aggregates[edge.target()], aggregates)))
01809             return edge.target();
01810         }
01811       }
01812       return AggregatesMap<Vertex>::UNAGGREGATED;
01813     }
01814     
01815     template<class G>
01816     Aggregator<G>::FrontNeighbourCounter::FrontNeighbourCounter(const MatrixGraph& graph)
01817       : Counter(), graph_(graph)
01818     {}
01819 
01820     template<class G>
01821     void Aggregator<G>::FrontNeighbourCounter::operator()(const typename MatrixGraph::ConstEdgeIterator& edge)
01822     {
01823       if(graph_.getVertexProperties(edge.target()).front())
01824         Counter::increment();
01825     }
01826     
01827     template<class G>
01828     int Aggregator<G>::noFrontNeighbours(const Vertex& vertex) const
01829     {
01830       FrontNeighbourCounter counter(*graph_);
01831       visitNeighbours(*graph_, vertex, counter);
01832       return counter.value();
01833     }
01834     
01835     template<class G>
01836     template<class C>
01837     void Aggregator<G>::growAggregate(const Vertex& seed, const AggregatesMap<Vertex>& aggregates, const C& c)
01838     {
01839       while(aggregate_->size() < c.minAggregateSize()){
01840         int maxTwoCons=0, maxOneCons=0, maxNeighbours=-1;
01841         double maxCon=-1;
01842                 
01843         Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
01844         
01845         unmarkFront();
01846         markFront(aggregates);
01847 
01848         typedef typename VertexList::const_iterator Iterator;
01849           
01850         for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
01851           // Only nonisolated nodes are considered
01852           if(graph_->getVertexProperties(*vertex).isolated())
01853             continue;
01854           
01855           int twoWayCons = twoWayConnections(*vertex, aggregate_->id(), aggregates);
01856           
01857           /* The case of two way connections. */
01858           if( maxTwoCons == twoWayCons && twoWayCons > 0){
01859             double con = connectivity(*vertex, aggregates);
01860 
01861             if(con == maxCon){
01862               int neighbours = noFrontNeighbours(*vertex);
01863               
01864               if(neighbours > maxNeighbours){
01865                 maxNeighbours = neighbours;
01866                 
01867                 std::size_t distance_ = distance(*vertex, aggregates);
01868 
01869                 if(c.maxDistance() >= distance_){
01870                   candidate = *vertex;
01871                 }
01872               }
01873             }else if( con > maxCon){
01874               maxCon = con;
01875               maxNeighbours = noFrontNeighbours(*vertex);
01876               std::size_t distance_ = distance(*vertex, aggregates);
01877 
01878               if(c.maxDistance() >= distance_){
01879                 candidate = *vertex;
01880               }
01881             }
01882           }else if(twoWayCons > maxTwoCons){
01883             maxTwoCons = twoWayCons;
01884             maxCon = connectivity(*vertex, aggregates);
01885             maxNeighbours = noFrontNeighbours(*vertex);
01886             std::size_t distance_ = distance(*vertex, aggregates);
01887             
01888             if(c.maxDistance() >= distance_){
01889               candidate = *vertex;
01890             }
01891             
01892             // two way connections preceed
01893             maxOneCons = std::numeric_limits<int>::max();
01894           }
01895           
01896           if(twoWayCons > 0)
01897             continue; // THis is a two-way node, skip tests for one way nodes
01898 
01899           /* The one way case */
01900           int oneWayCons = oneWayConnections(*vertex, aggregate_->id(), aggregates);
01901           
01902           if(oneWayCons==0)
01903             continue; // No strong connections, skip the tests.
01904 
01905           if(!admissible(*vertex, aggregate_->id(), aggregates))
01906             continue;
01907           
01908           if( maxOneCons == oneWayCons && oneWayCons > 0){
01909             double con = connectivity(*vertex, aggregates);
01910 
01911             if(con == maxCon){
01912               int neighbours = noFrontNeighbours(*vertex);
01913               
01914               if(neighbours > maxNeighbours){
01915                 maxNeighbours = neighbours;
01916                 std::size_t distance_ = distance(*vertex, aggregates);
01917                 
01918                 if(c.maxDistance() >= distance_){
01919                   candidate = *vertex;
01920                 }
01921               }
01922             }else if( con > maxCon){
01923               maxCon = con;
01924               maxNeighbours = noFrontNeighbours(*vertex);
01925               std::size_t distance_ = distance(*vertex, aggregates);
01926               if(c.maxDistance() >= distance_){
01927                 candidate = *vertex;
01928               }
01929             }
01930           }else if(oneWayCons > maxOneCons){
01931             maxOneCons = oneWayCons;
01932             maxCon = connectivity(*vertex, aggregates);
01933             maxNeighbours = noFrontNeighbours(*vertex);
01934             std::size_t distance_ = distance(*vertex, aggregates);
01935                 
01936             if(c.maxDistance() >= distance_){
01937               candidate = *vertex;
01938             }
01939           }
01940         }
01941         
01942         
01943         if(candidate == AggregatesMap<Vertex>::UNAGGREGATED)
01944           break; // No more candidates found
01945 
01946         aggregate_->add(candidate);
01947       }
01948     }
01949       
01950     template<typename V>
01951     template<typename M, typename G, typename C>
01952     tuple<int,int,int> AggregatesMap<V>::buildAggregates(const M& matrix, G& graph, const C& criterion)
01953     {
01954       Aggregator<G> aggregator;
01955       return aggregator.build(matrix, graph, *this, criterion);
01956     }
01957     
01958     template<class G>
01959     template<class M, class C>
01960     tuple<int,int,int> Aggregator<G>::build(const M& m, G& graph, AggregatesMap<Vertex>& aggregates, const C& c)
01961     {
01962       // Stack for fast vertex access
01963       Stack stack_(graph, *this, aggregates);
01964       
01965       graph_ = &graph;
01966             
01967       aggregate_ = new Aggregate<G,VertexSet>(graph, aggregates, connected_);
01968       
01969       // Allocate the mapping to aggregate.
01970       size_ = graph.maxVertex();
01971 
01972       Timer watch;
01973       watch.reset();
01974 
01975       buildDependency(graph, m, c);
01976 
01977       dverb<<"Build dependency took "<< watch.elapsed()<<" seconds."<<std::endl;
01978       int noAggregates, conAggregates, isoAggregates, oneAggregates;
01979       noAggregates = conAggregates = isoAggregates = oneAggregates = 0;
01980       
01981       while(true){
01982         Vertex seed = stack_.pop();
01983         
01984         if(seed == Stack::NullEntry)
01985           // No more unaggregated vertices. We are finished!
01986           break;
01987         
01988         // Debugging output
01989         if((noAggregates+1)%10000 == 0)
01990           Dune::dverb<<"c";
01991         
01992         aggregate_->seed(seed);
01993         
01994         
01995         if(graph.getVertexProperties(seed).isolated()){
01996           // isolated vertices are not aggregated but skipped on the coarser levels.
01997           aggregates[seed]=AggregatesMap<Vertex>::ISOLATED;
01998           ++isoAggregates;
01999           // skip rest as no agglomeration is done.
02000           continue;
02001         }else
02002           growAggregate(seed, aggregates, c);
02003         
02004         
02005         /* The rounding step. */
02006         while(aggregate_->size() < c.maxAggregateSize()){
02007           
02008           unmarkFront();
02009           markFront(aggregates);
02010           
02011           Vertex candidate = AggregatesMap<Vertex>::UNAGGREGATED;
02012           
02013           typedef typename VertexList::const_iterator Iterator;
02014           
02015           for(Iterator vertex = front_.begin(); vertex != front_.end(); ++vertex){
02016 
02017             if(graph.getVertexProperties(*vertex).isolated())
02018               continue; // No isolated nodes here
02019 
02020             if(twoWayConnections( *vertex, aggregate_->id(), aggregates) == 0 && 
02021                (oneWayConnections( *vertex, aggregate_->id(), aggregates) == 0 || 
02022                 !admissible( *vertex, aggregate_->id(), aggregates) ))
02023               continue;
02024           
02025             std::pair<int,int> neighbourPair=neighbours(*vertex, aggregate_->id(),
02026                                                      aggregates);
02027             
02028             //if(aggregateNeighbours(*vertex, aggregate_->id(), aggregates) <= unusedNeighbours(*vertex, aggregates))
02029             // continue;
02030             
02031             if(neighbourPair.first >= neighbourPair.second)
02032               continue;
02033                     
02034             if(distance(*vertex, aggregates) > c.maxDistance())
02035               continue; // Distance too far
02036             candidate = *vertex;
02037             break;
02038           }
02039                   
02040           if(candidate == AggregatesMap<Vertex>::UNAGGREGATED) break; // no more candidates found.
02041           
02042           aggregate_->add(candidate);
02043           
02044         }
02045         
02046         // try to merge aggregates consisting of only one nonisolated vertex with other aggregates
02047         if(aggregate_->size()==1)
02048           if(!graph.getVertexProperties(seed).isolated()){
02049             Vertex mergedNeighbour = mergeNeighbour(seed, aggregates);
02050 
02051             if(mergedNeighbour != AggregatesMap<Vertex>::UNAGGREGATED){
02052               aggregates[seed] = aggregates[mergedNeighbour];
02053               /* // Reconstruct aggregate. Needed for markFront
02054               this->template breadthFirstSearch<
02055               visitAggregateNeighbours(seed, aggregates[seed], aggregates,)
02056               if(aggregate_->size()==2)
02057                 // Was a one node aggregate formerly
02058                 --oneAggregates;
02059               */
02060             }else{
02061               ++oneAggregates;
02062               ++conAggregates;
02063             }
02064             
02065           }else{
02066             ++oneAggregates;
02067             ++isoAggregates;
02068           }
02069         else{
02070           if(graph.getVertexProperties(seed).isolated())
02071             ++isoAggregates;
02072           else
02073             ++conAggregates;
02074         }
02075         unmarkFront();
02076         markFront(aggregates);
02077         seedFromFront(stack_, graph.getVertexProperties(seed).isolated());
02078         unmarkFront();
02079       }
02080       
02081       Dune::dinfo<<"connected aggregates: "<<conAggregates;
02082       Dune::dinfo<<" isolated aggregates: "<<isoAggregates;
02083       Dune::dinfo<<" one node aggregates: "<<oneAggregates<<std::endl;
02084       
02085       delete aggregate_;
02086       return make_tuple(conAggregates,isoAggregates,oneAggregates);
02087     }
02088     
02089     template<class G>
02090     inline void Aggregator<G>::seedFromFront(Stack& stack_, bool isolated)
02091     {
02092       typedef typename VertexList::const_iterator Iterator;
02093       
02094       Iterator end= front_.end();
02095       int count=0;
02096       for(Iterator vertex=front_.begin(); vertex != end; ++vertex,++count)
02097         stack_.push(*vertex);
02098       /*
02099       if(MINIMAL_DEBUG_LEVEL<=2 && count==0 && !isolated)
02100         Dune::dverb<< " no vertices pushed for nonisolated aggregate!"<<std::endl;
02101       */
02102     }
02103 
02104     template<class G>
02105     Aggregator<G>::Stack::Stack(const MatrixGraph& graph, const Aggregator<G>& aggregatesBuilder,
02106                                 const AggregatesMap<Vertex>& aggregates)
02107       : graph_(graph), aggregatesBuilder_(aggregatesBuilder), aggregates_(aggregates), size_(0), maxSize_(0), head_(0), filled_(0)
02108     {
02109       vals_ = new  Vertex[N];
02110     }
02111     
02112     template<class G>
02113     Aggregator<G>::Stack::~Stack()
02114     {
02115       Dune::dverb << "Max stack size was "<<maxSize_<<" filled="<<filled_<<std::endl;
02116       delete[] vals_;
02117     }
02118     
02119     template<class G> 
02120     const typename Aggregator<G>::Vertex Aggregator<G>::Stack::NullEntry 
02121     = std::numeric_limits<typename G::VertexDescriptor>::max();
02122 
02123     template<class G>
02124     inline bool Aggregator<G>::Stack::push(const Vertex& v)
02125     {
02126       if(aggregates_[v] == AggregatesMap<Vertex>::UNAGGREGATED){
02127         localPush(v);
02128         return true;
02129       }else
02130         return false;
02131     }
02132     
02133     template<class G>
02134     inline void Aggregator<G>::Stack::localPush(const Vertex& v)
02135     {
02136       vals_[head_] = v;
02137       size_ = std::min<int>(size_+1, N);
02138       head_ = (head_+N+1)%N;
02139     }
02140     
02141     template<class G>
02142     void Aggregator<G>::Stack::fill()
02143     {
02144       int isolated = 0, connected=0;
02145       int isoumin, umin;
02146       filled_++;
02147       
02148       head_ = size_ = 0;
02149       isoumin = umin = std::numeric_limits<int>::max();
02150       
02151       typedef typename MatrixGraph::ConstVertexIterator Iterator;
02152       
02153       const Iterator end = graph_.end();
02154       
02155       for(Iterator vertex = graph_.begin(); vertex != end; ++vertex){
02156         // Skip already aggregated vertices
02157         if(aggregates_[*vertex] != AggregatesMap<Vertex>::UNAGGREGATED)
02158           continue;
02159         
02160         if(vertex.properties().isolated()){
02161           isoumin = std::min(isoumin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02162           isolated++;
02163         }else{
02164           umin = std::min(umin, aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_));
02165           connected++;
02166         }
02167       }
02168       
02169       if(connected + isolated == 0)
02170         // No unaggregated vertices.
02171         return;
02172         
02173       if(connected > 0){
02174         // Connected vertices have higher priority.
02175          for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02176            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && !vertex.properties().isolated() 
02177               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == umin)
02178              localPush(*vertex);
02179       }else{
02180         for(Iterator vertex = graph_.begin(); vertex != end; ++vertex)
02181            if(aggregates_[*vertex] == AggregatesMap<Vertex>::UNAGGREGATED && vertex.properties().isolated() 
02182               && aggregatesBuilder_.unusedNeighbours(*vertex, aggregates_) == isoumin)
02183              localPush(*vertex);
02184       }
02185       maxSize_ = std::max(size_, maxSize_);
02186     }
02187 
02188     template<class G>
02189     inline typename G::VertexDescriptor Aggregator<G>::Stack::pop()
02190     {
02191       while(size_>0){
02192         head_ = (head_ + N -1) % N;
02193         size_--;
02194         Vertex v = vals_[head_];
02195         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02196           return v;
02197       }
02198       // Stack is empty try to fill it
02199       fill();
02200       
02201       // try again
02202       while(size_>0){
02203         head_ = (head_ + N -1) % N;
02204         size_--;
02205         Vertex v = vals_[head_];
02206         if(aggregates_[v]==AggregatesMap<Vertex>::UNAGGREGATED)
02207           return v;
02208       }
02209       return NullEntry;
02210     }
02211 
02212     template<class V>
02213     void printAggregates2d(const AggregatesMap<V>& aggregates, int n, int m,  std::ostream& os)
02214     {
02215       std::ios_base::fmtflags oldOpts=os.flags();
02216       
02217       os.setf(std::ios_base::right, std::ios_base::adjustfield);
02218       
02219       V max=0;
02220       int width=1;
02221 
02222       for(int i=0; i< n*m; i++)
02223         max=std::max(max, aggregates[i]);
02224       
02225       for(int i=10; i < 1000000; i*=10)
02226         if(max/i>0)
02227           width++;
02228         else
02229           break;
02230       
02231       for(int j=0, entry=0; j < m; j++){
02232         for(int i=0; i<n; i++, entry++){
02233           os.width(width);
02234           os<<aggregates[entry]<<" ";
02235         }
02236         
02237         os<<std::endl;
02238       }
02239       os<<std::endl;
02240       os.flags(oldOpts);
02241     }
02242     
02243     
02244   }// namespace Amg
02245   
02246 }// namespace Dune
02247 
02248 
02249 #endif

Generated on Sun Nov 15 22:29:35 2009 for dune-istl by  doxygen 1.5.6