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  {
179  typename MapType::iterator lb = m.lower_bound(k);
180  if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
181  lb->second = v;
182  return(lb);
183  }
184  else {
185  typedef typename MapType::value_type MVT;
186  return(m.insert(lb, MVT(k, v)));
187  }
188  }
189 
197  namespace SortDetails {
198 
207  template<class IT1>
208  bool isAlreadySorted(const IT1& first, const IT1& last){
209  typedef typename std::iterator_traits<IT1>::difference_type DT;
210  DT myit = Teuchos::OrdinalTraits<DT>::one();
211  const DT sz = last - first;
212  for(;myit < sz; ++myit){
213  if(first[myit] < first[myit-1]){
214  return false;
215  }
216  }
217  return true;
218  }
219 
229  template<class IT>
230  IT getPivot(const IT& first, const IT& last){
231  IT pivot(first+(last-first)/2);
232  if(*first<=*pivot && *(last-1)<=*first) pivot=first;
233  else if(*(last-1)<=*pivot && *first<= *(last-1)) 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  {
259  typename std::iterator_traits<IT1>::value_type piv(*pivot);
260  std::swap(*pivot, *(last1-1));
261  std::swap(first2[(pivot-first1)], *(last2-1));
262  IT1 store1=first1;
263  for(IT1 it=first1; it!=last1-1; ++it){
264  if(*it<=piv){
265  std::swap(*store1, *it);
266  std::swap(first2[(store1-first1)], first2[(it-first1)]);
267  ++store1;
268  }
269  }
270  std::swap(*(last1-1), *store1);
271  std::swap(*(last2-1), first2[store1-first1]);
272  return store1;
273  }
274 
291  template<class IT1, class IT2, class IT3>
292  IT1 partition3(
293  const IT1& first1,
294  const IT1& last1,
295  const IT2& first2,
296  const IT2& last2,
297  const IT3& first3,
298  const IT3& last3,
299  const IT1& pivot)
300  {
301  typename std::iterator_traits<IT1>::value_type piv(*pivot);
302  std::swap(*pivot, *(last1-1));
303  std::swap(first2[(pivot-first1)], *(last2-1));
304  std::swap(first3[(pivot-first1)], *(last3-1));
305  IT1 store1=first1;
306  for(IT1 it=first1; it!=last1-1; ++it){
307  if(*it<=piv){
308  std::swap(*store1, *it);
309  std::swap(first2[(store1-first1)], first2[(it-first1)]);
310  std::swap(first3[(store1-first1)], first3[(it-first1)]);
311  ++store1;
312  }
313  }
314  std::swap(*(last1-1), *store1);
315  std::swap(*(last2-1), first2[store1-first1]);
316  std::swap(*(last3-1), first3[store1-first1]);
317  return store1;
318  }
319 
330  template<class IT1, class IT2>
331  void quicksort2(
332  const IT1& first1,
333  const IT1& last1,
334  const IT2& first2,
335  const IT2& last2)
336  {
337  typedef typename std::iterator_traits<IT1>::difference_type DT;
338  DT DT1 = Teuchos::OrdinalTraits<DT>::one();
339  if(last1-first1 > DT1){
340  IT1 pivot = getPivot(first1, last1);
341  pivot = partition2(first1, last1, first2, last2, pivot);
342  quicksort2(first1, pivot, first2, first2+(pivot-first1));
343  quicksort2(pivot+1, last1, first2+(pivot-first1)+1, last2);
344  }
345  }
346 
359  template<class IT1, class IT2, class IT3>
360  void quicksort3(
361  const IT1& first1,
362  const IT1& last1,
363  const IT2& first2,
364  const IT2& last2,
365  const IT3& first3,
366  const IT3& last3)
367  {
368  typedef typename std::iterator_traits<IT1>::difference_type DT;
369  DT DT1 = Teuchos::OrdinalTraits<DT>::one();
370  if(last1-first1 > DT1){
371  IT1 pivot = getPivot(first1, last1);
372  pivot = partition3(first1, last1, first2, last2, first3, last3, pivot);
373  quicksort3(first1, pivot, first2, first2+(pivot-first1), first3, first3+(pivot-first1));
374  quicksort3(pivot+1, last1, first2+(pivot-first1)+1, last2, first3+(pivot-first1)+1, last3);
375  }
376  }
377 
384  template<class IT1, class IT2, class IT3>
385  void sh_sort3(
386  const IT1& first1,
387  const IT1& last1,
388  const IT2& first2,
389  const IT2& /* last2 */,
390  const IT3& first3,
391  const IT3& /* last3 */)
392  {
393  typedef typename std::iterator_traits<IT1>::difference_type DT;
394  DT n = last1 - first1;
395  DT m = n / 2;
396  DT z = Teuchos::OrdinalTraits<DT>::zero();
397  while (m > z)
398  {
399  DT max = n - m;
400  for (DT j = 0; j < max; j++)
401  {
402  for (DT k = j; k >= 0; k-=m)
403  {
404  if (first1[k+m] >= first1[k])
405  break;
406  std::swap(first1[k+m], first1[k]);
407  std::swap(first2[k+m], first2[k]);
408  std::swap(first3[k+m], first3[k]);
409  }
410  }
411  m = m/2;
412  }
413  }
414 
421  template<class IT1, class IT2>
422  void sh_sort2(
423  const IT1& first1,
424  const IT1& last1,
425  const IT2& first2,
426  const IT2& /* last2 */)
427  {
428  typedef typename std::iterator_traits<IT1>::difference_type DT;
429  DT n = last1 - first1;
430  DT m = n / 2;
431  DT z = Teuchos::OrdinalTraits<DT>::zero();
432  while (m > z)
433  {
434  DT max = n - m;
435  for (DT j = 0; j < max; j++)
436  {
437  for (DT k = j; k >= 0; k-=m)
438  {
439  if (first1[k+m] >= first1[k])
440  break;
441  std::swap(first1[k+m], first1[k]);
442  std::swap(first2[k+m], first2[k]);
443  }
444  }
445  m = m/2;
446  }
447  }
448 
453  template<typename IT1>
454  std::vector<typename std::iterator_traits<IT1>::difference_type> sort_indexes(IT1 first, IT1 last) {
455 
456  typedef typename std::iterator_traits<IT1>::difference_type DT;
457 
458  DT length = last - first;
459  std::vector<DT> idx(length);
460  std::iota(idx.begin(), idx.end(), 0);
461 
462  std::stable_sort(idx.begin(), idx.end(),
463  [&first](size_t i1, size_t i2) {return first[i1] < first[i2];});
464 
465  return idx;
466  }
467 
471  template<typename IT1, typename IT2>
472  void
473  apply_permutation(
474  IT1 first,
475  IT1 last,
476  IT2 indices)
477  {
478  typedef typename std::iterator_traits<IT1>::difference_type DT;
479  typedef typename std::iterator_traits<IT1>::value_type T;
480 
481  DT n = last - first;
482 
483  Kokkos::View<T*, Kokkos::HostSpace> tmp(Kokkos::view_alloc(Kokkos::WithoutInitializing, "tmp"), n);
484 
485  Kokkos::parallel_for("apply_permutation_1",
486  Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
487  [=](const int j) {
488  tmp(j) = first[indices[j]];
489  });
490  Kokkos::parallel_for("apply_permutation_2",
491  Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
492  [=](const int j) {
493  first[j] = tmp(j);
494  });
495  }
496 
503  template<class IT1, class IT2>
504  void std_sort2(const IT1& first1,
505  const IT1& last1,
506  const IT2& first2,
507  const IT2& last2)
508  {
509  auto indices = sort_indexes(first1, last1);
510  apply_permutation(first1, last1, indices);
511  apply_permutation(first2, last2, indices);
512  }
513 
520  template<class IT1, class IT2, class IT3>
521  void std_sort3(
522  const IT1& first1,
523  const IT1& last1,
524  const IT2& first2,
525  const IT2& last2,
526  const IT3& first3,
527  const IT3& last3)
528  {
529  auto indices = sort_indexes(first1, last1);
530  apply_permutation(first1, last1, indices);
531  apply_permutation(first2, last2, indices);
532  apply_permutation(first3, last3, indices);
533  }
534 
535  } //end namespace SortDetails
536 
537 
556  template<class IT1, class IT2>
557  void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false) {
558  // Quicksort uses best-case N log N time whether or not the input
559  // data is sorted. However, the common case in Tpetra is that the
560  // input data are sorted, so we first check whether this is the
561  // case before reverting to Quicksort.
562  if(SortDetails::isAlreadySorted(first1, last1)){
563  return;
564  }
565  if(stableSort)
566  SortDetails::std_sort2(first1, last1, first2, first2+(last1-first1));
567  else
568  SortDetails::sh_sort2(first1, last1, first2, first2+(last1-first1));
569 #ifdef HAVE_TPETRA_DEBUG
570  if(!SortDetails::isAlreadySorted(first1, last1)){
571  std::cout << "Trouble: sort() did not sort !!" << std::endl;
572  return;
573  }
574 #endif
575  }
576 
577 
594  template<class View1, class View2>
595  void sort2(View1 &view1, const size_t &size, View2 &view2) {
596  // NOTE: This assumes the view is host-accessible.
597 
598  // Wrap the views as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
599  Teuchos::ArrayRCP<typename View1::non_const_value_type> view1_rcp = Kokkos::Compat::persistingView(view1, 0, size);
600  Teuchos::ArrayRCP<typename View2::non_const_value_type> view2_rcp = Kokkos::Compat::persistingView(view2, 0, size);
601 
602  sort2(view1_rcp.begin(),view1_rcp.end(),view2_rcp.begin());
603  }
604 
613  template<class View>
614  void sort(View &view, const size_t &size) {
615  // NOTE: This assumes the view is host-accessible.
616 
617  // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
618  Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
619 
620  std::sort(view_rcp.begin(),view_rcp.end());
621  }
622 
631  template<class View>
632  void reverse_sort(View &view, const size_t &size) {
633  // NOTE: This assumes the view is host-accessible.
634  // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
635  Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
636 
637  std::sort(view_rcp.rbegin(),view_rcp.rend());
638  }
639 
640 
641 
642 
658  template<class IT1, class IT2, class IT3>
659  void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2,
660  const IT3 &first3, const bool stableSort=false)
661  {
662  // Quicksort uses best-case N log N time whether or not the input
663  // data is sorted. However, the common case in Tpetra is that the
664  // input data are sorted, so we first check whether this is the
665  // case before reverting to Quicksort.
666  if(SortDetails::isAlreadySorted(first1, last1)){
667  return;
668  }
669  if(stableSort)
670  SortDetails::std_sort3(first1, last1, first2, first2+(last1-first1), first3,
671  first3+(last1-first1));
672  else
673  SortDetails::sh_sort3(first1, last1, first2, first2+(last1-first1), first3,
674  first3+(last1-first1));
675 #ifdef HAVE_TPETRA_DEBUG
676  if(!SortDetails::isAlreadySorted(first1, last1)){
677  std::cout << " Trouble sort did not actually sort... !!!!!!" <<
678  std::endl;
679  return;
680  }
681 #endif
682  }
683 
727  template<class IT1, class IT2>
728  void
729  merge2 (IT1& indResultOut, IT2& valResultOut,
730  IT1 indBeg, IT1 indEnd,
731  IT2 valBeg, IT2 /* valEnd */)
732  {
733  if (indBeg == indEnd) {
734  indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
735  valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
736  }
737  else {
738  IT1 indResult = indBeg;
739  IT2 valResult = valBeg;
740  if (indBeg != indEnd) {
741  ++indBeg;
742  ++valBeg;
743  while (indBeg != indEnd) {
744  if (*indResult == *indBeg) { // adjacent column indices equal
745  *valResult += *valBeg; // merge entries by adding their values together
746  } else { // adjacent column indices not equal
747  *(++indResult) = *indBeg; // shift over the index
748  *(++valResult) = *valBeg; // shift over the value
749  }
750  ++indBeg;
751  ++valBeg;
752  }
753  ++indResult; // exclusive end of merged result
754  ++valResult; // exclusive end of merged result
755 
756  // mfh 24 Feb 2014: Setting these is technically correct, but
757  // since the resulting variables aren't used after this point,
758  // it may result in a build error.
759  //
760  // indEnd = indResult;
761  // valEnd = valResult;
762  }
763  indResultOut = indResult;
764  valResultOut = valResult;
765  }
766  }
767 
816  template<class IT1, class IT2, class BinaryFunction>
817  void
818  merge2 (IT1& indResultOut, IT2& valResultOut,
819  IT1 indBeg, IT1 indEnd,
820  IT2 valBeg, IT2 valEnd,
821  BinaryFunction f)
822  {
823  if (indBeg == indEnd) {
824  indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
825  valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
826  }
827  else {
828  IT1 indResult = indBeg;
829  IT2 valResult = valBeg;
830  if (indBeg != indEnd) {
831  ++indBeg;
832  ++valBeg;
833  while (indBeg != indEnd) {
834  if (*indResult == *indBeg) { // adjacent column indices equal
835  *valResult = f (*valResult, *valBeg); // merge entries via values
836  } else { // adjacent column indices not equal
837  *(++indResult) = *indBeg; // shift over the index
838  *(++valResult) = *valBeg; // shift over the value
839  }
840  ++indBeg;
841  ++valBeg;
842  }
843  ++indResult; // exclusive end of merged result
844  ++valResult; // exclusive end of merged result
845  indEnd = indResult;
846  valEnd = valResult;
847  }
848  indResultOut = indResult;
849  valResultOut = valResult;
850  }
851  }
852 
853 
882  template<class KeyInputIterType, class ValueInputIterType,
883  class KeyOutputIterType, class ValueOutputIterType,
884  class BinaryFunction>
885  void
886  keyValueMerge (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
887  ValueInputIterType valBeg1, ValueInputIterType valEnd1,
888  KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
889  ValueInputIterType valBeg2, ValueInputIterType valEnd2,
890  KeyOutputIterType keyOut, ValueOutputIterType valOut,
891  BinaryFunction f)
892  {
893  while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
894  if (*keyBeg1 < *keyBeg2) {
895  *keyOut++ = *keyBeg1++;
896  *valOut++ = *valBeg1++;
897  } else if (*keyBeg1 > *keyBeg2) {
898  *keyOut++ = *keyBeg2++;
899  *valOut++ = *valBeg2++;
900  } else { // *keyBeg1 == *keyBeg2
901  *keyOut++ = *keyBeg1;
902  *valOut++ = f (*valBeg1, *valBeg2);
903  ++keyBeg1;
904  ++valBeg1;
905  ++keyBeg2;
906  ++valBeg2;
907  }
908  }
909  // At most one of the two sequences will be nonempty.
910  std::copy (keyBeg1, keyEnd1, keyOut);
911  std::copy (valBeg1, valEnd1, valOut);
912  std::copy (keyBeg2, keyEnd2, keyOut);
913  std::copy (valBeg2, valEnd2, valOut);
914  }
915 
916  template<class KeyInputIterType>
917  size_t
918  keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
919  KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
920  {
921  size_t count = 0;
922  while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
923  if (*keyBeg1 < *keyBeg2) {
924  ++keyBeg1;
925  } else if (*keyBeg1 > *keyBeg2) {
926  ++keyBeg2;
927  } else { // *keyBeg1 == *keyBeg2
928  ++keyBeg1;
929  ++keyBeg2;
930  }
931  ++count;
932  }
933  // At most one of the two sequences will be nonempty.
934  count += static_cast<size_t> (keyEnd1 - keyBeg1) +
935  static_cast<size_t> (keyEnd2 - keyBeg2);
936  return count;
937  }
938 
939  namespace Details {
959  bool
960  congruent (const Teuchos::Comm<int>& comm1,
961  const Teuchos::Comm<int>& comm2);
962 
972  template<class DualViewType>
973  Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
974  getArrayViewFromDualView (const DualViewType& x)
975  {
976  static_assert (static_cast<int> (DualViewType::t_dev::rank) == 1,
977  "The input DualView must have rank 1.");
978  TEUCHOS_TEST_FOR_EXCEPTION
979  (x.need_sync_host (), std::logic_error, "The "
980  "input Kokkos::DualView was most recently modified on device, but this "
981  "function needs the host view of the data to be the most recently "
982  "modified.");
983 
984  auto x_host = x.view_host ();
985  typedef typename DualViewType::t_dev::value_type value_type;
986  // mfh 15 Jan 2019: In debug mode, Teuchos::ArrayView's
987  // constructor throws if the pointer is nonnull but the length
988  // is nonpositive.
989  const auto len = x_host.extent (0);
990  return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () : nullptr,
991  len);
992  }
993 
1010  template<class T, class DT>
1011  Kokkos::DualView<T*, DT>
1012  getDualViewCopyFromArrayView (const Teuchos::ArrayView<const T>& x_av,
1013  const char label[],
1014  const bool leaveOnHost)
1015  {
1016  using Kokkos::MemoryUnmanaged;
1017  typedef typename DT::memory_space DMS;
1018  typedef typename DT::execution_space execution_space;
1019  typedef Kokkos::HostSpace HMS;
1020 
1021  const size_t len = static_cast<size_t> (x_av.size ());
1022  Kokkos::View<const T*, HMS, MemoryUnmanaged> x_in (x_av.getRawPtr (), len);
1023  Kokkos::DualView<T*, DT> x_out (label, len);
1024  if (leaveOnHost) {
1025  x_out.modify_host ();
1026  // DEEP_COPY REVIEW - NOT TESTED FOR CUDA BUILD
1027  Kokkos::deep_copy (x_out.view_host (), x_in);
1028  }
1029  else {
1030  x_out.template modify<DMS> ();
1031  // DEEP_COPY REVIEW - HOST-TO-DEVICE
1032  Kokkos::deep_copy (execution_space(), x_out.template view<DMS> (), x_in);
1033  }
1034  return x_out;
1035  }
1036 
1044  template<class DualViewType>
1045  std::string dualViewStatusToString (const DualViewType& dv, const char name[])
1046  {
1047  const auto host = dv.need_sync_device();
1048  const auto dev = dv.need_sync_host();
1049 
1050  std::ostringstream os;
1051  os << name << ": {size: " << dv.extent (0)
1052  << ", sync: {host: " << host << ", dev: " << dev << "}";
1053  return os.str ();
1054  }
1055 
1060  template<class ArrayType>
1061  void
1062  verbosePrintArray(std::ostream& out,
1063  const ArrayType& x,
1064  const char name[],
1065  const size_t maxNumToPrint)
1066  {
1067  out << name << ": [";
1068 
1069  const size_t numEnt(x.size());
1070  if (maxNumToPrint == 0) {
1071  if (numEnt != 0) {
1072  out << "...";
1073  }
1074  }
1075  else {
1076  const size_t numToPrint = numEnt > maxNumToPrint ?
1077  maxNumToPrint : numEnt;
1078  size_t k = 0;
1079  for ( ; k < numToPrint; ++k) {
1080  out << x[k];
1081  if (k + size_t(1) < numToPrint) {
1082  out << ", ";
1083  }
1084  }
1085  if (k < numEnt) {
1086  out << ", ...";
1087  }
1088  }
1089  out << "]";
1090  }
1091 
1095  std::unique_ptr<std::string>
1096  createPrefix(const int myRank,
1097  const char prefix[]);
1098 
1106  std::unique_ptr<std::string>
1107  createPrefix(const Teuchos::Comm<int>* comm,
1108  const char functionName[]);
1109 
1116  std::unique_ptr<std::string>
1117  createPrefix(const Teuchos::Comm<int>*,
1118  const char className[],
1119  const char methodName[]);
1120 
1121  } // namespace Details
1122 } // namespace Tpetra
1123 
1124 #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:34
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:71