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           cnt = 0;
00148           for( i = 0; i < NumRemoteIDs_; ++i )
00149             if( RemotePIDs[i] != -1 ) {
00150               NewRemoteGIDs[cnt] = RemoteGIDs[i];
00151               NewRemotePIDs[cnt] = RemotePIDs[i];
00152               ++cnt;
00153             }
00154           NumRemoteIDs_ = cnt;
00155           delete [] RemoteGIDs;
00156           delete [] RemotePIDs;
00157           RemoteGIDs = NewRemoteGIDs;
00158           RemotePIDs = NewRemotePIDs;
00159           ReportError("Warning in Epetra_Import: Target IDs not found in Source Map (Do you want to import to subset of Target Map?)", 1);
00160         }
00161         else { //valid RemoteIDs empty
00162           NumRemoteIDs_ = 0;
00163           delete [] RemoteGIDs;
00164           RemoteGIDs = 0;
00165           delete [] RemotePIDs;
00166           RemotePIDs = 0;
00167         }
00168       }
00169     }
00170 
00171     //Sort Remote IDs by processor so DoReverses will work
00172     Epetra_Util util;
00173     int * tmpPtr[2];
00174     tmpPtr[0] = RemoteLIDs_, tmpPtr[1] = RemoteGIDs;
00175     util.Sort(true,NumRemoteIDs_,RemotePIDs,0,0,2,tmpPtr);
00176 
00177     Distor_ = SourceMap.Comm().CreateDistributor();
00178     
00179     // Construct list of exports that calling processor needs to send as a result
00180     // of everyone asking for what it needs to receive.
00181     
00182     bool Deterministic = true;
00183     ierr = Distor_->CreateFromRecvs( NumRemoteIDs_, RemoteGIDs, RemotePIDs,
00184                        Deterministic, NumExportIDs_, ExportLIDs_, ExportPIDs_ );
00185     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromRecvs()", ierr);
00186 
00187     // Export IDs come in as GIDs, convert to LIDs
00188     for (i=0; i< NumExportIDs_; i++) {
00189       if (ExportPIDs_[i] < 0) throw ReportError("TargetMap requested a GID that is not in the SourceMap.", -1);
00190       ExportLIDs_[i] = SourceMap.LID(ExportLIDs_[i]);
00191     }
00192   }
00193 
00194   if( NumRemoteIDs_>0 ) delete [] RemoteGIDs;
00195   if( NumRemoteIDs_>0 ) delete [] RemotePIDs;
00196 
00197   if (NumTargetIDs>0) delete [] TargetGIDs;
00198   if (NumSourceIDs>0) delete [] SourceGIDs;
00199   
00200   return;
00201 }
00202 
00203 //==============================================================================
00204 // Epetra_Import copy constructor 
00205 Epetra_Import::Epetra_Import(const Epetra_Import & Importer)
00206   : Epetra_Object(Importer),
00207     TargetMap_(Importer.TargetMap_),
00208     SourceMap_(Importer.SourceMap_),
00209     NumSameIDs_(Importer.NumSameIDs_),
00210     NumPermuteIDs_(Importer.NumPermuteIDs_),
00211     PermuteToLIDs_(0),
00212     PermuteFromLIDs_(0),
00213     NumRemoteIDs_(Importer.NumRemoteIDs_),
00214     RemoteLIDs_(0),
00215     NumExportIDs_(Importer.NumExportIDs_),
00216     ExportLIDs_(0),
00217     ExportPIDs_(0),
00218     NumSend_(Importer.NumSend_),
00219     NumRecv_(Importer.NumRecv_),
00220     Distor_(0)
00221 {
00222   int i;
00223   if (NumPermuteIDs_>0) {
00224     PermuteToLIDs_ = new int[NumPermuteIDs_];
00225     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00226     for (i=0; i< NumPermuteIDs_; i++) {
00227       PermuteToLIDs_[i] = Importer.PermuteToLIDs_[i];
00228       PermuteFromLIDs_[i] = Importer.PermuteFromLIDs_[i];
00229     }
00230   }
00231 
00232   if (NumRemoteIDs_>0) {
00233     RemoteLIDs_ = new int[NumRemoteIDs_];
00234     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Importer.RemoteLIDs_[i];
00235   }
00236 
00237   if (NumExportIDs_>0) {
00238     ExportLIDs_ = new int[NumExportIDs_];
00239     ExportPIDs_ = new int[NumExportIDs_];
00240     for (i=0; i< NumExportIDs_; i++) {
00241       ExportLIDs_[i] = Importer.ExportLIDs_[i];
00242       ExportPIDs_[i] = Importer.ExportPIDs_[i];
00243     }
00244   }
00245 
00246   if (Importer.Distor_!=0) Distor_ = Importer.Distor_->Clone();
00247 
00248 }
00249 
00250 //==============================================================================
00251 // Epetra_Import destructor 
00252 Epetra_Import::~Epetra_Import()
00253 {
00254   if( Distor_ != 0 ) delete Distor_;
00255   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00256   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00257   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00258 
00259   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by Distor_
00260   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00261 }
00262 //=============================================================================
00263 void Epetra_Import::Print(ostream & os) const
00264 {
00265 
00266   os << endl << endl << "Source Map:" << endl << endl;
00267   SourceMap_.Print(os);
00268   
00269   os << endl << endl << "Target Map:" << endl << endl;
00270   TargetMap_.Print(os);
00271   
00272   os << endl << endl << "Distributor:" << endl << endl;
00273   if (Distor_==0) os << "  Is empty...." << endl;
00274   else Distor_->Print(os);
00275   
00276   os << "Number of Same IDs = " << NumSameIDs_ << endl;
00277 
00278   os << "Number of Permute IDs = " << NumPermuteIDs_ << endl;
00279 
00280   os << "Number of Export IDs = " << NumExportIDs_ << endl;
00281 
00282   os << "Number of Remote IDs = " << NumRemoteIDs_ << endl;
00283   
00284   os << "Epetra_Import Print Needs attention!!!!" << endl;
00285   return;
00286 }
00287 

Generated on Thu Sep 18 12:37:57 2008 for Epetra Package Browser (Single Doxygen Collection) by doxygen 1.3.9.1