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 terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ************************************************************************
00027 //@HEADER
00028 
00029 #include "Epetra_Export.h"
00030 #include "Epetra_BlockMap.h"
00031 #include "Epetra_Distributor.h"
00032 #include "Epetra_Comm.h"
00033 #include "Epetra_Util.h"
00034 
00035 //==============================================================================
00036 // Epetra_Export constructor for a Epetra_BlockMap object
00037 Epetra_Export::Epetra_Export( const Epetra_BlockMap &  SourceMap, const Epetra_BlockMap & TargetMap)
00038   : Epetra_Object("Epetra::Export"), 
00039     TargetMap_(TargetMap),
00040     SourceMap_(SourceMap),
00041     NumSameIDs_(0),
00042     NumPermuteIDs_(0),
00043     PermuteToLIDs_(0),
00044     PermuteFromLIDs_(0),
00045     NumRemoteIDs_(0),
00046     RemoteLIDs_(0),
00047     NumExportIDs_(0),
00048     ExportLIDs_(0),
00049     ExportPIDs_(0),
00050     NumSend_(0),
00051     NumRecv_(0),
00052     Distor_(0)
00053 {
00054 
00055   int i;
00056 
00057   // Build three ID lists:
00058   // NumSameIDs - Number of IDs in TargetMap and SourceMap that are identical, up to the first
00059   //              nonidentical ID.
00060   // NumPermuteIDs - Number of IDs in SourceMap that must be indirectly loaded but are on this processor.
00061   // NumExportIDs - Number of IDs that are in SourceMap but not in TargetMap, and thus must be exported.
00062 
00063   int NumSourceIDs = SourceMap.NumMyElements();
00064   int NumTargetIDs = TargetMap.NumMyElements();
00065 
00066   int *TargetGIDs = 0;
00067   if (NumTargetIDs>0) {
00068     TargetGIDs = new int[NumTargetIDs];
00069     TargetMap.MyGlobalElements(TargetGIDs);
00070   }
00071 
00072   int * SourceGIDs = 0;
00073   if (NumSourceIDs>0) {
00074     SourceGIDs = new int[NumSourceIDs];
00075     SourceMap.MyGlobalElements(SourceGIDs);
00076   }
00077 
00078   int MinIDs = EPETRA_MIN(NumSourceIDs, NumTargetIDs);
00079 
00080   NumSameIDs_ = 0;
00081   for (i=0; i< MinIDs; i++) if (TargetGIDs[i]==SourceGIDs[i]) NumSameIDs_++; else break;
00082 
00083   // Find count of Source IDs that are truly remote and those that are local but permuted
00084 
00085   NumPermuteIDs_ = 0;
00086   NumExportIDs_ = 0;
00087   for (i=NumSameIDs_; i< NumSourceIDs; i++) 
00088     if (TargetMap.MyGID(SourceGIDs[i])) NumPermuteIDs_++; // Check if Source GID is a local Target GID
00089     else NumExportIDs_++; // If not, then it is remote
00090 
00091   // Define remote and permutation lists
00092 
00093   int * ExportGIDs = 0;
00094   if (NumExportIDs_>0) {
00095     ExportLIDs_ = new int[NumExportIDs_];
00096     ExportGIDs = new int[NumExportIDs_];
00097   }
00098   if (NumPermuteIDs_>0)  {
00099     PermuteToLIDs_ = new int[NumPermuteIDs_];
00100     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00101   }
00102 
00103   NumPermuteIDs_ = 0;
00104   NumExportIDs_ = 0;
00105   for (i=NumSameIDs_; i< NumSourceIDs; i++) {
00106     if (TargetMap.MyGID(SourceGIDs[i])) {
00107       PermuteFromLIDs_[NumPermuteIDs_] = i;
00108       PermuteToLIDs_[NumPermuteIDs_++] = TargetMap.LID(SourceGIDs[i]);
00109     }
00110     else {
00111       //NumSend_ +=SourceMap.ElementSize(i); // Count total number of entries to send
00112       NumSend_ +=SourceMap.MaxElementSize(); // Count total number of entries to send (currently need max)
00113       ExportGIDs[NumExportIDs_] = SourceGIDs[i];
00114       ExportLIDs_[NumExportIDs_++] = i;
00115     }
00116   }
00117      
00118   if ( NumExportIDs_>0 && !SourceMap.DistributedGlobal()) 
00119     ReportError("Warning in Epetra_Export: Serial Export has remote IDs. (Exporting from Subset of Source Map)", 1);
00120 
00121   // Test for distributed cases
00122   int ierr = 0;
00123 
00124   if (SourceMap.DistributedGlobal()) {
00125 
00126     if (NumExportIDs_>0) ExportPIDs_ = new int[NumExportIDs_];
00127     ierr = TargetMap.RemoteIDList(NumExportIDs_, ExportGIDs, ExportPIDs_, 0); // Get remote PIDs
00128     if( ierr ) throw ReportError("Error in Epetra_BlockMap::RemoteIDList", ierr);
00129 
00130     //Get rid of IDs not in Target Map
00131     if(NumExportIDs_>0) {
00132       int cnt = 0;
00133       for( i = 0; i < NumExportIDs_; ++i )
00134   if( ExportPIDs_[i] == -1 ) ++cnt;
00135       if( cnt ) {
00136   int * NewExportGIDs = 0;
00137   int * NewExportPIDs = 0;
00138   int * NewExportLIDs = 0;
00139   int cnt1 = NumExportIDs_-cnt;
00140   if (cnt1) {
00141     NewExportGIDs = new int[cnt1];
00142     NewExportPIDs = new int[cnt1];
00143     NewExportLIDs = new int[cnt1];
00144   }
00145   cnt = 0;
00146   for( i = 0; i < NumExportIDs_; ++i )
00147     if( ExportPIDs_[i] != -1 ) {
00148       NewExportGIDs[cnt] = ExportGIDs[i];
00149       NewExportPIDs[cnt] = ExportPIDs_[i];
00150       NewExportLIDs[cnt] = ExportLIDs_[i];
00151       ++cnt;
00152           }
00153   assert(cnt==cnt1); // Sanity test
00154   NumExportIDs_ = cnt;
00155   delete [] ExportGIDs;
00156   delete [] ExportPIDs_;
00157   delete [] ExportLIDs_;
00158   ExportGIDs = NewExportGIDs;
00159   ExportPIDs_ = NewExportPIDs;
00160   ExportLIDs_ = NewExportLIDs;
00161   ReportError("Warning in Epetra_Export: Source IDs not found in Target Map (Do you want to export from subset of Source Map?)", 1 );
00162       }
00163     }
00164     
00165     //Make sure Export IDs are ordered by processor
00166     Epetra_Util util;
00167     int * tmpPtr[2];
00168     tmpPtr[0] = ExportLIDs_, tmpPtr[1] = ExportGIDs;
00169     util.Sort(true,NumExportIDs_,ExportPIDs_,0,0,2,tmpPtr);
00170 
00171     Distor_ = SourceMap.Comm().CreateDistributor();
00172     
00173     // Construct list of exports that calling processor needs to send as a result
00174     // of everyone asking for what it needs to receive.
00175     
00176     ierr = Distor_->CreateFromSends( NumExportIDs_, ExportPIDs_, true, NumRemoteIDs_);
00177     if (ierr!=0) throw ReportError("Error in Epetra_Distributor.CreateFromSends()", ierr);
00178     
00179     // Use comm plan with ExportGIDs to find out who is sending to us and
00180     // get proper ordering of GIDs for remote entries 
00181     // (that we will convert to LIDs when done).
00182     
00183     if (NumRemoteIDs_>0) RemoteLIDs_ = new int[NumRemoteIDs_]; // Allocate space for LIDs in target that are
00184     // going to get something from off-processor.
00185     char * cRemoteGIDs = 0; //Do will alloc memory for this object
00186     int LenCRemoteGIDs = 0;
00187     ierr = Distor_->Do(reinterpret_cast<char *> (ExportGIDs), 
00188     sizeof( int ),
00189     LenCRemoteGIDs,
00190     cRemoteGIDs);
00191     if (ierr) throw ReportError("Error in Epetra_Distributor.Do()", ierr);
00192     int * RemoteGIDs = reinterpret_cast<int*>(cRemoteGIDs);
00193 
00194     // Remote IDs come in as GIDs, convert to LIDs
00195     for (i=0; i< NumRemoteIDs_; i++) {
00196       RemoteLIDs_[i] = TargetMap.LID(RemoteGIDs[i]);
00197       //NumRecv_ += TargetMap.ElementSize(RemoteLIDs_[i]); // Count total number of entries to receive
00198       NumRecv_ += TargetMap.MaxElementSize(); // Count total number of entries to receive (currently need max)
00199     }
00200 
00201     if (NumExportIDs_>0) delete [] ExportGIDs;
00202     if (LenCRemoteGIDs>0) delete [] cRemoteGIDs;
00203   }
00204   if (NumTargetIDs>0) delete [] TargetGIDs;
00205   if (NumSourceIDs>0) delete [] SourceGIDs;
00206   
00207   return;
00208 }
00209 
00210 //==============================================================================
00211 // Epetra_Export copy constructor 
00212 Epetra_Export::Epetra_Export(const Epetra_Export & Exporter)
00213   : Epetra_Object(Exporter), 
00214      TargetMap_(Exporter.TargetMap_),
00215     SourceMap_(Exporter.SourceMap_),
00216     NumSameIDs_(Exporter.NumSameIDs_),
00217     NumPermuteIDs_(Exporter.NumPermuteIDs_),
00218     PermuteToLIDs_(0),
00219     PermuteFromLIDs_(0),
00220     NumRemoteIDs_(Exporter.NumRemoteIDs_),
00221     RemoteLIDs_(0),
00222     NumExportIDs_(Exporter.NumExportIDs_),
00223     ExportLIDs_(0),
00224     ExportPIDs_(0),
00225     NumSend_(Exporter.NumSend_),
00226     NumRecv_(Exporter.NumRecv_),
00227     Distor_(0)
00228 {
00229   int i;
00230   if (NumPermuteIDs_>0) {
00231     PermuteToLIDs_ = new int[NumPermuteIDs_];
00232     PermuteFromLIDs_ = new int[NumPermuteIDs_];
00233     for (i=0; i< NumPermuteIDs_; i++) {
00234       PermuteToLIDs_[i] = Exporter.PermuteToLIDs_[i];
00235       PermuteFromLIDs_[i] = Exporter.PermuteFromLIDs_[i];
00236     }
00237   }
00238 
00239   if (NumRemoteIDs_>0) {
00240     RemoteLIDs_ = new int[NumRemoteIDs_];
00241     for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Exporter.RemoteLIDs_[i];
00242   }
00243 
00244   TargetMap().Comm().Barrier();
00245   if (NumExportIDs_>0) {
00246     ExportLIDs_ = new int[NumExportIDs_];
00247     ExportPIDs_ = new int[NumExportIDs_];
00248     for (i=0; i< NumExportIDs_; i++) {
00249       ExportLIDs_[i] = Exporter.ExportLIDs_[i];
00250       ExportPIDs_[i] = Exporter.ExportPIDs_[i];
00251     }
00252   }
00253 
00254   if (Exporter.Distor_!=0) Distor_ = Exporter.Distor_->Clone();
00255 
00256 }
00257 
00258 //==============================================================================
00259 // Epetra_Export destructor 
00260 Epetra_Export::~Epetra_Export()
00261 {
00262   if( Distor_ != 0 ) delete Distor_;
00263 
00264   if (RemoteLIDs_ != 0) delete [] RemoteLIDs_;
00265   if (PermuteToLIDs_ != 0) delete [] PermuteToLIDs_;
00266   if (PermuteFromLIDs_ != 0) delete [] PermuteFromLIDs_;
00267 
00268   if( ExportPIDs_ != 0 ) delete [] ExportPIDs_; // These were created by GSPlan
00269   if( ExportLIDs_ != 0 ) delete [] ExportLIDs_;
00270 }
00271 //=============================================================================
00272 void Epetra_Export::Print(ostream & os) const
00273 {
00274 
00275   os << endl << endl << "Source Map:" << endl << endl;
00276   SourceMap_.Print(os);
00277   
00278   os << endl << endl << "Target Map:" << endl << endl;
00279   TargetMap_.Print(os);
00280   
00281   os << endl << endl << "Distributor:" << endl << endl;
00282   if (Distor_==0) os << "  Is empty...." << endl;
00283   else Distor_->Print(os);
00284   
00285   os << "Number of Same IDs = " << NumSameIDs_ << endl;
00286   os << "Number of Permute IDs = " << NumPermuteIDs_ << endl;
00287   os << "Number of Export IDs = " << NumExportIDs_ << endl;
00288   
00289   os << "Epetra_Export Print Needs attention!!!!" << endl;
00290   return;
00291 }
00292 
00293 //----------------------------------------------------------------------------
00294 Epetra_Export& Epetra_Export::operator=(const Epetra_Export& src)
00295 {
00296   (void)src;
00297   //not currently supported
00298   bool throw_err = true;
00299   if (throw_err) {
00300     throw ReportError("Epetra_Export::operator= not supported.",-1);
00301   }
00302   return(*this);
00303 }

Generated on Wed May 12 21:41:05 2010 for Epetra Package Browser (Single Doxygen Collection) by  doxygen 1.4.7