int check(Epetra_RowMatrix& A, Epetra_RowMatrix & B, bool verbose) { int ierr = 0; EPETRA_TEST_ERR(!A.Comm().NumProc()==B.Comm().NumProc(),ierr); EPETRA_TEST_ERR(!A.Comm().MyPID()==B.Comm().MyPID(),ierr); EPETRA_TEST_ERR(!A.Filled()==B.Filled(),ierr); EPETRA_TEST_ERR(!A.HasNormInf()==B.HasNormInf(),ierr); EPETRA_TEST_ERR(!A.LowerTriangular()==B.LowerTriangular(),ierr); EPETRA_TEST_ERR(!A.Map().SameAs(B.Map()),ierr); EPETRA_TEST_ERR(!A.MaxNumEntries()==B.MaxNumEntries(),ierr); EPETRA_TEST_ERR(!A.NumGlobalCols64()==B.NumGlobalCols64(),ierr); EPETRA_TEST_ERR(!A.NumGlobalDiagonals64()==B.NumGlobalDiagonals64(),ierr); EPETRA_TEST_ERR(!A.NumGlobalNonzeros64()==B.NumGlobalNonzeros64(),ierr); EPETRA_TEST_ERR(!A.NumGlobalRows64()==B.NumGlobalRows64(),ierr); EPETRA_TEST_ERR(!A.NumMyCols()==B.NumMyCols(),ierr); EPETRA_TEST_ERR(!A.NumMyDiagonals()==B.NumMyDiagonals(),ierr); EPETRA_TEST_ERR(!A.NumMyNonzeros()==B.NumMyNonzeros(),ierr); for (int i=0; i<A.NumMyRows(); i++) { int nA, nB; A.NumMyRowEntries(i,nA); B.NumMyRowEntries(i,nB); EPETRA_TEST_ERR(!nA==nB,ierr); } EPETRA_TEST_ERR(!A.NumMyRows()==B.NumMyRows(),ierr); EPETRA_TEST_ERR(!A.OperatorDomainMap().SameAs(B.OperatorDomainMap()),ierr); EPETRA_TEST_ERR(!A.OperatorRangeMap().SameAs(B.OperatorRangeMap()),ierr); EPETRA_TEST_ERR(!A.RowMatrixColMap().SameAs(B.RowMatrixColMap()),ierr); EPETRA_TEST_ERR(!A.RowMatrixRowMap().SameAs(B.RowMatrixRowMap()),ierr); EPETRA_TEST_ERR(!A.UpperTriangular()==B.UpperTriangular(),ierr); EPETRA_TEST_ERR(!A.UseTranspose()==B.UseTranspose(),ierr); int NumVectors = 5; { // No transpose case Epetra_MultiVector X(A.OperatorDomainMap(), NumVectors); Epetra_MultiVector YA1(A.OperatorRangeMap(), NumVectors); Epetra_MultiVector YA2(YA1); Epetra_MultiVector YB1(YA1); Epetra_MultiVector YB2(YA1); X.Random(); bool transA = false; A.SetUseTranspose(transA); B.SetUseTranspose(transA); A.Apply(X,YA1); A.Multiply(transA, X, YA2); EPETRA_TEST_ERR(checkMultiVectors(YA1,YA2,"A Multiply and A Apply", verbose),ierr); B.Apply(X,YB1); EPETRA_TEST_ERR(checkMultiVectors(YA1,YB1,"A Multiply and B Multiply", verbose),ierr); B.Multiply(transA, X, YB2); EPETRA_TEST_ERR(checkMultiVectors(YA1,YB2,"A Multiply and B Apply", verbose), ierr); } {// transpose case Epetra_MultiVector X(A.OperatorRangeMap(), NumVectors); Epetra_MultiVector YA1(A.OperatorDomainMap(), NumVectors); Epetra_MultiVector YA2(YA1); Epetra_MultiVector YB1(YA1); Epetra_MultiVector YB2(YA1); X.Random(); bool transA = true; A.SetUseTranspose(transA); B.SetUseTranspose(transA); A.Apply(X,YA1); A.Multiply(transA, X, YA2); EPETRA_TEST_ERR(checkMultiVectors(YA1,YA2, "A Multiply and A Apply (transpose)", verbose),ierr); B.Apply(X,YB1); EPETRA_TEST_ERR(checkMultiVectors(YA1,YB1, "A Multiply and B Multiply (transpose)", verbose),ierr); B.Multiply(transA, X,YB2); EPETRA_TEST_ERR(checkMultiVectors(YA1,YB2, "A Multiply and B Apply (transpose)", verbose),ierr); } Epetra_Vector diagA(A.RowMatrixRowMap()); EPETRA_TEST_ERR(A.ExtractDiagonalCopy(diagA),ierr); Epetra_Vector diagB(B.RowMatrixRowMap()); EPETRA_TEST_ERR(B.ExtractDiagonalCopy(diagB),ierr); EPETRA_TEST_ERR(checkMultiVectors(diagA,diagB, "ExtractDiagonalCopy", verbose),ierr); Epetra_Vector rowA(A.RowMatrixRowMap()); EPETRA_TEST_ERR(A.InvRowSums(rowA),ierr); Epetra_Vector rowB(B.RowMatrixRowMap()); EPETRA_TEST_ERR(B.InvRowSums(rowB),ierr) EPETRA_TEST_ERR(checkMultiVectors(rowA,rowB, "InvRowSums", verbose),ierr); Epetra_Vector colA(A.RowMatrixColMap()); EPETRA_TEST_ERR(A.InvColSums(colA),ierr); Epetra_Vector colB(B.RowMatrixColMap()); EPETRA_TEST_ERR(B.InvColSums(colB),ierr); EPETRA_TEST_ERR(checkMultiVectors(colA,colB, "InvColSums", verbose),ierr); EPETRA_TEST_ERR(checkValues(A.NormInf(), B.NormInf(), "NormInf before scaling", verbose), ierr); EPETRA_TEST_ERR(checkValues(A.NormOne(), B.NormOne(), "NormOne before scaling", verbose),ierr); EPETRA_TEST_ERR(A.RightScale(colA),ierr); EPETRA_TEST_ERR(B.RightScale(colB),ierr); EPETRA_TEST_ERR(A.LeftScale(rowA),ierr); EPETRA_TEST_ERR(B.LeftScale(rowB),ierr); EPETRA_TEST_ERR(checkValues(A.NormInf(), B.NormInf(), "NormInf after scaling", verbose), ierr); EPETRA_TEST_ERR(checkValues(A.NormOne(), B.NormOne(), "NormOne after scaling", verbose),ierr); vector<double> valuesA(A.MaxNumEntries()); vector<int> indicesA(A.MaxNumEntries()); vector<double> valuesB(B.MaxNumEntries()); vector<int> indicesB(B.MaxNumEntries()); return(0); for (int i=0; i<A.NumMyRows(); i++) { int nA, nB; EPETRA_TEST_ERR(A.ExtractMyRowCopy(i, A.MaxNumEntries(), nA, &valuesA[0], &indicesA[0]),ierr); EPETRA_TEST_ERR(B.ExtractMyRowCopy(i, B.MaxNumEntries(), nB, &valuesB[0], &indicesB[0]),ierr); EPETRA_TEST_ERR(!nA==nB,ierr); for (int j=0; j<nA; j++) { double curVal = valuesA[j]; int curIndex = indicesA[j]; bool notfound = true; int jj = 0; while (notfound && jj< nB) { if (!checkValues(curVal, valuesB[jj])) notfound = false; jj++; } EPETRA_TEST_ERR(notfound, ierr); vector<int>::iterator p = find(indicesB.begin(),indicesB.end(),curIndex); // find curIndex in indicesB EPETRA_TEST_ERR(p==indicesB.end(), ierr); } } if (verbose) cout << "RowMatrix Methods check OK" << endl; return (ierr); }
int GMGSolver::solve() { int rank = Teuchos::GlobalMPISession::getRank(); // in place of doing the scaling ourselves, for the moment I've switched // over to using Aztec's built-in scaling. This appears to be functionally identical. bool useAztecToScaleDiagonally = true; AztecOO solver(problem()); Epetra_CrsMatrix *A = dynamic_cast<Epetra_CrsMatrix *>( problem().GetMatrix() ); if (A == NULL) { cout << "Error: GMGSolver requires an Epetra_CrsMatrix.\n"; TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Error: GMGSolver requires an Epetra_CrsMatrix.\n"); } // EpetraExt::RowMatrixToMatlabFile("/tmp/A_pre_scaling.dat",*A); // Epetra_MultiVector *b = problem().GetRHS(); // EpetraExt::MultiVectorToMatlabFile("/tmp/b_pre_scaling.dat",*b); // Epetra_MultiVector *x = problem().GetLHS(); // EpetraExt::MultiVectorToMatlabFile("/tmp/x_initial_guess.dat",*x); const Epetra_Map* map = &A->RowMatrixRowMap(); Epetra_Vector diagA(*map); A->ExtractDiagonalCopy(diagA); // EpetraExt::MultiVectorToMatlabFile("/tmp/diagA.dat",diagA); // Epetra_Vector scale_vector(*map); Epetra_Vector diagA_sqrt_inv(*map); Epetra_Vector diagA_inv(*map); if (_diagonalScaling && !useAztecToScaleDiagonally) { int length = scale_vector.MyLength(); for (int i=0; i<length; i++) scale_vector[i] = 1.0 / sqrt(fabs(diagA[i])); problem().LeftScale(scale_vector); problem().RightScale(scale_vector); } Teuchos::RCP<Epetra_MultiVector> diagA_ptr = Teuchos::rcp( &diagA, false ); _gmgOperator.setStiffnessDiagonal(diagA_ptr); _gmgOperator.setApplyDiagonalSmoothing(_diagonalSmoothing); _gmgOperator.setFineSolverUsesDiagonalScaling(_diagonalScaling); _gmgOperator.computeCoarseStiffnessMatrix(A); if (_diagonalScaling && useAztecToScaleDiagonally) { solver.SetAztecOption(AZ_scaling, AZ_sym_diag); } else { solver.SetAztecOption(AZ_scaling, AZ_none); } if (_useCG) { if (_computeCondest) { solver.SetAztecOption(AZ_solver, AZ_cg_condnum); } else { solver.SetAztecOption(AZ_solver, AZ_cg); } } else { solver.SetAztecOption(AZ_kspace, 200); // default is 30 if (_computeCondest) { solver.SetAztecOption(AZ_solver, AZ_gmres_condnum); } else { solver.SetAztecOption(AZ_solver, AZ_gmres); } } solver.SetPrecOperator(&_gmgOperator); // solver.SetAztecOption(AZ_precond, AZ_none); solver.SetAztecOption(AZ_precond, AZ_user_precond); solver.SetAztecOption(AZ_conv, _azConvergenceOption); // solver.SetAztecOption(AZ_output, AZ_last); solver.SetAztecOption(AZ_output, _azOutput); int solveResult = solver.Iterate(_maxIters,_tol); const double* status = solver.GetAztecStatus(); int remainingIters = _maxIters; int whyTerminated = status[AZ_why]; int maxRestarts = 1; int numRestarts = 0; while ((whyTerminated==AZ_loss) && (numRestarts < maxRestarts)) { remainingIters -= status[AZ_its]; if (rank==0) cout << "Aztec warned that the recursive residual indicates convergence even though the true residual is too large. Restarting with the new solution as initial guess, with maxIters = " << remainingIters << endl; solveResult = solver.Iterate(remainingIters,_tol); whyTerminated = status[AZ_why]; numRestarts++; } remainingIters -= status[AZ_its]; _iterationCount = _maxIters - remainingIters; _condest = solver.Condest(); // will be -1 if running without condest if (rank==0) { switch (whyTerminated) { case AZ_normal: // cout << "whyTerminated: AZ_normal " << endl; break; case AZ_param: cout << "whyTerminated: AZ_param " << endl; break; case AZ_breakdown: cout << "whyTerminated: AZ_breakdown " << endl; break; case AZ_loss: cout << "whyTerminated: AZ_loss " << endl; break; case AZ_ill_cond: cout << "whyTerminated: AZ_ill_cond " << endl; break; case AZ_maxits: cout << "whyTerminated: AZ_maxits " << endl; break; default: break; } } // Epetra_MultiVector *x = problem().GetLHS(); // EpetraExt::MultiVectorToMatlabFile("/tmp/x.dat",*x); if (_diagonalScaling && !useAztecToScaleDiagonally) { // reverse the scaling here scale_vector.Reciprocal(scale_vector); problem().LeftScale(scale_vector); problem().RightScale(scale_vector); } double norminf = A->NormInf(); double normone = A->NormOne(); int numIters = solver.NumIters(); if (_printToConsole) { cout << "\n Inf-norm of stiffness matrix after scaling = " << norminf; cout << "\n One-norm of stiffness matrix after scaling = " << normone << endl << endl; cout << "Num iterations: " << numIters << endl; } _gmgOperator.setStiffnessDiagonal(Teuchos::rcp((Epetra_MultiVector*) NULL )); return solveResult; }