//============================================================================= int Epetra_SerialSpdDenseSolver::Factor(void) { if (Factored()) return(0); // Already factored if (Inverted()) EPETRA_CHK_ERR(-100); // Cannot factor inverted matrix int ierr = 0; ANORM_ = SymMatrix_->OneNorm(); // If we want to refine the solution, then the factor must // be stored separatedly from the original matrix if (A_ == AF_) if (RefineSolution_ ) { SymFactor_ = new Epetra_SerialSymDenseMatrix(*SymMatrix_); Factor_ = SymFactor_; AF_ = SymFactor_->A(); LDAF_ = SymFactor_->LDA(); } if (Equilibrate_) ierr = EquilibrateMatrix(); if (ierr!=0) EPETRA_CHK_ERR(ierr-2); POTRF (SymMatrix_->UPLO(), N_, AF_, LDAF_, &INFO_); Factored_ = true; double DN = N_; UpdateFlops((DN*DN*DN)/3.0); EPETRA_CHK_ERR(INFO_); return(0); }
//============================================================================== int Ifpack2_OverlapFactor::InitValues(const Tpetra_RowMatrix * UserMatrix) { if (OverlapGraph_!=0) { Tpetra_CrsMatrix * CrsMatrix = dynamic_cast<Tpetra_CrsMatrix *>(UserMatrix); if (CrsMatrix!=0) if (!Allocated()) EPETRA_CHK_ERR(-1); //Must be allocated if (ValuesInitialized()) EPETRA_CHK_ERR(1); // Values already init'ed, warn caller EPETRA_CHK_ERR(DerivedFactor()); // Call Derived class factorization SetValuesInitialized(false); SetFactored(true); return(0); } //============================================================================== int Ifpack2_OverlapFactor::Factor() { if (!ValuesInitialized()) EPETRA_CHK_ERR(-1); // Values must be initialized if (Factored()) EPETRA_CHK_ERR(1); // Return with a warning that factor already done EPETRA_CHK_ERR(DerivedFactor()); // Call Derived class factorization SetValuesInitialized(false); SetFactored(true); return(0); }
//============================================================================= int Epetra_SerialDenseSVD::Invert( double rthresh, double athresh ) { if (!Factored()) Factor(); // Need matrix factored. //apply threshold double thresh = S_[0]*rthresh + athresh; int num_replaced = 0; for( int i = 0; i < M_; ++i ) if( S_[i] < thresh ) { //cout << num_replaced << thresh << " " << S_[0] << " " << S_[i] << std::endl; // S_[i] = thresh; S_[i] = 0.0; ++num_replaced; } //scale cols of U_ with reciprocal singular values double *p = U_; for( int i = 0; i < N_; ++i ) { double scale = 0.0; if( S_[i] ) scale = 1./S_[i]; for( int j = 0; j < M_; ++j ) *p++ *= scale; } //create new Inverse_ if necessary if( Inverse_ == 0 ) { Inverse_ = new Epetra_SerialDenseMatrix(); Inverse_->Shape( N_, M_ ); AI_ = Inverse_->A(); LDAI_ = Inverse_->LDA(); } /* else //zero it out { for( int i = 0; i < Inverse_->M(); ++i ) for( int j = 0; j < Inverse_->N(); ++j ) (*Inverse_)(i,j) = 0.0; } */ GEMM( 'T', 'T', M_, M_, M_, 1.0, Vt_, M_, U_, M_, 0.0, AI_, M_ ); double DN = N_; UpdateFlops((DN*DN*DN)); Inverted_ = true; Factored_ = false; EPETRA_CHK_ERR(INFO_); return(num_replaced); }
//============================================================================= int Epetra_SerialSpdDenseSolver::Invert(void) { if (!Factored()) Factor(); // Need matrix factored. POTRI ( SymMatrix_->UPLO(), N_, AF_, LDAF_, &INFO_); // Copy lower/upper triangle to upper/lower triangle: make full inverse SymMatrix_->CopyUPLOMat(SymMatrix_->Upper(), AF_, LDAF_, N_); double DN = N_; UpdateFlops((DN*DN*DN)); Inverted_ = true; Factored_ = false; EPETRA_CHK_ERR(INFO_); return(0); }
//============================================================================= int Epetra_SerialSpdDenseSolver::ReciprocalConditionEstimate(double & Value) { int ierr = 0; if (ReciprocalConditionEstimated()) { Value = RCOND_; return(0); // Already computed, just return it. } if (ANORM_<0.0) ANORM_ = SymMatrix_->OneNorm(); if (ierr!=0) EPETRA_CHK_ERR(ierr-1); if (!Factored()) ierr = Factor(); // Need matrix factored. if (ierr!=0) EPETRA_CHK_ERR(ierr-2); AllocateWORK(); AllocateIWORK(); POCON( SymMatrix_->UPLO(), N_, AF_, LDAF_, ANORM_, &RCOND_, WORK_, IWORK_, &INFO_); ReciprocalConditionEstimated_ = true; Value = RCOND_; UpdateFlops(2*N_*N_); // Not sure of count EPETRA_CHK_ERR(INFO_); return(0); }
//========================================================================== int Ifpack_CrsIct::Factor() { // if (!Allocated()) return(-1); // This test is not needed at this time. All constructors allocate. if (!ValuesInitialized_) EPETRA_CHK_ERR(-2); // Must have values initialized. if (Factored()) EPETRA_CHK_ERR(-3); // Can't have already computed factors. SetValuesInitialized(false); int i; int m, n, nz, Nrhs, ldrhs, ldlhs; int * ptr=0, * ind; double * val, * rhs, * lhs; int ierr = Epetra_Util_ExtractHbData(U_.get(), 0, 0, m, n, nz, ptr, ind, val, Nrhs, rhs, ldrhs, lhs, ldlhs); if (ierr<0) EPETRA_CHK_ERR(ierr); Matrix * Aict; if (Aict_==0) { Aict = new Matrix; Aict_ = (void *) Aict; } else Aict = (Matrix *) Aict_; Matrix * Lict; if (Lict_==0) { Lict = new Matrix; Lict_ = (void *) Lict; } else Lict = (Matrix *) Lict_; Aict->val = val; Aict->col = ind; Aict->ptr = ptr; double *DV; EPETRA_CHK_ERR(D_->ExtractView(&DV)); // Get view of diagonal crout_ict(m, Aict, DV, Droptol_, Lfil_, Lict, &Ldiag_); // Get rid of unnecessary data delete [] ptr; // Create Epetra View of L from crout_ict if (LevelOverlap_==0) { U_ = Teuchos::rcp( new Epetra_CrsMatrix(View, A_.RowMatrixRowMap(), A_.RowMatrixRowMap(),0) ); D_ = Teuchos::rcp( new Epetra_Vector(View, A_.RowMatrixRowMap(), Ldiag_) ); } else { EPETRA_CHK_ERR(-1); // LevelOverlap > 0 not implemented yet // U_ = new Epetra_CrsMatrix(Copy, OverlapRowMap()); // D_ = new Epetra_Vector(OverlapRowMap()); } ptr = Lict->ptr; ind = Lict->col; val = Lict->val; for (i=0; i< m; i++) { int NumEntries = ptr[i+1]-ptr[i]; int * Indices = ind+ptr[i]; double * Values = val+ptr[i]; U_->InsertMyValues(i, NumEntries, Values, Indices); } U_->FillComplete(A_.OperatorDomainMap(), A_.OperatorRangeMap()); D_->Reciprocal(*D_); // Put reciprocal of diagonal in this vector // Add up flops double current_flops = 2 * nz; // Just an estimate double total_flops = 0; A_.Comm().SumAll(¤t_flops, &total_flops, 1); // Get total madds across all PEs // Now count the rest total_flops += (double) U_->NumGlobalNonzeros(); // Accounts for multiplier above total_flops += (double) D_->GlobalLength(); // Accounts for reciprocal of diagonal UpdateFlops(total_flops); // Update flop count SetFactored(true); return(0); }
//========================================================================== 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 Epetra_SerialSpdDenseSolver::Solve(void) { int ierr = 0; // We will call one of four routines depending on what services the user wants and // whether or not the matrix has been inverted or factored already. // // If the matrix has been inverted, use DGEMM to compute solution. // Otherwise, if the user want the matrix to be equilibrated or wants a refined solution, we will // call the X interface. // Otherwise, if the matrix is already factored we will call the TRS interface. // Otherwise, if the matrix is unfactored we will call the SV interface. if (Equilibrate_) { ierr = Epetra_SerialDenseSolver::EquilibrateRHS(); B_Equilibrated_ = true; } EPETRA_CHK_ERR(ierr); if (A_Equilibrated_ && !B_Equilibrated_) EPETRA_CHK_ERR(-1); // Matrix and vectors must be similarly scaled if (!A_Equilibrated_ && B_Equilibrated_) EPETRA_CHK_ERR(-2); if (B_==0) EPETRA_CHK_ERR(-3); // No B if (X_==0) EPETRA_CHK_ERR(-4); // No B if (ShouldEquilibrate() && !A_Equilibrated_) ierr = 1; // Warn that the system should be equilibrated. double DN = N_; double DNRHS = NRHS_; if (Inverted()) { if (B_==X_) EPETRA_CHK_ERR(-100); // B and X must be different for this case GEMM('N', 'N', N_, NRHS_, N_, 1.0, AF_, LDAF_, B_, LDB_, 0.0, X_, LDX_); if (INFO_!=0) EPETRA_CHK_ERR(INFO_); UpdateFlops(2.0*DN*DN*DNRHS); Solved_ = true; } else { if (!Factored()) Factor(); // Matrix must be factored if (B_!=X_) { *LHS_ = *RHS_; // Copy B to X if needed X_ = LHS_->A(); LDX_ = LHS_->LDA(); } POTRS(SymMatrix_->UPLO(), N_, NRHS_, AF_, LDAF_, X_, LDX_, &INFO_); if (INFO_!=0) EPETRA_CHK_ERR(INFO_); UpdateFlops(2.0*DN*DN*DNRHS); Solved_ = true; } int ierr1=0; if (RefineSolution_) ierr1 = ApplyRefinement(); if (ierr1!=0) { EPETRA_CHK_ERR(ierr1); } else { EPETRA_CHK_ERR(ierr); } if (Equilibrate_) ierr1 = Epetra_SerialDenseSolver::UnequilibrateLHS(); EPETRA_CHK_ERR(ierr1); return(0); }