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 Dune::Amg::AggregatesMap<typename MatrixGraph<Matrix>::VertexDescriptor> AggregatesMap;
00294
00296 typedef Dune::Amg::Hierarchy<MatrixOperator,Allocator> ParallelMatrixHierarchy;
00297
00299 typedef Dune::Amg::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 dune_static_assert((static_cast<int>(MatrixOperator::category) == static_cast<int>(SolverCategory::sequential) ||
00551 static_cast<int>(MatrixOperator::category) == static_cast<int>(SolverCategory::overlapping)),
00552 "MatrixOperator must be of category sequential or overlapping");
00553 dune_static_assert((static_cast<int>(MatrixOperator::category) == static_cast<int>(ParallelInformation::category)),
00554 "MatrixOperator and ParallelInformation must belong to the same category!");
00555 }
00556
00557 template<class M, class IS, class A>
00558 template<typename O, typename T>
00559 void MatrixHierarchy<M,IS,A>::build(const T& criterion)
00560 {
00561 typedef O OverlapFlags;
00562 typedef typename ParallelMatrixHierarchy::Iterator MatIterator;
00563 typedef typename ParallelInformationHierarchy::Iterator PInfoIterator;
00564
00565 GalerkinProduct<ParallelInformation> productBuilder;
00566 MatIterator mlevel = matrices_.finest();
00567 MatrixStats<typename M::matrix_type,MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL>::stats(mlevel->getmat());
00568
00569 PInfoIterator infoLevel = parallelInformation_.finest();
00570
00571
00572 int procs = infoLevel->communicator().size();
00573 int level = 0;
00574 int rank = 0;
00575 int unknowns = mlevel->getmat().N();;
00576
00577 unknowns = infoLevel->communicator().sum(unknowns);
00578 infoLevel->buildGlobalLookup(mlevel->getmat().N());
00579
00580 for(; level < criterion.maxLevel(); ++level, ++mlevel){
00581
00582 rank = infoLevel->communicator().rank();
00583 dverb<<infoLevel->communicator().rank()<<": Level "<<level<<" has "<<mlevel->getmat().N()<<" unknows!"<<std::endl;
00584 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00585 dinfo<<"Level "<<level<<" has "<<unknowns<<" unknowns, "<<unknowns/infoLevel->communicator().size()<<" unknowns per proc"<<std::endl;
00586
00587 if(unknowns <= criterion.coarsenTarget())
00588
00589 break;
00590
00591 typedef PropertiesGraphCreator<MatrixOperator> GraphCreator;
00592 typedef typename GraphCreator::PropertiesGraph PropertiesGraph;
00593 typedef typename GraphCreator::MatrixGraph MatrixGraph;
00594 typedef typename GraphCreator::GraphTuple GraphTuple;
00595
00596 typedef typename PropertiesGraph::VertexDescriptor Vertex;
00597
00598 std::vector<bool> excluded(mlevel->getmat().N(), false);
00599
00600 GraphTuple graphs = GraphCreator::create(*mlevel, excluded, *infoLevel, OverlapFlags());
00601
00602 AggregatesMap* aggregatesMap=new AggregatesMap(Element<1>::get(graphs)->maxVertex());
00603
00604 aggregatesMaps_.push_back(aggregatesMap);
00605
00606 Timer watch;
00607 watch.reset();
00608 int noAggregates, isoAggregates, oneAggregates;
00609
00610 tie(noAggregates, isoAggregates, oneAggregates) =
00611 aggregatesMap->buildAggregates(mlevel->getmat(), *(Element<1>::get(graphs)), criterion);
00612
00613 #ifdef TEST_AGGLO
00614 {
00615
00616 int start, end, overlapStart, overlapEnd;
00617 int n = UNKNOWNS/procs;
00618 int bigger = UNKNOWNS%procs;
00619 int procs=infoLevel->communicator().rank();
00620
00621
00622 if(rank<bigger){
00623 start = rank*(n+1);
00624 end = (rank+1)*(n+1);
00625 }else{
00626 start = bigger + rank * n;
00627 end = bigger + (rank + 1) * n;
00628 }
00629
00630
00631 if(start>0)
00632 overlapStart = start - 1;
00633 else
00634 overlapStart = start;
00635
00636 if(end<UNKNOWNS)
00637 overlapEnd = end + 1;
00638 else
00639 overlapEnd = end;
00640
00641 int noKnown = overlapEnd-overlapStart;
00642 int offset = start-overlapStart;
00643 int starti = 1;
00644 int endi = (overlapEnd-end==0)?end-start-1:end-start;
00645
00646 for(int j=1; j< UNKNOWNS-1; ++j)
00647 for(int i=starti; i < endi; ++i)
00648 (*aggregatesMap)[j*(overlapEnd-overlapStart)+i+offset]=((j-1)/2)*(endi-starti)/2+((i-starti)/2);
00649 noAggregates=((UNKNOWNS-2)/2)*(endi-starti)/2;
00650 }
00651 #endif
00652 noAggregates = infoLevel->communicator().sum(noAggregates);
00653
00654 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00655 dinfo << "Building "<<noAggregates<<" aggregates took "<<watch.elapsed()<<" seconds."<<std::endl;
00656
00657 if(!noAggregates || unknowns/noAggregates<criterion.minCoarsenRate())
00658 {
00659 if(procs>1 && criterion.accumulate())
00660 DUNE_THROW(NotImplemented, "Accumulation to fewer processes not yet implemented!");
00661 else{
00662 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL && rank==0)
00663 {
00664 if(noAggregates)
00665 dinfo << "Stopped coarsening because of rate breakdown "<<unknowns/noAggregates<<"<"
00666 <<criterion.minCoarsenRate()<<std::endl;
00667 else
00668 dinfo << "Could not build any aggregates. Probably no connected nodes."<<std::endl;
00669 }
00670 aggregatesMap->free();
00671 delete aggregatesMap;
00672 aggregatesMaps_.pop_back();
00673 break;
00674 }
00675 }
00676 unknowns = noAggregates;
00677
00678 if(noAggregates < criterion.coarsenTarget() && procs>1 && criterion.accumulate()){
00679 DUNE_THROW(NotImplemented, "Accumulation to fewer processes not yet implemented!");
00680 }
00681
00682 parallelInformation_.addCoarser(infoLevel->communicator());
00683
00684 PInfoIterator fineInfo = infoLevel++;
00685
00686 typename PropertyMapTypeSelector<VertexVisitedTag,PropertiesGraph>::Type visitedMap =
00687 get(VertexVisitedTag(), *(Element<1>::get(graphs)));
00688
00689 watch.reset();
00690 int aggregates = IndicesCoarsener<ParallelInformation,OverlapFlags>
00691 ::coarsen(*fineInfo,
00692 *(Element<1>::get(graphs)),
00693 visitedMap,
00694 *aggregatesMap,
00695 *infoLevel);
00696
00697 dinfo<< rank<<": agglomeration achieved "<<aggregates<<" aggregates"<<std::endl;
00698
00699 GraphCreator::free(graphs);
00700
00701 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00702 infoLevel->communicator().barrier();
00703 if(rank==0)
00704 dinfo<<"Coarsening of index sets took "<<watch.elapsed()<<" seconds."<<std::endl;
00705 }
00706
00707 watch.reset();
00708
00709 infoLevel->buildGlobalLookup(aggregates);
00710 AggregatesPublisher<Vertex,OverlapFlags,ParallelInformation>::publish(*aggregatesMap,
00711 *fineInfo,
00712 infoLevel->globalLookup());
00713
00714
00715 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00716 infoLevel->communicator().barrier();
00717 if(rank==0)
00718 dinfo<<"Communicating global aggregate numbers took "<<watch.elapsed()<<" seconds."<<std::endl;
00719 }
00720
00721 watch.reset();
00722 std::vector<bool>& visited=excluded;
00723
00724 typedef std::vector<bool>::iterator Iterator;
00725 typedef IteratorPropertyMap<Iterator, IdentityMap> VisitedMap2;
00726 Iterator end = visited.end();
00727 for(Iterator iter= visited.begin(); iter != end; ++iter)
00728 *iter=false;
00729
00730 VisitedMap2 visitedMap2(visited.begin(), Dune::IdentityMap());
00731
00732 typename MatrixOperator::matrix_type* coarseMatrix;
00733
00734 coarseMatrix = productBuilder.build(mlevel->getmat(), *(Element<0>::get(graphs)), visitedMap2,
00735 *fineInfo,
00736 *aggregatesMap,
00737 aggregates,
00738 OverlapFlags());
00739
00740 fineInfo->freeGlobalLookup();
00741
00742 delete Element<0>::get(graphs);
00743 productBuilder.calculate(mlevel->getmat(), *aggregatesMap, *coarseMatrix, *infoLevel, OverlapFlags());
00744
00745 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL){
00746 infoLevel->communicator().barrier();
00747 if(rank==0)
00748 dinfo<<"Calculation of Galerkin product took "<<watch.elapsed()<<" seconds."<<std::endl;
00749 }
00750
00751 MatrixArgs args(*coarseMatrix, *infoLevel);
00752
00753 matrices_.addCoarser(args);
00754 }
00755
00756 infoLevel->freeGlobalLookup();
00757
00758 built_=true;
00759 AggregatesMap* aggregatesMap=new AggregatesMap(0);
00760 aggregatesMaps_.push_back(aggregatesMap);
00761
00762 if(MINIMAL_DEBUG_LEVEL>=INFO_DEBUG_LEVEL)
00763 if(level==criterion.maxLevel()){
00764 int unknowns = mlevel->getmat().N();
00765 unknowns = infoLevel->communicator().sum(unknowns);
00766 if(rank==0)
00767 dinfo<<"Level "<<level<<" has "<<unknowns<<" unknowns, "<<unknowns/infoLevel->communicator().size()<<" unknowns per proc"<<std::endl;
00768 }
00769 }
00770
00771 template<class M, class IS, class A>
00772 const typename MatrixHierarchy<M,IS,A>::ParallelMatrixHierarchy&
00773 MatrixHierarchy<M,IS,A>::matrices() const
00774 {
00775 return matrices_;
00776 }
00777
00778 template<class M, class IS, class A>
00779 const typename MatrixHierarchy<M,IS,A>::ParallelInformationHierarchy&
00780 MatrixHierarchy<M,IS,A>::parallelInformation() const
00781 {
00782 return parallelInformation_;
00783 }
00784
00785 template<class M, class IS, class A>
00786 const typename MatrixHierarchy<M,IS,A>::AggregatesMapList&
00787 MatrixHierarchy<M,IS,A>::aggregatesMaps() const
00788 {
00789 return aggregatesMaps_;
00790 }
00791 template<class M, class IS, class A>
00792 MatrixHierarchy<M,IS,A>::~MatrixHierarchy()
00793 {
00794 typedef typename AggregatesMapList::reverse_iterator AggregatesMapIterator;
00795 typedef typename ParallelMatrixHierarchy::Iterator Iterator;
00796 typedef typename ParallelInformationHierarchy::Iterator InfoIterator;
00797
00798 AggregatesMapIterator amap = aggregatesMaps_.rbegin();
00799 InfoIterator info = parallelInformation_.coarsest();
00800 for(Iterator level=matrices_.coarsest(), finest=matrices_.finest(); level != finest; --level, --info, ++amap){
00801 (*amap)->free();
00802 delete *amap;
00803 delete &level->getmat();
00804 }
00805 delete *amap;
00806 }
00807
00808 template<class M, class IS, class A>
00809 template<class V, class TA>
00810 void MatrixHierarchy<M,IS,A>::coarsenVector(Hierarchy<BlockVector<V,TA> >& hierarchy) const
00811 {
00812 assert(hierarchy.levels()==1);
00813 typedef typename ParallelMatrixHierarchy::ConstIterator Iterator;
00814 Iterator coarsest = matrices_.coarsest();
00815 int level=0;
00816 Dune::dvverb<<"Level "<<level<<" has "<<matrices_.finest()->getmat().N()<<" unknows!"<<std::endl;
00817
00818 for(Iterator matrix = matrices_.finest(); matrix != coarsest;){
00819 ++matrix;
00820 ++level;
00821 Dune::dvverb<<"Level "<<level<<" has "<<matrix->getmat().N()<<" unknows!"<<std::endl;
00822 hierarchy.addCoarser(matrix->getmat().N());
00823 }
00824 }
00825
00826 template<class M, class IS, class A>
00827 template<class S, class TA>
00828 void MatrixHierarchy<M,IS,A>::coarsenSmoother(Hierarchy<S,TA>& smoothers,
00829 const typename SmootherTraits<S>::Arguments& sargs) const
00830 {
00831 assert(smoothers.levels()==0);
00832 typedef typename ParallelMatrixHierarchy::ConstIterator MatrixIterator;
00833 typedef typename ParallelInformationHierarchy::ConstIterator PinfoIterator;
00834 typedef typename AggregatesMapList::const_iterator AggregatesIterator;
00835
00836 typename ConstructionTraits<S>::Arguments cargs;
00837 cargs.setArgs(sargs);
00838 PinfoIterator pinfo = parallelInformation_.finest();
00839 AggregatesIterator aggregates = aggregatesMaps_.begin();
00840 for(MatrixIterator matrix = matrices_.finest(), coarsest = matrices_.coarsest();
00841 matrix != coarsest; ++matrix, ++pinfo, ++aggregates){
00842 cargs.setMatrix(matrix->getmat(), **aggregates);
00843 cargs.setComm(*pinfo);
00844 smoothers.addCoarser(cargs);
00845 }
00846 }
00847
00848 template<class M, class IS, class A>
00849 template<class F>
00850 void MatrixHierarchy<M,IS,A>::recalculateGalerkin(const F& copyFlags)
00851 {
00852 typedef typename AggregatesMapList::iterator AggregatesMapIterator;
00853 typedef typename ParallelMatrixHierarchy::Iterator Iterator;
00854 typedef typename ParallelInformationHierarchy::Iterator InfoIterator;
00855
00856 AggregatesMapIterator amap = aggregatesMaps_.begin();
00857 BaseGalerkinProduct productBuilder;
00858 InfoIterator info = parallelInformation_.finest();
00859
00860 for(Iterator level = matrices_.finest(), coarsest=matrices_.coarsest(); level!=coarsest; ++amap){
00861 const Matrix& fine = level->getmat();
00862 ++level;
00863 ++info;
00864 productBuilder.calculate(fine, *(*amap), const_cast<Matrix&>(level->getmat()), *info, copyFlags);
00865
00866 }
00867 }
00868
00869 template<class M, class IS, class A>
00870 int MatrixHierarchy<M,IS,A>::levels() const
00871 {
00872 return matrices_.levels();
00873 }
00874
00875 template<class M, class IS, class A>
00876 bool MatrixHierarchy<M,IS,A>::isBuilt() const
00877 {
00878 return built_;
00879 }
00880
00881 template<class T, class A>
00882 Hierarchy<T,A>::Hierarchy()
00883 : finest_(0), coarsest_(0), nonAllocated_(0), allocator_(), levels_(0)
00884 {}
00885
00886 template<class T, class A>
00887 Hierarchy<T,A>::Hierarchy(MemberType& first)
00888 : allocator_()
00889 {
00890 finest_ = allocator_.allocate(1,0);
00891 finest_->element_ = &first;
00892 finest_->redistributed_ = 0;
00893 nonAllocated_ = finest_;
00894 coarsest_ = finest_;
00895 coarsest_->coarser_ = coarsest_->finer_ = 0;
00896 levels_ = 1;
00897 }
00898
00899 template<class T, class A>
00900 Hierarchy<T,A>::~Hierarchy()
00901 {
00902 while(coarsest_){
00903 Element* current = coarsest_;
00904 coarsest_ = coarsest_->finer_;
00905 if(current != nonAllocated_){
00906 ConstructionTraits<T>::deconstruct(current->element_);
00907 }
00908 allocator_.deallocate(current, 1);
00909
00910 }
00911 }
00912
00913 template<class T, class A>
00914 int Hierarchy<T,A>::levels() const
00915 {
00916 return levels_;
00917 }
00918
00919 template<class T, class A>
00920 void Hierarchy<T,A>::addCoarser(Arguments& args)
00921 {
00922 if(!coarsest_){
00923 assert(!finest_);
00924 coarsest_ = allocator_.allocate(1,0);
00925 coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
00926 finest_ = coarsest_;
00927 coarsest_->finer_ = 0;
00928 coarsest_->redistributed_ = 0;
00929 }else{
00930 coarsest_->coarser_ = allocator_.allocate(1,0);
00931 coarsest_->coarser_->finer_ = coarsest_;
00932 coarsest_ = coarsest_->coarser_;
00933 coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
00934 finest_->redistributed_ = 0;
00935 }
00936 coarsest_->coarser_=0;
00937 ++levels_;
00938 }
00939
00940 template<class T, class A>
00941 void Hierarchy<T,A>::addFiner(Arguments& args)
00942 {
00943 if(!finest_){
00944 assert(!coarsest_);
00945 finest_ = allocator_.allocate(1,0);
00946 finest_->element = ConstructionTraits<T>::construct(args);
00947 coarsest_ = finest_;
00948 coarsest_->coarser_ = coarsest_->finer_ = 0;
00949 }else{
00950 finest_->finer_ = allocator_.allocate(1,0);
00951 finest_->finer_->coarser_ = finest_;
00952 finest_ = finest_->finer_;
00953 finest_->finer = 0;
00954 finest_->element = ConstructionTraits<T>::construct(args);
00955 }
00956 ++levels_;
00957 }
00958
00959 template<class T, class A>
00960 typename Hierarchy<T,A>::Iterator Hierarchy<T,A>::finest()
00961 {
00962 return Iterator(finest_);
00963 }
00964
00965 template<class T, class A>
00966 typename Hierarchy<T,A>::Iterator Hierarchy<T,A>::coarsest()
00967 {
00968 return Iterator(coarsest_);
00969 }
00970
00971 template<class T, class A>
00972 typename Hierarchy<T,A>::ConstIterator Hierarchy<T,A>::finest() const
00973 {
00974 return ConstIterator(finest_);
00975 }
00976
00977 template<class T, class A>
00978 typename Hierarchy<T,A>::ConstIterator Hierarchy<T,A>::coarsest() const
00979 {
00980 return ConstIterator(coarsest_);
00981 }
00983 }
00984 }
00985
00986 #endif