int main(int argc, char *argv[]) { // Teuchos::GlobalMPISession session(&argc, &argv, NULL); // 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; // use left preconditioning to solve these linear systems int frequency = -1; // how often residuals are printed by solver int blocksize = 4; int numrhs = 15; int maxrestarts = 15; // number of restarts allowed int length = 25; int maxiters = -1; // maximum iterations allowed std::string filename("orsirr1.hb"); MT tol = 1.0e-5; // relative residual tolerance 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 Harwell-Boeing test matrix."); 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("max-restarts",&maxrestarts,"Maximum number of restarts allowed for GMRES solver."); cmdp.setOption("blocksize",&blocksize,"Block size used by GMRES."); cmdp.setOption("maxiters",&maxiters,"Maximum number of iterations per linear system (-1 = adapted to problem/block size)."); cmdp.setOption("subspace-size",&length,"Dimension of Krylov subspace used by GMRES."); 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 // int MyPID; RCP<Epetra_CrsMatrix> A; int return_val =Belos::createEpetraProblem(filename,NULL,&A,NULL,NULL,&MyPID); const Epetra_Map &Map = A->RowMap(); if(return_val != 0) return return_val; proc_verbose = verbose && (MyPID==0); /* Only print on zero processor */ // // *****Construct the Preconditioner***** // if (proc_verbose) std::cout << std::endl << std::endl; if (proc_verbose) std::cout << "Constructing ILU preconditioner" << std::endl; int Lfill = 2; // if (argc > 2) Lfill = atoi(argv[2]); if (proc_verbose) std::cout << "Using Lfill = " << Lfill << std::endl; int Overlap = 2; // if (argc > 3) Overlap = atoi(argv[3]); if (proc_verbose) std::cout << "Using Level Overlap = " << Overlap << std::endl; double Athresh = 0.0; // if (argc > 4) Athresh = atof(argv[4]); if (proc_verbose) std::cout << "Using Absolute Threshold Value of " << Athresh << std::endl; double Rthresh = 1.0; // if (argc >5) Rthresh = atof(argv[5]); if (proc_verbose) std::cout << "Using Relative Threshold Value of " << Rthresh << std::endl; // Teuchos::RCP<Ifpack_IlukGraph> ilukGraph; Teuchos::RCP<Ifpack_CrsRiluk> ilukFactors; // if (Lfill > -1) { ilukGraph = Teuchos::rcp(new Ifpack_IlukGraph(A->Graph(), Lfill, Overlap)); int info = ilukGraph->ConstructFilledGraph(); assert( info == 0 ); ilukFactors = Teuchos::rcp(new Ifpack_CrsRiluk(*ilukGraph)); int initerr = ilukFactors->InitValues(*A); if (initerr != 0) std::cout << "InitValues error = " << initerr; info = ilukFactors->Factor(); assert( info == 0 ); } // bool transA = false; double Cond_Est; ilukFactors->Condest(transA, Cond_Est); if (proc_verbose) { std::cout << "Condition number estimate for this preconditoner = " << Cond_Est << std::endl; std::cout << std::endl; } // // 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> Prec = rcp( new Belos::EpetraPrecOp( ilukFactors ) ); // // ********Other information used by block solver*********** // **************(can be user specified)******************** // const int NumGlobalElements = Map.NumGlobalElements(); if (maxiters == -1) maxiters = NumGlobalElements/blocksize - 1; // maximum number of iterations to run // ParameterList innerBelosList; innerBelosList.set( "Solver", "BlockGmres" ); // Set the inner solver to use block Gmres innerBelosList.set( "Num Blocks", length ); // Maximum number of blocks in Krylov factorization innerBelosList.set( "Block Size", blocksize ); // Blocksize to be used by iterative solver innerBelosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed innerBelosList.set( "Maximum Restarts", maxrestarts ); // Maximum number of restarts allowed innerBelosList.set( "Convergence Tolerance", 1.0e-2 ); // Relative convergence tolerance requested innerBelosList.set( "Verbosity", Belos::Errors + Belos::Warnings ); innerBelosList.set( "Timer Label", "Belos Preconditioner Solve" );// Choose a different label for the inner solve // // *****Construct linear problem using A and Prec***** // ***The solution and RHS vectors will be set later** Belos::LinearProblem<double,MV,OP> innerProblem; innerProblem.setOperator( A ); if (leftprec) innerProblem.setLeftPrec( Prec ); else innerProblem.setRightPrec( Prec ); innerProblem.setLabel( "Belos Preconditioner Solve" ); // // *****Create the inner block Gmres iteration******** // RCP<Belos::EpetraOperator> innerSolver; innerSolver = rcp( new Belos::EpetraOperator( rcp(&innerProblem,false) , rcp(&innerBelosList,false), true ) ); // // *****Construct solution std::vector and random right-hand-sides ***** // RCP<Epetra_MultiVector> X = rcp( new Epetra_MultiVector(Map, numrhs) ); X->PutScalar( 0.0 ); RCP<Epetra_MultiVector> B = rcp( new Epetra_MultiVector(Map, numrhs) ); B->Random(); Belos::LinearProblem<double,MV,OP> problem( A, X, B ); problem.setRightPrec( innerSolver ); problem.setLabel( "Belos Flexible Gmres Solve" ); 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; } // // Copy the list for the inner solver // Teuchos::ParameterList belosList( innerBelosList ); belosList.set( "Flexible Gmres" , true ); // Use flexible Gmres to solve this problem belosList.set( "Timer Label", "Belos Flexible Gmres Solve" );// Choose a different label for the outer solve belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested if (verbose) { belosList.set( "Verbosity", Belos::Errors + Belos::Warnings + Belos::TimingDetails + Belos::StatusTestDetails ); if (frequency > 0) belosList.set( "Output Frequency", frequency ); } // // ******************************************************************* // **********Create the flexible, block Gmres iteration*************** // ******************************************************************* // RCP< Belos::SolverManager<double,MV,OP> > solver; solver = rcp( new Belos::BlockGmresSolMgr<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 << "Number of restarts allowed: " << maxrestarts << std::endl; std::cout << "Length of block Arnoldi factorization: " << length*blocksize << " ( "<< length << " blocks ) " <<std::endl; std::cout << "Max number of Gmres 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 R(Map, numrhs); OPT::Apply( *A, *X, R ); MVT::MvAddMv( -1.0, R, 1.0, *B, R ); MVT::MvNorm( R, 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); return success ? EXIT_SUCCESS : EXIT_FAILURE; } // end test_bl_fgmres_hb.cpp
int main(int argc, char *argv[]) { using Teuchos::CommandLineProcessor; using Teuchos::ParameterList; using Teuchos::RCP; using Teuchos::rcp; using std::cout; using std::endl; 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; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); const int MyPID = Comm.MyPID(); #else // No EPETRA_MPI Epetra_SerialComm Comm; const int MyPID = 0; #endif // EPETRA_MPI bool verbose = false, debug = false; int frequency = -1; // frequency of status test output. int numrhs = 1; // number of right-hand sides to solve for int maxiters = -1; // maximum number of iterations allowed per linear system MT tol = 1.0e-8; // relative residual tolerance // Define command-line arguments CommandLineProcessor cmdp(false,true); cmdp.setOption ("verbose", "quiet", &verbose, "Print messages and results."); cmdp.setOption ("debug", "nodebug", &debug, "Print debugging information from the solver."); cmdp.setOption ("frequency", &frequency, "Solver's frequency for printing residuals (#iters)."); cmdp.setOption ("tol", &tol, "Relative residual tolerance used by MINRES solver."); cmdp.setOption ("num-rhs", &numrhs, "Number of right-hand sides for which to solve (> 0)."); cmdp.setOption ("max-iters", &maxiters, "Maximum number of iterations per linear system. -1 means " "we choose, based on problem size."); // Parse command-line arguments and fetch values if (cmdp.parse(argc,argv) != CommandLineProcessor::PARSE_SUCCESSFUL) { std::cout << "Failed to parse command-line arguments!" << std::endl; std::cout << "End Result: TEST FAILED" << std::endl; return -1; } // ********************************************************************** // ******************Set up the problem to be solved********************* // construct diagonal matrix const int NumGlobalElements = 1e2; const int m = 4; // number of negative eigenvalues // Create diagonal matrix with n-m positive and m negative eigenvalues. Epetra_Map epetraMap( NumGlobalElements, 0, Comm ); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, epetraMap, 1 ) ); for ( int k=0; k<epetraMap.NumMyElements(); k++ ) { int GIDk = epetraMap.GID(k); double val = 2*(GIDk-m) + 1; TEUCHOS_ASSERT_EQUALITY( 0, A->InsertGlobalValues( GIDk, 1, &val, &GIDk ) ); } TEUCHOS_ASSERT_EQUALITY( 0, A->FillComplete() ); TEUCHOS_ASSERT_EQUALITY( 0, A->OptimizeStorage() ); // // Make some (multi)vectors, for use in testing: an exact solution, // its corresponding right-hand side, and an initial guess. // // Make a random exact solution. Teuchos::RCP<Epetra_MultiVector> X_exact (new Epetra_MultiVector (epetraMap, numrhs)); X_exact->Seed(); MVT::MvRandom (*X_exact); // Compute the right-hand side as B = A*X. Teuchos::RCP<Epetra_MultiVector> B = MVT::Clone (*X_exact, numrhs); OPT::Apply (*A, *X_exact, *B); // Choose an initial guess of all zeros. Teuchos::RCP<Epetra_MultiVector> X = MVT::Clone (*X_exact, numrhs); MVT::MvInit (*X, ST(0.0)); // ********************************************************************** // // Set parameters that the user asked us to pick intelligently. // // Maximum number of iterations: set according to problem size. // maxiters=numGlobalElements-1 may not always converge, so we // set to numGlobalElements+1 for good measure. if (maxiters == -1) maxiters = NumGlobalElements + 1; // In a nonverbose test, the frequency should be set to -1, which // Belos interprets as "no intermediate status output." Override // whatever the user may have specified. if (! verbose) frequency = -1; // Silently fix a bad frequency value. else if (frequency < 0 && frequency != -1) frequency = -1; // Validate command-line arguments TEUCHOS_TEST_FOR_EXCEPTION( tol < 0, std::invalid_argument, "Relative residual tolerance must be nonnegative, but " "you supplied tol = " << tol << "." ); TEUCHOS_TEST_FOR_EXCEPTION( numrhs < 1, std::invalid_argument, "MINRES test requires at least one right-hand side, but " "you set the number of right-hand sides to " << numrhs << "." ); TEUCHOS_TEST_FOR_EXCEPTION( maxiters < 1, std::invalid_argument, "MINRES test requires at least one iteration, but you " "set the maximum number of iterations to " << maxiters << "." ); const bool proc_verbose = verbose && (MyPID==0); /* Only print on the zero processor */ // // ********Other information used by block solver*********** // *****************(can be user specified)****************** // // ParameterList belosList; belosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested 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", (int) verbosity ); // // Construct an unpreconditioned linear problem instance. // Belos::LinearProblem< ST, MV, OP > problem (A, X, B); { const bool set = problem.setProblem(); TEUCHOS_TEST_FOR_EXCEPTION( set == false, std::logic_error, "Belos::LinearProblem failed to set up correctly (setP" "roblem() returned false)! This probably means we imp" "lemented our test incorrectly." ); } // // ******************************************************************* // ****************Start the MINRES iteration************************* // ******************************************************************* // // Create an iterative solver manager. RCP< Belos::SolverManager<ST,MV,OP> > newSolver = rcp( new Belos::MinresSolMgr<ST,MV,OP>(rcp(&problem,false), rcp(&belosList,false))); // // **********Print out information about problem******************* // if (proc_verbose) { cout << endl << endl; cout << "Dimension of matrix: " << NumGlobalElements << endl; cout << "Number of right-hand sides: " << numrhs << endl; cout << "Relative residual tolerance: " << tol << endl; cout << endl; } // // Perform solve // Belos::ReturnType ret = Belos::Unconverged; try { ret = newSolver->solve(); } catch (std::exception& e) { if (MyPID == 0) cout << "MINRES solver threw an exception: " << e.what() << endl; throw e; } // // 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; } // // Default return value // if (proc_verbose) std::cout << std::endl << "End Result: TEST PASSED" << std::endl; #ifdef EPETRA_MPI MPI_Finalize(); #endif if (ret!=Belos::Converged || badRes) return -1; else return 0; }
/// actual computation void PoissonSolver::computeField(VField_Edge_t & EFD, VField_Cell_t & HFD, VField_Edge_t & JFD, const double & dt, const double & tol, const int & maxIterations) { Mesh_t & mesh = EFD.get_mesh(); FieldLayout<DIM> & FL = EFD.getLayout(); const NDIndex<DIM> lDom = FL.getLocalNDIndex(); _bunch.saveR(); const GCS_t & gcs = EFD.getGuardCellSizes(); Timings::startTimer(_setupTimer); Epetra_Map* Map = getGlobalElements(); Teuchos::RCP<Epetra_Vector> LHS; LHS = Teuchos::rcp(new Epetra_Vector(*Map)); Teuchos::RCP<Epetra_Vector> RHS; RHS = Teuchos::rcp(new Epetra_Vector(*Map)); Teuchos::RCP<Epetra_CrsMatrix> A; A = Teuchos::rcp(new Epetra_CrsMatrix(Copy, *Map, 5)); StencilGeometry(RHS, A); // print("PoissonMatrix.dat", RHS, A); Teuchos::ParameterList belosList; belosList.set( "Maximum Iterations", maxIterations ); // Maximum number of iterations allowed belosList.set( "Convergence Tolerance", tol ); belosList.set( "Verbosity", (Belos::Errors + Belos::Warnings + Belos::TimingDetails + Belos::FinalSummary + Belos::StatusTestDetails) ); Teuchos::ParameterList MLList; SetupMLList(MLList); Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> MLPrec = Teuchos::rcp(new ML_Epetra::MultiLevelPreconditioner(*A, MLList,false)); MLPrec->ComputePreconditioner(); Teuchos::RCP<Belos::EpetraPrecOp> prec = Teuchos::rcp(new Belos::EpetraPrecOp(MLPrec)); Belos::LinearProblem<ST, MV, OP> problem; problem.setOperator(A); problem.setLHS(LHS); problem.setRHS(RHS); problem.setLeftPrec(prec); if (!problem.isProblemSet()) { if (!problem.setProblem()) { std::cerr << "\nERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; } } Teuchos::RCP< Belos::SolverManager<ST, MV, OP> > solver; solver = Teuchos::rcp( new Belos::BlockCGSolMgr<ST, MV, OP>(Teuchos::rcp(&problem, false), Teuchos::rcp(&belosList, false))); Timings::stopTimer(_setupTimer); BinaryVtkFile vtkFile; SField_t rho(mesh, FL, gcs); _bunch.drift_particles(dt / 2); _bunch.scatterQ(rho); _bunch.drift_particles(-dt / 2); fillRHS(rho, RHS); LHS->Random(); problem.setProblem(Teuchos::null, RHS); Timings::startTimer(_solveTimer); solver->solve(); Timings::stopTimer(_solveTimer); plotPotential(vtkFile, LHS, EFD, 1); fillFields(LHS, EFD, HFD, 1); _bunch.move_by(Vector_t(-0.5 * _hr[0] / _gamma, 0.0)); _bunch.scatterQ(rho); fillRHS(rho, RHS); shiftLHS(rho, LHS, 1.0); problem.setProblem(Teuchos::null, RHS); belosList.set("Convergence Tolerance", 1e-6); solver->setParameters(Teuchos::rcp(&belosList, false)); Timings::startTimer(_solveTimer); solver->solve(); Timings::stopTimer(_solveTimer); plotPotential(vtkFile, LHS, EFD, 2); fillFields(LHS, EFD, HFD, 2); _bunch.restoreR(); _bunch.scatterQ(rho); vtkFile.addScalarField(rho, "rho"); JFD = 0.0; JFD[lDom[0]][lDom[1]](0) += Physics::c * sqrt(1.0 - 1.0 / (_gamma * _gamma)) * rho[lDom[0]][lDom[1]]; fillRHS(rho, RHS); shiftLHS(rho, LHS, -0.5); problem.setProblem(Teuchos::null, RHS); Timings::startTimer(_solveTimer); solver->solve(); Timings::stopTimer(_solveTimer); plotPotential(vtkFile, LHS, EFD, 0); fillFields(LHS, EFD, HFD, 0); vtkFile.writeFile("Data/potential"); delete Map; }