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