#include "Epetra_CrsMatrix.h"
#include "Teuchos_StandardCatchMacros.hpp"
#ifdef HAVE_MPI
#include "Epetra_MpiComm.h"
#include <mpi.h>
#else
#include "Epetra_SerialComm.h"
#endif
#include "Epetra_Map.h"
int main(int argc, char *argv[]) {
#ifdef HAVE_MPI
  
  
  MPI_Init(&argc,&argv);
#endif
  bool success = false;
  try {
    
    
#ifdef HAVE_MPI
#else
#endif
    
    
    
    
    std::string which("SM");
    cmdp.
setOption(
"sort",&which,
"Targetted eigenvalues (SM or LM).");
 
      throw -1;
    }
    
    
    
    
    const int nx = 10;
    
    
    const int NumGlobalElements = nx*nx;
    
    
    
    
    
    std::vector<int> MyGlobalElements(NumMyElements);
    
    
    
    
    std::vector<int> NumNz(NumMyElements);
    
    for (int i=0; i<NumMyElements; i++) {
      if (MyGlobalElements[i] == 0 || MyGlobalElements[i] == NumGlobalElements-1 ||
          MyGlobalElements[i] == nx-1 || MyGlobalElements[i] == nx*(nx-1) ) {
        NumNz[i] = 3;
      }
      else if (MyGlobalElements[i] < nx || MyGlobalElements[i] > nx*(nx-1) ||
          MyGlobalElements[i]%nx == 0 || (MyGlobalElements[i]+1)%nx == 0) {
        NumNz[i] = 4;
      }
      else {
        NumNz[i] = 5;
      }
    }
    
    
    
    
    const double one = 1.0;
    std::vector<double> Values(4);
    std::vector<int> Indices(4);
    double rho = 0.0;
    double h = one /(nx+1);
    double h2 = h*h;
    double c = 5.0e-01*rho/ h;
    Values[0] = -one/h2 - c; Values[1] = -one/h2 + c; Values[2] = -one/h2; Values[3]= -one/h2;
    double diag = 4.0 / h2;
    int NumEntries;
    for (int i=0; i<NumMyElements; i++)
    {
      if (MyGlobalElements[i]==0)
      {
        Indices[0] = 1;
        Indices[1] = nx;
        NumEntries = 2;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]);
 
      }
      else if (MyGlobalElements[i] == nx*(nx-1))
      {
        Indices[0] = nx*(nx-1)+1;
        Indices[1] = nx*(nx-2);
        NumEntries = 2;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]);
 
      }
      else if (MyGlobalElements[i] == nx-1)
      {
        Indices[0] = nx-2;
        NumEntries = 1;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
 
        assert( info==0 );
        Indices[0] = 2*nx-1;
      }
      else if (MyGlobalElements[i] == NumGlobalElements-1)
      {
        Indices[0] = NumGlobalElements-2;
        NumEntries = 1;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
 
        assert( info==0 );
        Indices[0] = nx*(nx-1)-1;
      }
      else if (MyGlobalElements[i] < nx)
      {
        Indices[0] = MyGlobalElements[i]-1;
        Indices[1] = MyGlobalElements[i]+1;
        Indices[2] = MyGlobalElements[i]+nx;
        NumEntries = 3;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
 
      }
      else if (MyGlobalElements[i] > nx*(nx-1))
      {
        Indices[0] = MyGlobalElements[i]-1;
        Indices[1] = MyGlobalElements[i]+1;
        Indices[2] = MyGlobalElements[i]-nx;
        NumEntries = 3;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
 
      }
      else if (MyGlobalElements[i]%nx == 0)
      {
        Indices[0] = MyGlobalElements[i]+1;
        Indices[1] = MyGlobalElements[i]-nx;
        Indices[2] = MyGlobalElements[i]+nx;
        NumEntries = 3;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]);
 
      }
      else if ((MyGlobalElements[i]+1)%nx == 0)
      {
        Indices[0] = MyGlobalElements[i]-nx;
        Indices[1] = MyGlobalElements[i]+nx;
        NumEntries = 2;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]);
 
        assert( info==0 );
        Indices[0] = MyGlobalElements[i]-1;
        NumEntries = 1;
      }
      else
      {
        Indices[0] = MyGlobalElements[i]-1;
        Indices[1] = MyGlobalElements[i]+1;
        Indices[2] = MyGlobalElements[i]-nx;
        Indices[3] = MyGlobalElements[i]+nx;
        NumEntries = 4;
        int info = A->
InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
 
      }
      
    }
    
    assert( info==0 );
    A->SetTracebackMode(1); 
    
    for (int i=0; i<NumMyElements; i++)
    {
      Values[0] = one;
      Indices[0] = i;
      NumEntries = 1;
      assert( info==0 );
    }
    
    assert( info==0 );
    M->SetTracebackMode(1); 
    
    
    
    
    
    
    const int    nev         = 4;
    const int    blockSize   = 5;
    const int    numBlocks   = 8;
    const int    maxRestarts = 100;
    const double tol         = 1.0e-8;
    
    
    
    ivec->Random();
    
    
    
    
    MyProblem->setHermitian(true);
    
    
    MyProblem->setNEV( nev );
    
    
    bool boolret = MyProblem->setProblem();
    if (boolret != true) {
      throw -1;
    }
    
    
    MyPL.
set( 
"Which", which );
 
    MyPL.
set( 
"Block Size", blockSize );
 
    MyPL.
set( 
"Num Blocks", numBlocks );
 
    MyPL.
set( 
"Maximum Restarts", maxRestarts );
 
    MyPL.
set( 
"Convergence Tolerance", tol );
 
    MyPL.
set( 
"Verbosity", verbosity );
 
    
    
    
    
    
    
    std::vector<Anasazi::Value<double> > evals = sol.
Evals;
 
    
    
    std::vector<double> normR(sol.
numVecs);
 
      for (
int i=0; i<sol.
numVecs; i++) {
 
        T(i,i) = evals[i].realpart;
      }
      A->
Apply( *evecs, tempAevec );
 
      MVT::MvTimesMatAddMv( -1.0, *evecs, T, 1.0, tempAevec );
      MVT::MvNorm( tempAevec, normR );
    }
    
    
    std::ostringstream os;
    os.setf(std::ios_base::right, std::ios_base::adjustfield);
    os<<
"Solver manager returned " << (returnCode == 
Anasazi::Converged ? 
"converged." : 
"unconverged.") << std::endl;
 
    os<<std::endl;
    os<<"------------------------------------------------------"<<std::endl;
    os<<std::setw(16)<<"Eigenvalue"
      <<std::setw(18)<<"Direct Residual"
      <<std::endl;
    os<<"------------------------------------------------------"<<std::endl;
    for (
int i=0; i<sol.
numVecs; i++) {
 
      os<<std::setw(16)<<evals[i].realpart
        <<std::setw(18)<<normR[i]/evals[i].realpart
        <<std::endl;
    }
    os<<"------------------------------------------------------"<<std::endl;
    success = true;
  }
#ifdef HAVE_MPI
  MPI_Finalize();
#endif
  return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
}