Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
53 #include "Tpetra_Details_FixedHashTable.hpp"
54 #include "Tpetra_Details_gathervPrint.hpp"
56 #include "Tpetra_Core.hpp"
57 #include "Tpetra_Util.hpp"
58 #include "Teuchos_as.hpp"
59 #include "Teuchos_TypeNameTraits.hpp"
60 #include "Teuchos_CommHelpers.hpp"
61 #include "Tpetra_Details_mpiIsInitialized.hpp"
62 #include "Tpetra_Details_extractMpiCommFromTeuchos.hpp" // teuchosCommIsAnMpiComm
64 #include <memory>
65 #include <sstream>
66 #include <stdexcept>
67 #include <typeinfo>
68 
69 namespace { // (anonymous)
70 
71  template<class ExecutionSpace>
72  void
73  checkMapInputArray (const char ctorName[],
74  const void* indexList,
75  const size_t indexListSize,
76  const ExecutionSpace& execSpace,
77  const Teuchos::Comm<int>* const comm)
78  {
79  const bool debug = ::Tpetra::Details::Behavior::debug ();
80  if (debug) {
82  using Teuchos::outArg;
83  using Teuchos::REDUCE_MIN;
84  using Teuchos::reduceAll;
85  using std::endl;
86 
87  const int myRank = comm == nullptr ? 0 : comm->getRank ();
88  const bool verbose = ::Tpetra::Details::Behavior::verbose ();
89  std::ostringstream lclErrStrm;
90  int lclSuccess = 1;
91 
92  if (indexListSize != 0 && indexList == nullptr) {
93  lclSuccess = 0;
94  if (verbose) {
95  lclErrStrm << "Proc " << myRank << ": indexList is null, "
96  "but indexListSize=" << indexListSize << " != 0." << endl;
97  }
98  }
99  else {
100  if (indexListSize != 0 && indexList != nullptr &&
101  ! pointerAccessibleFromExecutionSpace (indexList, execSpace)) {
102  lclSuccess = 0;
103  if (verbose) {
104  using ::Tpetra::Details::memorySpaceName;
105  const std::string memSpaceName = memorySpaceName (indexList);
106  const std::string execSpaceName =
107  Teuchos::TypeNameTraits<ExecutionSpace>::name ();
108  lclErrStrm << "Proc " << myRank << ": Input array is not "
109  "accessible from the required execution space " <<
110  execSpaceName << ". As far as I can tell, array lives "
111  "in memory space " << memSpaceName << "." << endl;
112  }
113  }
114  }
115  int gblSuccess = 0; // output argument
116  reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
117  if (gblSuccess != 1) {
118  std::ostringstream gblErrStrm;
119  gblErrStrm << "Tpetra::Map constructor " << ctorName <<
120  " detected a problem with the input array "
121  "(raw array, Teuchos::ArrayView, or Kokkos::View) "
122  "of global indices." << endl;
123  if (verbose) {
124  using ::Tpetra::Details::gathervPrint;
125  gathervPrint (gblErrStrm, lclErrStrm.str (), *comm);
126  }
127  TEUCHOS_TEST_FOR_EXCEPTION
128  (true, std::invalid_argument, gblErrStrm.str ());
129  }
130  }
131  }
132 } // namespace (anonymous)
133 
134 namespace Tpetra {
135 
136  template <class LocalOrdinal, class GlobalOrdinal, class Node>
138  Map () :
139  comm_ (new Teuchos::SerialComm<int> ()),
140  indexBase_ (0),
141  numGlobalElements_ (0),
142  numLocalElements_ (0),
143  minMyGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
144  maxMyGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
145  minAllGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
146  maxAllGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
147  firstContiguousGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
148  lastContiguousGID_ (Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()),
149  uniform_ (false), // trivially
150  contiguous_ (false),
151  distributed_ (false), // no communicator yet
152  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
153  {
155  }
156 
157 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
158  template <class LocalOrdinal, class GlobalOrdinal, class Node>
159  TPETRA_DEPRECATED
161  Map (const global_size_t numGlobalElements,
162  const global_ordinal_type indexBase,
163  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
164  const LocalGlobal lOrG,
165  const Teuchos::RCP<Node> &/* node */) :
166  Map<LocalOrdinal,GlobalOrdinal,Node>::Map(numGlobalElements, indexBase,
167  comm, lOrG)
168  {}
169 #endif // TPETRA_ENABLE_DEPRECATED_CODE
170 
171  template <class LocalOrdinal, class GlobalOrdinal, class Node>
173  Map (const global_size_t numGlobalElements,
174  const global_ordinal_type indexBase,
175  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
176  const LocalGlobal lOrG) :
177  comm_ (comm),
178  uniform_ (true),
179  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
180  {
181  using Teuchos::as;
182  using Teuchos::broadcast;
183  using Teuchos::outArg;
184  using Teuchos::reduceAll;
185  using Teuchos::REDUCE_MIN;
186  using Teuchos::REDUCE_MAX;
187  using Teuchos::typeName;
188  using GO = global_ordinal_type;
189  using GST = global_size_t;
190  const GST GSTI = Tpetra::Details::OrdinalTraits<GST>::invalid ();
191 
193 
194 #ifdef HAVE_TPETRA_DEBUG
195  // In debug mode only, check whether numGlobalElements and
196  // indexBase are the same over all processes in the communicator.
197  {
198  GST proc0NumGlobalElements = numGlobalElements;
199  broadcast<int, GST> (*comm_, 0, outArg (proc0NumGlobalElements));
200  GST minNumGlobalElements = numGlobalElements;
201  GST maxNumGlobalElements = numGlobalElements;
202  reduceAll<int, GST> (*comm, REDUCE_MIN, numGlobalElements, outArg (minNumGlobalElements));
203  reduceAll<int, GST> (*comm, REDUCE_MAX, numGlobalElements, outArg (maxNumGlobalElements));
204  TEUCHOS_TEST_FOR_EXCEPTION(
205  minNumGlobalElements != maxNumGlobalElements || numGlobalElements != minNumGlobalElements,
206  std::invalid_argument,
207  "Tpetra::Map constructor: All processes must provide the same number "
208  "of global elements. Process 0 set numGlobalElements = "
209  << proc0NumGlobalElements << ". The calling process "
210  << comm->getRank () << " set numGlobalElements = " << numGlobalElements
211  << ". The min and max values over all processes are "
212  << minNumGlobalElements << " resp. " << maxNumGlobalElements << ".");
213 
214  GO proc0IndexBase = indexBase;
215  broadcast<int, GO> (*comm_, 0, outArg (proc0IndexBase));
216  GO minIndexBase = indexBase;
217  GO maxIndexBase = indexBase;
218  reduceAll<int, GO> (*comm, REDUCE_MIN, indexBase, outArg (minIndexBase));
219  reduceAll<int, GO> (*comm, REDUCE_MAX, indexBase, outArg (maxIndexBase));
220  TEUCHOS_TEST_FOR_EXCEPTION(
221  minIndexBase != maxIndexBase || indexBase != minIndexBase,
222  std::invalid_argument,
223  "Tpetra::Map constructor: "
224  "All processes must provide the same indexBase argument. "
225  "Process 0 set indexBase = " << proc0IndexBase << ". The calling "
226  "process " << comm->getRank () << " set indexBase = " << indexBase
227  << ". The min and max values over all processes are "
228  << minIndexBase << " resp. " << maxIndexBase << ".");
229  }
230 #endif // HAVE_TPETRA_DEBUG
231 
232  // Distribute the elements across the processes in the given
233  // communicator so that global IDs (GIDs) are
234  //
235  // - Nonoverlapping (only one process owns each GID)
236  // - Contiguous (the sequence of GIDs is nondecreasing, and no two
237  // adjacent GIDs differ by more than one)
238  // - As evenly distributed as possible (the numbers of GIDs on two
239  // different processes do not differ by more than one)
240 
241  // All processes have the same numGlobalElements, but we still
242  // need to check that it is valid. numGlobalElements must be
243  // positive and not the "invalid" value (GSTI).
244  //
245  // This comparison looks funny, but it avoids compiler warnings
246  // for comparing unsigned integers (numGlobalElements_in is a
247  // GST, which is unsigned) while still working if we
248  // later decide to make GST signed.
249  TEUCHOS_TEST_FOR_EXCEPTION(
250  (numGlobalElements < 1 && numGlobalElements != 0),
251  std::invalid_argument,
252  "Tpetra::Map constructor: numGlobalElements (= "
253  << numGlobalElements << ") must be nonnegative.");
254 
255  TEUCHOS_TEST_FOR_EXCEPTION(
256  numGlobalElements == GSTI, std::invalid_argument,
257  "Tpetra::Map constructor: You provided numGlobalElements = Teuchos::"
258  "OrdinalTraits<Tpetra::global_size_t>::invalid(). This version of the "
259  "constructor requires a valid value of numGlobalElements. You "
260  "probably mistook this constructor for the \"contiguous nonuniform\" "
261  "constructor, which can compute the global number of elements for you "
262  "if you set numGlobalElements to that value.");
263 
264  size_t numLocalElements = 0; // will set below
265  if (lOrG == GloballyDistributed) {
266  // Compute numLocalElements:
267  //
268  // If numGlobalElements == numProcs * B + remainder,
269  // then Proc r gets B+1 elements if r < remainder,
270  // and B elements if r >= remainder.
271  //
272  // This strategy is valid for any value of numGlobalElements and
273  // numProcs, including the following border cases:
274  // - numProcs == 1
275  // - numLocalElements < numProcs
276  //
277  // In the former case, remainder == 0 && numGlobalElements ==
278  // numLocalElements. In the latter case, remainder ==
279  // numGlobalElements && numLocalElements is either 0 or 1.
280  const GST numProcs = static_cast<GST> (comm_->getSize ());
281  const GST myRank = static_cast<GST> (comm_->getRank ());
282  const GST quotient = numGlobalElements / numProcs;
283  const GST remainder = numGlobalElements - quotient * numProcs;
284 
285  GO startIndex;
286  if (myRank < remainder) {
287  numLocalElements = static_cast<size_t> (1) + static_cast<size_t> (quotient);
288  // myRank was originally an int, so it should never overflow
289  // reasonable GO types.
290  startIndex = as<GO> (myRank) * as<GO> (numLocalElements);
291  } else {
292  numLocalElements = as<size_t> (quotient);
293  startIndex = as<GO> (myRank) * as<GO> (numLocalElements) +
294  as<GO> (remainder);
295  }
296 
297  minMyGID_ = indexBase + startIndex;
298  maxMyGID_ = indexBase + startIndex + numLocalElements - 1;
299  minAllGID_ = indexBase;
300  maxAllGID_ = indexBase + numGlobalElements - 1;
301  distributed_ = (numProcs > 1);
302  }
303  else { // lOrG == LocallyReplicated
304  numLocalElements = as<size_t> (numGlobalElements);
305  minMyGID_ = indexBase;
306  maxMyGID_ = indexBase + numGlobalElements - 1;
307  distributed_ = false;
308  }
309 
310  minAllGID_ = indexBase;
311  maxAllGID_ = indexBase + numGlobalElements - 1;
312  indexBase_ = indexBase;
313  numGlobalElements_ = numGlobalElements;
314  numLocalElements_ = numLocalElements;
315  firstContiguousGID_ = minMyGID_;
316  lastContiguousGID_ = maxMyGID_;
317  contiguous_ = true;
318 
319  // Create the Directory on demand in getRemoteIndexList().
320  //setupDirectory ();
321  }
322 
323 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
324  template <class LocalOrdinal, class GlobalOrdinal, class Node>
325  TPETRA_DEPRECATED
327  Map (const global_size_t numGlobalElements,
328  const size_t numLocalElements,
329  const global_ordinal_type indexBase,
330  const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
331  const Teuchos::RCP<Node> &/* node */) :
332  Map<LocalOrdinal,GlobalOrdinal,Node>::Map(numGlobalElements,
333  numLocalElements,
334  indexBase, comm)
335  {}
336 #endif // TPETRA_ENABLE_DEPRECATED_CODE
337 
338  template <class LocalOrdinal, class GlobalOrdinal, class Node>
340  Map (const global_size_t numGlobalElements,
341  const size_t numLocalElements,
342  const global_ordinal_type indexBase,
343  const Teuchos::RCP<const Teuchos::Comm<int> > &comm) :
344  comm_ (comm),
345  uniform_ (false),
346  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
347  {
348  using Teuchos::as;
349  using Teuchos::broadcast;
350  using Teuchos::outArg;
351  using Teuchos::reduceAll;
352  using Teuchos::REDUCE_MIN;
353  using Teuchos::REDUCE_MAX;
354  using Teuchos::REDUCE_SUM;
355  using Teuchos::scan;
356  using GO = global_ordinal_type;
357  using GST = global_size_t;
358  const GST GSTI = Tpetra::Details::OrdinalTraits<GST>::invalid ();
359 
361 
362 #ifdef HAVE_TPETRA_DEBUG
363  // Global sum of numLocalElements over all processes.
364  // Keep this for later debug checks.
365  const GST debugGlobalSum =
366  initialNonuniformDebugCheck (numGlobalElements, numLocalElements,
367  indexBase, comm);
368 #endif // HAVE_TPETRA_DEBUG
369 
370  // Distribute the elements across the nodes so that they are
371  // - non-overlapping
372  // - contiguous
373 
374  // This differs from the first Map constructor (that only takes a
375  // global number of elements) in that the user has specified the
376  // number of local elements, so that the elements are not
377  // (necessarily) evenly distributed over the processes.
378 
379  // Compute my local offset. This is an inclusive scan, so to get
380  // the final offset, we subtract off the input.
381  GO scanResult = 0;
382  scan<int, GO> (*comm, REDUCE_SUM, numLocalElements, outArg (scanResult));
383  const GO myOffset = scanResult - numLocalElements;
384 
385  if (numGlobalElements != GSTI) {
386  numGlobalElements_ = numGlobalElements; // Use the user's value.
387  } else {
388  // Inclusive scan means that the last process has the final sum.
389  // Rather than doing a reduceAll to get the sum of
390  // numLocalElements, we can just have the last process broadcast
391  // its result. That saves us a round of log(numProcs) messages.
392  const int numProcs = comm->getSize ();
393  GST globalSum = scanResult;
394  if (numProcs > 1) {
395  broadcast (*comm, numProcs - 1, outArg (globalSum));
396  }
397  numGlobalElements_ = globalSum;
398 
399 #ifdef HAVE_TPETRA_DEBUG
400  // No need for an all-reduce here; both come from collectives.
401  TEUCHOS_TEST_FOR_EXCEPTION(
402  globalSum != debugGlobalSum, std::logic_error,
403  "Tpetra::Map constructor (contiguous nonuniform): "
404  "globalSum = " << globalSum << " != debugGlobalSum = " << debugGlobalSum
405  << ". Please report this bug to the Tpetra developers.");
406 #endif // HAVE_TPETRA_DEBUG
407  }
408  numLocalElements_ = numLocalElements;
409  indexBase_ = indexBase;
410  minAllGID_ = (numGlobalElements_ == 0) ?
411  std::numeric_limits<GO>::max () :
412  indexBase;
413  maxAllGID_ = (numGlobalElements_ == 0) ?
414  std::numeric_limits<GO>::lowest () :
415  indexBase + static_cast<GO> (numGlobalElements_) - static_cast<GO> (1);
416  minMyGID_ = (numLocalElements_ == 0) ?
417  std::numeric_limits<GO>::max () :
418  indexBase + static_cast<GO> (myOffset);
419  maxMyGID_ = (numLocalElements_ == 0) ?
420  std::numeric_limits<GO>::lowest () :
421  indexBase + myOffset + static_cast<GO> (numLocalElements) - static_cast<GO> (1);
422  firstContiguousGID_ = minMyGID_;
423  lastContiguousGID_ = maxMyGID_;
424  contiguous_ = true;
425  distributed_ = checkIsDist ();
426 
427  // Create the Directory on demand in getRemoteIndexList().
428  //setupDirectory ();
429  }
430 
431  template <class LocalOrdinal, class GlobalOrdinal, class Node>
434  initialNonuniformDebugCheck (const global_size_t numGlobalElements,
435  const size_t numLocalElements,
436  const GlobalOrdinal indexBase,
437  const Teuchos::RCP<const Teuchos::Comm<int> >& comm) const
438  {
439 #ifdef HAVE_TPETRA_DEBUG
440  using Teuchos::broadcast;
441  using Teuchos::outArg;
442  using Teuchos::ptr;
443  using Teuchos::REDUCE_MAX;
444  using Teuchos::REDUCE_MIN;
445  using Teuchos::REDUCE_SUM;
446  using Teuchos::reduceAll;
447  typedef GlobalOrdinal GO;
448  typedef global_size_t GST;
449  const GST GSTI = Tpetra::Details::OrdinalTraits<GST>::invalid ();
450 
451  // The user has specified the distribution of indices over the
452  // processes. The distribution is not necessarily contiguous or
453  // equally shared over the processes.
454  //
455  // We assume that the number of local elements can be stored in a
456  // size_t. The instance member numLocalElements_ is a size_t, so
457  // this variable and that should have the same type.
458 
459  GST debugGlobalSum = 0; // Will be global sum of numLocalElements
460  reduceAll<int, GST> (*comm, REDUCE_SUM, static_cast<GST> (numLocalElements),
461  outArg (debugGlobalSum));
462  // In debug mode only, check whether numGlobalElements and
463  // indexBase are the same over all processes in the communicator.
464  {
465  GST proc0NumGlobalElements = numGlobalElements;
466  broadcast<int, GST> (*comm_, 0, outArg (proc0NumGlobalElements));
467  GST minNumGlobalElements = numGlobalElements;
468  GST maxNumGlobalElements = numGlobalElements;
469  reduceAll<int, GST> (*comm, REDUCE_MIN, numGlobalElements,
470  outArg (minNumGlobalElements));
471  reduceAll<int, GST> (*comm, REDUCE_MAX, numGlobalElements,
472  outArg (maxNumGlobalElements));
473  TEUCHOS_TEST_FOR_EXCEPTION(
474  minNumGlobalElements != maxNumGlobalElements ||
475  numGlobalElements != minNumGlobalElements,
476  std::invalid_argument,
477  "Tpetra::Map constructor: All processes must provide the same number "
478  "of global elements. This is true even if that argument is Teuchos::"
479  "OrdinalTraits<global_size_t>::invalid() to signal that the Map should "
480  "compute the global number of elements. Process 0 set numGlobalElements"
481  " = " << proc0NumGlobalElements << ". The calling process "
482  << comm->getRank () << " set numGlobalElements = " << numGlobalElements
483  << ". The min and max values over all processes are "
484  << minNumGlobalElements << " resp. " << maxNumGlobalElements << ".");
485 
486  GO proc0IndexBase = indexBase;
487  broadcast<int, GO> (*comm_, 0, outArg (proc0IndexBase));
488  GO minIndexBase = indexBase;
489  GO maxIndexBase = indexBase;
490  reduceAll<int, GO> (*comm, REDUCE_MIN, indexBase, outArg (minIndexBase));
491  reduceAll<int, GO> (*comm, REDUCE_MAX, indexBase, outArg (maxIndexBase));
492  TEUCHOS_TEST_FOR_EXCEPTION(
493  minIndexBase != maxIndexBase || indexBase != minIndexBase,
494  std::invalid_argument,
495  "Tpetra::Map constructor: "
496  "All processes must provide the same indexBase argument. "
497  "Process 0 set indexBase = " << proc0IndexBase << ". The calling "
498  "process " << comm->getRank () << " set indexBase = " << indexBase
499  << ". The min and max values over all processes are "
500  << minIndexBase << " resp. " << maxIndexBase << ".");
501 
502  // Make sure that the sum of numLocalElements over all processes
503  // equals numGlobalElements.
504  TEUCHOS_TEST_FOR_EXCEPTION
505  (numGlobalElements != GSTI && debugGlobalSum != numGlobalElements,
506  std::invalid_argument, "Tpetra::Map constructor: The sum of each "
507  "process' number of indices over all processes, " << debugGlobalSum
508  << " != numGlobalElements = " << numGlobalElements << ". If you "
509  "would like this constructor to compute numGlobalElements for you, "
510  "you may set numGlobalElements = "
511  "Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid() on input. "
512  "Please note that this is NOT necessarily -1.");
513  }
514 
515  return debugGlobalSum;
516 #else
517  (void)numGlobalElements;
518  (void)numLocalElements;
519  (void)indexBase;
520  (void)comm;
521  return static_cast<global_size_t> (0);
522 #endif // HAVE_TPETRA_DEBUG
523  }
524 
525  template <class LocalOrdinal, class GlobalOrdinal, class Node>
526  void
527  Map<LocalOrdinal,GlobalOrdinal,Node>::
528  initWithNonownedHostIndexList (const global_size_t numGlobalElements,
529  const Kokkos::View<const GlobalOrdinal*,
530  Kokkos::LayoutLeft,
531  Kokkos::HostSpace,
532  Kokkos::MemoryUnmanaged>& entryList_host,
533  const GlobalOrdinal indexBase,
534  const Teuchos::RCP<const Teuchos::Comm<int> >& comm)
535  {
536  using Kokkos::LayoutLeft;
537  using Kokkos::subview;
538  using Kokkos::View;
539  using Kokkos::view_alloc;
540  using Kokkos::WithoutInitializing;
541  using Teuchos::as;
542  using Teuchos::broadcast;
543  using Teuchos::outArg;
544  using Teuchos::ptr;
545  using Teuchos::REDUCE_MAX;
546  using Teuchos::REDUCE_MIN;
547  using Teuchos::REDUCE_SUM;
548  using Teuchos::reduceAll;
549  using LO = LocalOrdinal;
550  using GO = GlobalOrdinal;
551  using GST = global_size_t;
552  const GST GSTI = Tpetra::Details::OrdinalTraits<GST>::invalid ();
553 
554  // Make sure that Kokkos has been initialized (Github Issue #513).
555  TEUCHOS_TEST_FOR_EXCEPTION
556  (! Kokkos::is_initialized (), std::runtime_error,
557  "Tpetra::Map constructor: The Kokkos execution space "
558  << Teuchos::TypeNameTraits<execution_space>::name ()
559  << " has not been initialized. "
560  "Please initialize it before creating a Map.")
561 
562  // The user has specified the distribution of indices over the
563  // processes, via the input array of global indices on each
564  // process. The distribution is not necessarily contiguous or
565  // equally shared over the processes.
566 
567  // The length of the input array on this process is the number of
568  // local indices to associate with this process, even though the
569  // input array contains global indices. We assume that the number
570  // of local indices on a process can be stored in a size_t;
571  // numLocalElements_ is a size_t, so this variable and that should
572  // have the same type.
573  const size_t numLocalElements = static_cast<size_t> (entryList_host.size ());
574 
575  initialNonuniformDebugCheck (numGlobalElements, numLocalElements,
576  indexBase, comm);
577 
578  // NOTE (mfh 20 Feb 2013, 10 Oct 2016) In some sense, this global
579  // reduction is redundant, since the directory Map will have to do
580  // the same thing. Thus, we could do the scan and broadcast for
581  // the directory Map here, and give the computed offsets to the
582  // directory Map's constructor. However, a reduction costs less
583  // than a scan and broadcast, so this still saves time if users of
584  // this Map don't ever need the Directory (i.e., if they never
585  // call getRemoteIndexList on this Map).
586  if (numGlobalElements != GSTI) {
587  numGlobalElements_ = numGlobalElements; // Use the user's value.
588  }
589  else { // The user wants us to compute the sum.
590  reduceAll<int, GST> (*comm, REDUCE_SUM,
591  static_cast<GST> (numLocalElements),
592  outArg (numGlobalElements_));
593  }
594 
595  // mfh 20 Feb 2013: We've never quite done the right thing for
596  // duplicate GIDs here. Duplicate GIDs have always been counted
597  // distinctly in numLocalElements_, and thus should get a
598  // different LID. However, we've always used std::map or a hash
599  // table for the GID -> LID lookup table, so distinct GIDs always
600  // map to the same LID. Furthermore, the order of the input GID
601  // list matters, so it's not desirable to sort for determining
602  // uniqueness.
603  //
604  // I've chosen for now to write this code as if the input GID list
605  // contains no duplicates. If this is not desired, we could use
606  // the lookup table itself to determine uniqueness: If we haven't
607  // seen the GID before, it gets a new LID and it's added to the
608  // LID -> GID and GID -> LID tables. If we have seen the GID
609  // before, it doesn't get added to either table. I would
610  // implement this, but it would cost more to do the double lookups
611  // in the table (one to check, and one to insert).
612  //
613  // More importantly, since we build the GID -> LID table in (a
614  // thread-) parallel (way), the order in which duplicate GIDs may
615  // get inserted is not defined. This would make the assignment of
616  // LID to GID nondeterministic.
617 
618  numLocalElements_ = numLocalElements;
619  indexBase_ = indexBase;
620 
621  minMyGID_ = indexBase_;
622  maxMyGID_ = indexBase_;
623 
624  // NOTE (mfh 27 May 2015): While finding the initial contiguous
625  // GID range requires looking at all the GIDs in the range,
626  // dismissing an interval of GIDs only requires looking at the
627  // first and last GIDs. Thus, we could do binary search backwards
628  // from the end in order to catch the common case of a contiguous
629  // interval followed by noncontiguous entries. On the other hand,
630  // we could just expose this case explicitly as yet another Map
631  // constructor, and avoid the trouble of detecting it.
632  if (numLocalElements_ > 0) {
633  // Find contiguous GID range, with the restriction that the
634  // beginning of the range starts with the first entry. While
635  // doing so, fill in the LID -> GID table.
636  typename decltype (lgMap_)::non_const_type lgMap
637  (view_alloc ("lgMap", WithoutInitializing), numLocalElements_);
638  auto lgMap_host =
639  Kokkos::create_mirror_view (Kokkos::HostSpace (), lgMap);
640 
641  // The input array entryList_host is already on host, so we
642  // don't need to take a host view of it.
643  // auto entryList_host =
644  // Kokkos::create_mirror_view (Kokkos::HostSpace (), entryList);
645  // Kokkos::deep_copy (entryList_host, entryList);
646 
647  firstContiguousGID_ = entryList_host[0];
648  lastContiguousGID_ = firstContiguousGID_+1;
649 
650  // FIXME (mfh 23 Sep 2015) We need to copy the input GIDs
651  // anyway, so we have to look at them all. The logical way to
652  // find the first noncontiguous entry would thus be to "reduce,"
653  // where the local reduction result is whether entryList[i] + 1
654  // == entryList[i+1].
655 
656  lgMap_host[0] = firstContiguousGID_;
657  size_t i = 1;
658  for ( ; i < numLocalElements_; ++i) {
659  const GO curGid = entryList_host[i];
660  const LO curLid = as<LO> (i);
661 
662  if (lastContiguousGID_ != curGid) break;
663 
664  // Add the entry to the LID->GID table only after we know that
665  // the current GID is in the initial contiguous sequence, so
666  // that we don't repeat adding it in the first iteration of
667  // the loop below over the remaining noncontiguous GIDs.
668  lgMap_host[curLid] = curGid;
669  ++lastContiguousGID_;
670  }
671  --lastContiguousGID_;
672 
673  // [firstContiguousGID_, lastContigousGID_] is the initial
674  // sequence of contiguous GIDs. We can start the min and max
675  // GID using this range.
676  minMyGID_ = firstContiguousGID_;
677  maxMyGID_ = lastContiguousGID_;
678 
679  // Compute the GID -> LID lookup table, _not_ including the
680  // initial sequence of contiguous GIDs.
681  {
682  const std::pair<size_t, size_t> ncRange (i, entryList_host.extent (0));
683  auto nonContigGids_host = subview (entryList_host, ncRange);
684  TEUCHOS_TEST_FOR_EXCEPTION
685  (static_cast<size_t> (nonContigGids_host.extent (0)) !=
686  static_cast<size_t> (entryList_host.extent (0) - i),
687  std::logic_error, "Tpetra::Map noncontiguous constructor: "
688  "nonContigGids_host.extent(0) = "
689  << nonContigGids_host.extent (0)
690  << " != entryList_host.extent(0) - i = "
691  << (entryList_host.extent (0) - i) << " = "
692  << entryList_host.extent (0) << " - " << i
693  << ". Please report this bug to the Tpetra developers.");
694 
695  // FixedHashTable's constructor expects an owned device View,
696  // so we must deep-copy the subview of the input indices.
697  View<GO*, LayoutLeft, device_type>
698  nonContigGids (view_alloc ("nonContigGids", WithoutInitializing),
699  nonContigGids_host.size ());
700  Kokkos::deep_copy (nonContigGids, nonContigGids_host);
701 
702  glMap_ = global_to_local_table_type (nonContigGids,
703  firstContiguousGID_,
704  lastContiguousGID_,
705  static_cast<LO> (i));
706  }
707 
708  // FIXME (mfh 10 Oct 2016) When we construct the global-to-local
709  // table above, we have to look at all the (noncontiguous) input
710  // indices anyway. Thus, why not have the constructor compute
711  // and return the min and max?
712 
713  for ( ; i < numLocalElements_; ++i) {
714  const GO curGid = entryList_host[i];
715  const LO curLid = static_cast<LO> (i);
716  lgMap_host[curLid] = curGid; // LID -> GID table
717 
718  // While iterating through entryList, we compute its
719  // (process-local) min and max elements.
720  if (curGid < minMyGID_) {
721  minMyGID_ = curGid;
722  }
723  if (curGid > maxMyGID_) {
724  maxMyGID_ = curGid;
725  }
726  }
727 
728  // We filled lgMap on host above; now sync back to device.
729  Kokkos::deep_copy (lgMap, lgMap_host);
730 
731  // "Commit" the local-to-global lookup table we filled in above.
732  lgMap_ = lgMap;
733  // We've already created this, so use it.
734  lgMapHost_ = lgMap_host;
735  }
736  else {
737  minMyGID_ = std::numeric_limits<GlobalOrdinal>::max();
738  maxMyGID_ = std::numeric_limits<GlobalOrdinal>::lowest();
739  // This insures tests for GIDs in the range
740  // [firstContiguousGID_, lastContiguousGID_] fail for processes
741  // with no local elements.
742  firstContiguousGID_ = indexBase_+1;
743  lastContiguousGID_ = indexBase_;
744  // glMap_ was default constructed, so it's already empty.
745  }
746 
747  // Compute the min and max of all processes' GIDs. If
748  // numLocalElements_ == 0 on this process, minMyGID_ and maxMyGID_
749  // are both indexBase_. This is wrong, but fixing it would
750  // require either a fancy sparse all-reduce, or a custom reduction
751  // operator that ignores invalid values ("invalid" means
752  // Tpetra::Details::OrdinalTraits<GO>::invalid()).
753  //
754  // Also, while we're at it, use the same all-reduce to figure out
755  // if the Map is distributed. "Distributed" means that there is
756  // at least one process with a number of local elements less than
757  // the number of global elements.
758  //
759  // We're computing the min and max of all processes' GIDs using a
760  // single MAX all-reduce, because min(x,y) = -max(-x,-y) (when x
761  // and y are signed). (This lets us combine the min and max into
762  // a single all-reduce.) If each process sets localDist=1 if its
763  // number of local elements is strictly less than the number of
764  // global elements, and localDist=0 otherwise, then a MAX
765  // all-reduce on localDist tells us if the Map is distributed (1
766  // if yes, 0 if no). Thus, we can append localDist onto the end
767  // of the data and get the global result from the all-reduce.
768  if (std::numeric_limits<GO>::is_signed) {
769  // Does my process NOT own all the elements?
770  const GO localDist =
771  (as<GST> (numLocalElements_) < numGlobalElements_) ? 1 : 0;
772 
773  GO minMaxInput[3];
774  minMaxInput[0] = -minMyGID_;
775  minMaxInput[1] = maxMyGID_;
776  minMaxInput[2] = localDist;
777 
778  GO minMaxOutput[3];
779  minMaxOutput[0] = 0;
780  minMaxOutput[1] = 0;
781  minMaxOutput[2] = 0;
782  reduceAll<int, GO> (*comm, REDUCE_MAX, 3, minMaxInput, minMaxOutput);
783  minAllGID_ = -minMaxOutput[0];
784  maxAllGID_ = minMaxOutput[1];
785  const GO globalDist = minMaxOutput[2];
786  distributed_ = (comm_->getSize () > 1 && globalDist == 1);
787  }
788  else { // unsigned; use two reductions
789  // This is always correct, no matter the signedness of GO.
790  reduceAll<int, GO> (*comm_, REDUCE_MIN, minMyGID_, outArg (minAllGID_));
791  reduceAll<int, GO> (*comm_, REDUCE_MAX, maxMyGID_, outArg (maxAllGID_));
792  distributed_ = checkIsDist ();
793  }
794 
795  contiguous_ = false; // "Contiguous" is conservative.
796 
797  TEUCHOS_TEST_FOR_EXCEPTION(
798  minAllGID_ < indexBase_,
799  std::invalid_argument,
800  "Tpetra::Map constructor (noncontiguous): "
801  "Minimum global ID = " << minAllGID_ << " over all process(es) is "
802  "less than the given indexBase = " << indexBase_ << ".");
803 
804  // Create the Directory on demand in getRemoteIndexList().
805  //setupDirectory ();
806  }
807 
808  template <class LocalOrdinal, class GlobalOrdinal, class Node>
810  Map (const global_size_t numGlobalElements,
811  const GlobalOrdinal indexList[],
812  const LocalOrdinal indexListSize,
813  const GlobalOrdinal indexBase,
814  const Teuchos::RCP<const Teuchos::Comm<int> >& comm) :
815  comm_ (comm),
816  uniform_ (false),
817  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
818  {
820  checkMapInputArray ("(GST, const GO[], LO, GO, comm)",
821  indexList, static_cast<size_t> (indexListSize),
822  Kokkos::DefaultHostExecutionSpace (),
823  comm.getRawPtr ());
824  // Not quite sure if I trust all code to behave correctly if the
825  // pointer is nonnull but the array length is nonzero, so I'll
826  // make sure the raw pointer is null if the length is zero.
827  const GlobalOrdinal* const indsRaw = indexListSize == 0 ? NULL : indexList;
828  Kokkos::View<const GlobalOrdinal*,
829  Kokkos::LayoutLeft,
830  Kokkos::HostSpace,
831  Kokkos::MemoryUnmanaged> inds (indsRaw, indexListSize);
832  initWithNonownedHostIndexList (numGlobalElements, inds, indexBase, comm);
833  }
834 
835 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
836  template <class LocalOrdinal, class GlobalOrdinal, class Node>
838  Map (const global_size_t numGlobalElements,
839  const Teuchos::ArrayView<const GlobalOrdinal>& entryList,
840  const GlobalOrdinal indexBase,
841  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
842  const Teuchos::RCP<Node>& /* node */) :
843  Map<LocalOrdinal,GlobalOrdinal,Node>::Map(numGlobalElements, entryList,
844  indexBase, comm)
845  {}
846 #endif // TPETRA_ENABLE_DEPRECATED_CODE
847 
848  template <class LocalOrdinal, class GlobalOrdinal, class Node>
850  Map (const global_size_t numGlobalElements,
851  const Teuchos::ArrayView<const GlobalOrdinal>& entryList,
852  const GlobalOrdinal indexBase,
853  const Teuchos::RCP<const Teuchos::Comm<int> >& comm) :
854  comm_ (comm),
855  uniform_ (false),
856  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
857  {
859  const size_t numLclInds = static_cast<size_t> (entryList.size ());
860  checkMapInputArray ("(GST, ArrayView, GO, comm)",
861  entryList.getRawPtr (), numLclInds,
862  Kokkos::DefaultHostExecutionSpace (),
863  comm.getRawPtr ());
864  // Not quite sure if I trust both ArrayView and View to behave
865  // correctly if the pointer is nonnull but the array length is
866  // nonzero, so I'll make sure it's null if the length is zero.
867  const GlobalOrdinal* const indsRaw =
868  numLclInds == 0 ? NULL : entryList.getRawPtr ();
869  Kokkos::View<const GlobalOrdinal*,
870  Kokkos::LayoutLeft,
871  Kokkos::HostSpace,
872  Kokkos::MemoryUnmanaged> inds (indsRaw, numLclInds);
873  initWithNonownedHostIndexList (numGlobalElements, inds, indexBase, comm);
874  }
875 
876  template <class LocalOrdinal, class GlobalOrdinal, class Node>
878  Map (const global_size_t numGlobalElements,
879  const Kokkos::View<const GlobalOrdinal*, device_type>& entryList,
880  const GlobalOrdinal indexBase,
881  const Teuchos::RCP<const Teuchos::Comm<int> >& comm) :
882  comm_ (comm),
883  uniform_ (false),
884  directory_ (new Directory<LocalOrdinal, GlobalOrdinal, Node> ())
885  {
886  using Kokkos::LayoutLeft;
887  using Kokkos::subview;
888  using Kokkos::View;
889  using Kokkos::view_alloc;
890  using Kokkos::WithoutInitializing;
891  using Teuchos::arcp;
892  using Teuchos::ArrayView;
893  using Teuchos::as;
894  using Teuchos::broadcast;
895  using Teuchos::outArg;
896  using Teuchos::ptr;
897  using Teuchos::REDUCE_MAX;
898  using Teuchos::REDUCE_MIN;
899  using Teuchos::REDUCE_SUM;
900  using Teuchos::reduceAll;
901  using Teuchos::typeName;
902  typedef LocalOrdinal LO;
903  typedef GlobalOrdinal GO;
904  typedef global_size_t GST;
905  const GST GSTI = Tpetra::Details::OrdinalTraits<GST>::invalid ();
906 
908  checkMapInputArray ("(GST, Kokkos::View, GO, comm)",
909  entryList.data (),
910  static_cast<size_t> (entryList.extent (0)),
911  execution_space (), comm.getRawPtr ());
912 
913  // The user has specified the distribution of indices over the
914  // processes, via the input array of global indices on each
915  // process. The distribution is not necessarily contiguous or
916  // equally shared over the processes.
917 
918  // The length of the input array on this process is the number of
919  // local indices to associate with this process, even though the
920  // input array contains global indices. We assume that the number
921  // of local indices on a process can be stored in a size_t;
922  // numLocalElements_ is a size_t, so this variable and that should
923  // have the same type.
924  const size_t numLocalElements = static_cast<size_t> (entryList.size ());
925 
926  initialNonuniformDebugCheck (numGlobalElements, numLocalElements,
927  indexBase, comm);
928 
929  // NOTE (mfh 20 Feb 2013, 10 Oct 2016) In some sense, this global
930  // reduction is redundant, since the directory Map will have to do
931  // the same thing. Thus, we could do the scan and broadcast for
932  // the directory Map here, and give the computed offsets to the
933  // directory Map's constructor. However, a reduction costs less
934  // than a scan and broadcast, so this still saves time if users of
935  // this Map don't ever need the Directory (i.e., if they never
936  // call getRemoteIndexList on this Map).
937  if (numGlobalElements != GSTI) {
938  numGlobalElements_ = numGlobalElements; // Use the user's value.
939  }
940  else { // The user wants us to compute the sum.
941  reduceAll<int, GST> (*comm, REDUCE_SUM,
942  static_cast<GST> (numLocalElements),
943  outArg (numGlobalElements_));
944  }
945 
946  // mfh 20 Feb 2013: We've never quite done the right thing for
947  // duplicate GIDs here. Duplicate GIDs have always been counted
948  // distinctly in numLocalElements_, and thus should get a
949  // different LID. However, we've always used std::map or a hash
950  // table for the GID -> LID lookup table, so distinct GIDs always
951  // map to the same LID. Furthermore, the order of the input GID
952  // list matters, so it's not desirable to sort for determining
953  // uniqueness.
954  //
955  // I've chosen for now to write this code as if the input GID list
956  // contains no duplicates. If this is not desired, we could use
957  // the lookup table itself to determine uniqueness: If we haven't
958  // seen the GID before, it gets a new LID and it's added to the
959  // LID -> GID and GID -> LID tables. If we have seen the GID
960  // before, it doesn't get added to either table. I would
961  // implement this, but it would cost more to do the double lookups
962  // in the table (one to check, and one to insert).
963  //
964  // More importantly, since we build the GID -> LID table in (a
965  // thread-) parallel (way), the order in which duplicate GIDs may
966  // get inserted is not defined. This would make the assignment of
967  // LID to GID nondeterministic.
968 
969  numLocalElements_ = numLocalElements;
970  indexBase_ = indexBase;
971 
972  minMyGID_ = indexBase_;
973  maxMyGID_ = indexBase_;
974 
975  // NOTE (mfh 27 May 2015): While finding the initial contiguous
976  // GID range requires looking at all the GIDs in the range,
977  // dismissing an interval of GIDs only requires looking at the
978  // first and last GIDs. Thus, we could do binary search backwards
979  // from the end in order to catch the common case of a contiguous
980  // interval followed by noncontiguous entries. On the other hand,
981  // we could just expose this case explicitly as yet another Map
982  // constructor, and avoid the trouble of detecting it.
983  if (numLocalElements_ > 0) {
984  // Find contiguous GID range, with the restriction that the
985  // beginning of the range starts with the first entry. While
986  // doing so, fill in the LID -> GID table.
987  typename decltype (lgMap_)::non_const_type lgMap
988  (view_alloc ("lgMap", WithoutInitializing), numLocalElements_);
989  auto lgMap_host =
990  Kokkos::create_mirror_view (Kokkos::HostSpace (), lgMap);
991 
992  using array_layout =
993  typename View<const GO*, device_type>::array_layout;
994  View<GO*, array_layout, Kokkos::HostSpace> entryList_host
995  (view_alloc ("entryList_host", WithoutInitializing),
996  entryList.extent(0));
997  Kokkos::deep_copy (entryList_host, entryList);
998 
999  firstContiguousGID_ = entryList_host[0];
1000  lastContiguousGID_ = firstContiguousGID_+1;
1001 
1002  // FIXME (mfh 23 Sep 2015) We need to copy the input GIDs
1003  // anyway, so we have to look at them all. The logical way to
1004  // find the first noncontiguous entry would thus be to "reduce,"
1005  // where the local reduction result is whether entryList[i] + 1
1006  // == entryList[i+1].
1007 
1008  lgMap_host[0] = firstContiguousGID_;
1009  size_t i = 1;
1010  for ( ; i < numLocalElements_; ++i) {
1011  const GO curGid = entryList_host[i];
1012  const LO curLid = as<LO> (i);
1013 
1014  if (lastContiguousGID_ != curGid) break;
1015 
1016  // Add the entry to the LID->GID table only after we know that
1017  // the current GID is in the initial contiguous sequence, so
1018  // that we don't repeat adding it in the first iteration of
1019  // the loop below over the remaining noncontiguous GIDs.
1020  lgMap_host[curLid] = curGid;
1021  ++lastContiguousGID_;
1022  }
1023  --lastContiguousGID_;
1024 
1025  // [firstContiguousGID_, lastContigousGID_] is the initial
1026  // sequence of contiguous GIDs. We can start the min and max
1027  // GID using this range.
1028  minMyGID_ = firstContiguousGID_;
1029  maxMyGID_ = lastContiguousGID_;
1030 
1031  // Compute the GID -> LID lookup table, _not_ including the
1032  // initial sequence of contiguous GIDs.
1033  {
1034  const std::pair<size_t, size_t> ncRange (i, entryList.extent (0));
1035  auto nonContigGids = subview (entryList, ncRange);
1036  TEUCHOS_TEST_FOR_EXCEPTION
1037  (static_cast<size_t> (nonContigGids.extent (0)) !=
1038  static_cast<size_t> (entryList.extent (0) - i),
1039  std::logic_error, "Tpetra::Map noncontiguous constructor: "
1040  "nonContigGids.extent(0) = "
1041  << nonContigGids.extent (0)
1042  << " != entryList.extent(0) - i = "
1043  << (entryList.extent (0) - i) << " = "
1044  << entryList.extent (0) << " - " << i
1045  << ". Please report this bug to the Tpetra developers.");
1046 
1047  glMap_ = global_to_local_table_type (nonContigGids,
1048  firstContiguousGID_,
1049  lastContiguousGID_,
1050  static_cast<LO> (i));
1051  }
1052 
1053  // FIXME (mfh 10 Oct 2016) When we construct the global-to-local
1054  // table above, we have to look at all the (noncontiguous) input
1055  // indices anyway. Thus, why not have the constructor compute
1056  // and return the min and max?
1057 
1058  for ( ; i < numLocalElements_; ++i) {
1059  const GO curGid = entryList_host[i];
1060  const LO curLid = static_cast<LO> (i);
1061  lgMap_host[curLid] = curGid; // LID -> GID table
1062 
1063  // While iterating through entryList, we compute its
1064  // (process-local) min and max elements.
1065  if (curGid < minMyGID_) {
1066  minMyGID_ = curGid;
1067  }
1068  if (curGid > maxMyGID_) {
1069  maxMyGID_ = curGid;
1070  }
1071  }
1072 
1073  // We filled lgMap on host above; now sync back to device.
1074  Kokkos::deep_copy (lgMap, lgMap_host);
1075 
1076  // "Commit" the local-to-global lookup table we filled in above.
1077  lgMap_ = lgMap;
1078  // We've already created this, so use it.
1079  lgMapHost_ = lgMap_host;
1080  }
1081  else {
1082  minMyGID_ = std::numeric_limits<GlobalOrdinal>::max();
1083  maxMyGID_ = std::numeric_limits<GlobalOrdinal>::lowest();
1084  // This insures tests for GIDs in the range
1085  // [firstContiguousGID_, lastContiguousGID_] fail for processes
1086  // with no local elements.
1087  firstContiguousGID_ = indexBase_+1;
1088  lastContiguousGID_ = indexBase_;
1089  // glMap_ was default constructed, so it's already empty.
1090  }
1091 
1092  // Compute the min and max of all processes' GIDs. If
1093  // numLocalElements_ == 0 on this process, minMyGID_ and maxMyGID_
1094  // are both indexBase_. This is wrong, but fixing it would
1095  // require either a fancy sparse all-reduce, or a custom reduction
1096  // operator that ignores invalid values ("invalid" means
1097  // Tpetra::Details::OrdinalTraits<GO>::invalid()).
1098  //
1099  // Also, while we're at it, use the same all-reduce to figure out
1100  // if the Map is distributed. "Distributed" means that there is
1101  // at least one process with a number of local elements less than
1102  // the number of global elements.
1103  //
1104  // We're computing the min and max of all processes' GIDs using a
1105  // single MAX all-reduce, because min(x,y) = -max(-x,-y) (when x
1106  // and y are signed). (This lets us combine the min and max into
1107  // a single all-reduce.) If each process sets localDist=1 if its
1108  // number of local elements is strictly less than the number of
1109  // global elements, and localDist=0 otherwise, then a MAX
1110  // all-reduce on localDist tells us if the Map is distributed (1
1111  // if yes, 0 if no). Thus, we can append localDist onto the end
1112  // of the data and get the global result from the all-reduce.
1113  if (std::numeric_limits<GO>::is_signed) {
1114  // Does my process NOT own all the elements?
1115  const GO localDist =
1116  (as<GST> (numLocalElements_) < numGlobalElements_) ? 1 : 0;
1117 
1118  GO minMaxInput[3];
1119  minMaxInput[0] = -minMyGID_;
1120  minMaxInput[1] = maxMyGID_;
1121  minMaxInput[2] = localDist;
1122 
1123  GO minMaxOutput[3];
1124  minMaxOutput[0] = 0;
1125  minMaxOutput[1] = 0;
1126  minMaxOutput[2] = 0;
1127  reduceAll<int, GO> (*comm, REDUCE_MAX, 3, minMaxInput, minMaxOutput);
1128  minAllGID_ = -minMaxOutput[0];
1129  maxAllGID_ = minMaxOutput[1];
1130  const GO globalDist = minMaxOutput[2];
1131  distributed_ = (comm_->getSize () > 1 && globalDist == 1);
1132  }
1133  else { // unsigned; use two reductions
1134  // This is always correct, no matter the signedness of GO.
1135  reduceAll<int, GO> (*comm_, REDUCE_MIN, minMyGID_, outArg (minAllGID_));
1136  reduceAll<int, GO> (*comm_, REDUCE_MAX, maxMyGID_, outArg (maxAllGID_));
1137  distributed_ = checkIsDist ();
1138  }
1139 
1140  contiguous_ = false; // "Contiguous" is conservative.
1141 
1142  TEUCHOS_TEST_FOR_EXCEPTION(
1143  minAllGID_ < indexBase_,
1144  std::invalid_argument,
1145  "Tpetra::Map constructor (noncontiguous): "
1146  "Minimum global ID = " << minAllGID_ << " over all process(es) is "
1147  "less than the given indexBase = " << indexBase_ << ".");
1148 
1149  // Create the Directory on demand in getRemoteIndexList().
1150  //setupDirectory ();
1151  }
1152 
1153 
1154  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1156  {
1157  if (! Kokkos::is_initialized ()) {
1158  std::ostringstream os;
1159  os << "WARNING: Tpetra::Map destructor (~Map()) is being called after "
1160  "Kokkos::finalize() has been called. This is user error! There are "
1161  "two likely causes: " << std::endl <<
1162  " 1. You have a static Tpetra::Map (or RCP or shared_ptr of a Map)"
1163  << std::endl <<
1164  " 2. You declare and construct a Tpetra::Map (or RCP or shared_ptr "
1165  "of a Tpetra::Map) at the same scope in main() as Kokkos::finalize() "
1166  "or Tpetra::finalize()." << std::endl << std::endl <<
1167  "Don't do either of these! Please refer to GitHib Issue #2372."
1168  << std::endl;
1169  ::Tpetra::Details::printOnce (std::cerr, os.str (),
1170  this->getComm ().getRawPtr ());
1171  }
1172  else {
1173  using ::Tpetra::Details::mpiIsInitialized;
1174  using ::Tpetra::Details::mpiIsFinalized;
1175  using ::Tpetra::Details::teuchosCommIsAnMpiComm;
1176 
1177  Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm ();
1178  if (! comm.is_null () && teuchosCommIsAnMpiComm (*comm) &&
1179  mpiIsInitialized () && mpiIsFinalized ()) {
1180  // Tpetra itself does not require MPI, even if building with
1181  // MPI. It is legal to create Tpetra objects that do not use
1182  // MPI, even in an MPI program. However, calling Tpetra stuff
1183  // after MPI_Finalize() has been called is a bad idea, since
1184  // some Tpetra defaults may use MPI if available.
1185  std::ostringstream os;
1186  os << "WARNING: Tpetra::Map destructor (~Map()) is being called after "
1187  "MPI_Finalize() has been called. This is user error! There are "
1188  "two likely causes: " << std::endl <<
1189  " 1. You have a static Tpetra::Map (or RCP or shared_ptr of a Map)"
1190  << std::endl <<
1191  " 2. You declare and construct a Tpetra::Map (or RCP or shared_ptr "
1192  "of a Tpetra::Map) at the same scope in main() as MPI_finalize() or "
1193  "Tpetra::finalize()." << std::endl << std::endl <<
1194  "Don't do either of these! Please refer to GitHib Issue #2372."
1195  << std::endl;
1196  ::Tpetra::Details::printOnce (std::cerr, os.str (), comm.getRawPtr ());
1197  }
1198  }
1199  // mfh 20 Mar 2018: We can't check Tpetra::isInitialized() yet,
1200  // because Tpetra does not yet require Tpetra::initialize /
1201  // Tpetra::finalize.
1202  }
1203 
1204 
1205  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1206  bool
1208  {
1209  TEUCHOS_TEST_FOR_EXCEPTION(
1210  getComm ().is_null (), std::logic_error, "Tpetra::Map::isOneToOne: "
1211  "getComm() returns null. Please report this bug to the Tpetra "
1212  "developers.");
1213 
1214  // This is a collective operation, if it hasn't been called before.
1215  setupDirectory ();
1216  return directory_->isOneToOne (*this);
1217  }
1218 
1219 
1220  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1221  LocalOrdinal
1223  getLocalElement (GlobalOrdinal globalIndex) const
1224  {
1225  if (isContiguous ()) {
1226  if (globalIndex < getMinGlobalIndex () ||
1227  globalIndex > getMaxGlobalIndex ()) {
1228  return Tpetra::Details::OrdinalTraits<LocalOrdinal>::invalid ();
1229  }
1230  return static_cast<LocalOrdinal> (globalIndex - getMinGlobalIndex ());
1231  }
1232  else if (globalIndex >= firstContiguousGID_ &&
1233  globalIndex <= lastContiguousGID_) {
1234  return static_cast<LocalOrdinal> (globalIndex - firstContiguousGID_);
1235  }
1236  else {
1237  // If the given global index is not in the table, this returns
1238  // the same value as OrdinalTraits<LocalOrdinal>::invalid().
1239  return glMap_.get (globalIndex);
1240  }
1241  }
1242 
1243  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1244  GlobalOrdinal
1246  getGlobalElement (LocalOrdinal localIndex) const
1247  {
1248  if (localIndex < getMinLocalIndex () || localIndex > getMaxLocalIndex ()) {
1249  return Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ();
1250  }
1251  if (isContiguous ()) {
1252  return getMinGlobalIndex () + localIndex;
1253  }
1254  else {
1255  // This is a host Kokkos::View access, with no RCP or ArrayRCP
1256  // involvement. As a result, it is thread safe.
1257  //
1258  // lgMapHost_ is a host pointer; this does NOT assume UVM.
1259  return lgMapHost_[localIndex];
1260  }
1261  }
1262 
1263  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1264  bool
1266  isNodeLocalElement (LocalOrdinal localIndex) const
1267  {
1268  if (localIndex < getMinLocalIndex () || localIndex > getMaxLocalIndex ()) {
1269  return false;
1270  } else {
1271  return true;
1272  }
1273  }
1274 
1275  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1276  bool
1278  isNodeGlobalElement (GlobalOrdinal globalIndex) const {
1279  return this->getLocalElement (globalIndex) !=
1280  Tpetra::Details::OrdinalTraits<LocalOrdinal>::invalid ();
1281  }
1282 
1283  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1285  return uniform_;
1286  }
1287 
1288  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1290  return contiguous_;
1291  }
1292 
1293 
1294  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1298  {
1299  return local_map_type (glMap_, lgMap_, getIndexBase (),
1300  getMinGlobalIndex (), getMaxGlobalIndex (),
1301  firstContiguousGID_, lastContiguousGID_,
1302  getNodeNumElements (), isContiguous ());
1303  }
1304 
1305  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1306  bool
1309  {
1310  using Teuchos::outArg;
1311  using Teuchos::REDUCE_MIN;
1312  using Teuchos::reduceAll;
1313  //
1314  // Tests that avoid the Boolean all-reduce below by using
1315  // globally consistent quantities.
1316  //
1317  if (this == &map) {
1318  // Pointer equality on one process always implies pointer
1319  // equality on all processes, since Map is immutable.
1320  return true;
1321  }
1322  else if (getComm ()->getSize () != map.getComm ()->getSize ()) {
1323  // The two communicators have different numbers of processes.
1324  // It's not correct to call isCompatible() in that case. This
1325  // may result in the all-reduce hanging below.
1326  return false;
1327  }
1328  else if (getGlobalNumElements () != map.getGlobalNumElements ()) {
1329  // Two Maps are definitely NOT compatible if they have different
1330  // global numbers of indices.
1331  return false;
1332  }
1333  else if (isContiguous () && isUniform () &&
1334  map.isContiguous () && map.isUniform ()) {
1335  // Contiguous uniform Maps with the same number of processes in
1336  // their communicators, and with the same global numbers of
1337  // indices, are always compatible.
1338  return true;
1339  }
1340  else if (! isContiguous () && ! map.isContiguous () &&
1341  lgMap_.extent (0) != 0 && map.lgMap_.extent (0) != 0 &&
1342  lgMap_.data () == map.lgMap_.data ()) {
1343  // Noncontiguous Maps whose global index lists are nonempty and
1344  // have the same pointer must be the same (and therefore
1345  // contiguous).
1346  //
1347  // Nonempty is important. For example, consider a communicator
1348  // with two processes, and two Maps that share this
1349  // communicator, with zero global indices on the first process,
1350  // and different nonzero numbers of global indices on the second
1351  // process. In that case, on the first process, the pointers
1352  // would both be NULL.
1353  return true;
1354  }
1355 
1356  TEUCHOS_TEST_FOR_EXCEPTION(
1357  getGlobalNumElements () != map.getGlobalNumElements (), std::logic_error,
1358  "Tpetra::Map::isCompatible: There's a bug in this method. We've already "
1359  "checked that this condition is true above, but it's false here. "
1360  "Please report this bug to the Tpetra developers.");
1361 
1362  // Do both Maps have the same number of indices on each process?
1363  const int locallyCompat =
1364  (getNodeNumElements () == map.getNodeNumElements ()) ? 1 : 0;
1365 
1366  int globallyCompat = 0;
1367  reduceAll<int, int> (*comm_, REDUCE_MIN, locallyCompat, outArg (globallyCompat));
1368  return (globallyCompat == 1);
1369  }
1370 
1371  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1372  bool
1375  {
1376  using Teuchos::ArrayView;
1377  typedef GlobalOrdinal GO;
1378  typedef typename ArrayView<const GO>::size_type size_type;
1379 
1380  // If both Maps are contiguous, we can compare their GID ranges
1381  // easily by looking at the min and max GID on this process.
1382  // Otherwise, we'll compare their GID lists. If only one Map is
1383  // contiguous, then we only have to call getNodeElementList() on
1384  // the noncontiguous Map. (It's best to avoid calling it on a
1385  // contiguous Map, since it results in unnecessary storage that
1386  // persists for the lifetime of the Map.)
1387 
1388  if (this == &map) {
1389  // Pointer equality on one process always implies pointer
1390  // equality on all processes, since Map is immutable.
1391  return true;
1392  }
1393  else if (getNodeNumElements () != map.getNodeNumElements ()) {
1394  return false;
1395  }
1396  else if (getMinGlobalIndex () != map.getMinGlobalIndex () ||
1397  getMaxGlobalIndex () != map.getMaxGlobalIndex ()) {
1398  return false;
1399  }
1400  else {
1401  if (isContiguous ()) {
1402  if (map.isContiguous ()) {
1403  return true; // min and max match, so the ranges match.
1404  }
1405  else { // *this is contiguous, but map is not contiguous
1406  TEUCHOS_TEST_FOR_EXCEPTION(
1407  ! this->isContiguous () || map.isContiguous (), std::logic_error,
1408  "Tpetra::Map::locallySameAs: BUG");
1409  ArrayView<const GO> rhsElts = map.getNodeElementList ();
1410  const GO minLhsGid = this->getMinGlobalIndex ();
1411  const size_type numRhsElts = rhsElts.size ();
1412  for (size_type k = 0; k < numRhsElts; ++k) {
1413  const GO curLhsGid = minLhsGid + static_cast<GO> (k);
1414  if (curLhsGid != rhsElts[k]) {
1415  return false; // stop on first mismatch
1416  }
1417  }
1418  return true;
1419  }
1420  }
1421  else if (map.isContiguous ()) { // *this is not contiguous, but map is
1422  TEUCHOS_TEST_FOR_EXCEPTION(
1423  this->isContiguous () || ! map.isContiguous (), std::logic_error,
1424  "Tpetra::Map::locallySameAs: BUG");
1425  ArrayView<const GO> lhsElts = this->getNodeElementList ();
1426  const GO minRhsGid = map.getMinGlobalIndex ();
1427  const size_type numLhsElts = lhsElts.size ();
1428  for (size_type k = 0; k < numLhsElts; ++k) {
1429  const GO curRhsGid = minRhsGid + static_cast<GO> (k);
1430  if (curRhsGid != lhsElts[k]) {
1431  return false; // stop on first mismatch
1432  }
1433  }
1434  return true;
1435  }
1436  else if (this->lgMap_.data () == map.lgMap_.data ()) {
1437  // Pointers to LID->GID "map" (actually just an array) are the
1438  // same, and the number of GIDs are the same.
1439  return this->getNodeNumElements () == map.getNodeNumElements ();
1440  }
1441  else { // we actually have to compare the GIDs
1442  if (this->getNodeNumElements () != map.getNodeNumElements ()) {
1443  return false; // We already checked above, but check just in case
1444  }
1445  else {
1446  ArrayView<const GO> lhsElts = getNodeElementList ();
1447  ArrayView<const GO> rhsElts = map.getNodeElementList ();
1448 
1449  // std::equal requires that the latter range is as large as
1450  // the former. We know the ranges have equal length, because
1451  // they have the same number of local entries.
1452  return std::equal (lhsElts.begin (), lhsElts.end (), rhsElts.begin ());
1453  }
1454  }
1455  }
1456  }
1457 
1458  template <class LocalOrdinal,class GlobalOrdinal, class Node>
1459  bool
1462  {
1463  if (this == &map)
1464  return true;
1465 
1466  // We are going to check if lmap1 is fitted into lmap2
1467  auto lmap1 = map.getLocalMap();
1468  auto lmap2 = this->getLocalMap();
1469 
1470  auto numLocalElements1 = lmap1.getNodeNumElements();
1471  auto numLocalElements2 = lmap2.getNodeNumElements();
1472 
1473  if (numLocalElements1 > numLocalElements2) {
1474  // There are more indices in the first map on this process than in second map.
1475  return false;
1476  }
1477 
1478  if (lmap1.isContiguous () && lmap2.isContiguous ()) {
1479  // When both Maps are contiguous, just check the interval inclusion.
1480  return ((lmap1.getMinGlobalIndex () == lmap2.getMinGlobalIndex ()) &&
1481  (lmap1.getMaxGlobalIndex () <= lmap2.getMaxGlobalIndex ()));
1482  }
1483 
1484  if (lmap1.getMinGlobalIndex () < lmap2.getMinGlobalIndex () ||
1485  lmap1.getMaxGlobalIndex () > lmap2.getMaxGlobalIndex ()) {
1486  // The second map does not include the first map bounds, and thus some of
1487  // the first map global indices are not in the second map.
1488  return false;
1489  }
1490 
1491  typedef Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space> range_type;
1492 
1493  // Check all elements.
1494  LocalOrdinal numDiff = 0;
1495  Kokkos::parallel_reduce("isLocallyFitted", range_type(0, numLocalElements1),
1496  KOKKOS_LAMBDA(const LocalOrdinal i, LocalOrdinal& diff) {
1497  diff += (lmap1.getGlobalElement(i) != lmap2.getGlobalElement(i));
1498  }, numDiff);
1499 
1500  return (numDiff == 0);
1501  }
1502 
1503  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1504  bool
1507  {
1508  using Teuchos::outArg;
1509  using Teuchos::REDUCE_MIN;
1510  using Teuchos::reduceAll;
1511  //
1512  // Tests that avoid the Boolean all-reduce below by using
1513  // globally consistent quantities.
1514  //
1515  if (this == &map) {
1516  // Pointer equality on one process always implies pointer
1517  // equality on all processes, since Map is immutable.
1518  return true;
1519  }
1520  else if (getComm ()->getSize () != map.getComm ()->getSize ()) {
1521  // The two communicators have different numbers of processes.
1522  // It's not correct to call isSameAs() in that case. This
1523  // may result in the all-reduce hanging below.
1524  return false;
1525  }
1526  else if (getGlobalNumElements () != map.getGlobalNumElements ()) {
1527  // Two Maps are definitely NOT the same if they have different
1528  // global numbers of indices.
1529  return false;
1530  }
1531  else if (getMinAllGlobalIndex () != map.getMinAllGlobalIndex () ||
1532  getMaxAllGlobalIndex () != map.getMaxAllGlobalIndex () ||
1533  getIndexBase () != map.getIndexBase ()) {
1534  // If the global min or max global index doesn't match, or if
1535  // the index base doesn't match, then the Maps aren't the same.
1536  return false;
1537  }
1538  else if (isDistributed () != map.isDistributed ()) {
1539  // One Map is distributed and the other is not, which means that
1540  // the Maps aren't the same.
1541  return false;
1542  }
1543  else if (isContiguous () && isUniform () &&
1544  map.isContiguous () && map.isUniform ()) {
1545  // Contiguous uniform Maps with the same number of processes in
1546  // their communicators, with the same global numbers of indices,
1547  // and with matching index bases and ranges, must be the same.
1548  return true;
1549  }
1550 
1551  // The two communicators must have the same number of processes,
1552  // with process ranks occurring in the same order. This uses
1553  // MPI_COMM_COMPARE. The MPI 3.1 standard (Section 6.4) says:
1554  // "Operations that access communicators are local and their
1555  // execution does not require interprocess communication."
1556  // However, just to be sure, I'll put this call after the above
1557  // tests that don't communicate.
1558  if (! ::Tpetra::Details::congruent (*comm_, * (map.getComm ()))) {
1559  return false;
1560  }
1561 
1562  // If we get this far, we need to check local properties and then
1563  // communicate local sameness across all processes.
1564  const int isSame_lcl = locallySameAs (map) ? 1 : 0;
1565 
1566  // Return true if and only if all processes report local sameness.
1567  int isSame_gbl = 0;
1568  reduceAll<int, int> (*comm_, REDUCE_MIN, isSame_lcl, outArg (isSame_gbl));
1569  return isSame_gbl == 1;
1570  }
1571 
1572  namespace { // (anonymous)
1573  template <class LO, class GO, class DT>
1574  class FillLgMap {
1575  public:
1576  FillLgMap (const Kokkos::View<GO*, DT>& lgMap,
1577  const GO startGid) :
1578  lgMap_ (lgMap), startGid_ (startGid)
1579  {
1580  Kokkos::RangePolicy<LO, typename DT::execution_space>
1581  range (static_cast<LO> (0), static_cast<LO> (lgMap.size ()));
1582  Kokkos::parallel_for (range, *this);
1583  }
1584 
1585  KOKKOS_INLINE_FUNCTION void operator () (const LO& lid) const {
1586  lgMap_(lid) = startGid_ + static_cast<GO> (lid);
1587  }
1588 
1589  private:
1590  const Kokkos::View<GO*, DT> lgMap_;
1591  const GO startGid_;
1592  };
1593 
1594  } // namespace (anonymous)
1595 
1596 
1597  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1598  typename Map<LocalOrdinal,GlobalOrdinal,Node>::global_indices_array_type
1600  {
1601  typedef LocalOrdinal LO;
1602  typedef GlobalOrdinal GO;
1603  typedef device_type DT;
1604 
1605  typedef decltype (lgMap_) const_lg_view_type;
1606  typedef typename const_lg_view_type::non_const_type lg_view_type;
1607 
1608  // If the local-to-global mapping doesn't exist yet, and if we
1609  // have local entries, then create and fill the local-to-global
1610  // mapping.
1611  const bool needToCreateLocalToGlobalMapping =
1612  lgMap_.extent (0) == 0 && numLocalElements_ > 0;
1613 
1614  if (needToCreateLocalToGlobalMapping) {
1615 #ifdef HAVE_TEUCHOS_DEBUG
1616  // The local-to-global mapping should have been set up already
1617  // for a noncontiguous map.
1618  TEUCHOS_TEST_FOR_EXCEPTION( ! isContiguous(), std::logic_error,
1619  "Tpetra::Map::getNodeElementList: The local-to-global mapping (lgMap_) "
1620  "should have been set up already for a noncontiguous Map. Please report"
1621  " this bug to the Tpetra team.");
1622 #endif // HAVE_TEUCHOS_DEBUG
1623 
1624  const LO numElts = static_cast<LO> (getNodeNumElements ());
1625 
1626  using Kokkos::view_alloc;
1627  using Kokkos::WithoutInitializing;
1628  lg_view_type lgMap ("lgMap", numElts);
1629  FillLgMap<LO, GO, DT> fillIt (lgMap, minMyGID_);
1630 
1631  auto lgMapHost =
1632  Kokkos::create_mirror_view (Kokkos::HostSpace (), lgMap);
1633  Kokkos::deep_copy (lgMapHost, lgMap);
1634 
1635  // "Commit" the local-to-global lookup table we filled in above.
1636  lgMap_ = lgMap;
1637  lgMapHost_ = lgMapHost;
1638 
1639  // lgMapHost_ may be a UVM View, so insert a fence to ensure
1640  // coherent host access. We only need to do this once, because
1641  // lgMapHost_ is immutable after initialization.
1642  execution_space().fence ();
1643  }
1644 
1645  return lgMap_;
1646  }
1647 
1648  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1649  Teuchos::ArrayView<const GlobalOrdinal>
1651  {
1652  typedef GlobalOrdinal GO; // convenient abbreviation
1653 
1654  // If the local-to-global mapping doesn't exist yet, and if we
1655  // have local entries, then create and fill the local-to-global
1656  // mapping.
1657  (void) this->getMyGlobalIndices ();
1658 
1659  // This does NOT assume UVM; lgMapHost_ is a host pointer.
1660  const GO* lgMapHostRawPtr = lgMapHost_.data ();
1661  // The third argument forces ArrayView not to try to track memory
1662  // in a debug build. We have to use it because the memory does
1663  // not belong to a Teuchos memory management class.
1664  return Teuchos::ArrayView<const GO> (lgMapHostRawPtr,
1665  lgMapHost_.extent (0),
1666  Teuchos::RCP_DISABLE_NODE_LOOKUP);
1667  }
1668 
1669  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1671  return distributed_;
1672  }
1673 
1674  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1676  using Teuchos::TypeNameTraits;
1677  std::ostringstream os;
1678 
1679  os << "Tpetra::Map: {"
1680  << "LocalOrdinalType: " << TypeNameTraits<LocalOrdinal>::name ()
1681  << ", GlobalOrdinalType: " << TypeNameTraits<GlobalOrdinal>::name ()
1682  << ", NodeType: " << TypeNameTraits<Node>::name ();
1683  if (this->getObjectLabel () != "") {
1684  os << ", Label: \"" << this->getObjectLabel () << "\"";
1685  }
1686  os << ", Global number of entries: " << getGlobalNumElements ()
1687  << ", Number of processes: " << getComm ()->getSize ()
1688  << ", Uniform: " << (isUniform () ? "true" : "false")
1689  << ", Contiguous: " << (isContiguous () ? "true" : "false")
1690  << ", Distributed: " << (isDistributed () ? "true" : "false")
1691  << "}";
1692  return os.str ();
1693  }
1694 
1699  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1700  std::string
1702  localDescribeToString (const Teuchos::EVerbosityLevel vl) const
1703  {
1704  typedef LocalOrdinal LO;
1705  using std::endl;
1706 
1707  // This preserves current behavior of Map.
1708  if (vl < Teuchos::VERB_HIGH) {
1709  return std::string ();
1710  }
1711  auto outStringP = Teuchos::rcp (new std::ostringstream ());
1712  Teuchos::RCP<Teuchos::FancyOStream> outp =
1713  Teuchos::getFancyOStream (outStringP);
1714  Teuchos::FancyOStream& out = *outp;
1715 
1716  auto comm = this->getComm ();
1717  const int myRank = comm->getRank ();
1718  const int numProcs = comm->getSize ();
1719  out << "Process " << myRank << " of " << numProcs << ":" << endl;
1720  Teuchos::OSTab tab1 (out);
1721 
1722  const LO numEnt = static_cast<LO> (this->getNodeNumElements ());
1723  out << "My number of entries: " << numEnt << endl
1724  << "My minimum global index: " << this->getMinGlobalIndex () << endl
1725  << "My maximum global index: " << this->getMaxGlobalIndex () << endl;
1726 
1727  if (vl == Teuchos::VERB_EXTREME) {
1728  out << "My global indices: [";
1729  const LO minLclInd = this->getMinLocalIndex ();
1730  for (LO k = 0; k < numEnt; ++k) {
1731  out << minLclInd + this->getGlobalElement (k);
1732  if (k + 1 < numEnt) {
1733  out << ", ";
1734  }
1735  }
1736  out << "]" << endl;
1737  }
1738 
1739  out.flush (); // make sure the ostringstream got everything
1740  return outStringP->str ();
1741  }
1742 
1743  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1744  void
1746  describe (Teuchos::FancyOStream &out,
1747  const Teuchos::EVerbosityLevel verbLevel) const
1748  {
1749  using Teuchos::TypeNameTraits;
1750  using Teuchos::VERB_DEFAULT;
1751  using Teuchos::VERB_NONE;
1752  using Teuchos::VERB_LOW;
1753  using Teuchos::VERB_HIGH;
1754  using std::endl;
1755  typedef LocalOrdinal LO;
1756  typedef GlobalOrdinal GO;
1757  const Teuchos::EVerbosityLevel vl =
1758  (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
1759 
1760  if (vl == VERB_NONE) {
1761  return; // don't print anything
1762  }
1763  // If this Map's Comm is null, then the Map does not participate
1764  // in collective operations with the other processes. In that
1765  // case, it is not even legal to call this method. The reasonable
1766  // thing to do in that case is nothing.
1767  auto comm = this->getComm ();
1768  if (comm.is_null ()) {
1769  return;
1770  }
1771  const int myRank = comm->getRank ();
1772  const int numProcs = comm->getSize ();
1773 
1774  // Only Process 0 should touch the output stream, but this method
1775  // in general may need to do communication. Thus, we may need to
1776  // preserve the current tab level across multiple "if (myRank ==
1777  // 0) { ... }" inner scopes. This is why we sometimes create
1778  // OSTab instances by pointer, instead of by value. We only need
1779  // to create them by pointer if the tab level must persist through
1780  // multiple inner scopes.
1781  Teuchos::RCP<Teuchos::OSTab> tab0, tab1;
1782 
1783  if (myRank == 0) {
1784  // At every verbosity level but VERB_NONE, Process 0 prints.
1785  // By convention, describe() always begins with a tab before
1786  // printing.
1787  tab0 = Teuchos::rcp (new Teuchos::OSTab (out));
1788  out << "\"Tpetra::Map\":" << endl;
1789  tab1 = Teuchos::rcp (new Teuchos::OSTab (out));
1790  {
1791  out << "Template parameters:" << endl;
1792  Teuchos::OSTab tab2 (out);
1793  out << "LocalOrdinal: " << TypeNameTraits<LO>::name () << endl
1794  << "GlobalOrdinal: " << TypeNameTraits<GO>::name () << endl
1795  << "Node: " << TypeNameTraits<Node>::name () << endl;
1796  }
1797  const std::string label = this->getObjectLabel ();
1798  if (label != "") {
1799  out << "Label: \"" << label << "\"" << endl;
1800  }
1801  out << "Global number of entries: " << getGlobalNumElements () << endl
1802  << "Minimum global index: " << getMinAllGlobalIndex () << endl
1803  << "Maximum global index: " << getMaxAllGlobalIndex () << endl
1804  << "Index base: " << getIndexBase () << endl
1805  << "Number of processes: " << numProcs << endl
1806  << "Uniform: " << (isUniform () ? "true" : "false") << endl
1807  << "Contiguous: " << (isContiguous () ? "true" : "false") << endl
1808  << "Distributed: " << (isDistributed () ? "true" : "false") << endl;
1809  }
1810 
1811  // This is collective over the Map's communicator.
1812  if (vl >= VERB_HIGH) { // VERB_HIGH or VERB_EXTREME
1813  const std::string lclStr = this->localDescribeToString (vl);
1814  Tpetra::Details::gathervPrint (out, lclStr, *comm);
1815  }
1816  }
1817 
1818  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1819  Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1821  replaceCommWithSubset (const Teuchos::RCP<const Teuchos::Comm<int> >& newComm) const
1822  {
1823  using Teuchos::RCP;
1824  using Teuchos::rcp;
1825  typedef global_size_t GST;
1826  typedef LocalOrdinal LO;
1827  typedef GlobalOrdinal GO;
1828  typedef Map<LO, GO, Node> map_type;
1829 
1830  // mfh 26 Mar 2013: The lazy way to do this is simply to recreate
1831  // the Map by calling its ordinary public constructor, using the
1832  // original Map's data. This only involves O(1) all-reduces over
1833  // the new communicator, which in the common case only includes a
1834  // small number of processes.
1835 
1836  // Create the Map to return.
1837  if (newComm.is_null () || newComm->getSize () < 1) {
1838  return Teuchos::null; // my process does not participate in the new Map
1839  }
1840  else if (newComm->getSize () == 1) {
1841  // The case where the new communicator has only one process is
1842  // easy. We don't have to communicate to get all the
1843  // information we need. Use the default comm to create the new
1844  // Map, then fill in all the fields directly.
1845  RCP<map_type> newMap (new map_type ());
1846 
1847  newMap->comm_ = newComm;
1848  // mfh 07 Oct 2016: Preserve original behavior, even though the
1849  // original index base may no longer be the globally min global
1850  // index. See #616 for why this doesn't matter so much anymore.
1851  newMap->indexBase_ = this->indexBase_;
1852  newMap->numGlobalElements_ = this->numLocalElements_;
1853  newMap->numLocalElements_ = this->numLocalElements_;
1854  newMap->minMyGID_ = this->minMyGID_;
1855  newMap->maxMyGID_ = this->maxMyGID_;
1856  newMap->minAllGID_ = this->minMyGID_;
1857  newMap->maxAllGID_ = this->maxMyGID_;
1858  newMap->firstContiguousGID_ = this->firstContiguousGID_;
1859  newMap->lastContiguousGID_ = this->lastContiguousGID_;
1860  // Since the new communicator has only one process, neither
1861  // uniformity nor contiguity have changed.
1862  newMap->uniform_ = this->uniform_;
1863  newMap->contiguous_ = this->contiguous_;
1864  // The new communicator only has one process, so the new Map is
1865  // not distributed.
1866  newMap->distributed_ = false;
1867  newMap->lgMap_ = this->lgMap_;
1868  newMap->lgMapHost_ = this->lgMapHost_;
1869  newMap->glMap_ = this->glMap_;
1870  // It's OK not to initialize the new Map's Directory.
1871  // This is initialized lazily, on first call to getRemoteIndexList.
1872 
1873  return newMap;
1874  }
1875  else { // newComm->getSize() != 1
1876  // Even if the original Map is contiguous, the new Map might not
1877  // be, especially if the excluded processes have ranks != 0 or
1878  // newComm->getSize()-1. The common case for this method is to
1879  // exclude many (possibly even all but one) processes, so it
1880  // likely doesn't pay to do the global communication (over the
1881  // original communicator) to figure out whether we can optimize
1882  // the result Map. Thus, we just set up the result Map as
1883  // noncontiguous.
1884  //
1885  // TODO (mfh 07 Oct 2016) We don't actually need to reconstruct
1886  // the global-to-local table, etc. Optimize this code path to
1887  // avoid unnecessary local work.
1888 
1889  // Make Map (re)compute the global number of elements.
1890  const GST RECOMPUTE = Tpetra::Details::OrdinalTraits<GST>::invalid ();
1891  // TODO (mfh 07 Oct 2016) If we use any Map constructor, we have
1892  // to use the noncontiguous Map constructor, since the new Map
1893  // might not be contiguous. Even if the old Map was contiguous,
1894  // some process in the "middle" might have been excluded. If we
1895  // want to avoid local work, we either have to do the setup by
1896  // hand, or write a new Map constructor.
1897 #if 1
1898  // The disabled code here throws the following exception in
1899  // Map's replaceCommWithSubset test:
1900  //
1901  // Throw test that evaluated to true: static_cast<unsigned long long> (numKeys) > static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ())
1902  // 10:
1903  // 10: Tpetra::Details::FixedHashTable: The number of keys -3 is greater than the maximum representable ValueType value 2147483647. This means that it is not possible to use this constructor.
1904  // 10: Process 3: origComm->replaceCommWithSubset(subsetComm) threw an exception: /scratch/prj/Trilinos/Trilinos/packages/tpetra/core/src/Tpetra_Details_FixedHashTable_def.hpp:1044:
1905 
1906  auto lgMap = this->getMyGlobalIndices ();
1907  typedef typename std::decay<decltype (lgMap.extent (0)) >::type size_type;
1908  const size_type lclNumInds =
1909  static_cast<size_type> (this->getNodeNumElements ());
1910  using Teuchos::TypeNameTraits;
1911  TEUCHOS_TEST_FOR_EXCEPTION
1912  (lgMap.extent (0) != lclNumInds, std::logic_error,
1913  "Tpetra::Map::replaceCommWithSubset: Result of getMyGlobalIndices() "
1914  "has length " << lgMap.extent (0) << " (of type " <<
1915  TypeNameTraits<size_type>::name () << ") != this->getNodeNumElements()"
1916  " = " << this->getNodeNumElements () << ". The latter, upon being "
1917  "cast to size_type = " << TypeNameTraits<size_type>::name () << ", "
1918  "becomes " << lclNumInds << ". Please report this bug to the Tpetra "
1919  "developers.");
1920 #else
1921  Teuchos::ArrayView<const GO> lgMap = this->getNodeElementList ();
1922 #endif // 1
1923 
1924  const GO indexBase = this->getIndexBase ();
1925  return rcp (new map_type (RECOMPUTE, lgMap, indexBase, newComm));
1926  }
1927  }
1928 
1929  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1930  Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1933  {
1934  using Teuchos::Comm;
1935  using Teuchos::null;
1936  using Teuchos::outArg;
1937  using Teuchos::RCP;
1938  using Teuchos::rcp;
1939  using Teuchos::REDUCE_MIN;
1940  using Teuchos::reduceAll;
1941 
1942  // Create the new communicator. split() returns a valid
1943  // communicator on all processes. On processes where color == 0,
1944  // ignore the result. Passing key == 0 tells MPI to order the
1945  // processes in the new communicator by their rank in the old
1946  // communicator.
1947  const int color = (numLocalElements_ == 0) ? 0 : 1;
1948  // MPI_Comm_split must be called collectively over the original
1949  // communicator. We can't just call it on processes with color
1950  // one, even though we will ignore its result on processes with
1951  // color zero.
1952  RCP<const Comm<int> > newComm = comm_->split (color, 0);
1953  if (color == 0) {
1954  newComm = null;
1955  }
1956 
1957  // Create the Map to return.
1958  if (newComm.is_null ()) {
1959  return null; // my process does not participate in the new Map
1960  } else {
1961  // The default constructor that's useful for clone() above is
1962  // also useful here.
1963  RCP<Map> map = rcp (new Map ());
1964 
1965  map->comm_ = newComm;
1966  map->indexBase_ = indexBase_;
1967  map->numGlobalElements_ = numGlobalElements_;
1968  map->numLocalElements_ = numLocalElements_;
1969  map->minMyGID_ = minMyGID_;
1970  map->maxMyGID_ = maxMyGID_;
1971  map->minAllGID_ = minAllGID_;
1972  map->maxAllGID_ = maxAllGID_;
1973  map->firstContiguousGID_= firstContiguousGID_;
1974  map->lastContiguousGID_ = lastContiguousGID_;
1975 
1976  // Uniformity and contiguity have not changed. The directory
1977  // has changed, but we've taken care of that above.
1978  map->uniform_ = uniform_;
1979  map->contiguous_ = contiguous_;
1980 
1981  // If the original Map was NOT distributed, then the new Map
1982  // cannot be distributed.
1983  //
1984  // If the number of processes in the new communicator is 1, then
1985  // the new Map is not distributed.
1986  //
1987  // Otherwise, we have to check the new Map using an all-reduce
1988  // (over the new communicator). For example, the original Map
1989  // may have had some processes with zero elements, and all other
1990  // processes with the same number of elements as in the whole
1991  // Map. That Map is technically distributed, because of the
1992  // processes with zero elements. Removing those processes would
1993  // make the new Map locally replicated.
1994  if (! distributed_ || newComm->getSize () == 1) {
1995  map->distributed_ = false;
1996  } else {
1997  const int iOwnAllGids = (numLocalElements_ == numGlobalElements_) ? 1 : 0;
1998  int allProcsOwnAllGids = 0;
1999  reduceAll<int, int> (*newComm, REDUCE_MIN, iOwnAllGids, outArg (allProcsOwnAllGids));
2000  map->distributed_ = (allProcsOwnAllGids == 1) ? false : true;
2001  }
2002 
2003  map->lgMap_ = lgMap_;
2004  map->lgMapHost_ = lgMapHost_;
2005  map->glMap_ = glMap_;
2006 
2007  // Map's default constructor creates an uninitialized Directory.
2008  // The Directory will be initialized on demand in
2009  // getRemoteIndexList().
2010  //
2011  // FIXME (mfh 26 Mar 2013) It should be possible to "filter" the
2012  // directory more efficiently than just recreating it. If
2013  // directory recreation proves a bottleneck, we can always
2014  // revisit this. On the other hand, Directory creation is only
2015  // collective over the new, presumably much smaller
2016  // communicator, so it may not be worth the effort to optimize.
2017 
2018  return map;
2019  }
2020  }
2021 
2022  template <class LocalOrdinal, class GlobalOrdinal, class Node>
2023  void
2025  {
2026  TEUCHOS_TEST_FOR_EXCEPTION(
2027  directory_.is_null (), std::logic_error, "Tpetra::Map::setupDirectory: "
2028  "The Directory is null. "
2029  "Please report this bug to the Tpetra developers.");
2030 
2031  // Only create the Directory if it hasn't been created yet.
2032  // This is a collective operation.
2033  if (! directory_->initialized ()) {
2034  directory_->initialize (*this);
2035  }
2036  }
2037 
2038  template <class LocalOrdinal, class GlobalOrdinal, class Node>
2039  LookupStatus
2041  getRemoteIndexList (const Teuchos::ArrayView<const GlobalOrdinal>& GIDs,
2042  const Teuchos::ArrayView<int>& PIDs,
2043  const Teuchos::ArrayView<LocalOrdinal>& LIDs) const
2044  {
2045  using Tpetra::Details::OrdinalTraits;
2046  typedef Teuchos::ArrayView<int>::size_type size_type;
2047 
2048  // Empty Maps (i.e., containing no indices on any processes in the
2049  // Map's communicator) are perfectly valid. In that case, if the
2050  // input GID list is nonempty, we fill the output arrays with
2051  // invalid values, and return IDNotPresent to notify the caller.
2052  // It's perfectly valid to give getRemoteIndexList GIDs that the
2053  // Map doesn't own. SubmapImport test 2 needs this functionality.
2054  if (getGlobalNumElements () == 0) {
2055  if (GIDs.size () == 0) {
2056  return AllIDsPresent; // trivially
2057  } else {
2058  for (size_type k = 0; k < PIDs.size (); ++k) {
2059  PIDs[k] = OrdinalTraits<int>::invalid ();
2060  }
2061  for (size_type k = 0; k < LIDs.size (); ++k) {
2062  LIDs[k] = OrdinalTraits<LocalOrdinal>::invalid ();
2063  }
2064  return IDNotPresent;
2065  }
2066  }
2067 
2068  // getRemoteIndexList must be called collectively, and Directory
2069  // initialization is collective too, so it's OK to initialize the
2070  // Directory on demand.
2071  setupDirectory ();
2072  return directory_->getDirectoryEntries (*this, GIDs, PIDs, LIDs);
2073  }
2074 
2075  template <class LocalOrdinal, class GlobalOrdinal, class Node>
2076  LookupStatus
2078  getRemoteIndexList (const Teuchos::ArrayView<const GlobalOrdinal> & GIDs,
2079  const Teuchos::ArrayView<int> & PIDs) const
2080  {
2081  if (getGlobalNumElements () == 0) {
2082  if (GIDs.size () == 0) {
2083  return AllIDsPresent; // trivially
2084  } else {
2085  // The Map contains no indices, so all output PIDs are invalid.
2086  for (Teuchos::ArrayView<int>::size_type k = 0; k < PIDs.size (); ++k) {
2087  PIDs[k] = Tpetra::Details::OrdinalTraits<int>::invalid ();
2088  }
2089  return IDNotPresent;
2090  }
2091  }
2092 
2093  // getRemoteIndexList must be called collectively, and Directory
2094  // initialization is collective too, so it's OK to initialize the
2095  // Directory on demand.
2096  setupDirectory ();
2097  return directory_->getDirectoryEntries (*this, GIDs, PIDs);
2098  }
2099 
2100  template <class LocalOrdinal, class GlobalOrdinal, class Node>
2101  Teuchos::RCP<const Teuchos::Comm<int> >
2103  return comm_;
2104  }
2105 
2106 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2107  template <class LocalOrdinal, class GlobalOrdinal, class Node>
2108  TPETRA_DEPRECATED
2109  Teuchos::RCP<Node>
2111  // Node instances don't do anything any more, but sometimes it
2112  // helps for them to be nonnull.
2113  return Teuchos::rcp (new Node);
2114  }
2115 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2116 
2117  template <class LocalOrdinal,class GlobalOrdinal, class Node>
2118  bool Map<LocalOrdinal,GlobalOrdinal,Node>::checkIsDist() const {
2119  using Teuchos::as;
2120  using Teuchos::outArg;
2121  using Teuchos::REDUCE_MIN;
2122  using Teuchos::reduceAll;
2123 
2124  bool global = false;
2125  if (comm_->getSize () > 1) {
2126  // The communicator has more than one process, but that doesn't
2127  // necessarily mean the Map is distributed.
2128  int localRep = 0;
2129  if (numGlobalElements_ == as<global_size_t> (numLocalElements_)) {
2130  // The number of local elements on this process equals the
2131  // number of global elements.
2132  //
2133  // NOTE (mfh 22 Nov 2011) Does this still work if there were
2134  // duplicates in the global ID list on input (the third Map
2135  // constructor), so that the number of local elements (which
2136  // are not duplicated) on this process could be less than the
2137  // number of global elements, even if this process owns all
2138  // the elements?
2139  localRep = 1;
2140  }
2141  int allLocalRep;
2142  reduceAll<int, int> (*comm_, REDUCE_MIN, localRep, outArg (allLocalRep));
2143  if (allLocalRep != 1) {
2144  // At least one process does not own all the elements.
2145  // This makes the Map a distributed Map.
2146  global = true;
2147  }
2148  }
2149  // If the communicator has only one process, then the Map is not
2150  // distributed.
2151  return global;
2152  }
2153 
2154 } // namespace Tpetra
2155 
2156 template <class LocalOrdinal, class GlobalOrdinal>
2157 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
2158 Tpetra::createLocalMap (const size_t numElements,
2159  const Teuchos::RCP<const Teuchos::Comm<int> >& comm)
2160 {
2161  typedef LocalOrdinal LO;
2162  typedef GlobalOrdinal GO;
2163  typedef typename ::Tpetra::Map<LO, GO>::node_type NT;
2164  return createLocalMapWithNode<LO, GO, NT> (numElements, comm);
2165 }
2166 
2167 template <class LocalOrdinal, class GlobalOrdinal>
2168 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
2169 Tpetra::createUniformContigMap (const global_size_t numElements,
2170  const Teuchos::RCP<const Teuchos::Comm<int> >& comm)
2171 {
2172  typedef LocalOrdinal LO;
2173  typedef GlobalOrdinal GO;
2174  typedef typename ::Tpetra::Map<LO, GO>::node_type NT;
2175  return createUniformContigMapWithNode<LO, GO, NT> (numElements, comm);
2176 }
2177 
2178 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2179 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2180 TPETRA_DEPRECATED
2181 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2182 Tpetra::createUniformContigMapWithNode (const global_size_t numElements,
2183  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
2184  const Teuchos::RCP<Node>& /* node */
2185 )
2186 {
2187  return Tpetra::createUniformContigMapWithNode<LocalOrdinal,GlobalOrdinal,Node>
2188  (numElements, comm);
2189 }
2190 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2191 
2192 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2193 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2194 Tpetra::createUniformContigMapWithNode (const global_size_t numElements,
2195  const Teuchos::RCP<const Teuchos::Comm<int> >& comm
2196 )
2197 {
2198  using Teuchos::rcp;
2200  const GlobalOrdinal indexBase = static_cast<GlobalOrdinal> (0);
2201 
2202  return rcp (new map_type (numElements, indexBase, comm, GloballyDistributed));
2203 }
2204 
2205 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2206 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2207 TPETRA_DEPRECATED
2208 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2209 Tpetra::createLocalMapWithNode (const size_t numElements,
2210  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
2211  const Teuchos::RCP<Node>& /* node */
2212 )
2213 {
2214  return Tpetra::createLocalMapWithNode<LocalOrdinal,GlobalOrdinal,Node>
2215  (numElements, comm);
2216 }
2217 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2218 
2219 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2220 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2221 Tpetra::createLocalMapWithNode (const size_t numElements,
2222  const Teuchos::RCP<const Teuchos::Comm<int> >& comm
2223 )
2224 {
2225  using Tpetra::global_size_t;
2226  using Teuchos::rcp;
2228  const GlobalOrdinal indexBase = static_cast<GlobalOrdinal> (0);
2229  const global_size_t globalNumElts = static_cast<global_size_t> (numElements);
2230 
2231  return rcp (new map_type (globalNumElts, indexBase, comm, LocallyReplicated));
2232 }
2233 
2234 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2235 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2236 TPETRA_DEPRECATED
2237 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2239  const size_t localNumElements,
2240  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
2241  const Teuchos::RCP<Node>& /* node */
2242 )
2243 {
2244  return Tpetra::createContigMapWithNode<LocalOrdinal,GlobalOrdinal,Node>
2245  (numElements, localNumElements, comm);
2246 }
2247 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2248 
2249 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2250 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2252  const size_t localNumElements,
2253  const Teuchos::RCP<const Teuchos::Comm<int> >& comm
2254 )
2255 {
2256  using Teuchos::rcp;
2258  const GlobalOrdinal indexBase = static_cast<GlobalOrdinal> (0);
2259 
2260  return rcp (new map_type (numElements, localNumElements, indexBase, comm));
2261 }
2262 
2263 template <class LocalOrdinal, class GlobalOrdinal>
2264 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
2266  const size_t localNumElements,
2267  const Teuchos::RCP<const Teuchos::Comm<int> >& comm)
2268 {
2269  typedef LocalOrdinal LO;
2270  typedef GlobalOrdinal GO;
2272 
2273  return Tpetra::createContigMapWithNode<LO, GO, NT> (numElements, localNumElements, comm);
2274 }
2275 
2276 
2277 template <class LocalOrdinal, class GlobalOrdinal>
2278 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal> >
2279 Tpetra::createNonContigMap(const Teuchos::ArrayView<const GlobalOrdinal>& elementList,
2280  const Teuchos::RCP<const Teuchos::Comm<int> >& comm)
2281 {
2282  typedef LocalOrdinal LO;
2283  typedef GlobalOrdinal GO;
2285 
2286  return Tpetra::createNonContigMapWithNode<LO, GO, NT> (elementList, comm);
2287 }
2288 
2289 
2290 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2291 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2292 TPETRA_DEPRECATED
2293 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2294 Tpetra::createNonContigMapWithNode (const Teuchos::ArrayView<const GlobalOrdinal>& elementList,
2295  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
2296  const Teuchos::RCP<Node>& /* node */
2297 )
2298 {
2299  return Tpetra::createNonContigMapWithNode<LocalOrdinal,GlobalOrdinal,Node>
2300  (elementList, comm);
2301 }
2302 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2303 
2304 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2305 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2306 Tpetra::createNonContigMapWithNode (const Teuchos::ArrayView<const GlobalOrdinal>& elementList,
2307  const Teuchos::RCP<const Teuchos::Comm<int> >& comm
2308 )
2309 {
2310  using Teuchos::rcp;
2312  using GST = Tpetra::global_size_t;
2313  const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid ();
2314  // FIXME (mfh 22 Jul 2016) This is what I found here, but maybe this
2315  // shouldn't be zero, given that the index base is supposed to equal
2316  // the globally min global index?
2317  const GlobalOrdinal indexBase = 0;
2318 
2319  return rcp (new map_type (INV, elementList, indexBase, comm));
2320 }
2321 
2322 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2323 template <class LocalOrdinal, class GlobalOrdinal, class Node>
2324 TPETRA_DEPRECATED
2325 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2326 Tpetra::createWeightedContigMapWithNode (const int myWeight,
2327  const Tpetra::global_size_t numElements,
2328  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
2329  const Teuchos::RCP<Node>& /* node */
2330 )
2331 {
2332  Teuchos::RCP< Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map;
2333  int sumOfWeights, elemsLeft, localNumElements;
2334  const int numImages = comm->getSize();
2335  const int myImageID = comm->getRank();
2336  Teuchos::reduceAll<int>(*comm,Teuchos::REDUCE_SUM,myWeight,Teuchos::outArg(sumOfWeights));
2337  const double myShare = ((double)myWeight) / ((double)sumOfWeights);
2338  localNumElements = (int)std::floor( myShare * ((double)numElements) );
2339  // std::cout << "numElements: " << numElements << " myWeight: " << myWeight << " sumOfWeights: " << sumOfWeights << " myShare: " << myShare << std::endl;
2340  Teuchos::reduceAll<int>(*comm,Teuchos::REDUCE_SUM,localNumElements,Teuchos::outArg(elemsLeft));
2341  elemsLeft = numElements - elemsLeft;
2342  // std::cout << "(before) localNumElements: " << localNumElements << " elemsLeft: " << elemsLeft << std::endl;
2343  // i think this is true. just test it for now.
2344  TEUCHOS_TEST_FOR_EXCEPT(elemsLeft < -numImages || numImages < elemsLeft);
2345  if (elemsLeft < 0) {
2346  // last elemsLeft nodes lose an element
2347  if (myImageID >= numImages-elemsLeft) --localNumElements;
2348  }
2349  else if (elemsLeft > 0) {
2350  // first elemsLeft nodes gain an element
2351  if (myImageID < elemsLeft) ++localNumElements;
2352  }
2353  // std::cout << "(after) localNumElements: " << localNumElements << std::endl;
2354  return createContigMapWithNode<LocalOrdinal,GlobalOrdinal,Node>(numElements,localNumElements,comm);
2355 }
2356 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2357 
2358 
2359 template<class LO, class GO, class NT>
2360 Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >
2361 Tpetra::createOneToOne (const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >& M)
2362 {
2363  using Teuchos::Array;
2364  using Teuchos::ArrayView;
2365  using Teuchos::as;
2366  using Teuchos::rcp;
2367  typedef Tpetra::Map<LO, GO, NT> map_type;
2368  typedef global_size_t GST;
2369  const GST GINV = Tpetra::Details::OrdinalTraits<GST>::invalid ();
2370  const int myRank = M->getComm ()->getRank ();
2371 
2372  // Bypasses for special cases where either M is known to be
2373  // one-to-one, or the one-to-one version of M is easy to compute.
2374  // This is why we take M as an RCP, not as a const reference -- so
2375  // that we can return M itself if it is 1-to-1.
2376  if (! M->isDistributed ()) {
2377  // For a locally replicated Map, we assume that users want to push
2378  // all the GIDs to Process 0.
2379 
2380  // mfh 05 Nov 2013: getGlobalNumElements() does indeed return what
2381  // you think it should return, in this special case of a locally
2382  // replicated contiguous Map.
2383  const GST numGlobalEntries = M->getGlobalNumElements ();
2384  if (M->isContiguous ()) {
2385  const size_t numLocalEntries =
2386  (myRank == 0) ? as<size_t> (numGlobalEntries) : static_cast<size_t> (0);
2387  return rcp (new map_type (numGlobalEntries, numLocalEntries,
2388  M->getIndexBase (), M->getComm ()));
2389  }
2390  else {
2391  ArrayView<const GO> myGids =
2392  (myRank == 0) ? M->getNodeElementList () : Teuchos::null;
2393  return rcp (new map_type (GINV, myGids (), M->getIndexBase (),
2394  M->getComm ()));
2395  }
2396  }
2397  else if (M->isContiguous ()) {
2398  // Contiguous, distributed Maps are one-to-one by construction.
2399  // (Locally replicated Maps can be contiguous.)
2400  return M;
2401  }
2402  else {
2404  const size_t numMyElems = M->getNodeNumElements ();
2405  ArrayView<const GO> myElems = M->getNodeElementList ();
2406  Array<int> owner_procs_vec (numMyElems);
2407 
2408  directory.getDirectoryEntries (*M, myElems, owner_procs_vec ());
2409 
2410  Array<GO> myOwned_vec (numMyElems);
2411  size_t numMyOwnedElems = 0;
2412  for (size_t i = 0; i < numMyElems; ++i) {
2413  const GO GID = myElems[i];
2414  const int owner = owner_procs_vec[i];
2415 
2416  if (myRank == owner) {
2417  myOwned_vec[numMyOwnedElems++] = GID;
2418  }
2419  }
2420  myOwned_vec.resize (numMyOwnedElems);
2421 
2422  return rcp (new map_type (GINV, myOwned_vec (), M->getIndexBase (),
2423  M->getComm ()));
2424  }
2425 }
2426 
2427 template<class LocalOrdinal, class GlobalOrdinal, class Node>
2428 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
2431 {
2432  using ::Tpetra::Details::Behavior;
2433  using Teuchos::Array;
2434  using Teuchos::ArrayView;
2435  using Teuchos::RCP;
2436  using Teuchos::rcp;
2437  using Teuchos::toString;
2438  using std::cerr;
2439  using std::endl;
2440  using LO = LocalOrdinal;
2441  using GO = GlobalOrdinal;
2442  using map_type = Tpetra::Map<LO, GO, Node>;
2443  const char funcPrefix[] = "Tpetra::createOneToOne(Map,TieBreak): ";
2444 
2445  const bool verbose = Behavior::verbose ("Map") ||
2446  Behavior::verbose ("Directory");
2447  std::unique_ptr<std::string> procPrefix;
2448  if (verbose) {
2449  std::ostringstream os;
2450  os << "Proc ";
2451  if (M.is_null () || M->getComm ().is_null ()) {
2452  os << "?";
2453  }
2454  else {
2455  os << M->getComm ()->getRank ();
2456  }
2457  os << ": ";
2458  procPrefix = std::unique_ptr<std::string> (new std::string (os.str ()));
2459  os << funcPrefix << "Start" << endl;
2460  cerr << os.str ();
2461  }
2462 
2463  // FIXME (mfh 20 Feb 2013) We should have a bypass for contiguous
2464  // Maps (which are 1-to-1 by construction).
2465 
2466  //Based off Epetra's one to one.
2467 
2469  if (verbose) {
2470  std::ostringstream os;
2471  os << *procPrefix << "Initialize Directory" << endl;
2472  cerr << os.str ();
2473  }
2474  directory.initialize (*M, tie_break);
2475  if (verbose) {
2476  std::ostringstream os;
2477  os << *procPrefix << "Done initializing Directory" << endl;
2478  cerr << os.str ();
2479  }
2480  size_t numMyElems = M->getNodeNumElements ();
2481  ArrayView<const GO> myElems = M->getNodeElementList ();
2482  Array<int> owner_procs_vec (numMyElems);
2483  if (verbose) {
2484  std::ostringstream os;
2485  os << *procPrefix << "Call Directory::getDirectoryEntries with "
2486  "GIDs " << toString (myElems) << endl;
2487  cerr << os.str ();
2488  }
2489  directory.getDirectoryEntries (*M, myElems, owner_procs_vec ());
2490  if (verbose) {
2491  std::ostringstream os;
2492  os << *procPrefix << "Directory::getDirectoryEntries PIDs "
2493  "result: " << toString (owner_procs_vec) << endl;
2494  cerr << os.str ();
2495  }
2496 
2497  const int myRank = M->getComm()->getRank();
2498  Array<GO> myOwned_vec (numMyElems);
2499  size_t numMyOwnedElems = 0;
2500  for (size_t i = 0; i < numMyElems; ++i) {
2501  const GO GID = myElems[i];
2502  const int owner = owner_procs_vec[i];
2503  if (myRank == owner) {
2504  myOwned_vec[numMyOwnedElems++] = GID;
2505  }
2506  }
2507  myOwned_vec.resize (numMyOwnedElems);
2508 
2509  // FIXME (mfh 08 May 2014) The above Directory should be perfectly
2510  // valid for the new Map. Why can't we reuse it?
2511  const global_size_t GINV =
2512  Tpetra::Details::OrdinalTraits<global_size_t>::invalid ();
2513  if (verbose) {
2514  std::ostringstream os;
2515  os << *procPrefix << "Create Map with GIDs "
2516  << toString (myOwned_vec) << endl;
2517  cerr << os.str ();
2518  }
2519  RCP<const map_type> retMap
2520  (new map_type (GINV, myOwned_vec (), M->getIndexBase (),
2521  M->getComm ()));
2522  if (verbose) {
2523  std::ostringstream os;
2524  os << *procPrefix << funcPrefix << "Done!" << endl;
2525  cerr << os.str ();
2526  }
2527  return retMap;
2528 }
2529 
2530 //
2531 // Explicit instantiation macro
2532 //
2533 // Must be expanded from within the Tpetra namespace!
2534 //
2535 
2537 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2538 
2539 #define TPETRA_MAP_INSTANT(LO,GO,NODE) \
2540  \
2541  template class Map< LO , GO , NODE >; \
2542  \
2543  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2544  createLocalMapWithNode<LO,GO,NODE> (const size_t numElements, \
2545  const Teuchos::RCP< const Teuchos::Comm< int > >& comm); \
2546  \
2547  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2548  createContigMapWithNode<LO,GO,NODE> (const global_size_t numElements, \
2549  const size_t localNumElements, \
2550  const Teuchos::RCP< const Teuchos::Comm< int > >& comm); \
2551  \
2552  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2553  createNonContigMapWithNode(const Teuchos::ArrayView<const GO> &elementList, \
2554  const Teuchos::RCP<const Teuchos::Comm<int> > &comm); \
2555  \
2556  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2557  createUniformContigMapWithNode<LO,GO,NODE> (const global_size_t numElements, \
2558  const Teuchos::RCP< const Teuchos::Comm< int > >& comm); \
2559  \
2560  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2561  createLocalMapWithNode<LO,GO,NODE> (const size_t numElements, \
2562  const Teuchos::RCP< const Teuchos::Comm< int > >& comm, \
2563  const Teuchos::RCP< NODE >& node); \
2564  \
2565  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2566  createContigMapWithNode<LO,GO,NODE> (const global_size_t numElements, \
2567  const size_t localNumElements, \
2568  const Teuchos::RCP< const Teuchos::Comm< int > >& comm, \
2569  const Teuchos::RCP< NODE > &node); \
2570  \
2571  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2572  createNonContigMapWithNode(const Teuchos::ArrayView<const GO> &elementList, \
2573  const Teuchos::RCP<const Teuchos::Comm<int> > &comm, \
2574  const Teuchos::RCP<NODE> &node); \
2575  \
2576  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2577  createUniformContigMapWithNode<LO,GO,NODE> (const global_size_t numElements, \
2578  const Teuchos::RCP< const Teuchos::Comm< int > >& comm, \
2579  const Teuchos::RCP< NODE > &node); \
2580  \
2581  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2582  createWeightedContigMapWithNode<LO,GO,NODE> (const int thisNodeWeight, \
2583  const global_size_t numElements, \
2584  const Teuchos::RCP< const Teuchos::Comm< int > >& comm, \
2585  const Teuchos::RCP< NODE >& node); \
2586  \
2587  template Teuchos::RCP<const Map<LO,GO,NODE> > \
2588  createOneToOne (const Teuchos::RCP<const Map<LO,GO,NODE> >& M); \
2589  \
2590  template Teuchos::RCP<const Map<LO,GO,NODE> > \
2591  createOneToOne (const Teuchos::RCP<const Map<LO,GO,NODE> >& M, \
2592  const Tpetra::Details::TieBreak<LO,GO>& tie_break); \
2593 
2594 #else // !TPETRA_ENABLE_DEPRECATED_CODE
2595 
2596 #define TPETRA_MAP_INSTANT(LO,GO,NODE) \
2597  \
2598  template class Map< LO , GO , NODE >; \
2599  \
2600  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2601  createLocalMapWithNode<LO,GO,NODE> (const size_t numElements, \
2602  const Teuchos::RCP< const Teuchos::Comm< int > >& comm); \
2603  \
2604  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2605  createContigMapWithNode<LO,GO,NODE> (const global_size_t numElements, \
2606  const size_t localNumElements, \
2607  const Teuchos::RCP< const Teuchos::Comm< int > >& comm); \
2608  \
2609  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2610  createNonContigMapWithNode(const Teuchos::ArrayView<const GO> &elementList, \
2611  const Teuchos::RCP<const Teuchos::Comm<int> > &comm); \
2612  \
2613  template Teuchos::RCP< const Map<LO,GO,NODE> > \
2614  createUniformContigMapWithNode<LO,GO,NODE> (const global_size_t numElements, \
2615  const Teuchos::RCP< const Teuchos::Comm< int > >& comm); \
2616  \
2617  template Teuchos::RCP<const Map<LO,GO,NODE> > \
2618  createOneToOne (const Teuchos::RCP<const Map<LO,GO,NODE> >& M); \
2619  \
2620  template Teuchos::RCP<const Map<LO,GO,NODE> > \
2621  createOneToOne (const Teuchos::RCP<const Map<LO,GO,NODE> >& M, \
2622  const Tpetra::Details::TieBreak<LO,GO>& tie_break); \
2623 
2624 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2625 
2627 #define TPETRA_MAP_INSTANT_DEFAULTNODE(LO,GO) \
2628  template Teuchos::RCP< const Map<LO,GO> > \
2629  createLocalMap<LO,GO>( const size_t, const Teuchos::RCP< const Teuchos::Comm< int > > &); \
2630  \
2631  template Teuchos::RCP< const Map<LO,GO> > \
2632  createContigMap<LO,GO>( global_size_t, size_t, \
2633  const Teuchos::RCP< const Teuchos::Comm< int > > &); \
2634  \
2635  template Teuchos::RCP< const Map<LO,GO> > \
2636  createNonContigMap(const Teuchos::ArrayView<const GO> &, \
2637  const Teuchos::RCP<const Teuchos::Comm<int> > &); \
2638  \
2639  template Teuchos::RCP< const Map<LO,GO> > \
2640  createUniformContigMap<LO,GO>( const global_size_t, \
2641  const Teuchos::RCP< const Teuchos::Comm< int > > &); \
2642 
2643 #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
bool isLocallyFitted(const Map< LocalOrdinal, GlobalOrdinal, Node > &map) const
True if and only if map is locally fitted to this Map.
Declaration of Tpetra::Details::extractMpiCommFromTeuchos.
virtual ~Map()
Destructor (virtual for memory safety of derived classes).
GlobalOrdinal getMinGlobalIndex() const
The minimum global index owned by the calling process.
GlobalOrdinal global_ordinal_type
The type of global indices.
Declaration of Tpetra::Details::printOnce.
bool isNodeGlobalElement(GlobalOrdinal globalIndex) const
Whether the given global index is owned by this Map on the calling process.
std::string memorySpaceName(const void *ptr)
Return the Kokkos memory space name (without &quot;Kokkos::&quot;) corresponding to the given nonnull pointer...
global_indices_array_type getMyGlobalIndices() const
Return a view of the global indices owned by this process.
Declaration of functions for checking whether a given pointer is accessible from a given Kokkos execu...
bool isContiguous() const
True if this Map is distributed contiguously, else false.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
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(const global_size_t numElements, const size_t localNumElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Nonmember constructor for a (potentially) nonuniformly distributed, contiguous Map for a user-specifi...
GlobalOrdinal getIndexBase() const
The index base for this Map.
bool isDistributed() const
Whether this Map is globally distributed or locally replicated.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > removeEmptyProcesses() const
Advanced methods.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Accessors for the Teuchos::Comm and Kokkos Node objects.
static bool debug()
Whether Tpetra is in debug mode.
GlobalOrdinal getMinAllGlobalIndex() const
The minimum global index over all processes in the communicator.
bool locallySameAs(const Map< LocalOrdinal, GlobalOrdinal, node_type > &map) const
Is this Map locally the same as the input Map?
bool isNodeLocalElement(LocalOrdinal localIndex) const
Whether the given local index is valid for this Map on the calling process.
&quot;Local&quot; part of Map suitable for Kokkos kernels.
bool pointerAccessibleFromExecutionSpace(const void *ptr, const ExecutionSpace &space)
Is the given nonnull ptr accessible from the given execution space?
Declaration of Tpetra::Details::initializeKokkos.
GlobalOrdinal getMaxAllGlobalIndex() const
The maximum global index over all processes in the communicator.
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
void initializeKokkos()
Initialize Kokkos, using command-line arguments (if any) given to Teuchos::GlobalMPISession.
size_t global_size_t
Global size_t object.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createOneToOne(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &M)
Nonmember constructor for a contiguous Map with user-defined weights and a user-specified, possibly nondefault Kokkos Node type.
Teuchos::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.
Functions for initializing and finalizing Tpetra.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
static bool verbose()
Whether Tpetra is in verbose mode.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createUniformContigMap(const 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...
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.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createContigMap(const global_size_t numElements, const size_t localNumElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Non-member constructor for a (potentially) non-uniformly distributed, contiguous Map using the defaul...
LocalOrdinal getLocalElement(GlobalOrdinal globalIndex) const
The local index corresponding to the given global index.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createLocalMap(const size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Nonmember constructor for a locally replicated Map with the default Kokkos Node.
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
Teuchos::ArrayView< const GlobalOrdinal > getNodeElementList() const
Return a NONOWNING view of the global indices owned by this process.
typename device_type::execution_space execution_space
The Kokkos execution space.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createUniformContigMapWithNode(const global_size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Non-member constructor for a uniformly distributed, contiguous Map with a user-specified Kokkos Node...
size_t getNodeNumElements() const
The number of elements belonging to the calling process.
A parallel distribution of indices 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 > > createLocalMapWithNode(const size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Nonmember constructor for a locally replicated Map with a specified Kokkos Node.
typename Node::device_type device_type
This class&#39; Kokkos::Device specialization.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal > > createNonContigMap(const Teuchos::ArrayView< const GlobalOrdinal > &elementList, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Nonmember constructor for a non-contiguous Map using the default Kokkos::Device type.
LocalGlobal
Enum for local versus global allocation of Map entries.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object in a human-readable way to the given output stream.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createNonContigMapWithNode(const Teuchos::ArrayView< const GlobalOrdinal > &elementList, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Nonmember constructor for a noncontiguous Map with a user-specified, possibly nondefault Kokkos Node ...
Node node_type
Legacy typedef that will go away at some point.
global_size_t getGlobalNumElements() const
The number of elements in this Map.
std::string description() const
Implementation of Teuchos::Describable.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra&#39;s behavior.
Map()
Default constructor (that does nothing).