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 2011 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_ConfigDefs.h"
00045 #include "Epetra_Import.h"
00046 #include "Epetra_BlockMap.h"
00047 #include "Epetra_Distributor.h"
00048 #include "Epetra_Comm.h"
00049 #include "Epetra_Util.h"
00050 #include "Epetra_Export.h"
00051 
00052 #include <algorithm>
00053 #include <vector>
00054 
00055 
00056 #ifdef HAVE_MPI
00057 #include "Epetra_MpiDistributor.h"
00058 #endif
00059 
00060 #ifdef EPETRA_ENABLE_DEBUG
00061 #include "Epetra_IntVector.h"
00062 #endif
00063 
00064 //==============================================================================
00065 // Epetra_Import constructor function for a Epetra_BlockMap object
00066 template<typename int_type>
00067 void Epetra_Import::Construct_Expert( const Epetra_BlockMap &  targetMap, const Epetra_BlockMap & sourceMap, int NumRemotePIDs, const int * UserRemotePIDs,
00068               const int & UserNumExportIDs, const int * UserExportLIDs,  const int * UserExportPIDs)
00069 {
00070   int i,ierr;
00071   // Build three ID lists:
00072   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00073   //              nonidentical ID.
00074   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00075   // NumRemoteIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be imported.
00076   
00077   int NumSourceIDs = sourceMap.NumMyElements();
00078   int NumTargetIDs = targetMap.NumMyElements();
00079   
00080   int_type *TargetGIDs = 0;
00081   if (NumTargetIDs>0) {
00082     TargetGIDs = new int_type[NumTargetIDs];
00083     targetMap.MyGlobalElements(TargetGIDs);
00084   }
00085   
00086   int_type * SourceGIDs = 0;
00087   if (NumSourceIDs>0) {
00088     SourceGIDs = new int_type[NumSourceIDs];
00089     sourceMap.MyGlobalElements(SourceGIDs);
00090   }
00091   
00092   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00093     
00094   NumSameIDs_ = 0;
00095   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00096   
00097   // Find count of Target IDs that are truly remote and those that are local but permuted
00098   NumPermuteIDs_ = 0;
00099   NumRemoteIDs_ = 0;
00100   for (i=NumSameIDs_; i< NumTargetIDs; i++) 
00101     if (sourceMap.MyGID(TargetGIDs[i])) NumPermuteIDs_++; // Check if Target GID is a local Source GID
00102     else NumRemoteIDs_++; // If not, then it is remote
00103 
00104 
00105   
00106   // Define remote and permutation lists  
00107   int_type * RemoteGIDs=0;
00108   RemoteLIDs_ = 0;
00109   if (NumRemoteIDs_>0) {
00110     RemoteLIDs_ = new int[NumRemoteIDs_];
00111     RemoteGIDs = new int_type[NumRemoteIDs_];
00112   }
00113   if (NumPermuteIDs_>0)  {
00114     PermuteToLIDs_ = new int[NumPermuteIDs_];
00115     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00116   }
00117   
00118   NumPermuteIDs_ = 0;
00119   NumRemoteIDs_ = 0;
00120   for (i=NumSameIDs_; i< NumTargetIDs; i++) {
00121     if (sourceMap.MyGID(TargetGIDs[i])) {
00122       PermuteToLIDs_[NumPermuteIDs_] = i;
00123       PermuteFromLIDs_[NumPermuteIDs_++] = sourceMap.LID(TargetGIDs[i]);
00124     }
00125     else {
00126       //NumRecv_ +=TargetMap.ElementSize(i); // Count total number of entries to receive
00127       NumRecv_ +=targetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00128       RemoteGIDs[NumRemoteIDs_] = TargetGIDs[i];
00129       RemoteLIDs_[NumRemoteIDs_++] = i;
00130     }
00131   }
00132 
00133   if( NumRemoteIDs_>0 && !sourceMap.DistributedGlobal() )
00134     ReportError("Warning in Epetra_Import: Serial Import has remote IDs. (Importing to Subset of Target Map)", 1);
00135   
00136   // Test for distributed cases
00137   int * RemotePIDs = 0;
00138   
00139   if (sourceMap.DistributedGlobal()) {
00140     if (NumRemoteIDs_>0)  RemotePIDs = new int[NumRemoteIDs_];
00141 
00142 #ifdef EPETRA_ENABLE_DEBUG
00143     int myeq = (NumRemotePIDs==NumRemoteIDs_);
00144     int globaleq=0;
00145     sourceMap.Comm().MinAll(&myeq,&globaleq,1);
00146     if(globaleq!=1) { 
00147       printf("[%d] UserRemotePIDs count wrong %d != %d\n",sourceMap.Comm().MyPID(),NumRemotePIDs,NumRemoteIDs_);
00148       fflush(stdout);
00149       sourceMap.Comm().Barrier();
00150       sourceMap.Comm().Barrier();
00151       sourceMap.Comm().Barrier();
00152       ReportError("Epetra_Import: UserRemotePIDs count wrong",-1);
00153     }
00154 #endif
00155 
00156     if(NumRemotePIDs==NumRemoteIDs_){
00157       // Since I need to sort these, I'll copy them
00158       for(i=0; i<NumRemoteIDs_; i++)  RemotePIDs[i] = UserRemotePIDs[i];
00159     }
00160 
00161     //Get rid of IDs that don't exist in SourceMap
00162     if(NumRemoteIDs_>0) {
00163       int cnt = 0;
00164       for( i = 0; i < NumRemoteIDs_; ++i )
00165         if( RemotePIDs[i] == -1 ) ++cnt;
00166       if( cnt ) {
00167         if( NumRemoteIDs_-cnt ) {
00168           int_type * NewRemoteGIDs = new int_type[NumRemoteIDs_-cnt];
00169           int * NewRemotePIDs = new int[NumRemoteIDs_-cnt];
00170           int * NewRemoteLIDs = new int[NumRemoteIDs_-cnt];
00171           cnt = 0;
00172           for( i = 0; i < NumRemoteIDs_; ++i )
00173             if( RemotePIDs[i] != -1 ) {
00174               NewRemoteGIDs[cnt] = RemoteGIDs[i];
00175               NewRemotePIDs[cnt] = RemotePIDs[i];
00176               NewRemoteLIDs[cnt] = targetMap.LID(RemoteGIDs[i]);
00177               ++cnt;
00178             }
00179           NumRemoteIDs_ = cnt;
00180           delete [] RemoteGIDs;
00181           delete [] RemotePIDs;
00182           delete [] RemoteLIDs_;
00183           RemoteGIDs = NewRemoteGIDs;
00184           RemotePIDs = NewRemotePIDs;
00185           RemoteLIDs_ = NewRemoteLIDs;
00186           ReportError("Warning in Epetra_Import: Target IDs not found in Source Map (Do you want to import to subset of Target Map?)", 1);
00187         }
00188         else { //valid RemoteIDs empty
00189           NumRemoteIDs_ = 0;
00190           delete [] RemoteGIDs;
00191           RemoteGIDs = 0;
00192           delete [] RemotePIDs;
00193           RemotePIDs = 0;
00194         }
00195       }
00196     }
00197 
00198     //Sort Remote IDs by processor so DoReverses will work
00199     Epetra_Util util;
00200     
00201     if(targetMap.GlobalIndicesLongLong())
00202       {
00203   // FIXME (mfh 11 Jul 2013) This breaks ANSI aliasing rules, if
00204   // int_type != long long.  On some compilers, it results in
00205   // warnings such as this: "dereferencing type-punned pointer
00206   // will break strict-aliasing rules".
00207   util.Sort(true,NumRemoteIDs_,RemotePIDs,0,0, 1,&RemoteLIDs_, 1,(long long**)&RemoteGIDs);
00208       }
00209     else if(targetMap.GlobalIndicesInt())
00210       {
00211   int* ptrs[2] = {RemoteLIDs_, (int*)RemoteGIDs};
00212   util.Sort(true,NumRemoteIDs_,RemotePIDs,0,0,2,&ptrs[0], 0, 0);
00213       }
00214     else
00215       {
00216   throw ReportError("Epetra_Import::Epetra_Import: GlobalIndices Internal Error", -1);
00217       }
00218     
00219     // Build distributor & Export lists
00220     Distor_ = sourceMap.Comm().CreateDistributor();    
00221     
00222     NumExportIDs_=UserNumExportIDs;
00223     ExportLIDs_ = new int[NumExportIDs_];
00224     ExportPIDs_ = new int[NumExportIDs_];
00225     for(i=0; i<NumExportIDs_; i++)  {
00226       ExportPIDs_[i] = UserExportPIDs[i];
00227       ExportLIDs_[i] = UserExportLIDs[i];
00228     }
00229     
00230     // Send Counts
00231     for (i=0; i< NumExportIDs_; i++) {
00232       NumSend_ += sourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00233     }
00234 
00235 #ifdef HAVE_MPI
00236     Epetra_MpiDistributor* MpiDistor = dynamic_cast< Epetra_MpiDistributor*>(Distor_);
00237     bool Deterministic = true;
00238     if(MpiDistor)
00239       ierr=MpiDistor->CreateFromSendsAndRecvs(NumExportIDs_,ExportPIDs_,                
00240                 NumRemoteIDs_, RemoteGIDs, RemotePIDs,Deterministic);
00241     else ierr=-10;
00242 #else
00243     ierr=-20;
00244 #endif
00245     
00246     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromRecvs()", ierr);   
00247   }  
00248 
00249   if( NumRemoteIDs_>0 ) delete [] RemoteGIDs;
00250   if( NumRemoteIDs_>0 ) delete [] RemotePIDs;
00251   
00252   if (NumTargetIDs>0) delete [] TargetGIDs;
00253   if (NumSourceIDs>0) delete [] SourceGIDs;
00254 
00255 
00256 #ifdef EPETRA_ENABLE_DEBUG
00257 // Sanity check to make sure we got the import right
00258   Epetra_IntVector Source(sourceMap);
00259   Epetra_IntVector Target(targetMap);
00260 
00261   for(i=0; i<Source.MyLength(); i++)
00262     Source[i] = (int) (Source.Map().GID(i) % INT_MAX);
00263   Target.PutValue(-1);
00264  
00265   Target.Import(Source,*this,Insert);
00266   
00267   bool test_passed=true;
00268   for(i=0; i<Target.MyLength(); i++){
00269     if(Target[i] != Target.Map().GID(i) % INT_MAX) test_passed=false;
00270   }
00271 
00272   if(!test_passed) {  
00273     printf("[%d] PROCESSOR has a mismatch... prepearing to crash or hang!\n",sourceMap.Comm().MyPID());
00274     fflush(stdout);
00275     sourceMap.Comm().Barrier();
00276     sourceMap.Comm().Barrier();
00277     sourceMap.Comm().Barrier();
00278     throw ReportError("Epetra_Import: ERROR. User provided IDs do not match what an import generates.");
00279   }
00280 #endif
00281   
00282   return;
00283 }
00284 
00285 //==============================================================================
00286 // Epetra_Import constructor function for a Epetra_BlockMap object
00287 template<typename int_type>
00288 void Epetra_Import::Construct( const Epetra_BlockMap &  targetMap, const Epetra_BlockMap & sourceMap, int NumRemotePIDs, const int * UserRemotePIDs)
00289 {
00290   int i,ierr;
00291   // Build three ID lists:
00292   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00293   //              nonidentical ID.
00294   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00295   // NumRemoteIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be imported.
00296   
00297   int NumSourceIDs = sourceMap.NumMyElements();
00298   int NumTargetIDs = targetMap.NumMyElements();
00299   
00300   int_type *TargetGIDs = 0;
00301   if (NumTargetIDs>0) {
00302     TargetGIDs = new int_type[NumTargetIDs];
00303     targetMap.MyGlobalElements(TargetGIDs);
00304   }
00305   
00306   int_type * SourceGIDs = 0;
00307   if (NumSourceIDs>0) {
00308     SourceGIDs = new int_type[NumSourceIDs];
00309     sourceMap.MyGlobalElements(SourceGIDs);
00310   }
00311   
00312   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00313   
00314   
00315   NumSameIDs_ = 0;
00316   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00317   
00318   // Find count of Target IDs that are truly remote and those that are local but permuted
00319   NumPermuteIDs_ = 0;
00320   NumRemoteIDs_ = 0;
00321   for (i=NumSameIDs_; i< NumTargetIDs; i++) 
00322     if (sourceMap.MyGID(TargetGIDs[i])) NumPermuteIDs_++; // Check if Target GID is a local Source GID
00323     else NumRemoteIDs_++; // If not, then it is remote
00324   
00325   
00326   
00327   // Define remote and permutation lists  
00328   int_type * RemoteGIDs=0;
00329   RemoteLIDs_ = 0;
00330   if (NumRemoteIDs_>0) {
00331     RemoteLIDs_ = new int[NumRemoteIDs_];
00332     RemoteGIDs = new int_type[NumRemoteIDs_];
00333   }
00334   if (NumPermuteIDs_>0)  {
00335     PermuteToLIDs_ = new int[NumPermuteIDs_];
00336     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00337   }
00338   
00339   NumPermuteIDs_ = 0;
00340   NumRemoteIDs_ = 0;
00341   for (i=NumSameIDs_; i< NumTargetIDs; i++) {
00342     if (sourceMap.MyGID(TargetGIDs[i])) {
00343       PermuteToLIDs_[NumPermuteIDs_] = i;
00344       PermuteFromLIDs_[NumPermuteIDs_++] = sourceMap.LID(TargetGIDs[i]);
00345     }
00346     else {
00347       //NumRecv_ +=TargetMap.ElementSize(i); // Count total number of entries to receive
00348       NumRecv_ +=targetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00349       RemoteGIDs[NumRemoteIDs_] = TargetGIDs[i];
00350       RemoteLIDs_[NumRemoteIDs_++] = i;
00351     }
00352   }
00353 
00354   if( NumRemoteIDs_>0 && !sourceMap.DistributedGlobal() )
00355     ReportError("Warning in Epetra_Import: Serial Import has remote IDs. (Importing to Subset of Target Map)", 1);
00356   
00357   // Test for distributed cases
00358   int * RemotePIDs = 0;
00359   
00360   if (sourceMap.DistributedGlobal()) {
00361     if (NumRemoteIDs_>0)  RemotePIDs = new int[NumRemoteIDs_];
00362 
00363 #ifdef EPETRA_ENABLE_DEBUG
00364     if(NumRemotePIDs!=-1){
00365       int myeq = (NumRemotePIDs==NumRemoteIDs_);
00366       int globaleq=0;
00367       sourceMap.Comm().MinAll(&myeq,&globaleq,1);
00368       if(globaleq!=1) { 
00369   printf("[%d] UserRemotePIDs count wrong %d != %d\n",sourceMap.Comm().MyPID(),NumRemotePIDs,NumRemoteIDs_);
00370   fflush(stdout);
00371   sourceMap.Comm().Barrier();
00372   sourceMap.Comm().Barrier();
00373   sourceMap.Comm().Barrier();
00374   throw ReportError("Epetra_Import: UserRemotePIDs count wrong",-1);
00375       }
00376     }
00377 #endif
00378 
00379     if(NumRemotePIDs!=-1 && NumRemotePIDs==NumRemoteIDs_){
00380       // Since I need to sort these, I'll copy them
00381       for(i=0; i<NumRemoteIDs_; i++)  RemotePIDs[i] = UserRemotePIDs[i];
00382     }
00383     else{
00384       ierr=sourceMap.RemoteIDList(NumRemoteIDs_, RemoteGIDs, RemotePIDs, 0); // Get remote PIDs
00385       if (ierr) throw ReportError("Error in sourceMap.RemoteIDList call", ierr);
00386     }
00387 
00388     //Get rid of IDs that don't exist in SourceMap
00389     if(NumRemoteIDs_>0) {
00390       int cnt = 0;
00391       for( i = 0; i < NumRemoteIDs_; ++i )
00392         if( RemotePIDs[i] == -1 ) ++cnt;
00393       if( cnt ) {
00394         if( NumRemoteIDs_-cnt ) {
00395           int_type * NewRemoteGIDs = new int_type[NumRemoteIDs_-cnt];
00396           int * NewRemotePIDs = new int[NumRemoteIDs_-cnt];
00397           int * NewRemoteLIDs = new int[NumRemoteIDs_-cnt];
00398           cnt = 0;
00399           for( i = 0; i < NumRemoteIDs_; ++i )
00400             if( RemotePIDs[i] != -1 ) {
00401               NewRemoteGIDs[cnt] = RemoteGIDs[i];
00402               NewRemotePIDs[cnt] = RemotePIDs[i];
00403               NewRemoteLIDs[cnt] = targetMap.LID(RemoteGIDs[i]);
00404               ++cnt;
00405             }
00406           NumRemoteIDs_ = cnt;
00407           delete [] RemoteGIDs;
00408           delete [] RemotePIDs;
00409           delete [] RemoteLIDs_;
00410           RemoteGIDs = NewRemoteGIDs;
00411           RemotePIDs = NewRemotePIDs;
00412           RemoteLIDs_ = NewRemoteLIDs;
00413           ReportError("Warning in Epetra_Import: Target IDs not found in Source Map (Do you want to import to subset of Target Map?)", 1);
00414         }
00415         else { //valid RemoteIDs empty
00416           NumRemoteIDs_ = 0;
00417           delete [] RemoteGIDs;
00418           RemoteGIDs = 0;
00419           delete [] RemotePIDs;
00420           RemotePIDs = 0;
00421         }
00422       }
00423     }
00424 
00425     //Sort Remote IDs by processor so DoReverses will work
00426     if(targetMap.GlobalIndicesLongLong())
00427       {
00428   // FIXME (mfh 11 Jul 2013) This breaks ANSI aliasing rules, if
00429   // int_type != long long.  On some compilers, it results in
00430   // warnings such as this: "dereferencing type-punned pointer
00431   // will break strict-aliasing rules".
00432   Epetra_Util::Sort(true,NumRemoteIDs_,RemotePIDs,0,0, 1,&RemoteLIDs_, 1,(long long**)&RemoteGIDs);
00433       }
00434     else if(targetMap.GlobalIndicesInt())
00435       {
00436   int* ptrs[2] = {RemoteLIDs_, (int*)RemoteGIDs};
00437   Epetra_Util::Sort(true,NumRemoteIDs_,RemotePIDs,0,0,2,&ptrs[0], 0, 0);
00438       }
00439     else
00440       {
00441   throw ReportError("Epetra_Import::Epetra_Import: GlobalIndices Internal Error", -1);
00442       }
00443     Distor_ = sourceMap.Comm().CreateDistributor();
00444     
00445     // Construct list of exports that calling processor needs to send as a result
00446     // of everyone asking for what it needs to receive.
00447     
00448     bool Deterministic = true;
00449     int_type* tmp_ExportLIDs; //Export IDs come in as GIDs
00450     ierr = Distor_->CreateFromRecvs( NumRemoteIDs_, RemoteGIDs, RemotePIDs,
00451              Deterministic, NumExportIDs_, tmp_ExportLIDs, ExportPIDs_ );
00452     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromRecvs()", ierr);
00453     
00454 
00455     // Export IDs come in as GIDs, convert to LIDs
00456     if(targetMap.GlobalIndicesLongLong())
00457       {
00458   ExportLIDs_ = new int[NumExportIDs_];
00459   
00460   for (i=0; i< NumExportIDs_; i++) {
00461     if (ExportPIDs_[i] < 0) throw ReportError("targetMap requested a GID that is not in the sourceMap.", -1);
00462     ExportLIDs_[i] = sourceMap.LID(tmp_ExportLIDs[i]);
00463     NumSend_ += sourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00464   }
00465   
00466   delete[] tmp_ExportLIDs;
00467       }
00468     else if(targetMap.GlobalIndicesInt())
00469       {
00470   for (i=0; i< NumExportIDs_; i++) {
00471     if (ExportPIDs_[i] < 0) throw ReportError("targetMap requested a GID that is not in the sourceMap.", -1);
00472     tmp_ExportLIDs[i] = sourceMap.LID(tmp_ExportLIDs[i]);
00473     NumSend_ += sourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00474   }
00475   
00476   ExportLIDs_ = reinterpret_cast<int *>(tmp_ExportLIDs); // Can't reach here if tmp_ExportLIDs is long long.
00477       }
00478     else
00479       {
00480   throw ReportError("Epetra_Import::Epetra_Import: GlobalIndices Internal Error", -1);
00481       }
00482   }
00483   
00484   if( NumRemoteIDs_>0 ) delete [] RemoteGIDs;
00485   if( NumRemoteIDs_>0 ) delete [] RemotePIDs;
00486 
00487   if (NumTargetIDs>0) delete [] TargetGIDs;
00488   if (NumSourceIDs>0) delete [] SourceGIDs;
00489 
00490   return;
00491 }
00492 
00493 //==============================================================================
00494 Epetra_Import::Epetra_Import( const Epetra_BlockMap &  targetMap, const Epetra_BlockMap & sourceMap,int NumRemotePIDs,const int * RemotePIDs)
00495   : Epetra_Object("Epetra::Import"),
00496     TargetMap_(targetMap),
00497     SourceMap_(sourceMap),
00498     NumSameIDs_(0),
00499     NumPermuteIDs_(0),
00500     PermuteToLIDs_(0),
00501     PermuteFromLIDs_(0),
00502     NumRemoteIDs_(0),
00503     RemoteLIDs_(0),
00504     NumExportIDs_(0),
00505     ExportLIDs_(0),
00506     ExportPIDs_(0),
00507     NumSend_(0),
00508     NumRecv_(0),
00509     Distor_(0)
00510 {
00511   if(!targetMap.GlobalIndicesTypeMatch(sourceMap))
00512     throw ReportError("Epetra_Import::Epetra_Import: GlobalIndicesTypeMatch failed", -1);
00513 
00514   if(targetMap.GlobalIndicesInt())
00515 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00516     Construct<int>(targetMap, sourceMap,NumRemotePIDs,RemotePIDs);
00517 #else
00518     throw ReportError("Epetra_Import::Epetra_Import: ERROR, GlobalIndicesInt but no API for it.",-1);
00519 #endif
00520   else if(targetMap.GlobalIndicesLongLong())
00521 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00522     Construct<long long>(targetMap, sourceMap,NumRemotePIDs,RemotePIDs);
00523 #else
00524     throw ReportError("Epetra_Import::Epetra_Import: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00525 #endif
00526   else
00527     throw ReportError("Epetra_Import::Epetra_Import: Bad global indices type", -1);
00528 }
00529 
00530 
00531 
00532 //==============================================================================
00533 Epetra_Import::Epetra_Import( const Epetra_BlockMap &  targetMap, const Epetra_BlockMap & sourceMap,int NumRemotePIDs,const int * RemotePIDs,
00534             const int & NumExportIDs, const int * ExportLIDs,  const int * ExportPIDs)
00535   : Epetra_Object("Epetra::Import"),
00536     TargetMap_(targetMap),
00537     SourceMap_(sourceMap),
00538     NumSameIDs_(0),
00539     NumPermuteIDs_(0),
00540     PermuteToLIDs_(0),
00541     PermuteFromLIDs_(0),
00542     NumRemoteIDs_(0),
00543     RemoteLIDs_(0),
00544     NumExportIDs_(0),
00545     ExportLIDs_(0),
00546     ExportPIDs_(0),
00547     NumSend_(0),
00548     NumRecv_(0),
00549     Distor_(0)
00550 {
00551   if(!targetMap.GlobalIndicesTypeMatch(sourceMap))
00552     throw ReportError("Epetra_Import::Epetra_Import: GlobalIndicesTypeMatch failed", -1);
00553 
00554   if(targetMap.GlobalIndicesInt())
00555 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00556     Construct_Expert<int>(targetMap, sourceMap,NumRemotePIDs,RemotePIDs,NumExportIDs,ExportLIDs,ExportPIDs);
00557 #else
00558     throw ReportError("Epetra_Import::Epetra_Import: ERROR, GlobalIndicesInt but no API for it.",-1);
00559 #endif
00560   else if(targetMap.GlobalIndicesLongLong())
00561 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00562     Construct_Expert<long long>(targetMap, sourceMap,NumRemotePIDs,RemotePIDs,NumExportIDs,ExportLIDs,ExportPIDs);
00563 #else
00564     throw ReportError("Epetra_Import::Epetra_Import: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00565 #endif
00566   else
00567     throw ReportError("Epetra_Import::Epetra_Import: Bad global indices type", -1);
00568 }
00569 
00570 
00571 //==============================================================================
00572 Epetra_Import::Epetra_Import( const Epetra_BlockMap &  targetMap, const Epetra_BlockMap & sourceMap)
00573   : Epetra_Object("Epetra::Import"),
00574     TargetMap_(targetMap),
00575     SourceMap_(sourceMap),
00576     NumSameIDs_(0),
00577     NumPermuteIDs_(0),
00578     PermuteToLIDs_(0),
00579     PermuteFromLIDs_(0),
00580     NumRemoteIDs_(0),
00581     RemoteLIDs_(0),
00582     NumExportIDs_(0),
00583     ExportLIDs_(0),
00584     ExportPIDs_(0),
00585     NumSend_(0),
00586     NumRecv_(0),
00587     Distor_(0)
00588 {
00589   if(!targetMap.GlobalIndicesTypeMatch(sourceMap))
00590     throw ReportError("Epetra_Import::Epetra_Import: GlobalIndicesTypeMatch failed", -1);
00591 
00592   if(targetMap.GlobalIndicesInt())
00593 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00594     Construct<int>(targetMap, sourceMap);
00595 #else
00596     throw ReportError("Epetra_Import::Epetra_Import: ERROR, GlobalIndicesInt but no API for it.",-1);
00597 #endif
00598   else if(targetMap.GlobalIndicesLongLong())
00599 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00600     Construct<long long>(targetMap, sourceMap);
00601 #else
00602     throw ReportError("Epetra_Import::Epetra_Import: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00603 #endif
00604   else
00605     throw ReportError("Epetra_Import::Epetra_Import: Bad global indices type", -1);
00606 }
00607 
00608 //==============================================================================
00609 // Epetra_Import copy constructor 
00610 Epetra_Import::Epetra_Import(const Epetra_Import & Importer)
00611   : Epetra_Object(Importer),
00612     TargetMap_(Importer.TargetMap_),
00613     SourceMap_(Importer.SourceMap_),
00614     NumSameIDs_(Importer.NumSameIDs_),
00615     NumPermuteIDs_(Importer.NumPermuteIDs_),
00616     PermuteToLIDs_(0),
00617     PermuteFromLIDs_(0),
00618     NumRemoteIDs_(Importer.NumRemoteIDs_),
00619     RemoteLIDs_(0),
00620     NumExportIDs_(Importer.NumExportIDs_),
00621     ExportLIDs_(0),
00622     ExportPIDs_(0),
00623     NumSend_(Importer.NumSend_),
00624     NumRecv_(Importer.NumRecv_),
00625     Distor_(0)
00626 {
00627   int i;
00628   if (NumPermuteIDs_>0) {
00629     PermuteToLIDs_ = new int[NumPermuteIDs_];
00630     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00631     for (i=0; i< NumPermuteIDs_; i++) {
00632       PermuteToLIDs_[i] = Importer.PermuteToLIDs_[i];
00633       PermuteFromLIDs_[i] = Importer.PermuteFromLIDs_[i];
00634     }
00635   }
00636 
00637   if (NumRemoteIDs_>0) {
00638     RemoteLIDs_ = new int[NumRemoteIDs_];
00639     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Importer.RemoteLIDs_[i];
00640   }
00641 
00642   if (NumExportIDs_>0) {
00643     ExportLIDs_ = new int[NumExportIDs_];
00644     ExportPIDs_ = new int[NumExportIDs_];
00645     for (i=0; i< NumExportIDs_; i++) {
00646       ExportLIDs_[i] = Importer.ExportLIDs_[i];
00647       ExportPIDs_[i] = Importer.ExportPIDs_[i];
00648     }
00649   }
00650 
00651   if (Importer.Distor_!=0) Distor_ = Importer.Distor_->Clone();
00652 
00653 }
00654 
00655 //==============================================================================
00656 // Epetra_Import destructor 
00657 Epetra_Import::~Epetra_Import()
00658 {
00659   if( Distor_ != 0 ) delete Distor_;
00660   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00661   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00662   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00663 
00664   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by Distor_
00665   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00666 }
00667 
00668 //==============================================================================
00669 // Epetra_Import pseudo-copy constructor. 
00670 Epetra_Import::Epetra_Import(const Epetra_Export& Exporter):
00671   TargetMap_(Exporter.SourceMap_), //reverse
00672   SourceMap_(Exporter.TargetMap_),//reverse
00673   NumSameIDs_(Exporter.NumSameIDs_),
00674   NumPermuteIDs_(Exporter.NumPermuteIDs_),
00675   PermuteToLIDs_(0),
00676   PermuteFromLIDs_(0),
00677   NumRemoteIDs_(Exporter.NumExportIDs_),//reverse
00678   RemoteLIDs_(0),
00679   NumExportIDs_(Exporter.NumRemoteIDs_),//reverse
00680   ExportLIDs_(0),
00681   ExportPIDs_(0),
00682   NumSend_(Exporter.NumRecv_),//reverse
00683   NumRecv_(Exporter.NumSend_),//revsese
00684   Distor_(0)
00685 {
00686   int i;
00687   // Reverse the permutes
00688   if (NumPermuteIDs_>0) {
00689     PermuteToLIDs_   = new int[NumPermuteIDs_];
00690     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00691     for (i=0; i< NumPermuteIDs_; i++) {
00692       PermuteFromLIDs_[i] = Exporter.PermuteToLIDs_[i];
00693       PermuteToLIDs_[i]   = Exporter.PermuteFromLIDs_[i];
00694     }
00695   }
00696 
00697   // Copy the exports to the remotes
00698   if (NumRemoteIDs_>0) {
00699     RemoteLIDs_ = new int[NumRemoteIDs_];
00700     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Exporter.ExportLIDs_[i];
00701   }
00702 
00703   // Copy the remotes to the exports
00704   if (NumExportIDs_>0) {
00705     ExportLIDs_ = new int[NumExportIDs_];
00706     ExportPIDs_ = new int[NumExportIDs_];
00707     for (i=0; i< NumExportIDs_; i++) ExportLIDs_[i] = Exporter.RemoteLIDs_[i];
00708 
00709     
00710     // Extract the RemotePIDs from the Distributor
00711 #ifdef HAVE_MPI
00712     Epetra_MpiDistributor *D=dynamic_cast<Epetra_MpiDistributor*>(&Exporter.Distributor());
00713     if(!D) throw ReportError("Epetra_Import: Can't have ExportPIDs w/o an Epetra::MpiDistributor.",-1);
00714     int i,j,k;
00715     
00716     // Get the distributor's data
00717     int NumReceives        = D->NumReceives();
00718     const int *ProcsFrom   = D->ProcsFrom();
00719     const int *LengthsFrom = D->LengthsFrom();
00720     
00721     // Now, for each remote ID, record who actually owns it.  This loop follows the operation order in the
00722     // MpiDistributor so it ought to duplicate that effect.
00723     for(i=0,j=0;i<NumReceives;i++){
00724       int pid=ProcsFrom[i];
00725       for(k=0;k<LengthsFrom[i];k++){
00726   ExportPIDs_[j]=pid;
00727   j++;
00728       }    
00729     }
00730 #else
00731     throw ReportError("Epetra_Import: Can't have ExportPIDs w/o an Epetra::MpiDistributor.",-2);
00732 #endif
00733   }//end NumExportIDs>0
00734 
00735   if (Exporter.Distor_!=0) Distor_ = Exporter.Distor_->ReverseClone();
00736 }
00737 
00738 //=============================================================================
00739 void Epetra_Import::Print(std::ostream & os) const
00740 {
00741   // mfh 14 Dec 2011: The implementation of Print() I found here
00742   // previously didn't print much at all, and it included a message
00743   // saying that it wasn't finished ("Epetra_Import::Print needs
00744   // attention!!!").  What you see below is a port of
00745   // Tpetra::Import::print, which does have a full implementation.
00746   // This should allow a side-by-side comparison of Epetra_Import with
00747   // Tpetra::Import.
00748 
00749   // If true, then copy the array data and sort it before printing.
00750   // Otherwise, leave the data in its original order.  
00751   //
00752   // NOTE: Do NOT sort the arrays in place!  Only sort in the copy.
00753   // Epetra depends on the order being preserved, and some arrays'
00754   // orders are coupled.
00755   const bool sortIDs = false;
00756 
00757   const Epetra_Comm& comm = SourceMap_.Comm();
00758   const int myRank = comm.MyPID();
00759   const int numProcs = comm.NumProc();
00760   
00761   if (myRank == 0) {
00762     os << "Import Data Members:" << std::endl;
00763   }
00764   // We don't need a barrier before this for loop, because Proc 0 is
00765   // the first one to do anything in the for loop anyway.
00766   for (int p = 0; p < numProcs; ++p) {
00767     if (myRank == p) {
00768       os << "Image ID       : " << myRank << std::endl;
00769 
00770       os << "permuteFromLIDs:";
00771       if (PermuteFromLIDs_ == NULL) {
00772   os << " NULL";
00773       } else {
00774   std::vector<int> permuteFromLIDs (NumPermuteIDs_);
00775   std::copy (PermuteFromLIDs_, PermuteFromLIDs_ + NumPermuteIDs_, 
00776        permuteFromLIDs.begin());
00777   if (sortIDs) {
00778     std::sort (permuteFromLIDs.begin(), permuteFromLIDs.end());
00779   }
00780   os << " {";
00781   for (int i = 0; i < NumPermuteIDs_; ++i) {
00782     os << permuteFromLIDs[i];
00783     if (i < NumPermuteIDs_ - 1) {
00784       os << ", ";
00785     }
00786   }
00787   os << "}";
00788       }
00789       os << std::endl;
00790 
00791       os << "permuteToLIDs  :";
00792       if (PermuteToLIDs_ == NULL) {
00793   os << " NULL";
00794       } else {
00795   std::vector<int> permuteToLIDs (NumPermuteIDs_);
00796   std::copy (PermuteToLIDs_, PermuteToLIDs_ + NumPermuteIDs_, 
00797        permuteToLIDs.begin());
00798   if (sortIDs) {
00799     std::sort (permuteToLIDs.begin(), permuteToLIDs.end());
00800   }
00801   os << " {";
00802   for (int i = 0; i < NumPermuteIDs_; ++i) {
00803     os << permuteToLIDs[i];
00804     if (i < NumPermuteIDs_ - 1) {
00805       os << ", ";
00806     }
00807   }
00808   os << "}";
00809       }
00810       os << std::endl;
00811 
00812       os << "remoteLIDs     :";
00813       if (RemoteLIDs_ == NULL) {
00814   os << " NULL";
00815       } else {
00816   std::vector<int> remoteLIDs (NumRemoteIDs_);
00817   std::copy (RemoteLIDs_, RemoteLIDs_ + NumRemoteIDs_, 
00818        remoteLIDs.begin());
00819   if (sortIDs) {
00820     std::sort (remoteLIDs.begin(), remoteLIDs.end());
00821   }
00822   os << " {";
00823   for (int i = 0; i < NumRemoteIDs_; ++i) {
00824     os << remoteLIDs[i];
00825     if (i < NumRemoteIDs_ - 1) {
00826       os << ", ";
00827     }
00828   }
00829   os << "}";
00830       }
00831       os << std::endl;
00832 
00833       // If sorting for output, the export LIDs and export PIDs have
00834       // to be sorted together.  We can use Epetra_Util::Sort, using
00835       // the PIDs as the keys to match Tpetra::Import.
00836       std::vector<int> exportLIDs (NumExportIDs_);
00837       std::vector<int> exportPIDs (NumExportIDs_);
00838       if (ExportLIDs_ != NULL) {
00839   std::copy (ExportLIDs_, ExportLIDs_ + NumExportIDs_, exportLIDs.begin());
00840   std::copy (ExportPIDs_, ExportPIDs_ + NumExportIDs_, exportPIDs.begin());
00841 
00842   if (sortIDs && NumExportIDs_ > 0) {
00843     int* intCompanions[1]; // Input for Epetra_Util::Sort().
00844     intCompanions[0] = &exportLIDs[0];
00845     Epetra_Util::Sort (true, NumExportIDs_, &exportPIDs[0], 
00846            0, (double**) NULL, 1, intCompanions, 0, 0);
00847   }
00848       }
00849 
00850       os << "exportLIDs     :";
00851       if (ExportLIDs_ == NULL) {
00852   os << " NULL";
00853       } else {
00854   os << " {";
00855   for (int i = 0; i < NumExportIDs_; ++i) {
00856     os << exportLIDs[i];
00857     if (i < NumExportIDs_ - 1) {
00858       os << ", ";
00859     }
00860   }
00861   os << "}";
00862       }
00863       os << std::endl;
00864 
00865       os << "exportImageIDs :";
00866       if (ExportPIDs_ == NULL) {
00867   os << " NULL";
00868       } else {
00869   os << " {";
00870   for (int i = 0; i < NumExportIDs_; ++i) {
00871     os << exportPIDs[i];
00872     if (i < NumExportIDs_ - 1) {
00873       os << ", ";
00874     }
00875   }
00876   os << "}";
00877       }
00878       os << std::endl;
00879 
00880       os << "numSameIDs     : " << NumSameIDs_ << std::endl;
00881       os << "numPermuteIDs  : " << NumPermuteIDs_ << std::endl;
00882       os << "numRemoteIDs   : " << NumRemoteIDs_ << std::endl;
00883       os << "numExportIDs   : " << NumExportIDs_ << std::endl;
00884 
00885       // Epetra keeps NumSend_ and NumRecv_, whereas in Tpetra, these
00886       // are stored in the Distributor object.  This is why we print
00887       // them here.
00888       os << "Number of sends: " << NumSend_ << std::endl;
00889       os << "Number of recvs: " << NumRecv_ << std::endl;
00890     } // if my rank is p
00891 
00892     // A few global barriers give I/O a chance to complete.
00893     comm.Barrier();
00894     comm.Barrier();
00895     comm.Barrier();
00896   } // for each rank p
00897 
00898   const bool printMaps = false;
00899   if (printMaps) {
00900     // The original implementation printed the Maps first.  We moved
00901     // printing the Maps to the end, for easy comparison with the
00902     // output of Tpetra::Import::print().
00903     if (myRank == 0) {
00904       os << std::endl << std::endl << "Source Map:" << std::endl << std::flush;
00905     }
00906     comm.Barrier();
00907     SourceMap_.Print(os);
00908     comm.Barrier();
00909   
00910     if (myRank == 0) {
00911       os << std::endl << std::endl << "Target Map:" << std::endl << std::flush;
00912     }
00913     comm.Barrier();
00914     TargetMap_.Print(os);
00915     comm.Barrier();
00916   }
00917 
00918   if (myRank == 0) {
00919     os << std::endl << std::endl << "Distributor:" << std::endl << std::flush;
00920   }
00921   comm.Barrier();
00922   if (Distor_ == NULL) {
00923     if (myRank == 0) {
00924       os << " is NULL." << std::endl;
00925     }
00926   } else {
00927     Distor_->Print(os); // Printing the Distributor is itself distributed.
00928   }
00929   comm.Barrier();
00930 }
00931 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines