//! Update matrix static void update(Epetra_CrsMatrix& mat, double a, const Epetra_CrsMatrix& x) { int num_col; for (int i=0; i<mat.NumMyRows(); i++) { mat.NumMyRowEntries(i, num_col); for (int j=0; j<num_col; j++) mat[i][j] += a*x[i][j]; } }
int TPackAndPrepareWithOwningPIDs(const Epetra_CrsMatrix & A, int NumExportIDs, int * ExportLIDs, int & LenExports, char *& Exports, int & SizeOfPacket, int * Sizes, bool & VarSizes, std::vector<int>& pids) { int i, j; VarSizes = true; //enable variable block size data comm int TotalSendLength = 0; int * IntSizes = 0; if( NumExportIDs>0 ) IntSizes = new int[NumExportIDs]; int SizeofIntType = sizeof(int_type); for(i = 0; i < NumExportIDs; ++i) { int NumEntries; A.NumMyRowEntries( ExportLIDs[i], NumEntries ); // Will have NumEntries doubles, 2*NumEntries +2 ints pack them interleaved Sizes[i] = NumEntries; // NTS: We add the owning PID as the SECOND int of the pair for each entry Sizes[i] = NumEntries; // NOTE: Mixing and matching Int Types would be more efficient, BUT what about variable alignment? IntSizes[i] = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)sizeof(double)); TotalSendLength += (Sizes[i]+IntSizes[i]); } double * DoubleExports = 0; SizeOfPacket = (int)sizeof(double); //setup buffer locally for memory management by this object if( TotalSendLength*SizeOfPacket > LenExports ) { if( LenExports > 0 ) delete [] Exports; LenExports = TotalSendLength*SizeOfPacket; DoubleExports = new double[TotalSendLength]; for( int i = 0; i < TotalSendLength; ++i ) DoubleExports[i] = 0.0; Exports = (char *) DoubleExports; } int NumEntries; double * values; double * valptr, * dintptr; // Each segment of Exports will be filled by a packed row of information for each row as follows: // 1st int: GRID of row where GRID is the global row ID for the source matrix // next int: NumEntries, Number of indices in row // next 2*NumEntries: The actual indices and owning [1] PID each for the row in (GID,PID) pairs with the GID first. // [1] Owning is defined in the sense of "Who owns the GID in the DomainMap," aka, who sends the GID in the importer const Epetra_Map & rowMap = A.RowMap(); const Epetra_Map & colMap = A.ColMap(); if( NumExportIDs > 0 ) { int_type * Indices; int_type FromRow; int_type * intptr; int maxNumEntries = A.MaxNumEntries(); std::vector<int> MyIndices(maxNumEntries); dintptr = (double *) Exports; valptr = dintptr + IntSizes[0]; intptr = (int_type *) dintptr; for (i=0; i<NumExportIDs; i++) { FromRow = (int_type) rowMap.GID64(ExportLIDs[i]); intptr[0] = FromRow; values = valptr; Indices = intptr + 2; EPETRA_CHK_ERR(A.ExtractMyRowCopy(ExportLIDs[i], maxNumEntries, NumEntries, values, &MyIndices[0])); for (j=0; j<NumEntries; j++) { Indices[2*j] = (int_type) colMap.GID64(MyIndices[j]); // convert to GIDs Indices[2*j+1] = pids[MyIndices[j]]; // PID owning the entry. } intptr[1] = NumEntries; // Load second slot of segment if( i < (NumExportIDs-1) ) { dintptr += (IntSizes[i]+Sizes[i]); valptr = dintptr + IntSizes[i+1]; intptr = (int_type *) dintptr; } } for(i = 0; i < NumExportIDs; ++i ) Sizes[i] += IntSizes[i]; } if( IntSizes ) delete [] IntSizes; return(0); }