//==============================================================================
int Ifpack2_Amesos::
ApplyInverse(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
{

  if (IsComputed() == false)
    IFPACK2_CHK_ERR(-1);

  if (X.NumVectors() != Y.NumVectors())
    IFPACK2_CHK_ERR(-1); // wrong input
  
  Time_->ResetStartTime();

  // AztecOO gives X and Y pointing to the same memory location,
  // need to create an auxiliary vector, Xcopy
  Teuchos::RCP<const Tpetra_MultiVector> Xcopy;
  if (X.Pointers()[0] == Y.Pointers()[0])
    Xcopy = Teuchos::rcp( new Tpetra_MultiVector(X) );
  else
    Xcopy = Teuchos::rcp( &X, false );
    
  Problem_->SetLHS(&Y);
  Problem_->SetRHS((Tpetra_MultiVector*)Xcopy.get());
  IFPACK2_CHK_ERR(Solver_->Solve());

  ++NumApplyInverse_;
  ApplyInverseTime_ += Time_->ElapsedTime();

  return(0);
}
//==============================================================================
int Ifpack2_LocalFilter::
ExtractMyRowCopy(int MyRow, int Length, int & NumEntries,
                 double *Values, int * Indices) const
{
    if ((MyRow < 0) || (MyRow >= NumRows_)) {
        IFPACK2_CHK_ERR(-1); // range not valid
    }

    if (Length < NumEntries_[MyRow])
        return(-1);

    // always extract using the object Values_ and Indices_.
    // This is because I need more space than that given by
    // the user (for the external nodes)
    int Nnz;
    int ierr = Matrix_->ExtractMyRowCopy(MyRow,MaxNumEntriesA_,Nnz,
                                         &Values_[0],&Indices_[0]);

    IFPACK2_CHK_ERR(ierr);

    // populate the user's vectors, add diagonal if not found
    NumEntries = 0;

    for (int j = 0 ; j < Nnz ; ++j) {
        // only local indices
        if (Indices_[j] < NumRows_ ) {
            Indices[NumEntries] = Indices_[j];
            Values[NumEntries] = Values_[j];
            ++NumEntries;
        }
    }

    return(0);

}
int Ifpack2_SparseContainer<T>::Initialize()
{

    if (IsInitialized_ == true)
        Destroy();

    IsInitialized_ = false;

    Map_ = Teuchos::rcp( new Tpetra_Map(NumRows_,0,*SerialComm_) );

    LHS_ = Teuchos::rcp( new Tpetra_MultiVector(*Map_,NumVectors_) );
    RHS_ = Teuchos::rcp( new Tpetra_MultiVector(*Map_,NumVectors_) );
    GID_.Reshape(NumRows_,1);

    Matrix_ = Teuchos::rcp( new Tpetra_CrsMatrix(Copy,*Map_,0) );

    // create the inverse
    Inverse_ = Teuchos::rcp( new T(Matrix_.get()) );

    if (Inverse_ == Teuchos::null)
        IFPACK2_CHK_ERR(-5);

    IFPACK2_CHK_ERR(Inverse_->SetParameters(List_));

    // Call Inverse_->Initialize() in Compute(). This saves
    // some time, because I can extract the diagonal blocks faster,
    // and only once.

    Label_ = "Ifpack2_SparseContainer";

    IsInitialized_ = true;
    return(0);

}
//==============================================================================
int Ifpack2_ReorderFilter::
ExtractDiagonalCopy(Tpetra_Vector & Diagonal) const
{
  Tpetra_Vector DiagonalTilde(Diagonal.Map());
  IFPACK2_CHK_ERR(Matrix()->ExtractDiagonalCopy(DiagonalTilde));
  IFPACK2_CHK_ERR((Reordering_->P(DiagonalTilde,Diagonal)));
  return(0);
}
int Ifpack2_SparseContainer<T>::ApplyInverse()
{
    if (!IsComputed())
        IFPACK2_CHK_ERR(-1);

    IFPACK2_CHK_ERR(Inverse_->ApplyInverse(*RHS_, *LHS_));

    return(0);
}
  /*! 
    \param 
    TransA -(In) If true, multiply by the transpose of matrix, otherwise just use matrix.
    \param 
    X - (In) A Tpetra_MultiVector of dimension NumVectors to multiply with matrix.
    \param 
    Y -(Out) A Tpetra_MultiVector of dimension NumVectorscontaining result.

    \return Integer error code, set to 0 if successful.
    */
  virtual int Multiply(bool TransA, const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
  {
    if (TransA == true) {
      IFPACK2_CHK_ERR(-1);
    }

    IFPACK2_CHK_ERR(Apply(X,Y));
    return(0);
  }
int Ifpack2_SparseContainer<T>::Extract(const Tpetra_RowMatrix& Matrix_in)
{

    for (int j = 0 ; j < NumRows_ ; ++j) {
        // be sure that the user has set all the ID's
        if (ID(j) == -1)
            IFPACK2_CHK_ERR(-1);
        // be sure that all are local indices
        if (ID(j) > Matrix_in.NumMyRows())
            IFPACK2_CHK_ERR(-1);
    }

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

    for (int j = 0 ; j < NumRows_ ; ++j) {

        int LRID = ID(j);

        int NumEntries;

        int ierr =
            Matrix_in.ExtractMyRowCopy(LRID, Length, NumEntries,
                                       &Values[0], &Indices[0]);
        IFPACK2_CHK_ERR(ierr);

        for (int k = 0 ; k < NumEntries ; ++k) {

            int LCID = Indices[k];

            // skip off-processor elements
            if (LCID >= Matrix_in.NumMyRows())
                continue;

            // for local column IDs, look for each ID in the list
            // of columns hosted by this object
            // FIXME: use STL
            int jj = -1;
            for (int kk = 0 ; kk < NumRows_ ; ++kk)
                if (ID(kk) == LCID)
                    jj = kk;

            if (jj != -1)
                SetMatrixElement(j,jj,Values[k]);

        }
    }

    IFPACK2_CHK_ERR(Matrix_->FillComplete());

    return(0);
}
//==============================================================================
int Ifpack2_AMDReordering::InvReorder(const int i) const
{
#ifdef IFPACK2_ABC
  if (!IsComputed())
    IFPACK2_CHK_ERR(-1);
  if ((i < 0) || (i >= NumMyRows_))
    IFPACK2_CHK_ERR(-1);
#endif

  return(InvReorder_[i]);
}
int Ifpack2_SparseContainer<T>::Apply()
{
    if (IsComputed() == false) {
        IFPACK2_CHK_ERR(-3); // not yet computed
    }

    IFPACK2_CHK_ERR(Matrix_->Apply(*RHS_, *LHS_));

    ApplyFlops_ += 2 * Matrix_->NumGlobalNonzeros();
    return(0);
}
//==============================================================================
int Ifpack2_LocalFilter::ExtractDiagonalCopy(Tpetra_Vector & Diagonal) const
{
    if (!Diagonal.Map().SameAs(*Map_))
        IFPACK2_CHK_ERR(-1);
    Diagonal = *Diagonal_;
    return(0);
}
//==============================================================================
int Ifpack2_LocalFilter::Apply(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X,
                               Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
{

    // skip expensive checks, I suppose input data are ok

    Y.PutScalar(0.0);
    int NumVectors = Y.NumVectors();

    double** X_ptr;
    double** Y_ptr;
    X.ExtractView(&X_ptr);
    Y.ExtractView(&Y_ptr);

    for (int i = 0 ; i < NumRows_ ; ++i) {

        int Nnz;
        int ierr = Matrix_->ExtractMyRowCopy(i,MaxNumEntriesA_,Nnz,&Values_[0],
                                             &Indices_[0]);
        IFPACK2_CHK_ERR(ierr);

        for (int j = 0 ; j < Nnz ; ++j) {
            if (Indices_[j] < NumRows_ ) {
                for (int k = 0 ; k < NumVectors ; ++k)
                    Y_ptr[k][i] += Values_[j] * X_ptr[k][Indices_[j]];
            }
        }
    }

    return(0);
}
//==============================================================================
int Ifpack2_Amesos::
Apply(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
{
  // check for maps ???
  IFPACK2_CHK_ERR(Matrix_->Apply(X,Y));
  return(0);
}
  //! Sets all the parameters for the partitioner (none for linear partioning).
  int SetPartitionParameters(Teuchos::ParameterList& List)
  {
    Map_ = List.get("partitioner: map",Map_);
    if (Map_ == 0)
      IFPACK2_CHK_ERR(-1);

    return(0);
  }
//==============================================================================
int Ifpack2_AMDReordering::Compute(const Tpetra_RowMatrix& Matrix)
{
  Ifpack2_Graph_Tpetra_RowMatrix Graph(Teuchos::rcp(&Matrix,false));

  IFPACK2_CHK_ERR(Compute(Graph));

  return(0);
}
  //! Sets the number of vectors for LHS/RHS.
  virtual int SetNumVectors(const int NumVectors_in)
  {
    if (NumVectors_ == NumVectors_in) 
      return(0);

    NumVectors_ = NumVectors_in;
    IFPACK2_CHK_ERR(RHS_.Reshape(NumRows_,NumVectors_));
    IFPACK2_CHK_ERR(LHS_.Reshape(NumRows_,NumVectors_));
    // zero out vector elements
    for (int i = 0 ; i < NumRows_ ; ++i)
      for (int j = 0 ; j < NumVectors_ ; ++j) {
	LHS_(i,j) = 0.0;
	RHS_(i,j) = 0.0;
      }

    return(0);
  }
//==============================================================================
int Ifpack2_Amesos::Compute()
{

  if (!IsInitialized())
    IFPACK2_CHK_ERR(Initialize());

  IsComputed_ = false;
  Time_->ResetStartTime();

  if (Matrix_ == Teuchos::null)
    IFPACK2_CHK_ERR(-1);

  IFPACK2_CHK_ERR(Solver_->NumericFactorization());

  IsComputed_ = true;
  ++NumCompute_;
  ComputeTime_ += Time_->ElapsedTime();
  return(0);
}
//==============================================================================
int Ifpack2_Amesos::SetUseTranspose(bool UseTranspose_in)
{
  // store the value in UseTranspose_. If we have the solver, we pass to it
  // right away, otherwise we wait till when it is created.
  UseTranspose_ = UseTranspose_in;
  if (Solver_ != Teuchos::null)
    IFPACK2_CHK_ERR(Solver_->SetUseTranspose(UseTranspose_in));

  return(0);
}
int Ifpack2_SparseContainer<T>::Compute(const Tpetra_RowMatrix& Matrix_in)
{

    IsComputed_ = false;
    if (!IsInitialized()) {
        IFPACK2_CHK_ERR(Initialize());
    }

    // extract the submatrices
    IFPACK2_CHK_ERR(Extract(Matrix_in));

    // initialize the inverse operator
    IFPACK2_CHK_ERR(Inverse_->Initialize());

    // compute the inverse operator
    IFPACK2_CHK_ERR(Inverse_->Compute());

    Label_ = "Ifpack2_SparseContainer";

    IsComputed_ = true;

    return(0);
}
int Ifpack2_SparseContainer<T>::
SetMatrixElement(const int row, const int col, const double value)
{
    if (!IsInitialized())
        IFPACK2_CHK_ERR(-3); // problem not shaped yet

    if ((row < 0) || (row >= NumRows())) {
        IFPACK2_CHK_ERR(-2); // not in range
    }

    if ((col < 0) || (col >= NumRows())) {
        IFPACK2_CHK_ERR(-2); // not in range
    }

    int ierr = Matrix_->InsertGlobalValues((int)row,1,(double*)&value,(int*)&col);
    if (ierr < 0) {
        ierr = Matrix_->SumIntoGlobalValues((int)row,1,(double*)&value,(int*)&col);
        if (ierr < 0)
            IFPACK2_CHK_ERR(-1);
    }

    return(0);

}
//==============================================================================
int Ifpack2_ReorderFilter::
Multiply(bool TransA, const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
         Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
{
  // need two additional vectors
  Tpetra_MultiVector Xtilde(X.Map(),X.NumVectors());
  Tpetra_MultiVector Ytilde(Y.Map(),Y.NumVectors());
  // bring X back to original ordering
  Reordering_->Pinv(X,Xtilde);
  // apply original matrix
  IFPACK2_CHK_ERR(Matrix()->Multiply(TransA,Xtilde,Ytilde));
  // now reorder result
  Reordering_->P(Ytilde,Y);


  return(0);
}
//==============================================================================
int Ifpack2_ReorderFilter::
ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, 
                 double *Values, int * Indices) const
{
  int MyReorderdRow = Reordering_->InvReorder(MyRow);

  IFPACK2_CHK_ERR(Matrix()->ExtractMyRowCopy(MyReorderdRow,MaxNumEntries_,
                                           NumEntries, Values,Indices));

  // suppose all elements are local. Note that now
  // Indices can have indices in non-increasing order.
  for (int i = 0 ; i < NumEntries ; ++i) {
    Indices[i] = Reordering_->Reorder(Indices[i]);
  }

  return(0);
}
//==============================================================================
int Ifpack2_UserPartitioner::ComputePartitions()
{
  
  if (Map_ == 0)
    IFPACK2_CHK_ERR(-1);

  // simply copy user's vector
  for (int i = 0 ; i < NumMyRows() ; ++i) {
    Partition_[i] = Map_[i];
  }

  // put together all partitions composed by 1 one vertex
  // (if any)
  vector<int> singletons(NumLocalParts());
  for (unsigned int i = 0 ; i < singletons.size() ; ++i) {
    singletons[i] = 0;
  }

#if 0
  // may want to uncomment the following to ensure that no
  // partitions are in fact singletons
  for (int i = 0 ; i < NumMyRows() ; ++i) {
    ++singletons[Partition_[i]];
  }
  
  int count = 0;
  for (unsigned int i = 0 ; i < singletons.size() ; ++i) {
    if (singletons[i] == 1)
      ++count;
  }

  int index = -1;
  for (int i = 0 ; i < NumMyRows() ; ++i) {
    int j = Partition_[i];
    if (singletons[j] == 1) {
      if (index == -1)
        index = j;
      else
        Partition_[i] = index;
    }
  }
#endif

  return(0);
}
  virtual int Solve(bool Upper, bool Trans, bool UnitDiagonal, 
		    const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X,
		    Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
  {
    IFPACK2_CHK_ERR(-1);
  }
  virtual int ApplyInverse(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X,
			   Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
  {
    IFPACK2_CHK_ERR(-1);
  }
//==============================================================================
int Ifpack2_AMDReordering::Compute(const Ifpack2_Graph& Graph)
{
  IsComputed_ = false;
  NumMyRows_ = Graph.NumMyRows();
  int NumNz = Graph.NumMyNonzeros();
  
  if (NumMyRows_ == 0)
    IFPACK2_CHK_ERR(-1); // strange graph this one
  
  // Extract CRS format
  vector<int> ia(NumMyRows_+1,0);
  vector<int> ja(NumNz);
  int cnt;
  for( int i = 0; i < NumMyRows_; ++i )
  {
    int * tmpP = &ja[ia[i]];
    Graph.ExtractMyRowCopy( i, NumNz-ia[i], cnt, tmpP );
    ia[i+1] = ia[i] + cnt;
  }

  // Trim down to local only
  vector<int> iat(NumMyRows_+1);
  vector<int> jat(NumNz);
  int loc = 0;
  for( int i = 0; i < NumMyRows_; ++i )
  {
    iat[i] = loc;
    for( int j = ia[i]; j < ia[i+1]; ++j )
    {
      if( ja[j] < NumMyRows_ )
        jat[loc++] = ja[j];
      else
	break;
    }
  }
  iat[NumMyRows_] = loc;

  // Compute AMD permutation
  Reorder_.resize(NumMyRows_);
  vector<double> info(AMD_INFO);

  amesos_amd_order( NumMyRows_, &iat[0], &jat[0], &Reorder_[0], NULL, &info[0] );

  if( info[AMD_STATUS] == AMD_INVALID )
    cout << "AMD ORDERING: Invalid!!!!\n";

  // Build inverse reorder (will be used by ExtractMyRowCopy() 
  InvReorder_.resize(NumMyRows_);

  for (int i = 0 ; i < NumMyRows_ ; ++i)
    InvReorder_[i] = -1;

  for (int i = 0 ; i < NumMyRows_ ; ++i)
    InvReorder_[Reorder_[i]] = i;

  for (int i = 0 ; i < NumMyRows_ ; ++i) {
    if (InvReorder_[i] == -1)
      IFPACK2_CHK_ERR(-1);
  }

  IsComputed_ = true;
  return(0);
}
 virtual int InvColSums(Tpetra_Vector& x) const
 {
   IFPACK2_CHK_ERR(-1);;
 }
Exemple #27
0
 int SetParameter(const string Name, const double Value)
 {
   IFPACK2_CHK_ERR(-98);
 }
//==============================================================================
int Ifpack2_LocalFilter::ApplyInverse(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X,
                                      Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
{
    IFPACK2_CHK_ERR(-1); // not implemented
}
//==============================================================================
int Ifpack2_Amesos::Initialize()
{

  IsInitialized_ = false;
  IsComputed_ = false;

  if (Matrix_ == Teuchos::null)
    IFPACK2_CHK_ERR(-1);

#if 0
  // better to avoid strange games with maps, this class should be
  // used for Ifpack2_LocalFilter'd matrices only
  if (Comm().NumProc() != 1) {
    cout << "Class Ifpack2_Amesos must be used for serial runs;" << endl;
    cout << "for parallel runs you should declare objects as:" << endl; 
    cout << "Ifpack2_AdditiveSchwarz<Ifpack2_Amesos> APrec(Matrix)" << endl;
    exit(EXIT_FAILURE);
  }
#endif

  // only square matrices
  if (Matrix_->NumGlobalRows() != Matrix_->NumGlobalCols())
    IFPACK2_CHK_ERR(-1);

  // at least one nonzero
  if (Matrix_->NumMyNonzeros() == 0) 
    IFPACK2_CHK_ERR(-1);

  Problem_->SetOperator(const_cast<Tpetra_RowMatrix*>(Matrix_.get()));

  if (Time_ == Teuchos::null)
    Time_ = Teuchos::rcp( new Tpetra_Time(Comm()) );

  Amesos Factory;
  Solver_ = Teuchos::rcp( Factory.Create((char*)Label_.c_str(),*Problem_) );
  
  if (Solver_ == Teuchos::null) 
  {
    // try to create KLU, it is generally enabled
    Solver_ = Teuchos::rcp( Factory.Create("Amesos_Klu",*Problem_) );
  }
  if (Solver_ == Teuchos::null)
  {
    // finally try to create LAPACK, it is generally enabled
    // NOTE: the matrix is dense, so this should only be for
    // small problems...
    if (FirstTime)
    {
      cerr << "TIFPACK WARNING: In class Ifpack2_Amesos:" << endl;
      cerr << "TIFPACK WARNING: Using LAPACK because other Amesos" << endl;
      cerr << "TIFPACK WARNING: solvers are not available. LAPACK" << endl;
      cerr << "TIFPACK WARNING: allocates memory to store the matrix as" << endl;
      cerr << "TIFPACK WARNING: dense, I hope you have enough memory..." << endl;
      cerr << "TIFPACK WARNING: (file " << __FILE__ << ", line " << __LINE__ 
           << ")" << endl;
      FirstTime = false;
    }
    Solver_ = Teuchos::rcp( Factory.Create("Amesos_Lapack",*Problem_) );
  }
  // if empty, give up.
  if (Solver_ == Teuchos::null)
    IFPACK2_CHK_ERR(-1);

  IFPACK2_CHK_ERR(Solver_->SetUseTranspose(UseTranspose_));
  Solver_->SetParameters(List_);
  IFPACK2_CHK_ERR(Solver_->SymbolicFactorization());

  IsInitialized_ = true;
  ++NumInitialize_;
  InitializeTime_ += Time_->ElapsedTime();
  return(0);
}
 //! Sets the number of vectors for LHS/RHS.
 virtual int SetNumVectors(const int NumVectors_in)
 {
     if (NumVectors_ == NumVectors_in)
         return(0);
     IFPACK2_CHK_ERR(-99); // STILL TO DO
 }