// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void printMatrix(std::string filename_prefix, const Epetra_CrsMatrix& matrix,
		 int newton_step)
{
  std::stringstream ss;
  ss << filename_prefix << "_" << newton_step << ".dat";
  ofstream file( ss.str().c_str(), ios::out | ios::app );
  matrix.Print(file);
}
Esempio n. 2
0
int main(int narg, char *arg[])
{
  using std::cout;

#ifdef EPETRA_MPI  
  // Initialize MPI  
  MPI_Init(&narg,&arg);
  Epetra_MpiComm comm(MPI_COMM_WORLD);
#else
  Epetra_SerialComm comm;
#endif

  int me = comm.MyPID();
  int np = comm.NumProc();

  ITYPE nGlobalRows = 10;
  if (narg > 1) 
    nGlobalRows = (ITYPE) atol(arg[1]);

  bool verbose = (nGlobalRows < 20);

  // Linear map similar to Trilinos default, 
  // but want to allow adding OFFSET_EPETRA64 to the indices.
  int nMyRows = (int) (nGlobalRows / np + (nGlobalRows % np > me));
  ITYPE myFirstRow = (ITYPE)(me * (nGlobalRows / np) + MIN(nGlobalRows%np, me));
  ITYPE *myGlobalRows = new ITYPE[nMyRows];
  for (int i = 0; i < nMyRows; i++)
    myGlobalRows[i] = (ITYPE)i + myFirstRow + OFFSET_EPETRA64;
  Epetra_Map *rowMap = new Epetra_Map(-1, nMyRows, &myGlobalRows[0], 0, comm);
  if (verbose) rowMap->Print(std::cout);

  // Create an integer vector nnzPerRow that is used to build the Epetra Matrix.
  // nnzPerRow[i] is the number of entries for the ith local equation
  std::vector<int> nnzPerRow(nMyRows+1, 0);

  // Also create lists of the nonzeros to be assigned to processors.
  // To save programming time and complexity, these vectors are allocated 
  // bigger than they may actually be needed.
  std::vector<ITYPE> iv(3*nMyRows+1);
  std::vector<ITYPE> jv(3*nMyRows+1);
  std::vector<double> vv(3*nMyRows+1);

  // Generate the nonzeros for the Laplacian matrix.
  ITYPE nMyNonzeros = 0;
  for (ITYPE i = 0, myrowcnt = 0; i < nGlobalRows; i++) {
    if (rowMap->MyGID(i+OFFSET_EPETRA64)) { 
      // This processor owns this row; add nonzeros.
      if (i > 0) {
        iv[nMyNonzeros] = i + OFFSET_EPETRA64;
        jv[nMyNonzeros] = i-1 + OFFSET_EPETRA64;
        vv[nMyNonzeros] = -1;
        if (verbose)
          std::cout << "(" << iv[nMyNonzeros] << "," << jv[nMyNonzeros] << ")="
               << vv[nMyNonzeros] << " on processor " << me
               << " in " << myrowcnt << std::endl;
        nMyNonzeros++;
        nnzPerRow[myrowcnt]++;
      }

      iv[nMyNonzeros] = i + OFFSET_EPETRA64;
      jv[nMyNonzeros] = i + OFFSET_EPETRA64;
      vv[nMyNonzeros] = ((i == 0 || i == nGlobalRows-1) ? 1. : 2.);
      if (verbose) 
        std::cout << "(" << iv[nMyNonzeros] << "," << jv[nMyNonzeros] << ")="
             << vv[nMyNonzeros] << " on processor " << me
             << " in " << myrowcnt << std::endl;
      nMyNonzeros++;
      nnzPerRow[myrowcnt]++;

      if (i < nGlobalRows - 1) {
        iv[nMyNonzeros] = i + OFFSET_EPETRA64;
        jv[nMyNonzeros] = i+1 + OFFSET_EPETRA64;
        vv[nMyNonzeros] = -1;
        if (verbose) 
          std::cout << "(" << iv[nMyNonzeros] << "," << jv[nMyNonzeros] << ")="
               << vv[nMyNonzeros] << " on processor " << me
               << " in " << myrowcnt << std::endl;
        nMyNonzeros++;
        nnzPerRow[myrowcnt]++;
      }
      myrowcnt++;
    }
  }

  // Create an Epetra_Matrix
  Epetra_CrsMatrix *A = new Epetra_CrsMatrix(Copy, *rowMap, &nnzPerRow[0], false);

  // Insert the nonzeros.
  int info;
  ITYPE sum = 0;
  for (int i=0; i < nMyRows; i++) {
    if (nnzPerRow[i]) {
      if (verbose) {
        std::cout << "InsertGlobalValus row " << iv[sum]
             << " count " << nnzPerRow[i] 
             << " cols " << jv[sum] << " " << jv[sum+1] << " ";
        if (nnzPerRow[i] == 3) std::cout << jv[sum+2];
        std::cout << std::endl;
      }
      info = A->InsertGlobalValues(iv[sum],nnzPerRow[i],&vv[sum],&jv[sum]);
      assert(info==0);
      sum += nnzPerRow[i];
    }
  }

  // Finish up
  info = A->FillComplete();
  assert(info==0);
  if (verbose) A->Print(std::cout);

  // Sanity test:  Product of matrix and vector of ones should have norm == 0
  // and max/min/mean values of 0
  Epetra_Vector sanity(A->RangeMap());
  Epetra_Vector sanityres(A->DomainMap());
  sanity.PutScalar(1.);
  A->Multiply(false, sanity, sanityres);

  double jjone, jjtwo, jjmax;
  sanityres.Norm1(&jjone);
  sanityres.Norm2(&jjtwo);
  sanityres.NormInf(&jjmax);
  if (me == 0)
    std::cout << "SanityTest norms 1/2/inf: " << jjone << " "
                                         << jjtwo << " " << jjmax << std::endl;

  bool test_failed = (jjone != 0) || (jjtwo != 0) || (jjmax != 0);

  sanityres.MinValue(&jjone);
  sanityres.MeanValue(&jjtwo);
  sanityres.MaxValue(&jjmax);
  if (me == 0)
    std::cout << "SanityTest values min/max/avg: " << jjone << " "
                                              << jjmax << " " << jjtwo << std::endl;

  test_failed = test_failed || (jjone != 0) || (jjtwo != 0) || (jjmax != 0);

  if (me == 0) {
    if(test_failed)
      std::cout << "Bug_5794_IndexBase_LL tests FAILED" << std::endl;
  }

  delete A;
  delete rowMap;
  delete [] myGlobalRows;

  FINALIZE;
}
Esempio n. 3
0
//=============================================================================
int Amesos_Mumps::ConvertToTriplet(const bool OnlyValues)
{

  Epetra_RowMatrix* ptr;
  if (Comm().NumProc() == 1)
    ptr = &Matrix();
  else {
    ptr = &RedistrMatrix(true);
  }

  ResetTimer();
  
#ifdef EXTRA_DEBUG_INFO
  Epetra_CrsMatrix* Eptr = dynamic_cast<Epetra_CrsMatrix*>( ptr );
  if ( ptr->NumGlobalNonzeros() < 300 ) SetICNTL(4,3 );  // Enable more debug info for small matrices
  if ( ptr->NumGlobalNonzeros() < 42 && Eptr ) { 
      std::cout << " Matrix = " << std::endl ; 
      Eptr->Print( std::cout ) ; 
  } else {
      assert( Eptr );
  }
#endif

  Row.resize(ptr->NumMyNonzeros());
  Col.resize(ptr->NumMyNonzeros());
  Val.resize(ptr->NumMyNonzeros());

  int MaxNumEntries = ptr->MaxNumEntries();
  std::vector<int> Indices;
  std::vector<double> Values;
  Indices.resize(MaxNumEntries);
  Values.resize(MaxNumEntries);

  int count = 0;

  for (int i = 0; i < ptr->NumMyRows() ; ++i) {

    int GlobalRow = ptr->RowMatrixRowMap().GID(i);

    int NumEntries = 0;
    int ierr;
    ierr = ptr->ExtractMyRowCopy(i, MaxNumEntries,
				   NumEntries, &Values[0],
				   &Indices[0]);
    AMESOS_CHK_ERR(ierr);

    for (int j = 0 ; j < NumEntries ; ++j) {
      if (OnlyValues == false) {
	Row[count] = GlobalRow + 1;
	Col[count] = ptr->RowMatrixColMap().GID(Indices[j]) + 1;
      }
      
      // MS // Added on 15-Mar-05.
      if (AddToDiag_ && Indices[j] == i)
        Values[j] += AddToDiag_;

      Val[count] = Values[j];
      count++;
    }
  }

  MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_);
  
  assert (count <= ptr->NumMyNonzeros());

  return(0);
}
Esempio n. 4
0
  int TestOneMatrix( std::string HBname, std::string MMname, std::string TRIname, Epetra_Comm &Comm, bool verbose ) { 

  if ( Comm.MyPID() != 0 ) verbose = false ; 

  Epetra_Map * readMap = 0;

  Epetra_CrsMatrix * HbA = 0; 
  Epetra_Vector * Hbx = 0; 
  Epetra_Vector * Hbb = 0; 
  Epetra_Vector * Hbxexact = 0;
   
  Epetra_CrsMatrix * TriplesA = 0; 
  Epetra_Vector * Triplesx = 0; 
  Epetra_Vector * Triplesb = 0;
  Epetra_Vector * Triplesxexact = 0;
   
  Epetra_CrsMatrix * MatrixMarketA = 0; 
  Epetra_Vector * MatrixMarketx = 0; 
  Epetra_Vector * MatrixMarketb = 0;
  Epetra_Vector * MatrixMarketxexact = 0;
   
  int TRI_Size = TRIname.size() ; 
  std::string LastFiveBytes = TRIname.substr( EPETRA_MAX(0,TRI_Size-5), TRI_Size );

  if ( LastFiveBytes == ".TimD" ) { 
    // Call routine to read in a file with a Tim Davis header and zero-based indexing
    EPETRA_CHK_ERR( Trilinos_Util_ReadTriples2Epetra64( &TRIname[0], false, Comm, 
						      readMap, TriplesA, Triplesx, 
						      Triplesb, Triplesxexact, false, true, true ) );
    delete readMap;
  } else {
    if ( LastFiveBytes == ".triU" ) { 
    // Call routine to read in unsymmetric Triplet matrix
      EPETRA_CHK_ERR( Trilinos_Util_ReadTriples2Epetra64( &TRIname[0], false, Comm, 
							readMap, TriplesA, Triplesx, 
							Triplesb, Triplesxexact, false, false ) );
      delete readMap;
    } else {
      if ( LastFiveBytes == ".triS" ) { 
	// Call routine to read in symmetric Triplet matrix
	EPETRA_CHK_ERR( Trilinos_Util_ReadTriples2Epetra64( &TRIname[0], true, Comm, 
							  readMap, TriplesA, Triplesx, 
							  Triplesb, Triplesxexact, false, false ) );
        delete readMap;
      } else {
	assert( false ) ; 
      }
    }
  }

  EPETRA_CHK_ERR( Trilinos_Util_ReadMatrixMarket2Epetra64( &MMname[0], Comm, readMap, 
							 MatrixMarketA, MatrixMarketx, 
							 MatrixMarketb, MatrixMarketxexact) );
  delete readMap;

  // Call routine to read in HB problem
  Trilinos_Util_ReadHb2Epetra64( &HBname[0], Comm, readMap, HbA, Hbx, 
			       Hbb, Hbxexact) ;


#if 0
  std::cout << " HbA " ; 
  HbA->Print( std::cout ) ; 
  std::cout << std::endl ; 

  std::cout << " MatrixMarketA " ; 
  MatrixMarketA->Print( std::cout ) ; 
  std::cout << std::endl ; 

  std::cout << " TriplesA " ; 
  TriplesA->Print( std::cout ) ; 
  std::cout << std::endl ; 
#endif


  int TripleErr = 0 ; 
  int MMerr = 0 ; 
  for ( int i = 0 ; i < 10 ; i++ ) 
    {
      double resid_Hb_Triples;
      double resid_Hb_Matrix_Market;
      double norm_A ;
      Hbx->Random();
      //
      //  Set the output vectors to different values:
      //
      Triplesb->PutScalar(1.1);
      Hbb->PutScalar(1.2);
      MatrixMarketb->PutScalar(1.3);

      HbA->Multiply( false, *Hbx, *Hbb );
      norm_A = HbA->NormOne( ) ; 

      TriplesA->Multiply( false, *Hbx, *Triplesb );
      Triplesb->Update( 1.0, *Hbb, -1.0 ) ; 


      MatrixMarketA->Multiply( false, *Hbx, *MatrixMarketb );
      MatrixMarketb->Update( 1.0, *Hbb, -1.0 ) ; 

      Triplesb->Norm1( &resid_Hb_Triples ) ; 
      MatrixMarketb->Norm1( &resid_Hb_Matrix_Market ) ; 

      TripleErr += ( resid_Hb_Triples > 1e-11 * norm_A ) ; 
      MMerr += ( resid_Hb_Matrix_Market > 1e-11 * norm_A ) ; 

      if ( verbose && resid_Hb_Triples > 1e-11 * norm_A ) 
	std::cout << " resid_Hb_Triples = " <<  resid_Hb_Triples 
	     << " norm_A = " << norm_A << std::endl ; 
      if ( verbose && resid_Hb_Matrix_Market > 1e-11 * norm_A ) 
	std::cout << " resid_Hb_Matrix_Market = " <<  resid_Hb_Matrix_Market 
	     << " norm_A = " << norm_A << std::endl ; 

    }

  if ( verbose ) { 
    if ( TripleErr ) std::cout << " Error in reading " << HBname << " or " << TRIname << std::endl ; 
    if ( MMerr ) std::cout << " Error in reading " << HBname << " or " << MMname << std::endl ; 
  }

  delete HbA; 
  delete Hbx; 
  delete Hbb; 
  delete Hbxexact;
   
  delete TriplesA; 
  delete Triplesx; 
  delete Triplesb;
  delete Triplesxexact;
   
  delete MatrixMarketA; 
  delete MatrixMarketx; 
  delete MatrixMarketb;
  delete MatrixMarketxexact;

  delete readMap;

  return TripleErr+MMerr ; 
  }
