58 namespace Epetra_Import_Util {
62 template<
typename int_type>
71 std::vector<int>& pids)
75 int TotalSendLength = 0;
77 if( NumExportIDs>0 ) IntSizes =
new int[NumExportIDs];
79 int SizeofIntType =
sizeof(int_type);
81 for(
int i = 0; i < NumExportIDs; ++i) {
86 Sizes[i] = NumEntries;
88 IntSizes[i] = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
89 TotalSendLength += (Sizes[i]+IntSizes[i]);
92 double * DoubleExports = 0;
93 SizeOfPacket = (int)
sizeof(
double);
96 if( TotalSendLength*SizeOfPacket > LenExports ) {
97 if( LenExports > 0 )
delete [] Exports;
98 LenExports = TotalSendLength*SizeOfPacket;
99 DoubleExports =
new double[TotalSendLength];
100 for(
int i = 0; i < TotalSendLength; ++i ) DoubleExports[i] = 0.0;
101 Exports = (
char *) DoubleExports;
106 double * valptr, * dintptr;
118 if (NumExportIDs > 0) {
124 std::vector<int> MyIndices(maxNumEntries);
127 dintptr = (
double *) Exports;
128 valptr = dintptr + IntSizes[0];
131 intptr = (int_type *) dintptr;
132 for (
int i = 0; i < NumExportIDs; ++i) {
133 FromRow = (int_type) rowMap.
GID64(ExportLIDs[i]);
136 Indices = intptr + 2;
138 for (
int j = 0; j < NumEntries; ++j) {
139 Indices[2*j] = (int_type) colMap.
GID64(MyIndices[j]);
140 Indices[2*j+1] = pids[MyIndices[j]];
142 intptr[1] = NumEntries;
143 if (i < (NumExportIDs-1)) {
144 dintptr += (IntSizes[i]+Sizes[i]);
145 valptr = dintptr + IntSizes[i+1];
148 intptr = (int_type *) dintptr;
152 for (
int i = 0; i < NumExportIDs; ++i) {
153 Sizes[i] += IntSizes[i];
157 if( IntSizes )
delete [] IntSizes;
173 std::vector<int>& SourcePids)
176 return TPackAndPrepareWithOwningPIDs<int>(SourceMatrix,NumExportIDs,ExportLIDs,LenExports,Exports,SizeOfPacket,Sizes,VarSizes,SourcePids);
179 return TPackAndPrepareWithOwningPIDs<long long>(SourceMatrix,NumExportIDs,ExportLIDs,LenExports,Exports,SizeOfPacket,Sizes,VarSizes,SourcePids);
182 throw std::runtime_error(
"UnpackWithOwningPIDsCount: Unable to determine source global index type");
188 template<
typename int_type>
195 const int *PermuteFromLIDs,
200 int SizeofIntType = (int)
sizeof(int_type);
203 for(i=0; i<NumSameIDs; i++)
207 for(i=0; i<NumPermuteIDs; i++)
211 if(NumRemoteIDs > 0) {
212 double * dintptr = (
double *) Imports;
214 int_type * intptr = (int_type *) dintptr;
215 int NumEntries = (int) intptr[1];
216 int IntSize = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
217 for(i=0; i<NumRemoteIDs; i++) {
220 if( i < (NumRemoteIDs-1) ) {
221 dintptr += IntSize + NumEntries;
222 intptr = (int_type *) dintptr;
223 NumEntries = (int) intptr[1];
224 IntSize = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
238 const int * RemoteLIDs,
240 const int *PermuteToLIDs,
241 const int *PermuteFromLIDs,
246 return TUnpackWithOwningPIDsCount<int>(SourceMatrix,NumSameIDs,NumRemoteIDs,RemoteLIDs,NumPermuteIDs,
247 PermuteToLIDs,PermuteFromLIDs,LenImports,Imports);
250 return TUnpackWithOwningPIDsCount<long long>(SourceMatrix,NumSameIDs,NumRemoteIDs,RemoteLIDs,NumPermuteIDs,
251 PermuteToLIDs,PermuteFromLIDs,LenImports,Imports);
254 throw std::runtime_error(
"UnpackWithOwningPIDsCount: Unable to determine source global index type");
261 template<
typename int_type>
265 const int * RemoteLIDs,
267 const int *PermuteToLIDs,
268 const int *PermuteFromLIDs,
272 int TargetNumNonzeros,
275 int_type * CSR_colind,
277 const std::vector<int> &SourcePids,
278 std::vector<int> &TargetPids)
291 int N = TargetNumRows;
292 int mynnz = TargetNumNonzeros;
294 int MyPID = MyTargetPID;
296 int SizeofIntType =
sizeof(int_type);
299 for(i=0; i<N+1; i++) CSR_rowptr[i]=0;
302 for(i=0; i<NumSameIDs; i++)
306 for(i=0; i<NumPermuteIDs; i++)
307 CSR_rowptr[PermuteToLIDs[i]] = SourceMatrix.
NumMyEntries(PermuteFromLIDs[i]);
310 if(NumRemoteIDs > 0) {
311 double * dintptr = (
double *) Imports;
312 int_type * intptr = (int_type *) dintptr;
313 int NumEntries = (int) intptr[1];
314 int IntSize = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
315 for(i=0; i<NumRemoteIDs; i++) {
316 CSR_rowptr[RemoteLIDs[i]] += NumEntries;
318 if( i < (NumRemoteIDs-1) ) {
319 dintptr += IntSize + NumEntries;
320 intptr = (int_type *) dintptr;
321 NumEntries = (int) intptr[1];
322 IntSize = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
328 std::vector<int> NewStartRow(N+1);
331 int last_len = CSR_rowptr[0];
333 for(i=1; i<N+1; i++){
334 int new_len = CSR_rowptr[i];
335 CSR_rowptr[i] = last_len + CSR_rowptr[i-1];
336 NewStartRow[i] = CSR_rowptr[i];
341 if(TargetPids.size()!=(size_t)mynnz) TargetPids.resize(mynnz);
342 TargetPids.assign(mynnz,-1);
345 int * Source_rowptr, * Source_colind;
346 double * Source_vals;
348 if(rv)
throw std::runtime_error(
"UnpackAndCombineIntoCrsArrays: failed in ExtractCrsDataPointers");
351 for(i=0; i<NumSameIDs; i++) {
352 int FromRow = Source_rowptr[i];
353 int ToRow = CSR_rowptr[i];
354 NewStartRow[i] += Source_rowptr[i+1]-Source_rowptr[i];
356 for(j=Source_rowptr[i]; j<Source_rowptr[i+1]; j++) {
357 CSR_vals[ToRow + j - FromRow] = Source_vals[j];
358 CSR_colind[ToRow + j - FromRow] = (int_type) SourceMatrix.
GCID64(Source_colind[j]);
359 TargetPids[ToRow + j - FromRow] = (SourcePids[Source_colind[j]] != MyPID) ? SourcePids[Source_colind[j]] : -1;
364 for(i=0; i<NumPermuteIDs; i++) {
365 int FromLID = PermuteFromLIDs[i];
366 int FromRow = Source_rowptr[FromLID];
367 int ToRow = CSR_rowptr[PermuteToLIDs[i]];
369 NewStartRow[PermuteToLIDs[i]] += Source_rowptr[FromLID+1]-Source_rowptr[FromLID];
371 for(j=Source_rowptr[FromLID]; j<Source_rowptr[FromLID+1]; j++) {
372 CSR_vals[ToRow + j - FromRow] = Source_vals[j];
373 CSR_colind[ToRow + j - FromRow] = (int_type) SourceMatrix.
GCID64(Source_colind[j]);
374 TargetPids[ToRow + j - FromRow] = (SourcePids[Source_colind[j]] != MyPID) ? SourcePids[Source_colind[j]] : -1;
379 if(NumRemoteIDs > 0) {
380 double * dintptr = (
double *) Imports;
381 int_type * intptr = (int_type *) dintptr;
382 int NumEntries = (int) intptr[1];
383 int IntSize = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
384 double* valptr = dintptr + IntSize;
386 for (i=0; i<NumRemoteIDs; i++) {
387 int ToLID = RemoteLIDs[i];
388 int StartRow = NewStartRow[ToLID];
389 NewStartRow[ToLID]+=NumEntries;
391 double * values = valptr;
392 int_type * Indices = intptr + 2;
393 for(j=0; j<NumEntries; j++){
394 CSR_vals[StartRow + j] = values[j];
395 CSR_colind[StartRow + j] = Indices[2*j];
396 TargetPids[StartRow + j] = (Indices[2*j+1] != MyPID) ? Indices[2*j+1] : -1;
398 if( i < (NumRemoteIDs-1) ) {
399 dintptr += IntSize + NumEntries;
400 intptr = (int_type *) dintptr;
401 NumEntries = (int) intptr[1];
402 IntSize = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)
sizeof(
double));
403 valptr = dintptr + IntSize;
418 const int * RemoteLIDs,
420 const int *PermuteToLIDs,
421 const int *PermuteFromLIDs,
425 int TargetNumNonzeros,
430 const std::vector<int> &SourcePids,
431 std::vector<int> &TargetPids)
434 return TUnpackAndCombineIntoCrsArrays<int>(SourceMatrix,NumSameIDs,NumRemoteIDs,RemoteLIDs,NumPermuteIDs,
435 PermuteToLIDs,PermuteFromLIDs,LenImports,Imports,TargetNumRows,TargetNumNonzeros,MyTargetPID,
436 CSR_rowptr,CSR_colind,CSR_values,SourcePids,TargetPids);
439 throw std::runtime_error(
"UnpackAndCombineIntoCrsArrays: int type not matched.");
447 const int * RemoteLIDs,
449 const int *PermuteToLIDs,
450 const int *PermuteFromLIDs,
454 int TargetNumNonzeros,
457 long long * CSR_colind,
459 const std::vector<int> &SourcePids,
460 std::vector<int> &TargetPids)
463 return TUnpackAndCombineIntoCrsArrays<long long>(SourceMatrix,NumSameIDs,NumRemoteIDs,RemoteLIDs,NumPermuteIDs,
464 PermuteToLIDs,PermuteFromLIDs,LenImports,Imports,TargetNumRows,TargetNumNonzeros,MyTargetPID,
465 CSR_rowptr,CSR_colind,CSR_values,SourcePids,TargetPids);
468 throw std::runtime_error(
"UnpackAndCombineIntoCrsArrays: int type not matched.");
474 template<
typename int_type,
class MapType1,
class MapType2>
475 int TLowCommunicationMakeColMapAndReindex(
int N,
const int * rowptr,
int * colind_LID,
const int_type *colind_GID,
const Epetra_Map& domainMap,
const int * owningPIDs,
bool SortGhostsAssociatedWithEachProcessor, std::vector<int>& RemotePIDs, MapType1 & NewColMap)
484 else throw std::runtime_error(
"LowCommunicationMakeColMapAndReindex: cannot detect int type.");
490 bool * LocalGIDs = 0;
491 if (numDomainElements>0) LocalGIDs =
new bool[numDomainElements];
492 for (i=0; i<numDomainElements; i++) LocalGIDs[i] =
false;
495 if(DoSizes)
throw std::runtime_error(
"LowCommunicationMakeColMapAndReindex: cannot handle non-constant sized domainMap.");
501 const int numMyBlockRows = N;
502 int hashsize = numMyBlockRows;
if (hashsize < 100) hashsize = 100;
504 std::vector<int_type> RemoteGIDList; RemoteGIDList.reserve(hashsize);
505 std::vector<int> PIDList; PIDList.reserve(hashsize);
514 int NumLocalColGIDs = 0;
515 int NumRemoteColGIDs = 0;
516 for(i = 0; i < numMyBlockRows; i++) {
517 for(j = rowptr[i]; j < rowptr[i+1]; j++) {
518 int_type GID = colind_GID[j];
520 int LID = domainMap.
LID(GID);
522 bool alreadyFound = LocalGIDs[LID];
524 LocalGIDs[LID] =
true;
530 int_type hash_value=RemoteGIDs.
Get(GID);
531 if(hash_value == -1) {
532 int PID = owningPIDs[j];
533 if(PID==-1)
throw std::runtime_error(
"LowCommunicationMakeColMapAndReindex: Cannot figure out if PID is owned.");
534 colind_LID[j] = numDomainElements + NumRemoteColGIDs;
535 RemoteGIDs.
Add(GID, NumRemoteColGIDs);
536 RemoteGIDList.push_back(GID);
537 PIDList.push_back(PID);
541 colind_LID[j] = numDomainElements + hash_value;
549 if (NumRemoteColGIDs!=0) {
550 throw std::runtime_error(
"Some column IDs are not in domainMap. If matrix is rectangular, you must pass in a domainMap");
553 if (NumLocalColGIDs==numDomainElements) {
554 if (LocalGIDs!=0)
delete [] LocalGIDs;
557 NewColMap = domainMap;
564 int numMyBlockCols = NumLocalColGIDs + NumRemoteColGIDs;
565 std::vector<int_type> ColIndices;
566 int_type * RemoteColIndices=0;
567 if(numMyBlockCols > 0) {
568 ColIndices.resize(numMyBlockCols);
569 if(NumLocalColGIDs!=numMyBlockCols) RemoteColIndices = &ColIndices[NumLocalColGIDs];
570 else RemoteColIndices=0;
573 for(i = 0; i < NumRemoteColGIDs; i++)
574 RemoteColIndices[i] = RemoteGIDList[i];
577 std::vector<int> RemotePermuteIDs(NumRemoteColGIDs);
578 for(i=0; i<NumRemoteColGIDs; i++) RemotePermuteIDs[i]=i;
583 int * IntSortLists[2];
584 long long * LLSortLists[2];
588 IntSortLists[0] = (
int*) RemoteColIndices;
589 IntSortLists[1] = RemotePermuteIDs_ptr;
594 LLSortLists[0] = (
long long*) RemoteColIndices;
595 IntSortLists[0] = RemotePermuteIDs_ptr;
596 NumListsInt = NumListsLL = 1;
600 Epetra_Util::Sort(
true, NumRemoteColGIDs, PIDList_ptr, 0, 0, NumListsInt, IntSortLists,NumListsLL,LLSortLists);
603 PIDList.resize(NumRemoteColGIDs);
604 RemotePIDs = PIDList;
606 if (SortGhostsAssociatedWithEachProcessor) {
612 int StartCurrent, StartNext;
613 StartCurrent = 0; StartNext = 1;
614 while ( StartNext < NumRemoteColGIDs ) {
615 if (PIDList[StartNext]==PIDList[StartNext-1]) StartNext++;
617 IntSortLists[0] = &RemotePermuteIDs[StartCurrent];
618 Epetra_Util::Sort(
true,StartNext-StartCurrent, &(RemoteColIndices[StartCurrent]),0,0,1,IntSortLists,0,0);
619 StartCurrent = StartNext; StartNext++;
622 IntSortLists[0] = &RemotePermuteIDs[StartCurrent];
623 Epetra_Util::Sort(
true, StartNext-StartCurrent, &(RemoteColIndices[StartCurrent]), 0, 0, 1,IntSortLists,0,0);
627 std::vector<int> ReverseRemotePermuteIDs(NumRemoteColGIDs);
628 for(i=0; i<NumRemoteColGIDs; i++) ReverseRemotePermuteIDs[RemotePermuteIDs[i]]=i;
631 bool use_local_permute=
false;
632 std::vector<int> LocalPermuteIDs(numDomainElements);
641 if(NumLocalColGIDs > 0) {
646 int_type* MyGlobalElements = 0;
649 int NumLocalAgain = 0;
650 use_local_permute =
true;
651 for(i = 0; i < numDomainElements; i++) {
653 LocalPermuteIDs[i] = NumLocalAgain;
654 ColIndices[NumLocalAgain++] = MyGlobalElements[i];
657 assert(NumLocalAgain==NumLocalColGIDs);
661 if (LocalGIDs!=0)
delete [] LocalGIDs;
665 MapType2 temp((int_type)(-1), numMyBlockCols, ColIndices_ptr, (int_type)domainMap.
IndexBase64(), domainMap.
Comm());
669 for(i=0; i<numMyBlockRows; i++){
670 for(j=rowptr[i]; j<rowptr[i+1]; j++){
671 int ID=colind_LID[j];
672 if(ID < numDomainElements){
673 if(use_local_permute) colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
678 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j]-numDomainElements];
688 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
693 return TLowCommunicationMakeColMapAndReindex<int,Epetra_BlockMap,Epetra_Map>(N,rowptr,colind,colind,domainMap,owningPIDs,SortGhostsAssociatedWithEachProcessor,RemotePIDs,NewColMap);
695 throw std::runtime_error(
"LowCommunicationMakeColMapAndReindex: GID type mismatch.");
702 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
707 return TLowCommunicationMakeColMapAndReindex<long long,Epetra_BlockMap,Epetra_Map>(N,rowptr,colind_LID,colind_GID,domainMap,owningPIDs,SortGhostsAssociatedWithEachProcessor,RemotePIDs,NewColMap);
709 throw std::runtime_error(
"LowCommunicationMakeColMapAndReindex: GID type mismatch.");
int NumMyRowEntries(int MyRow, int &NumEntries) const
Return the current number of values stored for the specified local row.
Epetra_Map: A class for partitioning vectors and matrices.
int TLowCommunicationMakeColMapAndReindex(int N, const int *rowptr, int *colind_LID, const int_type *colind_GID, const Epetra_Map &domainMap, const int *owningPIDs, bool SortGhostsAssociatedWithEachProcessor, std::vector< int > &RemotePIDs, MapType1 &NewColMap)
int NumMyEntries(int Row) const
Returns the current number of nonzero entries in specified local row on this processor.
bool GlobalIndicesLongLong() const
Returns true if map create with long long NumGlobalElements.
long long IndexBase64() const
int MyGlobalElements(int *MyGlobalElementList) const
Puts list of global elements on this processor into the user-provided array.
value_type Get(const long long key)
int UnpackWithOwningPIDsCount(const Epetra_CrsMatrix &SourceMatrix, int NumSameIDs, int NumRemoteIDs, const int *RemoteLIDs, int NumPermuteIDs, const int *PermuteToLIDs, const int *PermuteFromLIDs, int LenImports, char *Imports)
UnpackWithOwningPIDsCount.
bool ConstantElementSize() const
Returns true if map has constant element size.
T * Epetra_Util_data_ptr(std::vector< T > &vec)
Function that returns either a pointer to the first entry in the vector or, if the vector is empty...
#define EPETRA_CHK_ERR(a)
bool GlobalIndicesInt() const
Returns true if map create with int NumGlobalElements.
int PackAndPrepareWithOwningPIDs(const Epetra_CrsMatrix &SourceMatrix, int NumExportIDs, int *ExportLIDs, int &LenExports, char *&Exports, int &SizeOfPacket, int *Sizes, bool &VarSizes, std::vector< int > &SourcePids)
PackAndPrepareWithOwningPIDs.
const Epetra_Map & ColMap() const
Returns the Epetra_Map object that describes the set of column-indices that appear in each processor'...
const Epetra_Map & RowMap() const
Returns the Epetra_Map object associated with the rows of this matrix.
int NumMyElements() const
Number of elements on the calling processor.
int UnpackAndCombineIntoCrsArrays(const Epetra_CrsMatrix &SourceMatrix, int NumSameIDs, int NumRemoteIDs, const int *RemoteLIDs, int NumPermuteIDs, const int *PermuteToLIDs, const int *PermuteFromLIDs, int LenImports, char *Imports, int TargetNumRows, int TargetNumNonzeros, int MyTargetPID, int *CSR_rowptr, int *CSR_colind, double *CSR_values, const std::vector< int > &SourcePids, std::vector< int > &TargetPids)
UnpackAndCombineIntoCrsArrays.
long long GID64(int LID) const
int MaxNumEntries() const
Returns the maximum number of nonzero entries across all rows on this processor.
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
int MyGlobalElementsPtr(int *&MyGlobalElementList) const
int LID(int GID) const
Returns local ID of global ID, return -1 if not found on this processor.
int LowCommunicationMakeColMapAndReindex(int N, const int *rowptr, int *colind, const Epetra_Map &domainMap, const int *owningPIDs, bool SortGhostsAssociatedWithEachProcessor, std::vector< int > &RemotePIDs, Epetra_BlockMap &NewColMap)
LowCommunicationMakeColMapAndReindex.
int TUnpackAndCombineIntoCrsArrays(const Epetra_CrsMatrix &SourceMatrix, int NumSameIDs, int NumRemoteIDs, const int *RemoteLIDs, int NumPermuteIDs, const int *PermuteToLIDs, const int *PermuteFromLIDs, int, char *Imports, int TargetNumRows, int TargetNumNonzeros, int MyTargetPID, int *CSR_rowptr, int_type *CSR_colind, double *CSR_vals, const std::vector< int > &SourcePids, std::vector< int > &TargetPids)
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
int TUnpackWithOwningPIDsCount(const Epetra_CrsMatrix &SourceMatrix, int NumSameIDs, int NumRemoteIDs, const int *, int NumPermuteIDs, const int *, const int *PermuteFromLIDs, int, char *Imports)
virtual int NumProc() const =0
Returns total number of processes.
Epetra_CrsMatrix: A class for constructing and using real-valued double-precision sparse compressed r...
static void EPETRA_LIB_DLL_EXPORT Sort(bool SortAscending, int NumKeys, T *Keys, int NumDoubleCompanions, double **DoubleCompanions, int NumIntCompanions, int **IntCompanions, int NumLongLongCompanions, long long **LongLongCompanions)
Epetra_Util Sort Routine (Shell sort)
int ExtractMyRowCopy(int MyRow, int Length, int &NumEntries, double *Values, int *Indices) const
Returns a copy of the specified local row in user-provided arrays.
int TPackAndPrepareWithOwningPIDs(const Epetra_CrsMatrix &A, int NumExportIDs, int *ExportLIDs, int &LenExports, char *&Exports, int &SizeOfPacket, int *Sizes, bool &VarSizes, std::vector< int > &pids)
long long GCID64(int LCID_in) const
void Add(const long long key, const value_type value)
int ExtractCrsDataPointers(int *&IndexOffset, int *&Indices, double *&Values_in) const
Returns internal data pointers associated with Crs matrix format.