Epetra_Import.cpp

Go to the documentation of this file.
00001 
00002 //@HEADER
00003 // ************************************************************************
00004 // 
00005 //               Epetra: Linear Algebra Services Package 
00006 //                 Copyright (2001) Sandia Corporation
00007 // 
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //  
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA
00025 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00026 // 
00027 // ************************************************************************
00028 //@HEADER
00029 
00030 #include "Epetra_Import.h"
00031 #include "Epetra_BlockMap.h"
00032 #include "Epetra_Distributor.h"
00033 #include "Epetra_Comm.h"
00034 #include "Epetra_Util.h"
00035 
00036 
00037 //==============================================================================
00038 // Epetra_Import constructor for a Epetra_BlockMap object
00039 Epetra_Import::Epetra_Import( const Epetra_BlockMap &  TargetMap, const Epetra_BlockMap & SourceMap)
00040   : Epetra_Object("Epetra::Import"),
00041     TargetMap_(TargetMap),
00042     SourceMap_(SourceMap),
00043     NumSameIDs_(0),
00044     NumPermuteIDs_(0),
00045     PermuteToLIDs_(0),
00046     PermuteFromLIDs_(0),
00047     NumRemoteIDs_(0),
00048     RemoteLIDs_(0),
00049     NumExportIDs_(0),
00050     ExportLIDs_(0),
00051     ExportPIDs_(0),
00052     NumSend_(0),
00053     NumRecv_(0),
00054     Distor_(0)
00055 {
00056 
00057   int i;
00058   
00059   // Build three ID lists:
00060   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00061   //              nonidentical ID.
00062   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00063   // NumRemoteIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be imported.
00064   
00065   int NumSourceIDs = SourceMap.NumMyElements();
00066   int NumTargetIDs = TargetMap.NumMyElements();
00067   
00068   int *TargetGIDs = 0;
00069   if (NumTargetIDs>0) {
00070     TargetGIDs = new int[NumTargetIDs];
00071     TargetMap.MyGlobalElements(TargetGIDs);
00072   }
00073   
00074   int * SourceGIDs = 0;
00075   if (NumSourceIDs>0) {
00076     SourceGIDs = new int[NumSourceIDs];
00077     SourceMap.MyGlobalElements(SourceGIDs);
00078   }
00079   
00080   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00081   
00082   
00083   NumSameIDs_ = 0;
00084   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00085   
00086   
00087   // Find count of Target IDs that are truly remote and those that are local but permuted
00088 
00089   NumPermuteIDs_ = 0;
00090   NumRemoteIDs_ = 0;
00091   for (i=NumSameIDs_; i< NumTargetIDs; i++) 
00092     if (SourceMap.MyGID(TargetGIDs[i])) NumPermuteIDs_++; // Check if Target GID is a local Source GID
00093     else NumRemoteIDs_++; // If not, then it is remote
00094   
00095   
00096   
00097   // Define remote and permutation lists
00098   
00099   int * RemoteGIDs=0;
00100   RemoteLIDs_ = 0;
00101   if (NumRemoteIDs_>0) {
00102     RemoteLIDs_ = new int[NumRemoteIDs_];
00103     RemoteGIDs = new int[NumRemoteIDs_];
00104   }
00105   if (NumPermuteIDs_>0)  {
00106     PermuteToLIDs_ = new int[NumPermuteIDs_];
00107     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00108   }
00109   
00110   NumPermuteIDs_ = 0;
00111   NumRemoteIDs_ = 0;
00112   for (i=NumSameIDs_; i< NumTargetIDs; i++) {
00113     if (SourceMap.MyGID(TargetGIDs[i])) {
00114       PermuteToLIDs_[NumPermuteIDs_] = i;
00115       PermuteFromLIDs_[NumPermuteIDs_++] = SourceMap.LID(TargetGIDs[i]);
00116     }
00117     else {
00118       //NumRecv_ +=TargetMap.ElementSize(i); // Count total number of entries to receive
00119       NumRecv_ +=TargetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00120       RemoteGIDs[NumRemoteIDs_] = TargetGIDs[i];
00121       RemoteLIDs_[NumRemoteIDs_++] = i;
00122     }
00123   }
00124 
00125   if( NumRemoteIDs_>0 && !SourceMap.DistributedGlobal() )
00126     ReportError("Warning in Epetra_Import: Serial Import has remote IDs. (Importing to Subset of Target Map)", 1);
00127   
00128   // Test for distributed cases
00129   
00130   int * RemotePIDs = 0;
00131 
00132   if (SourceMap.DistributedGlobal()) {
00133     
00134     if (NumRemoteIDs_>0)  RemotePIDs = new int[NumRemoteIDs_];
00135     int ierr = SourceMap.RemoteIDList(NumRemoteIDs_, RemoteGIDs, RemotePIDs, 0); // Get remote PIDs
00136     if (ierr) throw ReportError("Error in SourceMap.RemoteIDList call", ierr);
00137 
00138     //Get rid of IDs that don't exist in SourceMap
00139     if(NumRemoteIDs_>0) {
00140       int cnt = 0;
00141       for( i = 0; i < NumRemoteIDs_; ++i )
00142         if( RemotePIDs[i] == -1 ) ++cnt;
00143       if( cnt ) {
00144         if( NumRemoteIDs_-cnt ) {
00145           int * NewRemoteGIDs = new int[NumRemoteIDs_-cnt];
00146           int * NewRemotePIDs = new int[NumRemoteIDs_-cnt];
00147           int * NewRemoteLIDs = new int[NumRemoteIDs_-cnt];
00148           cnt = 0;
00149           for( i = 0; i < NumRemoteIDs_; ++i )
00150             if( RemotePIDs[i] != -1 ) {
00151               NewRemoteGIDs[cnt] = RemoteGIDs[i];
00152               NewRemotePIDs[cnt] = RemotePIDs[i];
00153               NewRemoteLIDs[cnt] = TargetMap.LID(RemoteGIDs[i]);
00154               ++cnt;
00155             }
00156           NumRemoteIDs_ = cnt;
00157           delete [] RemoteGIDs;
00158           delete [] RemotePIDs;
00159           delete [] RemoteLIDs_;
00160           RemoteGIDs = NewRemoteGIDs;
00161           RemotePIDs = NewRemotePIDs;
00162           RemoteLIDs_ = NewRemoteLIDs;
00163           ReportError("Warning in Epetra_Import: Target IDs not found in Source Map (Do you want to import to subset of Target Map?)", 1);
00164         }
00165         else { //valid RemoteIDs empty
00166           NumRemoteIDs_ = 0;
00167           delete [] RemoteGIDs;
00168           RemoteGIDs = 0;
00169           delete [] RemotePIDs;
00170           RemotePIDs = 0;
00171         }
00172       }
00173     }
00174 
00175     //Sort Remote IDs by processor so DoReverses will work
00176     Epetra_Util util;
00177     int * tmpPtr[2];
00178     tmpPtr[0] = RemoteLIDs_, tmpPtr[1] = RemoteGIDs;
00179     util.Sort(true,NumRemoteIDs_,RemotePIDs,0,0,2,tmpPtr);
00180 
00181     Distor_ = SourceMap.Comm().CreateDistributor();
00182     
00183     // Construct list of exports that calling processor needs to send as a result
00184     // of everyone asking for what it needs to receive.
00185     
00186     bool Deterministic = true;
00187     ierr = Distor_->CreateFromRecvs( NumRemoteIDs_, RemoteGIDs, RemotePIDs,
00188                        Deterministic, NumExportIDs_, ExportLIDs_, ExportPIDs_ );
00189     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromRecvs()", ierr);
00190 
00191     // Export IDs come in as GIDs, convert to LIDs
00192     for (i=0; i< NumExportIDs_; i++) {
00193       if (ExportPIDs_[i] < 0) throw ReportError("TargetMap requested a GID that is not in the SourceMap.", -1);
00194       ExportLIDs_[i] = SourceMap.LID(ExportLIDs_[i]);
00195       NumSend_ += SourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00196     }
00197   }
00198 
00199   if( NumRemoteIDs_>0 ) delete [] RemoteGIDs;
00200   if( NumRemoteIDs_>0 ) delete [] RemotePIDs;
00201 
00202   if (NumTargetIDs>0) delete [] TargetGIDs;
00203   if (NumSourceIDs>0) delete [] SourceGIDs;
00204   
00205   return;
00206 }
00207 
00208 //==============================================================================
00209 // Epetra_Import copy constructor 
00210 Epetra_Import::Epetra_Import(const Epetra_Import & Importer)
00211   : Epetra_Object(Importer),
00212     TargetMap_(Importer.TargetMap_),
00213     SourceMap_(Importer.SourceMap_),
00214     NumSameIDs_(Importer.NumSameIDs_),
00215     NumPermuteIDs_(Importer.NumPermuteIDs_),
00216     PermuteToLIDs_(0),
00217     PermuteFromLIDs_(0),
00218     NumRemoteIDs_(Importer.NumRemoteIDs_),
00219     RemoteLIDs_(0),
00220     NumExportIDs_(Importer.NumExportIDs_),
00221     ExportLIDs_(0),
00222     ExportPIDs_(0),
00223     NumSend_(Importer.NumSend_),
00224     NumRecv_(Importer.NumRecv_),
00225     Distor_(0)
00226 {
00227   int i;
00228   if (NumPermuteIDs_>0) {
00229     PermuteToLIDs_ = new int[NumPermuteIDs_];
00230     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00231     for (i=0; i< NumPermuteIDs_; i++) {
00232       PermuteToLIDs_[i] = Importer.PermuteToLIDs_[i];
00233       PermuteFromLIDs_[i] = Importer.PermuteFromLIDs_[i];
00234     }
00235   }
00236 
00237   if (NumRemoteIDs_>0) {
00238     RemoteLIDs_ = new int[NumRemoteIDs_];
00239     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Importer.RemoteLIDs_[i];
00240   }
00241 
00242   if (NumExportIDs_>0) {
00243     ExportLIDs_ = new int[NumExportIDs_];
00244     ExportPIDs_ = new int[NumExportIDs_];
00245     for (i=0; i< NumExportIDs_; i++) {
00246       ExportLIDs_[i] = Importer.ExportLIDs_[i];
00247       ExportPIDs_[i] = Importer.ExportPIDs_[i];
00248     }
00249   }
00250 
00251   if (Importer.Distor_!=0) Distor_ = Importer.Distor_->Clone();
00252 
00253 }
00254 
00255 //==============================================================================
00256 // Epetra_Import destructor 
00257 Epetra_Import::~Epetra_Import()
00258 {
00259   if( Distor_ != 0 ) delete Distor_;
00260   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00261   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00262   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00263 
00264   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by Distor_
00265   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00266 }
00267 //=============================================================================
00268 void Epetra_Import::Print(ostream & os) const
00269 {
00270 
00271   os << endl << endl << "Source Map:" << endl << endl;
00272   SourceMap_.Print(os);
00273   
00274   os << endl << endl << "Target Map:" << endl << endl;
00275   TargetMap_.Print(os);
00276   
00277   os << endl << endl << "Distributor:" << endl << endl;
00278   if (Distor_==0) os << "  Is empty...." << endl;
00279   else Distor_->Print(os);
00280   
00281   os << "Number of Same IDs = " << NumSameIDs_ << endl;
00282 
00283   os << "Number of Permute IDs = " << NumPermuteIDs_ << endl;
00284 
00285   os << "Number of Export IDs = " << NumExportIDs_ << endl;
00286 
00287   os << "Number of Remote IDs = " << NumRemoteIDs_ << endl;
00288   
00289   os << "Epetra_Import Print Needs attention!!!!" << endl;
00290   return;
00291 }
00292 

Generated on Wed May 12 21:41:05 2010 for Epetra Package Browser (Single Doxygen Collection) by  doxygen 1.4.7