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
00365 void endResize() throw(InvalidIndexSetState);
00366
00376 inline IndexPair&
00377 operator[](const GlobalIndex& global);
00378
00379
00389 inline const IndexPair&
00390 operator[](const GlobalIndex& global) const;
00391
00396 inline iterator begin();
00397
00402 inline iterator end();
00403
00408 inline const_iterator begin() const;
00409
00414 inline const_iterator end() const;
00415
00425 inline void renumberLocal();
00426
00433 inline int seqNo() const;
00434
00439 inline size_t size() const;
00440
00441 private:
00443 ArrayList<IndexPair,N> localIndices_;
00445 ArrayList<IndexPair,N> newIndices_;
00447 ParallelIndexSetState state_;
00449 int seqNo_;
00451 bool deletedEntries_;
00456 inline void merge();
00457 };
00458
00459
00465 template<class TG, class TL, int N>
00466 std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet);
00467
00473 template<class I>
00474 class GlobalLookupIndexSet
00475 {
00476 public:
00480 typedef I ParallelIndexSet;
00481
00485 typedef typename ParallelIndexSet::LocalIndex LocalIndex;
00486
00490 typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
00491
00495 typedef typename ParallelIndexSet::const_iterator const_iterator;
00496
00497 typedef Dune::IndexPair<typename I::GlobalIndex, typename I::LocalIndex> IndexPair;
00498
00505 GlobalLookupIndexSet(const ParallelIndexSet& indexset, std::size_t size);
00506
00512 GlobalLookupIndexSet(const ParallelIndexSet& indexset);
00513
00517 ~GlobalLookupIndexSet();
00518
00528 inline const IndexPair&
00529 operator[](const GlobalIndex& global) const;
00530
00534 inline const IndexPair*
00535 pair(const std::size_t& local) const;
00536
00541 inline const_iterator begin() const;
00542
00547 inline const_iterator end() const;
00548
00555 inline int seqNo() const;
00556
00561 inline size_t size() const;
00562 private:
00566 const ParallelIndexSet& indexSet_;
00567
00571 std::size_t size_;
00572
00576 std::vector<const IndexPair*> indices_;
00577
00578 };
00579
00580
00581 template<class TG, class TL>
00582 inline std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair)
00583 {
00584 os<<"{global="<<pair.global_<<", local="<<pair.local_<<"}";
00585 return os;
00586 }
00587
00588 template<class TG, class TL, int N>
00589 inline std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet)
00590 {
00591 typedef typename ParallelIndexSet<TG,TL,N>::const_iterator Iterator;
00592 Iterator end = indexSet.end();
00593 os<<"{";
00594 for(Iterator index = indexSet.begin(); index != end; ++index)
00595 os<<*index<<" ";
00596 os<<"}";
00597 return os;
00598
00599 }
00600
00601 template<class TG, class TL>
00602 inline bool operator==(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00603 {
00604 return a.global_==b.global_;
00605 }
00606
00607 template<class TG, class TL>
00608 inline bool operator!=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00609 {
00610 return a.global_!=b.global_;
00611 }
00612
00613 template<class TG, class TL>
00614 inline bool operator<(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00615 {
00616 return a.global_<b.global_;
00617 }
00618
00619 template<class TG, class TL>
00620 inline bool operator>(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00621 {
00622 return a.global_>b.global_;
00623 }
00624
00625 template<class TG, class TL>
00626 inline bool operator<=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00627 {
00628 return a.global_<=b.global_;
00629 }
00630
00631 template<class TG, class TL>
00632 inline bool operator >=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
00633 {
00634 return a.global_>=b.global_;
00635 }
00636
00637 template<class TG, class TL>
00638 inline bool operator==(const IndexPair<TG,TL>& a, const TG& b)
00639 {
00640 return a.global_==b;
00641 }
00642
00643 template<class TG, class TL>
00644 inline bool operator!=(const IndexPair<TG,TL>& a, const TG& b)
00645 {
00646 return a.global_!=b;
00647 }
00648
00649 template<class TG, class TL>
00650 inline bool operator<(const IndexPair<TG,TL>& a, const TG& b)
00651 {
00652 return a.global_<b;
00653 }
00654
00655 template<class TG, class TL>
00656 inline bool operator>(const IndexPair<TG,TL>& a, const TG& b)
00657 {
00658 return a.global_>b;
00659 }
00660
00661 template<class TG, class TL>
00662 inline bool operator<=(const IndexPair<TG,TL>& a, const TG& b)
00663 {
00664 return a.global_<=b;
00665 }
00666
00667 template<class TG, class TL>
00668 inline bool operator >=(const IndexPair<TG,TL>& a, const TG& b)
00669 {
00670 return a.global_>=b;
00671 }
00672
00673 template<class TG, class TL>
00674 IndexPair<TG,TL>::IndexPair(const TG& global, const TL& local)
00675 : global_(global), local_(local){}
00676
00677 template<class TG, class TL>
00678 IndexPair<TG,TL>::IndexPair(const TG& global)
00679 : global_(global), local_(){}
00680
00681 template<class TG, class TL>
00682 IndexPair<TG,TL>::IndexPair()
00683 : global_(), local_(){}
00684
00685 template<class TG, class TL>
00686 inline const TG& IndexPair<TG,TL>::global() const{
00687 return global_;
00688 }
00689
00690 template<class TG, class TL>
00691 inline TL& IndexPair<TG,TL>::local() {
00692 return local_;
00693 }
00694
00695 template<class TG, class TL>
00696 inline const TL& IndexPair<TG,TL>::local() const{
00697 return local_;
00698 }
00699
00700 template<class TG, class TL>
00701 inline void IndexPair<TG,TL>::setLocal(int local){
00702 local_=local;
00703 }
00704
00705 template<class TG, class TL, int N>
00706 ParallelIndexSet<TG,TL,N>::ParallelIndexSet()
00707 : state_(GROUND), seqNo_(0)
00708 {}
00709
00710 template<class TG, class TL, int N>
00711 void ParallelIndexSet<TG,TL,N>::beginResize() throw(InvalidIndexSetState)
00712 {
00713
00714
00715 #ifndef NDEBUG
00716 if(state_!=GROUND)
00717 DUNE_THROW(InvalidIndexSetState,
00718 "IndexSet has to be in GROUND state, when "
00719 << "beginResize() is called!");
00720 #endif
00721
00722 state_ = RESIZE;
00723 deletedEntries_ = false;
00724 }
00725
00726 template<class TG, class TL, int N>
00727 inline void ParallelIndexSet<TG,TL,N>::add(const GlobalIndex& global)
00728 throw(InvalidIndexSetState)
00729 {
00730
00731 #ifndef NDEBUG
00732 if(state_ != RESIZE)
00733 DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
00734 <<"while in RESIZE state!");
00735 #endif
00736 newIndices_.push_back(IndexPair(global));
00737 }
00738
00739 template<class TG, class TL, int N>
00740 inline void ParallelIndexSet<TG,TL,N>::add(const TG& global, const TL& local)
00741 throw(InvalidIndexSetState)
00742 {
00743
00744 #ifndef NDEBUG
00745 if(state_ != RESIZE)
00746 DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
00747 <<"while in RESIZE state!");
00748 #endif
00749 newIndices_.push_back(IndexPair(global,local));
00750 }
00751
00752 template<class TG, class TL, int N>
00753 inline void ParallelIndexSet<TG,TL,N>::markAsDeleted(const iterator& global)
00754 throw(InvalidIndexSetState){
00755
00756 #ifndef NDEBUG
00757 if(state_ != RESIZE)
00758 DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
00759 <<"while in RESIZE state!");
00760 #endif
00761 deletedEntries_ = true;
00762
00763 global.markAsDeleted();
00764 }
00765
00766 template<class TG, class TL, int N>
00767 void ParallelIndexSet<TG,TL,N>::endResize() throw(InvalidIndexSetState){
00768
00769 #ifndef NDEBUG
00770 if(state_ != RESIZE)
00771 DUNE_THROW(InvalidIndexSetState, "endResize called while not "
00772 <<"in RESIZE state!");
00773 #endif
00774
00775 std::sort(newIndices_.begin(), newIndices_.end());
00776 merge();
00777 seqNo_++;
00778 state_ = GROUND;
00779 }
00780
00781
00782 template<class TG, class TL, int N>
00783 inline void ParallelIndexSet<TG,TL,N>::merge(){
00784 if(localIndices_.size()==0)
00785 {
00786 localIndices_=newIndices_;
00787 newIndices_.clear();
00788 }
00789 else if(newIndices_.size()>0 || deletedEntries_)
00790 {
00791 ArrayList<IndexPair,N> tempPairs;
00792 typedef typename ArrayList<IndexPair,N>::iterator iterator;
00793 typedef typename ArrayList<IndexPair,N>::const_iterator const_iterator;
00794
00795 iterator old=localIndices_.begin();
00796 iterator added=newIndices_.begin();
00797 const const_iterator endold=localIndices_.end();
00798 const const_iterator endadded=newIndices_.end();
00799
00800 while(old != endold && added!= endadded)
00801 {
00802 if(old->local().state()==DELETED){
00803 old.eraseToHere();
00804 }
00805 else if(old->global() < added->global())
00806 {
00807 tempPairs.push_back(*old);
00808 old.eraseToHere();
00809 }
00810 else if(old->global() == added->global()){
00811
00812 assert(old->local()==added->local());
00813 old.eraseToHere();
00814 }
00815 else
00816 {
00817 tempPairs.push_back(*added);
00818 added.eraseToHere();
00819 }
00820 }
00821
00822 while(old != endold)
00823 {
00824 if(old->local().state()!=DELETED){
00825 tempPairs.push_back(*old);
00826 }
00827 old.eraseToHere();
00828 }
00829
00830 while(added!= endadded)
00831 {
00832 tempPairs.push_back(*added);
00833 added.eraseToHere();
00834 }
00835 localIndices_ = tempPairs;
00836 }
00837 }
00838
00839
00840 template<class TG, class TL, int N>
00841 inline const IndexPair<TG,TL>&
00842 ParallelIndexSet<TG,TL,N>::operator[](const TG& global) const
00843 {
00844
00845 int low=0, high=localIndices_.size()-1, probe=-1;
00846
00847 while(low<high)
00848 {
00849 probe = (high + low) / 2;
00850 if(global <= localIndices_[probe].global())
00851 high = probe;
00852 else
00853 low = probe+1;
00854 }
00855
00856 #ifdef DUNE_ISTL_WITH_CHECKING
00857 if(probe==-1)
00858 DUNE_THROW(RangeError, "No entries!");
00859
00860 if( localIndices_[low].global() != global)
00861 DUNE_THROW(RangeError, "Could not find entry of "<<global);
00862 else
00863 #endif
00864 return localIndices_[low];
00865 }
00866
00867
00868 template<class TG, class TL, int N>
00869 inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::operator[](const TG& global)
00870 {
00871
00872 int low=0, high=localIndices_.size()-1, probe=-1;
00873
00874 while(low<high)
00875 {
00876 probe = (high + low) / 2;
00877 if(localIndices_[probe].global() >= global)
00878 high = probe;
00879 else
00880 low = probe+1;
00881 }
00882
00883 #ifdef DUNE_ISTL_WITH_CHECKING
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 #endif
00891 return localIndices_[low];
00892 }
00893
00894 template<class TG, class TL, int N>
00895 inline typename ParallelIndexSet<TG,TL,N>::iterator
00896 ParallelIndexSet<TG,TL,N>::begin()
00897 {
00898 return iterator(*this, localIndices_.begin());
00899 }
00900
00901
00902 template<class TG, class TL, int N>
00903 inline typename ParallelIndexSet<TG,TL,N>::iterator
00904 ParallelIndexSet<TG,TL,N>::end()
00905 {
00906 return iterator(*this,localIndices_.end());
00907 }
00908
00909 template<class TG, class TL, int N>
00910 inline typename ParallelIndexSet<TG,TL,N>::const_iterator
00911 ParallelIndexSet<TG,TL,N>::begin() const
00912 {
00913 return localIndices_.begin();
00914 }
00915
00916
00917 template<class TG, class TL, int N>
00918 inline typename ParallelIndexSet<TG,TL,N>::const_iterator
00919 ParallelIndexSet<TG,TL,N>::end() const
00920 {
00921 return localIndices_.end();
00922 }
00923
00924 template<class TG, class TL, int N>
00925 void ParallelIndexSet<TG,TL,N>::renumberLocal(){
00926 #ifndef NDEBUG
00927 if(state_==RESIZE)
00928 DUNE_THROW(InvalidIndexSetState, "IndexSet has to be in "
00929 <<"GROUND state for renumberLocal()");
00930 #endif
00931
00932 typedef typename ArrayList<IndexPair,N>::iterator iterator;
00933 const const_iterator end_ = end();
00934 uint32_t index=0;
00935
00936 for(iterator pair=begin(); pair!=end_; index++, ++pair)
00937 pair->local()=index;
00938 }
00939
00940 template<class TG, class TL, int N>
00941 inline int ParallelIndexSet<TG,TL,N>::seqNo() const
00942 {
00943 return seqNo_;
00944 }
00945
00946 template<class TG, class TL, int N>
00947 inline size_t ParallelIndexSet<TG,TL,N>::size() const
00948 {
00949 return localIndices_.size();
00950 }
00951
00952 template<class I>
00953 GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset,
00954 std::size_t size)
00955 : indexSet_(indexset), size_(size),
00956 indices_(size_, static_cast<const IndexPair*>(0))
00957 {
00958 assert(size>=indexset.size());
00959 const_iterator end_ = indexSet_.end();
00960
00961 for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair){
00962 assert(pair->local()<size_);
00963 indices_[pair->local()] = &(*pair);
00964 }
00965 }
00966
00967 template<class I>
00968 GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset)
00969 : indexSet_(indexset)
00970 {
00971 const_iterator end_ = indexSet_.end();
00972 size_t size=0;
00973 for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
00974 size_=std::max(size_,static_cast<std::size_t>(pair->local()));
00975
00976 indices_.resize(++size_);
00977
00978 for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
00979 indices_[pair->local()] = &(*pair);
00980 }
00981
00982 template<class I>
00983 GlobalLookupIndexSet<I>::~GlobalLookupIndexSet()
00984 {}
00985
00986
00987 template<class I>
00988 inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>*
00989 GlobalLookupIndexSet<I>::pair(const std::size_t& local) const
00990 {
00991 return indices_[local];
00992 }
00993
00994 template<class I>
00995 inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>&
00996 GlobalLookupIndexSet<I>::operator[](const GlobalIndex& global) const
00997 {
00998 return indexSet_[global];
00999 }
01000
01001 template<class I>
01002 typename I::const_iterator GlobalLookupIndexSet<I>::begin() const
01003 {
01004 return indexSet_.begin();
01005 }
01006
01007 template<class I>
01008 typename I::const_iterator GlobalLookupIndexSet<I>::end() const
01009 {
01010 return indexSet_.end();
01011 }
01012
01013 template<class I>
01014 inline size_t GlobalLookupIndexSet<I>::size() const
01015 {
01016 return size_;
01017 }
01018
01019 template<class I>
01020 inline int GlobalLookupIndexSet<I>::seqNo() const
01021 {
01022 return indexSet_.seqNo();
01023 }
01024 }
01025 #endif