hierarchy.hh

Go to the documentation of this file.
00001 // $Id: hierarchy.hh 764 2007-05-03 12:39:19Z mblatt $
00002 #ifndef DUNE_AMGHIERARCHY_HH
00003 #define DUNE_AMGHIERARCHY_HH
00004 
00005 #include<list>
00006 #include<memory>
00007 #include<limits>
00008 #include<algorithm>
00009 #include"pmatrix.hh"
00010 #include"aggregates.hh"
00011 #include"graph.hh"
00012 #include"galerkin.hh"
00013 #include"renumberer.hh"
00014 #include"graphcreator.hh"
00015 #include<dune/common/stdstreams.hh>
00016 #include<dune/common/timer.hh>
00017 #include<dune/common/tuples.hh>
00018 #include<dune/istl/bvector.hh>
00019 #include<dune/istl/indexset.hh>
00020 #include<dune/istl/paamg/dependency.hh>
00021 #include<dune/istl/paamg/graph.hh>
00022 #include<dune/istl/paamg/indicescoarsener.hh>
00023 #include<dune/istl/paamg/globalaggregates.hh>
00024 #include<dune/istl/paamg/construction.hh>
00025 #include<dune/istl/paamg/smoother.hh>
00026 
00027 namespace Dune
00028 {
00029   namespace Amg
00030   {
00048     template<typename T, typename A=std::allocator<T> >
00049     class Hierarchy
00050     {
00051     public:
00055       typedef T MemberType;
00056 
00057       template<typename T1, typename T2>
00058       class LevelIterator;
00059 
00060     private:
00064       struct Element
00065       {
00066         friend class LevelIterator<Hierarchy<T,A>, T>;
00067         friend class LevelIterator<const Hierarchy<T,A>, const T>;
00068 
00070         Element* coarser_;
00071         
00073         Element* finer_;
00074         
00076         MemberType* element_;
00077         
00079         MemberType* redistributed_;
00080       };
00081     public:
00082 //       enum{
00083 //      /**
00084 //       * @brief If true only the method addCoarser will be usable
00085 //       * otherwise only the method addFiner will be usable.
00086 //       */
00087 //      coarsen = b
00088 //        };
00089       
00093       typedef typename A::template rebind<Element>::other Allocator;
00094 
00095       typedef typename ConstructionTraits<T>::Arguments Arguments;
00096       
00101       Hierarchy(MemberType& first);
00102       
00106       Hierarchy();
00107 
00112       void addCoarser(Arguments& args);
00113       
00114       
00119       void addFiner(Arguments& args);
00120 
00127       template<class C, class T1>
00128       class LevelIterator 
00129         : public BidirectionalIteratorFacade<LevelIterator<C,T1>,T1,T1&>
00130       {
00131         friend class LevelIterator<typename Dune::RemoveConst<C>::Type,
00132                                    typename Dune::RemoveConst<T1>::Type >;
00133         friend class LevelIterator<const typename Dune::RemoveConst<C>::Type, 
00134                                    const typename Dune::RemoveConst<T1>::Type >;
00135 
00136       public:
00138         LevelIterator()
00139           : element_(0)
00140         {}
00141         
00142         LevelIterator(Element* element)
00143           : element_(element)
00144         {}
00145         
00147         LevelIterator(const LevelIterator<typename Dune::RemoveConst<C>::Type,
00148                       typename Dune::RemoveConst<T1>::Type>& other)
00149           : element_(other.element_)
00150         {}
00151         
00153         LevelIterator(const LevelIterator<const typename Dune::RemoveConst<C>::Type,
00154                       const typename Dune::RemoveConst<T1>::Type>& other)
00155           : element_(other.element_)
00156         {}
00157 
00161         bool equals(const LevelIterator<typename Dune::RemoveConst<C>::Type, 
00162                     typename Dune::RemoveConst<T1>::Type>& other) const
00163         {
00164           return element_ == other.element_;
00165         }
00166         
00170         bool equals(const LevelIterator<const typename Dune::RemoveConst<C>::Type, 
00171                     const typename Dune::RemoveConst<T1>::Type>& other) const
00172         {
00173           return element_ == other.element_;
00174         }
00175 
00177         T1& dereference() const
00178         {
00179           return *(element_->element_);
00180         }
00181         
00183         void increment()
00184         {
00185           element_ = element_->coarser_;
00186         }
00187         
00189         void decrement()
00190         {
00191           element_ = element_->finer_;
00192         }
00193         
00198         bool isRedistributed() const
00199         {
00200           return element_->redistributed_;
00201         }
00202         
00207         T1& getRedistributed() const
00208         {
00209           assert(element_->redistributed_);
00210           return *element_->redistributed_;
00211         }
00212         
00213       private:
00214         Element* element_;
00215       };
00216       
00218       typedef LevelIterator<Hierarchy<T,A>,T> Iterator;
00219 
00221       typedef LevelIterator<const Hierarchy<T,A>, const T> ConstIterator;
00222 
00227       Iterator finest();
00228       
00233       Iterator coarsest();
00234       
00235       
00240       ConstIterator finest() const;
00241       
00246       ConstIterator coarsest() const;
00247 
00252       int levels() const;
00253       
00255       ~Hierarchy();
00256       
00257     private:
00259       Element* finest_;
00261       Element* coarsest_;
00263       Element* nonAllocated_;
00265       Allocator allocator_;
00267       int levels_;
00268     };
00269     
00276     template<class M, class PI, class A=std::allocator<M> >
00277     class MatrixHierarchy
00278     {
00279     public:
00281       typedef M MatrixOperator;
00282       
00284       typedef typename MatrixOperator::matrix_type Matrix;
00285 
00287       typedef PI ParallelInformation;
00288       
00290       typedef A Allocator;
00291 
00293       typedef AggregatesMap<typename MatrixGraph<Matrix>::VertexDescriptor> AggregatesMap;
00294 
00296       typedef Hierarchy<MatrixOperator,Allocator> ParallelMatrixHierarchy;
00297 
00299       typedef Hierarchy<ParallelInformation,Allocator> ParallelInformationHierarchy;
00300 
00302       typedef typename Allocator::template rebind<AggregatesMap*>::other AAllocator;
00303       
00305       typedef std::list<AggregatesMap*,AAllocator> AggregatesMapList;
00306 
00312       MatrixHierarchy(const MatrixOperator& fineMatrix,
00313                       const ParallelInformation& pinfo=ParallelInformation());
00314       
00315       
00316       ~MatrixHierarchy();
00317       
00323       template<typename O, typename T>
00324       void build(const T& criterion);
00325 
00333       template<class F>
00334       void recalculateGalerkin(const F& copyFlags);
00335 
00340       template<class V, class TA>
00341       void coarsenVector(Hierarchy<BlockVector<V,TA> >& hierarchy) const;
00342 
00348       template<class S, class TA>
00349       void coarsenSmoother(Hierarchy<S,TA>& smoothers, 
00350                            const typename SmootherTraits<S>::Arguments& args) const;
00351       
00356       int levels() const;
00357 
00362       bool isBuilt() const;
00363 
00368       const ParallelMatrixHierarchy& matrices() const;
00369       
00374       const ParallelInformationHierarchy& parallelInformation() const;
00375       
00380       const AggregatesMapList& aggregatesMaps() const;
00381       
00382     private:
00383       typedef typename ConstructionTraits<MatrixOperator>::Arguments MatrixArgs;
00385       AggregatesMapList aggregatesMaps_;
00387       ParallelMatrixHierarchy matrices_;
00389       ParallelInformationHierarchy parallelInformation_;
00390 
00392       bool built_;
00393 
00397       template<class Matrix, bool print>
00398       struct MatrixStats
00399       {
00400         
00404         static void stats(const Matrix& matrix)
00405         {}
00406       };
00407       
00408       template<class Matrix>
00409       struct MatrixStats<Matrix,true>
00410       {
00411         struct calc
00412         {
00413           typedef typename Matrix::size_type size_type;
00414           typedef typename Matrix::row_type matrix_row;
00415           
00416           calc()
00417           {
00418             min=std::numeric_limits<size_type>::max();
00419             max=0;
00420             sum=0;
00421           }
00422           
00423           void operator()(const matrix_row& row)
00424           {
00425             min=std::min(min, row.size());
00426             max=std::max(max, row.size());
00427             sum += row.size();
00428           }
00429           
00430           size_type min;
00431           size_type max;
00432           size_type sum;
00433         };
00437         static void stats(const Matrix& matrix)
00438         {
00439           calc c= for_each(matrix.begin(), matrix.end(), calc());
00440           dinfo<<"Matrix row: min="<<c.min<<" max="<<c.max
00441                <<" average="<<static_cast<double>(c.sum)/matrix.N()
00442                <<std::endl;
00443         }
00444       };
00445     };
00446 
00450     template<class T>
00451     class CoarsenCriterion : public T
00452     {
00453     public:
00458       typedef T DependencyCriterion;
00459       
00463       void setMaxLevel(int l)
00464       {
00465         maxLevel_ = l;
00466       }
00470       int maxLevel() const
00471       {
00472         return maxLevel_;
00473       }
00474       
00478       void setCoarsenTarget(int nodes)
00479       {
00480         coarsenTarget_ = nodes;
00481       }
00482       
00486       int coarsenTarget() const
00487       {
00488         return coarsenTarget_;
00489       }
00490       
00496       void setMinCoarsenRate(double rate)
00497       {
00498         minCoarsenRate_ = rate;
00499       }
00500       
00504       double minCoarsenRate() const
00505       {
00506         return minCoarsenRate_;
00507       }
00511       bool accumulate() const
00512       {
00513         return false;
00514       }
00515       
00524       CoarsenCriterion(int maxLevel=100, int coarsenTarget=1000, double minCoarsenRate=1.2)
00525         : T(), maxLevel_(maxLevel), coarsenTarget_(coarsenTarget), minCoarsenRate_(minCoarsenRate)
00526       {}
00527       
00528     private:
00532       int maxLevel_;
00536       int coarsenTarget_;
00540       double minCoarsenRate_;
00541     };
00542     
00543 
00544     template<class M, class IS, class A>
00545     MatrixHierarchy<M,IS,A>::MatrixHierarchy(const MatrixOperator& fineOperator,
00546                                              const ParallelInformation& pinfo)
00547       : matrices_(const_cast<MatrixOperator&>(fineOperator)),
00548         parallelInformation_(const_cast<ParallelInformation&>(pinfo))
00549     {
00550       IsTrue<static_cast<int>(MatrixOperator::category) == static_cast<int>(SolverCategory::sequential) ||
00551         static_cast<int>(MatrixOperator::category) == static_cast<int>(SolverCategory::overlapping)>::yes();
00552       IsTrue<static_cast<int>(MatrixOperator::category) == static_cast<int>(ParallelInformation::category)>::yes();
00553     }
00554     
00555     template<class M, class IS, class A>
00556     template<typename O, typename T>
00557     void MatrixHierarchy<M,IS,A>::build(const T& criterion)
00558     {
00559       typedef O OverlapFlags;
00560       typedef typename ParallelMatrixHierarchy::Iterator MatIterator;
00561       typedef typename ParallelInformationHierarchy::Iterator PInfoIterator;
00562       
00563       GalerkinProduct<ParallelInformation> productBuilder;
00564       MatIterator mlevel = matrices_.finest();
00565       MatrixStats<typename M::matrix_type,MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL>::stats(mlevel->getmat());
00566       
00567       PInfoIterator infoLevel = parallelInformation_.finest();
00568       
00569       
00570       int procs = infoLevel->communicator().size();
00571       int level = 0;
00572       int rank = 0;
00573       int unknowns = mlevel->getmat().N();;
00574 
00575       unknowns = infoLevel->communicator().sum(unknowns);
00576       infoLevel->buildGlobalLookup(mlevel->getmat().N());
00577 
00578       for(; level < criterion.maxLevel(); ++level, ++mlevel){
00579 
00580         rank = infoLevel->communicator().rank();
00581         dverb<<infoLevel->communicator().rank()<<": Level "<<level<<" has "<<mlevel->getmat().N()<<" unknows!"<<std::endl;
00582         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00583             dinfo<<"Level "<<level<<" has "<<unknowns<<" unknowns, "<<unknowns/infoLevel->communicator().size()<<" unknowns per proc"<<std::endl;
00584 
00585         if(unknowns <= criterion.coarsenTarget())
00586            // No further coarsening needed
00587            break;
00588 
00589         typedef PropertiesGraphCreator<MatrixOperator> GraphCreator;
00590         typedef typename GraphCreator::PropertiesGraph PropertiesGraph;
00591         typedef typename GraphCreator::MatrixGraph MatrixGraph;
00592         typedef typename GraphCreator::GraphTuple  GraphTuple;
00593 
00594         typedef typename PropertiesGraph::VertexDescriptor Vertex;
00595         
00596         std::vector<bool> excluded(mlevel->getmat().N(), false);
00597 
00598         GraphTuple graphs = GraphCreator::create(*mlevel, excluded, *infoLevel, OverlapFlags());
00599         
00600         AggregatesMap* aggregatesMap=new AggregatesMap(Element<1>::get(graphs)->maxVertex());
00601 
00602         aggregatesMaps_.push_back(aggregatesMap);
00603                 
00604         Timer watch;
00605         watch.reset();
00606         int noAggregates, isoAggregates, oneAggregates;
00607         
00608         tie(noAggregates, isoAggregates, oneAggregates) =       
00609           aggregatesMap->buildAggregates(mlevel->getmat(), *(Element<1>::get(graphs)), criterion);
00610 
00611         noAggregates = infoLevel->communicator().sum(noAggregates);
00612 
00613         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00614           dinfo << "Building "<<noAggregates<<" aggregates took "<<watch.elapsed()<<" seconds."<<std::endl;     
00615 
00616         if(!noAggregates || unknowns/noAggregates<criterion.minCoarsenRate())
00617           if(procs>1 && criterion.accumulate())
00618             DUNE_THROW(NotImplemented, "Accumulation to fewer processes not yet implemented!");
00619           else{
00620             if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00621               if(noAggregates)
00622                 dinfo << "Stopped coarsening because of rate breakdown "<<unknowns/noAggregates<<"<"
00623                       <<criterion.minCoarsenRate()<<std::endl;
00624               else
00625                 dinfo << "Could not build any aggregates. Probably no connected nodes."<<std::endl;
00626             delete aggregatesMap;
00627             break;
00628           }
00629          
00630         unknowns =  noAggregates;
00631             
00632         if(noAggregates < criterion.coarsenTarget() && procs>1 && criterion.accumulate()){
00633           DUNE_THROW(NotImplemented, "Accumulation to fewer processes not yet implemented!");
00634         }
00635                 
00636         parallelInformation_.addCoarser(infoLevel->communicator());
00637         
00638         PInfoIterator fineInfo = infoLevel++;
00639                 
00640         typename PropertyMapTypeSelector<VertexVisitedTag,PropertiesGraph>::Type visitedMap = 
00641           get(VertexVisitedTag(), *(Element<1>::get(graphs)));
00642   
00643         watch.reset();
00644         int aggregates = IndicesCoarsener<ParallelInformation,OverlapFlags>
00645           ::coarsen(*fineInfo,
00646                     *(Element<1>::get(graphs)),
00647                     visitedMap,
00648                     *aggregatesMap,
00649                     *infoLevel);
00650         dinfo<< rank<<": agglomeration achieved "<<aggregates<<" aggregates"<<std::endl;
00651         
00652         GraphCreator::free(graphs);
00653         
00654         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00655           infoLevel->communicator().barrier();
00656           if(rank==0)
00657             dinfo<<"Coarsening of index sets took "<<watch.elapsed()<<" seconds."<<std::endl;
00658         }
00659         
00660         watch.reset();
00661 
00662         infoLevel->buildGlobalLookup(aggregates);
00663         AggregatesPublisher<Vertex,OverlapFlags,ParallelInformation>::publish(*aggregatesMap,
00664                                                                               *fineInfo,
00665                                                                               infoLevel->globalLookup());
00666         
00667                 
00668         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00669           infoLevel->communicator().barrier();
00670           if(rank==0)
00671             dinfo<<"Communicating global aggregate numbers took "<<watch.elapsed()<<" seconds."<<std::endl;
00672         }
00673 
00674         watch.reset();
00675         std::vector<bool>& visited=excluded;
00676         
00677         typedef std::vector<bool>::iterator Iterator;
00678         typedef IteratorPropertyMap<Iterator, IdentityMap> VisitedMap2;
00679         Iterator end = visited.end();
00680         for(Iterator iter= visited.begin(); iter != end; ++iter)
00681           *iter=false;
00682         
00683         VisitedMap2 visitedMap2(visited.begin(), Dune::IdentityMap());
00684 
00685         typename MatrixOperator::matrix_type* coarseMatrix;
00686 
00687         coarseMatrix = productBuilder.build(mlevel->getmat(), *(Element<0>::get(graphs)), visitedMap2, 
00688                                             *fineInfo, 
00689                                             *aggregatesMap,
00690                                             aggregates,
00691                                             OverlapFlags());
00692         
00693         fineInfo->freeGlobalLookup();
00694         
00695         delete Element<0>::get(graphs);
00696         productBuilder.calculate(mlevel->getmat(), *aggregatesMap, *coarseMatrix, *infoLevel, OverlapFlags());
00697         
00698         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00699           infoLevel->communicator().barrier();
00700           if(rank==0)
00701             dinfo<<"Calculation of Galerkin product took "<<watch.elapsed()<<" seconds."<<std::endl;
00702         }
00703         
00704         MatrixArgs args(*coarseMatrix, *infoLevel);
00705         
00706         matrices_.addCoarser(args);
00707       }
00708 
00709       infoLevel->freeGlobalLookup();
00710       
00711       built_=true;
00712       AggregatesMap* aggregatesMap=new AggregatesMap(0);
00713       aggregatesMaps_.push_back(aggregatesMap);
00714 
00715       if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL)
00716         if(level==criterion.maxLevel()){
00717           int unknowns = mlevel->getmat().N();
00718           unknowns = infoLevel->communicator().sum(unknowns);
00719           if(rank==0)
00720             dinfo<<"Level "<<level<<" has "<<unknowns<<" unknowns, "<<unknowns/infoLevel->communicator().size()<<" unknowns per proc"<<std::endl;
00721         }
00722     }
00723     
00724     template<class M, class IS, class A>
00725     const typename MatrixHierarchy<M,IS,A>::ParallelMatrixHierarchy& 
00726     MatrixHierarchy<M,IS,A>::matrices() const
00727     {
00728       return matrices_;
00729     }
00730     
00731     template<class M, class IS, class A>
00732     const typename MatrixHierarchy<M,IS,A>::ParallelInformationHierarchy& 
00733     MatrixHierarchy<M,IS,A>::parallelInformation() const
00734     {
00735       return parallelInformation_;
00736     }
00737     
00738     template<class M, class IS, class A>
00739     const typename MatrixHierarchy<M,IS,A>::AggregatesMapList& 
00740     MatrixHierarchy<M,IS,A>::aggregatesMaps() const
00741     {
00742       return aggregatesMaps_;
00743     }
00744     template<class M, class IS, class A>
00745     MatrixHierarchy<M,IS,A>::~MatrixHierarchy()
00746     {
00747       typedef typename AggregatesMapList::reverse_iterator AggregatesMapIterator;
00748       typedef typename ParallelMatrixHierarchy::Iterator Iterator;
00749       typedef typename ParallelInformationHierarchy::Iterator InfoIterator;
00750       
00751       AggregatesMapIterator amap = aggregatesMaps_.rbegin();
00752       InfoIterator info = parallelInformation_.coarsest();
00753       for(Iterator level=matrices_.coarsest(), finest=matrices_.finest(); level != finest;  --level, --info, ++amap){
00754         (*amap)->free();
00755         delete *amap;
00756         delete &level->getmat();
00757       }
00758       delete *amap;
00759     }
00760 
00761     template<class M, class IS, class A>
00762     template<class V, class TA>
00763     void MatrixHierarchy<M,IS,A>::coarsenVector(Hierarchy<BlockVector<V,TA> >& hierarchy) const
00764     {
00765       assert(hierarchy.levels()==1);
00766       typedef typename ParallelMatrixHierarchy::ConstIterator Iterator;
00767       Iterator coarsest = matrices_.coarsest();
00768       int level=0;
00769       Dune::dvverb<<"Level "<<level<<" has "<<matrices_.finest()->getmat().N()<<" unknows!"<<std::endl;
00770       
00771       for(Iterator matrix = matrices_.finest(); matrix != coarsest;){
00772         ++matrix;
00773         ++level;
00774         Dune::dvverb<<"Level "<<level<<" has "<<matrix->getmat().N()<<" unknows!"<<std::endl;
00775         hierarchy.addCoarser(matrix->getmat().N());
00776       }
00777     }
00778     
00779     template<class M, class IS, class A>
00780     template<class S, class TA>
00781     void MatrixHierarchy<M,IS,A>::coarsenSmoother(Hierarchy<S,TA>& smoothers, 
00782                                                     const typename SmootherTraits<S>::Arguments& sargs) const
00783     {
00784       assert(smoothers.levels()==0);
00785       typedef typename ParallelMatrixHierarchy::ConstIterator MatrixIterator;
00786       typedef typename ParallelInformationHierarchy::ConstIterator PinfoIterator;
00787       typename ConstructionTraits<S>::Arguments cargs;
00788       cargs.setArgs(sargs);
00789       PinfoIterator pinfo = parallelInformation_.finest();
00790 
00791       for(MatrixIterator matrix = matrices_.finest(), coarsest = matrices_.coarsest(); 
00792           matrix != coarsest; ++matrix, ++pinfo){
00793         cargs.setMatrix(matrix->getmat());
00794         cargs.setComm(*pinfo);
00795         smoothers.addCoarser(cargs);
00796       }
00797     }
00798     
00799     template<class M, class IS, class A>
00800     template<class F>
00801     void MatrixHierarchy<M,IS,A>::recalculateGalerkin(const F& copyFlags)
00802     {
00803       typedef typename AggregatesMapList::iterator AggregatesMapIterator;
00804       typedef typename ParallelMatrixHierarchy::Iterator Iterator;
00805       typedef typename ParallelInformationHierarchy::Iterator InfoIterator;
00806       
00807       AggregatesMapIterator amap = aggregatesMaps_.begin();
00808       BaseGalerkinProduct productBuilder;
00809       InfoIterator info = parallelInformation_.finest();
00810       
00811       for(Iterator level = matrices_.finest(), coarsest=matrices_.coarsest(); level!=coarsest; ++amap){
00812         const Matrix& fine = level->getmat();
00813         ++level;
00814         ++info;
00815         productBuilder.calculate(fine, *(*amap), const_cast<Matrix&>(level->getmat()), *info, copyFlags);
00816         
00817       }
00818     }
00819 
00820     template<class M, class IS, class A>
00821     int MatrixHierarchy<M,IS,A>::levels() const
00822     {
00823       return matrices_.levels();
00824     }
00825 
00826     template<class M, class IS, class A>
00827     bool MatrixHierarchy<M,IS,A>::isBuilt() const
00828     {
00829       return built_;
00830     }
00831     
00832     template<class T, class A>
00833     Hierarchy<T,A>::Hierarchy()
00834       : finest_(0), coarsest_(0), nonAllocated_(0), allocator_(), levels_(0)
00835     {}
00836 
00837     template<class T, class A>
00838     Hierarchy<T,A>::Hierarchy(MemberType& first)
00839       : allocator_()
00840     {
00841       finest_ = allocator_.allocate(1,0);
00842       finest_->element_ = &first;
00843       finest_->redistributed_ = 0;
00844       nonAllocated_ = finest_;
00845       coarsest_ = finest_;
00846       coarsest_->coarser_ = coarsest_->finer_ = 0;
00847       levels_ = 1;
00848     }
00849 
00850     template<class T, class A>
00851     Hierarchy<T,A>::~Hierarchy()
00852     {
00853       while(coarsest_){
00854         Element* current = coarsest_;
00855         coarsest_ = coarsest_->finer_;
00856         if(current != nonAllocated_){
00857           ConstructionTraits<T>::deconstruct(current->element_);
00858         }
00859         allocator_.deallocate(current, 1);
00860         //coarsest_->coarser_ = 0;
00861       }
00862     }
00863 
00864     template<class T, class A>
00865     int Hierarchy<T,A>::levels() const
00866     {
00867       return levels_;
00868     }
00869 
00870     template<class T, class A>
00871     void Hierarchy<T,A>::addCoarser(Arguments& args)
00872     {
00873       if(!coarsest_){
00874         assert(!finest_);
00875         coarsest_ = allocator_.allocate(1,0);
00876         coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
00877         finest_ = coarsest_;
00878         coarsest_->finer_ = 0;
00879         coarsest_->redistributed_ = 0;
00880       }else{
00881         coarsest_->coarser_ = allocator_.allocate(1,0);
00882         coarsest_->coarser_->finer_ = coarsest_;
00883         coarsest_ = coarsest_->coarser_;
00884         coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
00885         finest_->redistributed_ = 0;
00886       }
00887       coarsest_->coarser_=0;
00888       ++levels_;
00889     }
00890     
00891     template<class T, class A>
00892     void Hierarchy<T,A>::addFiner(Arguments& args)
00893     {
00894       if(!finest_){
00895         assert(!coarsest_);
00896         finest_ = allocator_.allocate(1,0);
00897         finest_->element = ConstructionTraits<T>::construct(args);
00898         coarsest_ = finest_;
00899         coarsest_->coarser_ = coarsest_->finer_ = 0;
00900       }else{
00901         finest_->finer_ = allocator_.allocate(1,0);
00902         finest_->finer_->coarser_ = finest_;
00903         finest_ = finest_->finer_;
00904         finest_->finer = 0;
00905         finest_->element = ConstructionTraits<T>::construct(args);
00906       }
00907       ++levels_;
00908     }
00909 
00910     template<class T, class A>
00911     typename Hierarchy<T,A>::Iterator Hierarchy<T,A>::finest()
00912     {
00913       return Iterator(finest_);
00914     }
00915 
00916     template<class T, class A>
00917     typename Hierarchy<T,A>::Iterator Hierarchy<T,A>::coarsest()
00918     {
00919       return Iterator(coarsest_);
00920     }
00921 
00922     template<class T, class A>
00923     typename Hierarchy<T,A>::ConstIterator Hierarchy<T,A>::finest() const
00924     {
00925       return ConstIterator(finest_);
00926     }
00927 
00928     template<class T, class A>
00929     typename Hierarchy<T,A>::ConstIterator Hierarchy<T,A>::coarsest() const
00930     {
00931       return ConstIterator(coarsest_);
00932     }
00934   }// namespace Amg
00935 }// namespace Dune
00936 
00937 #endif

Generated on 12 Dec 2007 with Doxygen (ver 1.5.1)