test_bl_fgmres_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 sove 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 "BelosStatusTestCombo.hpp"
00050 #include "BelosEpetraAdapter.hpp"
00051 #include "BelosBlockGmres.hpp"
00052 #include "createEpetraProblem.hpp"
00053 #include "Ifpack_IlukGraph.h"
00054 #include "Ifpack_CrsRiluk.h"
00055 #include "Epetra_CrsMatrix.h"
00056 #include "Epetra_Map.h"
00057 #include "Teuchos_CommandLineProcessor.hpp"
00058 #include "Teuchos_ParameterList.hpp"
00059 
00060 int main(int argc, char *argv[]) {
00061   //
00062 #ifdef EPETRA_MPI 
00063   MPI_Init(&argc,&argv);
00064   Belos::MPIFinalize mpiFinalize; // Will call finalize with *any* return
00065 #endif  
00066   //
00067   typedef double                            ST;
00068   typedef Teuchos::ScalarTraits<ST>        SCT;
00069   typedef SCT::magnitudeType                MT;
00070   typedef Belos::MultiVec<ST>               MV;
00071   typedef Belos::Operator<ST>               OP;
00072   typedef Belos::MultiVecTraits<ST,MV>     MVT;
00073   typedef Belos::OperatorTraits<ST,MV,OP>  OPT;
00074 
00075   using Teuchos::ParameterList;
00076   using Teuchos::RefCountPtr;
00077   using Teuchos::rcp;
00078 
00079   bool verbose = false, proc_verbose = false;
00080   int blocksize = 1;
00081   int numrhs = 1;
00082   int numrestarts = 25; // number of restarts allowed 
00083   std::string filename("orsirr1.hb");
00084   MT tol = 1.0e-5;  // relative residual tolerance
00085 
00086   Teuchos::CommandLineProcessor cmdp(false,true);
00087   cmdp.setOption("verbose","quiet",&verbose,"Print messages and results.");
00088   cmdp.setOption("filename",&filename,"Filename for Harwell-Boeing test matrix.");
00089   cmdp.setOption("tol",&tol,"Relative residual tolerance used by GMRES solver.");
00090   cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for.");
00091   cmdp.setOption("num-restarts",&numrestarts,"Number of restarts allowed for GMRES solver.");
00092   cmdp.setOption("block-size",&blocksize,"Block size used by GMRES.");
00093   if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
00094     return -1;
00095   }
00096   //
00097   // Get the problem
00098   //
00099   int MyPID;
00100   RefCountPtr<Epetra_CrsMatrix> A;
00101   int return_val =Belos::createEpetraProblem(filename,NULL,&A,NULL,NULL,&MyPID);
00102   if(return_val != 0) return return_val;
00103   const Epetra_Map &Map = A->RowMap();
00104   proc_verbose = verbose && (MyPID==0);  /* Only print on the zero processor */
00105   //
00106   // *****Construct the Preconditioner*****
00107   //
00108   if (proc_verbose) cout << endl << endl;
00109   if (proc_verbose) cout << "Constructing ILU preconditioner" << endl;
00110   int Lfill = 0;
00111   // if (argc > 2) Lfill = atoi(argv[2]);
00112   if (proc_verbose) cout << "Using Lfill = " << Lfill << endl;
00113   int Overlap = 0;
00114   // if (argc > 3) Overlap = atoi(argv[3]);
00115   if (proc_verbose) cout << "Using Level Overlap = " << Overlap << endl;
00116   double Athresh = 0.0;
00117   // if (argc > 4) Athresh = atof(argv[4]);
00118   if (proc_verbose) cout << "Using Absolute Threshold Value of " << Athresh << endl;
00119   double Rthresh = 1.0;
00120   // if (argc >5) Rthresh = atof(argv[5]);
00121   if (proc_verbose) cout << "Using Relative Threshold Value of " << Rthresh << endl;
00122   //
00123   Teuchos::RefCountPtr<Ifpack_IlukGraph> ilukGraph;
00124   Teuchos::RefCountPtr<Ifpack_CrsRiluk> ilukFactors;
00125   //
00126   if (Lfill > -1) {
00127     ilukGraph = Teuchos::rcp( new Ifpack_IlukGraph(A->Graph(), Lfill, Overlap) );
00128     assert(ilukGraph->ConstructFilledGraph()==0);
00129     ilukFactors = Teuchos::rcp( new Ifpack_CrsRiluk(*ilukGraph) );
00130     int initerr = ilukFactors->InitValues(*A);
00131     if (initerr != 0) cout << "InitValues error = " << initerr;
00132     assert(ilukFactors->Factor() == 0);
00133   }
00134   //
00135   bool transA = false;
00136   double Cond_Est;
00137   ilukFactors->Condest(transA, Cond_Est);
00138   if (proc_verbose) {
00139     cout << "Condition number estimate for this preconditoner = " << Cond_Est << endl;
00140     cout << endl;
00141   }
00142   //
00143   // Solve using Belos
00144   //
00145   // Construct a Belos::Operator instance through the Epetra interface.
00146   //
00147   Belos::EpetraOp Amat( A );
00148   //
00149   // call the ctor for the preconditioning object
00150   //
00151   Belos::EpetraPrecOp Prec( ilukFactors );
00152   //
00153   // ********Other information used by block solver***********
00154   // *****************(can be user specified)******************
00155   //
00156   const int NumGlobalElements = Map.NumGlobalElements();
00157   int maxits = NumGlobalElements/blocksize - 1; // maximum number of iterations to run
00158   int length = 25;
00159   //
00160   ParameterList My_PL;
00161   My_PL.set( "Length", length );
00162   My_PL.set( "Variant", "Flexible" );
00163   //
00164   // *****Construct solution vector and random right-hand-sides *****
00165   //
00166   Belos::EpetraMultiVec soln(Map, numrhs);
00167   Belos::EpetraMultiVec rhs(Map, numrhs);
00168   rhs.MvRandom();
00169   Belos::LinearProblem<double,MV,OP>
00170     My_LP( rcp(&Amat,false), rcp(&soln,false), rcp(&rhs,false) );
00171   My_LP.SetRightPrec( rcp(&Prec,false) );
00172   //My_LP.SetLeftPrec( rcp(&Prec,false) );
00173   My_LP.SetBlockSize( blocksize );
00174   
00175   typedef Belos::StatusTestCombo<double,MV,OP>  StatusTestCombo_t;
00176   typedef Belos::StatusTestResNorm<double,MV,OP>  StatusTestResNorm_t;
00177   Belos::StatusTestMaxIters<double,MV,OP> test1( maxits );
00178   Belos::StatusTestMaxRestarts<double,MV,OP> test2( numrestarts );
00179   StatusTestCombo_t BasicTest( StatusTestCombo_t::OR, test1, test2 );
00180   StatusTestResNorm_t test3( tol );
00181   test3.DefineScaleForm( StatusTestResNorm_t::NormOfPrecInitRes, Belos::TwoNorm );
00182   BasicTest.AddStatusTest( test3 );
00183   StatusTestResNorm_t ExpTest( tol );
00184   ExpTest.DefineResForm( StatusTestResNorm_t::Explicit, Belos::TwoNorm ); 
00185   StatusTestCombo_t My_Test( StatusTestCombo_t::SEQ, BasicTest, ExpTest );
00186   
00187   Belos::OutputManager<double> My_OM( MyPID );
00188   if (verbose)
00189     My_OM.SetVerbosity( Belos::Errors + Belos::Warnings   
00190       + Belos::TimingDetails + Belos::FinalSummary );
00191   //
00192   // *******************************************************************
00193   // *************Start the block Gmres iteration*************************
00194   // *******************************************************************
00195   //
00196   Belos::BlockGmres<double,MV,OP>
00197     MyBlockGmres( rcp(&My_LP,false), rcp(&My_Test,false), rcp(&My_OM,false), rcp(&My_PL,false));
00198   //
00199   // **********Print out information about problem*******************
00200   //
00201   if (proc_verbose) {
00202     cout << endl << endl;
00203     cout << "Dimension of matrix: " << NumGlobalElements << endl;
00204     cout << "Number of right-hand sides: " << numrhs << endl;
00205     cout << "Block size used by solver: " << blocksize << endl;
00206     cout << "Number of restarts allowed: " << numrestarts << endl;
00207     cout << "Length of block Arnoldi factorization: " << length*blocksize << " ( "<< length << " blocks ) " <<endl;
00208     cout << "Max number of Gmres iterations: " << maxits << endl; 
00209     cout << "Relative residual tolerance: " << tol << endl;
00210     cout << endl;
00211   }
00212   //
00213   //
00214   if (proc_verbose) {
00215     cout << endl << endl;
00216     cout << "Running Block Gmres -- please wait" << endl;
00217     cout << (numrhs+blocksize-1)/blocksize 
00218    << " pass(es) through the solver required to solve for " << endl; 
00219     cout << numrhs << " right-hand side(s) -- using a block size of " << blocksize
00220    << endl << endl;
00221   }
00222 
00223   //
00224   // Perform solve.
00225   //
00226   MyBlockGmres.Solve();
00227 
00228   //
00229   // Compute actual residuals.
00230   //
00231   std::vector<double> actual_resids( numrhs );
00232   std::vector<double> rhs_norm( numrhs );
00233   Belos::EpetraMultiVec resid(Map, numrhs);
00234   OPT::Apply( Amat, soln, resid );
00235   MVT::MvAddMv( -1.0, resid, 1.0, rhs, resid ); 
00236   MVT::MvNorm( resid, &actual_resids );
00237   MVT::MvNorm( rhs, &rhs_norm );
00238   if (proc_verbose) {
00239     cout<< "---------- Actual Residuals (normalized) ----------"<<endl<<endl;
00240     for ( int i=0; i<numrhs; i++) {
00241       cout<<"Problem "<<i<<" : \t"<< actual_resids[i]/rhs_norm[i] <<endl;
00242     }
00243   }
00244 
00245   if (My_Test.GetStatus()!=Belos::Converged) {
00246         if (proc_verbose)
00247                 cout << "End Result: TEST FAILED" << endl;
00248         return -1;
00249   }
00250   //
00251   // Default return value
00252   //
00253   if (proc_verbose)
00254     cout << "End Result: TEST PASSED" << endl;
00255   return 0;
00256   //
00257 } // end test_bl_fgmres_hb.cpp

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