//============================================================================== 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::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_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_AMDReordering::Pinv(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Xorig, Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X) const { int NumVectors = X.NumVectors(); for (int j = 0 ; j < NumVectors ; ++j) { for (int i = 0 ; i < NumMyRows_ ; ++i) { int np = Reorder_[i]; X[j][i] = Xorig[j][np]; } } return(0); }
//============================================================================= // This function finds X such that LDU Y = X or U(trans) D L(trans) Y = X for multiple RHS int Ifpack2_ILU::ApplyInverse(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const { #ifdef ENABLE_IFPACK2_ILU_TEUCHOS_TIMERS TEUCHOS_FUNC_TIME_MONITOR("Ifpack2_ILU::ApplyInverse"); #endif if (!IsComputed()) IFPACK2_CHK_ERR(-3); if (X.NumVectors() != Y.NumVectors()) IFPACK2_CHK_ERR(-2); 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 ); IFPACK2_CHK_ERR(Solve(Ifpack2_ILU::UseTranspose(), *Xcopy, Y)); // approx is the number of nonzeros in L and U ApplyInverseFlops_ += X.NumVectors() * 4 * (L_->NumGlobalNonzeros() + U_->NumGlobalNonzeros()); ++NumApplyInverse_; ApplyInverseTime_ += Time_.ElapsedTime(); return(0); }
/* //old Apply (no communication) int Ifpack2_NodeFilter::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_NodeFilter::Apply(const Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, Tpetra_MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const { // // This function forms the product Y = A * X. // int NumEntries; int NumVectors = X.NumVectors(); if (NumVectors!=Y.NumVectors()) { EPETRA_CHK_ERR(-1); // Need same number of vectors in each MV } // Make sure Import and Export Vectors are compatible UpdateImportVector(NumVectors); UpdateExportVector(NumVectors); double ** Xp = (double**) X.Pointers(); double ** Yp = (double**) Y.Pointers(); // If we have a non-trivial importer, we must import elements that are permuted or are on other processors if (Importer()!=0) { EPETRA_CHK_ERR(ImportVector_->Import(X, *Importer(), Insert)); Xp = (double**)ImportVector_->Pointers(); } // If we have a non-trivial exporter, we must export elements that are permuted or belong to other processors if (Exporter()!=0) { Yp = (double**)ExportVector_->Pointers(); } // Do actual computation assert(ovA_!=0); int *MyRows; double *MyValues; int *MyIndices; if(Acrs_){ // A rows - CrsMatrix Case IFPACK2_CHK_ERR(Acrs_->ExtractCrsDataPointers(MyRows,MyIndices,MyValues)); //special case NumVectors==1 if (NumVectors==1) { for(int i=0;i<NumMyRowsA_;i++) { int LocRow=Ar_LIDMap_[i]; double sum = 0.0; for(int j = MyRows[i]; j < MyRows[i+1]; j++) sum += MyValues[j]*Xp[0][Ac_LIDMap_[MyIndices[j]]]; Yp[0][LocRow] = sum; } } else { for(int i=0;i<NumMyRowsA_;i++) { int LocRow=Ar_LIDMap_[i]; for (int k=0; k<NumVectors; k++) { double sum = 0.0; for(int j = MyRows[i]; j < MyRows[i+1]; j++) sum += MyValues[j]*Xp[k][Ac_LIDMap_[MyIndices[j]]]; Yp[k][LocRow] = sum; } } } } else{ // A rows - RowMatrix Case MyValues=&Values_[0]; MyIndices=&Indices_[0]; for(int i=0;i<NumMyRowsA_;i++) { ovA_->A().ExtractMyRowCopy(i,MaxNumEntries_,NumEntries,MyValues,MyIndices); int LocRow=Ar_LIDMap_[i]; for (int k=0; k<NumVectors; k++) { double sum = 0.0; for(int j = 0; j < NumEntries; j++) sum += MyValues[j]*Xp[k][Ac_LIDMap_[MyIndices[j]]]; Yp[k][LocRow] = sum; } } } // B rows, always CrsMatrix IFPACK2_CHK_ERR(ovA_->B().ExtractCrsDataPointers(MyRows,MyIndices,MyValues)); //special case NumVectors==1 if (NumVectors==1) { for(int i=0;i<NumMyRowsB_;i++) { int LocRow=Br_LIDMap_[i]; double sum = 0.0; for(int j = MyRows[i]; j < MyRows[i+1]; j++) sum += MyValues[j]*Xp[0][Bc_LIDMap_[MyIndices[j]]]; Yp[0][LocRow] = sum; } } else { for(int i=0;i<NumMyRowsB_;i++) { int LocRow=Br_LIDMap_[i]; for (int k=0; k<NumVectors; k++) { //FIXME optimization, check for NumVectors=1 double sum = 0.0; for(int j = MyRows[i]; j < MyRows[i+1]; j++) sum += MyValues[j]*Xp[k][Bc_LIDMap_[MyIndices[j]]]; Yp[k][LocRow] = sum; } } } if (Exporter()!=0) { Y.PutScalar(0.0); // Make sure target is zero Y.Export(*ExportVector_, *Exporter(), Add); // Fill Y with Values from export vector } // Handle case of rangemap being a local replicated map if (!OperatorRangeMap().DistributedGlobal() && Comm().NumProc()>1) EPETRA_CHK_ERR(Y.Reduce()); return(0); } //Apply