00001
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
00083
00084
00085
00086
00087
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
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
00614 int start, end, overlapStart, overlapEnd;
00615 int n = UNKNOWNS/procs;
00616 int bigger = UNKNOWNS%procs;
00617 int procs=infoLevel->communicator().rank();
00618
00619
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
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;
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
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 }
00977 }
00978
00979 #endif