test_bl_pgmres_hb.cpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Belos: Block Linear Solvers Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 //
00029 // This driver reads a problem from a Harwell-Boeing (HB) file.
00030 // Multiple right-hand-sides are created randomly.
00031 // The initial guesses are all set to zero. 
00032 //
00033 // As currently set up, this driver tests the case when the number of right-hand
00034 // sides (numrhs = 15) is greater than the blocksize (block = 10) used by 
00035 // the solver. Here, 2 passes through the solver are required to solve 
00036 // for all right-hand sides. This information can be edited (see below - other
00037 // information used by block solver - can be user specified) to solve for
00038 // other sizes of systems. For example, one could set numrhs = 1 and block = 1,
00039 // to solve a single right-hand side system in the traditional way, or, set
00040 // numrhs = 1 and block > 1 to solve a single rhs-system with a block implementation. 
00041 //
00042 // 
00043 #include "BelosConfigDefs.hpp"
00044 #include "BelosLinearProblem.hpp"
00045 #include "BelosOutputManager.hpp"
00046 #include "BelosStatusTestMaxIters.hpp"
00047 #include "BelosStatusTestMaxRestarts.hpp"
00048 #include "BelosStatusTestResNorm.hpp"
00049 #include "BelosStatusTestOutputter.hpp"
00050 #include "BelosStatusTestCombo.hpp"
00051 #include "BelosEpetraAdapter.hpp"
00052 #include "BelosBlockGmres.hpp"
00053 #include "createEpetraProblem.hpp"
00054 #include "Ifpack_IlukGraph.h"
00055 #include "Ifpack_CrsRiluk.h"
00056 #include "Epetra_CrsMatrix.h"
00057 #include "Epetra_Map.h"
00058 #include "Teuchos_CommandLineProcessor.hpp"
00059 #include "Teuchos_ParameterList.hpp"
00060 
00061 int main(int argc, char *argv[]) {
00062   //
00063 #ifdef EPETRA_MPI 
00064   MPI_Init(&argc,&argv);
00065   Belos::MPIFinalize mpiFinalize; // Will call finalize with *any* return
00066 #endif  
00067   //
00068   typedef double                            ST;
00069   typedef Teuchos::ScalarTraits<ST>        SCT;
00070   typedef SCT::magnitudeType                MT;
00071   typedef Belos::MultiVec<ST>               MV;
00072   typedef Belos::Operator<ST>               OP;
00073   typedef Belos::MultiVecTraits<ST,MV>     MVT;
00074   typedef Belos::OperatorTraits<ST,MV,OP>  OPT;
00075 
00076   using Teuchos::ParameterList;
00077   using Teuchos::RefCountPtr;
00078   using Teuchos::rcp;
00079 
00080   bool verbose = false, proc_verbose = false;
00081   int frequency = -1;  // how often residuals are printed by solver
00082   int blocksize = 4;
00083   int numrhs = 15;
00084   int numrestarts = 15; // number of restarts allowed 
00085   int length = 25;
00086   std::string filename("orsirr1.hb");
00087   MT tol = 1.0e-5;  // relative residual tolerance
00088 
00089   Teuchos::CommandLineProcessor cmdp(false,true);
00090   cmdp.setOption("verbose","quiet",&verbose,"Print messages and results.");
00091   cmdp.setOption("frequency",&frequency,"Solvers frequency for printing residuals (#iters).");
00092   cmdp.setOption("filename",&filename,"Filename for Harwell-Boeing test matrix.");
00093   cmdp.setOption("tol",&tol,"Relative residual tolerance used by GMRES solver.");
00094   cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for.");
00095   cmdp.setOption("num-restarts",&numrestarts,"Number of restarts allowed for GMRES solver.");
00096   cmdp.setOption("block-size",&blocksize,"Block size used by GMRES.");
00097   cmdp.setOption("subspace-size",&length,"Dimension of Krylov subspace used by GMRES.");  
00098   if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
00099     return -1;
00100   }
00101   if (!verbose)
00102     frequency = -1;  // reset frequency if test is not verbose
00103   //
00104   // Get the problem
00105   //
00106   int MyPID;
00107   RefCountPtr<Epetra_CrsMatrix> A;
00108   int return_val =Belos::createEpetraProblem(filename,NULL,&A,NULL,NULL,&MyPID);
00109   const Epetra_Map &Map = A->RowMap();
00110   if(return_val != 0) return return_val;
00111   proc_verbose = verbose && (MyPID==0); /* Only print on zero processor */
00112   //
00113   // *****Construct the Preconditioner*****
00114   //
00115   if (proc_verbose) cout << endl << endl;
00116   if (proc_verbose) cout << "Constructing ILU preconditioner" << endl;
00117   int Lfill = 2;
00118   // if (argc > 2) Lfill = atoi(argv[2]);
00119   if (proc_verbose) cout << "Using Lfill = " << Lfill << endl;
00120   int Overlap = 2;
00121   // if (argc > 3) Overlap = atoi(argv[3]);
00122   if (proc_verbose) cout << "Using Level Overlap = " << Overlap << endl;
00123   double Athresh = 0.0;
00124   // if (argc > 4) Athresh = atof(argv[4]);
00125   if (proc_verbose) cout << "Using Absolute Threshold Value of " << Athresh << endl;
00126   double Rthresh = 1.0;
00127   // if (argc >5) Rthresh = atof(argv[5]);
00128   if (proc_verbose) cout << "Using Relative Threshold Value of " << Rthresh << endl;
00129   //
00130   Teuchos::RefCountPtr<Ifpack_IlukGraph> ilukGraph;
00131   Teuchos::RefCountPtr<Ifpack_CrsRiluk> ilukFactors;
00132   //
00133   if (Lfill > -1) {
00134     ilukGraph = Teuchos::rcp(new Ifpack_IlukGraph(A->Graph(), Lfill, Overlap));
00135     assert(ilukGraph->ConstructFilledGraph()==0);
00136     ilukFactors = Teuchos::rcp(new Ifpack_CrsRiluk(*ilukGraph));
00137     int initerr = ilukFactors->InitValues(*A);
00138     if (initerr != 0) cout << "InitValues error = " << initerr;
00139     assert(ilukFactors->Factor() == 0);
00140   }
00141   //
00142   bool transA = false;
00143   double Cond_Est;
00144   ilukFactors->Condest(transA, Cond_Est);
00145   if (proc_verbose) {
00146     cout << "Condition number estimate for this preconditoner = " << Cond_Est << endl;
00147     cout << endl;
00148   }
00149   //
00150   // Solve using Belos
00151   //
00152   // Construct a Belos::Operator instance through the Epetra interface.
00153   //
00154   Belos::EpetraOp Amat( A );
00155   //
00156   // call the ctor for the preconditioning object
00157   //
00158   Belos::EpetraPrecOp Prec( ilukFactors );
00159   //
00160   // ********Other information used by block solver***********
00161   // *****************(can be user specified)******************
00162   //
00163   const int NumGlobalElements = Map.NumGlobalElements();
00164   int maxits = NumGlobalElements/blocksize - 1; // maximum number of iterations to run
00165   //
00166   ParameterList My_PL;
00167   My_PL.set( "Length", length );
00168   //
00169   // *****Construct solution vector and random right-hand-sides *****
00170   //
00171   Belos::EpetraMultiVec soln(Map, numrhs);
00172   Belos::EpetraMultiVec rhs(Map, numrhs);
00173   rhs.MvRandom();
00174   Belos::LinearProblem<double,MV,OP>
00175   My_LP( rcp(&Amat,false), rcp(&soln,false), rcp(&rhs,false) );
00176   //My_LP.SetRightPrec( rcp(&Prec,false) );
00177   My_LP.SetLeftPrec( rcp(&Prec,false) );
00178   My_LP.SetBlockSize( blocksize );
00179   
00180   Belos::OutputManager<double> My_OM( MyPID );
00181   if (verbose)
00182     My_OM.SetVerbosity( Belos::Errors + Belos::Warnings 
00183       + Belos::TimingDetails + Belos::FinalSummary );
00184 
00185   typedef Belos::StatusTestCombo<double,MV,OP>  StatusTestCombo_t;
00186   typedef Belos::StatusTestResNorm<double,MV,OP>  StatusTestResNorm_t;
00187   Belos::StatusTestMaxIters<double,MV,OP> test1( maxits );
00188   Belos::StatusTestMaxRestarts<double,MV,OP> test2( numrestarts );
00189   StatusTestCombo_t BasicTest( StatusTestCombo_t::OR, test1, test2 );
00190   StatusTestResNorm_t test3( tol );
00191   test3.DefineScaleForm( StatusTestResNorm_t::NormOfPrecInitRes, Belos::TwoNorm );
00192   Belos::StatusTestOutputter<ST,MV,OP> test4( frequency, false, "Native Residual: ||A*x-b||/||b||" );
00193   test4.set_resNormStatusTest( rcp(&test3, false) );
00194   test4.set_outputManager( rcp(&My_OM,false) );
00195   BasicTest.AddStatusTest( test4 );      
00196   StatusTestResNorm_t ExpTest( tol );
00197   ExpTest.DefineResForm( StatusTestResNorm_t::Explicit, Belos::TwoNorm ); 
00198   StatusTestCombo_t My_Test( StatusTestCombo_t::SEQ, BasicTest, ExpTest );  
00199   //
00200   // *******************************************************************
00201   // *************Start the block Gmres iteration*************************
00202   // *******************************************************************
00203   //
00204   Belos::BlockGmres<double,MV,OP>
00205     MyBlockGmres( rcp(&My_LP,false), rcp(&My_Test,false), rcp(&My_OM,false), rcp(&My_PL,false));
00206   //
00207   // **********Print out information about problem*******************
00208   //
00209   if (proc_verbose) {
00210     cout << endl << endl;
00211     cout << "Dimension of matrix: " << NumGlobalElements << endl;
00212     cout << "Number of right-hand sides: " << numrhs << endl;
00213     cout << "Block size used by solver: " << blocksize << endl;
00214     cout << "Number of restarts allowed: " << numrestarts << endl;
00215     cout << "Length of block Arnoldi factorization: " << length*blocksize << " ( "<< length << " blocks ) " <<endl;
00216     cout << "Max number of Gmres iterations: " << maxits << endl; 
00217     cout << "Relative residual tolerance: " << tol << endl;
00218     cout << endl;
00219   }
00220   //
00221   //
00222   if (proc_verbose) {
00223     cout << endl << endl;
00224     cout << "Running Block Gmres -- please wait" << endl;
00225     cout << (numrhs+blocksize-1)/blocksize 
00226    << " pass(es) through the solver required to solve for " << endl; 
00227     cout << numrhs << " right-hand side(s) -- using a block size of " << blocksize
00228    << endl << endl;
00229   }
00230 
00231   //
00232   // Perform solve
00233   //
00234   MyBlockGmres.Solve();
00235 
00236   //
00237   // Compute actual residuals.
00238   //
00239   std::vector<double> actual_resids( numrhs );
00240   std::vector<double> rhs_norm( numrhs );
00241   Belos::EpetraMultiVec resid(Map, numrhs);
00242   OPT::Apply( Amat, soln, resid );
00243   MVT::MvAddMv( -1.0, resid, 1.0, rhs, resid ); 
00244   MVT::MvNorm( resid, &actual_resids );
00245   MVT::MvNorm( rhs, &rhs_norm );
00246   if (proc_verbose) {
00247     cout<< "---------- Actual Residuals (normalized) ----------"<<endl<<endl;
00248     for ( int i=0; i<numrhs; i++) {
00249       cout<<"Problem "<<i<<" : \t"<< actual_resids[i]/rhs_norm[i] <<endl;
00250     }
00251   }
00252 
00253   if (My_Test.GetStatus()!=Belos::Converged) {
00254   if (proc_verbose)
00255           cout << "End Result: TEST FAILED" << endl;  
00256   return -1;
00257   }
00258   //
00259   // Default return value
00260   //
00261   if (proc_verbose)
00262     cout << "End Result: TEST PASSED" << endl;
00263   return 0;
00264   //
00265 } // end test_bl_pgmres_hb.cpp

Generated on Thu Sep 18 12:30:21 2008 for Belos Package Browser (Single Doxygen Collection) by doxygen 1.3.9.1