Epetra Package Browser (Single Doxygen Collection) Development
Epetra_BasicDirectory.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 #include "Epetra_BasicDirectory.h"
00044 #include "Epetra_BlockMap.h"
00045 #include "Epetra_Map.h"
00046 #include "Epetra_Comm.h"
00047 #include "Epetra_Distributor.h"
00048 #include "Epetra_Util.h"
00049 
00050 //==============================================================================
00051 // Epetra_BasicDirectory constructor for a Epetra_BlockMap object
00052 Epetra_BasicDirectory::Epetra_BasicDirectory(const Epetra_BlockMap & Map)
00053   : DirectoryMap_(0),
00054     ProcList_(0),
00055     ProcListLists_(0),
00056     ProcListLens_(0),
00057     numProcLists_(0),
00058     entryOnMultipleProcs_(false),
00059     LocalIndexList_(0),
00060     SizeList_(0),
00061     SizeIsConst_(true),
00062     AllMinGIDs_(0)
00063 {
00064   // Test for simple cases
00065 
00066   // Uniprocessor and local map cases (Nothing to set up)
00067 
00068   if (!(Map.DistributedGlobal())) return;
00069 
00070   // Linear Map case
00071 
00072   else if (Map.LinearMap()) {
00073 
00074     // Build a list of the Minimum global ids for all processors on each processor.
00075     // Since the map is linear, we know that all GIDs are contiguous on each processor
00076     // and can be found using the MinGIDs.
00077 
00078     int NumProc = Map.Comm().NumProc();
00079     AllMinGIDs_ = new int[NumProc+1];
00080     int MinMyGID = Map.MinMyGID();
00081     Map.Comm().GatherAll(&MinMyGID, AllMinGIDs_, 1);
00082     AllMinGIDs_[NumProc] = 1 + Map.MaxAllGID(); // Set max cap
00083   }
00084 
00085   // General case.  Need to build a directory via calls to communication functions
00086   else {
00087     
00088     int flag = Generate(Map);
00089     assert(flag==0);
00090   }
00091 }
00092 
00093 //==============================================================================
00094 // Epetra_BasicDirectory copy constructor
00095 Epetra_BasicDirectory::Epetra_BasicDirectory(const Epetra_BasicDirectory & Directory)
00096   : DirectoryMap_(0),
00097     ProcList_(0),
00098     ProcListLists_(0),
00099     ProcListLens_(0),
00100     numProcLists_(0),
00101     entryOnMultipleProcs_(false),
00102     LocalIndexList_(0),
00103     SizeList_(0),
00104     SizeIsConst_(Directory.SizeIsConst_),
00105     AllMinGIDs_(0)
00106 {
00107   if (Directory.DirectoryMap_!=0) DirectoryMap_ = new Epetra_Map(Directory.DirectoryMap());
00108 
00109   int Dir_NumMyElements = DirectoryMap_->NumMyElements();
00110 
00111   if (Directory.ProcList_!=0) {
00112     ProcList_ = new int[Dir_NumMyElements];
00113     for (int i=0; i<Dir_NumMyElements; i++) ProcList_[i] = Directory.ProcList_[i];
00114   }
00115   if (Directory.LocalIndexList_!=0) {
00116     LocalIndexList_ = new int[Dir_NumMyElements];
00117     for (int i=0; i<Dir_NumMyElements; i++) LocalIndexList_[i] = Directory.LocalIndexList_[i];
00118     }
00119   if (Directory.SizeList_!=0) {
00120     SizeList_ = new int[Dir_NumMyElements];
00121     for (int i=0; i<Dir_NumMyElements; i++) SizeList_[i] = Directory.SizeList_[i];
00122     }
00123   if (Directory.AllMinGIDs_!=0) {
00124     int NumProc = DirectoryMap_->Comm().NumProc();
00125     AllMinGIDs_ = new int[NumProc+1];
00126     for (int i=0; i<NumProc+1; i++) AllMinGIDs_[i] = Directory.AllMinGIDs_[i];
00127     }
00128 
00129   if (Directory.numProcLists_ > 0) {
00130     int num = Directory.numProcLists_;
00131     ProcListLens_ = new int[num];
00132     ProcListLists_ = new int*[num];
00133     numProcLists_ = num;
00134 
00135     for(int i=0; i<num; ++i) {
00136       int len = Directory.ProcListLens_[i];
00137       ProcListLens_[i] = len;
00138 
00139       if (len > 0) {
00140   ProcListLists_[i] = new int[len];
00141   const int* dir_list = Directory.ProcListLists_[i];
00142   for(int j=0; j<len; ++j) {
00143     ProcListLists_[i][j] = dir_list[j];
00144   }
00145       }
00146       else ProcListLists_[i] = 0;
00147     }
00148   }
00149 
00150   entryOnMultipleProcs_ = Directory.entryOnMultipleProcs_;
00151 }
00152 
00153 //==============================================================================
00154 // Epetra_BasicDirectory destructor 
00155 Epetra_BasicDirectory::~Epetra_BasicDirectory()
00156 {
00157   if (numProcLists_>0) {
00158     for(int i=0; i<numProcLists_; ++i) {
00159       if (ProcListLens_[i] > 0) delete [] ProcListLists_[i];
00160     }
00161     delete [] ProcListLists_; ProcListLists_ = 0;
00162     delete [] ProcListLens_;  ProcListLens_ = 0;
00163     numProcLists_ = 0;
00164   }
00165 
00166   if( DirectoryMap_ != 0 ) delete DirectoryMap_;
00167   if( ProcList_ != 0 ) delete [] ProcList_;
00168   if( LocalIndexList_ != 0 ) delete [] LocalIndexList_;
00169   if( SizeList_ != 0 ) delete [] SizeList_;
00170   if( AllMinGIDs_ != 0 ) delete [] AllMinGIDs_;
00171 
00172   DirectoryMap_ = 0;
00173   ProcList_ = 0 ;
00174   LocalIndexList_ = 0;
00175   SizeList_ = 0;
00176   AllMinGIDs_ = 0;
00177 }
00178 
00179 //==============================================================================
00180 void Epetra_BasicDirectory::create_ProcListArrays()
00181 {
00182   numProcLists_ = DirectoryMap_->NumMyElements();
00183   ProcListLens_ = new int[numProcLists_];
00184   ProcListLists_ = new int*[numProcLists_];
00185 
00186   for(int i=0; i<numProcLists_; ++i) {
00187     ProcListLens_[i] = 0;
00188     ProcListLists_[i] = 0;
00189   }
00190 }
00191 
00192 //==============================================================================
00193 void Epetra_BasicDirectory::addProcToList(int proc, int LID)
00194 {
00195   int insertPoint = -1;
00196   int index = Epetra_Util_binary_search(proc, ProcListLists_[LID],
00197             ProcListLens_[LID], insertPoint);
00198   if (index < 0) {
00199     int tmp = ProcListLens_[LID];
00200     Epetra_Util_insert(proc, insertPoint, ProcListLists_[LID],
00201            ProcListLens_[LID], tmp, 1);
00202   }
00203 }
00204 
00205 //==============================================================================
00206 // Generate: Generates Directory Tables
00207 int Epetra_BasicDirectory::Generate(const Epetra_BlockMap& Map)
00208 {
00209   int i;
00210   SizeIsConst_ = Map.ConstantElementSize();
00211   int MinAllGID = Map.MinAllGID();
00212   int MaxAllGID = Map.MaxAllGID();
00213   // DirectoryMap will have a range of elements from the minimum to the maximum
00214   // GID of the user map, and an IndexBase of MinAllGID from the user map
00215   int Dir_NumGlobalElements = MaxAllGID - MinAllGID + 1;
00216 
00217   // Create a uniform linear map to contain the directory
00218   DirectoryMap_ = new Epetra_Map( Dir_NumGlobalElements, MinAllGID, Map.Comm() );
00219 
00220   int Dir_NumMyElements = DirectoryMap_->NumMyElements(); // Get NumMyElements
00221 
00222 
00223 
00224   // Allocate Processor list and Local Index List.  Initialize to -1s.
00225 
00226   if (Dir_NumMyElements>0) {
00227     ProcList_ = new int[ Dir_NumMyElements ];
00228     LocalIndexList_ = new int[ Dir_NumMyElements ];
00229     if (!SizeIsConst_) SizeList_ = new int[ Dir_NumMyElements ];
00230     // Initialize values to -1 in case the user global element list does
00231     // fill all IDs from MinAllGID to MaxAllGID (e.g., allows global indices to be 
00232     // all even integers.
00233     for (i=0; i<Dir_NumMyElements; i++) {
00234       ProcList_[i] = -1;
00235       LocalIndexList_[i] = -1;
00236       if (!SizeIsConst_) SizeList_[i] = -1;
00237     }
00238   }
00239 
00240   
00241   // Get list of processors owning the directory entries for the Map GIDs
00242 
00243   int MyPID = Map.Comm().MyPID();
00244 
00245   int Map_NumMyElements = Map.NumMyElements();
00246   int * send_procs = 0;
00247   if (Map_NumMyElements>0) send_procs = new int[Map_NumMyElements];
00248   int * Map_MyGlobalElements = Map.MyGlobalElements();
00249 
00250   EPETRA_CHK_ERR(DirectoryMap_->RemoteIDList(Map_NumMyElements,
00251                Map_MyGlobalElements, 
00252                send_procs, 0));
00253 
00254   bool det_flag = true;
00255 
00256   int num_recvs=0;
00257     
00258   Epetra_Distributor * Distor = Map.Comm().CreateDistributor();
00259 
00260   EPETRA_CHK_ERR(Distor->CreateFromSends( Map_NumMyElements, send_procs, det_flag, num_recvs ));
00261 
00262   if (Map_NumMyElements>0) delete [] send_procs;
00263 
00264   int * export_elements = 0;
00265   char * c_import_elements = 0;
00266   int * import_elements = 0;
00267   int len_import_elements = 0;
00268   int * ElementSizeList = 0;
00269 
00270   int packetSize = 3; // Assume we will send GIDs, PIDs and LIDs (will increase to 4 if also sending sizes)
00271   if (!SizeIsConst_) packetSize++; // Must send element size info also
00272  
00273   if (Map_NumMyElements>0) {
00274     if (!SizeIsConst_) ElementSizeList = Map.ElementSizeList();
00275     export_elements = new int[ packetSize * Map_NumMyElements ];
00276     int * ptr = export_elements;
00277     for( i = 0; i < Map_NumMyElements; i++ )
00278       {
00279   *ptr++ = Map_MyGlobalElements[i];
00280   *ptr++ = MyPID;
00281   *ptr++ = i;
00282   if (!SizeIsConst_) *ptr++ = ElementSizeList[i];
00283       }
00284   }
00285 
00286   //if (num_recvs>0) import_elements = new int[ packetSize * num_recvs ];
00287   //for (i=0; i< packetSize*num_recvs; i++) import_elements[i] = 0;
00288 
00289   EPETRA_CHK_ERR(Distor->Do(reinterpret_cast<char *> (export_elements), 
00290           packetSize * (int)sizeof( int ),
00291           len_import_elements,
00292           c_import_elements ));
00293 
00294   import_elements = reinterpret_cast<int *>(c_import_elements);
00295   
00296   //bool MYPID = (Map.Comm().MyPID()==0);
00297   int curr_LID;
00298   //if (MYPID) cout << "Processor " << Map.Comm().MyPID()<< "  num_recvs = "<< num_recvs << endl << flush;
00299   int * ptr = import_elements;
00300   for( i = 0; i < num_recvs; i++ )
00301   {
00302     curr_LID = DirectoryMap_->LID(*ptr++); // Convert incoming GID to Directory LID
00303     //if (MYPID) cout << " Receive ID = " << i << "  GID = " << import_elements[3*i] << "  LID = " << curr_LID << endl << flush;
00304     assert(curr_LID !=-1); // Internal error
00305     int proc = *ptr++;
00306     if (ProcList_[curr_LID] >= 0) {
00307       if (ProcList_[curr_LID] != proc) {
00308   if (numProcLists_ < 1) {
00309     create_ProcListArrays();
00310   }
00311 
00312   addProcToList(ProcList_[curr_LID], curr_LID);
00313   addProcToList(proc, curr_LID);
00314 
00315   //leave the lowest-numbered proc in ProcList_[curr_LID].
00316   ProcList_[curr_LID] = ProcListLists_[curr_LID][0];
00317       }
00318     }
00319     else {
00320       ProcList_[curr_LID] = proc;
00321     }
00322     LocalIndexList_[ curr_LID ] = *ptr++;
00323     if (!SizeIsConst_) SizeList_[ curr_LID ] = *ptr++;
00324   }
00325 
00326   int localval, globalval;
00327   localval = numProcLists_;
00328   DirectoryMap_->Comm().MaxAll(&localval, &globalval, 1);
00329   entryOnMultipleProcs_ = globalval > 0 ? true : false;
00330 
00331   if (len_import_elements!=0) delete [] c_import_elements;
00332   if (export_elements!=0) delete [] export_elements;
00333   
00334   delete Distor;
00335   return(0);
00336 }
00337 
00338 //==============================================================================
00339 bool Epetra_BasicDirectory::GIDsAllUniquelyOwned() const
00340 {
00341   return( !entryOnMultipleProcs_ );
00342 }
00343 
00344 //==============================================================================
00345 // GetDirectoryEntries: Get non-local GID references ( procID and localID )
00346 //      Space should already be allocated for Procs and
00347 //          LocalEntries.
00348 int Epetra_BasicDirectory::GetDirectoryEntries( const Epetra_BlockMap& Map,
00349             const int NumEntries,
00350             const int * GlobalEntries,
00351             int * Procs,
00352             int * LocalEntries,
00353             int * EntrySizes,
00354             bool high_rank_sharing_procs) const
00355 {
00356   int ierr = 0;
00357   int j;
00358   int i;
00359   int MyPID = Map.Comm().MyPID();
00360   int NumProc = Map.Comm().NumProc();
00361   int n_over_p = Map.NumGlobalElements() / NumProc;
00362 
00363   // Test for simple cases
00364 
00365   // Uniprocessor and local map cases
00366 
00367   if (!Map.DistributedGlobal()) {
00368     int ElementSize = 0;
00369     int * ElementSizeList = 0;
00370     bool ConstantElementSize = Map.ConstantElementSize();
00371     if (ConstantElementSize)
00372       ElementSize = Map.MaxElementSize();
00373     else
00374       ElementSizeList = Map.ElementSizeList();
00375     for (i=0; i<NumEntries; i++) {
00376       int LID = Map.LID(GlobalEntries[i]); // Get LID
00377       // Procs[i] will be MyPID, or -1 if the GID is not owned by this map
00378       if (LID==-1) {
00379   Procs[i] = -1; 
00380   ierr = 1; // Send warning error back that one of the GIDs is not part of this map
00381       }
00382       else Procs[i] = MyPID;
00383 
00384       // Put LID in return array if needed
00385       if (LocalEntries!=0) LocalEntries[i] = LID;
00386       
00387       // Fill EntrySizes if needed
00388       if (EntrySizes!=0) {
00389   if (ConstantElementSize)
00390     EntrySizes[i] = ElementSize;
00391   else if (LID>-1) 
00392     EntrySizes[i] = ElementSizeList[LID];
00393   else
00394     EntrySizes[i] = 0;
00395       }
00396     }
00397     EPETRA_CHK_ERR(ierr);
00398     return(0);
00399   }
00400 
00401   // Linear Map case
00402   if (Map.LinearMap()) {
00403     
00404     int MinAllGID = Map.MinAllGID(); // Get Min of all GID
00405     int MaxAllGID = Map.MaxAllGID(); // Get Max of all GID
00406     for (i=0; i<NumEntries; i++) {
00407       int LID = -1; // Assume not found
00408       int Proc = -1;
00409       int GID = GlobalEntries[i];
00410       if (GID<MinAllGID) ierr = 1;
00411       else if (GID>MaxAllGID) ierr = 1;
00412       else {
00413   // Guess uniform distribution and start a little above it
00414   int Proc1 = EPETRA_MIN(GID/EPETRA_MAX(n_over_p,1) + 2, NumProc-1);
00415   bool found = false;
00416   while (Proc1 >= 0 && Proc1< NumProc) {
00417     if (AllMinGIDs_[Proc1]<=GID) {
00418       if (GID <AllMinGIDs_[Proc1+1]) {
00419       found = true;
00420       break;
00421       }
00422       else Proc1++;
00423     }
00424     else Proc1--;
00425   }
00426   if (found) {
00427     Proc = Proc1;
00428     LID = GID - AllMinGIDs_[Proc];
00429   }
00430       }
00431       Procs[i] = Proc;
00432       if (LocalEntries!=0) LocalEntries[i] = LID;
00433     }
00434     if (EntrySizes!=0) {
00435       if (Map.ConstantElementSize()) {
00436   int ElementSize = Map.MaxElementSize();
00437   for (i=0; i<NumEntries; i++) EntrySizes[i] = ElementSize;
00438       }
00439       else {
00440   int * ElementSizeList = Map.ElementSizeList(); // We know this exists
00441   
00442   
00443   Epetra_Distributor * Size_Distor = Map.Comm().CreateDistributor();
00444   
00445   int Size_num_sends;
00446   int * Size_send_gids = 0;
00447   int * Size_send_procs = 0;
00448 
00449   
00450   EPETRA_CHK_ERR(Size_Distor->CreateFromRecvs( NumEntries, GlobalEntries, Procs, true,
00451                    Size_num_sends, Size_send_gids, Size_send_procs ));
00452   
00453   int * Size_exports = 0;
00454   char * c_Size_imports = 0;
00455   int * Size_imports = 0;
00456   if (Size_num_sends>0) {
00457     Size_exports = new int[ 2 * Size_num_sends ];
00458     for( i = 0; i < Size_num_sends; i++ )
00459       {
00460         int Size_curr_GID = Size_send_gids[i];
00461         int Size_curr_LID = Map.LID(Size_curr_GID);
00462         assert(Size_curr_LID!=-1); // Internal error 
00463         Size_exports[2*i] = Size_curr_GID;
00464         int Size_curr_size = ElementSizeList[Size_curr_LID];
00465         Size_exports[2*i+1] = Size_curr_size;
00466       }
00467   }
00468   
00469         int len_Size_imports = 0;
00470   EPETRA_CHK_ERR(Size_Distor->Do( reinterpret_cast<char*> (Size_exports),
00471                                         2 * (int)sizeof( int ),
00472                                         len_Size_imports,
00473                                         c_Size_imports));
00474   Size_imports = reinterpret_cast<int*>(c_Size_imports);
00475   
00476   for( i = 0; i < NumEntries; i++ )
00477     {
00478 
00479       // Need to change !!!!
00480       //bool found = false;
00481       int Size_curr_LID = Size_imports[2*i];
00482       for( j = 0; j < NumEntries; j++ )
00483         if( Size_curr_LID == GlobalEntries[j] )
00484     {
00485       EntrySizes[j] = Size_imports[2*i+1];
00486       // found = true;
00487       break;
00488     }
00489       //  if (!found) cout << "Internal error:  Epetra_BasicDirectory::GetDirectoryEntries: Global Index " << curr_LID
00490       //       << " not on processor " << MyPID << endl; abort();
00491     }
00492   
00493   if( Size_send_gids != 0 ) delete [] Size_send_gids;
00494   if( Size_send_procs != 0 ) delete [] Size_send_procs;
00495   
00496   if( len_Size_imports != 0 ) delete [] c_Size_imports;
00497   if( Size_exports != 0 ) delete [] Size_exports;
00498   
00499   delete Size_Distor;
00500       }
00501     }
00502     EPETRA_CHK_ERR(ierr);
00503     return(0);
00504   }
00505 
00506   // General case (need to set up an actual directory structure)
00507   
00508   int PacketSize = 2; // We will send at least the GID and PID.  Might also send LID and Size info
00509   bool DoSizes = false;
00510   if (EntrySizes!=0) {
00511     if (Map.ConstantElementSize()) {
00512       int ElementSize = Map.MaxElementSize();
00513   for (i=0; i<NumEntries; i++) EntrySizes[i] = ElementSize;
00514     }
00515     else {
00516       DoSizes = true;
00517       PacketSize++; // Sending Size info
00518     }
00519   }
00520 
00521   bool DoLIDs = (LocalEntries!=0); // Do LIDs?
00522   if (DoLIDs) PacketSize++; // Sending LIDs also
00523 
00524   
00525   Epetra_Distributor * Distor = DirectoryMap_->Comm().CreateDistributor();
00526   
00527   
00528   int * dir_procs = 0;
00529   if (NumEntries>0) dir_procs = new int[ NumEntries ];
00530   
00531   // Get directory locations for the requested list of entries
00532   DirectoryMap_->RemoteIDList(NumEntries, GlobalEntries, dir_procs, 0);
00533 
00534   //Check for unfound GlobalEntries and set corresponding Procs to -1
00535   int NumMissing = 0;
00536   {for( i = 0; i < NumEntries; ++i )
00537     if( dir_procs[i] == -1 )
00538     {
00539       Procs[i] = -1;
00540       if (DoLIDs) LocalEntries[i] = -1;
00541       ++NumMissing;
00542   }}
00543 
00544   int num_sends;
00545   int * send_gids = 0;
00546   int * send_procs = 0;
00547   
00548   EPETRA_CHK_ERR(Distor->CreateFromRecvs( NumEntries, GlobalEntries, dir_procs, true,
00549              num_sends, send_gids, send_procs));
00550 
00551   if (NumEntries>0) delete [] dir_procs;
00552 
00553 
00554   int curr_LID;
00555   int * exports = 0;
00556   char * c_imports = 0;
00557   int * imports = 0;
00558   int len_imports = 0;
00559   if (num_sends>0) {
00560     exports = new int[ PacketSize * num_sends ];
00561     int * ptr = exports;
00562     for( i = 0; i < num_sends; i++ )
00563       {
00564   int curr_GID = send_gids[i];
00565   *ptr++ = curr_GID;
00566   curr_LID = DirectoryMap_->LID(curr_GID);
00567   assert(curr_LID!=-1); // Internal error 
00568   if (high_rank_sharing_procs==false) {
00569     *ptr++ = ProcList_[ curr_LID ];
00570   }
00571   else {
00572     //high_rank_sharing_procs==true means that if multiple procs share a
00573     //GID, we want to use the proc with highest rank rather than the
00574     //proc with lowest rank.
00575     if (numProcLists_ > 0) {
00576       int num = ProcListLens_[curr_LID];
00577       if (num > 1) {
00578         *ptr++ = ProcListLists_[curr_LID][num-1];
00579       }
00580       else {
00581         *ptr++ = ProcList_[ curr_LID ];
00582       }
00583     }
00584     else {
00585       *ptr++ = ProcList_[ curr_LID ];
00586     }
00587   }
00588 
00589   if (DoLIDs) *ptr++ = LocalIndexList_[curr_LID];
00590   if (DoSizes) *ptr++ = SizeList_[curr_LID];
00591       }
00592   }
00593 
00594   int NumRecv = NumEntries - NumMissing;
00595   EPETRA_CHK_ERR(Distor->Do(reinterpret_cast<char*> (exports),
00596                             PacketSize * (int)sizeof( int ),
00597                             len_imports,
00598                             c_imports));
00599   imports = reinterpret_cast<int*>(c_imports);
00600 
00601   //create a sorted copy of the GlobalEntries array, along with a companion
00602   //array that will allow us to put result arrays (Procs, LocalEntries &
00603   //EntrySizes) in the same order as the unsorted GlobalEntries array
00604   int* sortedGE = new int[NumEntries*2];
00605   int* offsets = sortedGE+NumEntries;
00606   for(i=0; i<NumEntries; ++i) {
00607     offsets[i] = i;
00608   }
00609 
00610   std::memcpy(sortedGE, GlobalEntries, NumEntries*sizeof(int));
00611   Epetra_Util Utils;
00612   Utils.Sort(true, NumEntries, sortedGE, 0, 0, 1, &offsets);
00613 
00614   int * ptr = imports;
00615   int insertPoint; //insertPoint won't be used, but is argument to binary_search
00616 
00617   for( i = 0; i < NumRecv; i++ ) {
00618     curr_LID = *ptr++;
00619     j = Epetra_Util_binary_search(curr_LID, sortedGE, NumEntries, insertPoint);
00620     if (j > -1) {
00621       Procs[offsets[j]] = *ptr++;
00622       if (DoLIDs) LocalEntries[offsets[j]] = *ptr++;
00623       if (DoSizes) EntrySizes[offsets[j]] = *ptr++;
00624     }
00625   }
00626 
00627   delete [] sortedGE;
00628 
00629   if( send_gids ) delete [] send_gids;
00630   if( send_procs ) delete [] send_procs;
00631   
00632   if( len_imports ) delete [] c_imports;
00633   if( exports ) delete [] exports;
00634 
00635   delete Distor;
00636   return(0);
00637 }
00638 
00639 //==============================================================================
00640 void Epetra_BasicDirectory::Print( ostream & os) const {
00641   
00642   int MyPID;
00643   if( DirectoryMap_ != 0 ) {;
00644     MyPID = DirectoryMap_->Comm().MyPID();
00645     os << MyPID << " Epetra_BasicDirectory Object: "
00646       << DirectoryMap_->NumMyElements() << endl;
00647     for( int i = 0; i < DirectoryMap_->NumMyElements(); i++ ) {
00648       os << " " << i << " " << ProcList_[i] << " "
00649    << LocalIndexList_[i];
00650       if (!SizeIsConst_)
00651   os  << " " <<  SizeList_[i];
00652       os << endl;
00653       os << endl;
00654     }
00655   }
00656   else
00657   {
00658     cout << "Epetra_BasicDirectory not setup<<<<<<" << endl;
00659   }
00660 
00661   return;
00662 }
00663 
00664 //--------------------------------------------------------------------------------
00665 Epetra_BasicDirectory& Epetra_BasicDirectory::operator=(const Epetra_BasicDirectory& src)
00666 {
00667   (void)src;
00668   //not currently supported
00669   bool throw_error = true;
00670   if (throw_error) {
00671     std::cerr << std::endl
00672         << "Epetra_BasicDirectory::operator= not supported."
00673         << std::endl;
00674     throw -1;
00675   }
00676   return( *this );
00677 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines