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) {
83 A.NumMyRowEntries( ExportLIDs[i], NumEntries );
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) {
123 int maxNumEntries =
A.MaxNumEntries();
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.");