IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_SubdomainFilter.cpp
00001 //@HEADER
00002 // ************************************************************************
00003 // 
00004 //              Ifpack_SubdomainFilter
00005 //              Author: Radu Popescu <radu.popescu@epfl.ch>
00006 //              Copyright 2011 EPFL - CMCS
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are
00010 // met:
00011 //
00012 // 1. Redistributions of source code must retain the above copyright
00013 // notice, this list of conditions and the following disclaimer.
00014 //
00015 // 2. Redistributions in binary form must reproduce the above copyright
00016 // notice, this list of conditions and the following disclaimer in the
00017 // documentation and/or other materials provided with the distribution.
00018 //
00019 // 3. Neither the name of the copyright holder nor the names of the
00020 // contributors may be used to endorse or promote products derived from
00021 // this software without specific prior written permission.
00022 //
00023 // THIS SOFTWARE IS PROVIDED BY EPFL - CMCS "AS IS" AND ANY EXPRESS OR
00024 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 // ARE DISCLAIMED. IN NO EVENT SHALL EPFL - CMCS OR THE CONTRIBUTORS
00027 // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
00028 // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00029 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00030 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00031 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00032 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00033 // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 //
00035 // ************************************************************************
00036 //@HEADER
00037 
00038 #include "Ifpack_ConfigDefs.h"
00039 
00040 #ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
00041 
00042 #include <vector>
00043 #include <algorithm>
00044 
00045 #include "Epetra_MultiVector.h"
00046 #include "Epetra_Vector.h"
00047 #include "Epetra_IntVector.h"
00048 #include "Epetra_RowMatrix.h"
00049 #include "Epetra_Map.h"
00050 #include "Epetra_BlockMap.h"
00051 #include "Ifpack_OverlappingRowMatrix.h"
00052 #include "Epetra_Import.h"
00053 #include "Epetra_Export.h"
00054 #include "Epetra_CrsMatrix.h"
00055 #include "Epetra_BLAS_wrappers.h"
00056 
00057 #include "Ifpack_SubdomainFilter.h"
00058 
00059 using namespace Teuchos;
00060 
00061 //==============================================================================
00062 Ifpack_SubdomainFilter::Ifpack_SubdomainFilter(const RefCountPtr<const Epetra_RowMatrix>& Matrix,int subdomainId) :
00063   Matrix_(Matrix),
00064   NumMyRows_(0),
00065   NumMyNonzeros_(0),
00066   NumGlobalRows_(0),
00067   NumGlobalCols_(0),
00068   MaxNumEntries_(0),
00069   MaxNumEntriesA_(0)
00070 {
00071   sprintf(Label_,"%s","Ifpack_SubdomainFilter");
00072 
00073   ImportVector_ = 0;
00074   ExportVector_ = 0;
00075 
00076   ovA_ = dynamic_cast<const Ifpack_OverlappingRowMatrix*>(&*Matrix_);
00077 
00078   if (ovA_) {
00079     Acrs_=dynamic_cast<const Epetra_CrsMatrix*>(&ovA_->A());
00080     NumMyRowsA_ = ovA_->A().NumMyRows();
00081     NumMyRowsB_ = ovA_->B().NumMyRows();
00082   } else {
00083     NumMyRowsA_ = Matrix->NumMyRows();
00084     NumMyRowsB_ = 0;
00085   }
00086   
00087 #ifdef HAVE_MPI
00088   const Epetra_MpiComm *pComm = dynamic_cast<const Epetra_MpiComm*>( &(Matrix->Comm()) );
00089   assert(pComm != NULL);
00090   MPI_Comm_split(pComm->Comm(), subdomainId, pComm->MyPID(), &subdomainMPIComm_);
00091   SubComm_ = rcp( new Epetra_MpiComm(subdomainMPIComm_) );
00092 #else
00093   SubComm_ = rcp( new Epetra_SerialComm );
00094 #endif
00095 
00096   NumMyRows_ = Matrix->NumMyRows();
00097   SubComm_->SumAll(&NumMyRows_,&NumGlobalRows_,1);
00098 
00099   // Get the row GID corresponding to the process
00100   const Epetra_Map &globRowMap = Matrix->RowMatrixRowMap();
00101   std::vector<int> myRowsGID(NumMyRows_);
00102   globRowMap.MyGlobalElements(&myRowsGID[0]);
00103 
00104   // Gather the GID of all rows in the subdomain
00105   // Get the maximum number of local rows on each processor in the subdomain
00106   // Allocate a vector large enough (Proc cout * max number local rows
00107   // Gather all the local row indices. If a process has less than max num
00108   // local rows, pad the local vector with -1;
00109   // After the gather, eliminate the -1 elements from the target vector
00110   //
00111   // TODO: this section should be rewritten to avoid the GatherAll call.
00112   //       Right now it's not memory efficient. It could be moved to
00113   //       Epetra_Map since it a map operation
00114 
00115   int MaxLocalRows = 0;
00116   SubComm_->MaxAll(&NumMyRows_, &MaxLocalRows, 1);
00117   
00118   std::vector<int> SubdomainRowGID(SubComm_->NumProc() * MaxLocalRows);
00119   myRowsGID.resize(MaxLocalRows, -1);
00120 
00121   SubComm_->GatherAll(&myRowsGID[0],
00122                       &SubdomainRowGID[0],
00123                       MaxLocalRows);
00124 
00125   std::sort(SubdomainRowGID.begin(), SubdomainRowGID.end());
00126 
00127   int PaddingSize = SubdomainRowGID.size() - NumGlobalRows_;
00128   SubdomainRowGID.erase(SubdomainRowGID.begin(),
00129                          SubdomainRowGID.begin() + PaddingSize);
00130 
00131   // Get the col GID corresponding to the process
00132   const Epetra_Map &globColMap = Matrix->RowMatrixColMap();
00133   NumMyCols_ = globColMap.NumMyElements();
00134   std::vector<int> myGlobalCols(NumMyCols_);
00135   globColMap.MyGlobalElements(&myGlobalCols[0]);
00136 
00137   // Eliminate column GID that are outside the subdomain
00138   std::vector<int> filteredColGID;
00139   for (int i = 0; i < NumMyCols_; ++i) {
00140     if (std::find(SubdomainRowGID.begin(), SubdomainRowGID.end(),
00141       myGlobalCols[i]) != SubdomainRowGID.end()) {
00142       filteredColGID.push_back(myGlobalCols[i]);
00143     }
00144   }
00145   NumMyCols_ = filteredColGID.size();
00146 
00147   // Create the maps with the reindexed GIDs
00148   Map_ = rcp( new Epetra_Map(-1, NumMyRows_, &myRowsGID[0], globRowMap.IndexBase(), *SubComm_) );
00149   colMap_ = rcp( new Epetra_Map(-1, NumMyCols_, &filteredColGID[0], globColMap.IndexBase(), *SubComm_) );
00150   NumGlobalCols_ = NumGlobalRows_;
00151 
00152   NumEntries_.resize(NumMyRows_);
00153   MaxNumEntriesA_ = Matrix->MaxNumEntries();
00154   MaxNumEntries_ = Matrix->MaxNumEntries();
00155 
00156   Diagonal_ = rcp( new Epetra_Vector(*Map_) );
00157   if (Diagonal_ == Teuchos::null) IFPACK_CHK_ERRV(-5);
00158 
00159   Indices_.resize(MaxNumEntries_);
00160   Values_.resize(MaxNumEntries_);
00161 
00162   Ac_LIDMap_ = 0;
00163   Bc_LIDMap_ = 0;
00164   Ar_LIDMap_ = 0;
00165   Br_LIDMap_ = 0;
00166 
00167   if(ovA_){
00168     Ac_LIDMap_ = new int[ovA_->A().NumMyCols() + 1];
00169     for(int i = 0; i < ovA_->A().NumMyCols(); i++) {
00170       Ac_LIDMap_[i] = colMap_->LID(ovA_->A().RowMatrixColMap().GID(i));    
00171     }
00172     Bc_LIDMap_ = new int[ovA_->B().NumMyCols() + 1];
00173     for(int i = 0; i < ovA_->B().NumMyCols(); i++) {
00174       Bc_LIDMap_[i] = colMap_->LID(ovA_->B().RowMatrixColMap().GID(i));
00175     }
00176     Ar_LIDMap_ = new int[ovA_->A().NumMyRows() + 1];
00177     for(int i = 0; i < ovA_->A().NumMyRows(); i++) {
00178       Ar_LIDMap_[i] = Map_->LID(ovA_->A().RowMatrixRowMap().GID(i));    
00179     }
00180     Br_LIDMap_ = new int[ovA_->B().NumMyRows() + 1];
00181     for(int i = 0; i < ovA_->B().NumMyRows(); i++) {
00182       Br_LIDMap_[i] = Map_->LID(ovA_->B().RowMatrixRowMap().GID(i));
00183     }
00184   }
00185 
00186   int ActualMaxNumEntries = 0;
00187 
00188   for (int i = 0 ; i < NumMyRows_; ++i) {
00189     NumEntries_[i] = 0;
00190     int Nnz;
00191     IFPACK_CHK_ERRV(ExtractMyRowCopy(i, MaxNumEntries_, Nnz, &Values_[0], &Indices_[0]));
00192 
00193     for (int j = 0 ; j < Nnz; ++j) {
00194       if (Indices_[j] == i) {
00195         (*Diagonal_)[i] = Values_[j];
00196       }
00197     }
00198 
00199     if (Nnz > ActualMaxNumEntries) {
00200       ActualMaxNumEntries = Nnz;
00201     }
00202 
00203     NumMyNonzeros_ += Nnz;
00204     NumEntries_[i] = Nnz;
00205   }
00206 
00207   SubComm_->SumAll(&NumMyNonzeros_, &NumGlobalNonzeros_, 1);
00208   MaxNumEntries_ = ActualMaxNumEntries;
00209 
00210   int gpid = Matrix->Comm().MyPID();
00211   Exporter_ = null;
00212   Importer_ = null;
00213 
00214   if (!(RowMatrixRowMap().SameAs(OperatorRangeMap()))) {
00215     try{
00216       Exporter_ = rcp(new Epetra_Export(RowMatrixRowMap(), OperatorRangeMap()));
00217     }
00218     catch(...) {
00219       printf("** * gpid %d: Ifpack_SubdomainFilter ctor: problem creating Exporter_ * **\n\n",gpid);
00220     }
00221   }
00222 
00223   if (!(*colMap_).SameAs(*Map_)) {
00224     try{
00225       Importer_ = rcp(new Epetra_Import(*colMap_, *Map_));
00226     }
00227     catch(...) {
00228       printf("** * gpid %d: Ifpack_SubdomainFilter ctor: problem creating Importer_ * **\n\n",gpid);
00229     }
00230   }
00231 
00232 } //Ifpack_SubdomainFilter() ctor
00233 
00234 //==============================================================================
00235 Ifpack_SubdomainFilter::~Ifpack_SubdomainFilter()
00236 {
00237     if(Ac_LIDMap_) delete [] Ac_LIDMap_;
00238     if(Bc_LIDMap_) delete [] Bc_LIDMap_;
00239     if(Ar_LIDMap_) delete [] Ar_LIDMap_;
00240     if(Br_LIDMap_) delete [] Br_LIDMap_;
00241 
00242     if(ImportVector_) delete ImportVector_; 
00243 } //Ifpack_SubdomainFilter destructor
00244 
00245 //==============================================================================
00246 int Ifpack_SubdomainFilter:: ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, 
00247     double *Values, int * Indices) const
00248 {
00249   if ((MyRow < 0) || (MyRow >= NumMyRows_)) {
00250     IFPACK_CHK_ERR(-1);
00251   }
00252 
00253   assert(Length >= NumEntries_[MyRow]);
00254 
00255   int ierr;
00256   if (ovA_) {
00257     int LocRow = ovA_->A().RowMatrixRowMap().LID(Map_->GID(MyRow));      
00258     if (LocRow != -1) { 
00259       ierr = ovA_->A().ExtractMyRowCopy(LocRow, Length, NumEntries, Values, Indices);
00260       for(int j = 0;j < NumEntries; j++) {
00261         Indices[j] = Ac_LIDMap_[Indices[j]];
00262       }
00263     }
00264     else {
00265       LocRow = ovA_->B().RowMatrixRowMap().LID(Map_->GID(MyRow));      
00266       ierr = ovA_->B().ExtractMyRowCopy(LocRow, Length, NumEntries, Values, Indices);
00267       for(int j = 0; j < NumEntries; j++) {
00268         Indices[j] = Bc_LIDMap_[Indices[j]];
00269       }
00270     }
00271   } else {
00272     int Nnz = 0;
00273     ierr = Matrix_->ExtractMyRowCopy(MyRow, MaxNumEntriesA_, Nnz, &Values_[0], &Indices_[0]);
00274     IFPACK_CHK_ERR(ierr);
00275 
00276     NumEntries = 0;
00277     for (int j = 0 ; j < Nnz ; ++j) {
00278       int subdomainLocalIndex = colMap_->LID(Matrix_->RowMatrixColMap().GID(Indices_[j]));
00279       if (subdomainLocalIndex != -1) {
00280         Indices[NumEntries] = subdomainLocalIndex;
00281         Values[NumEntries] = Values_[j];
00282         NumEntries++;
00283       }
00284     }
00285   }
00286 
00287   return(ierr);
00288 }
00289 
00290 //==============================================================================
00291 int Ifpack_SubdomainFilter::ExtractDiagonalCopy(Epetra_Vector & Diagonal) const
00292 {
00293   if (!Diagonal.Map().SameAs(*Map_)) {
00294     IFPACK_CHK_ERR(-1);
00295   }
00296 
00297   Diagonal = *Diagonal_;
00298   return(0);
00299 }
00300 
00301 //==============================================================================
00302 int Ifpack_SubdomainFilter::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00303 {
00304     std::cout << "Ifpack_SubdomainFilter::Apply not implemented.\n";
00305     IFPACK_CHK_ERR(-1); // not implemented
00306 }
00307 
00308 //==============================================================================
00309 void Ifpack_SubdomainFilter::UpdateImportVector(int NumVectors) const
00310 {
00311 }
00312 
00313 //==============================================================================
00314 void Ifpack_SubdomainFilter::UpdateExportVector(int NumVectors) const
00315 {
00316 }
00317 
00318 //==============================================================================
00319 int Ifpack_SubdomainFilter::ApplyInverse(const Epetra_MultiVector& X,
00320          Epetra_MultiVector& Y) const
00321 {
00322   std::cout << "Ifpack_SubdomainFilter::ApplyInverse not implemented.\n";
00323   IFPACK_CHK_ERR(-1); // not implemented
00324 }
00325 
00326 //==============================================================================
00327 const Epetra_BlockMap& Ifpack_SubdomainFilter::Map() const
00328 {
00329   return(*Map_);
00330 }
00331 
00332 #endif //ifdef HAVE_IFPACK_PARALLEL_SUBDOMAIN_SOLVERS
 All Classes Files Functions Variables Enumerations Friends