EpetraExt Development
Loading...
Searching...
No Matches
EpetraExt_MMHelpers.h
Go to the documentation of this file.
1//@HEADER
2// ***********************************************************************
3//
4// EpetraExt: Epetra Extended - Linear Algebra Services Package
5// Copyright (2011) Sandia Corporation
6//
7// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8// the U.S. Government retains certain rights in this software.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ***********************************************************************
40//@HEADER
41
42#ifndef EPETRAEXT_MMHELPERS_H
43#define EPETRAEXT_MMHELPERS_H
44
45#if defined(EpetraExt_SHOW_DEPRECATED_WARNINGS)
46#ifdef __GNUC__
47#warning "The EpetraExt package is deprecated"
48#endif
49#endif
50
52#include "Epetra_ConfigDefs.h"
53#include "Epetra_DistObject.h"
54#include "Epetra_Map.h"
55#include "Teuchos_RCP.hpp"
56#include "Epetra_Comm.h"
57#include "Epetra_Import.h"
58#include "Epetra_CrsMatrix.h"
59#include <Teuchos_TimeMonitor.hpp>
60
61#include <vector>
62#include <set>
63#include <map>
64
65
67
68namespace EpetraExt {
69class LightweightCrsMatrix;
70
71//#define HAVE_EPETRAEXT_DEBUG // for extra sanity checks
72
73
74
75
76// ==============================================================
77//struct that holds views of the contents of a CrsMatrix. These
78//contents may be a mixture of local and remote rows of the
79//actual matrix.
81public:
83
84 virtual ~CrsMatrixStruct();
85
86 void deleteContents();
87
89
90 // The following class members get used in the transpose modes of the MMM
91 // but not in the A*B mode.
93 int** indices;
94 double** values;
95 bool* remote;
98
99 // Maps and matrices (all modes)
106
107 // The following class members are only used for A*B mode
108 std::vector<int> targetMapToOrigRow;
109 std::vector<int> targetMapToImportRow;
110};
111
113
114// ==============================================================
116 public:
117 virtual ~CrsWrapper(){}
118
119 virtual const Epetra_Map& RowMap() const = 0;
120
121 virtual bool Filled() = 0;
122
123#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
124 virtual int InsertGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices) = 0;
125
126 virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices) = 0;
127#endif
128
129#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
130 virtual int InsertGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices) = 0;
131
132 virtual int SumIntoGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices) = 0;
133#endif
134};
135
136// ==============================================================
138 public:
141
142 const Epetra_Map& RowMap() const;
143
144 bool Filled();
145
146#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
147 int InsertGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices);
148 int SumIntoGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices);
149#endif
150
151#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
152 int InsertGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices);
153 int SumIntoGlobalValues(long long GlobalRow, int NumEntries, double* Values, long long* Indices);
154#endif
155
156 private:
157 Epetra_CrsMatrix& ecrsmat_;
158};
159
160// ==============================================================
161template<typename int_type>
163 public:
165 virtual ~CrsWrapper_GraphBuilder();
166
167 const Epetra_Map& RowMap() const {return rowmap_; }
168
169 bool Filled();
170
171 int InsertGlobalValues(int_type GlobalRow, int NumEntries, double* Values, int_type* Indices);
172 int SumIntoGlobalValues(int_type GlobalRow, int NumEntries, double* Values, int_type* Indices);
173
174 std::map<int_type,std::set<int_type>*>& get_graph();
175
176 int get_max_row_length() { return max_row_length_; }
177
178 private:
179 std::map<int_type,std::set<int_type>*> graph_;
180 const Epetra_Map& rowmap_;
181 int max_row_length_;
182};
183
184// ==============================================================
185template<typename int_type>
186void insert_matrix_locations(CrsWrapper_GraphBuilder<int_type>& graphbuilder,
188
189template<typename int_type>
191 const std::vector<int_type>& proc_col_ranges,
192 std::vector<int_type>& send_rows,
193 std::vector<int>& rows_per_send_proc);
194
195#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
197 const std::vector<int>& proc_col_ranges,
198 std::vector<int>& send_rows,
199 std::vector<int>& rows_per_send_proc);
200#endif
201
202#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
204 const std::vector<long long>& proc_col_ranges,
205 std::vector<long long>& send_rows,
206 std::vector<int>& rows_per_send_proc);
207#endif
208
209template<typename int_type>
210std::pair<int_type,int_type> get_col_range(const Epetra_Map& emap);
211
212template<typename int_type>
213std::pair<int_type,int_type> get_col_range(const Epetra_CrsMatrix& mtx);
214
215// ==============================================================
217 friend class LightweightMap;
218 public:
221 long long IndexBase_;
222#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
223 std::vector<int> MyGlobalElements_int_;
225#endif
226#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
227 std::vector<long long> MyGlobalElements_LL_;
229#endif
230
231 // For "copy" constructor only...
233
234 };
235
237 public:
239#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
240 LightweightMap(int NumGlobalElements,int NumMyElements, const int * MyGlobalElements, int IndexBase, bool GenerateHash=true);
241#endif
242#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
243 LightweightMap(long long NumGlobalElements,int NumMyElements, const long long * MyGlobalElements, int IndexBase, bool GenerateHash=true);
244 LightweightMap(long long NumGlobalElements,int NumMyElements, const long long * MyGlobalElements, long long IndexBase, bool GenerateHash=true);
245#endif
246 LightweightMap(const Epetra_Map & Map);
247 LightweightMap(const LightweightMap & Map);
249
251#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
252 int LID(int GID) const;
253 int GID(int LID) const;
254#endif
255
256#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
257 int LID(long long GID) const;
258#endif
259 long long GID64(int LID) const;
260 int NumMyElements() const;
261
262#if defined(EPETRA_NO_32BIT_GLOBAL_INDICES) && defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
263 // default implementation so that no compiler/linker error in case neither 32 nor 64
264 // bit indices present.
265 int LID(long long GID) const { return -1; }
266#endif
267
268#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
269 int* MyGlobalElements() const;
270 int IndexBase() const {
271 if(IndexBase64() == (long long) static_cast<int>(IndexBase64()))
272 return (int) IndexBase64();
273 throw "EpetraExt::LightweightMap::IndexBase: IndexBase cannot fit an int.";
274 }
275 void MyGlobalElementsPtr(int *& MyGlobalElementList) const;
276#endif
277
278#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
279 long long* MyGlobalElements64() const;
280 void MyGlobalElementsPtr(long long *& MyGlobalElementList) const;
281#endif
282 long long IndexBase64() const {return Data_->IndexBase_;}
283
284 int MinLID() const;
285 int MaxLID() const;
286
287 bool GlobalIndicesInt() const { return IsInt; }
288 bool GlobalIndicesLongLong() const { return IsLongLong; }
289 private:
290 void CleanupData();
291 LightweightMapData *Data_;
292 bool IsLongLong;
293 bool IsInt;
294 //Epetra_BlockMapData* Data_;
295
296#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
297 void Construct_int(int NumGlobalElements,int NumMyElements, const int * MyGlobalElements, long long IndexBase, bool GenerateHash=true);
298#endif
299#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
300 void Construct_LL(long long NumGlobalElements,int NumMyElements, const long long * MyGlobalElements, long long IndexBase, bool GenerateHash=true);
301#endif
302};
303
304
305// ==============================================================
307 public:
308 RemoteOnlyImport(const Epetra_Import & Importer, LightweightMap & RemoteOnlyTargetMap);
310
311 int NumSameIDs() {return 0;}
312
313 int NumPermuteIDs() {return 0;}
314
315 int NumRemoteIDs() {return NumRemoteIDs_;}
316
317 int NumExportIDs() {return NumExportIDs_;}
318
319 int* ExportLIDs() {return ExportLIDs_;}
320
321 int* ExportPIDs() {return ExportPIDs_;}
322
323 int* RemoteLIDs() {return RemoteLIDs_;}
324
325 int* PermuteToLIDs() {return 0;}
326
327 int* PermuteFromLIDs() {return 0;}
328
329 int NumSend() {return NumSend_;}
330
331 Epetra_Distributor & Distributor() {return *Distor_;}
332
333 const Epetra_BlockMap & SourceMap() const {return *SourceMap_;}
334 const LightweightMap & TargetMap() const {return *TargetMap_;}
335
336 private:
337 int NumSend_;
338 int NumRemoteIDs_;
339 int NumExportIDs_;
340 int * ExportLIDs_;
341 int * ExportPIDs_;
342 int * RemoteLIDs_;
343 Epetra_Distributor* Distor_;
344 const Epetra_BlockMap* SourceMap_;
345 const LightweightMap *TargetMap_;
346};
347
348// ==============================================================
350 public:
351 LightweightCrsMatrix(const Epetra_CrsMatrix & A, RemoteOnlyImport & RowImporter, bool SortGhosts=false,const char * label=0);
352 LightweightCrsMatrix(const Epetra_CrsMatrix & A, Epetra_Import & RowImporter);
354
355 // Standard crs data structures
356 std::vector<int> rowptr_;
357 std::vector<int> colind_;
358 std::vector<double> vals_;
359
360#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
361 // Colind in LL-GID space (if needed)
362 std::vector<long long> colind_LL_;
363#endif
364
365 // Epetra Maps
366 bool use_lw;
371
372
373 // List of owning PIDs (from the DomainMap) as ordered by entries in the column map.
374 std::vector<int> ColMapOwningPIDs_;
375
376 // For building the final importer for C
377 std::vector<int> ExportLIDs_;
378 std::vector<int> ExportPIDs_;
379
380 private:
381
382 template <typename ImportType, typename int_type>
383 void Construct(const Epetra_CrsMatrix & A, ImportType & RowImporter,bool SortGhosts=false, const char * label=0);
384
385 // Templated versions of MakeColMapAndReindex (to prevent code duplication)
386 template <class GO>
387 int MakeColMapAndReindex(std::vector<int> owningPIDs,std::vector<GO> Gcolind,bool SortGhosts=false, const char * label=0);
388
389 template<typename int_type>
390 std::vector<int_type>& getcolind();
391
392 template<typename ImportType, typename int_type>
393 int PackAndPrepareReverseComm(const Epetra_CrsMatrix & SourceMatrix, ImportType & RowImporter,
394 std::vector<int> &ReverseSendSizes, std::vector<int_type> &ReverseSendBuffer);
395
396 template<typename ImportType, typename int_type>
397 int MakeExportLists(const Epetra_CrsMatrix & SourceMatrix, ImportType & RowImporter,
398 std::vector<int> &ReverseRecvSizes, const int_type *ReverseRecvBuffer,
399 std::vector<int> & ExportPIDs, std::vector<int> & ExportLIDs);
400
401};
402
403#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
404template<> inline std::vector<int>& LightweightCrsMatrix::getcolind() { return colind_; }
405#endif
406#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
407template<> inline std::vector<long long>& LightweightCrsMatrix::getcolind() { return colind_LL_; }
408#endif
409
410// ==============================================================
411template<typename int_type>
413 const Epetra_Map& targetMap,
414 CrsMatrixStruct& Mview,
415 const Epetra_Import * prototypeImporter=0,bool SortGhosts=false,
416 const char * label=0)
417{
418 // The goal of this method to populare the Mview object with ONLY the rows of M
419 // that correspond to elements in 'targetMap.' There will be no population of the
420 // numEntriesPerRow, indices, values, remote or numRemote arrays.
421
422
423 // The prototype importer, if used, has to know who owns all of the PIDs in M's rowmap.
424 // The typical use of this is to provide A's column map when I&XV is called for B, for
425 // a C = A * B multiply.
426
427#ifdef ENABLE_MMM_TIMINGS
428 std::string tpref;
429 if(label) tpref = std::string(label);
430 using Teuchos::TimeMonitor;
431 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(tpref + std::string("EpetraExt: MMM Ionly Setup"))));
432#endif
433
434 Mview.deleteContents();
435
436 Mview.origMatrix = &M;
437 const Epetra_Map& Mrowmap = M.RowMap();
438 int numProcs = Mrowmap.Comm().NumProc();
439 Mview.numRows = targetMap.NumMyElements();
440
441 Mview.origRowMap = &(M.RowMap());
442 Mview.rowMap = &targetMap;
443 Mview.colMap = &(M.ColMap());
444 Mview.domainMap = &(M.DomainMap());
445 Mview.importColMap = NULL;
446
447 int i;
448 int numRemote =0;
449 int N = Mview.rowMap->NumMyElements();
450
451 if(Mrowmap.SameAs(targetMap)) {
452 numRemote = 0;
453 Mview.targetMapToOrigRow.resize(N);
454 for(i=0;i<N; i++) Mview.targetMapToOrigRow[i]=i;
455 return 0;
456 }
457 else if(prototypeImporter && prototypeImporter->SourceMap().SameAs(M.RowMap()) && prototypeImporter->TargetMap().SameAs(targetMap)){
458 numRemote = prototypeImporter->NumRemoteIDs();
459
460 Mview.targetMapToOrigRow.resize(N); Mview.targetMapToOrigRow.assign(N,-1);
461 Mview.targetMapToImportRow.resize(N); Mview.targetMapToImportRow.assign(N,-1);
462
463 const int * PermuteToLIDs = prototypeImporter->PermuteToLIDs();
464 const int * PermuteFromLIDs = prototypeImporter->PermuteFromLIDs();
465 const int * RemoteLIDs = prototypeImporter->RemoteLIDs();
466
467 for(i=0; i<prototypeImporter->NumSameIDs();i++)
468 Mview.targetMapToOrigRow[i] = i;
469
470 // NOTE: These are reversed on purpose since we're doing a reverse map.
471 for(i=0; i<prototypeImporter->NumPermuteIDs();i++)
472 Mview.targetMapToOrigRow[PermuteToLIDs[i]] = PermuteFromLIDs[i];
473
474 for(i=0; i<prototypeImporter->NumRemoteIDs();i++)
475 Mview.targetMapToImportRow[RemoteLIDs[i]] = i;
476
477 }
478 else
479 throw std::runtime_error("import_only: This routine only works if you either have the right map or no prototypeImporter");
480
481 if (numProcs < 2) {
482 if (Mview.numRemote > 0) {
483 std::cerr << "EpetraExt::MatrixMatrix::Multiply ERROR, numProcs < 2 but "
484 << "attempting to import remote matrix rows."<<std::endl;
485 return(-1);
486 }
487
488 //If only one processor we don't need to import any remote rows, so return.
489 return(0);
490 }
491
492#ifdef ENABLE_MMM_TIMINGS
493 MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(tpref + std::string("EpetraExt: MMM Ionly Import-1"))));
494#endif
495 const int * RemoteLIDs = prototypeImporter->RemoteLIDs();
496
497 //Create a map that describes the remote rows of M that we need.
498 int_type* MremoteRows = numRemote>0 ? new int_type[prototypeImporter->NumRemoteIDs()] : 0;
499 for(i=0; i<prototypeImporter->NumRemoteIDs(); i++)
500 MremoteRows[i] = (int_type) targetMap.GID64(RemoteLIDs[i]);
501
502 LightweightMap MremoteRowMap((int_type) -1, numRemote, MremoteRows, (int_type)Mrowmap.IndexBase64());
503
504#ifdef ENABLE_MMM_TIMINGS
505 MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(tpref + std::string("EpetraExt: MMM Ionly Import-2"))));
506#endif
507 //Create an importer with target-map MremoteRowMap and
508 //source-map Mrowmap.
509 RemoteOnlyImport * Rimporter=0;
510 Rimporter = new RemoteOnlyImport(*prototypeImporter,MremoteRowMap);
511
512#ifdef ENABLE_MMM_TIMINGS
513 MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(tpref + std::string("EpetraExt: MMM Ionly Import-3"))));
514#endif
515
516 Mview.importMatrix = new LightweightCrsMatrix(M,*Rimporter,SortGhosts,label);
517
518#ifdef ENABLE_MMM_TIMINGS
519 MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(tpref + std::string("EpetraExt: MMM Ionly Import-4"))));
520#endif
521
522#ifdef ENABLE_MMM_STATISTICS
523 printMultiplicationStatistics(Rimporter, label + std::string(" I&X MMM"));
524#endif
525
526 // Cleanup
527 delete Rimporter;
528 delete [] MremoteRows;
529
530 return(0);
531}
532
533
534
535// Statistics printing routines for when ENABLE_MMM_STATISTICS is enabled
536void PrintMultiplicationStatistics(Epetra_Import * Transfer, const std::string &label);
537void PrintMultiplicationStatistics(Epetra_Export * Transfer, const std::string &label);
538
539
540}//namespace EpetraExt
541
542#endif
const Epetra_CrsMatrix * origMatrix
std::vector< int > targetMapToImportRow
LightweightCrsMatrix * importMatrix
const Epetra_BlockMap * importColMap
std::vector< int > targetMapToOrigRow
int SumIntoGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)
int InsertGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)
std::map< int_type, std::set< int_type > * > & get_graph()
int InsertGlobalValues(int_type GlobalRow, int NumEntries, double *Values, int_type *Indices)
int SumIntoGlobalValues(int_type GlobalRow, int NumEntries, double *Values, int_type *Indices)
virtual bool Filled()=0
virtual const Epetra_Map & RowMap() const =0
virtual int InsertGlobalValues(long long GlobalRow, int NumEntries, double *Values, long long *Indices)=0
virtual int SumIntoGlobalValues(long long GlobalRow, int NumEntries, double *Values, long long *Indices)=0
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)=0
virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)=0
std::vector< long long > colind_LL_
std::vector< long long > MyGlobalElements_LL_
Epetra_HashTable< int > * LIDHash_int_
Epetra_HashTable< long long > * LIDHash_LL_
LightweightMap & operator=(const LightweightMap &map)
long long GID64(int LID) const
long long * MyGlobalElements64() const
void MyGlobalElementsPtr(int *&MyGlobalElementList) const
const LightweightMap & TargetMap() const
Epetra_Distributor & Distributor()
const Epetra_BlockMap & SourceMap() const
bool SameAs(const Epetra_BlockMap &Map) const
const Epetra_Comm & Comm() const
int NumMyElements() const
virtual int NumProc() const=0
const Epetra_Map & RowMap() const
const Epetra_Map & ColMap() const
const Epetra_Map & DomainMap() const
EpetraExt::BlockCrsMatrix: A class for constructing a distributed block matrix.
void insert_matrix_locations(CrsWrapper_GraphBuilder< int_type > &graphbuilder, Epetra_CrsMatrix &C)
void pack_outgoing_rows(const Epetra_CrsMatrix &mtx, const std::vector< int > &proc_col_ranges, std::vector< int > &send_rows, std::vector< int > &rows_per_send_proc)
void PrintMultiplicationStatistics(Epetra_Import *Transfer, const std::string &label)
void printMultiplicationStatistics(Epetra_Import *Transfer, const std::string &label)
int import_only(const Epetra_CrsMatrix &M, const Epetra_Map &targetMap, CrsMatrixStruct &Mview, const Epetra_Import *prototypeImporter)
std::pair< int_type, int_type > get_col_range(const Epetra_Map &emap)
int dumpCrsMatrixStruct(const CrsMatrixStruct &M)
void Tpack_outgoing_rows(const Epetra_CrsMatrix &mtx, const std::vector< int_type > &proc_col_ranges, std::vector< int_type > &send_rows, std::vector< int > &rows_per_send_proc)