test_bl_gmres_diag.cpp

Go to the documentation of this file.
00001 
00002 
00003 #include <BelosConfigDefs.hpp>
00004 #include <BelosLinearProblem.hpp>
00005 #include <BelosOutputManager.hpp>
00006 #include <BelosStatusTestMaxIters.hpp>
00007 #include <BelosStatusTestMaxRestarts.hpp>
00008 #include <BelosStatusTestResNorm.hpp>
00009 #include <BelosStatusTestCombo.hpp>
00010 #include <BelosEpetraAdapter.hpp>
00011 #include <BelosEpetraOperator.h>
00012 #include <BelosBlockGmres.hpp>
00013 
00014 #include <Epetra_Map.h>
00015 #include <Epetra_Vector.h>
00016 #include <Epetra_CrsMatrix.h>
00017 
00018 #include <Teuchos_Time.hpp>
00019 
00020 #ifdef EPETRA_MPI
00021 #include <Epetra_MpiComm.h>
00022 #include <mpi.h>
00023 #else
00024 #include <Epetra_SerialComm.h>
00025 #endif
00026 
00027 using std::vector;
00028 using namespace Belos;
00029 
00030 //************************************************************************************************
00031 
00032 class Vector_Operator
00033 {
00034   public:
00035 
00036     Vector_Operator(unsigned m, unsigned n) : m(m), n(n) { y.resize(m, 0.0); };
00037 
00038     virtual ~Vector_Operator() {};
00039 
00040     virtual vector<double> & operator () (const vector<double> &x) = 0;
00041 
00042     int size (int dim) const { return (dim == 1) ? m : n; };
00043 
00044   protected:
00045 
00046     unsigned m, n;        // an (m x n) operator 
00047     vector<double> y;
00048 
00049   private:
00050 
00051     // Not allowing copy construction.
00052     Vector_Operator( const Vector_Operator& ) {};
00053     Vector_Operator* operator=( const Vector_Operator& ) { return NULL; };
00054 
00055 };
00056 
00057 //************************************************************************************************
00058 
00059 class Diagonal_Operator : public Vector_Operator
00060 {
00061   public:
00062 
00063     Diagonal_Operator(unsigned n, double v) : Vector_Operator(n, n), v(v) { };
00064 
00065     ~Diagonal_Operator() { };
00066 
00067     vector<double> & operator () (const vector<double> &x)
00068     {
00069         for (unsigned i=0; i < m; ++i) y[i] = v*x[i];  // NOTE: square operator!
00070 
00071         return y;
00072     };
00073 
00074   private:
00075 
00076     double v;
00077 };
00078 
00079 //************************************************************************************************
00080 
00081 class Diagonal_Operator_2 : public Vector_Operator
00082 {
00083   public:
00084 
00085     Diagonal_Operator_2(unsigned n, double v) : Vector_Operator(n, n), v(v) { };
00086 
00087     ~Diagonal_Operator_2() { };
00088 
00089     vector<double> & operator () (const vector<double> &x)
00090     {
00091         for (unsigned i=0; i < m; ++i) y[i] = (i+1)*v*x[i];  // NOTE: square operator!
00092 
00093         return y;
00094     };
00095 
00096   private:
00097 
00098     double v;
00099 };
00100 
00101 //************************************************************************************************
00102 
00103 class Composed_Operator : public Vector_Operator
00104 {
00105   public:
00106 
00107     Composed_Operator(unsigned n, 
00108           const Teuchos::RefCountPtr<Vector_Operator>& pA, 
00109           const Teuchos::RefCountPtr<Vector_Operator>& pB);
00110 
00111     virtual ~Composed_Operator() {};
00112 
00113     virtual vector<double> & operator () (const vector<double> &x);
00114 
00115   private:
00116 
00117     Teuchos::RefCountPtr<Vector_Operator> pA; 
00118     Teuchos::RefCountPtr<Vector_Operator> pB; 
00119 };
00120 
00121 Composed_Operator::Composed_Operator(unsigned n, 
00122                                      const Teuchos::RefCountPtr<Vector_Operator>& pA, 
00123                                      const Teuchos::RefCountPtr<Vector_Operator>& pB) 
00124     : Vector_Operator(n, n), pA(pA), pB(pB) 
00125 {
00126 }
00127 
00128 vector<double> & Composed_Operator::operator () (const vector<double> &x)
00129 {
00130     y = (*pA)((*pB)(x));
00131     return y;
00132 }
00133 
00134 //************************************************************************************************
00135 
00136 class Trilinos_Interface : public Epetra_Operator
00137 {
00138   public:
00139 
00140     Trilinos_Interface(const Teuchos::RefCountPtr<Vector_Operator>   pA,
00141                        const Teuchos::RefCountPtr<const Epetra_Comm> pComm,
00142                        const Teuchos::RefCountPtr<const Epetra_Map>  pMap)
00143         : pA(pA), pComm(pComm), pMap(pMap) 
00144     {
00145     };
00146 
00147     int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
00148 
00149     int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const 
00150     {
00151         return(Apply(X,Y));  // No inverse
00152     };
00153 
00154     virtual ~Trilinos_Interface() {};
00155 
00156     const char * Label() const {return("Trilinos_Interface, an Epetra_Operator implementation");}; 
00157   
00158     bool UseTranspose() const {return(use_transpose);};      // always set to false
00159       
00160     int SetUseTranspose(bool UseTranspose_) { use_transpose = false; return(-1); };
00161 
00162     bool HasNormInf() const {return(false);};                // cannot return inf-norm
00163 
00164     double NormInf() const {return(0.0);};                   
00165 
00166     virtual const Epetra_Comm & Comm() const {return *pComm; }
00167       
00168     virtual const Epetra_Map & OperatorDomainMap() const {return *pMap; };
00169       
00170     virtual const Epetra_Map & OperatorRangeMap() const {return *pMap; };
00171 
00172   private:
00173 
00174     Teuchos::RefCountPtr<Vector_Operator>   pA;
00175     Teuchos::RefCountPtr<const Epetra_Comm> pComm;
00176     Teuchos::RefCountPtr<const Epetra_Map>  pMap;
00177 
00178     bool use_transpose;
00179 };
00180 
00181 int Trilinos_Interface::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00182 {
00183     vector<double> x(X.MyLength());
00184     X.ExtractCopy(&x[0], X.MyLength());
00185     x = (*pA)(x);
00186 
00187     for (int i = 0; i < Y.MyLength(); ++i) 
00188         Y.ReplaceMyValue(i, 0, x[i]);
00189     return(0);
00190 }
00191 
00192 //************************************************************************************************
00193 
00194 class Iterative_Inverse_Operator : public Vector_Operator
00195 {
00196 
00197   typedef Epetra_MultiVector MV;
00198   typedef Epetra_Operator    OP;
00199 
00200   public:
00201 
00202   Iterative_Inverse_Operator(unsigned n, 
00203            const Teuchos::RefCountPtr<Vector_Operator>& pA, 
00204            string opString="Iterative Solver", bool print=false);              
00205   
00206   virtual ~Iterative_Inverse_Operator() {}
00207   
00208   virtual vector<double> & operator () (const vector<double> &b);
00209   
00210 private:
00211   
00212   Teuchos::RefCountPtr<Vector_Operator> pA;       // operator which will be inverted 
00213   // supplies a matrix vector multiply
00214   const bool print;
00215   
00216   Teuchos::Time timer;
00217   Teuchos::RefCountPtr<Epetra_Comm> pComm;
00218   Teuchos::RefCountPtr<Epetra_Map>  pMap;
00219   
00220   Teuchos::RefCountPtr<OP> pPE;   
00221   Teuchos::RefCountPtr<MV> pPX;   
00222   Teuchos::RefCountPtr<MV> pPB;
00223   Teuchos::RefCountPtr<StatusTestMaxIters<double,MV,OP> >    test1;
00224   Teuchos::RefCountPtr<StatusTestMaxRestarts<double,MV,OP> > test2;
00225   Teuchos::RefCountPtr<StatusTestCombo<double,MV,OP> >       test3;
00226   Teuchos::RefCountPtr<StatusTestResNorm<double,MV,OP> >     test4;
00227   Teuchos::RefCountPtr<Teuchos::ParameterList>         pList;
00228   Teuchos::RefCountPtr<StatusTestCombo<double,MV,OP> > pTest;
00229   Teuchos::RefCountPtr<LinearProblem<double,MV,OP> >   pProb;
00230   Teuchos::RefCountPtr<OutputManager<double> >         pOM;
00231   Teuchos::RefCountPtr<BlockGmres<double,MV,OP> >      pBelos;
00232 };
00233 
00234 Iterative_Inverse_Operator::Iterative_Inverse_Operator(unsigned n, 
00235                                                        const Teuchos::RefCountPtr<Vector_Operator>& pA, 
00236                                                        string opString, bool print)
00237   : Vector_Operator(n, n),      // square operator
00238     pA(pA), 
00239     print(print),
00240     timer(opString)
00241 {
00242   
00243   unsigned n_global;
00244   
00245 #ifdef EPETRA_MPI
00246   MPI_Allreduce(&n, &n_global, 1, MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
00247   pComm = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_WORLD) );
00248 #else
00249   pComm = Teuchos::rcp( new Epetra_SerialComm() );
00250   n_global = n;
00251 #endif
00252   pMap =  Teuchos::rcp( new Epetra_Map(n_global, n, 0, *pComm) );
00253   
00254   pPE = Teuchos::rcp( new Trilinos_Interface(pA, pComm, pMap ) );
00255   pPX = Teuchos::rcp( new Epetra_MultiVector(*pMap, 1) );  // block size of 1
00256   pPB = Teuchos::rcp( new Epetra_MultiVector(*pMap, 1) );
00257   
00258   pProb = Teuchos::rcp( new LinearProblem<double,MV,OP>(pPE, pPX, pPB) );
00259   pProb->SetBlockSize(1);
00260   
00261   int restart  = 10; 
00262   int max_iter = 100;
00263   double tol = 1.0e-10;
00264   
00265   test1 = Teuchos::rcp( new StatusTestMaxIters<double,MV,OP>( max_iter ) );
00266   test2 = Teuchos::rcp( new StatusTestMaxRestarts<double,MV,OP>( static_cast<int>(ceil((double)max_iter/restart)) ) );
00267   test3 = Teuchos::rcp( new StatusTestCombo<double,MV,OP>(Belos::StatusTestCombo<double,MV,OP>::OR, *test1, *test2) );
00268   test4 = Teuchos::rcp( new StatusTestResNorm<double,MV,OP>( tol ) );
00269   test4->DefineResForm( Belos::StatusTestResNorm<double,MV,OP>::Explicit, Belos::TwoNorm );
00270   pTest = Teuchos::rcp( new StatusTestCombo<double,MV,OP>(Belos::StatusTestCombo<double,MV,OP>::OR, *test3, *test4) );
00271   
00272   int pid = pComm->MyPID();
00273  
00274   if (print)
00275     pOM = Teuchos::rcp( new OutputManager<double>(pid, 2, 0) );
00276   else
00277     pOM = Teuchos::rcp( new OutputManager<double>(pid) );
00278   
00279   pList = Teuchos::rcp( new Teuchos::ParameterList );
00280   pList->set( "Length", restart );  
00281 
00282   pBelos = Teuchos::rcp( new BlockGmres<double,MV,OP>(pProb, pTest, pOM, pList) );
00283 }
00284 
00285 vector<double> & Iterative_Inverse_Operator::operator () (const vector<double> &b)
00286 {
00287   for (unsigned int i=0; i < b.size(); ++i) {
00288     pPB->ReplaceMyValue(i, 0, b[i]); 
00289   }
00290   pPX->PutScalar( 0.0 );
00291   
00292   // Reset the solver, problem, and status test for next solve (HKT)
00293   pBelos->Reset();
00294   pProb->Reset(pPX,pPB);
00295   pTest->Reset();
00296   
00297   timer.start();
00298   pBelos->Solve();
00299   timer.stop();
00300   
00301   int pid = pComm->MyPID();
00302   
00303   if (pid == 0 && print)
00304     if (pTest->GetStatus() == Belos::Converged)
00305       {
00306   cout << endl << "pid[" << pid << "] Block GMRES converged in " 
00307        << pBelos->GetNumIters() << " iteration(s)" << endl;
00308   cout << "Solution time: " << timer.totalElapsedTime() << endl;
00309   
00310       }
00311     else 
00312       cout << endl << "pid[" << pid << "] Block GMRES did not converge" << endl;
00313   
00314   pPX->ExtractCopy(&y[0], pPX->Stride());       // store the result in Vector_Operator::y
00315   
00316   return y;
00317 }
00318 
00319 //************************************************************************************************
00320 //************************************************************************************************
00321 
00322 int main(int argc, char *argv[])
00323 {
00324 
00325   int pid = -1;
00326 
00327 #ifdef EPETRA_MPI
00328     MPI_Init(&argc, &argv);
00329     MPI_Comm_rank(MPI_COMM_WORLD, &pid);
00330 #else
00331     pid = 0;
00332 #endif
00333 
00334     unsigned int n(10);
00335 
00336     vector<double> x(n, 1.0);
00337 
00338     // Inner computes inv(D2)*y
00339     Teuchos::RefCountPtr<Diagonal_Operator_2> D2 = Teuchos::rcp(new Diagonal_Operator_2(n, 1.0));
00340     Iterative_Inverse_Operator A2(n, D2, "Belos (inv(D2))", true); 
00341     
00342     // should return x=(1, 1/2, 1/3, ..., 1/10)
00343     x = A2(x);
00344 
00345     if (pid==0) {
00346       std::cout << "Vector x should have all entries [1, 1/2, 1/3, ..., 1/10]" << std::endl;
00347       for (unsigned int i = 0; i < n; ++i)
00348         std::cout << "x[" << i << "]=" << x[i] << std::endl;
00349       std::cout << std::endl;
00350     }
00351     
00352     // Inner computes inv(D)*x
00353     Teuchos::RefCountPtr<Diagonal_Operator> D = Teuchos::rcp(new Diagonal_Operator(n, 4.0));
00354     Teuchos::RefCountPtr<Iterative_Inverse_Operator> Inner = 
00355       Teuchos::rcp(new Iterative_Inverse_Operator(n, D, "Belos (inv(D))", false)); 
00356 
00357     // Composed_Operator computed inv(D)*B*x
00358     Teuchos::RefCountPtr<Diagonal_Operator> B = Teuchos::rcp(new Diagonal_Operator(n, 4.0));
00359     Teuchos::RefCountPtr<Composed_Operator> C = Teuchos::rcp(new Composed_Operator(n, Inner, B)); 
00360 
00361     // Outer computes inv(C) = inv(inv(D)*B)*x = inv(B)*D*x = x
00362     Teuchos::RefCountPtr<Iterative_Inverse_Operator> Outer =
00363       Teuchos::rcp(new Iterative_Inverse_Operator(n, C, "Belos (inv(C)=inv(inv(D)*B)", true)); 
00364     
00365     // should return x=1/4
00366     vector<double> y(n, 1.0);
00367     y = (*Inner)(y);
00368 
00369     if (pid==0) {
00370       std::cout << "Vector y should have all entries [1/4, 1/4, 1/4, ..., 1/4]" << std::endl;
00371       for (unsigned int i = 0; i < n; ++i) 
00372         std::cout << "y[" << i << "]=" << y[i] << std::endl;
00373       std::cout << std::endl;
00374     }      
00375 
00376     // should return x=1
00377     vector<double> z(n, 1.0);
00378     z = (*Outer)(z);
00379 
00380     if (pid==0) {
00381       std::cout << "Vector z should have all entries [1, 1, 1, ..., 1]" << std::endl;
00382       for (unsigned int i = 0; i < n; ++i) 
00383         std::cout << "z[" << i << "]=" << z[i] << std::endl;
00384     }
00385 
00386     double norm_z, sum_z = 0.0;
00387     for (unsigned int i = 0; i < n; ++i) 
00388        sum_z += Teuchos::ScalarTraits<double>::magnitude(z[i] - 1.0)*Teuchos::ScalarTraits<double>::magnitude(z[i] - 1.0);
00389     norm_z = Teuchos::ScalarTraits<double>::squareroot( sum_z );     
00390     if (pid==0)
00391       std::cout << "Two-norm of vector (z-1.0) : "<< norm_z << std::endl;
00392 
00393 #ifdef EPETRA_MPI
00394     MPI_Finalize(); 
00395 #endif
00396 
00397   if (norm_z > 1e-10 || Teuchos::ScalarTraits<double>::isnaninf( norm_z ) ) {
00398         if (pid==0)
00399                 cout << "End Result: TEST FAILED" << endl;
00400         return -1;
00401   }
00402 
00403   //
00404   // Default return value
00405   //
00406   if (pid==0)
00407     cout << "End Result: TEST PASSED" << endl;
00408   return 0;
00409 }

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