//============================================================================== 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);; }
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 }