hierarchy.hh

Go to the documentation of this file.
00001 // $Id: hierarchy.hh 817 2007-09-21 18:48:11Z 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 remove_const<C>::type,
00132                                    typename remove_const<T1>::type >;
00133         friend class LevelIterator<const typename remove_const<C>::type, 
00134                                    const typename remove_const<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 remove_const<C>::type,
00148                       typename remove_const<T1>::type>& other)
00149           : element_(other.element_)
00150         {}
00151         
00153         LevelIterator(const LevelIterator<const typename remove_const<C>::type,
00154                       const typename remove_const<T1>::type>& other)
00155           : element_(other.element_)
00156         {}
00157 
00161         bool equals(const LevelIterator<typename remove_const<C>::type, 
00162                     typename remove_const<T1>::type>& other) const
00163         {
00164           return element_ == other.element_;
00165         }
00166         
00170         bool equals(const LevelIterator<const typename remove_const<C>::type, 
00171                     const typename remove_const<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 #ifdef TEST_AGGLO
00612  {
00613         // calculate size of local matrix in the distributed direction
00614         int start, end, overlapStart, overlapEnd;
00615         int n = UNKNOWNS/procs; // number of unknowns per process
00616         int bigger = UNKNOWNS%procs; // number of process with n+1 unknows
00617         int procs=infoLevel->communicator().rank();
00618 
00619         // Compute owner region
00620         if(rank<bigger){
00621           start = rank*(n+1);
00622           end   = (rank+1)*(n+1);
00623         }else{
00624           start = bigger + rank * n;
00625           end   = bigger + (rank + 1) * n;
00626         }
00627   
00628         // Compute overlap region
00629         if(start>0)
00630           overlapStart = start - 1;
00631         else
00632           overlapStart = start;
00633         
00634         if(end<UNKNOWNS)
00635           overlapEnd = end + 1;
00636         else
00637           overlapEnd = end;
00638   
00639         int noKnown = overlapEnd-overlapStart;
00640         int offset = start-overlapStart;
00641         int starti = 1;//(start-overlapStart==0)?1:0;
00642         int endi = (overlapEnd-end==0)?end-start-1:end-start;
00643         
00644         for(int j=1; j< UNKNOWNS-1; ++j)
00645           for(int i=starti; i < endi; ++i)
00646             (*aggregatesMap)[j*(overlapEnd-overlapStart)+i+offset]=((j-1)/2)*(endi-starti)/2+((i-starti)/2);
00647         noAggregates=((UNKNOWNS-2)/2)*(endi-starti)/2;
00648  }
00649 #endif
00650         noAggregates = infoLevel->communicator().sum(noAggregates);
00651 
00652         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00653           dinfo << "Building "<<noAggregates<<" aggregates took "<<watch.elapsed()<<" seconds."<<std::endl;     
00654 
00655         if(!noAggregates || unknowns/noAggregates<criterion.minCoarsenRate())
00656           if(procs>1 && criterion.accumulate())
00657             DUNE_THROW(NotImplemented, "Accumulation to fewer processes not yet implemented!");
00658           else{
00659             if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00660               if(noAggregates)
00661                 dinfo << "Stopped coarsening because of rate breakdown "<<unknowns/noAggregates<<"<"
00662                       <<criterion.minCoarsenRate()<<std::endl;
00663               else
00664                 dinfo << "Could not build any aggregates. Probably no connected nodes."<<std::endl;
00665             delete aggregatesMap;
00666             break;
00667           }
00668          
00669         unknowns =  noAggregates;
00670             
00671         if(noAggregates < criterion.coarsenTarget() && procs>1 && criterion.accumulate()){
00672           DUNE_THROW(NotImplemented, "Accumulation to fewer processes not yet implemented!");
00673         }
00674                 
00675         parallelInformation_.addCoarser(infoLevel->communicator());
00676         
00677         PInfoIterator fineInfo = infoLevel++;
00678                 
00679         typename PropertyMapTypeSelector<VertexVisitedTag,PropertiesGraph>::Type visitedMap = 
00680           get(VertexVisitedTag(), *(Element<1>::get(graphs)));
00681   
00682         watch.reset();
00683         int aggregates = IndicesCoarsener<ParallelInformation,OverlapFlags>
00684           ::coarsen(*fineInfo,
00685                     *(Element<1>::get(graphs)),
00686                     visitedMap,
00687                     *aggregatesMap,
00688                     *infoLevel);
00689 
00690         dinfo<< rank<<": agglomeration achieved "<<aggregates<<" aggregates"<<std::endl;
00691         
00692         GraphCreator::free(graphs);
00693         
00694         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00695           infoLevel->communicator().barrier();
00696           if(rank==0)
00697             dinfo<<"Coarsening of index sets took "<<watch.elapsed()<<" seconds."<<std::endl;
00698         }
00699         
00700         watch.reset();
00701 
00702         infoLevel->buildGlobalLookup(aggregates);
00703         AggregatesPublisher<Vertex,OverlapFlags,ParallelInformation>::publish(*aggregatesMap,
00704                                                                               *fineInfo,
00705                                                                               infoLevel->globalLookup());
00706         
00707                 
00708         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00709           infoLevel->communicator().barrier();
00710           if(rank==0)
00711             dinfo<<"Communicating global aggregate numbers took "<<watch.elapsed()<<" seconds."<<std::endl;
00712         }
00713 
00714         watch.reset();
00715         std::vector<bool>& visited=excluded;
00716         
00717         typedef std::vector<bool>::iterator Iterator;
00718         typedef IteratorPropertyMap<Iterator, IdentityMap> VisitedMap2;
00719         Iterator end = visited.end();
00720         for(Iterator iter= visited.begin(); iter != end; ++iter)
00721           *iter=false;
00722         
00723         VisitedMap2 visitedMap2(visited.begin(), Dune::IdentityMap());
00724 
00725         typename MatrixOperator::matrix_type* coarseMatrix;
00726 
00727         coarseMatrix = productBuilder.build(mlevel->getmat(), *(Element<0>::get(graphs)), visitedMap2, 
00728                                             *fineInfo, 
00729                                             *aggregatesMap,
00730                                             aggregates,
00731                                             OverlapFlags());
00732         
00733         fineInfo->freeGlobalLookup();
00734         
00735         delete Element<0>::get(graphs);
00736         productBuilder.calculate(mlevel->getmat(), *aggregatesMap, *coarseMatrix, *infoLevel, OverlapFlags());
00737         
00738         if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00739           infoLevel->communicator().barrier();
00740           if(rank==0)
00741             dinfo<<"Calculation of Galerkin product took "<<watch.elapsed()<<" seconds."<<std::endl;
00742         }
00743         
00744         MatrixArgs args(*coarseMatrix, *infoLevel);
00745         
00746         matrices_.addCoarser(args);
00747       }
00748 
00749       infoLevel->freeGlobalLookup();
00750       
00751       built_=true;
00752       AggregatesMap* aggregatesMap=new AggregatesMap(0);
00753       aggregatesMaps_.push_back(aggregatesMap);
00754 
00755       if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL)
00756         if(level==criterion.maxLevel()){
00757           int unknowns = mlevel->getmat().N();
00758           unknowns = infoLevel->communicator().sum(unknowns);
00759           if(rank==0)
00760             dinfo<<"Level "<<level<<" has "<<unknowns<<" unknowns, "<<unknowns/infoLevel->communicator().size()<<" unknowns per proc"<<std::endl;
00761         }
00762     }
00763     
00764     template<class M, class IS, class A>
00765     const typename MatrixHierarchy<M,IS,A>::ParallelMatrixHierarchy& 
00766     MatrixHierarchy<M,IS,A>::matrices() const
00767     {
00768       return matrices_;
00769     }
00770     
00771     template<class M, class IS, class A>
00772     const typename MatrixHierarchy<M,IS,A>::ParallelInformationHierarchy& 
00773     MatrixHierarchy<M,IS,A>::parallelInformation() const
00774     {
00775       return parallelInformation_;
00776     }
00777     
00778     template<class M, class IS, class A>
00779     const typename MatrixHierarchy<M,IS,A>::AggregatesMapList& 
00780     MatrixHierarchy<M,IS,A>::aggregatesMaps() const
00781     {
00782       return aggregatesMaps_;
00783     }
00784     template<class M, class IS, class A>
00785     MatrixHierarchy<M,IS,A>::~MatrixHierarchy()
00786     {
00787       typedef typename AggregatesMapList::reverse_iterator AggregatesMapIterator;
00788       typedef typename ParallelMatrixHierarchy::Iterator Iterator;
00789       typedef typename ParallelInformationHierarchy::Iterator InfoIterator;
00790       
00791       AggregatesMapIterator amap = aggregatesMaps_.rbegin();
00792       InfoIterator info = parallelInformation_.coarsest();
00793       for(Iterator level=matrices_.coarsest(), finest=matrices_.finest(); level != finest;  --level, --info, ++amap){
00794         (*amap)->free();
00795         delete *amap;
00796         delete &level->getmat();
00797       }
00798       delete *amap;
00799     }
00800 
00801     template<class M, class IS, class A>
00802     template<class V, class TA>
00803     void MatrixHierarchy<M,IS,A>::coarsenVector(Hierarchy<BlockVector<V,TA> >& hierarchy) const
00804     {
00805       assert(hierarchy.levels()==1);
00806       typedef typename ParallelMatrixHierarchy::ConstIterator Iterator;
00807       Iterator coarsest = matrices_.coarsest();
00808       int level=0;
00809       Dune::dvverb<<"Level "<<level<<" has "<<matrices_.finest()->getmat().N()<<" unknows!"<<std::endl;
00810       
00811       for(Iterator matrix = matrices_.finest(); matrix != coarsest;){
00812         ++matrix;
00813         ++level;
00814         Dune::dvverb<<"Level "<<level<<" has "<<matrix->getmat().N()<<" unknows!"<<std::endl;
00815         hierarchy.addCoarser(matrix->getmat().N());
00816       }
00817     }
00818     
00819     template<class M, class IS, class A>
00820     template<class S, class TA>
00821     void MatrixHierarchy<M,IS,A>::coarsenSmoother(Hierarchy<S,TA>& smoothers, 
00822                                                     const typename SmootherTraits<S>::Arguments& sargs) const
00823     {
00824       assert(smoothers.levels()==0);
00825       typedef typename ParallelMatrixHierarchy::ConstIterator MatrixIterator;
00826       typedef typename ParallelInformationHierarchy::ConstIterator PinfoIterator;
00827       typedef typename AggregatesMapList::const_iterator AggregatesIterator;
00828       
00829       typename ConstructionTraits<S>::Arguments cargs;
00830       cargs.setArgs(sargs);
00831       PinfoIterator pinfo = parallelInformation_.finest();
00832       AggregatesIterator aggregates = aggregatesMaps_.begin();
00833       for(MatrixIterator matrix = matrices_.finest(), coarsest = matrices_.coarsest(); 
00834           matrix != coarsest; ++matrix, ++pinfo, ++aggregates){
00835         cargs.setMatrix(matrix->getmat(), **aggregates);
00836         cargs.setComm(*pinfo);
00837         smoothers.addCoarser(cargs);
00838       }
00839     }
00840     
00841     template<class M, class IS, class A>
00842     template<class F>
00843     void MatrixHierarchy<M,IS,A>::recalculateGalerkin(const F& copyFlags)
00844     {
00845       typedef typename AggregatesMapList::iterator AggregatesMapIterator;
00846       typedef typename ParallelMatrixHierarchy::Iterator Iterator;
00847       typedef typename ParallelInformationHierarchy::Iterator InfoIterator;
00848       
00849       AggregatesMapIterator amap = aggregatesMaps_.begin();
00850       BaseGalerkinProduct productBuilder;
00851       InfoIterator info = parallelInformation_.finest();
00852       
00853       for(Iterator level = matrices_.finest(), coarsest=matrices_.coarsest(); level!=coarsest; ++amap){
00854         const Matrix& fine = level->getmat();
00855         ++level;
00856         ++info;
00857         productBuilder.calculate(fine, *(*amap), const_cast<Matrix&>(level->getmat()), *info, copyFlags);
00858         
00859       }
00860     }
00861 
00862     template<class M, class IS, class A>
00863     int MatrixHierarchy<M,IS,A>::levels() const
00864     {
00865       return matrices_.levels();
00866     }
00867 
00868     template<class M, class IS, class A>
00869     bool MatrixHierarchy<M,IS,A>::isBuilt() const
00870     {
00871       return built_;
00872     }
00873     
00874     template<class T, class A>
00875     Hierarchy<T,A>::Hierarchy()
00876       : finest_(0), coarsest_(0), nonAllocated_(0), allocator_(), levels_(0)
00877     {}
00878 
00879     template<class T, class A>
00880     Hierarchy<T,A>::Hierarchy(MemberType& first)
00881       : allocator_()
00882     {
00883       finest_ = allocator_.allocate(1,0);
00884       finest_->element_ = &first;
00885       finest_->redistributed_ = 0;
00886       nonAllocated_ = finest_;
00887       coarsest_ = finest_;
00888       coarsest_->coarser_ = coarsest_->finer_ = 0;
00889       levels_ = 1;
00890     }
00891 
00892     template<class T, class A>
00893     Hierarchy<T,A>::~Hierarchy()
00894     {
00895       while(coarsest_){
00896         Element* current = coarsest_;
00897         coarsest_ = coarsest_->finer_;
00898         if(current != nonAllocated_){
00899           ConstructionTraits<T>::deconstruct(current->element_);
00900         }
00901         allocator_.deallocate(current, 1);
00902         //coarsest_->coarser_ = 0;
00903       }
00904     }
00905 
00906     template<class T, class A>
00907     int Hierarchy<T,A>::levels() const
00908     {
00909       return levels_;
00910     }
00911 
00912     template<class T, class A>
00913     void Hierarchy<T,A>::addCoarser(Arguments& args)
00914     {
00915       if(!coarsest_){
00916         assert(!finest_);
00917         coarsest_ = allocator_.allocate(1,0);
00918         coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
00919         finest_ = coarsest_;
00920         coarsest_->finer_ = 0;
00921         coarsest_->redistributed_ = 0;
00922       }else{
00923         coarsest_->coarser_ = allocator_.allocate(1,0);
00924         coarsest_->coarser_->finer_ = coarsest_;
00925         coarsest_ = coarsest_->coarser_;
00926         coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
00927         finest_->redistributed_ = 0;
00928       }
00929       coarsest_->coarser_=0;
00930       ++levels_;
00931     }
00932     
00933     template<class T, class A>
00934     void Hierarchy<T,A>::addFiner(Arguments& args)
00935     {
00936       if(!finest_){
00937         assert(!coarsest_);
00938         finest_ = allocator_.allocate(1,0);
00939         finest_->element = ConstructionTraits<T>::construct(args);
00940         coarsest_ = finest_;
00941         coarsest_->coarser_ = coarsest_->finer_ = 0;
00942       }else{
00943         finest_->finer_ = allocator_.allocate(1,0);
00944         finest_->finer_->coarser_ = finest_;
00945         finest_ = finest_->finer_;
00946         finest_->finer = 0;
00947         finest_->element = ConstructionTraits<T>::construct(args);
00948       }
00949       ++levels_;
00950     }
00951 
00952     template<class T, class A>
00953     typename Hierarchy<T,A>::Iterator Hierarchy<T,A>::finest()
00954     {
00955       return Iterator(finest_);
00956     }
00957 
00958     template<class T, class A>
00959     typename Hierarchy<T,A>::Iterator Hierarchy<T,A>::coarsest()
00960     {
00961       return Iterator(coarsest_);
00962     }
00963 
00964     template<class T, class A>
00965     typename Hierarchy<T,A>::ConstIterator Hierarchy<T,A>::finest() const
00966     {
00967       return ConstIterator(finest_);
00968     }
00969 
00970     template<class T, class A>
00971     typename Hierarchy<T,A>::ConstIterator Hierarchy<T,A>::coarsest() const
00972     {
00973       return ConstIterator(coarsest_);
00974     }
00976   }// namespace Amg
00977 }// namespace Dune
00978 
00979 #endif

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