00001
00002 #ifndef DUNE_INDEXSET_HH
00003 #define DUNE_INDEXSET_HH
00004
00005 #include<algorithm>
00006 #include<dune/common/arraylist.hh>
00007 #include<dune/common/exceptions.hh>
00008 #include<iostream>
00009
00010 #include"localindex.hh"
00011
00012 #include <stdint.h>
00013
00014 namespace Dune
00015 {
00025
00026
00027 template<class TG, class TL>
00028 class IndexPair;
00029
00035 template<class TG, class TL>
00036 std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair);
00037
00038 template<class TG, class TL>
00039 bool operator==(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00040
00041 template<class TG, class TL>
00042 bool operator!=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00043
00044 template<class TG, class TL>
00045 bool operator<(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00046
00047 template<class TG, class TL>
00048 bool operator>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00049
00050 template<class TG, class TL>
00051 bool operator<=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00052
00053 template<class TG, class TL>
00054 bool operator >=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00055
00056 template<class TG, class TL>
00057 bool operator==(const IndexPair<TG,TL>&, const TG&);
00058
00059 template<class TG, class TL>
00060 bool operator!=(const IndexPair<TG,TL>&, const TG&);
00061
00062 template<class TG, class TL>
00063 bool operator<(const IndexPair<TG,TL>&, const TG&);
00064
00065 template<class TG, class TL>
00066 bool operator>(const IndexPair<TG,TL>&, const TG&);
00067
00068 template<class TG, class TL>
00069 bool operator<=(const IndexPair<TG,TL>&, const TG&);
00070
00071 template<class TG, class TL>
00072 bool operator >=(const IndexPair<TG,TL>&, const TG&);
00073
00074 template<typename T>
00075 class MPITraits;
00076
00080 template<class TG, class TL>
00081 class IndexPair
00082 {
00083 friend std::ostream& operator<<<>(std::ostream&, const IndexPair<TG,TL>&);
00084 friend bool operator==<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00085 friend bool operator!=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00086 friend bool operator< <>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00087 friend bool operator><>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00088 friend bool operator<=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00089 friend bool operator>=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
00090 friend bool operator==<>(const IndexPair<TG,TL>&, const TG&);
00091 friend bool operator!=<>(const IndexPair<TG,TL>&, const TG&);
00092 friend bool operator< <>(const IndexPair<TG,TL>&, const TG&);
00093 friend bool operator> <>(const IndexPair<TG,TL>&, const TG&);
00094 friend bool operator<=<>(const IndexPair<TG,TL>&, const TG&);
00095 friend bool operator>=<>(const IndexPair<TG,TL>&, const TG&);
00096 friend class MPITraits<IndexPair<TG,TL> >;
00097
00098 public:
00104 typedef TG GlobalIndex;
00105
00117 typedef TL LocalIndex;
00118
00125 IndexPair(const GlobalIndex& global, const LocalIndex& local);
00126
00130 IndexPair();
00137 IndexPair(const GlobalIndex& global);
00138
00144 inline const GlobalIndex& global() const;
00145
00151 inline LocalIndex& local();
00152
00158 inline const LocalIndex& local()const;
00159
00165 inline void setLocal(int index);
00166 private:
00168 GlobalIndex global_;
00170 LocalIndex local_;
00171 };
00172
00177 enum ParallelIndexSetState
00178 {
00183 GROUND,
00187 RESIZE
00197 };
00198
00202 class InvalidIndexSetState: public Exception{};
00203
00204
00205 template<class I> class GlobalLookupIndexSet;
00206
00213 template<typename TG, typename TL, int N=100>
00214 class ParallelIndexSet
00215 {
00216 friend class GlobalLookupIndexSet<ParallelIndexSet<TG,TL,N> >;
00217
00218 public:
00223 typedef TG GlobalIndex;
00224
00236 typedef TL LocalIndex;
00237
00241 typedef Dune::IndexPair<GlobalIndex,LocalIndex> IndexPair;
00242
00243 enum{
00250 arraySize= (N>0)?N:1
00251 };
00252
00254 class iterator :
00255 public ArrayList<IndexPair,N>::iterator
00256 {
00257 typedef typename ArrayList<IndexPair,N>::iterator
00258 Father;
00259 friend class ParallelIndexSet<GlobalIndex,LocalIndex,N>;
00260 public:
00261 iterator(ParallelIndexSet<TG,TL,N>& indexSet, const Father& father)
00262 : Father(father), indexSet_(&indexSet)
00263 {}
00264
00265 iterator(const iterator& other)
00266 : Father(other), indexSet_(other.indexSet_)
00267 {}
00268
00269 iterator& operator==(const iterator& other)
00270 {
00271 Father::operator==(other);
00272 indexSet_ = other.indexSet_;
00273 }
00274
00275 private:
00283 inline void markAsDeleted() const throw(InvalidIndexSetState)
00284 {
00285 #ifndef NDEBUG
00286 if(indexSet_->state_ != RESIZE)
00287 DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
00288 <<"while in RESIZE state!");
00289 #endif
00290 Father::operator*().local().setState(DELETED);
00291 }
00292
00294 ParallelIndexSet<TG,TL,N>* indexSet_;
00295
00296 };
00297
00298
00299
00301 typedef typename
00302 ArrayList<IndexPair,N>::const_iterator
00303 const_iterator;
00304
00308 ParallelIndexSet();
00309
00314 inline const ParallelIndexSetState& state();
00315
00321 void beginResize() throw(InvalidIndexSetState);
00322
00331 inline void add(const GlobalIndex& global) throw(InvalidIndexSetState);
00332
00341 inline void add(const GlobalIndex& global, const LocalIndex& local)
00342 throw(InvalidIndexSetState);
00343
00351 inline void markAsDeleted(const iterator& position)
00352 throw(InvalidIndexSetState);
00353
00366 void endResize() throw(InvalidIndexSetState);
00367
00378 inline IndexPair&
00379 operator[](const GlobalIndex& global);
00380
00390 inline IndexPair&
00391 at(const GlobalIndex& global);
00392
00403 inline const IndexPair&
00404 operator[](const GlobalIndex& global) const;
00405
00415 inline const IndexPair&
00416 at(const GlobalIndex& global) const;
00417
00422 inline iterator begin();
00423
00428 inline iterator end();
00429
00434 inline const_iterator begin() const;
00435
00440 inline const_iterator end() const;
00441
00451 inline void renumberLocal();
00452
00459 inline int seqNo() const;
00460
00465 inline size_t size() const;
00466
00467 private:
00469 ArrayList<IndexPair,N> localIndices_;
00471 ArrayList<IndexPair,N> newIndices_;
00473 ParallelIndexSetState state_;
00475 int seqNo_;
00477 bool deletedEntries_;
00482 inline void merge();
00483 };
00484
00485
00491 template<class TG, class TL, int N>
00492 std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet);
00493
00499 template<class I>
00500 class GlobalLookupIndexSet
00501 {
00502 public:
00506 typedef I ParallelIndexSet;
00507
00511 typedef typename ParallelIndexSet::LocalIndex LocalIndex;
00512
00516 typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
00517
00521 typedef typename ParallelIndexSet::const_iterator const_iterator;
00522
00523 typedef Dune::IndexPair<typename I::GlobalIndex, typename I::LocalIndex> IndexPair;
00524
00531 GlobalLookupIndexSet(const ParallelIndexSet& indexset, std::size_t size);
00532
00538 GlobalLookupIndexSet(const ParallelIndexSet& indexset);
00539
00543 ~GlobalLookupIndexSet();
00544
00554 inline const IndexPair&
00555 operator[](const GlobalIndex& global) const;
00556
00560 inline const IndexPair*
00561 pair(const std::size_t& local) const;
00562
00567 inline const_iterator begin() const;
00568
00573 inline const_iterator end() const;
00574
00581 inline int seqNo() const;
00582
00587 inline size_t size() const;
00588 private:
00592 const ParallelIndexSet& indexSet_;
00593
00597 std::size_t size_;
00598
00602 std::vector<const IndexPair*> indices_;
00603
00604 };
00605
00606
00607 template<class TG, class TL>
00608 inline std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair)
00609 {
00610 os<<"{global="<<pair.global_<<", local="<<pair.local_<<"}";
00611 return os;
00612 }
00613
00614 template<class TG, class TL, int N>
00615 inline std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet)
00616 {
00617 typedef typename ParallelIndexSet<TG,TL,N>::const_iterator Iterator;
00618 Iterator end = indexSet.end();
00619 os<<"{";
00620 for(Iterator index = indexSet.begin(); index != end; ++index)
00621 os<<*index<<" ";
00622 os<<"}";
00623 return os;
00624
00625 }
00626
00627 template<class TG, class TL>
00628 inline bool operator==(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00629 {
00630 return a.global_==b.global_;
00631 }
00632
00633 template<class TG, class TL>
00634 inline bool operator!=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00635 {
00636 return a.global_!=b.global_;
00637 }
00638
00639 template<class TG, class TL>
00640 inline bool operator<(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00641 {
00642 return a.global_<b.global_;
00643 }
00644
00645 template<class TG, class TL>
00646 inline bool operator>(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00647 {
00648 return a.global_>b.global_;
00649 }
00650
00651 template<class TG, class TL>
00652 inline bool operator<=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00653 {
00654 return a.global_<=b.global_;
00655 }
00656
00657 template<class TG, class TL>
00658 inline bool operator >=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00659 {
00660 return a.global_>=b.global_;
00661 }
00662
00663 template<class TG, class TL>
00664 inline bool operator==(const IndexPair<TG,TL>& a, const TG& b)
00665 {
00666 return a.global_==b;
00667 }
00668
00669 template<class TG, class TL>
00670 inline bool operator!=(const IndexPair<TG,TL>& a, const TG& b)
00671 {
00672 return a.global_!=b;
00673 }
00674
00675 template<class TG, class TL>
00676 inline bool operator<(const IndexPair<TG,TL>& a, const TG& b)
00677 {
00678 return a.global_<b;
00679 }
00680
00681 template<class TG, class TL>
00682 inline bool operator>(const IndexPair<TG,TL>& a, const TG& b)
00683 {
00684 return a.global_>b;
00685 }
00686
00687 template<class TG, class TL>
00688 inline bool operator<=(const IndexPair<TG,TL>& a, const TG& b)
00689 {
00690 return a.global_<=b;
00691 }
00692
00693 template<class TG, class TL>
00694 inline bool operator >=(const IndexPair<TG,TL>& a, const TG& b)
00695 {
00696 return a.global_>=b;
00697 }
00698
00699 #ifndef DOXYGEN
00700
00701 template<class TG, class TL>
00702 IndexPair<TG,TL>::IndexPair(const TG& global, const TL& local)
00703 : global_(global), local_(local){}
00704
00705 template<class TG, class TL>
00706 IndexPair<TG,TL>::IndexPair(const TG& global)
00707 : global_(global), local_(){}
00708
00709 template<class TG, class TL>
00710 IndexPair<TG,TL>::IndexPair()
00711 : global_(), local_(){}
00712
00713 template<class TG, class TL>
00714 inline const TG& IndexPair<TG,TL>::global() const{
00715 return global_;
00716 }
00717
00718 template<class TG, class TL>
00719 inline TL& IndexPair<TG,TL>::local() {
00720 return local_;
00721 }
00722
00723 template<class TG, class TL>
00724 inline const TL& IndexPair<TG,TL>::local() const{
00725 return local_;
00726 }
00727
00728 template<class TG, class TL>
00729 inline void IndexPair<TG,TL>::setLocal(int local){
00730 local_=local;
00731 }
00732
00733 template<class TG, class TL, int N>
00734 ParallelIndexSet<TG,TL,N>::ParallelIndexSet()
00735 : state_(GROUND), seqNo_(0)
00736 {}
00737
00738 template<class TG, class TL, int N>
00739 void ParallelIndexSet<TG,TL,N>::beginResize() throw(InvalidIndexSetState)
00740 {
00741
00742
00743 #ifndef NDEBUG
00744 if(state_!=GROUND)
00745 DUNE_THROW(InvalidIndexSetState,
00746 "IndexSet has to be in GROUND state, when "
00747 << "beginResize() is called!");
00748 #endif
00749
00750 state_ = RESIZE;
00751 deletedEntries_ = false;
00752 }
00753
00754 template<class TG, class TL, int N>
00755 inline void ParallelIndexSet<TG,TL,N>::add(const GlobalIndex& global)
00756 throw(InvalidIndexSetState)
00757 {
00758
00759 #ifndef NDEBUG
00760 if(state_ != RESIZE)
00761 DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
00762 <<"while in RESIZE state!");
00763 #endif
00764 newIndices_.push_back(IndexPair(global));
00765 }
00766
00767 template<class TG, class TL, int N>
00768 inline void ParallelIndexSet<TG,TL,N>::add(const TG& global, const TL& local)
00769 throw(InvalidIndexSetState)
00770 {
00771
00772 #ifndef NDEBUG
00773 if(state_ != RESIZE)
00774 DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
00775 <<"while in RESIZE state!");
00776 #endif
00777 newIndices_.push_back(IndexPair(global,local));
00778 }
00779
00780 template<class TG, class TL, int N>
00781 inline void ParallelIndexSet<TG,TL,N>::markAsDeleted(const iterator& global)
00782 throw(InvalidIndexSetState){
00783
00784 #ifndef NDEBUG
00785 if(state_ != RESIZE)
00786 DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
00787 <<"while in RESIZE state!");
00788 #endif
00789 deletedEntries_ = true;
00790
00791 global.markAsDeleted();
00792 }
00793
00794 template<class TG, class TL, int N>
00795 void ParallelIndexSet<TG,TL,N>::endResize() throw(InvalidIndexSetState){
00796
00797 #ifndef NDEBUG
00798 if(state_ != RESIZE)
00799 DUNE_THROW(InvalidIndexSetState, "endResize called while not "
00800 <<"in RESIZE state!");
00801 #endif
00802
00803 std::sort(newIndices_.begin(), newIndices_.end());
00804 merge();
00805 seqNo_++;
00806 state_ = GROUND;
00807 }
00808
00809
00810 template<class TG, class TL, int N>
00811 inline void ParallelIndexSet<TG,TL,N>::merge(){
00812 if(localIndices_.size()==0)
00813 {
00814 localIndices_=newIndices_;
00815 newIndices_.clear();
00816 }
00817 else if(newIndices_.size()>0 || deletedEntries_)
00818 {
00819 ArrayList<IndexPair,N> tempPairs;
00820 typedef typename ArrayList<IndexPair,N>::iterator iterator;
00821 typedef typename ArrayList<IndexPair,N>::const_iterator const_iterator;
00822
00823 iterator old=localIndices_.begin();
00824 iterator added=newIndices_.begin();
00825 const const_iterator endold=localIndices_.end();
00826 const const_iterator endadded=newIndices_.end();
00827
00828 while(old != endold && added!= endadded)
00829 {
00830 if(old->local().state()==DELETED){
00831 old.eraseToHere();
00832 }
00833 else if(old->global() < added->global())
00834 {
00835 tempPairs.push_back(*old);
00836 old.eraseToHere();
00837 }
00838 else if(old->global() == added->global()){
00839
00840 assert(old->local()==added->local());
00841 old.eraseToHere();
00842 }
00843 else
00844 {
00845 tempPairs.push_back(*added);
00846 added.eraseToHere();
00847 }
00848 }
00849
00850 while(old != endold)
00851 {
00852 if(old->local().state()!=DELETED){
00853 tempPairs.push_back(*old);
00854 }
00855 old.eraseToHere();
00856 }
00857
00858 while(added!= endadded)
00859 {
00860 tempPairs.push_back(*added);
00861 added.eraseToHere();
00862 }
00863 localIndices_ = tempPairs;
00864 }
00865 }
00866
00867
00868 template<class TG, class TL, int N>
00869 inline const IndexPair<TG,TL>&
00870 ParallelIndexSet<TG,TL,N>::at(const TG& global) const
00871 {
00872
00873 int low=0, high=localIndices_.size()-1, probe=-1;
00874
00875 while(low<high)
00876 {
00877 probe = (high + low) / 2;
00878 if(global <= localIndices_[probe].global())
00879 high = probe;
00880 else
00881 low = probe+1;
00882 }
00883
00884 if(probe==-1)
00885 DUNE_THROW(RangeError, "No entries!");
00886
00887 if( localIndices_[low].global() != global)
00888 DUNE_THROW(RangeError, "Could not find entry of "<<global);
00889 else
00890 return localIndices_[low];
00891 }
00892
00893 template<class TG, class TL, int N>
00894 inline const IndexPair<TG,TL>&
00895 ParallelIndexSet<TG,TL,N>::operator[](const TG& global) const
00896 {
00897
00898 int low=0, high=localIndices_.size()-1, probe=-1;
00899
00900 while(low<high)
00901 {
00902 probe = (high + low) / 2;
00903 if(global <= localIndices_[probe].global())
00904 high = probe;
00905 else
00906 low = probe+1;
00907 }
00908
00909 return localIndices_[low];
00910 }
00911 template<class TG, class TL, int N>
00912 inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::at(const TG& global)
00913 {
00914
00915 int low=0, high=localIndices_.size()-1, probe=-1;
00916
00917 while(low<high)
00918 {
00919 probe = (high + low) / 2;
00920 if(localIndices_[probe].global() >= global)
00921 high = probe;
00922 else
00923 low = probe+1;
00924 }
00925
00926 if(probe==-1)
00927 DUNE_THROW(RangeError, "No entries!");
00928
00929 if( localIndices_[low].global() != global)
00930 DUNE_THROW(RangeError, "Could not find entry of "<<global);
00931 else
00932 return localIndices_[low];
00933 }
00934
00935 template<class TG, class TL, int N>
00936 inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::operator[](const TG& global)
00937 {
00938
00939 int low=0, high=localIndices_.size()-1, probe=-1;
00940
00941 while(low<high)
00942 {
00943 probe = (high + low) / 2;
00944 if(localIndices_[probe].global() >= global)
00945 high = probe;
00946 else
00947 low = probe+1;
00948 }
00949
00950 return localIndices_[low];
00951 }
00952 template<class TG, class TL, int N>
00953 inline typename ParallelIndexSet<TG,TL,N>::iterator
00954 ParallelIndexSet<TG,TL,N>::begin()
00955 {
00956 return iterator(*this, localIndices_.begin());
00957 }
00958
00959
00960 template<class TG, class TL, int N>
00961 inline typename ParallelIndexSet<TG,TL,N>::iterator
00962 ParallelIndexSet<TG,TL,N>::end()
00963 {
00964 return iterator(*this,localIndices_.end());
00965 }
00966
00967 template<class TG, class TL, int N>
00968 inline typename ParallelIndexSet<TG,TL,N>::const_iterator
00969 ParallelIndexSet<TG,TL,N>::begin() const
00970 {
00971 return localIndices_.begin();
00972 }
00973
00974
00975 template<class TG, class TL, int N>
00976 inline typename ParallelIndexSet<TG,TL,N>::const_iterator
00977 ParallelIndexSet<TG,TL,N>::end() const
00978 {
00979 return localIndices_.end();
00980 }
00981
00982 template<class TG, class TL, int N>
00983 void ParallelIndexSet<TG,TL,N>::renumberLocal(){
00984 #ifndef NDEBUG
00985 if(state_==RESIZE)
00986 DUNE_THROW(InvalidIndexSetState, "IndexSet has to be in "
00987 <<"GROUND state for renumberLocal()");
00988 #endif
00989
00990 typedef typename ArrayList<IndexPair,N>::iterator iterator;
00991 const const_iterator end_ = end();
00992 uint32_t index=0;
00993
00994 for(iterator pair=begin(); pair!=end_; index++, ++pair)
00995 pair->local()=index;
00996 }
00997
00998 template<class TG, class TL, int N>
00999 inline int ParallelIndexSet<TG,TL,N>::seqNo() const
01000 {
01001 return seqNo_;
01002 }
01003
01004 template<class TG, class TL, int N>
01005 inline size_t ParallelIndexSet<TG,TL,N>::size() const
01006 {
01007 return localIndices_.size();
01008 }
01009
01010 template<class I>
01011 GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset,
01012 std::size_t size)
01013 : indexSet_(indexset), size_(size),
01014 indices_(size_, static_cast<const IndexPair*>(0))
01015 {
01016 const_iterator end_ = indexSet_.end();
01017
01018 for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair){
01019 assert(pair->local()<size_);
01020 indices_[pair->local()] = &(*pair);
01021 }
01022 }
01023
01024 template<class I>
01025 GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset)
01026 : indexSet_(indexset), size_(0)
01027 {
01028 const_iterator end_ = indexSet_.end();
01029 for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
01030 size_=std::max(size_,static_cast<std::size_t>(pair->local()));
01031
01032 indices_.resize(++size_, 0);
01033
01034 for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
01035 indices_[pair->local()] = &(*pair);
01036 }
01037
01038 template<class I>
01039 GlobalLookupIndexSet<I>::~GlobalLookupIndexSet()
01040 {}
01041
01042 template<class I>
01043 inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>*
01044 GlobalLookupIndexSet<I>::pair(const std::size_t& local) const
01045 {
01046 return indices_[local];
01047 }
01048
01049 template<class I>
01050 inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>&
01051 GlobalLookupIndexSet<I>::operator[](const GlobalIndex& global) const
01052 {
01053 return indexSet_[global];
01054 }
01055
01056 template<class I>
01057 typename I::const_iterator GlobalLookupIndexSet<I>::begin() const
01058 {
01059 return indexSet_.begin();
01060 }
01061
01062 template<class I>
01063 typename I::const_iterator GlobalLookupIndexSet<I>::end() const
01064 {
01065 return indexSet_.end();
01066 }
01067
01068 template<class I>
01069 inline size_t GlobalLookupIndexSet<I>::size() const
01070 {
01071 return size_;
01072 }
01073
01074 template<class I>
01075 inline int GlobalLookupIndexSet<I>::seqNo() const
01076 {
01077 return indexSet_.seqNo();
01078 }
01079
01080 #endif // DOXYGEN
01081
01082 }
01083 #endif