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;

    //
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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;
}
Ejemplo n.º 5
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
Ejemplo n.º 6
0
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;
}