Epetra Package Browser (Single Doxygen Collection) Development
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 the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00039 // 
00040 // ************************************************************************
00041 //@HEADER
00042 */
00043 
00044 #include "Epetra_Import.h"
00045 #include "Epetra_BlockMap.h"
00046 #include "Epetra_Distributor.h"
00047 #include "Epetra_Comm.h"
00048 #include "Epetra_Util.h"
00049 
00050 
00051 //==============================================================================
00052 // Epetra_Import constructor for a Epetra_BlockMap object
00053 Epetra_Import::Epetra_Import( const Epetra_BlockMap &  TargetMap, const Epetra_BlockMap & SourceMap)
00054   : Epetra_Object("Epetra::Import"),
00055     TargetMap_(TargetMap),
00056     SourceMap_(SourceMap),
00057     NumSameIDs_(0),
00058     NumPermuteIDs_(0),
00059     PermuteToLIDs_(0),
00060     PermuteFromLIDs_(0),
00061     NumRemoteIDs_(0),
00062     RemoteLIDs_(0),
00063     NumExportIDs_(0),
00064     ExportLIDs_(0),
00065     ExportPIDs_(0),
00066     NumSend_(0),
00067     NumRecv_(0),
00068     Distor_(0)
00069 {
00070 
00071   int i;
00072   
00073   // Build three ID lists:
00074   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00075   //              nonidentical ID.
00076   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00077   // NumRemoteIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be imported.
00078   
00079   int NumSourceIDs = SourceMap.NumMyElements();
00080   int NumTargetIDs = TargetMap.NumMyElements();
00081   
00082   int *TargetGIDs = 0;
00083   if (NumTargetIDs>0) {
00084     TargetGIDs = new int[NumTargetIDs];
00085     TargetMap.MyGlobalElements(TargetGIDs);
00086   }
00087   
00088   int * SourceGIDs = 0;
00089   if (NumSourceIDs>0) {
00090     SourceGIDs = new int[NumSourceIDs];
00091     SourceMap.MyGlobalElements(SourceGIDs);
00092   }
00093   
00094   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00095   
00096   
00097   NumSameIDs_ = 0;
00098   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00099   
00100   
00101   // Find count of Target IDs that are truly remote and those that are local but permuted
00102 
00103   NumPermuteIDs_ = 0;
00104   NumRemoteIDs_ = 0;
00105   for (i=NumSameIDs_; i< NumTargetIDs; i++) 
00106     if (SourceMap.MyGID(TargetGIDs[i])) NumPermuteIDs_++; // Check if Target GID is a local Source GID
00107     else NumRemoteIDs_++; // If not, then it is remote
00108   
00109   
00110   
00111   // Define remote and permutation lists
00112   
00113   int * RemoteGIDs=0;
00114   RemoteLIDs_ = 0;
00115   if (NumRemoteIDs_>0) {
00116     RemoteLIDs_ = new int[NumRemoteIDs_];
00117     RemoteGIDs = new int[NumRemoteIDs_];
00118   }
00119   if (NumPermuteIDs_>0)  {
00120     PermuteToLIDs_ = new int[NumPermuteIDs_];
00121     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00122   }
00123   
00124   NumPermuteIDs_ = 0;
00125   NumRemoteIDs_ = 0;
00126   for (i=NumSameIDs_; i< NumTargetIDs; i++) {
00127     if (SourceMap.MyGID(TargetGIDs[i])) {
00128       PermuteToLIDs_[NumPermuteIDs_] = i;
00129       PermuteFromLIDs_[NumPermuteIDs_++] = SourceMap.LID(TargetGIDs[i]);
00130     }
00131     else {
00132       //NumRecv_ +=TargetMap.ElementSize(i); // Count total number of entries to receive
00133       NumRecv_ +=TargetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00134       RemoteGIDs[NumRemoteIDs_] = TargetGIDs[i];
00135       RemoteLIDs_[NumRemoteIDs_++] = i;
00136     }
00137   }
00138 
00139   if( NumRemoteIDs_>0 && !SourceMap.DistributedGlobal() )
00140     ReportError("Warning in Epetra_Import: Serial Import has remote IDs. (Importing to Subset of Target Map)", 1);
00141   
00142   // Test for distributed cases
00143   
00144   int * RemotePIDs = 0;
00145 
00146   if (SourceMap.DistributedGlobal()) {
00147     
00148     if (NumRemoteIDs_>0)  RemotePIDs = new int[NumRemoteIDs_];
00149     int ierr = SourceMap.RemoteIDList(NumRemoteIDs_, RemoteGIDs, RemotePIDs, 0); // Get remote PIDs
00150     if (ierr) throw ReportError("Error in SourceMap.RemoteIDList call", ierr);
00151 
00152     //Get rid of IDs that don't exist in SourceMap
00153     if(NumRemoteIDs_>0) {
00154       int cnt = 0;
00155       for( i = 0; i < NumRemoteIDs_; ++i )
00156         if( RemotePIDs[i] == -1 ) ++cnt;
00157       if( cnt ) {
00158         if( NumRemoteIDs_-cnt ) {
00159           int * NewRemoteGIDs = new int[NumRemoteIDs_-cnt];
00160           int * NewRemotePIDs = new int[NumRemoteIDs_-cnt];
00161           int * NewRemoteLIDs = new int[NumRemoteIDs_-cnt];
00162           cnt = 0;
00163           for( i = 0; i < NumRemoteIDs_; ++i )
00164             if( RemotePIDs[i] != -1 ) {
00165               NewRemoteGIDs[cnt] = RemoteGIDs[i];
00166               NewRemotePIDs[cnt] = RemotePIDs[i];
00167               NewRemoteLIDs[cnt] = TargetMap.LID(RemoteGIDs[i]);
00168               ++cnt;
00169             }
00170           NumRemoteIDs_ = cnt;
00171           delete [] RemoteGIDs;
00172           delete [] RemotePIDs;
00173           delete [] RemoteLIDs_;
00174           RemoteGIDs = NewRemoteGIDs;
00175           RemotePIDs = NewRemotePIDs;
00176           RemoteLIDs_ = NewRemoteLIDs;
00177           ReportError("Warning in Epetra_Import: Target IDs not found in Source Map (Do you want to import to subset of Target Map?)", 1);
00178         }
00179         else { //valid RemoteIDs empty
00180           NumRemoteIDs_ = 0;
00181           delete [] RemoteGIDs;
00182           RemoteGIDs = 0;
00183           delete [] RemotePIDs;
00184           RemotePIDs = 0;
00185         }
00186       }
00187     }
00188 
00189     //Sort Remote IDs by processor so DoReverses will work
00190     Epetra_Util util;
00191     int * tmpPtr[2];
00192     tmpPtr[0] = RemoteLIDs_, tmpPtr[1] = RemoteGIDs;
00193     util.Sort(true,NumRemoteIDs_,RemotePIDs,0,0,2,tmpPtr);
00194 
00195     Distor_ = SourceMap.Comm().CreateDistributor();
00196     
00197     // Construct list of exports that calling processor needs to send as a result
00198     // of everyone asking for what it needs to receive.
00199     
00200     bool Deterministic = true;
00201     ierr = Distor_->CreateFromRecvs( NumRemoteIDs_, RemoteGIDs, RemotePIDs,
00202                        Deterministic, NumExportIDs_, ExportLIDs_, ExportPIDs_ );
00203     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromRecvs()", ierr);
00204 
00205     // Export IDs come in as GIDs, convert to LIDs
00206     for (i=0; i< NumExportIDs_; i++) {
00207       if (ExportPIDs_[i] < 0) throw ReportError("TargetMap requested a GID that is not in the SourceMap.", -1);
00208       ExportLIDs_[i] = SourceMap.LID(ExportLIDs_[i]);
00209       NumSend_ += SourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00210     }
00211   }
00212 
00213   if( NumRemoteIDs_>0 ) delete [] RemoteGIDs;
00214   if( NumRemoteIDs_>0 ) delete [] RemotePIDs;
00215 
00216   if (NumTargetIDs>0) delete [] TargetGIDs;
00217   if (NumSourceIDs>0) delete [] SourceGIDs;
00218   
00219   return;
00220 }
00221 
00222 //==============================================================================
00223 // Epetra_Import copy constructor 
00224 Epetra_Import::Epetra_Import(const Epetra_Import & Importer)
00225   : Epetra_Object(Importer),
00226     TargetMap_(Importer.TargetMap_),
00227     SourceMap_(Importer.SourceMap_),
00228     NumSameIDs_(Importer.NumSameIDs_),
00229     NumPermuteIDs_(Importer.NumPermuteIDs_),
00230     PermuteToLIDs_(0),
00231     PermuteFromLIDs_(0),
00232     NumRemoteIDs_(Importer.NumRemoteIDs_),
00233     RemoteLIDs_(0),
00234     NumExportIDs_(Importer.NumExportIDs_),
00235     ExportLIDs_(0),
00236     ExportPIDs_(0),
00237     NumSend_(Importer.NumSend_),
00238     NumRecv_(Importer.NumRecv_),
00239     Distor_(0)
00240 {
00241   int i;
00242   if (NumPermuteIDs_>0) {
00243     PermuteToLIDs_ = new int[NumPermuteIDs_];
00244     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00245     for (i=0; i< NumPermuteIDs_; i++) {
00246       PermuteToLIDs_[i] = Importer.PermuteToLIDs_[i];
00247       PermuteFromLIDs_[i] = Importer.PermuteFromLIDs_[i];
00248     }
00249   }
00250 
00251   if (NumRemoteIDs_>0) {
00252     RemoteLIDs_ = new int[NumRemoteIDs_];
00253     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Importer.RemoteLIDs_[i];
00254   }
00255 
00256   if (NumExportIDs_>0) {
00257     ExportLIDs_ = new int[NumExportIDs_];
00258     ExportPIDs_ = new int[NumExportIDs_];
00259     for (i=0; i< NumExportIDs_; i++) {
00260       ExportLIDs_[i] = Importer.ExportLIDs_[i];
00261       ExportPIDs_[i] = Importer.ExportPIDs_[i];
00262     }
00263   }
00264 
00265   if (Importer.Distor_!=0) Distor_ = Importer.Distor_->Clone();
00266 
00267 }
00268 
00269 //==============================================================================
00270 // Epetra_Import destructor 
00271 Epetra_Import::~Epetra_Import()
00272 {
00273   if( Distor_ != 0 ) delete Distor_;
00274   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00275   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00276   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00277 
00278   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by Distor_
00279   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00280 }
00281 //=============================================================================
00282 void Epetra_Import::Print(ostream & os) const
00283 {
00284 
00285   os << endl << endl << "Source Map:" << endl << endl;
00286   SourceMap_.Print(os);
00287   
00288   os << endl << endl << "Target Map:" << endl << endl;
00289   TargetMap_.Print(os);
00290   
00291   os << endl << endl << "Distributor:" << endl << endl;
00292   if (Distor_==0) os << "  Is empty...." << endl;
00293   else Distor_->Print(os);
00294   
00295   os << "Number of Same IDs = " << NumSameIDs_ << endl;
00296 
00297   os << "Number of Permute IDs = " << NumPermuteIDs_ << endl;
00298 
00299   os << "Number of Export IDs = " << NumExportIDs_ << endl;
00300 
00301   os << "Number of Remote IDs = " << NumRemoteIDs_ << endl;
00302   
00303   os << "Epetra_Import Print Needs attention!!!!" << endl;
00304   return;
00305 }
00306 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines