int main(int argc, char *argv[]) { // int MyPID = 0; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); MyPID = Comm.MyPID(); #else Epetra_SerialComm Comm; #endif // typedef double ST; typedef Teuchos::ScalarTraits<ST> SCT; typedef SCT::magnitudeType MT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Belos::MultiVecTraits<ST,MV> MVT; typedef Belos::OperatorTraits<ST,MV,OP> OPT; using Teuchos::ParameterList; using Teuchos::RCP; using Teuchos::rcp; bool success = false; bool verbose = false; try { bool proc_verbose = false; int frequency = -1; // frequency of status test output. int blocksize = 1; // blocksize int numrhs = 1; // number of right-hand sides to solve for int maxrestarts = 15; // maximum number of restarts allowed int maxiters = -1; // maximum number of iterations allowed per linear system int maxsubspace = 25; // maximum number of blocks the solver can use for the subspace std::string filename("orsirr1.hb"); MT tol = 1.0e-5; // relative residual tolerance // Specify whether to use RHS as initial guess. If false, use zero. bool useRHSAsInitialGuess = false; Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("use-rhs","use-zero",&useRHSAsInitialGuess,"Use RHS as initial guess."); cmdp.setOption("frequency",&frequency,"Solvers frequency for printing residuals (#iters)."); cmdp.setOption("filename",&filename,"Filename for test matrix. Acceptable file extensions: *.hb,*.mtx,*.triU,*.triS"); cmdp.setOption("tol",&tol,"Relative residual tolerance used by GMRES solver."); cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for."); cmdp.setOption("block-size",&blocksize,"Block size used by GMRES."); cmdp.setOption("max-iters",&maxiters,"Maximum number of iterations per linear system (-1 = adapted to problem/block size)."); cmdp.setOption("max-subspace",&maxsubspace,"Maximum number of blocks the solver can use for the subspace."); cmdp.setOption("max-restarts",&maxrestarts,"Maximum number of restarts allowed for GMRES solver."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { return EXIT_FAILURE; } if (!verbose) frequency = -1; // reset frequency if test is not verbose // // *************Get the problem********************* // RCP<Epetra_Map> Map; RCP<Epetra_CrsMatrix> A; RCP<Epetra_MultiVector> B, X; RCP<Epetra_Vector> vecB, vecX; EpetraExt::readEpetraLinearSystem(filename, Comm, &A, &Map, &vecX, &vecB); A->OptimizeStorage(); proc_verbose = verbose && (MyPID==0); /* Only print on the zero processor */ // Check to see if the number of right-hand sides is the same as requested. if (numrhs>1) { X = rcp( new Epetra_MultiVector( *Map, numrhs ) ); B = rcp( new Epetra_MultiVector( *Map, numrhs ) ); X->Seed(); X->Random(); OPT::Apply( *A, *X, *B ); X->PutScalar( 0.0 ); } else { X = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecX); B = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecB); } // If requested, use a copy of B as initial guess if (useRHSAsInitialGuess) { X->Update(1.0, *B, 0.0); } // // ************Construct preconditioner************* // ParameterList ifpackList; // allocates an IFPACK factory. No data is associated // to this object (only method Create()). Ifpack Factory; // create the preconditioner. For valid PrecType values, // please check the documentation std::string PrecType = "ILU"; // incomplete LU int OverlapLevel = 1; // must be >= 0. If Comm.NumProc() == 1, // it is ignored. RCP<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*A, OverlapLevel) ); assert(Prec != Teuchos::null); // specify parameters for ILU ifpackList.set("fact: level-of-fill", 1); // the combine mode is on the following: // "Add", "Zero", "Insert", "InsertAdd", "Average", "AbsMax" // Their meaning is as defined in file Epetra_CombineMode.h ifpackList.set("schwarz: combine mode", "Add"); // sets the parameters IFPACK_CHK_ERR(Prec->SetParameters(ifpackList)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. IFPACK_CHK_ERR(Prec->Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. IFPACK_CHK_ERR(Prec->Compute()); // Create the Belos preconditioned operator from the Ifpack preconditioner. // NOTE: This is necessary because Belos expects an operator to apply the // preconditioner with Apply() NOT ApplyInverse(). RCP<Belos::EpetraPrecOp> belosPrec = rcp( new Belos::EpetraPrecOp( Prec ) ); // // *****Create parameter list for the block GMRES solver manager***** // const int NumGlobalElements = B->GlobalLength(); if (maxiters == -1) maxiters = NumGlobalElements/blocksize - 1; // maximum number of iterations to run // ParameterList belosList; belosList.set( "Flexible Gmres", true ); // Flexible Gmres will be used to solve this problem belosList.set( "Num Blocks", maxsubspace ); // Maximum number of blocks in Krylov factorization belosList.set( "Block Size", blocksize ); // Blocksize to be used by iterative solver belosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed belosList.set( "Maximum Restarts", maxrestarts ); // Maximum number of restarts allowed belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested if (numrhs > 1) { belosList.set( "Show Maximum Residual Norm Only", true ); // Show only the maximum residual norm } if (verbose) { belosList.set( "Verbosity", Belos::Errors + Belos::Warnings + Belos::TimingDetails + Belos::StatusTestDetails ); if (frequency > 0) belosList.set( "Output Frequency", frequency ); } else belosList.set( "Verbosity", Belos::Errors + Belos::Warnings ); // // *******Construct a preconditioned linear problem******** // RCP<Belos::LinearProblem<double,MV,OP> > problem = rcp( new Belos::LinearProblem<double,MV,OP>( A, X, B ) ); problem->setRightPrec( belosPrec ); bool set = problem->setProblem(); if (set == false) { if (proc_verbose) std::cout << std::endl << "ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; return EXIT_FAILURE; } // Create an iterative solver manager. RCP< Belos::SolverManager<double,MV,OP> > solver = rcp( new Belos::BlockGmresSolMgr<double,MV,OP>(problem, rcp(&belosList,false))); // // ******************************************************************* // *************Start the block Gmres iteration************************* // ******************************************************************* // if (proc_verbose) { std::cout << std::endl << std::endl; std::cout << "Dimension of matrix: " << NumGlobalElements << std::endl; std::cout << "Number of right-hand sides: " << numrhs << std::endl; std::cout << "Block size used by solver: " << blocksize << std::endl; std::cout << "Number of restarts allowed: " << maxrestarts << std::endl; std::cout << "Max number of Gmres iterations per restart cycle: " << maxiters << std::endl; std::cout << "Relative residual tolerance: " << tol << std::endl; std::cout << std::endl; } // // Perform solve // Belos::ReturnType ret = solver->solve(); // // Compute actual residuals. // bool badRes = false; std::vector<double> actual_resids( numrhs ); std::vector<double> rhs_norm( numrhs ); Epetra_MultiVector resid(*Map, numrhs); OPT::Apply( *A, *X, resid ); MVT::MvAddMv( -1.0, resid, 1.0, *B, resid ); MVT::MvNorm( resid, actual_resids ); MVT::MvNorm( *B, rhs_norm ); if (proc_verbose) { std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl; for ( int i=0; i<numrhs; i++) { double actRes = actual_resids[i]/rhs_norm[i]; std::cout<<"Problem "<<i<<" : \t"<< actRes <<std::endl; if (actRes > tol) badRes = true; } } success = ret==Belos::Converged && !badRes; if (success) { if (proc_verbose) std::cout << "End Result: TEST PASSED" << std::endl; } else { if (proc_verbose) std::cout << "End Result: TEST FAILED" << std::endl; } } TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success); #ifdef EPETRA_MPI MPI_Finalize(); #endif return ( success ? EXIT_SUCCESS : EXIT_FAILURE ); }
int main(int argc, char *argv[]) { // int MyPID = 0; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); MyPID = Comm.MyPID(); #else Epetra_SerialComm Comm; #endif // typedef double ST; typedef Teuchos::ScalarTraits<ST> SCT; typedef SCT::magnitudeType MT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Belos::MultiVecTraits<ST,MV> MVT; typedef Belos::OperatorTraits<ST,MV,OP> OPT; using Teuchos::ParameterList; using Teuchos::RCP; using Teuchos::rcp; bool verbose = false, debug = false, proc_verbose = false, strict_conv = false; int frequency = -1; // frequency of status test output. int blocksize = 1; // blocksize int numrhs = 1; // number of right-hand sides to solve for int maxiters = -1; // maximum number of iterations allowed per linear system int maxsubspace = 50; // maximum number of blocks the solver can use for the subspace int maxrestarts = 15; // number of restarts allowed std::string filename("orsirr1.hb"); std::string precond("none"); MT tol = 1.0e-5; // relative residual tolerance MT polytol = tol/10; // relative residual tolerance for polynomial construction Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","nondebug",&debug,"Print debugging information from solver."); cmdp.setOption("strict-conv","not-strict-conv",&strict_conv,"Require solver to strictly adhere to convergence tolerance."); cmdp.setOption("frequency",&frequency,"Solvers frequency for printing residuals (#iters)."); cmdp.setOption("filename",&filename,"Filename for test matrix. Acceptable file extensions: *.hb,*.mtx,*.triU,*.triS"); cmdp.setOption("precond",&precond,"Preconditioning type (none, left, right)."); cmdp.setOption("tol",&tol,"Relative residual tolerance used by GMRES solver."); cmdp.setOption("poly-tol",&polytol,"Relative residual tolerance used to construct the GMRES polynomial."); cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for."); cmdp.setOption("block-size",&blocksize,"Block size used by GMRES."); cmdp.setOption("max-iters",&maxiters,"Maximum number of iterations per linear system (-1 = adapted to problem/block size)."); cmdp.setOption("max-subspace",&maxsubspace,"Maximum number of blocks the solver can use for the subspace."); cmdp.setOption("max-restarts",&maxrestarts,"Maximum number of restarts allowed for GMRES solver."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { return -1; } if (!verbose) frequency = -1; // reset frequency if test is not verbose // // Get the problem // RCP<Epetra_Map> Map; RCP<Epetra_CrsMatrix> A; RCP<Epetra_MultiVector> B, X; RCP<Epetra_Vector> vecB, vecX; EpetraExt::readEpetraLinearSystem(filename, Comm, &A, &Map, &vecX, &vecB); A->OptimizeStorage(); proc_verbose = verbose && (MyPID==0); /* Only print on the zero processor */ // Check to see if the number of right-hand sides is the same as requested. if (numrhs>1) { X = rcp( new Epetra_MultiVector( *Map, numrhs ) ); B = rcp( new Epetra_MultiVector( *Map, numrhs ) ); X->Seed(); X->Random(); OPT::Apply( *A, *X, *B ); X->PutScalar( 0.0 ); } else { X = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecX); B = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecB); } // // ************Construct preconditioner************* // RCP<Belos::EpetraPrecOp> belosPrec; if (precond != "none") { ParameterList ifpackList; // allocates an IFPACK factory. No data is associated // to this object (only method Create()). Ifpack Factory; // create the preconditioner. For valid PrecType values, // please check the documentation std::string PrecType = "ILU"; // incomplete LU int OverlapLevel = 1; // must be >= 0. If Comm.NumProc() == 1, // it is ignored. RCP<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*A, OverlapLevel) ); assert(Prec != Teuchos::null); // specify parameters for ILU ifpackList.set("fact: drop tolerance", 1e-9); ifpackList.set("fact: ilut level-of-fill", 1.0); // the combine mode is on the following: // "Add", "Zero", "Insert", "InsertAdd", "Average", "AbsMax" // Their meaning is as defined in file Epetra_CombineMode.h ifpackList.set("schwarz: combine mode", "Add"); // sets the parameters IFPACK_CHK_ERR(Prec->SetParameters(ifpackList)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. IFPACK_CHK_ERR(Prec->Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. IFPACK_CHK_ERR(Prec->Compute()); // Create the Belos preconditioned operator from the Ifpack preconditioner. // NOTE: This is necessary because Belos expects an operator to apply the // preconditioner with Apply() NOT ApplyInverse(). belosPrec = rcp( new Belos::EpetraPrecOp( Prec ) ); } // // ********Other information used by block solver*********** // *****************(can be user specified)****************** // const int NumGlobalElements = B->GlobalLength(); if (maxiters == -1) maxiters = NumGlobalElements/blocksize - 1; // maximum number of iterations to run // ParameterList belosList; belosList.set( "Num Blocks", maxsubspace); // Maximum number of blocks in Krylov factorization belosList.set( "Block Size", blocksize ); // Blocksize to be used by iterative solver belosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed belosList.set( "Maximum Restarts", maxrestarts ); // Maximum number of restarts allowed belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested belosList.set( "Polynomial Tolerance", polytol ); // Polynomial convergence tolerance requested belosList.set( "Strict Convergence", strict_conv ); // Whether solver must strictly reach requested tolerance int verbosity = Belos::Errors + Belos::Warnings; if (verbose) { verbosity += Belos::TimingDetails + Belos::StatusTestDetails; if (frequency > 0) belosList.set( "Output Frequency", frequency ); } if (debug) { verbosity += Belos::Debug; } belosList.set( "Verbosity", verbosity ); // // Construct an unpreconditioned linear problem instance. // Belos::LinearProblem<double,MV,OP> problem( A, X, B ); if (precond == "left") { problem.setLeftPrec( belosPrec ); } else if (precond == "right") { problem.setRightPrec( belosPrec ); } bool set = problem.setProblem(); if (set == false) { if (proc_verbose) std::cout << std::endl << "ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; return -1; } // // ******************************************************************* // *************Start the block Gmres iteration************************* // ******************************************************************* // Belos::OutputManager<double> My_OM(); // Create an iterative solver manager. RCP< Belos::SolverManager<double,MV,OP> > newSolver //= rcp( new Belos::BlockGmresSolMgr<double,MV,OP>(rcp(&problem,false), rcp(&belosList,false))); = rcp( new Belos::GmresPolySolMgr<double,MV,OP>(rcp(&problem,false), rcp(&belosList,false))); // // **********Print out information about problem******************* // if (proc_verbose) { std::cout << std::endl << std::endl; std::cout << "Dimension of matrix: " << NumGlobalElements << std::endl; std::cout << "Number of right-hand sides: " << numrhs << std::endl; std::cout << "Block size used by solver: " << blocksize << std::endl; std::cout << "Max number of restarts allowed: " << maxrestarts << std::endl; std::cout << "Max number of Gmres iterations per restart cycle: " << maxiters << std::endl; std::cout << "Relative residual tolerance: " << tol << std::endl; std::cout << std::endl; } // // Perform solve // Belos::ReturnType ret = newSolver->solve(); // // Compute actual residuals. // bool badRes = false; std::vector<double> actual_resids( numrhs ); std::vector<double> rhs_norm( numrhs ); Epetra_MultiVector resid(*Map, numrhs); OPT::Apply( *A, *X, resid ); MVT::MvAddMv( -1.0, resid, 1.0, *B, resid ); MVT::MvNorm( resid, actual_resids ); MVT::MvNorm( *B, rhs_norm ); if (proc_verbose) { std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl; for ( int i=0; i<numrhs; i++) { double actRes = actual_resids[i]/rhs_norm[i]; std::cout<<"Problem "<<i<<" : \t"<< actRes <<std::endl; if (actRes > tol) badRes = true; } } #ifdef EPETRA_MPI MPI_Finalize(); #endif if ((ret!=Belos::Converged || badRes) && strict_conv) { if (proc_verbose) std::cout << std::endl << "ERROR: Belos did not converge!" << std::endl; return -1; } // // Default return value // if (proc_verbose) std::cout << std::endl << "SUCCESS: Belos converged!" << std::endl; return 0; // }
TEUCHOS_UNIT_TEST(Belos_Hypre, Laplace2D){ const double tol = 1E-7; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::ParameterList; typedef Belos::LinearProblem<double,Epetra_MultiVector,Epetra_Operator> LinearProblem; // // Create Laplace2D // #ifdef HAVE_MPI Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm(); #endif Teuchos::ParameterList GaleriList; int nx = 10 * Comm.NumProc(); int ny = 10 * Comm.NumProc(); GaleriList.set("nx", nx); GaleriList.set("ny", ny); Epetra_Map Map(nx*ny,0,Comm); RCP<Epetra_CrsMatrix> Crs_Matrix = rcp(Galeri::CreateCrsMatrix("Laplace2D", &Map, GaleriList)); int NumProc = Crs_Matrix->Comm().NumProc(); // // Create the hypre preconditioner // RCP<Ifpack_Hypre> preconditioner = rcp(new Ifpack_Hypre(Crs_Matrix.get())); TEST_EQUALITY(preconditioner->Initialize(),0); TEST_EQUALITY(preconditioner->SetParameter(Preconditioner, ParaSails),0); // Use a Euclid Preconditioner (but not really used) TEST_EQUALITY(preconditioner->SetParameter(Preconditioner),0); // Solve the problem TEST_EQUALITY(preconditioner->Compute(),0); // // Create the solution vector and rhs // int numVec = 1; RCP<Epetra_MultiVector> X = rcp(new Epetra_MultiVector(Crs_Matrix->OperatorDomainMap(), numVec)); RCP<Epetra_MultiVector> KnownX = rcp(new Epetra_MultiVector(Crs_Matrix->OperatorDomainMap(), numVec)); KnownX->Random(); RCP<Epetra_MultiVector> B = rcp(new Epetra_MultiVector(Crs_Matrix->OperatorRangeMap(), numVec)); Crs_Matrix->Apply(*KnownX, *B); // // Test the EpetraExt wrapper // amk November 24, 2015: Should we deprecate this? // // RCP<ParameterList> pl = rcp(new ParameterList()); // TEST_EQUALITY(X->PutScalar(0.0),0); // HYPRE_IJMatrix hypre_mat = preconditioner->HypreMatrix(); // RCP<EpetraExt_HypreIJMatrix> Hyp_Matrix = rcp(new EpetraExt_HypreIJMatrix(hypre_mat)); // TEST_EQUALITY(Hyp_Matrix->SetParameter(Preconditioner, ParaSails),0); // TEST_EQUALITY(Hyp_Matrix->SetParameter(Preconditioner),0); // TEST_EQUALITY(EquivalentMatrices(*Hyp_Matrix, *Crs_Matrix, tol), true); // RCP<LinearProblem> problem1 = rcp(new LinearProblem(Crs_Matrix,X,B)); // problem1->setLeftPrec(Hyp_Matrix); // TEST_EQUALITY(problem1->setProblem(),true); // Belos::PseudoBlockGmresSolMgr<double,Epetra_MultiVector,Epetra_Operator> solMgr1(problem1,pl); // Belos::ReturnType rv1 = solMgr1.solve(); // TEST_EQUALITY(solMgr2.solve(),Belos::Converged); // TEST_EQUALITY(rv1,Belos::Converged); // TEST_EQUALITY(EquivalentVectors(*X, *KnownX, tol*10*pow(10.0,NumProc)), true); // // Test the Ifpack hypre interface // RCP<ParameterList> pl2 = rcp(new ParameterList()); RCP<Epetra_Operator> invOp = rcp(new Epetra_InvOperator(preconditioner.get())); TEST_EQUALITY(X->PutScalar(0.0),0); RCP<LinearProblem> problem2 = rcp(new LinearProblem(Crs_Matrix,X,B)); problem2->setLeftPrec(invOp); TEST_EQUALITY(problem2->setProblem(),true); Belos::PseudoBlockGmresSolMgr<double,Epetra_MultiVector,Epetra_Operator> solMgr2(problem2,pl2); Belos::ReturnType rv2 = solMgr2.solve(); // TEST_EQUALITY(solMgr2.solve(),Belos::Converged); TEST_EQUALITY(rv2,Belos::Converged); TEST_EQUALITY(EquivalentVectors(*X, *KnownX, tol*10*pow(10.0,NumProc)), true); }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int main(int argc, char *argv[]) { using namespace std; using namespace Teuchos; using namespace PHX; #ifdef HAVE_MPI MPI_Init(&argc, &argv); #endif try { RCP<Time> total_time = TimeMonitor::getNewTimer("Total Run Time"); TimeMonitor tm(*total_time); bool print_debug_info = true; cout << "\nStarting Epetra_VBR_Test Example!\n" << endl; // ********************************************************* // * Build the Finite Element data structures // ********************************************************* // Create the mesh, one strip of 2D elements. const std::size_t num_local_cells = 5; double domain_length = 1.0; double dx = domain_length / static_cast<double>(num_local_cells); std::vector<int> global_id(4); global_id[0] = 0; global_id[1] = 2; global_id[2] = 3; global_id[3] = 1; std::vector<double> x_coords(4); std::vector<double> y_coords(4); std::vector<Element_Linear2D> cells; for (std::size_t i = 0; i < num_local_cells; ++i) { x_coords[0] = static_cast<double>(i) * dx; x_coords[1] = x_coords[0] + dx; x_coords[2] = x_coords[0] + dx; x_coords[3] = static_cast<double>(i) * dx; y_coords[0] = 0.0; y_coords[1] = 0.0; y_coords[2] = 1.0; y_coords[3] = 1.0; Element_Linear2D e(global_id, i, i, x_coords, y_coords); cells.push_back(e); // update global indices for next element for (std::size_t i=0; i < global_id.size(); ++i) global_id[i] += 2; } // Divide mesh into workset blocks const std::size_t workset_size = 5; std::vector<MyWorkset> worksets; { std::vector<Element_Linear2D>::iterator cell_it = cells.begin(); std::size_t count = 0; MyWorkset w; w.local_offset = cell_it->localElementIndex(); w.begin = cell_it; for (; cell_it != cells.end(); ++cell_it) { ++count; std::vector<Element_Linear2D>::iterator next = cell_it; ++next; if ( count == workset_size || next == cells.end()) { w.end = next; w.num_cells = count; worksets.push_back(w); count = 0; if (next != cells.end()) { w.local_offset = next->localElementIndex(); w.begin = next; } } } } if (print_debug_info) { cout << "Printing Element Information" << endl; for (std::size_t i = 0; i < worksets.size(); ++i) { std::vector<Element_Linear2D>::iterator it = worksets[i].begin; for (; it != worksets[i].end; ++it) cout << *it << endl; } } if (print_debug_info) { for (std::size_t i = 0; i < worksets.size(); ++i) { cout << "Printing Workset Information" << endl; cout << "worksets[" << i << "]" << endl; cout << " num_cells =" << worksets[i].num_cells << endl; cout << " local_offset =" << worksets[i].local_offset << endl; std::vector<Element_Linear2D>::iterator it = worksets[i].begin; for (; it != worksets[i].end; ++it) cout << " cell_local_index =" << it->localElementIndex() << endl; } cout << endl; } // ********************************************************* // * Build the Newton solver data structures // ********************************************************* // Setup Nonlinear Problem (build Epetra_Vector and Epetra_CrsMatrix) // Newton's method: J delta_x = -f const std::size_t num_eq = 2; const std::size_t num_nodes = 2 * (num_local_cells +1); const std::size_t num_dof = num_nodes * num_eq; RCP<Epetra_Vector> x; RCP<Epetra_Vector> delta_x; RCP<Epetra_Vector> f; RCP<Epetra_VbrRowMatrix> Jac; { Epetra_SerialComm comm; Epetra_BlockMap map(static_cast<int>(num_nodes), static_cast<int>(num_eq), 0, comm); Epetra_DataAccess copy = ::Copy; Epetra_CrsGraph graph(copy, map, 3); std::vector<Element_Linear2D>::iterator e = cells.begin(); for (; e != cells.end(); ++e) { for (int row = 0; row < e->numNodes(); ++row) { for (int col = 0; col < e->numNodes(); ++col) { int global_row = e->globalNodeId(row); int global_col = e->globalNodeId(col); graph.InsertGlobalIndices(global_row, 1, &global_col); } } } graph.FillComplete(); graph.Print(cout); Epetra_SerialDenseMatrix block_matrix(2,2); Epetra_SerialDenseMatrix diag_block_matrix(2,2); RCP<Epetra_VbrMatrix> Jac_vbr = rcp(new Epetra_VbrMatrix(copy,graph)); Epetra_Util util; e = cells.begin(); for (; e != cells.end(); ++e) { for (int row = 0; row < e->numNodes(); ++row) { int global_row = e->globalNodeId(row); block_matrix(0,0) = util.RandomDouble(); block_matrix(0,1) = util.RandomDouble(); block_matrix(1,0) = util.RandomDouble(); block_matrix(1,1) = util.RandomDouble(); diag_block_matrix(0,0) = 100.0*util.RandomDouble(); diag_block_matrix(0,1) = util.RandomDouble(); diag_block_matrix(1,0) = util.RandomDouble(); diag_block_matrix(1,1) = 100.0*util.RandomDouble(); for (int col = 0; col < e->numNodes(); ++col) { int global_col = e->globalNodeId(col); Jac_vbr->BeginReplaceMyValues(global_row, 1, &global_col); if (global_row==global_col) Jac_vbr->SubmitBlockEntry(diag_block_matrix); else Jac_vbr->SubmitBlockEntry(block_matrix); Jac_vbr->EndSubmitEntries(); } } } Jac_vbr->FillComplete(); x = rcp(new Epetra_Vector(map)); delta_x = rcp(new Epetra_Vector(map)); f = rcp(new Epetra_Vector(map)); x->PutScalar(1.0); Jac_vbr->Apply(*x,*f); Jac = rcpWithEmbeddedObjPostDestroy(new Epetra_VbrRowMatrix(Jac_vbr.get()), Jac_vbr); } if (print_debug_info) { x->Print(cout); Jac->Print(cout); f->Print(cout); } // ********************************************************* // * Build Preconditioner (Ifpack) // ********************************************************* Ifpack Factory; std::string PrecType = "ILU"; int OverlapLevel = 1; RCP<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*Jac, OverlapLevel) ); ParameterList ifpackList; ifpackList.set("fact: drop tolerance", 1e-9); ifpackList.set("fact: level-of-fill", 1); ifpackList.set("schwarz: combine mode", "Add"); IFPACK_CHK_ERR(Prec->SetParameters(ifpackList)); IFPACK_CHK_ERR(Prec->Initialize()); IFPACK_CHK_ERR(Prec->Compute()); IFPACK_CHK_ERR(Prec->Condest()); RCP<Belos::EpetraPrecOp> belosPrec = rcp( new Belos::EpetraPrecOp( Prec ) ); // ********************************************************* // * Build linear solver (Belos) // ********************************************************* // Linear solver parameters typedef double ST; typedef Teuchos::ScalarTraits<ST> SCT; typedef SCT::magnitudeType MT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Belos::MultiVecTraits<ST,MV> MVT; typedef Belos::OperatorTraits<ST,MV,OP> OPT; RCP<ParameterList> belosList = rcp(new ParameterList); belosList->set<int>("Num Blocks", num_dof); belosList->set<int>("Block Size", 1); belosList->set<int>("Maximum Iterations", 400); belosList->set<int>("Maximum Restarts", 0); belosList->set<MT>( "Convergence Tolerance", 1.0e-4); int verbosity = Belos::Errors + Belos::Warnings; if (false) { verbosity += Belos::TimingDetails + Belos::StatusTestDetails; belosList->set<int>( "Output Frequency", -1); } if (print_debug_info) { verbosity += Belos::Debug; belosList->set<int>( "Output Frequency", -1); } belosList->set( "Verbosity", verbosity ); RCP<Epetra_MultiVector> F = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(f); RCP<Epetra_MultiVector> DX = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(delta_x); RCP<Belos::LinearProblem<double,MV,OP> > problem = rcp(new Belos::LinearProblem<double,MV,OP>(Jac, DX, F) ); problem->setRightPrec( belosPrec ); RCP< Belos::SolverManager<double,MV,OP> > gmres_solver = rcp( new Belos::BlockGmresSolMgr<double,MV,OP>(problem, belosList) ); // ********************************************************* // * Solve the system // ********************************************************* RCP<Time> linear_solve_time = TimeMonitor::getNewTimer("Linear Solve Time"); std::size_t num_gmres_iterations = 0; { TimeMonitor t(*linear_solve_time); delta_x->PutScalar(0.0); IFPACK_CHK_ERR(Prec->Compute()); problem->setProblem(); Belos::ReturnType ret = gmres_solver->solve(); int num_iters = gmres_solver->getNumIters(); num_gmres_iterations += num_iters; if (print_debug_info) std::cout << "Number of gmres iterations performed for this solve: " << num_iters << std::endl; if (ret!=Belos::Converged) { std::cout << std::endl << "WARNING: Belos did not converge!" << std::endl; } } delta_x->Print(cout); // ********************************************************************* // Finished all testing // ********************************************************************* std::cout << "\nRun has completed successfully!\n" << std::endl; // ********************************************************************* // ********************************************************************* } catch (const std::exception& e) { std::cout << "************************************************" << endl; std::cout << "************************************************" << endl; std::cout << "Exception Caught!" << endl; std::cout << "Error message is below\n " << e.what() << endl; std::cout << "************************************************" << endl; } catch (...) { std::cout << "************************************************" << endl; std::cout << "************************************************" << endl; std::cout << "Unknown Exception Caught!" << endl; std::cout << "************************************************" << endl; } TimeMonitor::summarize(); #ifdef HAVE_MPI MPI_Finalize(); #endif return 0; }
int main(int argc, char *argv[]) { // #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Belos::MPIFinalize mpiFinalize; // Will call finalize with *any* return (void)mpiFinalize; #endif // using Teuchos::RCP; using Teuchos::rcp; // // Get test parameters from command-line processor // bool verbose = false, proc_verbose = false; int frequency = -1; // how often residuals are printed by solver int numrhs = 15; // total number of right-hand sides to solve for int blocksize = 10; // blocksize used by solver int maxiters = -1; // maximum number of iterations for the solver to use std::string filename("bcsstk14.hb"); double tol = 1.0e-5; // relative residual tolerance Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("frequency",&frequency,"Solvers frequency for printing residuals (#iters)."); cmdp.setOption("filename",&filename,"Filename for Harwell-Boeing test matrix."); cmdp.setOption("tol",&tol,"Relative residual tolerance used by CG solver."); cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for."); cmdp.setOption("block-size",&blocksize,"Block size to be used by CG solver."); cmdp.setOption("max-iters",&maxiters,"Maximum number of iterations per linear system (-1 := adapted to problem/block size)."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { return -1; } if (!verbose) frequency = -1; // Reset frequency if verbosity is off // // Get the problem // int MyPID; RCP<Epetra_CrsMatrix> A; RCP<Epetra_MultiVector> X, B; int return_val =Belos::createEpetraProblem(filename,NULL,&A,&B,&X,&MyPID); if(return_val != 0) return return_val; proc_verbose = ( verbose && (MyPID==0) ); // // Solve using Belos // typedef double ST; typedef Epetra_Operator OP; typedef Epetra_MultiVector MV; typedef Belos::OperatorTraits<ST,MV,OP> OPT; typedef Belos::MultiVecTraits<ST,MV> MVT; // // *****Construct initial guess and random right-hand-sides ***** // if (numrhs != 1) { X = rcp( new Epetra_MultiVector( A->Map(), numrhs ) ); MVT::MvRandom( *X ); B = rcp( new Epetra_MultiVector( A->Map(), numrhs ) ); OPT::Apply( *A, *X, *B ); MVT::MvInit( *X, 0.0 ); } // // ************Construct preconditioner************* // ParameterList ifpackList; // allocates an IFPACK factory. No data is associated // to this object (only method Create()). Ifpack Factory; // create the preconditioner. For valid PrecType values, // please check the documentation std::string PrecType = "ICT"; // incomplete Cholesky int OverlapLevel = 0; // must be >= 0. If Comm.NumProc() == 1, // it is ignored. RCP<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*A, OverlapLevel) ); assert(Prec != Teuchos::null); // specify parameters for ICT ifpackList.set("fact: drop tolerance", 1e-9); ifpackList.set("fact: ict level-of-fill", 1.0); // the combine mode is on the following: // "Add", "Zero", "Insert", "InsertAdd", "Average", "AbsMax" // Their meaning is as defined in file Epetra_CombineMode.h ifpackList.set("schwarz: combine mode", "Add"); // sets the parameters IFPACK_CHK_ERR(Prec->SetParameters(ifpackList)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. IFPACK_CHK_ERR(Prec->Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. IFPACK_CHK_ERR(Prec->Compute()); // Create the Belos preconditioned operator from the Ifpack preconditioner. // NOTE: This is necessary because Belos expects an operator to apply the // preconditioner with Apply() NOT ApplyInverse(). RCP<Belos::EpetraPrecOp> belosPrec = rcp( new Belos::EpetraPrecOp( Prec ) ); // // *****Create parameter list for the block CG solver manager***** // const int NumGlobalElements = B->GlobalLength(); if (maxiters == -1) maxiters = NumGlobalElements/blocksize - 1; // maximum number of iterations to run // ParameterList belosList; belosList.set( "Block Size", blocksize ); // Blocksize to be used by iterative solver belosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested if (verbose) { belosList.set( "Verbosity", Belos::Errors + Belos::Warnings + Belos::TimingDetails + Belos::FinalSummary + Belos::StatusTestDetails ); if (frequency > 0) belosList.set( "Output Frequency", frequency ); } else belosList.set( "Verbosity", Belos::Errors + Belos::Warnings ); // // *******Construct a preconditioned linear problem******** // RCP<Belos::LinearProblem<double,MV,OP> > problem = rcp( new Belos::LinearProblem<double,MV,OP>( A, X, B ) ); problem->setLeftPrec( belosPrec ); bool set = problem->setProblem(); if (set == false) { if (proc_verbose) std::cout << std::endl << "ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; return -1; } // Create an iterative solver manager. RCP< Belos::SolverManager<double,MV,OP> > solver = rcp( new Belos::BlockCGSolMgr<double,MV,OP>(problem, rcp(&belosList,false)) ); // // ******************************************************************* // *************Start the block CG iteration************************* // ******************************************************************* if (proc_verbose) { std::cout << std::endl << std::endl; std::cout << "Dimension of matrix: " << NumGlobalElements << std::endl; std::cout << "Number of right-hand sides: " << numrhs << std::endl; std::cout << "Block size used by solver: " << blocksize << std::endl; std::cout << "Max number of CG iterations: " << maxiters << std::endl; std::cout << "Relative residual tolerance: " << tol << std::endl; std::cout << std::endl; } // // Perform solve // Belos::ReturnType ret = solver->solve(); // // Compute actual residuals. // bool badRes = false; std::vector<double> actual_resids( numrhs ); std::vector<double> rhs_norm( numrhs ); Epetra_MultiVector resid(A->Map(), numrhs); OPT::Apply( *A, *X, resid ); MVT::MvAddMv( -1.0, resid, 1.0, *B, resid ); MVT::MvNorm( resid, actual_resids ); MVT::MvNorm( *B, rhs_norm ); if (proc_verbose) { std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl; for ( int i=0; i<numrhs; i++) { double actRes = actual_resids[i]/rhs_norm[i]; std::cout<<"Problem "<<i<<" : \t"<< actRes <<std::endl; if (actRes > tol) badRes = true; } } if (ret!=Belos::Converged || badRes) { if (proc_verbose) std::cout << std::endl << "End Result: TEST FAILED" << std::endl; return -1; } // // Default return value // if (proc_verbose) std::cout << std::endl << "End Result: TEST PASSED" << std::endl; return 0; // } // end test_bl_pcg_hb.cpp
int main(int argc, char *argv[]) { // int MyPID = 0; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); MyPID = Comm.MyPID(); #else Epetra_SerialComm Comm; #endif // typedef double ST; typedef Teuchos::ScalarTraits<ST> SCT; typedef SCT::magnitudeType MT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Belos::MultiVecTraits<ST,MV> MVT; typedef Belos::OperatorTraits<ST,MV,OP> OPT; using Teuchos::ParameterList; using Teuchos::RCP; using Teuchos::rcp; bool verbose = false; bool success = true; try { bool proc_verbose = false; bool leftprec = true; // left preconditioning or right. // LSQR applies the operator and the transposed operator. // A preconditioner must support transpose multiply. int frequency = -1; // frequency of status test output. int blocksize = 1; // blocksize // LSQR as currently implemented is a single vector algorithm. // However some of the parameters that would be used by a block version // have not been removed from this file. int numrhs = 1; // number of right-hand sides to solve for int maxiters = -1; // maximum number of iterations allowed per linear system std::string filename("orsirr1_scaled.hb"); MT relResTol = 1.0e-5; // relative residual tolerance for the preconditioned linear system MT resGrowthFactor = 1.0; // In this example, warn if |resid| > resGrowthFactor * relResTol MT relMatTol = 1.e-10; // relative Matrix error, default value sqrt(eps) MT maxCond = 1.e+5; // maximum condition number default value 1/eps MT damp = 0.; // regularization (or damping) parameter Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("left-prec","right-prec",&leftprec,"Left preconditioning or right."); cmdp.setOption("frequency",&frequency,"Solvers frequency for printing residuals (#iters)."); cmdp.setOption("filename",&filename,"Filename for test matrix. Acceptable file extensions: *.hb,*.mtx,*.triU,*.triS"); cmdp.setOption("lambda",&damp,"Regularization parameter"); cmdp.setOption("tol",&relResTol,"Relative residual tolerance"); cmdp.setOption("matrixTol",&relMatTol,"Relative error in Matrix"); cmdp.setOption("max-cond",&maxCond,"Maximum condition number"); cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for."); cmdp.setOption("block-size",&blocksize,"Block size used by LSQR."); cmdp.setOption("max-iters",&maxiters,"Maximum number of iterations per linear system (-1 = adapted to problem/block size)."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { return -1; } if (!verbose) frequency = -1; // reset frequency if test is not verbose // // *************Get the problem********************* // RCP<Epetra_Map> Map; RCP<Epetra_CrsMatrix> A; RCP<Epetra_MultiVector> B, X; RCP<Epetra_Vector> vecB, vecX; EpetraExt::readEpetraLinearSystem(filename, Comm, &A, &Map, &vecX, &vecB); A->OptimizeStorage(); proc_verbose = verbose && (MyPID==0); /* Only print on the zero processor */ // Check to see if the number of right-hand sides is the same as requested. if (numrhs>1) { X = rcp( new Epetra_MultiVector( *Map, numrhs ) ); B = rcp( new Epetra_MultiVector( *Map, numrhs ) ); X->Random(); OPT::Apply( *A, *X, *B ); X->PutScalar( 0.0 ); } else { int locNumCol = Map->MaxLID() + 1; // Create a known solution int globNumCol = Map->MaxAllGID() + 1; for( int li = 0; li < locNumCol; li++){ // assume consecutive lid int gid = Map->GID(li); double value = (double) ( globNumCol -1 - gid ); int numEntries = 1; vecX->ReplaceGlobalValues( numEntries, &value, &gid ); } bool Trans = false; A->Multiply( Trans, *vecX, *vecB ); // Create a consistent linear system // At this point, the initial guess is exact. bool zeroInitGuess = false; // annihilate initial guess bool goodInitGuess = true; // initial guess near solution if( zeroInitGuess ) { vecX->PutScalar( 0.0 ); } else { if( goodInitGuess ) { double value = 1.e-2; // "Rel RHS Err" and "Rel Mat Err" apply to the residual equation, int numEntries = 1; // norm( b - A x_k ) ?<? relResTol norm( b- Axo). int index = 0; // norm(b) is inaccessible to LSQR. vecX->SumIntoMyValues( numEntries, &value, &index); } } X = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecX); B = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecB); } // // ************Construct preconditioner************* // ParameterList ifpackList; // allocates an IFPACK factory. No data is associated // to this object (only method Create()). Ifpack Factory; // do support transpose multiply // create the preconditioner. For valid PrecType values, // please check the documentation std::string PrecType = "ILU"; // incomplete LU int OverlapLevel = 1; // nonnegative RCP<Ifpack_Preconditioner> Prec = Teuchos::rcp( Factory.Create(PrecType, &*A, OverlapLevel) ); assert(Prec != Teuchos::null); // specify parameters for ILU ifpackList.set("fact: level-of-fill", 1); // the combine mode is on the following: // "Add", "Zero", "Insert", "InsertAdd", "Average", "AbsMax" // Their meaning is as defined in file Epetra_CombineMode.h ifpackList.set("schwarz: combine mode", "Add"); // sets the parameters IFPACK_CHK_ERR(Prec->SetParameters(ifpackList)); // initialize the preconditioner. At this point the matrix must // have been FillComplete()'d, but actual values are ignored. IFPACK_CHK_ERR(Prec->Initialize()); // Builds the preconditioners, by looking for the values of // the matrix. IFPACK_CHK_ERR(Prec->Compute()); { const int errcode = Prec->SetUseTranspose (true); if (errcode != 0) { throw std::logic_error ("Oh hai! Ifpack_Preconditioner doesn't know how to apply its transpose."); } else { (void) Prec->SetUseTranspose (false); } } // Create the Belos preconditioned operator from the Ifpack preconditioner. // NOTE: This is necessary because Belos expects an operator to apply the // preconditioner with Apply() NOT ApplyInverse(). RCP<Belos::EpetraPrecOp> belosPrec = rcp( new Belos::EpetraPrecOp( Prec ) ); // // *****Create parameter list for the LSQR solver manager***** // const int NumGlobalElements = B->GlobalLength(); if (maxiters == -1) maxiters = NumGlobalElements/blocksize - 1; // maximum number of iterations to run // ParameterList belosList; belosList.set( "Block Size", blocksize ); // Blocksize to be used by iterative solver belosList.set( "Lambda", damp ); // Regularization parameter belosList.set( "Rel RHS Err", relResTol ); // Relative convergence tolerance requested belosList.set( "Rel Mat Err", relMatTol ); // Maximum number of restarts allowed belosList.set( "Condition Limit", maxCond); // upper bound for cond(A) belosList.set( "Maximum Iterations", maxiters );// Maximum number of iterations allowed if (numrhs > 1) { belosList.set( "Show Maximum Residual Norm Only", true ); // Show only the maximum residual norm } if (verbose) { belosList.set( "Verbosity", Belos::Errors + Belos::Warnings + Belos::TimingDetails + Belos::StatusTestDetails ); if (frequency > 0) belosList.set( "Output Frequency", frequency ); } else belosList.set( "Verbosity", Belos::Errors + Belos::Warnings ); // // *******Construct a preconditioned linear problem******** // RCP<Belos::LinearProblem<double,MV,OP> > problem = rcp( new Belos::LinearProblem<double,MV,OP>( A, X, B ) ); if (leftprec) { problem->setLeftPrec( belosPrec ); } else { problem->setRightPrec( belosPrec ); } bool set = problem->setProblem(); if (set == false) { if (proc_verbose) std::cout << std::endl << "ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; return -1; } // Create an iterative solver manager. RCP< Belos::LSQRSolMgr<double,MV,OP> > solver = rcp( new Belos::LSQRSolMgr<double,MV,OP>(problem, rcp(&belosList,false))); // // ******************************************************************* // ******************Start the LSQR iteration************************* // ******************************************************************* // if (proc_verbose) { std::cout << std::endl << std::endl; std::cout << "Dimension of matrix: " << NumGlobalElements << std::endl; std::cout << "Number of right-hand sides: " << numrhs << std::endl; std::cout << "Block size used by solver: " << blocksize << std::endl; std::cout << "Max number of Gmres iterations per restart cycle: " << maxiters << std::endl; std::cout << "Relative residual tolerance: " << relResTol << std::endl; std::cout << std::endl; std::cout << "Solver's Description: " << std::endl; std::cout << solver->description() << std::endl; // visually verify the parameter list } // // Perform solve // Belos::ReturnType ret = solver->solve(); // // Get the number of iterations for this solve. // std::vector<double> solNorm( numrhs ); // get solution norm MVT::MvNorm( *X, solNorm ); int numIters = solver->getNumIters(); MT condNum = solver->getMatCondNum(); MT matrixNorm= solver->getMatNorm(); MT resNorm = solver->getResNorm(); MT lsResNorm = solver->getMatResNorm(); if (proc_verbose) std::cout << "Number of iterations performed for this solve: " << numIters << std::endl << "matrix condition number: " << condNum << std::endl << "matrix norm: " << matrixNorm << std::endl << "residual norm: " << resNorm << std::endl << "solution norm: " << solNorm[0] << std::endl << "least squares residual Norm: " << lsResNorm << std::endl; // // Compute actual residuals. // bool badRes = false; std::vector<double> actual_resids( numrhs ); std::vector<double> rhs_norm( numrhs ); Epetra_MultiVector resid(*Map, numrhs); OPT::Apply( *A, *X, resid ); MVT::MvAddMv( -1.0, resid, 1.0, *B, resid ); MVT::MvNorm( resid, actual_resids ); MVT::MvNorm( *B, rhs_norm ); if (proc_verbose) { std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl; for ( int i=0; i<numrhs; i++) { double actRes = actual_resids[i]/rhs_norm[i]; std::cout<<"Problem "<<i<<" : \t"<< actRes <<std::endl; if (actRes > relResTol * resGrowthFactor ) badRes = true; } } if (ret!=Belos::Converged || badRes) { success = false; if (proc_verbose) std::cout << std::endl << "ERROR: Belos did not converge!" << std::endl; } else { success = true; if (proc_verbose) std::cout << std::endl << "SUCCESS: Belos converged!" << std::endl; } } TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success); #ifdef EPETRA_MPI MPI_Finalize(); #endif return success ? EXIT_SUCCESS : EXIT_FAILURE; }