Tpetra parallel linear algebra  Version of the Day
Tpetra_Map_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
46 
47 #ifndef TPETRA_MAP_DEF_HPP
48 #define TPETRA_MAP_DEF_HPP
49 
50 #include "Tpetra_Directory.hpp" // must include for implicit instantiation to work
51 #include "Tpetra_Details_FixedHashTable.hpp"
52 #include "Tpetra_Util.hpp"
53 #include "Teuchos_as.hpp"
54 #include <stdexcept>
55 
56 namespace Tpetra {
57  template <class LocalOrdinal, class GlobalOrdinal, class Node>
59  Map () :
60  comm_ (new Teuchos::SerialComm<int> ()),
61  node_ (KokkosClassic::Details::getNode<Node> ()),
62  indexBase_ (0),
63  numGlobalElements_ (0),
64  numLocalElements_ (0),
65  minMyGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
66  maxMyGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
67  minAllGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
68  maxAllGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
69  firstContiguousGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
70  lastContiguousGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
71  uniform_ (false), // trivially
72  contiguous_ (false),
73  distributed_ (false), // no communicator yet
74  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
75  {}
76 
77  template <class LocalOrdinal, class GlobalOrdinal, class Node>
79  Map (global_size_t numGlobalElements,
80  GlobalOrdinal indexBase,
81  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
82  LocalGlobal lOrG,
83  const Teuchos::RCP<Node> &node) :
84  comm_ (comm),
85  node_ (node),
86  uniform_ (true),
87  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
88  {
89  using Teuchos::as;
90  using Teuchos::broadcast;
91  using Teuchos::outArg;
92  using Teuchos::reduceAll;
93  using Teuchos::REDUCE_MIN;
94  using Teuchos::REDUCE_MAX;
95  using Teuchos::typeName;
96  typedef GlobalOrdinal GO;
97  typedef global_size_t GST;
99 
100 #ifdef HAVE_TPETRA_DEBUG
101  // In debug mode only, check whether numGlobalElements and
102  // indexBase are the same over all processes in the communicator.
103  {
104  GST proc0NumGlobalElements = numGlobalElements;
105  broadcast<int, GST> (*comm_, 0, outArg (proc0NumGlobalElements));
106  GST minNumGlobalElements = numGlobalElements;
107  GST maxNumGlobalElements = numGlobalElements;
108  reduceAll<int, GST> (*comm, REDUCE_MIN, numGlobalElements, outArg (minNumGlobalElements));
109  reduceAll<int, GST> (*comm, REDUCE_MAX, numGlobalElements, outArg (maxNumGlobalElements));
110  TEUCHOS_TEST_FOR_EXCEPTION(
111  minNumGlobalElements != maxNumGlobalElements || numGlobalElements != minNumGlobalElements,
112  std::invalid_argument,
113  "Tpetra::Map constructor: All processes must provide the same number "
114  "of global elements. Process 0 set numGlobalElements = "
115  << proc0NumGlobalElements << ". The calling process "
116  << comm->getRank () << " set numGlobalElements = " << numGlobalElements
117  << ". The min and max values over all processes are "
118  << minNumGlobalElements << " resp. " << maxNumGlobalElements << ".");
119 
120  GO proc0IndexBase = indexBase;
121  broadcast<int, GO> (*comm_, 0, outArg (proc0IndexBase));
122  GO minIndexBase = indexBase;
123  GO maxIndexBase = indexBase;
124  reduceAll<int, GO> (*comm, REDUCE_MIN, indexBase, outArg (minIndexBase));
125  reduceAll<int, GO> (*comm, REDUCE_MAX, indexBase, outArg (maxIndexBase));
126  TEUCHOS_TEST_FOR_EXCEPTION(
127  minIndexBase != maxIndexBase || indexBase != minIndexBase,
128  std::invalid_argument,
129  "Tpetra::Map constructor: "
130  "All processes must provide the same indexBase argument. "
131  "Process 0 set indexBase = " << proc0IndexBase << ". The calling "
132  "process " << comm->getRank () << " set indexBase = " << indexBase
133  << ". The min and max values over all processes are "
134  << minIndexBase << " resp. " << maxIndexBase << ".");
135  }
136 #endif // HAVE_TPETRA_DEBUG
137 
138  // Distribute the elements across the processes in the given
139  // communicator so that global IDs (GIDs) are
140  //
141  // - Nonoverlapping (only one process owns each GID)
142  // - Contiguous (the sequence of GIDs is nondecreasing, and no two
143  // adjacent GIDs differ by more than one)
144  // - As evenly distributed as possible (the numbers of GIDs on two
145  // different processes do not differ by more than one)
146 
147  // All processes have the same numGlobalElements, but we still
148  // need to check that it is valid. numGlobalElements must be
149  // positive and not the "invalid" value (GSTI).
150  //
151  // This comparison looks funny, but it avoids compiler warnings
152  // for comparing unsigned integers (numGlobalElements_in is a
153  // GST, which is unsigned) while still working if we
154  // later decide to make GST signed.
155  TEUCHOS_TEST_FOR_EXCEPTION(
156  (numGlobalElements < 1 && numGlobalElements != 0),
157  std::invalid_argument,
158  "Tpetra::Map constructor: numGlobalElements (= "
159  << numGlobalElements << ") must be nonnegative.");
160 
161  TEUCHOS_TEST_FOR_EXCEPTION(
162  numGlobalElements == GSTI, std::invalid_argument,
163  "Tpetra::Map constructor: You provided numGlobalElements = Teuchos::"
164  "OrdinalTraits<Tpetra::global_size_t>::invalid(). This version of the "
165  "constructor requires a valid value of numGlobalElements. You "
166  "probably mistook this constructor for the \"contiguous nonuniform\" "
167  "constructor, which can compute the global number of elements for you "
168  "if you set numGlobalElements to that value.");
169 
170  size_t numLocalElements = 0; // will set below
171  if (lOrG == GloballyDistributed) {
172  // Compute numLocalElements:
173  //
174  // If numGlobalElements == numProcs * B + remainder,
175  // then Proc r gets B+1 elements if r < remainder,
176  // and B elements if r >= remainder.
177  //
178  // This strategy is valid for any value of numGlobalElements and
179  // numProcs, including the following border cases:
180  // - numProcs == 1
181  // - numLocalElements < numProcs
182  //
183  // In the former case, remainder == 0 && numGlobalElements ==
184  // numLocalElements. In the latter case, remainder ==
185  // numGlobalElements && numLocalElements is either 0 or 1.
186  const GST numProcs = static_cast<GST> (comm_->getSize ());
187  const GST myRank = static_cast<GST> (comm_->getRank ());
188  const GST quotient = numGlobalElements / numProcs;
189  const GST remainder = numGlobalElements - quotient * numProcs;
190 
191  GO startIndex;
192  if (myRank < remainder) {
193  numLocalElements = static_cast<size_t> (1) + static_cast<size_t> (quotient);
194  // myRank was originally an int, so it should never overflow
195  // reasonable GO types.
196  startIndex = as<GO> (myRank) * as<GO> (numLocalElements);
197  } else {
198  numLocalElements = as<size_t> (quotient);
199  startIndex = as<GO> (myRank) * as<GO> (numLocalElements) +
200  as<GO> (remainder);
201  }
202 
203  minMyGID_ = indexBase + startIndex;
204  maxMyGID_ = indexBase + startIndex + numLocalElements - 1;
205  minAllGID_ = indexBase;
206  maxAllGID_ = indexBase + numGlobalElements - 1;
207  distributed_ = (numProcs > 1);
208  }
209  else { // lOrG == LocallyReplicated
210  numLocalElements = as<size_t> (numGlobalElements);
211  minMyGID_ = indexBase;
212  maxMyGID_ = indexBase + numGlobalElements - 1;
213  distributed_ = false;
214  }
215 
216  minAllGID_ = indexBase;
217  maxAllGID_ = indexBase + numGlobalElements - 1;
218  indexBase_ = indexBase;
219  numGlobalElements_ = numGlobalElements;
220  numLocalElements_ = numLocalElements;
221  firstContiguousGID_ = minMyGID_;
222  lastContiguousGID_ = maxMyGID_;
223  contiguous_ = true;
224 
225  // Create the Directory on demand in getRemoteIndexList().
226  //setupDirectory ();
227  }
228 
229  template <class LocalOrdinal, class GlobalOrdinal, class Node>
231  Map (global_size_t numGlobalElements,
232  size_t numLocalElements,
233  GlobalOrdinal indexBase,
234  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
235  const Teuchos::RCP<Node> &node) :
236  comm_ (comm),
237  node_ (node),
238  uniform_ (false),
239  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
240  {
241  using Teuchos::as;
242  using Teuchos::broadcast;
243  using Teuchos::outArg;
244  using Teuchos::reduceAll;
245  using Teuchos::REDUCE_MIN;
246  using Teuchos::REDUCE_MAX;
247  using Teuchos::REDUCE_SUM;
248  using Teuchos::scan;
249  typedef GlobalOrdinal GO;
250  typedef global_size_t GST;
252 
253 #ifdef HAVE_TPETRA_DEBUG
254  // Keep this for later debug checks.
255  GST debugGlobalSum = 0; // Will be global sum of numLocalElements
256  reduceAll<int, GST> (*comm, REDUCE_SUM, as<GST> (numLocalElements),
257  outArg (debugGlobalSum));
258  // In debug mode only, check whether numGlobalElements and
259  // indexBase are the same over all processes in the communicator.
260  {
261  GST proc0NumGlobalElements = numGlobalElements;
262  broadcast<int, GST> (*comm_, 0, outArg (proc0NumGlobalElements));
263  GST minNumGlobalElements = numGlobalElements;
264  GST maxNumGlobalElements = numGlobalElements;
265  reduceAll<int, GST> (*comm, REDUCE_MIN, numGlobalElements, outArg (minNumGlobalElements));
266  reduceAll<int, GST> (*comm, REDUCE_MAX, numGlobalElements, outArg (maxNumGlobalElements));
267  TEUCHOS_TEST_FOR_EXCEPTION(
268  minNumGlobalElements != maxNumGlobalElements || numGlobalElements != minNumGlobalElements,
269  std::invalid_argument,
270  "Tpetra::Map constructor: All processes must provide the same number "
271  "of global elements. This is true even if that argument is Teuchos::"
272  "OrdinalTraits<global_size_t>::invalid() to signal that the Map should "
273  "compute the global number of elements. Process 0 set numGlobalElements"
274  " = " << proc0NumGlobalElements << ". The calling process "
275  << comm->getRank () << " set numGlobalElements = " << numGlobalElements
276  << ". The min and max values over all processes are "
277  << minNumGlobalElements << " resp. " << maxNumGlobalElements << ".");
278 
279  GO proc0IndexBase = indexBase;
280  broadcast<int, GO> (*comm_, 0, outArg (proc0IndexBase));
281  GO minIndexBase = indexBase;
282  GO maxIndexBase = indexBase;
283  reduceAll<int, GO> (*comm, REDUCE_MIN, indexBase, outArg (minIndexBase));
284  reduceAll<int, GO> (*comm, REDUCE_MAX, indexBase, outArg (maxIndexBase));
285  TEUCHOS_TEST_FOR_EXCEPTION(
286  minIndexBase != maxIndexBase || indexBase != minIndexBase,
287  std::invalid_argument,
288  "Tpetra::Map constructor: "
289  "All processes must provide the same indexBase argument. "
290  "Process 0 set indexBase = " << proc0IndexBase << ". The calling "
291  "process " << comm->getRank () << " set indexBase = " << indexBase
292  << ". The min and max values over all processes are "
293  << minIndexBase << " resp. " << maxIndexBase << ".");
294 
295  // Make sure that the sum of numLocalElements over all processes
296  // equals numGlobalElements.
297  TEUCHOS_TEST_FOR_EXCEPTION(
298  numGlobalElements != GSTI && debugGlobalSum != numGlobalElements,
299  std::invalid_argument,
300  "Tpetra::Map constructor: The sum of numLocalElements over all "
301  "processes = " << debugGlobalSum << " != numGlobalElements = "
302  << numGlobalElements << ". If you would like this constructor to "
303  "compute numGlobalElements for you, you may set numGlobalElements = "
304  "Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid() on input.");
305  }
306 #endif // HAVE_TPETRA_DEBUG
307 
308  // Distribute the elements across the nodes so that they are
309  // - non-overlapping
310  // - contiguous
311 
312  // This differs from the first Map constructor (that only takes a
313  // global number of elements) in that the user has specified the
314  // number of local elements, so that the elements are not
315  // (necessarily) evenly distributed over the processes.
316 
317  // Compute my local offset. This is an inclusive scan, so to get
318  // the final offset, we subtract off the input.
319  GO scanResult = 0;
320  scan<int, GO> (*comm, REDUCE_SUM, numLocalElements, outArg (scanResult));
321  const GO myOffset = scanResult - numLocalElements;
322 
323  if (numGlobalElements != GSTI) {
324  numGlobalElements_ = numGlobalElements; // Use the user's value.
325  } else {
326  // Inclusive scan means that the last process has the final sum.
327  // Rather than doing a reduceAll to get the sum of
328  // numLocalElements, we can just have the last process broadcast
329  // its result. That saves us a round of log(numProcs) messages.
330  const int numProcs = comm->getSize ();
331  GST globalSum = scanResult;
332  if (numProcs > 1) {
333  broadcast (*comm, numProcs - 1, outArg (globalSum));
334  }
335  numGlobalElements_ = globalSum;
336 
337 #ifdef HAVE_TPETRA_DEBUG
338  // No need for an all-reduce here; both come from collectives.
339  TEUCHOS_TEST_FOR_EXCEPTION(
340  globalSum != debugGlobalSum, std::logic_error,
341  "Tpetra::Map constructor (contiguous nonuniform): "
342  "globalSum = " << globalSum << " != debugGlobalSum = " << debugGlobalSum
343  << ". Please report this bug to the Tpetra developers.");
344 #endif // HAVE_TPETRA_DEBUG
345  }
346  numLocalElements_ = numLocalElements;
347  indexBase_ = indexBase;
348  minAllGID_ = indexBase;
349  // numGlobalElements might be GSTI; use numGlobalElements_;
350  maxAllGID_ = indexBase + numGlobalElements_ - 1;
351  minMyGID_ = indexBase + myOffset;
352  maxMyGID_ = indexBase + myOffset + numLocalElements - 1;
353  firstContiguousGID_ = minMyGID_;
354  lastContiguousGID_ = maxMyGID_;
355  contiguous_ = true;
356  distributed_ = checkIsDist ();
357 
358  // Create the Directory on demand in getRemoteIndexList().
359  //setupDirectory ();
360  }
361 
362  template <class LocalOrdinal, class GlobalOrdinal, class Node>
364  Map (global_size_t numGlobalElements,
365  const Teuchos::ArrayView<const GlobalOrdinal> &entryList,
366  GlobalOrdinal indexBase,
367  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
368  const Teuchos::RCP<Node> &node) :
369  comm_ (comm),
370  node_ (node),
371  uniform_ (false),
372  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
373  {
374  using Teuchos::arcp;
375  using Teuchos::ArrayView;
376  using Teuchos::as;
377  using Teuchos::broadcast;
378  using Teuchos::outArg;
379  using Teuchos::ptr;
380  using Teuchos::REDUCE_MAX;
381  using Teuchos::REDUCE_MIN;
382  using Teuchos::REDUCE_SUM;
383  using Teuchos::reduceAll;
384  using Teuchos::typeName;
385  typedef LocalOrdinal LO;
386  typedef GlobalOrdinal GO;
387  typedef global_size_t GST;
388  typedef typename ArrayView<const GO>::size_type size_type;
390 
391  // The user has specified the distribution of elements over the
392  // processes, via entryList. The distribution is not necessarily
393  // contiguous or equally shared over the processes.
394 
395  // The length of entryList on this node is the number of local
396  // elements (on this node), even though entryList contains global
397  // indices. We assume that the number of local elements can be
398  // stored in a size_t; numLocalElements_ is a size_t, so this
399  // variable and that should have the same type.
400  const size_t numLocalElements = as<size_t> (entryList.size ());
401 
402 #ifdef HAVE_TPETRA_DEBUG
403  // Keep this for later debug checks.
404  GST debugGlobalSum = 0; // Will be global sum of numLocalElements
405  reduceAll<int, GST> (*comm, REDUCE_SUM, as<GST> (numLocalElements),
406  outArg (debugGlobalSum));
407  // In debug mode only, check whether numGlobalElements and
408  // indexBase are the same over all processes in the communicator.
409  {
410  GST proc0NumGlobalElements = numGlobalElements;
411  broadcast<int, GST> (*comm_, 0, outArg (proc0NumGlobalElements));
412  GST minNumGlobalElements = numGlobalElements;
413  GST maxNumGlobalElements = numGlobalElements;
414  reduceAll<int, GST> (*comm, REDUCE_MIN, numGlobalElements, outArg (minNumGlobalElements));
415  reduceAll<int, GST> (*comm, REDUCE_MAX, numGlobalElements, outArg (maxNumGlobalElements));
416  TEUCHOS_TEST_FOR_EXCEPTION(
417  minNumGlobalElements != maxNumGlobalElements || numGlobalElements != minNumGlobalElements,
418  std::invalid_argument,
419  "Tpetra::Map constructor: All processes must provide the same number "
420  "of global elements. This is true even if that argument is Teuchos::"
421  "OrdinalTraits<global_size_t>::invalid() to signal that the Map should "
422  "compute the global number of elements. Process 0 set numGlobalElements"
423  " = " << proc0NumGlobalElements << ". The calling process "
424  << comm->getRank () << " set numGlobalElements = " << numGlobalElements
425  << ". The min and max values over all processes are "
426  << minNumGlobalElements << " resp. " << maxNumGlobalElements << ".");
427 
428  GO proc0IndexBase = indexBase;
429  broadcast<int, GO> (*comm_, 0, outArg (proc0IndexBase));
430  GO minIndexBase = indexBase;
431  GO maxIndexBase = indexBase;
432  reduceAll<int, GO> (*comm, REDUCE_MIN, indexBase, outArg (minIndexBase));
433  reduceAll<int, GO> (*comm, REDUCE_MAX, indexBase, outArg (maxIndexBase));
434  TEUCHOS_TEST_FOR_EXCEPTION(
435  minIndexBase != maxIndexBase || indexBase != minIndexBase,
436  std::invalid_argument,
437  "Tpetra::Map constructor: "
438  "All processes must provide the same indexBase argument. "
439  "Process 0 set indexBase = " << proc0IndexBase << ". The calling "
440  "process " << comm->getRank () << " set indexBase = " << indexBase
441  << ". The min and max values over all processes are "
442  << minIndexBase << " resp. " << maxIndexBase << ".");
443 
444  // Make sure that the sum of numLocalElements over all processes
445  // equals numGlobalElements.
446  TEUCHOS_TEST_FOR_EXCEPTION(
447  ((numGlobalElements != GSTI) && (debugGlobalSum != numGlobalElements)),
448  std::invalid_argument,
449  "Tpetra::Map constructor: The sum of entryList.size() over all "
450  "processes = " << debugGlobalSum << " != numGlobalElements = "
451  << numGlobalElements << ". If you would like this constructor to "
452  "compute numGlobalElements for you, you may set numGlobalElements = "
453  "Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid() on input.");
454  }
455 #endif // HAVE_TPETRA_DEBUG
456 
457  // FIXME (mfh 20 Feb 2013) The global reduction is redundant,
458  // since the directory Map will have to do the same thing. We
459  // should actually do the scan and broadcast for the directory Map
460  // here, and give the computed offsets to the directory Map's
461  // constructor.
462  if (numGlobalElements != GSTI) {
463  numGlobalElements_ = numGlobalElements; // Use the user's value.
464  } else { // The user wants us to compute the sum.
465  reduceAll<int, GST> (*comm, REDUCE_SUM, as<GST> (numLocalElements),
466  outArg (numGlobalElements_));
467  }
468 
469  // mfh 20 Feb 2013: We've never quite done the right thing for
470  // duplicate GIDs here. Duplicate GIDs have always been counted
471  // distinctly in numLocalElements_, and thus should get a
472  // different LID. However, we've always used std::map or a hash
473  // table for the GID -> LID lookup table, so distinct GIDs always
474  // map to the same LID. Furthermore, the order of the input GID
475  // list matters, so it's not desirable to sort for determining
476  // uniqueness.
477  //
478  // I've chosen for now to write this code as if the input GID list
479  // contains no duplicates. If this is not desired, we could use
480  // the lookup table itself to determine uniqueness: If we haven't
481  // seen the GID before, it gets a new LID and it's added to the
482  // LID -> GID and GID -> LID tables. If we have seen the GID
483  // before, it doesn't get added to either table. I would
484  // implement this, but it would cost more to do the double lookups
485  // in the table (one to check, and one to insert).
486 
487  numLocalElements_ = numLocalElements;
488  indexBase_ = indexBase;
489 
490  minMyGID_ = indexBase_;
491  maxMyGID_ = indexBase_;
492 
493  // NOTE (mfh 27 May 2015): While finding the initial contiguous
494  // GID range requires looking at all the GIDs in the range,
495  // dismissing an interval of GIDs only requires looking at the
496  // first and last GIDs. Thus, we could do binary search backwards
497  // from the end in order to catch the common case of a contiguous
498  // interval followed by noncontiguous entries. On the other hand,
499  // we could just expose this case explicitly as yet another Map
500  // constructor, and avoid the trouble of detecting it.
501  if (numLocalElements_ > 0) {
502  // Find contiguous GID range, with the restriction that the
503  // beginning of the range starts with the first entry. While
504  // doing so, fill in the LID -> GID table.
505  Kokkos::DualView<GO*, device_type> lgMap ("lgMap", numLocalElements_);
506  typedef typename Kokkos::DualView<GO*, device_type>::t_host::memory_space host_memory_space;
507  auto lgMap_host = lgMap.template view<host_memory_space> ();
508  lgMap.template modify<host_memory_space> ();
509 
510  firstContiguousGID_ = entryList[0];
511  lastContiguousGID_ = firstContiguousGID_+1;
512 
513  // FIXME (mfh 23 Sep 2015) We need to copy the input GIDs
514  // anyway, so we have to look at them all. The logical way to
515  // find the first noncontiguous entry would thus be to "reduce,"
516  // where the local reduction result is whether entryList[i] + 1
517  // == entryList[i+1].
518 
519  lgMap_host[0] = firstContiguousGID_;
520  size_t i = 1;
521  for ( ; i < numLocalElements_; ++i) {
522  const GO curGid = entryList[i];
523  const LO curLid = as<LO> (i);
524 
525  if (lastContiguousGID_ != curGid) break;
526 
527  // Add the entry to the LID->GID table only after we know that
528  // the current GID is in the initial contiguous sequence, so
529  // that we don't repeat adding it in the first iteration of
530  // the loop below over the remaining noncontiguous GIDs.
531  lgMap_host[curLid] = curGid;
532  ++lastContiguousGID_;
533  }
534  --lastContiguousGID_;
535 
536  // [firstContiguousGID_, lastContigousGID_] is the initial
537  // sequence of contiguous GIDs. We can start the min and max
538  // GID using this range.
539  minMyGID_ = firstContiguousGID_;
540  maxMyGID_ = lastContiguousGID_;
541 
542  // Compute the GID -> LID lookup table, _not_ including the
543  // initial sequence of contiguous GIDs.
544  ArrayView<const GO> nonContigEntries =
545  entryList (as<size_type> (i), entryList.size () - as<size_type> (i));
546  glMap_ = global_to_local_table_type (nonContigEntries, firstContiguousGID_,
547  lastContiguousGID_, as<LO> (i));
548 
549  for ( ; i < numLocalElements_; ++i) {
550  const GO curGid = entryList[i];
551  const LO curLid = as<LO> (i);
552  lgMap_host[curLid] = curGid; // LID -> GID table
553 
554  // While iterating through entryList, we compute its
555  // (process-local) min and max elements.
556  if (curGid < minMyGID_) {
557  minMyGID_ = curGid;
558  }
559  if (curGid > maxMyGID_) {
560  maxMyGID_ = curGid;
561  }
562  }
563 
564  // In the code above, we filled in lgMap on host.
565  // Now, sync it back to device.
566  typedef typename Kokkos::DualView<GO*, device_type>::t_dev::memory_space device_memory_space;
567  lgMap.template sync<device_memory_space> ();
568 
569  // "Commit" the local-to-global lookup table we filled in above.
570  lgMap_ = lgMap;
571  }
572  else {
573  // This insures tests for GIDs in the range
574  // [firstContiguousGID_, lastContiguousGID_] fail for processes
575  // with no local elements.
576  firstContiguousGID_ = indexBase_+1;
577  lastContiguousGID_ = indexBase_;
578  // glMap_ was default constructed, so it's already empty.
579  }
580 
581  // Compute the min and max of all processes' GIDs. If
582  // numLocalElements_ == 0 on this process, minMyGID_ and maxMyGID_
583  // are both indexBase_. This is wrong, but fixing it would
584  // require either a fancy sparse all-reduce, or a custom reduction
585  // operator that ignores invalid values ("invalid" means
586  // Tpetra::Details::OrdinalTraits<GO>::invalid()).
587  //
588  // Also, while we're at it, use the same all-reduce to figure out
589  // if the Map is distributed. "Distributed" means that there is
590  // at least one process with a number of local elements less than
591  // the number of global elements.
592  //
593  // We're computing the min and max of all processes' GIDs using a
594  // single MAX all-reduce, because min(x,y) = -max(-x,-y) (when x
595  // and y are signed). (This lets us combine the min and max into
596  // a single all-reduce.) If each process sets localDist=1 if its
597  // number of local elements is strictly less than the number of
598  // global elements, and localDist=0 otherwise, then a MAX
599  // all-reduce on localDist tells us if the Map is distributed (1
600  // if yes, 0 if no). Thus, we can append localDist onto the end
601  // of the data and get the global result from the all-reduce.
602  if (std::numeric_limits<GO>::is_signed) {
603  // Does my process NOT own all the elements?
604  const GO localDist =
605  (as<GST> (numLocalElements_) < numGlobalElements_) ? 1 : 0;
606 
607  GO minMaxInput[3];
608  minMaxInput[0] = -minMyGID_;
609  minMaxInput[1] = maxMyGID_;
610  minMaxInput[2] = localDist;
611 
612  GO minMaxOutput[3];
613  minMaxOutput[0] = 0;
614  minMaxOutput[1] = 0;
615  minMaxOutput[2] = 0;
616  reduceAll<int, GO> (*comm, REDUCE_MAX, 3, minMaxInput, minMaxOutput);
617  minAllGID_ = -minMaxOutput[0];
618  maxAllGID_ = minMaxOutput[1];
619  const GO globalDist = minMaxOutput[2];
620  distributed_ = (comm_->getSize () > 1 && globalDist == 1);
621  }
622  else { // unsigned; use two reductions
623  // This is always correct, no matter the signedness of GO.
624  reduceAll<int, GO> (*comm_, REDUCE_MIN, minMyGID_, outArg (minAllGID_));
625  reduceAll<int, GO> (*comm_, REDUCE_MAX, maxMyGID_, outArg (maxAllGID_));
626  distributed_ = checkIsDist ();
627  }
628 
629  contiguous_ = false; // "Contiguous" is conservative.
630 
631  TEUCHOS_TEST_FOR_EXCEPTION(
632  minAllGID_ < indexBase_,
633  std::invalid_argument,
634  "Tpetra::Map constructor (noncontiguous): "
635  "Minimum global ID = " << minAllGID_ << " over all process(es) is "
636  "less than the given indexBase = " << indexBase_ << ".");
637 
638  // Create the Directory on demand in getRemoteIndexList().
639  //setupDirectory ();
640  }
641 
642 
643  template <class LocalOrdinal, class GlobalOrdinal, class Node>
645  {}
646 
647 
648  template <class LocalOrdinal, class GlobalOrdinal, class Node>
649  bool
651  {
652  TEUCHOS_TEST_FOR_EXCEPTION(
653  getComm ().is_null (), std::logic_error, "Tpetra::Map::isOneToOne: "
654  "getComm() returns null. Please report this bug to the Tpetra "
655  "developers.");
656 
657  // This is a collective operation, if it hasn't been called before.
658  setupDirectory ();
659  return directory_->isOneToOne (*this);
660  }
661 
662 
663  template <class LocalOrdinal, class GlobalOrdinal, class Node>
664  LocalOrdinal
666  getLocalElement (GlobalOrdinal globalIndex) const
667  {
668  if (isContiguous ()) {
669  if (globalIndex < getMinGlobalIndex () ||
670  globalIndex > getMaxGlobalIndex ()) {
672  }
673  return static_cast<LocalOrdinal> (globalIndex - getMinGlobalIndex ());
674  }
675  else if (globalIndex >= firstContiguousGID_ &&
676  globalIndex <= lastContiguousGID_) {
677  return static_cast<LocalOrdinal> (globalIndex - firstContiguousGID_);
678  }
679  else {
680  // If the given global index is not in the table, this returns
681  // the same value as OrdinalTraits<LocalOrdinal>::invalid().
682  return glMap_.get (globalIndex);
683  }
684  }
685 
686  template <class LocalOrdinal, class GlobalOrdinal, class Node>
687  GlobalOrdinal
689  getGlobalElement (LocalOrdinal localIndex) const
690  {
691  if (localIndex < getMinLocalIndex () || localIndex > getMaxLocalIndex ()) {
693  }
694  if (isContiguous ()) {
695  return getMinGlobalIndex () + localIndex;
696  }
697  else {
698  // This is a host Kokkos::View access, with no RCP or ArrayRCP
699  // involvement. As a result, it is thread safe.
700  return lgMap_.h_view[localIndex];
701  }
702  }
703 
704  template <class LocalOrdinal, class GlobalOrdinal, class Node>
705  bool
707  isNodeLocalElement (LocalOrdinal localIndex) const
708  {
709  if (localIndex < getMinLocalIndex () || localIndex > getMaxLocalIndex ()) {
710  return false;
711  } else {
712  return true;
713  }
714  }
715 
716  template <class LocalOrdinal, class GlobalOrdinal, class Node>
717  bool
719  isNodeGlobalElement (GlobalOrdinal globalIndex) const {
720  return this->getLocalElement (globalIndex) !=
722  }
723 
724  template <class LocalOrdinal, class GlobalOrdinal, class Node>
726  return uniform_;
727  }
728 
729  template <class LocalOrdinal, class GlobalOrdinal, class Node>
731  return contiguous_;
732  }
733 
734  template <class LocalOrdinal, class GlobalOrdinal, class Node>
735  bool
738  {
739  using Teuchos::outArg;
740  using Teuchos::REDUCE_MIN;
741  using Teuchos::reduceAll;
742  //
743  // Tests that avoid the Boolean all-reduce below by using
744  // globally consistent quantities.
745  //
746  if (this == &map) {
747  // Pointer equality on one process always implies pointer
748  // equality on all processes, since Map is immutable.
749  return true;
750  }
751  else if (getComm ()->getSize () != map.getComm ()->getSize ()) {
752  // The two communicators have different numbers of processes.
753  // It's not correct to call isCompatible() in that case. This
754  // may result in the all-reduce hanging below.
755  return false;
756  }
757  else if (getGlobalNumElements () != map.getGlobalNumElements ()) {
758  // Two Maps are definitely NOT compatible if they have different
759  // global numbers of indices.
760  return false;
761  }
762  else if (isContiguous () && isUniform () &&
763  map.isContiguous () && map.isUniform ()) {
764  // Contiguous uniform Maps with the same number of processes in
765  // their communicators, and with the same global numbers of
766  // indices, are always compatible.
767  return true;
768  }
769  else if (! isContiguous () && ! map.isContiguous () &&
770  lgMap_.dimension_0 () != 0 && map.lgMap_.dimension_0 () != 0 &&
771  lgMap_.d_view.ptr_on_device () == map.lgMap_.d_view.ptr_on_device ()) {
772  // Noncontiguous Maps whose global index lists are nonempty and
773  // have the same pointer must be the same (and therefore
774  // contiguous).
775  //
776  // Nonempty is important. For example, consider a communicator
777  // with two processes, and two Maps that share this
778  // communicator, with zero global indices on the first process,
779  // and different nonzero numbers of global indices on the second
780  // process. In that case, on the first process, the pointers
781  // would both be NULL.
782  return true;
783  }
784 
785  TEUCHOS_TEST_FOR_EXCEPTION(
786  getGlobalNumElements () != map.getGlobalNumElements (), std::logic_error,
787  "Tpetra::Map::isCompatible: There's a bug in this method. We've already "
788  "checked that this condition is true above, but it's false here. "
789  "Please report this bug to the Tpetra developers.");
790 
791  // Do both Maps have the same number of indices on each process?
792  const int locallyCompat =
793  (getNodeNumElements () == map.getNodeNumElements ()) ? 1 : 0;
794 
795  int globallyCompat = 0;
796  reduceAll<int, int> (*comm_, REDUCE_MIN, locallyCompat, outArg (globallyCompat));
797  return (globallyCompat == 1);
798  }
799 
800  template <class LocalOrdinal, class GlobalOrdinal, class Node>
801  bool
804  {
805  using Teuchos::ArrayView;
806  typedef GlobalOrdinal GO;
807  typedef typename ArrayView<const GO>::size_type size_type;
808 
809  // If both Maps are contiguous, we can compare their GID ranges
810  // easily by looking at the min and max GID on this process.
811  // Otherwise, we'll compare their GID lists. If only one Map is
812  // contiguous, then we only have to call getNodeElementList() on
813  // the noncontiguous Map. (It's best to avoid calling it on a
814  // contiguous Map, since it results in unnecessary storage that
815  // persists for the lifetime of the Map.)
816 
817  if (getNodeNumElements () != map.getNodeNumElements ()) {
818  return false;
819  }
820  else if (getMinGlobalIndex () != map.getMinGlobalIndex () ||
821  getMaxGlobalIndex () != map.getMaxGlobalIndex ()) {
822  return false;
823  }
824  else {
825  if (isContiguous ()) {
826  if (map.isContiguous ()) {
827  return true; // min and max match, so the ranges match.
828  }
829  else { // *this is contiguous, but map is not contiguous
830  TEUCHOS_TEST_FOR_EXCEPTION(
831  ! this->isContiguous () || map.isContiguous (), std::logic_error,
832  "Tpetra::Map::locallySameAs: BUG");
833  ArrayView<const GO> rhsElts = map.getNodeElementList ();
834  const GO minLhsGid = this->getMinGlobalIndex ();
835  const size_type numRhsElts = rhsElts.size ();
836  for (size_type k = 0; k < numRhsElts; ++k) {
837  const GO curLhsGid = minLhsGid + static_cast<GO> (k);
838  if (curLhsGid != rhsElts[k]) {
839  return false; // stop on first mismatch
840  }
841  }
842  return true;
843  }
844  }
845  else if (map.isContiguous ()) { // *this is not contiguous, but map is
846  TEUCHOS_TEST_FOR_EXCEPTION(
847  this->isContiguous () || ! map.isContiguous (), std::logic_error,
848  "Tpetra::Map::locallySameAs: BUG");
849  ArrayView<const GO> lhsElts = this->getNodeElementList ();
850  const GO minRhsGid = map.getMinGlobalIndex ();
851  const size_type numLhsElts = lhsElts.size ();
852  for (size_type k = 0; k < numLhsElts; ++k) {
853  const GO curRhsGid = minRhsGid + static_cast<GO> (k);
854  if (curRhsGid != lhsElts[k]) {
855  return false; // stop on first mismatch
856  }
857  }
858  return true;
859  }
860  else if (this->lgMap_.d_view.ptr_on_device () == map.lgMap_.d_view.ptr_on_device ()) {
861  // Pointers to LID->GID "map" (actually just an array) are the
862  // same, and the number of GIDs are the same.
863  return this->getNodeNumElements () == map.getNodeNumElements ();
864  }
865  else { // we actually have to compare the GIDs
866  if (this->getNodeNumElements () != map.getNodeNumElements ()) {
867  return false; // We already checked above, but check just in case
868  }
869  else {
870  ArrayView<const GO> lhsElts = getNodeElementList ();
871  ArrayView<const GO> rhsElts = map.getNodeElementList ();
872 
873  // std::equal requires that the latter range is as large as
874  // the former. We know the ranges have equal length, because
875  // they have the same number of local entries.
876  return std::equal (lhsElts.begin (), lhsElts.end (), rhsElts.begin ());
877  }
878  }
879  }
880  }
881 
882  template <class LocalOrdinal, class GlobalOrdinal, class Node>
883  bool
886  {
887  using Teuchos::outArg;
888  using Teuchos::REDUCE_MIN;
889  using Teuchos::reduceAll;
890  //
891  // Tests that avoid the Boolean all-reduce below by using
892  // globally consistent quantities.
893  //
894  if (this == &map) {
895  // Pointer equality on one process always implies pointer
896  // equality on all processes, since Map is immutable.
897  return true;
898  }
899  else if (getComm ()->getSize () != map.getComm ()->getSize ()) {
900  // The two communicators have different numbers of processes.
901  // It's not correct to call isSameAs() in that case. This
902  // may result in the all-reduce hanging below.
903  return false;
904  }
905  else if (getGlobalNumElements () != map.getGlobalNumElements ()) {
906  // Two Maps are definitely NOT the same if they have different
907  // global numbers of indices.
908  return false;
909  }
910  else if (getMinAllGlobalIndex () != map.getMinAllGlobalIndex () ||
912  getIndexBase () != map.getIndexBase ()) {
913  // If the global min or max global index doesn't match, or if
914  // the index base doesn't match, then the Maps aren't the same.
915  return false;
916  }
917  else if (isDistributed () != map.isDistributed ()) {
918  // One Map is distributed and the other is not, which means that
919  // the Maps aren't the same.
920  return false;
921  }
922  else if (isContiguous () && isUniform () &&
923  map.isContiguous () && map.isUniform ()) {
924  // Contiguous uniform Maps with the same number of processes in
925  // their communicators, with the same global numbers of indices,
926  // and with matching index bases and ranges, must be the same.
927  return true;
928  }
929 
930  // The two communicators must have the same number of processes,
931  // with process ranks occurring in the same order. This uses
932  // MPI_COMM_COMPARE. The MPI 3.1 standard (Section 6.4) says:
933  // "Operations that access communicators are local and their
934  // execution does not require interprocess communication."
935  // However, just to be sure, I'll put this call after the above
936  // tests that don't communicate.
937  if (! Details::congruent (*comm_, * (map.getComm ()))) {
938  return false;
939  }
940 
941  // If we get this far, we need to check local properties and then
942  // communicate local sameness across all processes.
943  const int isSame_lcl = locallySameAs (map) ? 1 : 0;
944 
945  // Return true if and only if all processes report local sameness.
946  int isSame_gbl = 0;
947  reduceAll<int, int> (*comm_, REDUCE_MIN, isSame_lcl, outArg (isSame_gbl));
948  return isSame_gbl == 1;
949  }
950 
951  template <class LocalOrdinal, class GlobalOrdinal, class Node>
952  Teuchos::ArrayView<const GlobalOrdinal>
954  {
955  typedef GlobalOrdinal GO; // convenient abbreviation
956  typedef Kokkos::DualView<GO*, device_type> dual_view_type;
957  typedef typename dual_view_type::t_dev::memory_space device_memory_space;
958  typedef typename dual_view_type::t_host::memory_space host_memory_space;
959 
960  // If the local-to-global mapping doesn't exist yet, and if we
961  // have local entries, then create and fill the local-to-global
962  // mapping.
963  const bool needToCreateLocalToGlobalMapping = lgMap_.dimension_0 () == 0 && numLocalElements_ > 0;
964 
965  if (needToCreateLocalToGlobalMapping) {
966 #ifdef HAVE_TEUCHOS_DEBUG
967  // The local-to-global mapping should have been set up already
968  // for a noncontiguous map.
969  TEUCHOS_TEST_FOR_EXCEPTION( ! isContiguous(), std::logic_error,
970  "Tpetra::Map::getNodeElementList: The local-to-global mapping (lgMap_) "
971  "should have been set up already for a noncontiguous Map. Please report"
972  " this bug to the Tpetra team.");
973 #endif // HAVE_TEUCHOS_DEBUG
974 
975  typedef typename Teuchos::ArrayRCP<GO>::size_type size_type;
976  const size_type numElts = static_cast<size_type> (getNodeNumElements ());
977 
978  dual_view_type lgMap ("lgMap", numElts);
979  lgMap.template modify<host_memory_space> ();
980 
981  if (numElts != 0) {
982  auto lgMap_host = lgMap.template view<host_memory_space> ();
983  GO gid = minMyGID_;
984  for (size_type k = 0; k < numElts; ++k, ++gid) {
985  lgMap_host[k] = gid;
986  }
987  }
988 
989  // We filled in lgMap on host. Now, sync it back to device.
990  lgMap.template sync<device_memory_space> ();
991 
992  // "Commit" the local-to-global lookup table we filled in above.
993  lgMap_ = lgMap;
994  }
995 
996  const GO* lgMapHostRawPtr =
997  lgMap_.template view<host_memory_space> ().ptr_on_device ();
998  // The third argument forces ArrayView not to try to track memory
999  // in a debug build. We have to use it because the memory does
1000  // not belong to a Teuchos memory management class.
1001  return Teuchos::ArrayView<const GO> (lgMapHostRawPtr, lgMap_.dimension_0 (),
1002  Teuchos::RCP_DISABLE_NODE_LOOKUP);
1003  }
1004 
1005  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1007  return distributed_;
1008  }
1009 
1010  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1012  using Teuchos::TypeNameTraits;
1013  std::ostringstream os;
1014 
1015  os << "Tpetra::Map: {"
1016  << "LocalOrdinalType: " << TypeNameTraits<LocalOrdinal>::name ()
1017  << ", GlobalOrdinalType: " << TypeNameTraits<GlobalOrdinal>::name ()
1018  << ", NodeType: " << TypeNameTraits<Node>::name ();
1019  if (this->getObjectLabel () != "") {
1020  os << ", Label: \"" << this->getObjectLabel () << "\"";
1021  }
1022  os << ", Global number of entries: " << getGlobalNumElements ()
1023  << ", Number of processes: " << getComm ()->getSize ()
1024  << ", Uniform: " << (isUniform () ? "true" : "false")
1025  << ", Contiguous: " << (isContiguous () ? "true" : "false")
1026  << ", Distributed: " << (isDistributed () ? "true" : "false")
1027  << "}";
1028  return os.str ();
1029  }
1030 
1031  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1032  void
1034  describe (Teuchos::FancyOStream &out,
1035  const Teuchos::EVerbosityLevel verbLevel) const
1036  {
1037  using std::endl;
1038  using std::setw;
1039  using Teuchos::ArrayView;
1040  using Teuchos::as;
1041  using Teuchos::OSTab;
1042  using Teuchos::toString;
1043  using Teuchos::TypeNameTraits;
1044  using Teuchos::VERB_DEFAULT;
1045  using Teuchos::VERB_NONE;
1046  using Teuchos::VERB_LOW;
1047  using Teuchos::VERB_MEDIUM;
1048  using Teuchos::VERB_HIGH;
1049  using Teuchos::VERB_EXTREME;
1050  typedef typename ArrayView<const GlobalOrdinal>::size_type size_type;
1051 
1052  const size_t nME = getNodeNumElements ();
1053  ArrayView<const GlobalOrdinal> myEntries = getNodeElementList ();
1054  const int myRank = comm_->getRank ();
1055  const int numProcs = comm_->getSize ();
1056 
1057  const Teuchos::EVerbosityLevel vl = (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
1058 
1059  size_t width = 1;
1060  for (size_t dec=10; dec<getGlobalNumElements(); dec *= 10) {
1061  ++width;
1062  }
1063  width = std::max<size_t> (width, as<size_t> (12)) + 2;
1064 
1065  // By convention, describe() always begins with a tab before printing.
1066  OSTab tab0 (out);
1067 
1068  if (vl == VERB_NONE) {
1069  // do nothing
1070  }
1071  else if (vl == VERB_LOW) {
1072  if (myRank == 0) {
1073  out << "Tpetra::Map:" << endl;
1074  OSTab tab1 (out);
1075  out << "LocalOrdinalType: " << TypeNameTraits<LocalOrdinal>::name () << endl
1076  << "GlobalOrdinalType: " << TypeNameTraits<GlobalOrdinal>::name () << endl
1077  << "NodeType: " << TypeNameTraits<Node>::name () << endl;
1078  if (this->getObjectLabel () != "") {
1079  out << "Label: \"" << this->getObjectLabel () << "\"" << endl;
1080  }
1081  out << "Global number of entries: " << getGlobalNumElements () << endl
1082  << "Minimum global index: " << getMinAllGlobalIndex () << endl
1083  << "Maximum global index: " << getMaxAllGlobalIndex () << endl
1084  << "Index base: " << getIndexBase () << endl
1085  << "Number of processes: " << getComm ()->getSize () << endl
1086  << "Uniform: " << (isUniform () ? "true" : "false") << endl
1087  << "Contiguous: " << (isContiguous () ? "true" : "false") << endl
1088  << "Distributed: " << (isDistributed () ? "true" : "false") << endl;
1089  }
1090  }
1091 
1092  if (vl >= VERB_HIGH) { // HIGH or EXTREME
1093  for (int p = 0; p < numProcs; ++p) {
1094  if (myRank == p) {
1095  out << "Process " << myRank << ":" << endl;
1096  OSTab tab1 (out);
1097  out << "My number of entries: " << nME << endl
1098  << "My minimum global index: " << getMinGlobalIndex () << endl
1099  << "My maximum global index: " << getMaxGlobalIndex () << endl;
1100  if (vl == VERB_EXTREME) {
1101  out << "My global indices: [";
1102  for (size_type k = 0; k < myEntries.size (); ++k) {
1103  out << myEntries[k];
1104  if (k + 1 < myEntries.size ()) {
1105  out << ", ";
1106  }
1107  }
1108  out << "]" << endl;
1109  }
1110  std::flush (out);
1111  }
1112  // Do a few global ops to give I/O a chance to complete
1113  comm_->barrier ();
1114  comm_->barrier ();
1115  comm_->barrier ();
1116  }
1117  }
1118  }
1119 
1120  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1121  RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1123  replaceCommWithSubset (const Teuchos::RCP<const Teuchos::Comm<int> >& newComm) const
1124  {
1125  using Teuchos::Comm;
1126  using Teuchos::null;
1128  using Teuchos::outArg;
1129  using Teuchos::RCP;
1130  using Teuchos::rcp;
1131  using Teuchos::REDUCE_MIN;
1132  using Teuchos::reduceAll;
1133  typedef global_size_t GST;
1134  typedef LocalOrdinal LO;
1135  typedef GlobalOrdinal GO;
1136  typedef Map<LO, GO, Node> map_type;
1137 
1138  // mfh 26 Mar 2013: The lazy way to do this is simply to recreate
1139  // the Map by calling its ordinary public constructor, using the
1140  // original Map's data. This only involves O(1) all-reduces over
1141  // the new communicator, which in the common case only includes a
1142  // small number of processes.
1143 
1144  // Make Map compute the global number of elements.
1145  const GST globalNumElts = OrdinalTraits<GST>::invalid ();
1146  ArrayView<const GO> myElts = this->getNodeElementList ();
1147  RCP<Node> node = this->getNode ();
1148 
1149  // Create the Map to return.
1150  if (newComm.is_null ()) {
1151  return null; // my process does not participate in the new Map
1152  } else {
1153  // Map requires that the index base equal the global min GID.
1154  // Figuring out the global min GID requires a reduction over all
1155  // processes in the new communicator. It could be that some (or
1156  // even all) of these processes contain zero entries. (Recall
1157  // that this method, unlike removeEmptyProcesses(), may remove
1158  // an arbitrary subset of processes.) We deal with this by
1159  // doing a min over the min GID on each process if the process
1160  // has more than zero entries, or the global max GID, if that
1161  // process has zero entries. If no processes have any entries,
1162  // then the index base doesn't matter anyway.
1163  const GO myMinGid = (this->getNodeNumElements () == 0) ?
1164  this->getMaxAllGlobalIndex () : this->getMinGlobalIndex ();
1165  GO newIndexBase = OrdinalTraits<GO>::invalid ();
1166  reduceAll<int, GO> (*newComm, REDUCE_MIN, myMinGid, outArg (newIndexBase));
1167  return rcp (new map_type (globalNumElts, myElts, newIndexBase, newComm, node));
1168  }
1169  }
1170 
1171  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1172  RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1175  {
1176  using Teuchos::Comm;
1177  using Teuchos::null;
1178  using Teuchos::outArg;
1179  using Teuchos::RCP;
1180  using Teuchos::rcp;
1181  using Teuchos::REDUCE_MIN;
1182  using Teuchos::reduceAll;
1183 
1184  // Create the new communicator. split() returns a valid
1185  // communicator on all processes. On processes where color == 0,
1186  // ignore the result. Passing key == 0 tells MPI to order the
1187  // processes in the new communicator by their rank in the old
1188  // communicator.
1189  const int color = (numLocalElements_ == 0) ? 0 : 1;
1190  // MPI_Comm_split must be called collectively over the original
1191  // communicator. We can't just call it on processes with color
1192  // one, even though we will ignore its result on processes with
1193  // color zero.
1194  RCP<const Comm<int> > newComm = comm_->split (color, 0);
1195  if (color == 0) {
1196  newComm = null;
1197  }
1198 
1199  // Create the Map to return.
1200  if (newComm.is_null ()) {
1201  return null; // my process does not participate in the new Map
1202  } else {
1203  // The default constructor that's useful for clone() above is
1204  // also useful here.
1205  RCP<Map> map = rcp (new Map ());
1206 
1207  map->comm_ = newComm;
1208  map->indexBase_ = indexBase_;
1209  map->numGlobalElements_ = numGlobalElements_;
1210  map->numLocalElements_ = numLocalElements_;
1211  map->minMyGID_ = minMyGID_;
1212  map->maxMyGID_ = maxMyGID_;
1213  map->minAllGID_ = minAllGID_;
1214  map->maxAllGID_ = maxAllGID_;
1215  map->firstContiguousGID_= firstContiguousGID_;
1216  map->lastContiguousGID_ = lastContiguousGID_;
1217 
1218  // Uniformity and contiguity have not changed. The directory
1219  // has changed, but we've taken care of that above.
1220  map->uniform_ = uniform_;
1221  map->contiguous_ = contiguous_;
1222 
1223  // If the original Map was NOT distributed, then the new Map
1224  // cannot be distributed.
1225  //
1226  // If the number of processes in the new communicator is 1, then
1227  // the new Map is not distributed.
1228  //
1229  // Otherwise, we have to check the new Map using an all-reduce
1230  // (over the new communicator). For example, the original Map
1231  // may have had some processes with zero elements, and all other
1232  // processes with the same number of elements as in the whole
1233  // Map. That Map is technically distributed, because of the
1234  // processes with zero elements. Removing those processes would
1235  // make the new Map locally replicated.
1236  if (! distributed_ || newComm->getSize () == 1) {
1237  map->distributed_ = false;
1238  } else {
1239  const int iOwnAllGids = (numLocalElements_ == numGlobalElements_) ? 1 : 0;
1240  int allProcsOwnAllGids = 0;
1241  reduceAll<int, int> (*newComm, REDUCE_MIN, iOwnAllGids, outArg (allProcsOwnAllGids));
1242  map->distributed_ = (allProcsOwnAllGids == 1) ? false : true;
1243  }
1244 
1245  map->lgMap_ = lgMap_;
1246  map->glMap_ = glMap_;
1247  map->node_ = node_;
1248 
1249  // Map's default constructor creates an uninitialized Directory.
1250  // The Directory will be initialized on demand in
1251  // getRemoteIndexList().
1252  //
1253  // FIXME (mfh 26 Mar 2013) It should be possible to "filter" the
1254  // directory more efficiently than just recreating it. If
1255  // directory recreation proves a bottleneck, we can always
1256  // revisit this. On the other hand, Directory creation is only
1257  // collective over the new, presumably much smaller
1258  // communicator, so it may not be worth the effort to optimize.
1259 
1260  return map;
1261  }
1262  }
1263 
1264  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1265  void
1267  {
1268  TEUCHOS_TEST_FOR_EXCEPTION(
1269  directory_.is_null (), std::logic_error, "Tpetra::Map::setupDirectory: "
1270  "The Directory is null. "
1271  "Please report this bug to the Tpetra developers.");
1272 
1273  // Only create the Directory if it hasn't been created yet.
1274  // This is a collective operation.
1275  if (! directory_->initialized ()) {
1276  directory_->initialize (*this);
1277  }
1278  }
1279 
1280  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1281  LookupStatus
1283  getRemoteIndexList (const Teuchos::ArrayView<const GlobalOrdinal>& GIDs,
1284  const Teuchos::ArrayView<int>& PIDs,
1285  const Teuchos::ArrayView<LocalOrdinal>& LIDs) const
1286  {
1288  typedef Teuchos::ArrayView<int>::size_type size_type;
1289 
1290  // Empty Maps (i.e., containing no indices on any processes in the
1291  // Map's communicator) are perfectly valid. In that case, if the
1292  // input GID list is nonempty, we fill the output arrays with
1293  // invalid values, and return IDNotPresent to notify the caller.
1294  // It's perfectly valid to give getRemoteIndexList GIDs that the
1295  // Map doesn't own. SubmapImport test 2 needs this functionality.
1296  if (getGlobalNumElements () == 0) {
1297  if (GIDs.size () == 0) {
1298  return AllIDsPresent; // trivially
1299  } else {
1300  for (size_type k = 0; k < PIDs.size (); ++k) {
1301  PIDs[k] = OrdinalTraits<int>::invalid ();
1302  }
1303  for (size_type k = 0; k < LIDs.size (); ++k) {
1304  LIDs[k] = OrdinalTraits<LocalOrdinal>::invalid ();
1305  }
1306  return IDNotPresent;
1307  }
1308  }
1309 
1310  // getRemoteIndexList must be called collectively, and Directory
1311  // initialization is collective too, so it's OK to initialize the
1312  // Directory on demand.
1313  setupDirectory ();
1314  return directory_->getDirectoryEntries (*this, GIDs, PIDs, LIDs);
1315  }
1316 
1317  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1318  LookupStatus
1320  getRemoteIndexList (const Teuchos::ArrayView<const GlobalOrdinal> & GIDs,
1321  const Teuchos::ArrayView<int> & PIDs) const
1322  {
1323  if (getGlobalNumElements () == 0) {
1324  if (GIDs.size () == 0) {
1325  return AllIDsPresent; // trivially
1326  } else {
1327  // The Map contains no indices, so all output PIDs are invalid.
1328  for (Teuchos::ArrayView<int>::size_type k = 0; k < PIDs.size (); ++k) {
1330  }
1331  return IDNotPresent;
1332  }
1333  }
1334 
1335  // getRemoteIndexList must be called collectively, and Directory
1336  // initialization is collective too, so it's OK to initialize the
1337  // Directory on demand.
1338  setupDirectory ();
1339  return directory_->getDirectoryEntries (*this, GIDs, PIDs);
1340  }
1341 
1342  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1343  Teuchos::RCP<const Teuchos::Comm<int> >
1345  return comm_;
1346  }
1347 
1348  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1349  Teuchos::RCP<Node>
1351  return node_;
1352  }
1353 
1354  template <class LocalOrdinal,class GlobalOrdinal, class Node>
1356  using Teuchos::as;
1357  using Teuchos::outArg;
1358  using Teuchos::REDUCE_MIN;
1359  using Teuchos::reduceAll;
1360 
1361  bool global = false;
1362  if (comm_->getSize () > 1) {
1363  // The communicator has more than one process, but that doesn't
1364  // necessarily mean the Map is distributed.
1365  int localRep = 0;
1366  if (numGlobalElements_ == as<global_size_t> (numLocalElements_)) {
1367  // The number of local elements on this process equals the
1368  // number of global elements.
1369  //
1370  // NOTE (mfh 22 Nov 2011) Does this still work if there were
1371  // duplicates in the global ID list on input (the third Map
1372  // constructor), so that the number of local elements (which
1373  // are not duplicated) on this process could be less than the
1374  // number of global elements, even if this process owns all
1375  // the elements?
1376  localRep = 1;
1377  }
1378  int allLocalRep;
1379  reduceAll<int, int> (*comm_, REDUCE_MIN, localRep, outArg (allLocalRep));
1380  if (allLocalRep != 1) {
1381  // At least one process does not own all the elements.
1382  // This makes the Map a distributed Map.
1383  global = true;
1384  }
1385  }
1386  // If the communicator has only one process, then the Map is not
1387  // distributed.
1388  return global;
1389  }
1390 
1391 } // Tpetra namespace
1392 
1393 template <class LocalOrdinal, class GlobalOrdinal>
1394 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
1395 Tpetra::createLocalMap(size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm) {
1396  typedef LocalOrdinal LO;
1397  typedef GlobalOrdinal GO;
1398  typedef typename ::Tpetra::Map<LO, GO>::node_type NT;
1399  return createLocalMapWithNode<LO, GO> (numElements, comm, KokkosClassic::Details::getNode<NT> ());
1400 }
1401 
1402 template <class LocalOrdinal, class GlobalOrdinal>
1403 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
1404 Tpetra::createUniformContigMap(global_size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm) {
1405  typedef LocalOrdinal LO;
1406  typedef GlobalOrdinal GO;
1407  typedef typename ::Tpetra::Map<LO, GO>::node_type NT;
1408  return createUniformContigMapWithNode<LO, GO> (numElements, comm, KokkosClassic::Details::getNode<NT> ());
1409 }
1410 
1411 template <class LocalOrdinal, class GlobalOrdinal, class Node>
1412 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1414  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
1415  const Teuchos::RCP<Node>& node)
1416 {
1417  using Teuchos::rcp;
1419  const GlobalOrdinal indexBase = static_cast<GlobalOrdinal> (0);
1420 
1421  return rcp (new map_type (numElements, indexBase, comm, GloballyDistributed, node));
1422 }
1423 
1424 template <class LocalOrdinal, class GlobalOrdinal, class Node>
1425 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1426 Tpetra::createLocalMapWithNode (size_t numElements,
1427  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
1428  const Teuchos::RCP<Node>& node)
1429 {
1430  using Tpetra::global_size_t;
1431  using Teuchos::rcp;
1433  const GlobalOrdinal indexBase = static_cast<GlobalOrdinal> (0);
1434  const global_size_t globalNumElts = static_cast<global_size_t> (numElements);
1435 
1436  return rcp (new map_type (globalNumElts, indexBase, comm, LocallyReplicated, node));
1437 }
1438 
1439 template <class LocalOrdinal, class GlobalOrdinal, class Node>
1440 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1442  size_t localNumElements,
1443  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
1444  const Teuchos::RCP<Node>& node)
1445 {
1446  using Teuchos::rcp;
1448  const GlobalOrdinal indexBase = static_cast<GlobalOrdinal> (0);
1449 
1450  return rcp (new map_type (numElements, localNumElements, indexBase, comm, node));
1451 }
1452 
1453 template <class LocalOrdinal, class GlobalOrdinal>
1454 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
1455 Tpetra::createContigMap(Tpetra::global_size_t numElements, size_t localNumElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm) {
1456  return Tpetra::createContigMapWithNode<LocalOrdinal,GlobalOrdinal>(numElements, localNumElements, comm, KokkosClassic::DefaultNode::getDefaultNode() );
1457 }
1458 
1459 
1460 template <class LocalOrdinal, class GlobalOrdinal>
1461 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
1462 Tpetra::createNonContigMap(const Teuchos::ArrayView<const GlobalOrdinal> &elementList,
1463  const Teuchos::RCP<const Teuchos::Comm<int> > &comm)
1464 {
1465  return Tpetra::createNonContigMapWithNode<LocalOrdinal,GlobalOrdinal>(elementList, comm, KokkosClassic::DefaultNode::getDefaultNode() );
1466 }
1467 
1468 
1469 template <class LocalOrdinal, class GlobalOrdinal, class Node>
1470 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1471 Tpetra::createNonContigMapWithNode(const Teuchos::ArrayView<const GlobalOrdinal> &elementList,
1472  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
1473  const Teuchos::RCP<Node> &node)
1474 {
1475  using Teuchos::rcp;
1477  typedef Tpetra::global_size_t GST;
1478  return rcp (new map_type (Tpetra::Details::OrdinalTraits<GST>::invalid (),
1479  elementList,
1480  static_cast<GST> (0),
1481  comm,
1482  node));
1483 }
1484 
1485 template <class LocalOrdinal, class GlobalOrdinal, class Node>
1486 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1488  const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< Node > &node) {
1489  Teuchos::RCP< Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map;
1490  int sumOfWeights, elemsLeft, localNumElements;
1491  const int numImages = comm->getSize(),
1492  myImageID = comm->getRank();
1493  Teuchos::reduceAll<int>(*comm,Teuchos::REDUCE_SUM,myWeight,Teuchos::outArg(sumOfWeights));
1494  const double myShare = ((double)myWeight) / ((double)sumOfWeights);
1495  localNumElements = (int)std::floor( myShare * ((double)numElements) );
1496  // std::cout << "numElements: " << numElements << " myWeight: " << myWeight << " sumOfWeights: " << sumOfWeights << " myShare: " << myShare << std::endl;
1497  Teuchos::reduceAll<int>(*comm,Teuchos::REDUCE_SUM,localNumElements,Teuchos::outArg(elemsLeft));
1498  elemsLeft = numElements - elemsLeft;
1499  // std::cout << "(before) localNumElements: " << localNumElements << " elemsLeft: " << elemsLeft << std::endl;
1500  // i think this is true. just test it for now.
1501  TEUCHOS_TEST_FOR_EXCEPT(elemsLeft < -numImages || numImages < elemsLeft);
1502  if (elemsLeft < 0) {
1503  // last elemsLeft nodes lose an element
1504  if (myImageID >= numImages-elemsLeft) --localNumElements;
1505  }
1506  else if (elemsLeft > 0) {
1507  // first elemsLeft nodes gain an element
1508  if (myImageID < elemsLeft) ++localNumElements;
1509  }
1510  // std::cout << "(after) localNumElements: " << localNumElements << std::endl;
1511  return createContigMapWithNode<LocalOrdinal,GlobalOrdinal,Node>(numElements,localNumElements,comm,node);
1512 
1513 }
1514 
1515 
1516 template<class LO, class GO, class NT>
1517 Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >
1518 Tpetra::createOneToOne (const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >& M)
1519 {
1520  using Teuchos::Array;
1521  using Teuchos::ArrayView;
1522  using Teuchos::as;
1523  using Teuchos::rcp;
1524  typedef Tpetra::Map<LO, GO, NT> map_type;
1525  typedef global_size_t GST;
1527  const int myRank = M->getComm ()->getRank ();
1528 
1529  // Bypasses for special cases where either M is known to be
1530  // one-to-one, or the one-to-one version of M is easy to compute.
1531  // This is why we take M as an RCP, not as a const reference -- so
1532  // that we can return M itself if it is 1-to-1.
1533  if (! M->isDistributed ()) {
1534  // For a locally replicated Map, we assume that users want to push
1535  // all the GIDs to Process 0.
1536 
1537  // mfh 05 Nov 2013: getGlobalNumElements() does indeed return what
1538  // you think it should return, in this special case of a locally
1539  // replicated contiguous Map.
1540  const GST numGlobalEntries = M->getGlobalNumElements ();
1541  if (M->isContiguous ()) {
1542  const size_t numLocalEntries =
1543  (myRank == 0) ? as<size_t> (numGlobalEntries) : static_cast<size_t> (0);
1544  return rcp (new map_type (numGlobalEntries, numLocalEntries,
1545  M->getIndexBase (), M->getComm (),
1546  M->getNode ()));
1547  }
1548  else {
1549  ArrayView<const GO> myGids =
1550  (myRank == 0) ? M->getNodeElementList () : Teuchos::null;
1551  return rcp (new map_type (GINV, myGids (), M->getIndexBase (),
1552  M->getComm (), M->getNode ()));
1553 
1554  }
1555  }
1556  else if (M->isContiguous ()) {
1557  // Contiguous, distributed Maps are one-to-one by construction.
1558  // (Locally replicated Maps can be contiguous.)
1559  return M;
1560  }
1561  else {
1563  const size_t numMyElems = M->getNodeNumElements ();
1564  ArrayView<const GO> myElems = M->getNodeElementList ();
1565  Array<int> owner_procs_vec (numMyElems);
1566 
1567  directory.getDirectoryEntries (*M, myElems, owner_procs_vec ());
1568 
1569  Array<GO> myOwned_vec (numMyElems);
1570  size_t numMyOwnedElems = 0;
1571  for (size_t i = 0; i < numMyElems; ++i) {
1572  const GO GID = myElems[i];
1573  const int owner = owner_procs_vec[i];
1574 
1575  if (myRank == owner) {
1576  myOwned_vec[numMyOwnedElems++] = GID;
1577  }
1578  }
1579  myOwned_vec.resize (numMyOwnedElems);
1580 
1581  return rcp (new map_type (GINV, myOwned_vec (), M->getIndexBase (),
1582  M->getComm (), M->getNode ()));
1583  }
1584 }
1585 
1586 template<class LocalOrdinal, class GlobalOrdinal, class Node>
1587 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1590 {
1591  using Teuchos::Array;
1592  using Teuchos::ArrayView;
1593  using Teuchos::rcp;
1594  typedef LocalOrdinal LO;
1595  typedef GlobalOrdinal GO;
1596  typedef Tpetra::Map<LO,GO,Node> map_type;
1597  int myID = M->getComm()->getRank();
1598 
1599  // FIXME (mfh 20 Feb 2013) We should have a bypass for contiguous
1600  // Maps (which are 1-to-1 by construction).
1601 
1602  //Based off Epetra's one to one.
1603 
1605  directory.initialize (*M, tie_break);
1606  size_t numMyElems = M->getNodeNumElements ();
1607  ArrayView<const GO> myElems = M->getNodeElementList ();
1608  Array<int> owner_procs_vec (numMyElems);
1609 
1610  directory.getDirectoryEntries (*M, myElems, owner_procs_vec ());
1611 
1612  Array<GO> myOwned_vec (numMyElems);
1613  size_t numMyOwnedElems = 0;
1614  for (size_t i = 0; i < numMyElems; ++i) {
1615  GO GID = myElems[i];
1616  int owner = owner_procs_vec[i];
1617 
1618  if (myID == owner) {
1619  myOwned_vec[numMyOwnedElems++] = GID;
1620  }
1621  }
1622  myOwned_vec.resize (numMyOwnedElems);
1623 
1624  // FIXME (mfh 08 May 2014) The above Directory should be perfectly
1625  // valid for the new Map. Why can't we reuse it?
1626  const global_size_t GINV =
1628  return rcp (new map_type (GINV, myOwned_vec (), M->getIndexBase (),
1629  M->getComm (), M->getNode ()));
1630 }
1631 
1632 //
1633 // Explicit instantiation macro
1634 //
1635 // Must be expanded from within the Tpetra namespace!
1636 //
1637 
1639 #define TPETRA_MAP_INSTANT(LO,GO,NODE) \
1640  \
1641  template class Map< LO , GO , NODE >; \
1642  \
1643  template Teuchos::RCP< const Map<LO,GO,NODE> > \
1644  createLocalMapWithNode<LO,GO,NODE>(size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< NODE > &node); \
1645  \
1646  template Teuchos::RCP< const Map<LO,GO,NODE> > \
1647  createContigMapWithNode<LO,GO,NODE>(global_size_t numElements, size_t localNumElements, \
1648  const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< NODE > &node); \
1649  \
1650  template Teuchos::RCP< const Map<LO,GO,NODE> > \
1651  createNonContigMapWithNode(const Teuchos::ArrayView<const GO> &elementList, \
1652  const RCP<const Teuchos::Comm<int> > &comm, \
1653  const RCP<NODE> &node); \
1654  template Teuchos::RCP< const Map<LO,GO,NODE> > \
1655  createUniformContigMapWithNode<LO,GO,NODE>(global_size_t numElements, \
1656  const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< NODE > &node); \
1657  \
1658  template Teuchos::RCP< const Map<LO,GO,NODE> > \
1659  createWeightedContigMapWithNode<LO,GO,NODE>(int thisNodeWeight, global_size_t numElements, \
1660  const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< NODE > &node); \
1661  \
1662  template Teuchos::RCP<const Map<LO,GO,NODE> > \
1663  createOneToOne (const Teuchos::RCP<const Map<LO,GO,NODE> > &M); \
1664  \
1665  template Teuchos::RCP<const Map<LO,GO,NODE> > \
1666  createOneToOne (const Teuchos::RCP<const Map<LO,GO,NODE> > &M, \
1667  const Tpetra::Details::TieBreak<LO,GO> & tie_break);
1668 
1669 
1671 #define TPETRA_MAP_INSTANT_DEFAULTNODE(LO,GO) \
1672  template Teuchos::RCP< const Map<LO,GO> > \
1673  createLocalMap<LO,GO>( size_t, const Teuchos::RCP< const Teuchos::Comm< int > > &); \
1674  \
1675  template Teuchos::RCP< const Map<LO,GO> > \
1676  createContigMap<LO,GO>( global_size_t, size_t, \
1677  const Teuchos::RCP< const Teuchos::Comm< int > > &); \
1678  \
1679  template Teuchos::RCP< const Map<LO,GO> > \
1680  createNonContigMap(const Teuchos::ArrayView<const GO> &, \
1681  const RCP<const Teuchos::Comm<int> > &); \
1682  \
1683  template Teuchos::RCP< const Map<LO,GO> > \
1684  createUniformContigMap<LO,GO>( global_size_t, \
1685  const Teuchos::RCP< const Teuchos::Comm< int > > &); \
1686 
1687 #endif // TPETRA_MAP_DEF_HPP
Interface for breaking ties in ownership.
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
Definition: Tpetra_Util.cpp:65
Namespace Tpetra contains the class and methods constituting the Tpetra library.
~Map()
Destructor.
GlobalOrdinal getMinGlobalIndex() const
The minimum global index owned by the calling process.
bool isNodeGlobalElement(GlobalOrdinal globalIndex) const
Whether the given global index is owned by this Map on the calling process.
KOKKOS_INLINE_FUNCTION ValueType get(const KeyType &key) const
Get the value corresponding to the given key.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createNonContigMap(const ArrayView< const GlobalOrdinal > &elementList, const RCP< const Teuchos::Comm< int > > &comm)
Non-member constructor for a non-contiguous Map with the default Kokkos Node.
bool isContiguous() const
True if this Map is distributed contiguously, else false.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createLocalMapWithNode(size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< Node > &node=defaultArgNode< Node >())
Nonmember constructor for a locally replicated Map with a specified Kokkos Node.
bool isCompatible(const Map< LocalOrdinal, GlobalOrdinal, Node > &map) const
True if and only if map is compatible with this Map.
bool isUniform() const
Whether the range of global indices is uniform.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createContigMapWithNode(global_size_t numElements, size_t localNumElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< Node > &node=defaultArgNode< Node >())
Non-member constructor for a (potentially) non-uniformly distributed, contiguous Map with a user-spec...
GlobalOrdinal getIndexBase() const
The index base for this Map.
bool isDistributed() const
Whether this Map is globally distributed or locally replicated.
LocalOrdinal getMinLocalIndex() const
The minimum local index.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Accessors for the Teuchos::Comm and Kokkos Node objects.
GlobalOrdinal getMinAllGlobalIndex() const
The minimum global index over all processes in the communicator.
bool locallySameAs(const Map< LocalOrdinal, GlobalOrdinal, node_type > &map) const
Is the given Map locally the same as the input Map?
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createLocalMap(size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Nonmember constructor for a locally replicated Map with the default Kokkos Node.
bool isNodeLocalElement(LocalOrdinal localIndex) const
Whether the given local index is valid for this Map on the calling process.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createWeightedContigMapWithNode(int thisNodeWeight, global_size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< Node > &node)
Non-member constructor for a contiguous Map with user-defined weights and a user-specified Kokkos Nod...
Implementation details of Tpetra.
GlobalOrdinal getMaxAllGlobalIndex() const
The maximum global index over all processes in the communicator.
size_t global_size_t
Global size_t object.
Traits class for "invalid" (flag) values of integer types that Tpetra uses as local ordinals or globa...
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createUniformContigMap(global_size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Non-member constructor for a uniformly distributed, contiguous Map with the default Kokkos Node...
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createOneToOne(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &M)
Creates a one-to-one version of the given Map where each GID is owned by only one process...
RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > removeEmptyProcesses() const
Return a new Map with processes with zero elements removed.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
Teuchos::RCP< Node > getNode() const
Get this Map&#39;s Node object.
RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > replaceCommWithSubset(const Teuchos::RCP< const Teuchos::Comm< int > > &newComm) const
Replace this Map&#39;s communicator with a subset communicator.
GlobalOrdinal getMaxGlobalIndex() const
The maximum global index owned by the calling process.
LookupStatus getRemoteIndexList(const Teuchos::ArrayView< const GlobalOrdinal > &GIDList, const Teuchos::ArrayView< int > &nodeIDList, const Teuchos::ArrayView< LocalOrdinal > &LIDList) const
Return the process ranks and corresponding local indices for the given global indices.
LookupStatus getDirectoryEntries(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs) const
Given a global ID list, return the list of their owning process IDs.
LocalOrdinal getLocalElement(GlobalOrdinal globalIndex) const
The local index corresponding to the given global index.
Teuchos::ArrayView< const GlobalOrdinal > getNodeElementList() const
Return a view of the global indices owned by this process.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createContigMap(global_size_t numElements, size_t localNumElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Non-member constructor for a (potentially) non-uniformly distributed, contiguous Map with the default...
size_t getNodeNumElements() const
The number of elements belonging to the calling process.
Describes a parallel distribution of objects over processes.
bool isSameAs(const Map< LocalOrdinal, GlobalOrdinal, Node > &map) const
True if and only if map is identical to this Map.
Implement mapping from global ID to process ID and local ID.
Stand-alone utility functions and macros.
bool isOneToOne() const
Whether the Map is one to one.
void initialize(const map_type &map)
Initialize the Directory with its Map.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createNonContigMapWithNode(const ArrayView< const GlobalOrdinal > &elementList, const RCP< const Teuchos::Comm< int > > &comm, const RCP< Node > &node)
Non-member constructor for a non-contiguous Map with a user-specified Kokkos Node.
LocalGlobal
Enum for local versus global allocation of Map entries.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print this object with the given verbosity level to the given Teuchos::FancyOStream.
LocalOrdinal getMaxLocalIndex() const
The maximum local index on the calling process.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createUniformContigMapWithNode(global_size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< Node > &node=defaultArgNode< Node >())
Non-member constructor for a uniformly distributed, contiguous Map with a user-specified Kokkos Node...
global_size_t getGlobalNumElements() const
The number of elements in this Map.
std::string description() const
Implementation of Teuchos::Describable.
Map()
Default constructor (that does nothing).