Epetra_TSFOperator::Epetra_TSFOperator(const LinearOperator<double>& A,
				       const LinearSolver<double>& solver)
  : A_(A), solver_(solver), useTranspose_(false), comm_(), domain_(), range_(),
    isNativeEpetra_(false), isCompoundEpetra_(false), label_(A.description())
{
  const EpetraMatrix* em = dynamic_cast<const EpetraMatrix*>(A.ptr().get());
  const EpetraVectorSpace* ed = dynamic_cast<const EpetraVectorSpace*>(A.domain().ptr().get());
  const EpetraVectorSpace* er = dynamic_cast<const EpetraVectorSpace*>(A.range().ptr().get());

  if (em)
    {
      isNativeEpetra_ = true;
      const Epetra_CrsMatrix* crs = em->crsMatrix();
      domain_ = rcp(new Epetra_Map(crs->OperatorDomainMap()));
      range_ = rcp(new Epetra_Map(crs->OperatorRangeMap()));
      useTranspose_ = crs->UseTranspose();
      comm_ = rcp(crs->Comm().Clone());
    }
  else if (er != 0 && ed != 0)
    {
      domain_ = ed->epetraMap();
      range_ = er->epetraMap();
      comm_ = rcp(domain_->Comm().Clone());
      isCompoundEpetra_ = true;
    }
  else
    {
      TEST_FOR_EXCEPT(true);
    }
}
    virtual Preconditioner <Scalar>
    createPreconditioner(const LinearOperator<Scalar>& A) const 
    {
      /* In order for ICC factorization to work, the operator A must
       * implement the ICCFactorizableOp interface. We cast A's pointer
       * to a ICCFactorizableOp ptr. If the cast fails, throw a spoke. */
      
      const ICCFactorizableOp<Scalar>* fop 
        = dynamic_cast<const ICCFactorizableOp<Scalar>*>(A.ptr().get());

      TEUCHOS_TEST_FOR_EXCEPTION(fop==0, std::runtime_error,
                         "ICCPreconditionerFactory attempted to "
                         "create an ICC preconditioner for an operator type "
                         "that does not implement the ICCFactorizableOp "
                         "interface. The op is " << A.description());

      
      /* Now we can delegate the construction of the ICC factors to 
      * the factorizable op. */
      Preconditioner<Scalar> P;
      fop->getICCPreconditioner(fillLevels_,
                                 overlapFill_,
                                 relaxationValue_,
                                 relativeThreshold_,
                                 absoluteThreshold_,
                                 P);
      /* Return the preconditioner */
      return P;
    }