EpetraExt Package Browser (Single Doxygen Collection) Development
EpetraExt_MMHelpers.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 
00042 #ifndef EPETRAEXT_MMHELPERS_H
00043 #define EPETRAEXT_MMHELPERS_H
00044 
00045 #include "EpetraExt_ConfigDefs.h"
00046 #include "Epetra_ConfigDefs.h"
00047 #include "Epetra_DistObject.h"
00048 #include "Epetra_Map.h"
00049 #include "Teuchos_RCP.hpp"
00050 
00051 #include <vector>
00052 #include <set>
00053 #include <map>
00054 
00055 
00056 class Epetra_CrsMatrix;
00057 class Epetra_Import;
00058 class Epetra_Distributor;
00059 
00060 namespace EpetraExt {
00061 class LightweightCrsMatrix;
00062 
00063 //#define HAVE_EPETRAEXT_DEBUG // for extra sanity checks
00064 
00065 // ==============================================================
00066 //struct that holds views of the contents of a CrsMatrix. These
00067 //contents may be a mixture of local and remote rows of the
00068 //actual matrix.
00069 class CrsMatrixStruct {
00070 public:
00071   CrsMatrixStruct();
00072 
00073   virtual ~CrsMatrixStruct();
00074 
00075   void deleteContents();
00076 
00077   int numRows;
00078 
00079   // The following class members get used in the transpose modes of the MMM
00080   // but not in the A*B mode.  
00081   int* numEntriesPerRow;
00082   int** indices;
00083   double** values;
00084   bool* remote;
00085   int numRemote;
00086   const Epetra_BlockMap* importColMap;
00087 
00088   // Maps and matrices (all modes)
00089   const Epetra_Map* origRowMap;
00090   const Epetra_Map* rowMap;
00091   const Epetra_Map* colMap;
00092   const Epetra_Map* domainMap;
00093   LightweightCrsMatrix* importMatrix;
00094   const Epetra_CrsMatrix *origMatrix;
00095 
00096   // The following class members are only used for A*B mode
00097   std::vector<int> targetMapToOrigRow;
00098   std::vector<int> targetMapToImportRow;
00099 };
00100 
00101 int dumpCrsMatrixStruct(const CrsMatrixStruct& M);
00102 
00103 // ==============================================================
00104 class CrsWrapper {
00105  public:
00106   virtual ~CrsWrapper(){}
00107 
00108   virtual const Epetra_Map& RowMap() const = 0;
00109 
00110   virtual bool Filled() = 0;
00111 
00112 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00113   virtual int InsertGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices) = 0;
00114 
00115   virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices) = 0;
00116 #endif
00117 
00118 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00119   virtual int InsertGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices) = 0;
00120 
00121   virtual int SumIntoGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices) = 0;
00122 #endif
00123 };
00124 
00125 // ==============================================================
00126 class CrsWrapper_Epetra_CrsMatrix : public CrsWrapper {
00127  public:
00128   CrsWrapper_Epetra_CrsMatrix(Epetra_CrsMatrix& epetracrsmatrix);
00129   virtual ~CrsWrapper_Epetra_CrsMatrix();
00130 
00131   const Epetra_Map& RowMap() const;
00132 
00133   bool Filled();
00134 
00135 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00136   int InsertGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices);
00137   int SumIntoGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices);
00138 #endif
00139 
00140 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00141   int InsertGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices);
00142   int SumIntoGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices);
00143 #endif
00144 
00145  private:
00146   Epetra_CrsMatrix& ecrsmat_;
00147 };
00148 
00149 // ==============================================================
00150 template<typename int_type>
00151 class CrsWrapper_GraphBuilder : public CrsWrapper {
00152  public:
00153   CrsWrapper_GraphBuilder(const Epetra_Map& emap);
00154   virtual ~CrsWrapper_GraphBuilder();
00155 
00156   const Epetra_Map& RowMap() const {return rowmap_; }
00157 
00158   bool Filled();
00159 
00160   int InsertGlobalValues(int_type GlobalRow, int NumEntries, double* Values, int_type* Indices);
00161   int SumIntoGlobalValues(int_type GlobalRow, int NumEntries, double* Values, int_type* Indices);
00162 
00163   std::map<int_type,std::set<int_type>*>& get_graph();
00164 
00165   int get_max_row_length() { return max_row_length_; }
00166 
00167  private:
00168   std::map<int_type,std::set<int_type>*> graph_;
00169   const Epetra_Map& rowmap_;
00170   int max_row_length_;
00171 };
00172 
00173 // ==============================================================
00174 template<typename int_type>
00175 void insert_matrix_locations(CrsWrapper_GraphBuilder<int_type>& graphbuilder,
00176                               Epetra_CrsMatrix& C);
00177 
00178 template<typename int_type>
00179 void Tpack_outgoing_rows(const Epetra_CrsMatrix& mtx,
00180                         const std::vector<int_type>& proc_col_ranges,
00181                         std::vector<int_type>& send_rows,
00182                         std::vector<int>& rows_per_send_proc);
00183 
00184 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00185 void pack_outgoing_rows(const Epetra_CrsMatrix& mtx,
00186                         const std::vector<int>& proc_col_ranges,
00187                         std::vector<int>& send_rows,
00188                         std::vector<int>& rows_per_send_proc);
00189 #endif
00190 
00191 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00192 void pack_outgoing_rows(const Epetra_CrsMatrix& mtx,
00193                         const std::vector<long long>& proc_col_ranges,
00194                         std::vector<long long>& send_rows,
00195                         std::vector<int>& rows_per_send_proc);
00196 #endif
00197 
00198 template<typename int_type>
00199 std::pair<int_type,int_type> get_col_range(const Epetra_Map& emap);
00200 
00201 template<typename int_type>
00202 std::pair<int_type,int_type> get_col_range(const Epetra_CrsMatrix& mtx);
00203 
00204 // ==============================================================
00205 class LightweightMapData : Epetra_Data {
00206   friend class LightweightMap; 
00207  public:
00208   LightweightMapData();
00209   ~LightweightMapData();
00210   long long IndexBase_;
00211 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00212   std::vector<int> MyGlobalElements_int_; 
00213   Epetra_HashTable<int> * LIDHash_int_;
00214 #endif
00215 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00216   std::vector<long long> MyGlobalElements_LL_; 
00217   Epetra_HashTable<long long> * LIDHash_LL_;
00218 #endif
00219 
00220   // For "copy" constructor only...
00221   Epetra_Map * CopyMap_;
00222   
00223  };
00224 
00225 class LightweightMap {
00226  public:
00227   LightweightMap();
00228 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00229   LightweightMap(int NumGlobalElements,int NumMyElements, const int * MyGlobalElements, int IndexBase, bool GenerateHash=true);
00230 #endif
00231 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00232   LightweightMap(long long NumGlobalElements,int NumMyElements, const long long * MyGlobalElements, int IndexBase, bool GenerateHash=true);
00233   LightweightMap(long long NumGlobalElements,int NumMyElements, const long long * MyGlobalElements, long long IndexBase, bool GenerateHash=true);
00234 #endif
00235   LightweightMap(const Epetra_Map & Map);
00236   LightweightMap(const LightweightMap & Map);
00237   ~LightweightMap();
00238 
00239   LightweightMap & operator=(const LightweightMap & map);
00240 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00241   int LID(int GID) const;
00242   int GID(int LID) const;      
00243 #endif
00244 
00245 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00246   int  LID(long long GID) const;
00247 #endif
00248   long long GID64(int LID) const;
00249   int NumMyElements() const;
00250 
00251 #if defined(EPETRA_NO_32BIT_GLOBAL_INDICES) && defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
00252   // default implementation so that no compiler/linker error in case neither 32 nor 64
00253   // bit indices present.
00254   int  LID(long long GID) const { return -1; }
00255 #endif
00256 
00257 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00258   int* MyGlobalElements() const; 
00259   int IndexBase() const {
00260     if(IndexBase64() == (long long) static_cast<int>(IndexBase64()))
00261       return (int) IndexBase64();
00262     throw "EpetraExt::LightweightMap::IndexBase: IndexBase cannot fit an int.";
00263   }
00264   void MyGlobalElementsPtr(int *& MyGlobalElementList) const;
00265 #endif
00266 
00267 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00268   long long* MyGlobalElements64() const;
00269   void MyGlobalElementsPtr(long long *& MyGlobalElementList) const;
00270 #endif
00271   long long IndexBase64() const {return Data_->IndexBase_;}
00272 
00273   int MinLID() const;
00274   int MaxLID() const;
00275 
00276   bool GlobalIndicesInt() const { return IsInt; }
00277   bool GlobalIndicesLongLong() const { return IsLongLong; }
00278  private:
00279   void CleanupData();
00280   LightweightMapData *Data_;
00281   bool IsLongLong;
00282   bool IsInt;
00283   //Epetra_BlockMapData* Data_;
00284 
00285 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00286   void Construct_int(int NumGlobalElements,int NumMyElements, const int * MyGlobalElements, long long IndexBase, bool GenerateHash=true);
00287 #endif
00288 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00289   void Construct_LL(long long NumGlobalElements,int NumMyElements, const long long * MyGlobalElements, long long IndexBase, bool GenerateHash=true);
00290 #endif
00291 };
00292 
00293 
00294 // ==============================================================
00295 class RemoteOnlyImport {
00296  public:
00297   RemoteOnlyImport(const Epetra_Import & Importer, LightweightMap & RemoteOnlyTargetMap);
00298   ~RemoteOnlyImport();
00299 
00300   int NumSameIDs() {return 0;}
00301 
00302   int NumPermuteIDs() {return 0;} 
00303 
00304   int NumRemoteIDs() {return NumRemoteIDs_;}
00305 
00306   int NumExportIDs() {return NumExportIDs_;}
00307 
00308   int* ExportLIDs() {return ExportLIDs_;}
00309 
00310   int* ExportPIDs() {return ExportPIDs_;}
00311 
00312   int* RemoteLIDs() {return RemoteLIDs_;}  
00313 
00314   int* PermuteToLIDs() {return 0;}
00315 
00316   int* PermuteFromLIDs() {return 0;}
00317 
00318   int NumSend() {return NumSend_;}
00319   
00320   Epetra_Distributor & Distributor() {return *Distor_;}  
00321 
00322   const Epetra_BlockMap & SourceMap() const {return *SourceMap_;}
00323   const LightweightMap & TargetMap() const {return *TargetMap_;}
00324 
00325  private:
00326   int NumSend_;
00327   int NumRemoteIDs_;
00328   int NumExportIDs_;
00329   int * ExportLIDs_;
00330   int * ExportPIDs_;
00331   int * RemoteLIDs_;
00332   Epetra_Distributor* Distor_;
00333   const Epetra_BlockMap* SourceMap_;
00334   const LightweightMap  *TargetMap_;
00335 };
00336    
00337 // ==============================================================
00338 class LightweightCrsMatrix {
00339  public:
00340   LightweightCrsMatrix(const Epetra_CrsMatrix & A, RemoteOnlyImport & RowImporter);
00341   LightweightCrsMatrix(const Epetra_CrsMatrix & A, Epetra_Import & RowImporter);
00342   ~LightweightCrsMatrix();
00343 
00344   // Standard crs data structures
00345   std::vector<int>    rowptr_;
00346   std::vector<int>    colind_;
00347   std::vector<double> vals_;
00348 
00349 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00350   // Colind in LL-GID space (if needed)
00351   std::vector<long long>   colind_LL_;
00352 #endif
00353 
00354   // Epetra Maps
00355   bool                     use_lw;
00356   LightweightMap           *RowMapLW_;
00357   Epetra_BlockMap          *RowMapEP_;
00358   LightweightMap           ColMap_;
00359   Epetra_Map               DomainMap_;
00360 
00361 
00362   // List of owning PIDs (from the DomainMap) as ordered by entries in the column map.
00363   std::vector<int>    ColMapOwningPIDs_;
00364 
00365   // For building the final importer for C
00366   std::vector<int>    ExportLIDs_;
00367   std::vector<int>    ExportPIDs_;
00368 
00369  private: 
00370 
00371   template <typename ImportType, typename int_type>
00372   void Construct(const Epetra_CrsMatrix & A, ImportType & RowImporter);
00373 
00374   // Templated versions of MakeColMapAndReindex (to prevent code duplication)
00375   template <class GO>
00376   int MakeColMapAndReindex(std::vector<int> owningPIDs,std::vector<GO> Gcolind);
00377 
00378   template<typename int_type>
00379   std::vector<int_type>& getcolind();
00380 
00381   template<typename ImportType, typename int_type>
00382   int PackAndPrepareReverseComm(const Epetra_CrsMatrix & SourceMatrix, ImportType & RowImporter,
00383         std::vector<int> &ReverseSendSizes, std::vector<int_type> &ReverseSendBuffer);
00384 
00385   template<typename ImportType, typename int_type>
00386   int MakeExportLists(const Epetra_CrsMatrix & SourceMatrix, ImportType & RowImporter,
00387           std::vector<int> &ReverseRecvSizes, const int_type *ReverseRecvBuffer,
00388           std::vector<int> & ExportPIDs, std::vector<int> & ExportLIDs);
00389 
00390 };
00391 
00392 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00393 template<> inline std::vector<int>& LightweightCrsMatrix::getcolind() { return colind_; }
00394 #endif
00395 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00396 template<> inline std::vector<long long>& LightweightCrsMatrix::getcolind() { return colind_LL_; }
00397 #endif
00398 
00399 }//namespace EpetraExt
00400 
00401 #endif
00402 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines