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 #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 }
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.
static void EPETRA_LIB_DLL_EXPORT 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 MaxElementSize() const
Maximum element size across all processors.
void addProcToList(int proc, int LID)
#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...