//========================================================================== int Ifpack_CrsRiluk::Factor() { // if (!Allocated()) return(-1); // This test is not needed at this time. All constructors allocate. if (!ValuesInitialized()) return(-2); // Must have values initialized. if (Factored()) return(-3); // Can't have already computed factors. SetValuesInitialized(false); // MinMachNum should be officially defined, for now pick something a little // bigger than IEEE underflow value double MinDiagonalValue = Epetra_MinDouble; double MaxDiagonalValue = 1.0/MinDiagonalValue; int ierr = 0; int i, j, k; int * LI=0, * UI = 0; double * LV=0, * UV = 0; int NumIn, NumL, NumU; // Get Maximun Row length int MaxNumEntries = L_->MaxNumEntries() + U_->MaxNumEntries() + 1; vector<int> InI(MaxNumEntries); // Allocate temp space vector<double> InV(MaxNumEntries); vector<int> colflag(NumMyCols()); double *DV; ierr = D_->ExtractView(&DV); // Get view of diagonal #ifdef IFPACK_FLOPCOUNTERS int current_madds = 0; // We will count multiply-add as they happen #endif // Now start the factorization. // Need some integer workspace and pointers int NumUU; int * UUI; double * UUV; for (j=0; j<NumMyCols(); j++) colflag[j] = - 1; for(i=0; i<NumMyRows(); i++) { // Fill InV, InI with current row of L, D and U combined NumIn = MaxNumEntries; EPETRA_CHK_ERR(L_->ExtractMyRowCopy(i, NumIn, NumL, &InV[0], &InI[0])); LV = &InV[0]; LI = &InI[0]; InV[NumL] = DV[i]; // Put in diagonal InI[NumL] = i; EPETRA_CHK_ERR(U_->ExtractMyRowCopy(i, NumIn-NumL-1, NumU, &InV[NumL+1], &InI[NumL+1])); NumIn = NumL+NumU+1; UV = &InV[NumL+1]; UI = &InI[NumL+1]; // Set column flags for (j=0; j<NumIn; j++) colflag[InI[j]] = j; double diagmod = 0.0; // Off-diagonal accumulator for (int jj=0; jj<NumL; jj++) { j = InI[jj]; double multiplier = InV[jj]; // current_mults++; InV[jj] *= DV[j]; EPETRA_CHK_ERR(U_->ExtractMyRowView(j, NumUU, UUV, UUI)); // View of row above if (RelaxValue_==0.0) { for (k=0; k<NumUU; k++) { int kk = colflag[UUI[k]]; if (kk>-1) { InV[kk] -= multiplier*UUV[k]; #ifdef IFPACK_FLOPCOUNTERS current_madds++; #endif } } } else { for (k=0; k<NumUU; k++) { int kk = colflag[UUI[k]]; if (kk>-1) InV[kk] -= multiplier*UUV[k]; else diagmod -= multiplier*UUV[k]; #ifdef IFPACK_FLOPCOUNTERS current_madds++; #endif } } } if (NumL) { EPETRA_CHK_ERR(L_->ReplaceMyValues(i, NumL, LV, LI)); // Replace current row of L } DV[i] = InV[NumL]; // Extract Diagonal value if (RelaxValue_!=0.0) { DV[i] += RelaxValue_*diagmod; // Add off diagonal modifications // current_madds++; } if (fabs(DV[i]) > MaxDiagonalValue) { if (DV[i] < 0) DV[i] = - MinDiagonalValue; else DV[i] = MinDiagonalValue; } else DV[i] = 1.0/DV[i]; // Invert diagonal value for (j=0; j<NumU; j++) UV[j] *= DV[i]; // Scale U by inverse of diagonal if (NumU) { EPETRA_CHK_ERR(U_->ReplaceMyValues(i, NumU, UV, UI)); // Replace current row of L and U } // Reset column flags for (j=0; j<NumIn; j++) colflag[InI[j]] = -1; } // Validate that the L and U factors are actually lower and upper triangular if( !L_->LowerTriangular() ) EPETRA_CHK_ERR(-2); if( !U_->UpperTriangular() ) EPETRA_CHK_ERR(-3); #ifdef IFPACK_FLOPCOUNTERS // Add up flops double current_flops = 2 * current_madds; double total_flops = 0; EPETRA_CHK_ERR(Graph_.L_Graph().RowMap().Comm().SumAll(¤t_flops, &total_flops, 1)); // Get total madds across all PEs // Now count the rest total_flops += (double) L_->NumGlobalNonzeros(); // Accounts for multiplier above total_flops += (double) D_->GlobalLength(); // Accounts for reciprocal of diagonal if (RelaxValue_!=0.0) total_flops += 2 * (double)D_->GlobalLength(); // Accounts for relax update of diag UpdateFlops(total_flops); // Update flop count #endif SetFactored(true); return(ierr); }
//========================================================================== int Ifpack_CrsIct::InitValues(const Epetra_CrsMatrix & A) { int ierr = 0; int i, j; int NumIn, NumL, NumU; bool DiagFound; int NumNonzeroDiags = 0; Teuchos::RefCountPtr<Epetra_CrsMatrix> OverlapA = Teuchos::rcp( (Epetra_CrsMatrix *) &A_ , false ); if (LevelOverlap_>0) { EPETRA_CHK_ERR(-1); // Not implemented yet //OverlapA = new Epetra_CrsMatrix(Copy, *Graph_.OverlapGraph()); //EPETRA_CHK_ERR(OverlapA->Import(A, *Graph_.OverlapImporter(), Insert)); //EPETRA_CHK_ERR(OverlapA->FillComplete()); } // Get Maximun Row length int MaxNumEntries = OverlapA->MaxNumEntries(); vector<int> InI(MaxNumEntries); // Allocate temp space vector<int> UI(MaxNumEntries); vector<double> InV(MaxNumEntries); vector<double> UV(MaxNumEntries); double *DV; ierr = D_->ExtractView(&DV); // Get view of diagonal // First we copy the user's matrix into diagonal vector and U, regardless of fill level int NumRows = OverlapA->NumMyRows(); for (i=0; i< NumRows; i++) { OverlapA->ExtractMyRowCopy(i, MaxNumEntries, NumIn, &InV[0], &InI[0]); // Get Values and Indices // Split into L and U (we don't assume that indices are ordered). NumL = 0; NumU = 0; DiagFound = false; for (j=0; j< NumIn; j++) { int k = InI[j]; if (k==i) { DiagFound = true; DV[i] += Rthresh_ * InV[j] + EPETRA_SGN(InV[j]) * Athresh_; // Store perturbed diagonal in Epetra_Vector D_ } else if (k < 0) return(-1); // Out of range else if (i<k && k<NumRows) { UI[NumU] = k; UV[NumU] = InV[j]; NumU++; } } // Check in things for this row of L and U if (DiagFound) NumNonzeroDiags++; if (NumU) U_->InsertMyValues(i, NumU, &UV[0], &UI[0]); } U_->FillComplete(A_.OperatorDomainMap(), A_.OperatorRangeMap()); SetValuesInitialized(true); SetFactored(false); int ierr1 = 0; if (NumNonzeroDiags<U_->NumMyRows()) ierr1 = 1; A_.Comm().MaxAll(&ierr1, &ierr, 1); EPETRA_CHK_ERR(ierr); return(0); }
int Ifpack_CrsRiluk::InitAllValues(const Epetra_RowMatrix & OverlapA, int MaxNumEntries) { int ierr = 0; int i, j; int NumIn, NumL, NumU; bool DiagFound; int NumNonzeroDiags = 0; vector<int> InI(MaxNumEntries); // Allocate temp space vector<int> LI(MaxNumEntries); vector<int> UI(MaxNumEntries); vector<double> InV(MaxNumEntries); vector<double> LV(MaxNumEntries); vector<double> UV(MaxNumEntries); bool ReplaceValues = (L_->StaticGraph() || L_->IndicesAreLocal()); // Check if values should be inserted or replaced if (ReplaceValues) { L_->PutScalar(0.0); // Zero out L and U matrices U_->PutScalar(0.0); } D_->PutScalar(0.0); // Set diagonal values to zero double *DV; EPETRA_CHK_ERR(D_->ExtractView(&DV)); // Get view of diagonal // First we copy the user's matrix into L and U, regardless of fill level for (i=0; i< NumMyRows(); i++) { EPETRA_CHK_ERR(OverlapA.ExtractMyRowCopy(i, MaxNumEntries, NumIn, &InV[0], &InI[0])); // Get Values and Indices // Split into L and U (we don't assume that indices are ordered). NumL = 0; NumU = 0; DiagFound = false; for (j=0; j< NumIn; j++) { int k = InI[j]; if (k==i) { DiagFound = true; DV[i] += Rthresh_ * InV[j] + EPETRA_SGN(InV[j]) * Athresh_; // Store perturbed diagonal in Epetra_Vector D_ } else if (k < 0) {EPETRA_CHK_ERR(-1);} // Out of range else if (k < i) { LI[NumL] = k; LV[NumL] = InV[j]; NumL++; } else if (k<NumMyRows()) { UI[NumU] = k; UV[NumU] = InV[j]; NumU++; } } // Check in things for this row of L and U if (DiagFound) NumNonzeroDiags++; else DV[i] = Athresh_; if (NumL) { if (ReplaceValues) { EPETRA_CHK_ERR(L_->ReplaceMyValues(i, NumL, &LV[0], &LI[0])); } else { EPETRA_CHK_ERR(L_->InsertMyValues(i, NumL, &LV[0], &LI[0])); } } if (NumU) { if (ReplaceValues) { EPETRA_CHK_ERR(U_->ReplaceMyValues(i, NumU, &UV[0], &UI[0])); } else { EPETRA_CHK_ERR(U_->InsertMyValues(i, NumU, &UV[0], &UI[0])); } } } if (!ReplaceValues) { // The domain of L and the range of U are exactly their own row maps (there is no communication). // The domain of U and the range of L must be the same as those of the original matrix, // However if the original matrix is a VbrMatrix, these two latter maps are translation from // a block map to a point map. EPETRA_CHK_ERR(L_->FillComplete(L_->RowMatrixColMap(), *L_RangeMap_)); EPETRA_CHK_ERR(U_->FillComplete(*U_DomainMap_, U_->RowMatrixRowMap())); } // At this point L and U have the values of A in the structure of L and U, and diagonal vector D SetValuesInitialized(true); SetFactored(false); int TotalNonzeroDiags = 0; EPETRA_CHK_ERR(Graph_.L_Graph().RowMap().Comm().SumAll(&NumNonzeroDiags, &TotalNonzeroDiags, 1)); NumMyDiagonals_ = NumNonzeroDiags; if (NumNonzeroDiags != NumMyRows()) ierr = 1; // Diagonals are not right, warn user return(ierr); }