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 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
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
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 }
00935 }
00936
00937 #endif