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 
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 }
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:379