EpetraExt Development
EpetraExt_Directory.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines