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 //
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 // ************************************************************************
38 // @HEADER
39 
40 #ifndef TPETRA_UTIL_HPP
41 #define TPETRA_UTIL_HPP
42 
52 #include "Tpetra_ConfigDefs.hpp"
53 #include "Kokkos_DualView.hpp"
54 #include "KokkosCompat_View.hpp"
55 #include "Teuchos_Assert.hpp"
56 #include "Teuchos_CommHelpers.hpp"
57 #include "Teuchos_OrdinalTraits.hpp"
58 #include "Teuchos_TypeNameTraits.hpp"
59 #include "Teuchos_Utils.hpp"
60 #include <algorithm>
61 #include <iterator>
62 #include <memory>
63 #include <ostream>
64 #include <sstream>
65 
66 #if defined(HAVE_TPETRA_THROW_EFFICIENCY_WARNINGS) || defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
67 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg) \
101 { \
102  const bool tpetraEfficiencyWarningTest = (throw_exception_test); \
103  if (tpetraEfficiencyWarningTest) { \
104  std::ostringstream errStream; \
105  errStream << Teuchos::typeName(*this) << ":" << std::endl; \
106  errStream << "Efficiency warning: " << #throw_exception_test << std::endl; \
107  errStream << msg; \
108  std::string err = errStream.str(); \
109  if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
110  std::cerr << err << std::endl; \
111  } \
112  TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest, Exception, err); \
113  } \
114 }
115 #else
116 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg)
150 #endif
151 
152 // handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WARNINGS
153 #if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
154 #define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg) \
156 { \
157  std::ostringstream errStream; \
158  errStream << Teuchos::typeName(*this) << msg; \
159  std::string err = errStream.str(); \
160  if (TPETRA_PRINTS_ABUSE_WARNINGS && (throw_exception_test)) { \
161  std::cerr << err << std::endl; \
162  } \
163  TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
164 }
165 #else
166 #define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg)
168 #endif
169 
199 #define SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
200 { \
201  using Teuchos::outArg; \
202  const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm)+1 : 0; \
203  int gbl_throw; \
204  Teuchos::reduceAll(comm,Teuchos::REDUCE_MAX,lcl_throw_exception,outArg(gbl_throw)); \
205  TEUCHOS_TEST_FOR_EXCEPTION(gbl_throw,Exception, \
206  msg << " Failure on at least one process, including process " << gbl_throw-1 << "." << std::endl); \
207 }
208 
209 namespace Tpetra {
210 
222  template<typename MapType, typename KeyArgType, typename ValueArgType>
223  typename MapType::iterator efficientAddOrUpdate(MapType& m,
224  const KeyArgType & k,
225  const ValueArgType & v)
226  {
227  typename MapType::iterator lb = m.lower_bound(k);
228  if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
229  lb->second = v;
230  return(lb);
231  }
232  else {
233  typedef typename MapType::value_type MVT;
234  return(m.insert(lb, MVT(k, v)));
235  }
236  }
237 
245  namespace SortDetails {
246 
255  template<class IT1>
256  bool isAlreadySorted(const IT1& first, const IT1& last){
257  typedef typename std::iterator_traits<IT1>::difference_type DT;
258  DT myit = Teuchos::OrdinalTraits<DT>::one();
259  const DT sz = last - first;
260  for(;myit < sz; ++myit){
261  if(first[myit] < first[myit-1]){
262  return false;
263  }
264  }
265  return true;
266  }
267 
277  template<class IT>
278  IT getPivot(const IT& first, const IT& last){
279  IT pivot(first+(last-first)/2);
280  if(*first<=*pivot && *(last-1)<=*first) pivot=first;
281  else if(*(last-1)<=*pivot && *first<= *(last-1)) pivot = last-1;
282  return pivot;
283  }
284 
299  template<class IT1, class IT2>
300  IT1 partition2(
301  const IT1& first1,
302  const IT1& last1,
303  const IT2& first2,
304  const IT2& last2,
305  const IT1& pivot)
306  {
307  typename std::iterator_traits<IT1>::value_type piv(*pivot);
308  std::swap(*pivot, *(last1-1));
309  std::swap(first2[(pivot-first1)], *(last2-1));
310  IT1 store1=first1;
311  for(IT1 it=first1; it!=last1-1; ++it){
312  if(*it<=piv){
313  std::swap(*store1, *it);
314  std::swap(first2[(store1-first1)], first2[(it-first1)]);
315  ++store1;
316  }
317  }
318  std::swap(*(last1-1), *store1);
319  std::swap(*(last2-1), first2[store1-first1]);
320  return store1;
321  }
322 
339  template<class IT1, class IT2, class IT3>
340  IT1 partition3(
341  const IT1& first1,
342  const IT1& last1,
343  const IT2& first2,
344  const IT2& last2,
345  const IT3& first3,
346  const IT3& last3,
347  const IT1& pivot)
348  {
349  typename std::iterator_traits<IT1>::value_type piv(*pivot);
350  std::swap(*pivot, *(last1-1));
351  std::swap(first2[(pivot-first1)], *(last2-1));
352  std::swap(first3[(pivot-first1)], *(last3-1));
353  IT1 store1=first1;
354  for(IT1 it=first1; it!=last1-1; ++it){
355  if(*it<=piv){
356  std::swap(*store1, *it);
357  std::swap(first2[(store1-first1)], first2[(it-first1)]);
358  std::swap(first3[(store1-first1)], first3[(it-first1)]);
359  ++store1;
360  }
361  }
362  std::swap(*(last1-1), *store1);
363  std::swap(*(last2-1), first2[store1-first1]);
364  std::swap(*(last3-1), first3[store1-first1]);
365  return store1;
366  }
367 
378  template<class IT1, class IT2>
379  void quicksort2(
380  const IT1& first1,
381  const IT1& last1,
382  const IT2& first2,
383  const IT2& last2)
384  {
385  typedef typename std::iterator_traits<IT1>::difference_type DT;
386  DT DT1 = Teuchos::OrdinalTraits<DT>::one();
387  if(last1-first1 > DT1){
388  IT1 pivot = getPivot(first1, last1);
389  pivot = partition2(first1, last1, first2, last2, pivot);
390  quicksort2(first1, pivot, first2, first2+(pivot-first1));
391  quicksort2(pivot+1, last1, first2+(pivot-first1)+1, last2);
392  }
393  }
394 
407  template<class IT1, class IT2, class IT3>
408  void quicksort3(
409  const IT1& first1,
410  const IT1& last1,
411  const IT2& first2,
412  const IT2& last2,
413  const IT3& first3,
414  const IT3& last3)
415  {
416  typedef typename std::iterator_traits<IT1>::difference_type DT;
417  DT DT1 = Teuchos::OrdinalTraits<DT>::one();
418  if(last1-first1 > DT1){
419  IT1 pivot = getPivot(first1, last1);
420  pivot = partition3(first1, last1, first2, last2, first3, last3, pivot);
421  quicksort3(first1, pivot, first2, first2+(pivot-first1), first3, first3+(pivot-first1));
422  quicksort3(pivot+1, last1, first2+(pivot-first1)+1, last2, first3+(pivot-first1)+1, last3);
423  }
424  }
425 
432  template<class IT1, class IT2, class IT3>
433  void sh_sort3(
434  const IT1& first1,
435  const IT1& last1,
436  const IT2& first2,
437  const IT2& /* last2 */,
438  const IT3& first3,
439  const IT3& /* last3 */)
440  {
441  typedef typename std::iterator_traits<IT1>::difference_type DT;
442  DT n = last1 - first1;
443  DT m = n / 2;
444  DT z = Teuchos::OrdinalTraits<DT>::zero();
445  while (m > z)
446  {
447  DT max = n - m;
448  for (DT j = 0; j < max; j++)
449  {
450  for (DT k = j; k >= 0; k-=m)
451  {
452  if (first1[k+m] >= first1[k])
453  break;
454  std::swap(first1[k+m], first1[k]);
455  std::swap(first2[k+m], first2[k]);
456  std::swap(first3[k+m], first3[k]);
457  }
458  }
459  m = m/2;
460  }
461  }
462 
469  template<class IT1, class IT2>
470  void sh_sort2(
471  const IT1& first1,
472  const IT1& last1,
473  const IT2& first2,
474  const IT2& /* last2 */)
475  {
476  typedef typename std::iterator_traits<IT1>::difference_type DT;
477  DT n = last1 - first1;
478  DT m = n / 2;
479  DT z = Teuchos::OrdinalTraits<DT>::zero();
480  while (m > z)
481  {
482  DT max = n - m;
483  for (DT j = 0; j < max; j++)
484  {
485  for (DT k = j; k >= 0; k-=m)
486  {
487  if (first1[k+m] >= first1[k])
488  break;
489  std::swap(first1[k+m], first1[k]);
490  std::swap(first2[k+m], first2[k]);
491  }
492  }
493  m = m/2;
494  }
495  }
496 
497  } //end namespace SortDetails
498 
499 
518  template<class IT1, class IT2>
519  void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2) {
520  // Quicksort uses best-case N log N time whether or not the input
521  // data is sorted. However, the common case in Tpetra is that the
522  // input data are sorted, so we first check whether this is the
523  // case before reverting to Quicksort.
524  if(SortDetails::isAlreadySorted(first1, last1)){
525  return;
526  }
527  SortDetails::sh_sort2(first1, last1, first2, first2+(last1-first1));
528 #ifdef HAVE_TPETRA_DEBUG
529  if(!SortDetails::isAlreadySorted(first1, last1)){
530  std::cout << "Trouble: sort() did not sort !!" << std::endl;
531  return;
532  }
533 #endif
534  }
535 
536 
553  template<class View1, class View2>
554  void sort2(View1 &view1, const size_t &size, View2 &view2) {
555  // NOTE: This assumes the view is host-accessible.
556 
557  // Wrap the views as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
558  Teuchos::ArrayRCP<typename View1::non_const_value_type> view1_rcp = Kokkos::Compat::persistingView(view1, 0, size);
559  Teuchos::ArrayRCP<typename View2::non_const_value_type> view2_rcp = Kokkos::Compat::persistingView(view2, 0, size);
560 
561  sort2(view1_rcp.begin(),view1_rcp.end(),view2_rcp.begin());
562  }
563 
572  template<class View>
573  void sort(View &view, const size_t &size) {
574  // NOTE: This assumes the view is host-accessible.
575 
576  // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
577  Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
578 
579  std::sort(view_rcp.begin(),view_rcp.end());
580  }
581 
590  template<class View>
591  void reverse_sort(View &view, const size_t &size) {
592  // NOTE: This assumes the view is host-accessible.
593  // Wrap the view as rcps (this happens to preserve the reference counting, but that doesn't really matter here)
594  Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
595 
596  std::sort(view_rcp.rbegin(),view_rcp.rend());
597  }
598 
599 
600 
601 
617  template<class IT1, class IT2, class IT3>
618  void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2,
619  const IT3 &first3)
620  {
621  // Quicksort uses best-case N log N time whether or not the input
622  // data is sorted. However, the common case in Tpetra is that the
623  // input data are sorted, so we first check whether this is the
624  // case before reverting to Quicksort.
625  if(SortDetails::isAlreadySorted(first1, last1)){
626  return;
627  }
628  SortDetails::sh_sort3(first1, last1, first2, first2+(last1-first1), first3,
629  first3+(last1-first1));
630 
631 #ifdef HAVE_TPETRA_DEBUG
632  if(!SortDetails::isAlreadySorted(first1, last1)){
633  std::cout << " Trouble sort did not actually sort... !!!!!!" <<
634  std::endl;
635  return;
636  }
637 #endif
638  }
639 
683  template<class IT1, class IT2>
684  void
685  merge2 (IT1& indResultOut, IT2& valResultOut,
686  IT1 indBeg, IT1 indEnd,
687  IT2 valBeg, IT2 /* valEnd */)
688  {
689  if (indBeg == indEnd) {
690  indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
691  valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
692  }
693  else {
694  IT1 indResult = indBeg;
695  IT2 valResult = valBeg;
696  if (indBeg != indEnd) {
697  ++indBeg;
698  ++valBeg;
699  while (indBeg != indEnd) {
700  if (*indResult == *indBeg) { // adjacent column indices equal
701  *valResult += *valBeg; // merge entries by adding their values together
702  } else { // adjacent column indices not equal
703  *(++indResult) = *indBeg; // shift over the index
704  *(++valResult) = *valBeg; // shift over the value
705  }
706  ++indBeg;
707  ++valBeg;
708  }
709  ++indResult; // exclusive end of merged result
710  ++valResult; // exclusive end of merged result
711 
712  // mfh 24 Feb 2014: Setting these is technically correct, but
713  // since the resulting variables aren't used after this point,
714  // it may result in a build error.
715  //
716  // indEnd = indResult;
717  // valEnd = valResult;
718  }
719  indResultOut = indResult;
720  valResultOut = valResult;
721  }
722  }
723 
772  template<class IT1, class IT2, class BinaryFunction>
773  void
774  merge2 (IT1& indResultOut, IT2& valResultOut,
775  IT1 indBeg, IT1 indEnd,
776  IT2 valBeg, IT2 valEnd,
777  BinaryFunction f)
778  {
779  if (indBeg == indEnd) {
780  indResultOut = indBeg; // It's allowed for indResultOut to alias indEnd
781  valResultOut = valBeg; // It's allowed for valResultOut to alias valEnd
782  }
783  else {
784  IT1 indResult = indBeg;
785  IT2 valResult = valBeg;
786  if (indBeg != indEnd) {
787  ++indBeg;
788  ++valBeg;
789  while (indBeg != indEnd) {
790  if (*indResult == *indBeg) { // adjacent column indices equal
791  *valResult = f (*valResult, *valBeg); // merge entries via values
792  } else { // adjacent column indices not equal
793  *(++indResult) = *indBeg; // shift over the index
794  *(++valResult) = *valBeg; // shift over the value
795  }
796  ++indBeg;
797  ++valBeg;
798  }
799  ++indResult; // exclusive end of merged result
800  ++valResult; // exclusive end of merged result
801  indEnd = indResult;
802  valEnd = valResult;
803  }
804  indResultOut = indResult;
805  valResultOut = valResult;
806  }
807  }
808 
809 
838  template<class KeyInputIterType, class ValueInputIterType,
839  class KeyOutputIterType, class ValueOutputIterType,
840  class BinaryFunction>
841  void
842  keyValueMerge (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
843  ValueInputIterType valBeg1, ValueInputIterType valEnd1,
844  KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
845  ValueInputIterType valBeg2, ValueInputIterType valEnd2,
846  KeyOutputIterType keyOut, ValueOutputIterType valOut,
847  BinaryFunction f)
848  {
849  while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
850  if (*keyBeg1 < *keyBeg2) {
851  *keyOut++ = *keyBeg1++;
852  *valOut++ = *valBeg1++;
853  } else if (*keyBeg1 > *keyBeg2) {
854  *keyOut++ = *keyBeg2++;
855  *valOut++ = *valBeg2++;
856  } else { // *keyBeg1 == *keyBeg2
857  *keyOut++ = *keyBeg1;
858  *valOut++ = f (*valBeg1, *valBeg2);
859  ++keyBeg1;
860  ++valBeg1;
861  ++keyBeg2;
862  ++valBeg2;
863  }
864  }
865  // At most one of the two sequences will be nonempty.
866  std::copy (keyBeg1, keyEnd1, keyOut);
867  std::copy (valBeg1, valEnd1, valOut);
868  std::copy (keyBeg2, keyEnd2, keyOut);
869  std::copy (valBeg2, valEnd2, valOut);
870  }
871 
872  template<class KeyInputIterType>
873  size_t
874  keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
875  KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
876  {
877  size_t count = 0;
878  while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
879  if (*keyBeg1 < *keyBeg2) {
880  ++keyBeg1;
881  } else if (*keyBeg1 > *keyBeg2) {
882  ++keyBeg2;
883  } else { // *keyBeg1 == *keyBeg2
884  ++keyBeg1;
885  ++keyBeg2;
886  }
887  ++count;
888  }
889  // At most one of the two sequences will be nonempty.
890  count += static_cast<size_t> (keyEnd1 - keyBeg1) +
891  static_cast<size_t> (keyEnd2 - keyBeg2);
892  return count;
893  }
894 
895  namespace Details {
915  bool
916  congruent (const Teuchos::Comm<int>& comm1,
917  const Teuchos::Comm<int>& comm2);
918 
928  template<class DualViewType>
929  Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
930  getArrayViewFromDualView (const DualViewType& x)
931  {
932  static_assert (static_cast<int> (DualViewType::t_dev::rank) == 1,
933  "The input DualView must have rank 1.");
934  TEUCHOS_TEST_FOR_EXCEPTION
935  (x.need_sync_host (), std::logic_error, "The "
936  "input Kokkos::DualView was most recently modified on device, but this "
937  "function needs the host view of the data to be the most recently "
938  "modified.");
939 
940  auto x_host = x.view_host ();
941  typedef typename DualViewType::t_dev::value_type value_type;
942  // mfh 15 Jan 2019: In debug mode, Teuchos::ArrayView's
943  // constructor throws if the pointer is nonnull but the length
944  // is nonpositive.
945  const auto len = x_host.extent (0);
946  return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () : nullptr,
947  len);
948  }
949 
966  template<class T, class DT>
967  Kokkos::DualView<T*, DT>
968  getDualViewCopyFromArrayView (const Teuchos::ArrayView<const T>& x_av,
969  const char label[],
970  const bool leaveOnHost)
971  {
972  using Kokkos::MemoryUnmanaged;
973  typedef typename DT::memory_space DMS;
974  typedef typename DT::execution_space execution_space;
975  typedef Kokkos::HostSpace HMS;
976 
977  const size_t len = static_cast<size_t> (x_av.size ());
978  Kokkos::View<const T*, HMS, MemoryUnmanaged> x_in (x_av.getRawPtr (), len);
979  Kokkos::DualView<T*, DT> x_out (label, len);
980  if (leaveOnHost) {
981  x_out.modify_host ();
982  // DEEP_COPY REVIEW - NOT TESTED FOR CUDA BUILD
983  Kokkos::deep_copy (x_out.view_host (), x_in);
984  }
985  else {
986  x_out.template modify<DMS> ();
987  // DEEP_COPY REVIEW - HOST-TO-DEVICE
988  Kokkos::deep_copy (execution_space(), x_out.template view<DMS> (), x_in);
989  }
990  return x_out;
991  }
992 
1000  template<class DualViewType>
1001  std::string dualViewStatusToString (const DualViewType& dv, const char name[])
1002  {
1003  const auto host = dv.need_sync_device();
1004  const auto dev = dv.need_sync_host();
1005 
1006  std::ostringstream os;
1007  os << name << ": {size: " << dv.extent (0)
1008  << ", sync: {host: " << host << ", dev: " << dev << "}";
1009  return os.str ();
1010  }
1011 
1016  template<class ArrayType>
1017  void
1018  verbosePrintArray(std::ostream& out,
1019  const ArrayType& x,
1020  const char name[],
1021  const size_t maxNumToPrint)
1022  {
1023  out << name << ": [";
1024 
1025  const size_t numEnt(x.size());
1026  if (maxNumToPrint == 0) {
1027  if (numEnt != 0) {
1028  out << "...";
1029  }
1030  }
1031  else {
1032  const size_t numToPrint = numEnt > maxNumToPrint ?
1033  maxNumToPrint : numEnt;
1034  size_t k = 0;
1035  for ( ; k < numToPrint; ++k) {
1036  out << x[k];
1037  if (k + size_t(1) < numToPrint) {
1038  out << ", ";
1039  }
1040  }
1041  if (k < numEnt) {
1042  out << ", ...";
1043  }
1044  }
1045  out << "]";
1046  }
1047 
1051  std::unique_ptr<std::string>
1052  createPrefix(const int myRank,
1053  const char prefix[]);
1054 
1062  std::unique_ptr<std::string>
1063  createPrefix(const Teuchos::Comm<int>* comm,
1064  const char functionName[]);
1065 
1072  std::unique_ptr<std::string>
1073  createPrefix(const Teuchos::Comm<int>*,
1074  const char className[],
1075  const char methodName[]);
1076 
1077  } // namespace Details
1078 } // namespace Tpetra
1079 
1080 #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:64
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)
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...
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.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
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.