Epetra Package Browser (Single Doxygen Collection)  Development
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 #ifndef NDEBUG
112  int flag = -1;
113 #endif
114  if(Map.GlobalIndicesInt())
115 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
116 #ifndef NDEBUG
117  flag =
118 #endif
119  Generate<int>(Map);
120 #else
121  throw "Epetra_BasicDirectory::Epetra_BasicDirectory: ERROR, GlobalIndicesInt but no API for it.";
122 #endif
123  else if(Map.GlobalIndicesLongLong())
124 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
125 #ifndef NDEBUG
126  flag =
127 #endif
128  Generate<long long>(Map);
129 #else
130  throw "Epetra_BasicDirectory::Epetra_BasicDirectory: ERROR, GlobalIndicesLongLong but no API for it.";
131 #endif
132 
133  assert(flag==0);
134  }
135 }
136 
137 //==============================================================================
138 // Epetra_BasicDirectory copy constructor
140  : DirectoryMap_(0),
141  ProcList_(0),
142  ProcListLists_(0),
143  ProcListLens_(0),
144  numProcLists_(0),
145  entryOnMultipleProcs_(false),
146  LocalIndexList_(0),
147  SizeList_(0),
148  SizeIsConst_(Directory.SizeIsConst_)
149 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
150  ,AllMinGIDs_int_(0)
151 #endif
152 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
153  ,AllMinGIDs_LL_(0)
154 #endif
155 {
156  if (Directory.DirectoryMap_!=0) DirectoryMap_ = new Epetra_Map(Directory.DirectoryMap());
157 
158  int Dir_NumMyElements = DirectoryMap_->NumMyElements();
159 
160  if (Directory.ProcList_!=0) {
161  ProcList_ = new int[Dir_NumMyElements];
162  for (int i=0; i<Dir_NumMyElements; i++) ProcList_[i] = Directory.ProcList_[i];
163  }
164  if (Directory.LocalIndexList_!=0) {
165  LocalIndexList_ = new int[Dir_NumMyElements];
166  for (int i=0; i<Dir_NumMyElements; i++) LocalIndexList_[i] = Directory.LocalIndexList_[i];
167  }
168  if (Directory.SizeList_!=0) {
169  SizeList_ = new int[Dir_NumMyElements];
170  for (int i=0; i<Dir_NumMyElements; i++) SizeList_[i] = Directory.SizeList_[i];
171  }
172 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
173  if (Directory.AllMinGIDs_int_!=0) {
174  int NumProc = DirectoryMap_->Comm().NumProc();
175  AllMinGIDs_int_ = new int[NumProc+1];
176  for (int i=0; i<NumProc+1; i++) AllMinGIDs_int_[i] = Directory.AllMinGIDs_int_[i];
177  }
178 #endif
179 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
180  if (Directory.AllMinGIDs_LL_!=0) {
181  int NumProc = DirectoryMap_->Comm().NumProc();
182  AllMinGIDs_LL_ = new long long[NumProc+1];
183  for (int i=0; i<NumProc+1; i++) AllMinGIDs_LL_[i] = Directory.AllMinGIDs_LL_[i];
184  }
185 #endif
186 
187  if (Directory.numProcLists_ > 0) {
188  int num = Directory.numProcLists_;
189  ProcListLens_ = new int[num];
190  ProcListLists_ = new int*[num];
191  numProcLists_ = num;
192 
193  for(int i=0; i<num; ++i) {
194  int len = Directory.ProcListLens_[i];
195  ProcListLens_[i] = len;
196 
197  if (len > 0) {
198  ProcListLists_[i] = new int[len];
199  const int* dir_list = Directory.ProcListLists_[i];
200  for(int j=0; j<len; ++j) {
201  ProcListLists_[i][j] = dir_list[j];
202  }
203  }
204  else ProcListLists_[i] = 0;
205  }
206  }
207 
209 }
210 
211 //==============================================================================
212 // Epetra_BasicDirectory destructor
214 {
215  if (numProcLists_>0) {
216  for(int i=0; i<numProcLists_; ++i) {
217  if (ProcListLens_[i] > 0) delete [] ProcListLists_[i];
218  }
219  delete [] ProcListLists_; ProcListLists_ = 0;
220  delete [] ProcListLens_; ProcListLens_ = 0;
221  numProcLists_ = 0;
222  }
223 
224  if( DirectoryMap_ != 0 ) delete DirectoryMap_;
225  if( ProcList_ != 0 ) delete [] ProcList_;
226  if( LocalIndexList_ != 0 ) delete [] LocalIndexList_;
227  if( SizeList_ != 0 ) delete [] SizeList_;
228 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
229  if( AllMinGIDs_int_ != 0 ) delete [] AllMinGIDs_int_;
230  AllMinGIDs_int_ = 0;
231 #endif
232 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
233  if( AllMinGIDs_LL_ != 0 ) delete [] AllMinGIDs_LL_;
234  AllMinGIDs_LL_ = 0;
235 #endif
236 
237  DirectoryMap_ = 0;
238  ProcList_ = 0 ;
239  LocalIndexList_ = 0;
240  SizeList_ = 0;
241 }
242 
243 //==============================================================================
245 {
247  ProcListLens_ = new int[numProcLists_];
248  ProcListLists_ = new int*[numProcLists_];
249 
250  for(int i=0; i<numProcLists_; ++i) {
251  ProcListLens_[i] = 0;
252  ProcListLists_[i] = 0;
253  }
254 }
255 
256 //==============================================================================
258 {
259  int insertPoint = -1;
260  int index = Epetra_Util_binary_search(proc, ProcListLists_[LID],
261  ProcListLens_[LID], insertPoint);
262  if (index < 0) {
263  int tmp = ProcListLens_[LID];
264  Epetra_Util_insert(proc, insertPoint, ProcListLists_[LID],
265  ProcListLens_[LID], tmp, 1);
266  }
267 }
268 
269 //==============================================================================
270 // Generate: Generates Directory Tables
271 template<typename int_type>
273 {
274  int i;
276  int_type MinAllGID = (int_type) Map.MinAllGID64();
277  int_type MaxAllGID = (int_type) Map.MaxAllGID64();
278  // DirectoryMap will have a range of elements from the minimum to the maximum
279  // GID of the user map, and an IndexBase of MinAllGID from the user map
280  int_type Dir_NumGlobalElements = MaxAllGID - MinAllGID + 1;
281 
282  // Create a uniform linear map to contain the directory
283  DirectoryMap_ = new Epetra_Map( Dir_NumGlobalElements, MinAllGID, Map.Comm() );
284 
285  int Dir_NumMyElements = DirectoryMap_->NumMyElements(); // Get NumMyElements
286 
287 
288 
289  // Allocate Processor list and Local Index List. Initialize to -1s.
290 
291  if (Dir_NumMyElements>0) {
292  ProcList_ = new int[ Dir_NumMyElements ];
293  LocalIndexList_ = new int[ Dir_NumMyElements ];
294  if (!SizeIsConst_) SizeList_ = new int[ Dir_NumMyElements ];
295  // Initialize values to -1 in case the user global element list does
296  // fill all IDs from MinAllGID to MaxAllGID (e.g., allows global indices to be
297  // all even integers.
298  for (i=0; i<Dir_NumMyElements; i++) {
299  ProcList_[i] = -1;
300  LocalIndexList_[i] = -1;
301  if (!SizeIsConst_) SizeList_[i] = -1;
302  }
303  }
304 
305 
306  // Get list of processors owning the directory entries for the Map GIDs
307 
308  int MyPID = Map.Comm().MyPID();
309 
310  int Map_NumMyElements = Map.NumMyElements();
311  int * send_procs = 0;
312  if (Map_NumMyElements>0) send_procs = new int[Map_NumMyElements];
313  int_type * Map_MyGlobalElements = 0;
314 #if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
315  Map.MyGlobalElementsPtr(Map_MyGlobalElements);
316 
317  EPETRA_CHK_ERR(DirectoryMap_->RemoteIDList(Map_NumMyElements,
318  Map_MyGlobalElements,
319  send_procs, 0));
320 #endif
321 
322  bool det_flag = true;
323 
324  int num_recvs=0;
325 
326  Epetra_Distributor * Distor = Map.Comm().CreateDistributor();
327 
328  EPETRA_CHK_ERR(Distor->CreateFromSends( Map_NumMyElements, send_procs, det_flag, num_recvs ));
329 
330  if (Map_NumMyElements>0) delete [] send_procs;
331 
332  int * export_elements = 0;
333  char * c_import_elements = 0;
334  int * import_elements = 0;
335  int len_import_elements = 0;
336  int * ElementSizeList = 0;
337 
338  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)
339  if (!SizeIsConst_) packetSize++; // Must send element size info also
340 
341  if (Map_NumMyElements>0) {
342  if (!SizeIsConst_) ElementSizeList = Map.ElementSizeList();
343  export_elements = new int[ packetSize * Map_NumMyElements ];
344  int * ptr = export_elements;
345  for( i = 0; i < Map_NumMyElements; i++ )
346  {
347  *(int_type*)ptr = Map_MyGlobalElements[i];
348  ptr += sizeof(int_type)/sizeof(int);
349  *ptr++ = MyPID;
350  *ptr++ = i;
351  if (!SizeIsConst_) *ptr++ = ElementSizeList[i];
352  }
353  }
354 
355  //if (num_recvs>0) import_elements = new int[ packetSize * num_recvs ];
356  //for (i=0; i< packetSize*num_recvs; i++) import_elements[i] = 0;
357 
358  EPETRA_CHK_ERR(Distor->Do(reinterpret_cast<char *> (export_elements),
359  packetSize * (int)sizeof( int ),
360  len_import_elements,
361  c_import_elements ));
362 
363  import_elements = reinterpret_cast<int *>(c_import_elements);
364 
365  //bool MYPID = (Map.Comm().MyPID()==0);
366  int curr_LID;
367  //if (MYPID) cout << "Processor " << Map.Comm().MyPID()<< " num_recvs = "<< num_recvs << std::endl << flush;
368  int * ptr = import_elements;
369  for( i = 0; i < num_recvs; i++ )
370  {
371  curr_LID = DirectoryMap_->LID(*(int_type*)ptr); // Convert incoming GID to Directory LID
372  ptr += sizeof(int_type)/sizeof(int);
373  //if (MYPID) cout << " Receive ID = " << i << " GID = " << import_elements[3*i] << " LID = " << curr_LID << std::endl << flush;
374  assert(curr_LID !=-1); // Internal error
375  int proc = *ptr++;
376  if (ProcList_[curr_LID] >= 0) {
377  if (ProcList_[curr_LID] != proc) {
378  if (numProcLists_ < 1) {
380  }
381 
382  addProcToList(ProcList_[curr_LID], curr_LID);
383  addProcToList(proc, curr_LID);
384 
385  //leave the lowest-numbered proc in ProcList_[curr_LID].
386  ProcList_[curr_LID] = ProcListLists_[curr_LID][0];
387  }
388  }
389  else {
390  ProcList_[curr_LID] = proc;
391  }
392  LocalIndexList_[ curr_LID ] = *ptr++;
393  if (!SizeIsConst_) SizeList_[ curr_LID ] = *ptr++;
394  }
395 
396  int localval, globalval;
397  localval = numProcLists_;
398  DirectoryMap_->Comm().MaxAll(&localval, &globalval, 1);
399  entryOnMultipleProcs_ = globalval > 0 ? true : false;
400 
401  if (len_import_elements!=0) delete [] c_import_elements;
402  if (export_elements!=0) delete [] export_elements;
403 
404  delete Distor;
405  return(0);
406 }
407 
408 //==============================================================================
410 {
411  return( !entryOnMultipleProcs_ );
412 }
413 
414 //==============================================================================
415 // GetDirectoryEntries: Get non-local GID references ( procID and localID )
416 // Space should already be allocated for Procs and
417 // LocalEntries.
418 template<typename int_type>
420  const int NumEntries,
421  const int_type * GlobalEntries,
422  int * Procs,
423  int * LocalEntries,
424  int * EntrySizes,
425  bool high_rank_sharing_procs) const
426 {
427  int ierr = 0;
428  int j;
429  int i;
430  int MyPID = Map.Comm().MyPID();
431  int NumProc = Map.Comm().NumProc();
432  int_type n_over_p = (int_type) (Map.NumGlobalElements64() / NumProc);
433 
434  // Test for simple cases
435 
436  // Uniprocessor and local map cases
437 
438  if (!Map.DistributedGlobal()) {
439  int ElementSize = 0;
440  int * ElementSizeList = 0;
441  bool ConstantElementSize = Map.ConstantElementSize();
442  if (ConstantElementSize)
443  ElementSize = Map.MaxElementSize();
444  else
445  ElementSizeList = Map.ElementSizeList();
446  for (i=0; i<NumEntries; i++) {
447  int LID = Map.LID(GlobalEntries[i]); // Get LID
448  // Procs[i] will be MyPID, or -1 if the GID is not owned by this map
449  if (LID==-1) {
450  Procs[i] = -1;
451  ierr = 1; // Send warning error back that one of the GIDs is not part of this map
452  }
453  else Procs[i] = MyPID;
454 
455  // Put LID in return array if needed
456  if (LocalEntries!=0) LocalEntries[i] = LID;
457 
458  // Fill EntrySizes if needed
459  if (EntrySizes!=0) {
460  if (ConstantElementSize)
461  EntrySizes[i] = ElementSize;
462  else if (LID>-1)
463  EntrySizes[i] = ElementSizeList[LID];
464  else
465  EntrySizes[i] = 0;
466  }
467  }
468  EPETRA_CHK_ERR(ierr);
469  return(0);
470  }
471 
472  // Linear Map case
473  if (Map.LinearMap()) {
474 
475  int_type MinAllGID = (int_type) Map.MinAllGID64(); // Get Min of all GID
476  int_type MaxAllGID = (int_type) Map.MaxAllGID64(); // Get Max of all GID
477  for (i=0; i<NumEntries; i++) {
478  int LID = -1; // Assume not found
479  int Proc = -1;
480  int_type GID = GlobalEntries[i];
481  if (GID<MinAllGID) ierr = 1;
482  else if (GID>MaxAllGID) ierr = 1;
483  else {
484  // Guess uniform distribution and start a little above it
485  int Proc1 = (int) EPETRA_MIN(GID/EPETRA_MAX(n_over_p,(int_type)1) + 2, (int_type) NumProc-1);
486  bool found = false;
487  const int_type* AllMinGIDs_ptr = AllMinGIDs<int_type>();
488 
489  while (Proc1 >= 0 && Proc1< NumProc) {
490  if (AllMinGIDs_ptr[Proc1]<=GID) {
491  if (GID <AllMinGIDs_ptr[Proc1+1]) {
492  found = true;
493  break;
494  }
495  else Proc1++;
496  }
497  else Proc1--;
498  }
499  if (found) {
500  Proc = Proc1;
501  LID = (int) (GID - AllMinGIDs_ptr[Proc]);
502  }
503  }
504  Procs[i] = Proc;
505  if (LocalEntries!=0) LocalEntries[i] = LID;
506  }
507  if (EntrySizes!=0) {
508  if (Map.ConstantElementSize()) {
509  int ElementSize = Map.MaxElementSize();
510  for (i=0; i<NumEntries; i++) EntrySizes[i] = ElementSize;
511  }
512  else {
513  int * ElementSizeList = Map.ElementSizeList(); // We know this exists
514 
515 
516  Epetra_Distributor * Size_Distor = Map.Comm().CreateDistributor();
517 
518  int Size_num_sends;
519  int_type * Size_send_gids = 0;
520  int * Size_send_procs = 0;
521 
522 
523  EPETRA_CHK_ERR(Size_Distor->CreateFromRecvs( NumEntries, GlobalEntries, Procs, true,
524  Size_num_sends, Size_send_gids, Size_send_procs ));
525 
526  int * Size_exports = 0;
527  char * c_Size_imports = 0;
528  int * Size_imports = 0;
529  int packetSize = (int) (sizeof(int_type) + sizeof(int))/sizeof(int);
530  if (Size_num_sends>0) {
531  Size_exports = new int[ packetSize * Size_num_sends ];
532  for( i = 0; i < Size_num_sends; i++ )
533  {
534  int_type Size_curr_GID = Size_send_gids[i];
535  int Size_curr_LID = Map.LID(Size_curr_GID);
536  assert(Size_curr_LID!=-1); // Internal error
537  *(int_type*)(Size_exports + packetSize*i) = Size_curr_GID;
538  int Size_curr_size = ElementSizeList[Size_curr_LID];
539  *(Size_exports + packetSize*i + (packetSize - 1)) = Size_curr_size;
540  }
541  }
542 
543  int len_Size_imports = 0;
544  EPETRA_CHK_ERR(Size_Distor->Do( reinterpret_cast<char*> (Size_exports),
545  packetSize * (int)sizeof( int ),
546  len_Size_imports,
547  c_Size_imports));
548  Size_imports = reinterpret_cast<int*>(c_Size_imports);
549 
550  for( i = 0; i < NumEntries; i++ )
551  {
552 
553  // Need to change !!!!
554  //bool found = false;
555  int_type Size_curr_GID = *(int_type*)(Size_imports + packetSize*i);
556  for( j = 0; j < NumEntries; j++ )
557  if( Size_curr_GID == GlobalEntries[j] )
558  {
559  EntrySizes[j] = *(Size_imports + packetSize*i + (packetSize - 1));
560  // found = true;
561  break;
562  }
563  // if (!found) cout << "Internal error: Epetra_BasicDirectory::GetDirectoryEntries: Global Index " << curr_LID
564  // << " not on processor " << MyPID << std::endl; abort();
565  }
566 
567  if( Size_send_gids != 0 ) delete [] Size_send_gids;
568  if( Size_send_procs != 0 ) delete [] Size_send_procs;
569 
570  if( len_Size_imports != 0 ) delete [] c_Size_imports;
571  if( Size_exports != 0 ) delete [] Size_exports;
572 
573  delete Size_Distor;
574  }
575  }
576  EPETRA_CHK_ERR(ierr);
577  return(0);
578  }
579 
580  // General case (need to set up an actual directory structure)
581 
582  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
583  bool DoSizes = false;
584  if (EntrySizes!=0) {
585  if (Map.ConstantElementSize()) {
586  int ElementSize = Map.MaxElementSize();
587  for (i=0; i<NumEntries; i++) EntrySizes[i] = ElementSize;
588  }
589  else {
590  DoSizes = true;
591  PacketSize++; // Sending Size info
592  }
593  }
594 
595  bool DoLIDs = (LocalEntries!=0); // Do LIDs?
596  if (DoLIDs) PacketSize++; // Sending LIDs also
597 
598 
600 
601 
602  int * dir_procs = 0;
603  if (NumEntries>0) dir_procs = new int[ NumEntries ];
604 
605 #if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
606  // Get directory locations for the requested list of entries
607  DirectoryMap_->RemoteIDList(NumEntries, GlobalEntries, dir_procs, 0);
608 #endif
609 
610  //Check for unfound GlobalEntries and set corresponding Procs to -1
611  int NumMissing = 0;
612  {for( i = 0; i < NumEntries; ++i )
613  if( dir_procs[i] == -1 )
614  {
615  Procs[i] = -1;
616  if (DoLIDs) LocalEntries[i] = -1;
617  ++NumMissing;
618  }}
619 
620  int num_sends;
621  int_type * send_gids = 0;
622  int * send_procs = 0;
623 
624  EPETRA_CHK_ERR(Distor->CreateFromRecvs( NumEntries, GlobalEntries, dir_procs, true,
625  num_sends, send_gids, send_procs));
626 
627  if (NumEntries>0) delete [] dir_procs;
628 
629 
630  int curr_LID;
631  int * exports = 0;
632  char * c_imports = 0;
633  int * imports = 0;
634  int len_imports = 0;
635  if (num_sends>0) {
636  exports = new int[ PacketSize * num_sends ];
637  int * ptr = exports;
638  for( i = 0; i < num_sends; i++ )
639  {
640  int_type curr_GID = send_gids[i];
641  *(int_type*)ptr = curr_GID;
642  ptr += sizeof(int_type)/sizeof(int);
643  curr_LID = DirectoryMap_->LID(curr_GID);
644  assert(curr_LID!=-1); // Internal error
645  if (high_rank_sharing_procs==false) {
646  *ptr++ = ProcList_[ curr_LID ];
647  }
648  else {
649  //high_rank_sharing_procs==true means that if multiple procs share a
650  //GID, we want to use the proc with highest rank rather than the
651  //proc with lowest rank.
652  if (numProcLists_ > 0) {
653  int num = ProcListLens_[curr_LID];
654  if (num > 1) {
655  *ptr++ = ProcListLists_[curr_LID][num-1];
656  }
657  else {
658  *ptr++ = ProcList_[ curr_LID ];
659  }
660  }
661  else {
662  *ptr++ = ProcList_[ curr_LID ];
663  }
664  }
665 
666  if (DoLIDs) *ptr++ = LocalIndexList_[curr_LID];
667  if (DoSizes) *ptr++ = SizeList_[curr_LID];
668  }
669  }
670 
671  int NumRecv = NumEntries - NumMissing;
672  EPETRA_CHK_ERR(Distor->Do(reinterpret_cast<char*> (exports),
673  PacketSize * (int)sizeof( int ),
674  len_imports,
675  c_imports));
676  imports = reinterpret_cast<int*>(c_imports);
677 
678  //create a sorted copy of the GlobalEntries array, along with a companion
679  //array that will allow us to put result arrays (Procs, LocalEntries &
680  //EntrySizes) in the same order as the unsorted GlobalEntries array
681  int* sortedGE_int = new int[NumEntries*(1 + sizeof(int_type)/sizeof(int))];
682  int* offsets = sortedGE_int+NumEntries*sizeof(int_type)/sizeof(int);
683  int_type* sortedGE = reinterpret_cast<int_type*>(sortedGE_int);
684 
685  for(i=0; i<NumEntries; ++i) {
686  offsets[i] = i;
687  }
688 
689  std::memcpy(sortedGE, GlobalEntries, NumEntries*sizeof(int_type));
690  Epetra_Util Utils;
691  Utils.Sort(true, NumEntries, sortedGE, 0, 0, 1, &offsets, 0, 0);
692 
693  int * ptr = imports;
694  int insertPoint; //insertPoint won't be used, but is argument to binary_search
695 
696  for( i = 0; i < NumRecv; i++ ) {
697  int_type theCurrentLID = *(int_type*)ptr;
698  ptr += sizeof(int_type)/sizeof(int);
699  j = Epetra_Util_binary_search(theCurrentLID, sortedGE, NumEntries, insertPoint);
700  if (j > -1) {
701  Procs[offsets[j]] = *ptr++;
702  if (DoLIDs) LocalEntries[offsets[j]] = *ptr++;
703  if (DoSizes) EntrySizes[offsets[j]] = *ptr++;
704  }
705  }
706 
707  delete [] sortedGE_int;
708 
709  if( send_gids ) delete [] send_gids;
710  if( send_procs ) delete [] send_procs;
711 
712  if( len_imports ) delete [] c_imports;
713  if( exports ) delete [] exports;
714 
715  delete Distor;
716  return(0);
717 }
718 
719 //==============================================================================
720 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
722  const int NumEntries,
723  const int * GlobalEntries,
724  int * Procs,
725  int * LocalEntries,
726  int * EntrySizes,
727  bool high_rank_sharing_procs) const
728 {
729  if(!Map.GlobalIndicesInt())
730  throw "Epetra_BasicDirectory::GetDirectoryEntries: int version can't be called for non int map";
731 
732  return GetDirectoryEntries<int>(Map, NumEntries, GlobalEntries, Procs,
733  LocalEntries, EntrySizes, high_rank_sharing_procs);
734 }
735 #endif
736 
737 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
738 // GetDirectoryEntries: Get non-local GID references ( procID and localID )
739 // Space should already be allocated for Procs and
740 // LocalEntries.
742  const int NumEntries,
743  const long long * GlobalEntries,
744  int * Procs,
745  int * LocalEntries,
746  int * EntrySizes,
747  bool high_rank_sharing_procs) const
748 {
749  if(!Map.GlobalIndicesLongLong())
750  throw "Epetra_BasicDirectory::GetDirectoryEntries: long long version can't be called for non long long map";
751 
752  return GetDirectoryEntries<long long>(Map, NumEntries, GlobalEntries, Procs,
753  LocalEntries, EntrySizes, high_rank_sharing_procs);
754 }
755 #endif
756 
757 //==============================================================================
758 void Epetra_BasicDirectory::Print(std::ostream & os) const {
759 
760  int MyPID;
761  if( DirectoryMap_ != 0 ) {;
762  MyPID = DirectoryMap_->Comm().MyPID();
763  os << MyPID << " Epetra_BasicDirectory Object: "
764  << DirectoryMap_->NumMyElements() << std::endl;
765  for( int i = 0; i < DirectoryMap_->NumMyElements(); i++ ) {
766  os << " " << i << " " << ProcList_[i] << " "
767  << LocalIndexList_[i];
768  if (!SizeIsConst_)
769  os << " " << SizeList_[i];
770  os << std::endl;
771  os << std::endl;
772  }
773  }
774  else
775  {
776  std::cout << "Epetra_BasicDirectory not setup<<<<<<" << std::endl;
777  }
778 
779  return;
780 }
781 
782 //--------------------------------------------------------------------------------
784 {
785  (void)src;
786  //not currently supported
787  bool throw_error = true;
788  if (throw_error) {
789  std::cerr << std::endl
790  << "Epetra_BasicDirectory::operator= not supported."
791  << std::endl;
792  throw -1;
793  }
794  return( *this );
795 }
Epetra_Map: A class for partitioning vectors and matrices.
Definition: Epetra_Map.h:119
long long MinMyGID64() const
Epetra_Distributor: The Epetra Gather/Scatter Setup Base Class.
bool DistributedGlobal() const
Returns true if map is defined across more than one processor.
bool ConstantElementSize() const
Returns true if map has constant element size.
virtual int GatherAll(double *MyVals, double *AllVals, int Count) const =0
Epetra_Comm All Gather function.
Epetra_BasicDirectory(const Epetra_BlockMap &Map)
Epetra_BasicDirectory constructor.
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.
virtual ~Epetra_BasicDirectory(void)
Epetra_BasicDirectory destructor.
#define EPETRA_CHK_ERR(a)
#define EPETRA_MIN(x, y)
long long NumGlobalElements64() const
const Epetra_Map & DirectoryMap() const
Returns the Epetra_Map containing the directory.
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 MyPID() const =0
Return my process ID.
int * ElementSizeList() const
List of the element sizes corresponding to the array MyGlobalElements().
virtual int MaxAll(double *PartialMaxs, double *GlobalMaxs, int Count) const =0
Epetra_Comm Global Max function.
long long MaxAllGID64() const
Epetra_Util: The Epetra Util Wrapper Class.
Definition: Epetra_Util.h:79
int Generate(const Epetra_BlockMap &Map)
Generate: Sets up Directory tables.
Epetra_BasicDirectory: This class allows Epetra_Map objects to reference non-local elements...
bool GIDsAllUniquelyOwned() const
GIDsAllUniquelyOwned: returns true if all GIDs appear on just one processor.
bool GlobalIndicesInt() const
Returns true if map create with int NumGlobalElements.
int NumMyElements() const
Number of elements on the calling processor.
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
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...
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)
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.
int LID(int GID) const
Returns local ID of global ID, return -1 if not found on this processor.
long long MinAllGID64() const
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.
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)
int MyGlobalElementsPtr(int *&MyGlobalElementList) const
bool LinearMap() const
Returns true if the global ID space is contiguously divided (but not necessarily uniformly) across al...
virtual void Print(std::ostream &os) const
Print method.
bool GlobalIndicesLongLong() const
Returns true if map create with long long NumGlobalElements.
#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