Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Util.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Tpetra: Templated Linear Algebra Services Package
4 //
5 // Copyright 2008 NTESS and the Tpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TPETRA_UTIL_HPP
11 #define TPETRA_UTIL_HPP
12 
22 #include "Tpetra_ConfigDefs.hpp"
23 #include "Kokkos_DualView.hpp"
24 #include "KokkosCompat_View.hpp"
25 #include "Teuchos_Assert.hpp"
26 #include "Teuchos_CommHelpers.hpp"
27 #include "Teuchos_OrdinalTraits.hpp"
28 #include "Teuchos_TypeNameTraits.hpp"
29 #include "Teuchos_Utils.hpp"
30 #include <numeric>
31 #include <algorithm>
32 #include <iterator>
33 #include <memory>
34 #include <ostream>
35 #include <sstream>
36 
37 #if defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
38 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test, msg) \
63  { \
64  const bool tpetraEfficiencyWarningTest = (throw_exception_test); \
65  if (tpetraEfficiencyWarningTest) { \
66  std::ostringstream errStream; \
67  errStream << Teuchos::typeName(*this) << ":" << std::endl; \
68  errStream << "Efficiency warning: " << #throw_exception_test << std::endl; \
69  errStream << msg; \
70  std::string err = errStream.str(); \
71  if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
72  std::cerr << err << std::endl; \
73  } \
74  } \
75  }
76 #else
77 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test, msg)
102 #endif
103 
104 // handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WARNINGS
105 #if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
106 #define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg) \
108  { \
109  std::ostringstream errStream; \
110  errStream << Teuchos::typeName(*this) << msg; \
111  std::string err = errStream.str(); \
112  if (TPETRA_PRINTS_ABUSE_WARNINGS && (throw_exception_test)) { \
113  std::cerr << err << std::endl; \
114  } \
115  TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
116  }
117 #else
118 #define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg)
120 #endif
121 
151 #define SHARED_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg, comm) \
152  { \
153  using Teuchos::outArg; \
154  const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm) + 1 : 0; \
155  int gbl_throw; \
156  Teuchos::reduceAll(comm, Teuchos::REDUCE_MAX, lcl_throw_exception, outArg(gbl_throw)); \
157  TEUCHOS_TEST_FOR_EXCEPTION(gbl_throw, Exception, \
158  msg << " Failure on at least one process, including process " << gbl_throw - 1 << "." << std::endl); \
159  }
160 
161 namespace Tpetra {
162 
174 template <typename MapType, typename KeyArgType, typename ValueArgType>
175 typename MapType::iterator efficientAddOrUpdate(MapType& m,
176  const KeyArgType& k,
177  const ValueArgType& v) {
178  typename MapType::iterator lb = m.lower_bound(k);
179  if (lb != m.end() && !(m.key_comp()(k, lb->first))) {
180  lb->second = v;
181  return (lb);
182  } else {
183  typedef typename MapType::value_type MVT;
184  return (m.insert(lb, MVT(k, v)));
185  }
186 }
187 
195 namespace SortDetails {
196 
205 template <class IT1>
206 bool isAlreadySorted(const IT1& first, const IT1& last) {
207  typedef typename std::iterator_traits<IT1>::difference_type DT;
208  DT myit = Teuchos::OrdinalTraits<DT>::one();
209  const DT sz = last - first;
210  for (; myit < sz; ++myit) {
211  if (first[myit] < first[myit - 1]) {
212  return false;
213  }
214  }
215  return true;
216 }
217 
227 template <class IT>
228 IT getPivot(const IT& first, const IT& last) {
229  IT pivot(first + (last - first) / 2);
230  if (*first <= *pivot && *(last - 1) <= *first)
231  pivot = first;
232  else if (*(last - 1) <= *pivot && *first <= *(last - 1))
233  pivot = last - 1;
234  return pivot;
235 }
236 
251 template <class IT1, class IT2>
252 IT1 partition2(
253  const IT1& first1,
254  const IT1& last1,
255  const IT2& first2,
256  const IT2& last2,
257  const IT1& pivot) {
258  typename std::iterator_traits<IT1>::value_type piv(*pivot);
259  std::swap(*pivot, *(last1 - 1));
260  std::swap(first2[(pivot - first1)], *(last2 - 1));
261  IT1 store1 = first1;
262  for (IT1 it = first1; it != last1 - 1; ++it) {
263  if (*it <= piv) {
264  std::swap(*store1, *it);
265  std::swap(first2[(store1 - first1)], first2[(it - first1)]);
266  ++store1;
267  }
268  }
269  std::swap(*(last1 - 1), *store1);
270  std::swap(*(last2 - 1), first2[store1 - first1]);
271  return store1;
272 }
273 
290 template <class IT1, class IT2, class IT3>
291 IT1 partition3(
292  const IT1& first1,
293  const IT1& last1,
294  const IT2& first2,
295  const IT2& last2,
296  const IT3& first3,
297  const IT3& last3,
298  const IT1& pivot) {
299  typename std::iterator_traits<IT1>::value_type piv(*pivot);
300  std::swap(*pivot, *(last1 - 1));
301  std::swap(first2[(pivot - first1)], *(last2 - 1));
302  std::swap(first3[(pivot - first1)], *(last3 - 1));
303  IT1 store1 = first1;
304  for (IT1 it = first1; it != last1 - 1; ++it) {
305  if (*it <= piv) {
306  std::swap(*store1, *it);
307  std::swap(first2[(store1 - first1)], first2[(it - first1)]);
308  std::swap(first3[(store1 - first1)], first3[(it - first1)]);
309  ++store1;
310  }
311  }
312  std::swap(*(last1 - 1), *store1);
313  std::swap(*(last2 - 1), first2[store1 - first1]);
314  std::swap(*(last3 - 1), first3[store1 - first1]);
315  return store1;
316 }
317 
328 template <class IT1, class IT2>
329 void quicksort2(
330  const IT1& first1,
331  const IT1& last1,
332  const IT2& first2,
333  const IT2& last2) {
334  typedef typename std::iterator_traits<IT1>::difference_type DT;
335  DT DT1 = Teuchos::OrdinalTraits<DT>::one();
336  if (last1 - first1 > DT1) {
337  IT1 pivot = getPivot(first1, last1);
338  pivot = partition2(first1, last1, first2, last2, pivot);
339  quicksort2(first1, pivot, first2, first2 + (pivot - first1));
340  quicksort2(pivot + 1, last1, first2 + (pivot - first1) + 1, last2);
341  }
342 }
343 
356 template <class IT1, class IT2, class IT3>
357 void quicksort3(
358  const IT1& first1,
359  const IT1& last1,
360  const IT2& first2,
361  const IT2& last2,
362  const IT3& first3,
363  const IT3& last3) {
364  typedef typename std::iterator_traits<IT1>::difference_type DT;
365  DT DT1 = Teuchos::OrdinalTraits<DT>::one();
366  if (last1 - first1 > DT1) {
367  IT1 pivot = getPivot(first1, last1);
368  pivot = partition3(first1, last1, first2, last2, first3, last3, pivot);
369  quicksort3(first1, pivot, first2, first2 + (pivot - first1), first3, first3 + (pivot - first1));
370  quicksort3(pivot + 1, last1, first2 + (pivot - first1) + 1, last2, first3 + (pivot - first1) + 1, last3);
371  }
372 }
373 
380 template <class IT1, class IT2, class IT3>
381 void sh_sort3(
382  const IT1& first1,
383  const IT1& last1,
384  const IT2& first2,
385  const IT2& /* last2 */,
386  const IT3& first3,
387  const IT3& /* last3 */) {
388  typedef typename std::iterator_traits<IT1>::difference_type DT;
389  DT n = last1 - first1;
390  DT m = n / 2;
391  DT z = Teuchos::OrdinalTraits<DT>::zero();
392  while (m > z) {
393  DT max = n - m;
394  for (DT j = 0; j < max; j++) {
395  for (DT k = j; k >= 0; k -= m) {
396  if (first1[k + m] >= first1[k])
397  break;
398  std::swap(first1[k + m], first1[k]);
399  std::swap(first2[k + m], first2[k]);
400  std::swap(first3[k + m], first3[k]);
401  }
402  }
403  m = m / 2;
404  }
405 }
406 
413 template <class IT1, class IT2>
414 void sh_sort2(
415  const IT1& first1,
416  const IT1& last1,
417  const IT2& first2,
418  const IT2& /* last2 */) {
419  typedef typename std::iterator_traits<IT1>::difference_type DT;
420  DT n = last1 - first1;
421  DT m = n / 2;
422  DT z = Teuchos::OrdinalTraits<DT>::zero();
423  while (m > z) {
424  DT max = n - m;
425  for (DT j = 0; j < max; j++) {
426  for (DT k = j; k >= 0; k -= m) {
427  if (first1[k + m] >= first1[k])
428  break;
429  std::swap(first1[k + m], first1[k]);
430  std::swap(first2[k + m], first2[k]);
431  }
432  }
433  m = m / 2;
434  }
435 }
436 
441 template <typename IT1>
442 std::vector<typename std::iterator_traits<IT1>::difference_type> sort_indexes(IT1 first, IT1 last) {
443  typedef typename std::iterator_traits<IT1>::difference_type DT;
444 
445  DT length = last - first;
446  std::vector<DT> idx(length);
447  std::iota(idx.begin(), idx.end(), 0);
448 
449  std::stable_sort(idx.begin(), idx.end(),
450  [&first](size_t i1, size_t i2) { return first[i1] < first[i2]; });
451 
452  return idx;
453 }
454 
458 template <typename IT1, typename IT2>
459 void apply_permutation(
460  IT1 first,
461  IT1 last,
462  IT2 indices) {
463  typedef typename std::iterator_traits<IT1>::difference_type DT;
464  typedef typename std::iterator_traits<IT1>::value_type T;
465 
466  DT n = last - first;
467 
468  Kokkos::View<T*, Kokkos::HostSpace> tmp(Kokkos::view_alloc(Kokkos::WithoutInitializing, "tmp"), n);
469 
470  Kokkos::parallel_for("apply_permutation_1",
471  Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
472  [=](const int j) {
473  tmp(j) = first[indices[j]];
474  });
475  Kokkos::parallel_for("apply_permutation_2",
476  Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
477  [=](const int j) {
478  first[j] = tmp(j);
479  });
480 }
481 
488 template <class IT1, class IT2>
489 void std_sort2(const IT1& first1,
490  const IT1& last1,
491  const IT2& first2,
492  const IT2& last2) {
493  auto indices = sort_indexes(first1, last1);
494  apply_permutation(first1, last1, indices);
495  apply_permutation(first2, last2, indices);
496 }
497 
504 template <class IT1, class IT2, class IT3>
505 void std_sort3(
506  const IT1& first1,
507  const IT1& last1,
508  const IT2& first2,
509  const IT2& last2,
510  const IT3& first3,
511  const IT3& last3) {
512  auto indices = sort_indexes(first1, last1);
513  apply_permutation(first1, last1, indices);
514  apply_permutation(first2, last2, indices);
515  apply_permutation(first3, last3, indices);
516 }
517 
518 } // end namespace SortDetails
519 
538 template <class IT1, class IT2>
539 void sort2(const IT1& first1, const IT1& last1, const IT2& first2, const bool stableSort = false) {
540  // Quicksort uses best-case N log N time whether or not the input
541  // data is sorted. However, the common case in Tpetra is that the
542  // input data are sorted, so we first check whether this is the
543  // case before reverting to Quicksort.
544  if (SortDetails::isAlreadySorted(first1, last1)) {
545  return;
546  }
547  if (stableSort)
548  SortDetails::std_sort2(first1, last1, first2, first2 + (last1 - first1));
549  else
550  SortDetails::sh_sort2(first1, last1, first2, first2 + (last1 - first1));
551 #ifdef HAVE_TPETRA_DEBUG
552  if (!SortDetails::isAlreadySorted(first1, last1)) {
553  std::cout << "Trouble: sort() did not sort !!" << std::endl;
554  return;
555  }
556 #endif
557 }
558 
575 template <class View1, class View2>
576 void sort2(View1& view1, const size_t& size, View2& view2) {
577  // NOTE: This assumes the view is host-accessible.
578 
579  // Wrap the views as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
580  Teuchos::ArrayRCP<typename View1::non_const_value_type> view1_rcp = Kokkos::Compat::persistingView(view1, 0, size);
581  Teuchos::ArrayRCP<typename View2::non_const_value_type> view2_rcp = Kokkos::Compat::persistingView(view2, 0, size);
582 
583  sort2(view1_rcp.begin(), view1_rcp.end(), view2_rcp.begin());
584 }
585 
594 template <class View>
595 void sort(View& view, const size_t& size) {
596  // NOTE: This assumes the view is host-accessible.
597 
598  // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
599  Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
600 
601  std::sort(view_rcp.begin(), view_rcp.end());
602 }
603 
612 template <class View>
613 void reverse_sort(View& view, const size_t& size) {
614  // NOTE: This assumes the view is host-accessible.
615  // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
616  Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
617 
618  std::sort(view_rcp.rbegin(), view_rcp.rend());
619 }
620 
636 template <class IT1, class IT2, class IT3>
637 void sort3(const IT1& first1, const IT1& last1, const IT2& first2,
638  const IT3& first3, const bool stableSort = false) {
639  // Quicksort uses best-case N log N time whether or not the input
640  // data is sorted. However, the common case in Tpetra is that the
641  // input data are sorted, so we first check whether this is the
642  // case before reverting to Quicksort.
643  if (SortDetails::isAlreadySorted(first1, last1)) {
644  return;
645  }
646  if (stableSort)
647  SortDetails::std_sort3(first1, last1, first2, first2 + (last1 - first1), first3,
648  first3 + (last1 - first1));
649  else
650  SortDetails::sh_sort3(first1, last1, first2, first2 + (last1 - first1), first3,
651  first3 + (last1 - first1));
652 #ifdef HAVE_TPETRA_DEBUG
653  if (!SortDetails::isAlreadySorted(first1, last1)) {
654  std::cout << " Trouble sort did not actually sort... !!!!!!" << std::endl;
655  return;
656  }
657 #endif
658 }
659 
703 template <class IT1, class IT2>
704 void merge2(IT1& indResultOut, IT2& valResultOut,
705  IT1 indBeg, IT1 indEnd,
706  IT2 valBeg, IT2 /* valEnd */) {
707  if (indBeg == indEnd) {
708  indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
709  valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
710  } else {
711  IT1 indResult = indBeg;
712  IT2 valResult = valBeg;
713  if (indBeg != indEnd) {
714  ++indBeg;
715  ++valBeg;
716  while (indBeg != indEnd) {
717  if (*indResult == *indBeg) { // adjacent column indices equal
718  *valResult += *valBeg; // merge entries by adding their values together
719  } else { // adjacent column indices not equal
720  *(++indResult) = *indBeg; // shift over the index
721  *(++valResult) = *valBeg; // shift over the value
722  }
723  ++indBeg;
724  ++valBeg;
725  }
726  ++indResult; // exclusive end of merged result
727  ++valResult; // exclusive end of merged result
728 
729  // mfh 24 Feb 2014: Setting these is technically correct, but
730  // since the resulting variables aren't used after this point,
731  // it may result in a build error.
732  //
733  // indEnd = indResult;
734  // valEnd = valResult;
735  }
736  indResultOut = indResult;
737  valResultOut = valResult;
738  }
739 }
740 
789 template <class IT1, class IT2, class BinaryFunction>
790 void merge2(IT1& indResultOut, IT2& valResultOut,
791  IT1 indBeg, IT1 indEnd,
792  IT2 valBeg, IT2 valEnd,
793  BinaryFunction f) {
794  if (indBeg == indEnd) {
795  indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
796  valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
797  } else {
798  IT1 indResult = indBeg;
799  IT2 valResult = valBeg;
800  if (indBeg != indEnd) {
801  ++indBeg;
802  ++valBeg;
803  while (indBeg != indEnd) {
804  if (*indResult == *indBeg) { // adjacent column indices equal
805  *valResult = f(*valResult, *valBeg); // merge entries via values
806  } else { // adjacent column indices not equal
807  *(++indResult) = *indBeg; // shift over the index
808  *(++valResult) = *valBeg; // shift over the value
809  }
810  ++indBeg;
811  ++valBeg;
812  }
813  ++indResult; // exclusive end of merged result
814  ++valResult; // exclusive end of merged result
815  indEnd = indResult;
816  valEnd = valResult;
817  }
818  indResultOut = indResult;
819  valResultOut = valResult;
820  }
821 }
822 
851 template <class KeyInputIterType, class ValueInputIterType,
852  class KeyOutputIterType, class ValueOutputIterType,
853  class BinaryFunction>
854 void keyValueMerge(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
855  ValueInputIterType valBeg1, ValueInputIterType valEnd1,
856  KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
857  ValueInputIterType valBeg2, ValueInputIterType valEnd2,
858  KeyOutputIterType keyOut, ValueOutputIterType valOut,
859  BinaryFunction f) {
860  while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
861  if (*keyBeg1 < *keyBeg2) {
862  *keyOut++ = *keyBeg1++;
863  *valOut++ = *valBeg1++;
864  } else if (*keyBeg1 > *keyBeg2) {
865  *keyOut++ = *keyBeg2++;
866  *valOut++ = *valBeg2++;
867  } else { // *keyBeg1 == *keyBeg2
868  *keyOut++ = *keyBeg1;
869  *valOut++ = f(*valBeg1, *valBeg2);
870  ++keyBeg1;
871  ++valBeg1;
872  ++keyBeg2;
873  ++valBeg2;
874  }
875  }
876  // At most one of the two sequences will be nonempty.
877  std::copy(keyBeg1, keyEnd1, keyOut);
878  std::copy(valBeg1, valEnd1, valOut);
879  std::copy(keyBeg2, keyEnd2, keyOut);
880  std::copy(valBeg2, valEnd2, valOut);
881 }
882 
883 template <class KeyInputIterType>
884 size_t
885 keyMergeCount(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
886  KeyInputIterType keyBeg2, KeyInputIterType keyEnd2) {
887  size_t count = 0;
888  while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
889  if (*keyBeg1 < *keyBeg2) {
890  ++keyBeg1;
891  } else if (*keyBeg1 > *keyBeg2) {
892  ++keyBeg2;
893  } else { // *keyBeg1 == *keyBeg2
894  ++keyBeg1;
895  ++keyBeg2;
896  }
897  ++count;
898  }
899  // At most one of the two sequences will be nonempty.
900  count += static_cast<size_t>(keyEnd1 - keyBeg1) +
901  static_cast<size_t>(keyEnd2 - keyBeg2);
902  return count;
903 }
904 
905 namespace Details {
925 bool congruent(const Teuchos::Comm<int>& comm1,
926  const Teuchos::Comm<int>& comm2);
927 
937 template <class DualViewType>
938 Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
939 getArrayViewFromDualView(const DualViewType& x) {
940  static_assert(static_cast<int>(DualViewType::t_dev::rank) == 1,
941  "The input DualView must have rank 1.");
942  TEUCHOS_TEST_FOR_EXCEPTION(x.need_sync_host(), std::logic_error,
943  "The "
944  "input Kokkos::DualView was most recently modified on device, but this "
945  "function needs the host view of the data to be the most recently "
946  "modified.");
947 
948  auto x_host = x.view_host();
949  typedef typename DualViewType::t_dev::value_type value_type;
950  // mfh 15 Jan 2019: In debug mode, Teuchos::ArrayView's
951  // constructor throws if the pointer is nonnull but the length
952  // is nonpositive.
953  const auto len = x_host.extent(0);
954  return Teuchos::ArrayView<value_type>(len != 0 ? x_host.data() : nullptr,
955  len);
956 }
957 
974 template <class T, class DT>
975 Kokkos::DualView<T*, DT>
976 getDualViewCopyFromArrayView(const Teuchos::ArrayView<const T>& x_av,
977  const char label[],
978  const bool leaveOnHost) {
979  using Kokkos::MemoryUnmanaged;
980  typedef typename DT::memory_space DMS;
981  typedef typename DT::execution_space execution_space;
982  typedef Kokkos::HostSpace HMS;
983 
984  const size_t len = static_cast<size_t>(x_av.size());
985  Kokkos::View<const T*, HMS, MemoryUnmanaged> x_in(x_av.getRawPtr(), len);
986  Kokkos::DualView<T*, DT> x_out(label, len);
987  if (leaveOnHost) {
988  x_out.modify_host();
989  // DEEP_COPY REVIEW - NOT TESTED FOR CUDA BUILD
990  Kokkos::deep_copy(x_out.view_host(), x_in);
991  } else {
992  x_out.template modify<DMS>();
993  // DEEP_COPY REVIEW - HOST-TO-DEVICE
994  Kokkos::deep_copy(execution_space(), x_out.template view<DMS>(), x_in);
995  }
996  return x_out;
997 }
998 
1006 template <class DualViewType>
1007 std::string dualViewStatusToString(const DualViewType& dv, const char name[]) {
1008  const auto host = dv.need_sync_device();
1009  const auto dev = dv.need_sync_host();
1010 
1011  std::ostringstream os;
1012  os << name << ": {size: " << dv.extent(0)
1013  << ", sync: {host: " << host << ", dev: " << dev << "}";
1014  return os.str();
1015 }
1016 
1021 template <class ArrayType>
1022 void verbosePrintArray(std::ostream& out,
1023  const ArrayType& x,
1024  const char name[],
1025  const size_t maxNumToPrint) {
1026  out << name << ": [";
1027 
1028  const size_t numEnt(x.size());
1029  if (maxNumToPrint == 0) {
1030  if (numEnt != 0) {
1031  out << "...";
1032  }
1033  } else {
1034  const size_t numToPrint = numEnt > maxNumToPrint ? maxNumToPrint : numEnt;
1035  size_t k = 0;
1036  for (; k < numToPrint; ++k) {
1037  out << x[k];
1038  if (k + size_t(1) < numToPrint) {
1039  out << ", ";
1040  }
1041  }
1042  if (k < numEnt) {
1043  out << ", ...";
1044  }
1045  }
1046  out << "]";
1047 }
1048 
1052 std::unique_ptr<std::string>
1053 createPrefix(const int myRank,
1054  const char prefix[]);
1055 
1063 std::unique_ptr<std::string>
1064 createPrefix(const Teuchos::Comm<int>* comm,
1065  const char functionName[]);
1066 
1073 std::unique_ptr<std::string>
1074 createPrefix(const Teuchos::Comm<int>*,
1075  const char className[],
1076  const char methodName[]);
1077 
1078 } // namespace Details
1079 } // namespace Tpetra
1080 
1081 #endif // TPETRA_UTIL_HPP
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
Definition: Tpetra_Util.cpp:33
void merge2(IT1 &indResultOut, IT2 &valResultOut, IT1 indBeg, IT1 indEnd, IT2 valBeg, IT2)
Merge values in place, additively, with the same index.
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3, const bool stableSort=false)
Sort the first array, and apply the same permutation to the second and third arrays.
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
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.
Kokkos::DualView< T *, DT > getDualViewCopyFromArrayView(const Teuchos::ArrayView< const T > &x_av, const char label[], const bool leaveOnHost)
Get a 1-D Kokkos::DualView which is a deep copy of the input Teuchos::ArrayView (which views host mem...
void keyValueMerge(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1, ValueInputIterType valBeg1, ValueInputIterType valEnd1, KeyInputIterType keyBeg2, KeyInputIterType keyEnd2, ValueInputIterType valBeg2, ValueInputIterType valEnd2, KeyOutputIterType keyOut, ValueOutputIterType valOut, BinaryFunction f)
Merge two sorted (by keys) sequences of unique (key,value) pairs by combining pairs with equal keys...
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false)
Sort the first array, and apply the resulting permutation to the second array.
MapType::iterator efficientAddOrUpdate(MapType &m, const KeyArgType &k, const ValueArgType &v)
Efficiently insert or replace an entry in an std::map.
std::string dualViewStatusToString(const DualViewType &dv, const char name[])
Return the status of the given Kokkos::DualView, as a human-readable string.
Teuchos::ArrayView< typename DualViewType::t_dev::value_type > getArrayViewFromDualView(const DualViewType &x)
Get a Teuchos::ArrayView which views the host Kokkos::View of the input 1-D Kokkos::DualView.
void reverse_sort(View &view, const size_t &size)
Convenience wrapper for a reversed std::sort for host-accessible views.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
Definition: Tpetra_Util.cpp:69