Esempio n. 5
0
int main(int narg, char *arg[]) 
{
  using std::cout;

#ifdef EPETRA_MPI  
  // Initialize MPI  
  MPI_Init(&narg,&arg);   
  Epetra_MpiComm Comm( MPI_COMM_WORLD );  
#else  
  Epetra_SerialComm Comm;  
#endif
  
  int MyPID = Comm.MyPID();

  bool verbose = true;
  int verbosity = 1;
  
  bool testEpetra64 = true;

  // Matrix properties
  bool isHermitian = true;

  // Multivector properties

  std::string initvec = "random";

  // Eigenvalue properties

  std::string which = "SR";
  std::string method = "LOBPCG";
  std::string precond = "none";
  std::string ortho = "SVQB";
  bool lock = true;
  bool relconvtol = false;
  bool rellocktol = false;
  int nev = 5;

  // Block-Arnoldi properties

  int blockSize = -1;
  int numblocks = -1;
  int maxrestarts = -1;
  int maxiterations = -1;
  int extrablocks = 0;
  int gensize = 25;  // Needs to be long long to test with > INT_MAX rows
  double tol = 1.0e-5;
  
  // Echo the command line
  if (MyPID == 0)  {
    for (int i = 0; i < narg; i++)
      cout << arg[i] << " ";
    cout << endl;
  }

  // Command-line processing

  Teuchos::CommandLineProcessor cmdp(false,true);
  cmdp.setOption("Epetra64", "no-Epetra64", &testEpetra64,
                 "Force code to use Epetra64, even if the problem size does "
                 "not require it. (Epetra64 will be used automatically for "
                 "sufficiently large problems, or not used if Epetra does not have built in support.)");
  cmdp.setOption("gen",&gensize,
                 "Generate a simple Laplacian matrix of size n.");
  cmdp.setOption("verbosity", &verbosity, "0=quiet, 1=low, 2=medium, 3=high.");
  cmdp.setOption("method",&method,
                 "Solver method to use:  LOBPCG, BD, BKS or IRTR.");
  cmdp.setOption("nev",&nev,"Number of eigenvalues to find.");
  cmdp.setOption("which",&which,"Targetted eigenvalues (SM,LM,SR,or LR).");
  cmdp.setOption("tol",&tol,"Solver convergence tolerance.");
  cmdp.setOption("blocksize",&blockSize,"Block size to use in solver.");
  cmdp.setOption("numblocks",&numblocks,"Number of blocks to allocate.");
  cmdp.setOption("extrablocks",&extrablocks,
                 "Number of extra NEV blocks to allocate in BKS.");
  cmdp.setOption("maxrestarts",&maxrestarts,
                 "Maximum number of restarts in BKS or BD.");
  cmdp.setOption("maxiterations",&maxiterations,
                 "Maximum number of iterations in LOBPCG.");
  cmdp.setOption("lock","no-lock",&lock,
                 "Use Locking parameter (deflate for converged eigenvalues)");
  cmdp.setOption("initvec", &initvec,
                 "Initial vectors (random, unit, zero, random2)");
  cmdp.setOption("ortho", &ortho,
                 "Orthogonalization method (DGKS, SVQB, TSQR).");
  cmdp.setOption("relative-convergence-tol","no-relative-convergence-tol",
                 &relconvtol,
                 "Use Relative convergence tolerance "
                 "(normalized by eigenvalue)");
  cmdp.setOption("relative-lock-tol","no-relative-lock-tol",&rellocktol,
                 "Use Relative locking tolerance (normalized by eigenvalue)");
  if (cmdp.parse(narg,arg)!=Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
    FINALIZE;
    return -1;
  }

  // Print the most essential options (not in the MyPL parameters later)
  verbose = (verbosity>0);
  if (verbose && MyPID==0){
    cout << "verbosity = " << verbosity << endl;
    cout << "method = " << method << endl;
    cout << "initvec = " << initvec << endl;
    cout << "nev = " << nev << endl;
  }

  // We need blockSize to be set so we can allocate memory with it.
  // If it wasn't set on the command line, set it to the Anasazi defaults here.
  // Defaults are those given in the documentation.
  if (blockSize < 0) 
    if (method == "BKS") 
      blockSize = 1;
    else // other methods: LOBPCG, BD, IRTR
      blockSize = nev;

  // Make sure Epetra was built with 64-bit global indices enabled.
#ifdef EPETRA_NO_64BIT_GLOBAL_INDICES
  if (testEpetra64)
    testEpetra64 = false;
#endif

  Epetra_CrsMatrix *K = NULL;
  
  // Read matrix from file or generate a matrix
  if ((gensize > 0 && testEpetra64)) {
    // Generate the matrix using long long for global indices
    build_simple_matrix<long long>(Comm, K, (long long)gensize, true, verbose);
  }
  else if (gensize) {
    // Generate the matrix using int for global indices
    build_simple_matrix<int>(Comm, K, gensize, false, verbose);
  }
  else {
    printf("YOU SHOULDN'T BE HERE \n");
    exit(-1);
  }

  if (verbose && (K->NumGlobalRows64() < TINYMATRIX)) {
    if (MyPID == 0) cout << "Input matrix:  " << endl;
    K->Print(cout);
  }
  Teuchos::RCP<Epetra_CrsMatrix> rcpK = Teuchos::rcp( K );

  // Set Anasazi verbosity level
  if (MyPID == 0) cout << "Setting up the problem..." << endl;

  int anasazi_verbosity = Anasazi::Errors + Anasazi::Warnings;
  if (verbosity >= 1)  // low
    anasazi_verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails;
  if (verbosity >= 2)  // medium
    anasazi_verbosity += Anasazi::IterationDetails;
  if (verbosity >= 3)  // high
    anasazi_verbosity += Anasazi::StatusTestDetails
                       + Anasazi::OrthoDetails
                       + Anasazi::Debug;
  
  // Create parameter list to pass into solver
  Teuchos::ParameterList MyPL;
  MyPL.set("Verbosity", anasazi_verbosity);
  MyPL.set("Which", which);
  MyPL.set("Convergence Tolerance", tol);
  MyPL.set("Relative Convergence Tolerance", relconvtol);
  MyPL.set("Orthogonalization", ortho);

  // For the following, use Anasazi's defaults unless explicitly specified.
  if (numblocks > 0) MyPL.set( "Num Blocks", numblocks);
  if (maxrestarts > 0) MyPL.set( "Maximum Restarts", maxrestarts);
  if (maxiterations > 0) MyPL.set( "Maximum Iterations", maxiterations);
  if (blockSize > 0) MyPL.set( "Block Size", blockSize );

  typedef Epetra_MultiVector MV;
  typedef Epetra_Operator OP;
  typedef Anasazi::MultiVecTraits<double, MV> MVT;
  typedef Anasazi::OperatorTraits<double, MV, OP> OPT;
    

  // Create the eigenproblem to be solved.
    
  // Dummy initial vectors - will be set later.
  Teuchos::RCP<Epetra_MultiVector> ivec = 
    Teuchos::rcp(new Epetra_MultiVector(K->Map(), blockSize));

  Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem;
  MyProblem = 
    Teuchos::rcp(new Anasazi::BasicEigenproblem<double, MV, OP>(rcpK, ivec) );

  // Inform the eigenproblem whether K is Hermitian

  MyProblem->setHermitian(isHermitian);

  // Set the number of eigenvalues requested 

  MyProblem->setNEV(nev);

  // Loop to solve the same eigenproblem numtrial times (different initial vectors)
  int numfailed = 0;
  int iter = 0;
  double solvetime = 0;

  // Set random seed to have consistent initial vectors between
  // experiments.  Different seed in each loop iteration.
  ivec->SetSeed(2*(MyPID) +1); // Odd seed

  // Set up initial vectors
  // Using random values as the initial guess.
  if (initvec == "random"){
    MVT::MvRandom(*ivec);
  } 
  else if (initvec == "zero"){
    // All zero initial vector should be essentially the same,
    // but appears slightly worse in practice.
    ivec->PutScalar(0.);
  }
  else if (initvec == "unit"){
    // Orthogonal unit initial vectors.
    ivec->PutScalar(0.);
    for (int i = 0; i < blockSize; i++)
      ivec->ReplaceGlobalValue(i,i,1.);
  }
  else if (initvec == "random2"){
    // Partially random but orthogonal (0,1) initial vectors.
    // ivec(i,*) is zero in all but one column (for each i)
    // Inefficient implementation but this is only done once...
    double rowmax;
    int col;
    ivec->Random();
    for (int i = 0; i < ivec->MyLength(); i++){
      rowmax = -1;
      col = -1;
      for (int j = 0; j < blockSize; j++){
        // Make ivec(i,j) = 1 for largest random value in row i
        if ((*ivec)[j][i] > rowmax){
          rowmax = (*ivec)[j][i];
          col = j;
        }
        ivec->ReplaceMyValue(i,j,0.);
      }
      ivec->ReplaceMyValue(i,col,1.);
    }
  }
  else
    cout << "ERROR: Unknown value for initial vectors." << endl;

  if (verbose && (ivec->GlobalLength64() < TINYMATRIX)) 
    ivec->Print(std::cout);
  
  // Inform the eigenproblem that you are finished passing it information
  
  bool boolret = MyProblem->setProblem();
  if (boolret != true) {
    if (verbose && MyPID == 0) {
      cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." 
           << endl;
    }
    FINALIZE;
    return -1;
  }
 
  Teuchos::RCP<Anasazi::SolverManager<double, MV, OP> > MySolverMgr;
 
  if (method == "BKS") {
    // Initialize the Block Arnoldi solver
    MyPL.set("Extra NEV Blocks", extrablocks);
    MySolverMgr = Teuchos::rcp( new Anasazi::BlockKrylovSchurSolMgr<double, MV, OP>(MyProblem,MyPL) );
  }
  else if (method == "BD") {
    // Initialize the Block Davidson solver
    MyPL.set("Use Locking", lock);
    MyPL.set("Relative Locking Tolerance", rellocktol);
    MySolverMgr = Teuchos::rcp( new Anasazi::BlockDavidsonSolMgr<double, MV, OP>(MyProblem, MyPL) );
  }
  else if (method == "LOBPCG") {
    // Initialize the LOBPCG solver
    MyPL.set("Use Locking", lock);
    MyPL.set("Relative Locking Tolerance", rellocktol);
    MySolverMgr = Teuchos::rcp( new Anasazi::LOBPCGSolMgr<double, MV, OP>(MyProblem, MyPL) );
  }
  else if (method == "IRTR") {
    // Initialize the IRTR solver
    MySolverMgr = Teuchos::rcp( new Anasazi::RTRSolMgr<double, MV, OP>(MyProblem, MyPL) );
  }
  else
    cout << "Unknown solver method!" << endl;

  if (verbose && MyPID==0) MyPL.print(cout);
      
  // Solve the problem to the specified tolerances or length
  if (MyPID == 0) cout << "Beginning the " << method << " solve..." << endl;
    
  Anasazi::ReturnType returnCode = MySolverMgr->solve();
  if (returnCode != Anasazi::Converged && MyPID==0) {
    ++numfailed;
    cout << "Anasazi::SolverManager::solve() returned unconverged." << endl;
  }
  iter = MySolverMgr->getNumIters();
  solvetime = (MySolverMgr->getTimers()[0])->totalElapsedTime();
  
  if (MyPID == 0) {
    cout << "Iterations in this solve: " << iter << endl; 
    cout << "Solve complete; beginning post-processing..."<< endl;
  }
  
  // Get the eigenvalues and eigenvectors from the eigenproblem
  
  Anasazi::Eigensolution<double,MV> sol = MyProblem->getSolution();
  std::vector<Anasazi::Value<double> > evals = sol.Evals;
  Teuchos::RCP<MV> evecs = sol.Evecs;
  std::vector<int> index = sol.index;
  int numev = sol.numVecs;
  
  // Compute residuals.
  
  if (numev > 0) {
    Teuchos::LAPACK<int,double> lapack;
    std::vector<double> normR(numev);
     
    if (MyProblem->isHermitian()) {
      // Get storage
      Epetra_MultiVector Kevecs(K->Map(),numev);
      Teuchos::RCP<Epetra_MultiVector> Mevecs;
      Teuchos::SerialDenseMatrix<int,double> B(numev,numev);
      B.putScalar(0.0); 
      for (int i=0; i<numev; i++) {B(i,i) = evals[i].realpart;}
      
      // Compute A*evecs
      OPT::Apply( *rcpK, *evecs, Kevecs );
      Mevecs = evecs;
      
      // Compute A*evecs - lambda*evecs and its norm
      MVT::MvTimesMatAddMv( -1.0, *Mevecs, B, 1.0, Kevecs );
      MVT::MvNorm( Kevecs, normR );
        
      // Scale the norms by the eigenvalue if relative convergence tol was used
      if (relconvtol) {
        for (int i=0; i<numev; i++) 
          normR[i] /= Teuchos::ScalarTraits<double>::magnitude(evals[i].realpart);
      }
        
    } else {
      printf("The problem isn't non-Hermitian; sorry.\n");
      exit(-1);
    }
  
  
    if (verbose && MyPID==0) {
      cout.setf(std::ios_base::right, std::ios_base::adjustfield);	
      cout<<endl<< "Actual Results"<<endl;
      if (MyProblem->isHermitian()) {
        cout<< std::setw(16) << "Eigenvalue "
            << std::setw(20) << "Direct Residual"
            << (relconvtol?" (normalized by eigenvalue)":" (no normalization)")
            << endl;
        cout<<"--------------------------------------------------------"<<endl;
        for (int i=0; i<numev; i++) {
          cout<< "EV" << i << std::setw(16) << evals[i].realpart 
              << std::setw(20) << normR[i] << endl;
        }  
        cout<<"--------------------------------------------------------"<<endl;
      } 
      else {
        cout<< std::setw(16) << "Real Part"
            << std::setw(16) << "Imag Part"
            << std::setw(20) << "Direct Residual"<< endl;
        cout<<"--------------------------------------------------------"<<endl;
        for (int i=0; i<numev; i++) {
          cout<< std::setw(16) << evals[i].realpart 
              << std::setw(16) << evals[i].imagpart 
              << std::setw(20) << normR[i] << endl;
        }  
        cout<<"--------------------------------------------------------"<<endl;
      }  
    }
  }

  // Summarize iteration counts and solve time
  if (MyPID == 0) {
    cout << endl;
    cout << "DRIVER SUMMARY" << endl;
    cout << "Failed to converge: " << numfailed << endl;
    cout << "Solve time:           " << solvetime << endl; 
  }

  FINALIZE;

  if (numfailed) {
    if (MyPID == 0) {
      cout << "End Result: TEST FAILED" << endl;
    }
    return -1;
  }
  //
  // Default return value
  //
  if (MyPID == 0) {
    cout << "End Result: TEST PASSED" << endl;
  } 
  return 0;
}