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 (2001) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 #ifndef EPETRAEXT_DIRECTORY_H
00029 #define EPETRAEXT_DIRECTORY_H
00030                                                                                                  
00031 // ----------- Includes ----------
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   // Constructors
00076   Directory( MG migrate,
00077        DH distHash )
00078   : migrate_(migrate),
00079     distHash_(distHash)
00080   {}
00081 
00082   // Destructor
00083   ~Directory() {}
00084 
00085 private:
00086   // No public copy construction, assignment, or equality operators
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   // Add objects from directory.
00097   void addEntries( DataMap const & entries );
00098 
00099   // Remove objects from directory.
00100   void deleteEntries( KeyList & keys );
00101 
00102   // Get the items in the directory.
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 /*** Hash function for processor assignment
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   //Push Keys to owning processors
00263   KeyList newKeys;
00264   ProcList procs;
00265   pushKeys_( keys, newKeys, procs );
00266 
00267   KeyListCIter citKL  = newKeys.begin();
00268   KeyListCIter cendKL = newKeys.end();
00269 
00270   //Rvs migrate to move data from directory back to requesting procs
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 } //namespace EpetraExt
00338 
00339 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines