00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef EPETRAEXT_DIRECTORY_H
00029 #define EPETRAEXT_DIRECTORY_H
00030
00031
00032
00033 #include <map>
00034 #include <vector>
00035
00036 #include <cmath>
00037
00038 #include <Teuchos_RefCountPtr.hpp>
00039
00040 #include <EpetraExt_Functors.h>
00041
00042 namespace EpetraExt {
00043
00045
00047 template <typename KT, typename DT, class DH, class AC, class MG>
00048 class Directory
00049 {
00050
00051 public:
00052
00053 typedef typename std::map< KT, Teuchos::RefCountPtr<DT> > DataMap;
00054 typedef typename DataMap::iterator DataMapIter;
00055 typedef typename DataMap::const_iterator DataMapCIter;
00056
00057 typedef typename std::multimap< KT, Teuchos::RefCountPtr<DT> > DataRecvMap;
00058 typedef typename DataRecvMap::iterator DataRecvMapIter;
00059 typedef typename DataRecvMap::const_iterator DataRecvMapCIter;
00060
00061 typedef typename std::vector<KT> KeyList;
00062 typedef typename KeyList::iterator KeyListIter;
00063 typedef typename KeyList::const_iterator KeyListCIter;
00064
00065 typedef typename std::vector<int> ProcList;
00066 typedef typename ProcList::iterator ProcListIter;
00067
00068 typedef typename std::pair<int,KT> ProcKeyPair;
00069 typedef typename std::vector<ProcKeyPair> ProcKeyList;
00070 typedef typename ProcKeyList::iterator ProcKeyListIter;
00071
00072 typedef typename AC::iterator ContainerIter;
00073 typedef typename AC::const_iterator ContainerCIter;
00074
00075
00076 Directory( MG migrate,
00077 DH distHash )
00078 : migrate_(migrate),
00079 distHash_(distHash)
00080 {}
00081
00082
00083 ~Directory() {}
00084
00085 private:
00086
00087 Directory( const Directory & );
00088
00089 Directory & operator=( const Directory & );
00090
00091 bool operator==( const Directory & ) const;
00092 bool operator!=( const Directory & ) const;
00093
00094 public:
00095
00096
00097 void addEntries( DataMap const & entries );
00098
00099
00100 void deleteEntries( KeyList & keys );
00101
00102
00103 void getEntries( KeyList & keys,
00104 DataMap & entries );
00105
00106 AC & container() { return container_; }
00107 ContainerIter & begin() { return container_.begin(); }
00108 ContainerIter & end() { return container_.end(); }
00109
00110 protected:
00111
00112 #ifdef EPETRA_MPI
00113 void pushKeys_( KeyList &, KeyList &, ProcList & );
00114 void pushData_( DataMap const &, DataRecvMap &, ProcList & );
00115 #endif
00116
00117 MG migrate_;
00118 DH distHash_;
00119 AC container_;
00120
00121 };
00122
00124
00125
00126 template <typename T>
00127 class Hash
00128 {
00129 int operator()( const T & in ) { assert(0); return 0; }
00130 };
00131
00132 template <>
00133 class Hash<std::string>
00134 {
00135 float size_;
00136
00137 public:
00138
00139 Hash( int size )
00140 : size_( static_cast<double>(size) )
00141 {}
00142
00143 int operator()( const std::string & in )
00144 {
00145 int slen = in.length();
00146 int sum = 0;
00147 for( int i = 0; i < slen; ++i )
00148 sum += static_cast<int>( in[i] );
00149
00150 return static_cast<int>( fmod( static_cast<float>( sum ), size_ ) );
00151 }
00152 };
00153
00155
00157 template < typename T, typename U >
00158 void SortContainer2( T & firstContainer, U & secondContainer )
00159 {
00160 typedef typename std::multimap< typename T::value_type, typename U::value_type> UTMultiMap;
00161
00162 UTMultiMap SortMap;
00163
00164 typename T::iterator iterT = firstContainer.begin();
00165 typename T::iterator endT = firstContainer.end();
00166 typename U::iterator iterU = secondContainer.begin();
00167 typename U::iterator endU = secondContainer.end();
00168
00169 for( ; (iterT!=endT)||(iterU!=endU) ; ++iterT, ++iterU )
00170 SortMap.insert( typename UTMultiMap::value_type( *iterT, *iterU ) );
00171
00172 firstContainer.clear();
00173 secondContainer.clear();
00174
00175 typename UTMultiMap::iterator iterUTM = SortMap.begin();
00176 typename UTMultiMap::iterator endUTM = SortMap.end();
00177
00178 for( ; iterUTM != endUTM; ++iterUTM )
00179 {
00180 firstContainer.push_back( iterUTM->first );
00181 secondContainer.push_back( iterUTM->second );
00182 }
00183 }
00184
00186
00188 template < typename T >
00189 bool IsSorted( T & container )
00190 {
00191 if( container.size() < 2 ) return true;
00192
00193 typename T::iterator iterT = container.begin();
00194 typename T::iterator endT = container.end();
00195 typename T::iterator iterTPlus = iterT;
00196 iterTPlus++;
00197
00198 for( ; iterTPlus != endT; ++iterT, ++iterTPlus )
00199 if( !(*iterT<*iterTPlus) ) return false;
00200
00201 return true;
00202 }
00203
00204 template <typename KT, typename DT, class DH, class AC, class MG>
00205 void
00206 Directory<KT,DT,DH,AC,MG>::
00207 addEntries( DataMap const & entries )
00208 {
00209 #ifdef EPETRA_MPI
00210
00211 DataRecvMap newEntries;
00212 ProcList procs;
00213 pushData_( entries, newEntries, procs );
00214
00215 DataRecvMapCIter citDM = newEntries.begin();
00216 DataRecvMapCIter cendDM = newEntries.end();
00217
00218 #else
00219
00220 DataMapCIter citDM = entries.begin();
00221 DataMapCIter cendDM = entries.end();
00222
00223 #endif
00224
00225 for( ; citDM != cendDM; ++citDM )
00226 container_.insert( *citDM );
00227 }
00228
00229 template <typename KT, typename DT, class DH, class AC, class MG>
00230 void
00231 Directory<KT,DT,DH,AC,MG>::
00232 deleteEntries( KeyList & keys )
00233 {
00234 #ifdef EPETRA_MPI
00235
00236 KeyList newKeys;
00237 ProcList procs;
00238 pushKeys_( keys, newKeys, procs );
00239
00240 KeyListCIter citKL = newKeys.begin();
00241 KeyListCIter cendKL = newKeys.end();
00242
00243 #else
00244
00245 KeyListCIter citKL = keys.begin();
00246 KeyListCIter cendKL = keys.end();
00247
00248 #endif
00249
00250 for( ; citKL != cendKL; ++citKL )
00251 container_.erase( *citKL );
00252 }
00253
00254 template <typename KT, typename DT, class DH, class AC, class MG>
00255 void
00256 Directory<KT,DT,DH,AC,MG>::
00257 getEntries( KeyList & keys,
00258 DataMap & entries )
00259 {
00260 #ifdef EPETRA_MPI
00261
00262
00263 KeyList newKeys;
00264 ProcList procs;
00265 pushKeys_( keys, newKeys, procs );
00266
00267 KeyListCIter citKL = newKeys.begin();
00268 KeyListCIter cendKL = newKeys.end();
00269
00270
00271 DataMap newEntries;
00272 for( ; citKL != cendKL; ++citKL )
00273 {
00274 if( !container_.count( *citKL ) )
00275 throw "Data not in directory: " + *citKL + "\n";
00276
00277 newEntries[*citKL] = (container_.lower_bound( *citKL ))->second;
00278 }
00279
00280 migrate_.rvs( procs, newKeys, newEntries, entries );
00281
00282 #else
00283
00284 KeyListCIter citKL = keys.begin();
00285 KeyListCIter cendKL = keys.end();
00286 for( ; citKL != cendKL; ++citKL )
00287 {
00288 if( !container_.count( *citKL ) )
00289 throw "Data not in directory: " + *citKL + "\n";
00290
00291 entries[*citKL] = (container_.lower_bound( *citKL ))->second;
00292 }
00293
00294 #endif
00295 }
00296
00297 #ifdef EPETRA_MPI
00298
00299 template <typename KT, typename DT, class DH, class AC, class MG>
00300 void
00301 Directory<KT,DT,DH,AC,MG>::
00302 pushKeys_( KeyList & sKeys,
00303 KeyList & rKeys,
00304 ProcList & procs )
00305 {
00306 KeyListCIter itKL = sKeys.begin();
00307 KeyListCIter endKL = sKeys.end();
00308
00309 procs.clear();
00310 for( ; itKL != endKL; ++itKL )
00311 procs.push_back( distHash_(*itKL) );
00312
00313 if( !IsSorted( procs ) ) SortContainer2( procs, sKeys );
00314
00315 migrate_( procs, sKeys, rKeys );
00316 }
00317
00318 template <typename KT, typename DT, class DH, class AC, class MG>
00319 void
00320 Directory<KT,DT,DH,AC,MG>::
00321 pushData_( DataMap const & sData,
00322 DataRecvMap & rData,
00323 ProcList & procs )
00324 {
00325 DataMapCIter itDM = sData.begin();
00326 DataMapCIter endDM = sData.end();
00327
00328 procs.clear();
00329 for( ; itDM != endDM; ++itDM )
00330 procs.push_back( distHash_(itDM->first) );
00331
00332 migrate_( procs, sData, rData );
00333 }
00334
00335 #endif
00336
00337 }
00338
00339 #endif