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 2001 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_Export.h"
00043 #include "Epetra_BlockMap.h"
00044 #include "Epetra_Distributor.h"
00045 #include "Epetra_Comm.h"
00046 #include "Epetra_Util.h"
00047 
00048 //==============================================================================
00049 // Epetra_Export constructor for a Epetra_BlockMap object
00050 Epetra_Export::Epetra_Export( const Epetra_BlockMap &  SourceMap, const Epetra_BlockMap & TargetMap)
00051   : Epetra_Object("Epetra::Export"), 
00052     TargetMap_(TargetMap),
00053     SourceMap_(SourceMap),
00054     NumSameIDs_(0),
00055     NumPermuteIDs_(0),
00056     PermuteToLIDs_(0),
00057     PermuteFromLIDs_(0),
00058     NumRemoteIDs_(0),
00059     RemoteLIDs_(0),
00060     NumExportIDs_(0),
00061     ExportLIDs_(0),
00062     ExportPIDs_(0),
00063     NumSend_(0),
00064     NumRecv_(0),
00065     Distor_(0)
00066 {
00067 
00068   int i;
00069 
00070   // Build three ID lists:
00071   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00072   //              nonidentical ID.
00073   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00074   // NumExportIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be exported.
00075 
00076   int NumSourceIDs = SourceMap.NumMyElements();
00077   int NumTargetIDs = TargetMap.NumMyElements();
00078 
00079   int *TargetGIDs = 0;
00080   if (NumTargetIDs>0) {
00081     TargetGIDs = new int[NumTargetIDs];
00082     TargetMap.MyGlobalElements(TargetGIDs);
00083   }
00084 
00085   int * SourceGIDs = 0;
00086   if (NumSourceIDs>0) {
00087     SourceGIDs = new int[NumSourceIDs];
00088     SourceMap.MyGlobalElements(SourceGIDs);
00089   }
00090 
00091   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00092 
00093   NumSameIDs_ = 0;
00094   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00095 
00096   // Find count of Source IDs that are truly remote and those that are local but permuted
00097 
00098   NumPermuteIDs_ = 0;
00099   NumExportIDs_ = 0;
00100   for (i=NumSameIDs_; i< NumSourceIDs; i++) 
00101     if (TargetMap.MyGID(SourceGIDs[i])) NumPermuteIDs_++; // Check if Source GID is a local Target GID
00102     else NumExportIDs_++; // If not, then it is remote
00103 
00104   // Define remote and permutation lists
00105 
00106   int * ExportGIDs = 0;
00107   if (NumExportIDs_>0) {
00108     ExportLIDs_ = new int[NumExportIDs_];
00109     ExportGIDs = new int[NumExportIDs_];
00110   }
00111   if (NumPermuteIDs_>0)  {
00112     PermuteToLIDs_ = new int[NumPermuteIDs_];
00113     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00114   }
00115 
00116   NumPermuteIDs_ = 0;
00117   NumExportIDs_ = 0;
00118   for (i=NumSameIDs_; i< NumSourceIDs; i++) {
00119     if (TargetMap.MyGID(SourceGIDs[i])) {
00120       PermuteFromLIDs_[NumPermuteIDs_] = i;
00121       PermuteToLIDs_[NumPermuteIDs_++] = TargetMap.LID(SourceGIDs[i]);
00122     }
00123     else {
00124       //NumSend_ +=SourceMap.ElementSize(i); // Count total number of entries to send
00125       NumSend_ +=SourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00126       ExportGIDs[NumExportIDs_] = SourceGIDs[i];
00127       ExportLIDs_[NumExportIDs_++] = i;
00128     }
00129   }
00130      
00131   if ( NumExportIDs_>0 && !SourceMap.DistributedGlobal()) 
00132     ReportError("Warning in Epetra_Export: Serial Export has remote IDs. (Exporting from Subset of Source Map)", 1);
00133 
00134   // Test for distributed cases
00135   int ierr = 0;
00136 
00137   if (SourceMap.DistributedGlobal()) {
00138 
00139     if (NumExportIDs_>0) ExportPIDs_ = new int[NumExportIDs_];
00140     ierr = TargetMap.RemoteIDList(NumExportIDs_, ExportGIDs, ExportPIDs_, 0); // Get remote PIDs
00141     if( ierr ) throw ReportError("Error in Epetra_BlockMap::RemoteIDList", ierr);
00142 
00143     //Get rid of IDs not in Target Map
00144     if(NumExportIDs_>0) {
00145       int cnt = 0;
00146       for( i = 0; i < NumExportIDs_; ++i )
00147   if( ExportPIDs_[i] == -1 ) ++cnt;
00148       if( cnt ) {
00149   int * NewExportGIDs = 0;
00150   int * NewExportPIDs = 0;
00151   int * NewExportLIDs = 0;
00152   int cnt1 = NumExportIDs_-cnt;
00153   if (cnt1) {
00154     NewExportGIDs = new int[cnt1];
00155     NewExportPIDs = new int[cnt1];
00156     NewExportLIDs = new int[cnt1];
00157   }
00158   cnt = 0;
00159   for( i = 0; i < NumExportIDs_; ++i )
00160     if( ExportPIDs_[i] != -1 ) {
00161       NewExportGIDs[cnt] = ExportGIDs[i];
00162       NewExportPIDs[cnt] = ExportPIDs_[i];
00163       NewExportLIDs[cnt] = ExportLIDs_[i];
00164       ++cnt;
00165           }
00166   assert(cnt==cnt1); // Sanity test
00167   NumExportIDs_ = cnt;
00168   delete [] ExportGIDs;
00169   delete [] ExportPIDs_;
00170   delete [] ExportLIDs_;
00171   ExportGIDs = NewExportGIDs;
00172   ExportPIDs_ = NewExportPIDs;
00173   ExportLIDs_ = NewExportLIDs;
00174   ReportError("Warning in Epetra_Export: Source IDs not found in Target Map (Do you want to export from subset of Source Map?)", 1 );
00175       }
00176     }
00177     
00178     //Make sure Export IDs are ordered by processor
00179     Epetra_Util util;
00180     int * tmpPtr[2];
00181     tmpPtr[0] = ExportLIDs_, tmpPtr[1] = ExportGIDs;
00182     util.Sort(true,NumExportIDs_,ExportPIDs_,0,0,2,tmpPtr);
00183 
00184     Distor_ = SourceMap.Comm().CreateDistributor();
00185     
00186     // Construct list of exports that calling processor needs to send as a result
00187     // of everyone asking for what it needs to receive.
00188     
00189     ierr = Distor_->CreateFromSends( NumExportIDs_, ExportPIDs_, true, NumRemoteIDs_);
00190     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromSends()", ierr);
00191     
00192     // Use comm plan with ExportGIDs to find out who is sending to us and
00193     // get proper ordering of GIDs for remote entries 
00194     // (that we will convert to LIDs when done).
00195     
00196     if (NumRemoteIDs_>0) RemoteLIDs_ = new int[NumRemoteIDs_]; // Allocate space for LIDs in target that are
00197     // going to get something from off-processor.
00198     char * cRemoteGIDs = 0; //Do will alloc memory for this object
00199     int LenCRemoteGIDs = 0;
00200     ierr = Distor_->Do(reinterpret_cast<char *> (ExportGIDs), 
00201     sizeof( int ),
00202     LenCRemoteGIDs,
00203     cRemoteGIDs);
00204     if (ierr) throw ReportError("Error in Epetra_Distributor.Do()", ierr);
00205     int * RemoteGIDs = reinterpret_cast<int*>(cRemoteGIDs);
00206 
00207     // Remote IDs come in as GIDs, convert to LIDs
00208     for (i=0; i< NumRemoteIDs_; i++) {
00209       RemoteLIDs_[i] = TargetMap.LID(RemoteGIDs[i]);
00210       //NumRecv_ += TargetMap.ElementSize(RemoteLIDs_[i]); // Count total number of entries to receive
00211       NumRecv_ += TargetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00212     }
00213 
00214     if (NumExportIDs_>0) delete [] ExportGIDs;
00215     if (LenCRemoteGIDs>0) delete [] cRemoteGIDs;
00216   }
00217   if (NumTargetIDs>0) delete [] TargetGIDs;
00218   if (NumSourceIDs>0) delete [] SourceGIDs;
00219   
00220   return;
00221 }
00222 
00223 //==============================================================================
00224 // Epetra_Export copy constructor 
00225 Epetra_Export::Epetra_Export(const Epetra_Export & Exporter)
00226   : Epetra_Object(Exporter), 
00227      TargetMap_(Exporter.TargetMap_),
00228     SourceMap_(Exporter.SourceMap_),
00229     NumSameIDs_(Exporter.NumSameIDs_),
00230     NumPermuteIDs_(Exporter.NumPermuteIDs_),
00231     PermuteToLIDs_(0),
00232     PermuteFromLIDs_(0),
00233     NumRemoteIDs_(Exporter.NumRemoteIDs_),
00234     RemoteLIDs_(0),
00235     NumExportIDs_(Exporter.NumExportIDs_),
00236     ExportLIDs_(0),
00237     ExportPIDs_(0),
00238     NumSend_(Exporter.NumSend_),
00239     NumRecv_(Exporter.NumRecv_),
00240     Distor_(0)
00241 {
00242   int i;
00243   if (NumPermuteIDs_>0) {
00244     PermuteToLIDs_ = new int[NumPermuteIDs_];
00245     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00246     for (i=0; i< NumPermuteIDs_; i++) {
00247       PermuteToLIDs_[i] = Exporter.PermuteToLIDs_[i];
00248       PermuteFromLIDs_[i] = Exporter.PermuteFromLIDs_[i];
00249     }
00250   }
00251 
00252   if (NumRemoteIDs_>0) {
00253     RemoteLIDs_ = new int[NumRemoteIDs_];
00254     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Exporter.RemoteLIDs_[i];
00255   }
00256 
00257   TargetMap().Comm().Barrier();
00258   if (NumExportIDs_>0) {
00259     ExportLIDs_ = new int[NumExportIDs_];
00260     ExportPIDs_ = new int[NumExportIDs_];
00261     for (i=0; i< NumExportIDs_; i++) {
00262       ExportLIDs_[i] = Exporter.ExportLIDs_[i];
00263       ExportPIDs_[i] = Exporter.ExportPIDs_[i];
00264     }
00265   }
00266 
00267   if (Exporter.Distor_!=0) Distor_ = Exporter.Distor_->Clone();
00268 
00269 }
00270 
00271 //==============================================================================
00272 // Epetra_Export destructor 
00273 Epetra_Export::~Epetra_Export()
00274 {
00275   if( Distor_ != 0 ) delete Distor_;
00276 
00277   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00278   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00279   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00280 
00281   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by GSPlan
00282   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00283 }
00284 //=============================================================================
00285 void Epetra_Export::Print(ostream & os) const
00286 {
00287 
00288   os << endl << endl << "Source Map:" << endl << endl;
00289   SourceMap_.Print(os);
00290   
00291   os << endl << endl << "Target Map:" << endl << endl;
00292   TargetMap_.Print(os);
00293   
00294   os << endl << endl << "Distributor:" << endl << endl;
00295   if (Distor_==0) os << "  Is empty...." << endl;
00296   else Distor_->Print(os);
00297   
00298   os << "Number of Same IDs = " << NumSameIDs_ << endl;
00299   os << "Number of Permute IDs = " << NumPermuteIDs_ << endl;
00300   os << "Number of Export IDs = " << NumExportIDs_ << endl;
00301   
00302   os << "Epetra_Export Print Needs attention!!!!" << endl;
00303   return;
00304 }
00305 
00306 //----------------------------------------------------------------------------
00307 Epetra_Export& Epetra_Export::operator=(const Epetra_Export& src)
00308 {
00309   (void)src;
00310   //not currently supported
00311   bool throw_err = true;
00312   if (throw_err) {
00313     throw ReportError("Epetra_Export::operator= not supported.",-1);
00314   }
00315   return(*this);
00316 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines