|
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 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
1.7.6.1