Epetra Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Epetra_BasicDirectory.cpp
Go to the documentation of this file.
1 
2 //@HEADER
3 // ************************************************************************
4 //
5 // Epetra: Linear Algebra Services Package
6 // Copyright 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 
43 #include "Epetra_ConfigDefs.h"
44 #include "Epetra_BasicDirectory.h"
45 #include "Epetra_BlockMap.h"
46 #include "Epetra_Map.h"
47 #include "Epetra_Comm.h"
48 #include "Epetra_Distributor.h"
49 #include "Epetra_Util.h"
50 
51 //==============================================================================
52 // Epetra_BasicDirectory constructor for a Epetra_BlockMap object
54  : DirectoryMap_(0),
55  ProcList_(0),
56  ProcListLists_(0),
57  ProcListLens_(0),
58  numProcLists_(0),
59  entryOnMultipleProcs_(false),
60  LocalIndexList_(0),
61  SizeList_(0),
62  SizeIsConst_(true)
63 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
64  ,AllMinGIDs_int_(0)
65 #endif
66 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
67  ,AllMinGIDs_LL_(0)
68 #endif
69 {
70  // Test for simple cases
71 
72  // Uniprocessor and local map cases (Nothing to set up)
73 
74  if (!(Map.DistributedGlobal())) return;
75 
76  // Linear Map case
77 
78  else if (Map.LinearMap()) {
79 
80  // Build a list of the Minimum global ids for all processors on each processor.
81  // Since the map is linear, we know that all GIDs are contiguous on each processor
82  // and can be found using the MinGIDs.
83 
84  int NumProc = Map.Comm().NumProc();
85 
86 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
87  if(Map.GlobalIndicesInt())
88  {
89  AllMinGIDs_int_ = new int[NumProc+1];
90  int MinMyGID = (int) Map.MinMyGID64();
91  Map.Comm().GatherAll(&MinMyGID, AllMinGIDs_int_, 1);
92  AllMinGIDs_int_[NumProc] = (int) (1 + Map.MaxAllGID64()); // Set max cap
93  }
94  else
95 #endif
96 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
97  if(Map.GlobalIndicesLongLong())
98  {
99  AllMinGIDs_LL_ = new long long[NumProc+1];
100  long long MinMyGID = Map.MinMyGID64();
101  Map.Comm().GatherAll(&MinMyGID, AllMinGIDs_LL_, 1);
102  AllMinGIDs_LL_[NumProc] = 1 + Map.MaxAllGID64(); // Set max cap
103  }
104  else
105 #endif
106  throw "Epetra_BasicDirectory::Epetra_BasicDirectory: Unknown map index type";
107  }
108 
109  // General case. Need to build a directory via calls to communication functions
110  else {
111 
112  int flag = -1;
113  if(Map.GlobalIndicesInt())
114 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
115  flag = Generate<int>(Map);
116 #else
117  throw "Epetra_BasicDirectory::Epetra_BasicDirectory: ERROR, GlobalIndicesInt but no API for it.";
118 #endif
119  else if(Map.GlobalIndicesLongLong())
120 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
121  flag = Generate<long long>(Map);
122 #else
123  throw "Epetra_BasicDirectory::Epetra_BasicDirectory: ERROR, GlobalIndicesLongLong but no API for it.";
124 #endif
125 
126  assert(flag==0);
127  }
128 }
129 
130 //==============================================================================
131 // Epetra_BasicDirectory copy constructor
133  : DirectoryMap_(0),
134  ProcList_(0),
135  ProcListLists_(0),
136  ProcListLens_(0),
137  numProcLists_(0),
138  entryOnMultipleProcs_(false),
139  LocalIndexList_(0),
140  SizeList_(0),
141  SizeIsConst_(Directory.SizeIsConst_)
142 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
143  ,AllMinGIDs_int_(0)
144 #endif
145 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
146  ,AllMinGIDs_LL_(0)
147 #endif
148 {
149  if (Directory.DirectoryMap_!=0) DirectoryMap_ = new Epetra_Map(Directory.DirectoryMap());
150 
151  int Dir_NumMyElements = DirectoryMap_->NumMyElements();
152 
153  if (Directory.ProcList_!=0) {
154  ProcList_ = new int[Dir_NumMyElements];
155  for (int i=0; i<Dir_NumMyElements; i++) ProcList_[i] = Directory.ProcList_[i];
156  }
157  if (Directory.LocalIndexList_!=0) {
158  LocalIndexList_ = new int[Dir_NumMyElements];
159  for (int i=0; i<Dir_NumMyElements; i++) LocalIndexList_[i] = Directory.LocalIndexList_[i];
160  }
161  if (Directory.SizeList_!=0) {
162  SizeList_ = new int[Dir_NumMyElements];
163  for (int i=0; i<Dir_NumMyElements; i++) SizeList_[i] = Directory.SizeList_[i];
164  }
165 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
166  if (Directory.AllMinGIDs_int_!=0) {
167  int NumProc = DirectoryMap_->Comm().NumProc();
168  AllMinGIDs_int_ = new int[NumProc+1];
169  for (int i=0; i<NumProc+1; i++) AllMinGIDs_int_[i] = Directory.AllMinGIDs_int_[i];
170  }
171 #endif
172 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
173  if (Directory.AllMinGIDs_LL_!=0) {
174  int NumProc = DirectoryMap_->Comm().NumProc();
175  AllMinGIDs_LL_ = new long long[NumProc+1];
176  for (int i=0; i<NumProc+1; i++) AllMinGIDs_LL_[i] = Directory.AllMinGIDs_LL_[i];
177  }
178 #endif
179 
180  if (Directory.numProcLists_ > 0) {
181  int num = Directory.numProcLists_;
182  ProcListLens_ = new int[num];
183  ProcListLists_ = new int*[num];
184  numProcLists_ = num;
185 
186  for(int i=0; i<num; ++i) {
187  int len = Directory.ProcListLens_[i];
188  ProcListLens_[i] = len;
189 
190  if (len > 0) {
191  ProcListLists_[i] = new int[len];
192  const int* dir_list = Directory.ProcListLists_[i];
193  for(int j=0; j<len; ++j) {
194  ProcListLists_[i][j] = dir_list[j];
195  }
196  }
197  else ProcListLists_[i] = 0;
198  }
199  }
200 
202 }
203 
204 //==============================================================================
205 // Epetra_BasicDirectory destructor
207 {
208  if (numProcLists_>0) {
209  for(int i=0; i<numProcLists_; ++i) {
210  if (ProcListLens_[i] > 0) delete [] ProcListLists_[i];
211  }
212  delete [] ProcListLists_; ProcListLists_ = 0;
213  delete [] ProcListLens_; ProcListLens_ = 0;
214  numProcLists_ = 0;
215  }
216 
217  if( DirectoryMap_ != 0 ) delete DirectoryMap_;
218  if( ProcList_ != 0 ) delete [] ProcList_;
219  if( LocalIndexList_ != 0 ) delete [] LocalIndexList_;
220  if( SizeList_ != 0 ) delete [] SizeList_;
221 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
222  if( AllMinGIDs_int_ != 0 ) delete [] AllMinGIDs_int_;
223  AllMinGIDs_int_ = 0;
224 #endif
225 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
226  if( AllMinGIDs_LL_ != 0 ) delete [] AllMinGIDs_LL_;
227  AllMinGIDs_LL_ = 0;
228 #endif
229 
230  DirectoryMap_ = 0;
231  ProcList_ = 0 ;
232  LocalIndexList_ = 0;
233  SizeList_ = 0;
234 }
235 
236 //==============================================================================
238 {
240  ProcListLens_ = new int[numProcLists_];
241  ProcListLists_ = new int*[numProcLists_];
242 
243  for(int i=0; i<numProcLists_; ++i) {
244  ProcListLens_[i] = 0;
245  ProcListLists_[i] = 0;
246  }
247 }
248 
249 //==============================================================================
251 {
252  int insertPoint = -1;
253  int index = Epetra_Util_binary_search(proc, ProcListLists_[LID],
254  ProcListLens_[LID], insertPoint);
255  if (index < 0) {
256  int tmp = ProcListLens_[LID];
257  Epetra_Util_insert(proc, insertPoint, ProcListLists_[LID],
258  ProcListLens_[LID], tmp, 1);
259  }
260 }
261 
262 //==============================================================================
263 // Generate: Generates Directory Tables
264 template<typename int_type>
266 {
267  int i;
269  int_type MinAllGID = (int_type) Map.MinAllGID64();
270  int_type MaxAllGID = (int_type) Map.MaxAllGID64();
271  // DirectoryMap will have a range of elements from the minimum to the maximum
272  // GID of the user map, and an IndexBase of MinAllGID from the user map
273  int_type Dir_NumGlobalElements = MaxAllGID - MinAllGID + 1;
274 
275  // Create a uniform linear map to contain the directory
276  DirectoryMap_ = new Epetra_Map( Dir_NumGlobalElements, MinAllGID, Map.Comm() );
277 
278  int Dir_NumMyElements = DirectoryMap_->NumMyElements(); // Get NumMyElements
279 
280 
281 
282  // Allocate Processor list and Local Index List. Initialize to -1s.
283 
284  if (Dir_NumMyElements>0) {
285  ProcList_ = new int[ Dir_NumMyElements ];
286  LocalIndexList_ = new int[ Dir_NumMyElements ];
287  if (!SizeIsConst_) SizeList_ = new int[ Dir_NumMyElements ];
288  // Initialize values to -1 in case the user global element list does
289  // fill all IDs from MinAllGID to MaxAllGID (e.g., allows global indices to be
290  // all even integers.
291  for (i=0; i<Dir_NumMyElements; i++) {
292  ProcList_[i] = -1;
293  LocalIndexList_[i] = -1;
294  if (!SizeIsConst_) SizeList_[i] = -1;
295  }
296  }
297 
298 
299  // Get list of processors owning the directory entries for the Map GIDs
300 
301  int MyPID = Map.Comm().MyPID();
302 
303  int Map_NumMyElements = Map.NumMyElements();
304  int * send_procs = 0;
305  if (Map_NumMyElements>0) send_procs = new int[Map_NumMyElements];
306  int_type * Map_MyGlobalElements = 0;
307 #if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
308  Map.MyGlobalElementsPtr(Map_MyGlobalElements);
309 
310  EPETRA_CHK_ERR(DirectoryMap_->RemoteIDList(Map_NumMyElements,
311  Map_MyGlobalElements,
312  send_procs, 0));
313 #endif
314 
315  bool det_flag = true;
316 
317  int num_recvs=0;
318 
319  Epetra_Distributor * Distor = Map.Comm().CreateDistributor();
320 
321  EPETRA_CHK_ERR(Distor->CreateFromSends( Map_NumMyElements, send_procs, det_flag, num_recvs ));
322 
323  if (Map_NumMyElements>0) delete [] send_procs;
324 
325  int * export_elements = 0;
326  char * c_import_elements = 0;
327  int * import_elements = 0;
328  int len_import_elements = 0;
329  int * ElementSizeList = 0;
330 
331  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)
332  if (!SizeIsConst_) packetSize++; // Must send element size info also
333 
334  if (Map_NumMyElements>0) {
335  if (!SizeIsConst_) ElementSizeList = Map.ElementSizeList();
336  export_elements = new int[ packetSize * Map_NumMyElements ];
337  int * ptr = export_elements;
338  for( i = 0; i < Map_NumMyElements; i++ )
339  {
340  *(int_type*)ptr = Map_MyGlobalElements[i];
341  ptr += sizeof(int_type)/sizeof(int);
342  *ptr++ = MyPID;
343  *ptr++ = i;
344  if (!SizeIsConst_) *ptr++ = ElementSizeList[i];
345  }
346  }
347 
348  //if (num_recvs>0) import_elements = new int[ packetSize * num_recvs ];
349  //for (i=0; i< packetSize*num_recvs; i++) import_elements[i] = 0;
350 
351  EPETRA_CHK_ERR(Distor->Do(reinterpret_cast<char *> (export_elements),
352  packetSize * (int)sizeof( int ),
353  len_import_elements,
354  c_import_elements ));
355 
356  import_elements = reinterpret_cast<int *>(c_import_elements);
357 
358  //bool MYPID = (Map.Comm().MyPID()==0);
359  int curr_LID;
360  //if (MYPID) cout << "Processor " << Map.Comm().MyPID()<< " num_recvs = "<< num_recvs << std::endl << flush;
361  int * ptr = import_elements;
362  for( i = 0; i < num_recvs; i++ )
363  {
364  curr_LID = DirectoryMap_->LID(*(int_type*)ptr); // Convert incoming GID to Directory LID
365  ptr += sizeof(int_type)/sizeof(int);
366  //if (MYPID) cout << " Receive ID = " << i << " GID = " << import_elements[3*i] << " LID = " << curr_LID << std::endl << flush;
367  assert(curr_LID !=-1); // Internal error
368  int proc = *ptr++;
369  if (ProcList_[curr_LID] >= 0) {
370  if (ProcList_[curr_LID] != proc) {
371  if (numProcLists_ < 1) {
373  }
374 
375  addProcToList(ProcList_[curr_LID], curr_LID);
376  addProcToList(proc, curr_LID);
377 
378  //leave the lowest-numbered proc in ProcList_[curr_LID].
379  ProcList_[curr_LID] = ProcListLists_[curr_LID][0];
380  }
381  }
382  else {
383  ProcList_[curr_LID] = proc;
384  }
385  LocalIndexList_[ curr_LID ] = *ptr++;
386  if (!SizeIsConst_) SizeList_[ curr_LID ] = *ptr++;
387  }
388 
389  int localval, globalval;
390  localval = numProcLists_;
391  DirectoryMap_->Comm().MaxAll(&localval, &globalval, 1);
392  entryOnMultipleProcs_ = globalval > 0 ? true : false;
393 
394  if (len_import_elements!=0) delete [] c_import_elements;
395  if (export_elements!=0) delete [] export_elements;
396 
397  delete Distor;
398  return(0);
399 }
400 
401 //==============================================================================
403 {
404  return( !entryOnMultipleProcs_ );
405 }
406 
407 //==============================================================================
408 // GetDirectoryEntries: Get non-local GID references ( procID and localID )
409 // Space should already be allocated for Procs and
410 // LocalEntries.
411 template<typename int_type>
413  const int NumEntries,
414  const int_type * GlobalEntries,
415  int * Procs,
416  int * LocalEntries,
417  int * EntrySizes,
418  bool high_rank_sharing_procs) const
419 {
420  int ierr = 0;
421  int j;
422  int i;
423  int MyPID = Map.Comm().MyPID();
424  int NumProc = Map.Comm().NumProc();
425  int_type n_over_p = (int_type) (Map.NumGlobalElements64() / NumProc);
426 
427  // Test for simple cases
428 
429  // Uniprocessor and local map cases
430 
431  if (!Map.DistributedGlobal()) {
432  int ElementSize = 0;
433  int * ElementSizeList = 0;
434  bool ConstantElementSize = Map.ConstantElementSize();
435  if (ConstantElementSize)
436  ElementSize = Map.MaxElementSize();
437  else
438  ElementSizeList = Map.ElementSizeList();
439  for (i=0; i<NumEntries; i++) {
440  int LID = Map.LID(GlobalEntries[i]); // Get LID
441  // Procs[i] will be MyPID, or -1 if the GID is not owned by this map
442  if (LID==-1) {
443  Procs[i] = -1;
444  ierr = 1; // Send warning error back that one of the GIDs is not part of this map
445  }
446  else Procs[i] = MyPID;
447 
448  // Put LID in return array if needed
449  if (LocalEntries!=0) LocalEntries[i] = LID;
450 
451  // Fill EntrySizes if needed
452  if (EntrySizes!=0) {
453  if (ConstantElementSize)
454  EntrySizes[i] = ElementSize;
455  else if (LID>-1)
456  EntrySizes[i] = ElementSizeList[LID];
457  else
458  EntrySizes[i] = 0;
459  }
460  }
461  EPETRA_CHK_ERR(ierr);
462  return(0);
463  }
464 
465  // Linear Map case
466  if (Map.LinearMap()) {
467 
468  int_type MinAllGID = (int_type) Map.MinAllGID64(); // Get Min of all GID
469  int_type MaxAllGID = (int_type) Map.MaxAllGID64(); // Get Max of all GID
470  for (i=0; i<NumEntries; i++) {
471  int LID = -1; // Assume not found
472  int Proc = -1;
473  int_type GID = GlobalEntries[i];
474  if (GID<MinAllGID) ierr = 1;
475  else if (GID>MaxAllGID) ierr = 1;
476  else {
477  // Guess uniform distribution and start a little above it
478  int Proc1 = (int) EPETRA_MIN(GID/EPETRA_MAX(n_over_p,(int_type)1) + 2, (int_type) NumProc-1);
479  bool found = false;
480  const int_type* AllMinGIDs_ptr = AllMinGIDs<int_type>();
481 
482  while (Proc1 >= 0 && Proc1< NumProc) {
483  if (AllMinGIDs_ptr[Proc1]<=GID) {
484  if (GID <AllMinGIDs_ptr[Proc1+1]) {
485  found = true;
486  break;
487  }
488  else Proc1++;
489  }
490  else Proc1--;
491  }
492  if (found) {
493  Proc = Proc1;
494  LID = (int) (GID - AllMinGIDs_ptr[Proc]);
495  }
496  }
497  Procs[i] = Proc;
498  if (LocalEntries!=0) LocalEntries[i] = LID;
499  }
500  if (EntrySizes!=0) {
501  if (Map.ConstantElementSize()) {
502  int ElementSize = Map.MaxElementSize();
503  for (i=0; i<NumEntries; i++) EntrySizes[i] = ElementSize;
504  }
505  else {
506  int * ElementSizeList = Map.ElementSizeList(); // We know this exists
507 
508 
509  Epetra_Distributor * Size_Distor = Map.Comm().CreateDistributor();
510 
511  int Size_num_sends;
512  int_type * Size_send_gids = 0;
513  int * Size_send_procs = 0;
514 
515 
516  EPETRA_CHK_ERR(Size_Distor->CreateFromRecvs( NumEntries, GlobalEntries, Procs, true,
517  Size_num_sends, Size_send_gids, Size_send_procs ));
518 
519  int * Size_exports = 0;
520  char * c_Size_imports = 0;
521  int * Size_imports = 0;
522  int packetSize = (int) (sizeof(int_type) + sizeof(int))/sizeof(int);
523  if (Size_num_sends>0) {
524  Size_exports = new int[ packetSize * Size_num_sends ];
525  for( i = 0; i < Size_num_sends; i++ )
526  {
527  int_type Size_curr_GID = Size_send_gids[i];
528  int Size_curr_LID = Map.LID(Size_curr_GID);
529  assert(Size_curr_LID!=-1); // Internal error
530  *(int_type*)(Size_exports + packetSize*i) = Size_curr_GID;
531  int Size_curr_size = ElementSizeList[Size_curr_LID];
532  *(Size_exports + packetSize*i + (packetSize - 1)) = Size_curr_size;
533  }
534  }
535 
536  int len_Size_imports = 0;
537  EPETRA_CHK_ERR(Size_Distor->Do( reinterpret_cast<char*> (Size_exports),
538  packetSize * (int)sizeof( int ),
539  len_Size_imports,
540  c_Size_imports));
541  Size_imports = reinterpret_cast<int*>(c_Size_imports);
542 
543  for( i = 0; i < NumEntries; i++ )
544  {
545 
546  // Need to change !!!!
547  //bool found = false;
548  int_type Size_curr_GID = *(int_type*)(Size_imports + packetSize*i);
549  for( j = 0; j < NumEntries; j++ )
550  if( Size_curr_GID == GlobalEntries[j] )
551  {
552  EntrySizes[j] = *(Size_imports + packetSize*i + (packetSize - 1));
553  // found = true;
554  break;
555  }
556  // if (!found) cout << "Internal error: Epetra_BasicDirectory::GetDirectoryEntries: Global Index " << curr_LID
557  // << " not on processor " << MyPID << std::endl; abort();
558  }
559 
560  if( Size_send_gids != 0 ) delete [] Size_send_gids;
561  if( Size_send_procs != 0 ) delete [] Size_send_procs;
562 
563  if( len_Size_imports != 0 ) delete [] c_Size_imports;
564  if( Size_exports != 0 ) delete [] Size_exports;
565 
566  delete Size_Distor;
567  }
568  }
569  EPETRA_CHK_ERR(ierr);
570  return(0);
571  }
572 
573  // General case (need to set up an actual directory structure)
574 
575  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
576  bool DoSizes = false;
577  if (EntrySizes!=0) {
578  if (Map.ConstantElementSize()) {
579  int ElementSize = Map.MaxElementSize();
580  for (i=0; i<NumEntries; i++) EntrySizes[i] = ElementSize;
581  }
582  else {
583  DoSizes = true;
584  PacketSize++; // Sending Size info
585  }
586  }
587 
588  bool DoLIDs = (LocalEntries!=0); // Do LIDs?
589  if (DoLIDs) PacketSize++; // Sending LIDs also
590 
591 
593 
594 
595  int * dir_procs = 0;
596  if (NumEntries>0) dir_procs = new int[ NumEntries ];
597 
598 #if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
599  // Get directory locations for the requested list of entries
600  DirectoryMap_->RemoteIDList(NumEntries, GlobalEntries, dir_procs, 0);
601 #endif
602 
603  //Check for unfound GlobalEntries and set corresponding Procs to -1
604  int NumMissing = 0;
605  {for( i = 0; i < NumEntries; ++i )
606  if( dir_procs[i] == -1 )
607  {
608  Procs[i] = -1;
609  if (DoLIDs) LocalEntries[i] = -1;
610  ++NumMissing;
611  }}
612 
613  int num_sends;
614  int_type * send_gids = 0;
615  int * send_procs = 0;
616 
617  EPETRA_CHK_ERR(Distor->CreateFromRecvs( NumEntries, GlobalEntries, dir_procs, true,
618  num_sends, send_gids, send_procs));
619 
620  if (NumEntries>0) delete [] dir_procs;
621 
622 
623  int curr_LID;
624  int * exports = 0;
625  char * c_imports = 0;
626  int * imports = 0;
627  int len_imports = 0;
628  if (num_sends>0) {
629  exports = new int[ PacketSize * num_sends ];
630  int * ptr = exports;
631  for( i = 0; i < num_sends; i++ )
632  {
633  int_type curr_GID = send_gids[i];
634  *(int_type*)ptr = curr_GID;
635  ptr += sizeof(int_type)/sizeof(int);
636  curr_LID = DirectoryMap_->LID(curr_GID);
637  assert(curr_LID!=-1); // Internal error
638  if (high_rank_sharing_procs==false) {
639  *ptr++ = ProcList_[ curr_LID ];
640  }
641  else {
642  //high_rank_sharing_procs==true means that if multiple procs share a
643  //GID, we want to use the proc with highest rank rather than the
644  //proc with lowest rank.
645  if (numProcLists_ > 0) {
646  int num = ProcListLens_[curr_LID];
647  if (num > 1) {
648  *ptr++ = ProcListLists_[curr_LID][num-1];
649  }
650  else {
651  *ptr++ = ProcList_[ curr_LID ];
652  }
653  }
654  else {
655  *ptr++ = ProcList_[ curr_LID ];
656  }
657  }
658 
659  if (DoLIDs) *ptr++ = LocalIndexList_[curr_LID];
660  if (DoSizes) *ptr++ = SizeList_[curr_LID];
661  }
662  }
663 
664  int NumRecv = NumEntries - NumMissing;
665  EPETRA_CHK_ERR(Distor->Do(reinterpret_cast<char*> (exports),
666  PacketSize * (int)sizeof( int ),
667  len_imports,
668  c_imports));
669  imports = reinterpret_cast<int*>(c_imports);
670 
671  //create a sorted copy of the GlobalEntries array, along with a companion
672  //array that will allow us to put result arrays (Procs, LocalEntries &
673  //EntrySizes) in the same order as the unsorted GlobalEntries array
674  int* sortedGE_int = new int[NumEntries*(1 + sizeof(int_type)/sizeof(int))];
675  int* offsets = sortedGE_int+NumEntries*sizeof(int_type)/sizeof(int);
676  int_type* sortedGE = reinterpret_cast<int_type*>(sortedGE_int);
677 
678  for(i=0; i<NumEntries; ++i) {
679  offsets[i] = i;
680  }
681 
682  std::memcpy(sortedGE, GlobalEntries, NumEntries*sizeof(int_type));
683  Epetra_Util Utils;
684  Utils.Sort(true, NumEntries, sortedGE, 0, 0, 1, &offsets, 0, 0);
685 
686  int * ptr = imports;
687  int insertPoint; //insertPoint won't be used, but is argument to binary_search
688 
689  for( i = 0; i < NumRecv; i++ ) {
690  int_type theCurrentLID = *(int_type*)ptr;
691  ptr += sizeof(int_type)/sizeof(int);
692  j = Epetra_Util_binary_search(theCurrentLID, sortedGE, NumEntries, insertPoint);
693  if (j > -1) {
694  Procs[offsets[j]] = *ptr++;
695  if (DoLIDs) LocalEntries[offsets[j]] = *ptr++;
696  if (DoSizes) EntrySizes[offsets[j]] = *ptr++;
697  }
698  }
699 
700  delete [] sortedGE_int;
701 
702  if( send_gids ) delete [] send_gids;
703  if( send_procs ) delete [] send_procs;
704 
705  if( len_imports ) delete [] c_imports;
706  if( exports ) delete [] exports;
707 
708  delete Distor;
709  return(0);
710 }
711 
712 //==============================================================================
713 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
715  const int NumEntries,
716  const int * GlobalEntries,
717  int * Procs,
718  int * LocalEntries,
719  int * EntrySizes,
720  bool high_rank_sharing_procs) const
721 {
722  if(!Map.GlobalIndicesInt())
723  throw "Epetra_BasicDirectory::GetDirectoryEntries: int version can't be called for non int map";
724 
725  return GetDirectoryEntries<int>(Map, NumEntries, GlobalEntries, Procs,
726  LocalEntries, EntrySizes, high_rank_sharing_procs);
727 }
728 #endif
729 
730 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
731 // GetDirectoryEntries: Get non-local GID references ( procID and localID )
732 // Space should already be allocated for Procs and
733 // LocalEntries.
735  const int NumEntries,
736  const long long * GlobalEntries,
737  int * Procs,
738  int * LocalEntries,
739  int * EntrySizes,
740  bool high_rank_sharing_procs) const
741 {
742  if(!Map.GlobalIndicesLongLong())
743  throw "Epetra_BasicDirectory::GetDirectoryEntries: long long version can't be called for non long long map";
744 
745  return GetDirectoryEntries<long long>(Map, NumEntries, GlobalEntries, Procs,
746  LocalEntries, EntrySizes, high_rank_sharing_procs);
747 }
748 #endif
749 
750 //==============================================================================
751 void Epetra_BasicDirectory::Print(std::ostream & os) const {
752 
753  int MyPID;
754  if( DirectoryMap_ != 0 ) {;
755  MyPID = DirectoryMap_->Comm().MyPID();
756  os << MyPID << " Epetra_BasicDirectory Object: "
757  << DirectoryMap_->NumMyElements() << std::endl;
758  for( int i = 0; i < DirectoryMap_->NumMyElements(); i++ ) {
759  os << " " << i << " " << ProcList_[i] << " "
760  << LocalIndexList_[i];
761  if (!SizeIsConst_)
762  os << " " << SizeList_[i];
763  os << std::endl;
764  os << std::endl;
765  }
766  }
767  else
768  {
769  std::cout << "Epetra_BasicDirectory not setup<<<<<<" << std::endl;
770  }
771 
772  return;
773 }
774 
775 //--------------------------------------------------------------------------------
777 {
778  (void)src;
779  //not currently supported
780  bool throw_error = true;
781  if (throw_error) {
782  std::cerr << std::endl
783  << "Epetra_BasicDirectory::operator= not supported."
784  << std::endl;
785  throw -1;
786  }
787  return( *this );
788 }
long long MinMyGID64() const
long long MaxAllGID64() const
Epetra_Map: A class for partitioning vectors and matrices.
Definition: Epetra_Map.h:119
bool DistributedGlobal() const
Returns true if map is defined across more than one processor.
const Epetra_Map & DirectoryMap() const
Returns the Epetra_Map containing the directory.
bool GlobalIndicesLongLong() const
Returns true if map create with long long NumGlobalElements.
Epetra_Distributor: The Epetra Gather/Scatter Setup Base Class.
virtual int GatherAll(double *MyVals, double *AllVals, int Count) const =0
Epetra_Comm All Gather function.
bool GIDsAllUniquelyOwned() const
GIDsAllUniquelyOwned: returns true if all GIDs appear on just one processor.
Epetra_BasicDirectory(const Epetra_BlockMap &Map)
Epetra_BasicDirectory constructor.
long long NumGlobalElements64() const
int GetDirectoryEntries(const Epetra_BlockMap &Map, const int NumEntries, const int *GlobalEntries, int *Procs, int *LocalEntries, int *EntrySizes, bool high_rank_sharing_procs=false) const
GetDirectoryEntries : Returns proc and local id info for non-local map entries.
virtual int CreateFromSends(const int &NumExportIDs, const int *ExportPIDs, bool Deterministic, int &NumRemoteIDs)=0
Create Distributor object using list of process IDs to which we export.
bool ConstantElementSize() const
Returns true if map has constant element size.
virtual ~Epetra_BasicDirectory(void)
Epetra_BasicDirectory destructor.
#define EPETRA_CHK_ERR(a)
int * ElementSizeList() const
List of the element sizes corresponding to the array MyGlobalElements().
#define EPETRA_MIN(x, y)
bool GlobalIndicesInt() const
Returns true if map create with int NumGlobalElements.
virtual int MyPID() const =0
Return my process ID.
virtual int MaxAll(double *PartialMaxs, double *GlobalMaxs, int Count) const =0
Epetra_Comm Global Max function.
Epetra_Util: The Epetra Util Wrapper Class.
Definition: Epetra_Util.h:79
int NumMyElements() const
Number of elements on the calling processor.
int Generate(const Epetra_BlockMap &Map)
Generate: Sets up Directory tables.
long long MinAllGID64() const
Epetra_BasicDirectory: This class allows Epetra_Map objects to reference non-local elements...
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
int MyGlobalElementsPtr(int *&MyGlobalElementList) const
int LID(int GID) const
Returns local ID of global ID, return -1 if not found on this processor.
int Epetra_Util_binary_search(T item, const T *list, int len, int &insertPoint)
Utility function to perform a binary-search on a list of data.
Epetra_BasicDirectory & operator=(const Epetra_BasicDirectory &src)
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
virtual int Do(char *export_objs, int obj_size, int &len_import_objs, char *&import_objs)=0
Execute plan on buffer of export objects in a single step.
bool LinearMap() const
Returns true if the global ID space is contiguously divided (but not necessarily uniformly) across al...
virtual int CreateFromRecvs(const int &NumRemoteIDs, const int *RemoteGIDs, const int *RemotePIDs, bool Deterministic, int &NumExportIDs, int *&ExportGIDs, int *&ExportPIDs)=0
Create Distributor object using list of Remote global IDs and corresponding PIDs. ...
virtual int NumProc() const =0
Returns total number of processes.
virtual Epetra_Distributor * CreateDistributor() const =0
Create a distributor object.
virtual void Print(std::ostream &os) const
Print method.
int MaxElementSize() const
Maximum element size across all processors.
void addProcToList(int proc, int LID)
static void Sort(bool SortAscending, int NumKeys, T *Keys, int NumDoubleCompanions, double **DoubleCompanions, int NumIntCompanions, int **IntCompanions, int NumLongLongCompanions, long long **LongLongCompanions)
Epetra_Util Sort Routine (Shell sort)
#define EPETRA_MAX(x, y)
int Epetra_Util_insert(T item, int offset, T *&list, int &usedLength, int &allocatedLength, int allocChunkSize=32)
Function to insert an item in a list, at a specified offset.
Definition: Epetra_Util.h:398
int RemoteIDList(int NumIDs, const int *GIDList, int *PIDList, int *LIDList) const
Returns the processor IDs and corresponding local index value for a given list of global indices...