// ============================================================================ 
bool ML_Epetra::MatrixFreePreconditioner::
CheckSPD(const Epetra_Operator& A, const bool UseApply,
         const int NumChecks, 
         const int NumVectors) const
{
  bool res = true;
  std::vector<double> norm(NumVectors);

  if (!IsComputed())
    return(false);

  if (MyPID() == 0)
    std::cout << "Checking SPD property of the operator... " << std::endl;

  Epetra_MultiVector X(A.OperatorDomainMap(), NumVectors);
  Epetra_MultiVector AX(A.OperatorRangeMap(), NumVectors);

  try
  {
    for (int i = 0; i < NumChecks; ++i)
    {
      int ierr;

      if (X.Random()) res = false;
      if (UseApply)
        ierr = A.Apply(X, AX);
      else
        ierr = A.ApplyInverse(X, AX);

      if (ierr < 0)
        throw(-1);

      AX.Dot(X, &norm[0]);

      for (int v = 0; v < NumVectors; ++v)
      {
        std::cout << norm[v] << std::endl;
        if (norm[v] <= 0.0)
          throw(-2);
      }
    }
  }
  catch(...)
  {
    res = false;
  }

  if (MyPID() == 0)
  {
    if (res)
      std::cout << "Passed: all x * A * x are positive." << std::endl;
    else
      std::cout << "Failed: some  x * A * x are negative or zero!" << std::endl;
  }

  return(res);
}
Teuchos::RCP<Epetra_CrsMatrix> Epetra_Operator_to_Epetra_Matrix::constructInverseMatrix(const Epetra_Operator &op, const Epetra_Map &map)
{
  int numEntriesPerRow = 0;
  Teuchos::RCP<Epetra_FECrsMatrix> matrix = Teuchos::rcp(new Epetra_FECrsMatrix(::Copy, map, numEntriesPerRow));

  int numRows = map.NumGlobalElements();

  Epetra_Vector X(map);
  Epetra_Vector Y(map);

  double tol = 1e-15; // values below this will be considered 0

  for (int rowIndex=0; rowIndex<numRows; rowIndex++)
  {
    int lid = map.LID(rowIndex);
    if (lid != -1)
    {
      X[lid] = 1.0;
    }
    op.ApplyInverse(X, Y);
    if (lid != -1)
    {
      X[lid] = 0.0;
    }

    std::vector<double> values;
    std::vector<int> indices;
    for (int i=0; i<map.NumMyElements(); i++)
    {
      if (abs(Y[i]) > tol)
      {
        values.push_back(Y[i]);
        indices.push_back(map.GID(i));
      }
    }

    matrix->InsertGlobalValues(rowIndex, values.size(), &values[0], &indices[0]);
  }

  matrix->GlobalAssemble();
  return matrix;
}