Epetra Package Browser (Single Doxygen Collection) Development
Epetra_Export.cpp
Go to the documentation of this file.
00001 //@HEADER
00002 // ************************************************************************
00003 //
00004 //               Epetra: Linear Algebra Services Package
00005 //                 Copyright 2011 Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ************************************************************************
00040 //@HEADER
00041 
00042 #include "Epetra_ConfigDefs.h"
00043 #include "Epetra_Export.h"
00044 #include "Epetra_BlockMap.h"
00045 #include "Epetra_Distributor.h"
00046 #include "Epetra_Comm.h"
00047 #include "Epetra_Util.h"
00048 #include "Epetra_Import.h"
00049 #include <vector>
00050 
00051 #ifdef HAVE_MPI
00052 #include "Epetra_MpiDistributor.h"
00053 #endif
00054 
00055 
00056 //==============================================================================
00057 // Epetra_Export constructor function for a Epetra_BlockMap object
00058 template<typename int_type>
00059 void Epetra_Export::Construct( const Epetra_BlockMap &  sourceMap, const Epetra_BlockMap & targetMap)
00060 {
00061 
00062   int i;
00063 
00064   // Build three ID lists:
00065   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00066   //              nonidentical ID.
00067   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00068   // NumExportIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be exported.
00069 
00070   int NumSourceIDs = sourceMap.NumMyElements();
00071   int NumTargetIDs = targetMap.NumMyElements();
00072 
00073   int_type *TargetGIDs = 0;
00074   if (NumTargetIDs>0) {
00075     TargetGIDs = new int_type[NumTargetIDs];
00076     targetMap.MyGlobalElements(TargetGIDs);
00077   }
00078 
00079   int_type * SourceGIDs = 0;
00080   if (NumSourceIDs>0) {
00081     SourceGIDs = new int_type[NumSourceIDs];
00082     sourceMap.MyGlobalElements(SourceGIDs);
00083   }
00084 
00085   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00086 
00087   NumSameIDs_ = 0;
00088   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00089 
00090   // Find count of Source IDs that are truly remote and those that are local but permuted
00091 
00092   NumPermuteIDs_ = 0;
00093   NumExportIDs_ = 0;
00094   for (i=NumSameIDs_; i< NumSourceIDs; i++)
00095     if (targetMap.MyGID(SourceGIDs[i])) NumPermuteIDs_++; // Check if Source GID is a local Target GID
00096     else NumExportIDs_++; // If not, then it is remote
00097 
00098   // Define remote and permutation lists
00099 
00100   int_type * ExportGIDs = 0;
00101   if (NumExportIDs_>0) {
00102     ExportLIDs_ = new int[NumExportIDs_];
00103     ExportGIDs = new int_type[NumExportIDs_];
00104   }
00105   if (NumPermuteIDs_>0)  {
00106     PermuteToLIDs_ = new int[NumPermuteIDs_];
00107     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00108   }
00109 
00110   NumPermuteIDs_ = 0;
00111   NumExportIDs_ = 0;
00112   for (i=NumSameIDs_; i< NumSourceIDs; i++) {
00113     if (targetMap.MyGID(SourceGIDs[i])) {
00114       PermuteFromLIDs_[NumPermuteIDs_] = i;
00115       PermuteToLIDs_[NumPermuteIDs_++] = targetMap.LID(SourceGIDs[i]);
00116     }
00117     else {
00118       //NumSend_ +=sourceMap.ElementSize(i); // Count total number of entries to send
00119       NumSend_ +=sourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00120       ExportGIDs[NumExportIDs_] = SourceGIDs[i];
00121       ExportLIDs_[NumExportIDs_++] = i;
00122     }
00123   }
00124 
00125   if ( NumExportIDs_>0 && !sourceMap.DistributedGlobal())
00126     ReportError("Warning in Epetra_Export: Serial Export has remote IDs. (Exporting from Subset of Source Map)", 1);
00127 
00128   // Test for distributed cases
00129   int ierr = 0;
00130 
00131   if (sourceMap.DistributedGlobal()) {
00132 
00133     if (NumExportIDs_>0) ExportPIDs_ = new int[NumExportIDs_];
00134     ierr = targetMap.RemoteIDList(NumExportIDs_, ExportGIDs, ExportPIDs_, 0); // Get remote PIDs
00135     if( ierr ) throw ReportError("Error in Epetra_BlockMap::RemoteIDList", ierr);
00136 
00137     //Get rid of IDs not in Target Map
00138     if(NumExportIDs_>0) {
00139       int cnt = 0;
00140       for( i = 0; i < NumExportIDs_; ++i )
00141   if( ExportPIDs_[i] == -1 ) ++cnt;
00142       if( cnt ) {
00143   int_type * NewExportGIDs = 0;
00144   int * NewExportPIDs = 0;
00145   int * NewExportLIDs = 0;
00146   int cnt1 = NumExportIDs_-cnt;
00147   if (cnt1) {
00148     NewExportGIDs = new int_type[cnt1];
00149     NewExportPIDs = new int[cnt1];
00150     NewExportLIDs = new int[cnt1];
00151   }
00152   cnt = 0;
00153   for( i = 0; i < NumExportIDs_; ++i )
00154     if( ExportPIDs_[i] != -1 ) {
00155       NewExportGIDs[cnt] = ExportGIDs[i];
00156       NewExportPIDs[cnt] = ExportPIDs_[i];
00157       NewExportLIDs[cnt] = ExportLIDs_[i];
00158       ++cnt;
00159           }
00160   assert(cnt==cnt1); // Sanity test
00161   NumExportIDs_ = cnt;
00162   delete [] ExportGIDs;
00163   delete [] ExportPIDs_;
00164   delete [] ExportLIDs_;
00165   ExportGIDs = NewExportGIDs;
00166   ExportPIDs_ = NewExportPIDs;
00167   ExportLIDs_ = NewExportLIDs;
00168   ReportError("Warning in Epetra_Export: Source IDs not found in Target Map (Do you want to export from subset of Source Map?)", 1 );
00169       }
00170     }
00171 
00172     //Make sure Export IDs are ordered by processor
00173     Epetra_Util util;
00174 
00175     if(targetMap.GlobalIndicesLongLong()) {
00176       // FIXME (mfh 11 Jul 2013) This breaks ANSI aliasing rules, if
00177       // int_type != long long.  On some compilers, it results in
00178       // warnings such as this: "dereferencing type-punned pointer
00179       // will break strict-aliasing rules".
00180       util.Sort(true,NumExportIDs_,ExportPIDs_,0,0,1,&ExportLIDs_, 1, (long long **)&ExportGIDs);
00181     }
00182     else if(targetMap.GlobalIndicesInt()) {
00183       int* ptrs[2] = {ExportLIDs_, (int*) ExportGIDs};
00184       util.Sort(true,NumExportIDs_,ExportPIDs_,0,0, 2,&ptrs[0], 0, 0);
00185     }
00186     else {
00187       throw ReportError("Epetra_Import::Epetra_Import: GlobalIndices Internal Error", -1);
00188     }
00189 
00190     Distor_ = sourceMap.Comm().CreateDistributor();
00191 
00192     // Construct list of exports that calling processor needs to send as a result
00193     // of everyone asking for what it needs to receive.
00194 
00195     ierr = Distor_->CreateFromSends( NumExportIDs_, ExportPIDs_, true, NumRemoteIDs_);
00196     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromSends()", ierr);
00197 
00198     // Use comm plan with ExportGIDs to find out who is sending to us and
00199     // get proper ordering of GIDs for remote entries
00200     // (that we will convert to LIDs when done).
00201 
00202     if (NumRemoteIDs_>0) RemoteLIDs_ = new int[NumRemoteIDs_]; // Allocate space for LIDs in target that are
00203     // going to get something from off-processor.
00204     char * cRemoteGIDs = 0; //Do will alloc memory for this object
00205     int LenCRemoteGIDs = 0;
00206     ierr = Distor_->Do(reinterpret_cast<char *> (ExportGIDs),
00207     sizeof( int_type ),
00208     LenCRemoteGIDs,
00209     cRemoteGIDs);
00210     if (ierr) throw ReportError("Error in Epetra_Distributor.Do()", ierr);
00211     int_type * RemoteGIDs = reinterpret_cast<int_type*>(cRemoteGIDs);
00212 
00213     // Remote IDs come in as GIDs, convert to LIDs
00214     for (i=0; i< NumRemoteIDs_; i++) {
00215       RemoteLIDs_[i] = targetMap.LID(RemoteGIDs[i]);
00216       //NumRecv_ += targetMap.ElementSize(RemoteLIDs_[i]); // Count total number of entries to receive
00217       NumRecv_ += targetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00218     }
00219 
00220     if (LenCRemoteGIDs>0) delete [] cRemoteGIDs;
00221   }
00222   if (NumExportIDs_>0) delete [] ExportGIDs;
00223   if (NumTargetIDs>0) delete [] TargetGIDs;
00224   if (NumSourceIDs>0) delete [] SourceGIDs;
00225 
00226   return;
00227 }
00228 
00229 // Epetra_Export constructor for a Epetra_BlockMap object
00230 Epetra_Export::Epetra_Export( const Epetra_BlockMap &  sourceMap, const Epetra_BlockMap & targetMap)
00231   : Epetra_Object("Epetra::Export"),
00232     TargetMap_(targetMap),
00233     SourceMap_(sourceMap),
00234     NumSameIDs_(0),
00235     NumPermuteIDs_(0),
00236     PermuteToLIDs_(0),
00237     PermuteFromLIDs_(0),
00238     NumRemoteIDs_(0),
00239     RemoteLIDs_(0),
00240     NumExportIDs_(0),
00241     ExportLIDs_(0),
00242     ExportPIDs_(0),
00243     NumSend_(0),
00244     NumRecv_(0),
00245     Distor_(0)
00246 {
00247   if(!targetMap.GlobalIndicesTypeMatch(sourceMap))
00248     throw ReportError("Epetra_Export::Epetra_Export: GlobalIndicesTypeMatch failed", -1);
00249 
00250   if(targetMap.GlobalIndicesInt())
00251 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00252     Construct<int>(sourceMap, targetMap);
00253 #else
00254     throw ReportError("Epetra_Export::Epetra_Export: ERROR, GlobalIndicesInt but no API for it.",-1);
00255 #endif
00256   else if(targetMap.GlobalIndicesLongLong())
00257 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00258     Construct<long long>(sourceMap, targetMap);
00259 #else
00260     throw ReportError("Epetra_Export::Epetra_Export: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00261 #endif
00262   else
00263     throw ReportError("Epetra_Export::Epetra_Export: Bad global indices type", -1);
00264 }
00265 
00266 //==============================================================================
00267 // Epetra_Export copy constructor
00268 Epetra_Export::Epetra_Export(const Epetra_Export & Exporter)
00269   : Epetra_Object(Exporter),
00270      TargetMap_(Exporter.TargetMap_),
00271     SourceMap_(Exporter.SourceMap_),
00272     NumSameIDs_(Exporter.NumSameIDs_),
00273     NumPermuteIDs_(Exporter.NumPermuteIDs_),
00274     PermuteToLIDs_(0),
00275     PermuteFromLIDs_(0),
00276     NumRemoteIDs_(Exporter.NumRemoteIDs_),
00277     RemoteLIDs_(0),
00278     NumExportIDs_(Exporter.NumExportIDs_),
00279     ExportLIDs_(0),
00280     ExportPIDs_(0),
00281     NumSend_(Exporter.NumSend_),
00282     NumRecv_(Exporter.NumRecv_),
00283     Distor_(0)
00284 {
00285   int i;
00286   if (NumPermuteIDs_>0) {
00287     PermuteToLIDs_ = new int[NumPermuteIDs_];
00288     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00289     for (i=0; i< NumPermuteIDs_; i++) {
00290       PermuteToLIDs_[i] = Exporter.PermuteToLIDs_[i];
00291       PermuteFromLIDs_[i] = Exporter.PermuteFromLIDs_[i];
00292     }
00293   }
00294 
00295   if (NumRemoteIDs_>0) {
00296     RemoteLIDs_ = new int[NumRemoteIDs_];
00297     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Exporter.RemoteLIDs_[i];
00298   }
00299 
00300   TargetMap().Comm().Barrier();
00301   if (NumExportIDs_>0) {
00302     ExportLIDs_ = new int[NumExportIDs_];
00303     ExportPIDs_ = new int[NumExportIDs_];
00304     for (i=0; i< NumExportIDs_; i++) {
00305       ExportLIDs_[i] = Exporter.ExportLIDs_[i];
00306       ExportPIDs_[i] = Exporter.ExportPIDs_[i];
00307     }
00308   }
00309 
00310   if (Exporter.Distor_!=0) Distor_ = Exporter.Distor_->Clone();
00311 
00312 }
00313 
00314 //==============================================================================
00315 // Epetra_Export destructor
00316 Epetra_Export::~Epetra_Export()
00317 {
00318   if( Distor_ != 0 ) delete Distor_;
00319 
00320   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00321   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00322   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00323 
00324   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by GSPlan
00325   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00326 }
00327 
00328 //==============================================================================
00329 // Epetra_Export pseudo-copy constructor.
00330 Epetra_Export::Epetra_Export(const Epetra_Import& Importer):
00331   TargetMap_(Importer.SourceMap_), //reverse
00332   SourceMap_(Importer.TargetMap_),//reverse
00333   NumSameIDs_(Importer.NumSameIDs_),
00334   NumPermuteIDs_(Importer.NumPermuteIDs_),
00335   PermuteToLIDs_(0),
00336   PermuteFromLIDs_(0),
00337   NumRemoteIDs_(Importer.NumExportIDs_),//reverse
00338   RemoteLIDs_(0),
00339   NumExportIDs_(Importer.NumRemoteIDs_),//reverse
00340   ExportLIDs_(0),
00341   ExportPIDs_(0),
00342   NumSend_(Importer.NumRecv_),//reverse
00343   NumRecv_(Importer.NumSend_),//revsese
00344   Distor_(0)
00345 {
00346   int i;
00347   // Reverse the permutes
00348   if (NumPermuteIDs_>0) {
00349     PermuteToLIDs_   = new int[NumPermuteIDs_];
00350     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00351     for (i=0; i< NumPermuteIDs_; i++) {
00352       PermuteFromLIDs_[i] = Importer.PermuteToLIDs_[i];
00353       PermuteToLIDs_[i]   = Importer.PermuteFromLIDs_[i];
00354     }
00355   }
00356 
00357   // Copy the exports to the remotes
00358   if (NumRemoteIDs_>0) {
00359     RemoteLIDs_ = new int[NumRemoteIDs_];
00360     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Importer.ExportLIDs_[i];
00361   }
00362 
00363   // Copy the remotes to the exports
00364   if (NumExportIDs_>0) {
00365     ExportLIDs_ = new int[NumExportIDs_];
00366     ExportPIDs_ = new int[NumExportIDs_];
00367     for (i=0; i< NumExportIDs_; i++) ExportLIDs_[i] = Importer.RemoteLIDs_[i];
00368 
00369 
00370     // Extract the RemotePIDs from the Distributor
00371 #ifdef HAVE_MPI
00372     Epetra_MpiDistributor *D=dynamic_cast<Epetra_MpiDistributor*>(&Importer.Distributor());
00373     if(!D) throw ReportError("Epetra_Export: Can't have ExportPIDs w/o an Epetra::MpiDistributor.",-1);
00374     int i,j,k;
00375 
00376     // Get the distributor's data
00377     int NumReceives        = D->NumReceives();
00378     const int *ProcsFrom   = D->ProcsFrom();
00379     const int *LengthsFrom = D->LengthsFrom();
00380 
00381     // Now, for each remote ID, record who actually owns it.  This loop follows the operation order in the
00382     // MpiDistributor so it ought to duplicate that effect.
00383     for(i=0,j=0;i<NumReceives;i++){
00384       int pid=ProcsFrom[i];
00385       for(k=0;k<LengthsFrom[i];k++){
00386   ExportPIDs_[j]=pid;
00387   j++;
00388       }
00389     }
00390 #else
00391     throw ReportError("Epetra_Export: Can't have ExportPIDs w/o an Epetra::MpiDistributor.",-2);
00392 #endif
00393   }//end NumExportIDs>0
00394 
00395   if (Importer.Distor_!=0) Distor_ = Importer.Distor_->ReverseClone();
00396 
00397 }
00398 
00399 //=============================================================================
00400 void Epetra_Export::Print(std::ostream & os) const
00401 {
00402   // mfh 05 Jan 2012: The implementation of Print() I found here
00403   // previously didn't print much at all, and it included a message
00404   // saying that it wasn't finished ("Epetra_Export Print needs
00405   // attention!!!!").  What you see below is a port of
00406   // Tpetra::Export::print, which does have a full implementation.
00407   // This should allow a side-by-side comparison of Epetra_Export with
00408   // Tpetra::Export.
00409 
00410   // If true, then copy the array data and sort it before printing.
00411   // Otherwise, leave the data in its original order.
00412   //
00413   // NOTE: Do NOT sort the arrays in place!  Only sort in the copy.
00414   // Epetra depends on the order being preserved, and some arrays'
00415   // orders are coupled.
00416   const bool sortIDs = true;
00417 
00418   const Epetra_Comm& comm = SourceMap_.Comm();
00419   const int myRank = comm.MyPID();
00420   const int numProcs = comm.NumProc();
00421 
00422   if (myRank == 0) {
00423     os << "Export Data Members:" << std::endl;
00424   }
00425   // We don't need a barrier before this for loop, because Proc 0 is
00426   // the first one to do anything in the for loop anyway.
00427   for (int p = 0; p < numProcs; ++p) {
00428     if (myRank == p) {
00429       os << "Image ID       : " << myRank << std::endl;
00430 
00431       os << "permuteFromLIDs:";
00432       if (PermuteFromLIDs_ == NULL) {
00433   os << " NULL";
00434       } else {
00435   std::vector<int> permuteFromLIDs (NumPermuteIDs_);
00436   std::copy (PermuteFromLIDs_, PermuteFromLIDs_ + NumPermuteIDs_,
00437        permuteFromLIDs.begin());
00438   if (sortIDs) {
00439     std::sort (permuteFromLIDs.begin(), permuteFromLIDs.end());
00440   }
00441   os << " {";
00442   for (int i = 0; i < NumPermuteIDs_; ++i) {
00443     os << permuteFromLIDs[i];
00444     if (i < NumPermuteIDs_ - 1) {
00445       os << " ";
00446     }
00447   }
00448   os << "}";
00449       }
00450       os << std::endl;
00451 
00452       os << "permuteToLIDs  :";
00453       if (PermuteToLIDs_ == NULL) {
00454   os << " NULL";
00455       } else {
00456   std::vector<int> permuteToLIDs (NumPermuteIDs_);
00457   std::copy (PermuteToLIDs_, PermuteToLIDs_ + NumPermuteIDs_,
00458        permuteToLIDs.begin());
00459   if (sortIDs) {
00460     std::sort (permuteToLIDs.begin(), permuteToLIDs.end());
00461   }
00462   os << " {";
00463   for (int i = 0; i < NumPermuteIDs_; ++i) {
00464     os << permuteToLIDs[i];
00465     if (i < NumPermuteIDs_ - 1) {
00466       os << " ";
00467     }
00468   }
00469   os << "}";
00470       }
00471       os << std::endl;
00472 
00473       os << "remoteLIDs     :";
00474       if (RemoteLIDs_ == NULL) {
00475   os << " NULL";
00476       } else {
00477   std::vector<int> remoteLIDs (NumRemoteIDs_);
00478   std::copy (RemoteLIDs_, RemoteLIDs_ + NumRemoteIDs_,
00479        remoteLIDs.begin());
00480   if (sortIDs) {
00481     std::sort (remoteLIDs.begin(), remoteLIDs.end());
00482   }
00483   os << " {";
00484   for (int i = 0; i < NumRemoteIDs_; ++i) {
00485     os << remoteLIDs[i];
00486     if (i < NumRemoteIDs_ - 1) {
00487       os << " ";
00488     }
00489   }
00490   os << "}";
00491       }
00492       os << std::endl;
00493 
00494       // If sorting for output, the export LIDs and export PIDs have
00495       // to be sorted together.  We can use Epetra_Util::Sort, using
00496       // the PIDs as the keys to match Tpetra::Export.
00497       std::vector<int> exportLIDs (NumExportIDs_);
00498       std::vector<int> exportPIDs (NumExportIDs_);
00499       if (ExportLIDs_ != NULL) {
00500   std::copy (ExportLIDs_, ExportLIDs_ + NumExportIDs_, exportLIDs.begin());
00501   std::copy (ExportPIDs_, ExportPIDs_ + NumExportIDs_, exportPIDs.begin());
00502 
00503   if (sortIDs && NumExportIDs_ > 0) {
00504     int* intCompanions[1]; // Input for Epetra_Util::Sort().
00505     intCompanions[0] = &exportLIDs[0];
00506     Epetra_Util::Sort (true, NumExportIDs_, &exportPIDs[0],
00507            0, (double**) NULL, 1, intCompanions, 0, 0);
00508   }
00509       }
00510 
00511       os << "exportLIDs     :";
00512       if (ExportLIDs_ == NULL) {
00513   os << " NULL";
00514       } else {
00515   os << " {";
00516   for (int i = 0; i < NumExportIDs_; ++i) {
00517     os << exportLIDs[i];
00518     if (i < NumExportIDs_ - 1) {
00519       os << " ";
00520     }
00521   }
00522   os << "}";
00523       }
00524       os << std::endl;
00525 
00526       os << "exportImageIDs :";
00527       if (ExportPIDs_ == NULL) {
00528   os << " NULL";
00529       } else {
00530   os << " {";
00531   for (int i = 0; i < NumExportIDs_; ++i) {
00532     os << exportPIDs[i];
00533     if (i < NumExportIDs_ - 1) {
00534       os << " ";
00535     }
00536   }
00537   os << "}";
00538       }
00539       os << std::endl;
00540 
00541       os << "numSameIDs     : " << NumSameIDs_ << std::endl;
00542       os << "numPermuteIDs  : " << NumPermuteIDs_ << std::endl;
00543       os << "numRemoteIDs   : " << NumRemoteIDs_ << std::endl;
00544       os << "numExportIDs   : " << NumExportIDs_ << std::endl;
00545 
00546       // Epetra keeps NumSend_ and NumRecv_, whereas in Tpetra, these
00547       // are stored in the Distributor object.  This is why we print
00548       // them here.
00549       os << "Number of sends: " << NumSend_ << std::endl;
00550       os << "Number of recvs: " << NumRecv_ << std::endl;
00551     } // if my rank is p
00552 
00553     // A few global barriers give I/O a chance to complete.
00554     comm.Barrier();
00555     comm.Barrier();
00556     comm.Barrier();
00557   } // for each rank p
00558 
00559   // The original implementation printed the Maps first.  We moved
00560   // printing the Maps to the end, for easy comparison with the output
00561   // of Tpetra::Export::print().
00562   if (myRank == 0) {
00563     os << std::endl << std::endl << "Source Map:" << std::endl << std::flush;
00564   }
00565   comm.Barrier();
00566   SourceMap_.Print(os);
00567   comm.Barrier();
00568 
00569   if (myRank == 0) {
00570     os << std::endl << std::endl << "Target Map:" << std::endl << std::flush;
00571   }
00572   comm.Barrier();
00573   TargetMap_.Print(os);
00574   comm.Barrier();
00575 
00576   if (myRank == 0) {
00577     os << std::endl << std::endl << "Distributor:" << std::endl << std::flush;
00578   }
00579   comm.Barrier();
00580   if (Distor_ == NULL) {
00581     if (myRank == 0) {
00582       os << " is NULL." << std::endl;
00583     }
00584   } else {
00585     Distor_->Print(os); // Printing the Distributor is itself distributed.
00586   }
00587   comm.Barrier();
00588 }
00589 
00590 //----------------------------------------------------------------------------
00591 Epetra_Export& Epetra_Export::operator=(const Epetra_Export& src)
00592 {
00593   (void)src;
00594   //not currently supported
00595   bool throw_err = true;
00596   if (throw_err) {
00597     throw ReportError("Epetra_Export::operator= not supported.",-1);
00598   }
00599   return(*this);
00600 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines