|
EpetraExt Development
|
00001 //@HEADER 00002 // *********************************************************************** 00003 // 00004 // EpetraExt: Epetra Extended - Linear Algebra Services Package 00005 // Copyright (2011) Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 //@HEADER 00041 #ifndef EPETRAEXT_DIRECTORY_H 00042 #define EPETRAEXT_DIRECTORY_H 00043 00044 // ----------- Includes ---------- 00045 00046 #include <map> 00047 #include <vector> 00048 00049 #include <cmath> 00050 00051 #include <Teuchos_RefCountPtr.hpp> 00052 00053 #include <EpetraExt_Functors.h> 00054 00055 namespace EpetraExt { 00056 00058 00060 template <typename KT, typename DT, class DH, class AC, class MG> 00061 class Directory 00062 { 00063 00064 public: 00065 00066 typedef typename std::map< KT, Teuchos::RefCountPtr<DT> > DataMap; 00067 typedef typename DataMap::iterator DataMapIter; 00068 typedef typename DataMap::const_iterator DataMapCIter; 00069 00070 typedef typename std::multimap< KT, Teuchos::RefCountPtr<DT> > DataRecvMap; 00071 typedef typename DataRecvMap::iterator DataRecvMapIter; 00072 typedef typename DataRecvMap::const_iterator DataRecvMapCIter; 00073 00074 typedef typename std::vector<KT> KeyList; 00075 typedef typename KeyList::iterator KeyListIter; 00076 typedef typename KeyList::const_iterator KeyListCIter; 00077 00078 typedef typename std::vector<int> ProcList; 00079 typedef typename ProcList::iterator ProcListIter; 00080 00081 typedef typename std::pair<int,KT> ProcKeyPair; 00082 typedef typename std::vector<ProcKeyPair> ProcKeyList; 00083 typedef typename ProcKeyList::iterator ProcKeyListIter; 00084 00085 typedef typename AC::iterator ContainerIter; 00086 typedef typename AC::const_iterator ContainerCIter; 00087 00088 // Constructors 00089 Directory( MG migrate, 00090 DH distHash ) 00091 : migrate_(migrate), 00092 distHash_(distHash) 00093 {} 00094 00095 // Destructor 00096 ~Directory() {} 00097 00098 private: 00099 // No public copy construction, assignment, or equality operators 00100 Directory( const Directory & ); 00101 00102 Directory & operator=( const Directory & ); 00103 00104 bool operator==( const Directory & ) const; 00105 bool operator!=( const Directory & ) const; 00106 00107 public: 00108 00109 // Add objects from directory. 00110 void addEntries( DataMap const & entries ); 00111 00112 // Remove objects from directory. 00113 void deleteEntries( KeyList & keys ); 00114 00115 // Get the items in the directory. 00116 void getEntries( KeyList & keys, 00117 DataMap & entries ); 00118 00119 AC & container() { return container_; } 00120 ContainerIter & begin() { return container_.begin(); } 00121 ContainerIter & end() { return container_.end(); } 00122 00123 protected: 00124 00125 #ifdef EPETRA_MPI 00126 void pushKeys_( KeyList &, KeyList &, ProcList & ); 00127 void pushData_( DataMap const &, DataRecvMap &, ProcList & ); 00128 #endif 00129 00130 MG migrate_; 00131 DH distHash_; 00132 AC container_; 00133 00134 }; 00135 00137 /*** Hash function for processor assignment 00138 */ 00139 template <typename T> 00140 class Hash 00141 { 00142 int operator()( const T & in ) { assert(0); return 0; } 00143 }; 00144 00145 template <> 00146 class Hash<std::string> 00147 { 00148 float size_; 00149 00150 public: 00151 00152 Hash( int size ) 00153 : size_( static_cast<double>(size) ) 00154 {} 00155 00156 int operator()( const std::string & in ) 00157 { 00158 int slen = in.length(); 00159 int sum = 0; 00160 for( int i = 0; i < slen; ++i ) 00161 sum += static_cast<int>( in[i] ); 00162 00163 return static_cast<int>( fmod( static_cast<float>( sum ), size_ ) ); 00164 } 00165 }; 00166 00168 00170 template < typename T, typename U > 00171 void SortContainer2( T & firstContainer, U & secondContainer ) 00172 { 00173 typedef typename std::multimap< typename T::value_type, typename U::value_type> UTMultiMap; 00174 00175 UTMultiMap SortMap; 00176 00177 typename T::iterator iterT = firstContainer.begin(); 00178 typename T::iterator endT = firstContainer.end(); 00179 typename U::iterator iterU = secondContainer.begin(); 00180 typename U::iterator endU = secondContainer.end(); 00181 00182 for( ; (iterT!=endT)||(iterU!=endU) ; ++iterT, ++iterU ) 00183 SortMap.insert( typename UTMultiMap::value_type( *iterT, *iterU ) ); 00184 00185 firstContainer.clear(); 00186 secondContainer.clear(); 00187 00188 typename UTMultiMap::iterator iterUTM = SortMap.begin(); 00189 typename UTMultiMap::iterator endUTM = SortMap.end(); 00190 00191 for( ; iterUTM != endUTM; ++iterUTM ) 00192 { 00193 firstContainer.push_back( iterUTM->first ); 00194 secondContainer.push_back( iterUTM->second ); 00195 } 00196 } 00197 00199 00201 template < typename T > 00202 bool IsSorted( T & container ) 00203 { 00204 if( container.size() < 2 ) return true; 00205 00206 typename T::iterator iterT = container.begin(); 00207 typename T::iterator endT = container.end(); 00208 typename T::iterator iterTPlus = iterT; 00209 iterTPlus++; 00210 00211 for( ; iterTPlus != endT; ++iterT, ++iterTPlus ) 00212 if( !(*iterT<*iterTPlus) ) return false; 00213 00214 return true; 00215 } 00216 00217 template <typename KT, typename DT, class DH, class AC, class MG> 00218 void 00219 Directory<KT,DT,DH,AC,MG>:: 00220 addEntries( DataMap const & entries ) 00221 { 00222 #ifdef EPETRA_MPI 00223 00224 DataRecvMap newEntries; 00225 ProcList procs; 00226 pushData_( entries, newEntries, procs ); 00227 00228 DataRecvMapCIter citDM = newEntries.begin(); 00229 DataRecvMapCIter cendDM = newEntries.end(); 00230 00231 #else 00232 00233 DataMapCIter citDM = entries.begin(); 00234 DataMapCIter cendDM = entries.end(); 00235 00236 #endif 00237 00238 for( ; citDM != cendDM; ++citDM ) 00239 container_.insert( *citDM ); 00240 } 00241 00242 template <typename KT, typename DT, class DH, class AC, class MG> 00243 void 00244 Directory<KT,DT,DH,AC,MG>:: 00245 deleteEntries( KeyList & keys ) 00246 { 00247 #ifdef EPETRA_MPI 00248 00249 KeyList newKeys; 00250 ProcList procs; 00251 pushKeys_( keys, newKeys, procs ); 00252 00253 KeyListCIter citKL = newKeys.begin(); 00254 KeyListCIter cendKL = newKeys.end(); 00255 00256 #else 00257 00258 KeyListCIter citKL = keys.begin(); 00259 KeyListCIter cendKL = keys.end(); 00260 00261 #endif 00262 00263 for( ; citKL != cendKL; ++citKL ) 00264 container_.erase( *citKL ); 00265 } 00266 00267 template <typename KT, typename DT, class DH, class AC, class MG> 00268 void 00269 Directory<KT,DT,DH,AC,MG>:: 00270 getEntries( KeyList & keys, 00271 DataMap & entries ) 00272 { 00273 #ifdef EPETRA_MPI 00274 00275 //Push Keys to owning processors 00276 KeyList newKeys; 00277 ProcList procs; 00278 pushKeys_( keys, newKeys, procs ); 00279 00280 KeyListCIter citKL = newKeys.begin(); 00281 KeyListCIter cendKL = newKeys.end(); 00282 00283 //Rvs migrate to move data from directory back to requesting procs 00284 DataMap newEntries; 00285 for( ; citKL != cendKL; ++citKL ) 00286 { 00287 if( !container_.count( *citKL ) ) 00288 throw "Data not in directory: " + *citKL + "\n"; 00289 00290 newEntries[*citKL] = (container_.lower_bound( *citKL ))->second; 00291 } 00292 00293 migrate_.rvs( procs, newKeys, newEntries, entries ); 00294 00295 #else 00296 00297 KeyListCIter citKL = keys.begin(); 00298 KeyListCIter cendKL = keys.end(); 00299 for( ; citKL != cendKL; ++citKL ) 00300 { 00301 if( !container_.count( *citKL ) ) 00302 throw "Data not in directory: " + *citKL + "\n"; 00303 00304 entries[*citKL] = (container_.lower_bound( *citKL ))->second; 00305 } 00306 00307 #endif 00308 } 00309 00310 #ifdef EPETRA_MPI 00311 00312 template <typename KT, typename DT, class DH, class AC, class MG> 00313 void 00314 Directory<KT,DT,DH,AC,MG>:: 00315 pushKeys_( KeyList & sKeys, 00316 KeyList & rKeys, 00317 ProcList & procs ) 00318 { 00319 KeyListCIter itKL = sKeys.begin(); 00320 KeyListCIter endKL = sKeys.end(); 00321 00322 procs.clear(); 00323 for( ; itKL != endKL; ++itKL ) 00324 procs.push_back( distHash_(*itKL) ); 00325 00326 if( !IsSorted( procs ) ) SortContainer2( procs, sKeys ); 00327 00328 migrate_( procs, sKeys, rKeys ); 00329 } 00330 00331 template <typename KT, typename DT, class DH, class AC, class MG> 00332 void 00333 Directory<KT,DT,DH,AC,MG>:: 00334 pushData_( DataMap const & sData, 00335 DataRecvMap & rData, 00336 ProcList & procs ) 00337 { 00338 DataMapCIter itDM = sData.begin(); 00339 DataMapCIter endDM = sData.end(); 00340 00341 procs.clear(); 00342 for( ; itDM != endDM; ++itDM ) 00343 procs.push_back( distHash_(itDM->first) ); 00344 00345 migrate_( procs, sData, rData ); 00346 } 00347 00348 #endif 00349 00350 } //namespace EpetraExt 00351 00352 #endif
1.7.4