10 #ifndef TPETRA_UTIL_HPP
11 #define TPETRA_UTIL_HPP
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"
37 #if defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
38 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test,msg) \
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; \
70 std::string err = errStream.str(); \
71 if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
72 std::cerr << err << std::endl; \
77 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test,msg)
105 #if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
106 #define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg) \
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; \
115 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
118 #define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg)
151 #define SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
153 using Teuchos::outArg; \
154 const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm)+1 : 0; \
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); \
174 template<
typename MapType,
typename KeyArgType,
typename ValueArgType>
176 const KeyArgType & k,
177 const ValueArgType & v)
179 typename MapType::iterator lb = m.lower_bound(k);
180 if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
185 typedef typename MapType::value_type MVT;
186 return(m.insert(lb, MVT(k, v)));
197 namespace SortDetails {
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]){
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;
251 template<
class IT1,
class IT2>
259 typename std::iterator_traits<IT1>::value_type piv(*pivot);
260 std::swap(*pivot, *(last1-1));
261 std::swap(first2[(pivot-first1)], *(last2-1));
263 for(IT1 it=first1; it!=last1-1; ++it){
265 std::swap(*store1, *it);
266 std::swap(first2[(store1-first1)], first2[(it-first1)]);
270 std::swap(*(last1-1), *store1);
271 std::swap(*(last2-1), first2[store1-first1]);
291 template<
class IT1,
class IT2,
class IT3>
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));
306 for(IT1 it=first1; it!=last1-1; ++it){
308 std::swap(*store1, *it);
309 std::swap(first2[(store1-first1)], first2[(it-first1)]);
310 std::swap(first3[(store1-first1)], first3[(it-first1)]);
314 std::swap(*(last1-1), *store1);
315 std::swap(*(last2-1), first2[store1-first1]);
316 std::swap(*(last3-1), first3[store1-first1]);
330 template<
class IT1,
class IT2>
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);
359 template<
class IT1,
class IT2,
class IT3>
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);
384 template<
class IT1,
class IT2,
class IT3>
393 typedef typename std::iterator_traits<IT1>::difference_type DT;
394 DT n = last1 - first1;
396 DT z = Teuchos::OrdinalTraits<DT>::zero();
400 for (DT j = 0; j < max; j++)
402 for (DT k = j; k >= 0; k-=m)
404 if (first1[k+m] >= first1[k])
406 std::swap(first1[k+m], first1[k]);
407 std::swap(first2[k+m], first2[k]);
408 std::swap(first3[k+m], first3[k]);
421 template<
class IT1,
class IT2>
428 typedef typename std::iterator_traits<IT1>::difference_type DT;
429 DT n = last1 - first1;
431 DT z = Teuchos::OrdinalTraits<DT>::zero();
435 for (DT j = 0; j < max; j++)
437 for (DT k = j; k >= 0; k-=m)
439 if (first1[k+m] >= first1[k])
441 std::swap(first1[k+m], first1[k]);
442 std::swap(first2[k+m], first2[k]);
453 template<
typename IT1>
454 std::vector<typename std::iterator_traits<IT1>::difference_type> sort_indexes(IT1 first, IT1 last) {
456 typedef typename std::iterator_traits<IT1>::difference_type DT;
458 DT length = last - first;
459 std::vector<DT> idx(length);
460 std::iota(idx.begin(), idx.end(), 0);
462 std::stable_sort(idx.begin(), idx.end(),
463 [&first](
size_t i1,
size_t i2) {
return first[i1] < first[i2];});
471 template<
typename IT1,
typename IT2>
478 typedef typename std::iterator_traits<IT1>::difference_type DT;
479 typedef typename std::iterator_traits<IT1>::value_type T;
483 Kokkos::View<T*, Kokkos::HostSpace> tmp(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"tmp"), n);
485 Kokkos::parallel_for(
"apply_permutation_1",
486 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
488 tmp(j) = first[indices[j]];
490 Kokkos::parallel_for(
"apply_permutation_2",
491 Kokkos::RangePolicy<Kokkos::DefaultHostExecutionSpace>(0, n),
503 template<
class IT1,
class IT2>
504 void std_sort2(
const IT1& first1,
509 auto indices = sort_indexes(first1, last1);
510 apply_permutation(first1, last1, indices);
511 apply_permutation(first2, last2, indices);
520 template<
class IT1,
class IT2,
class IT3>
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);
556 template<
class IT1,
class IT2>
557 void sort2(
const IT1 &first1,
const IT1 &last1,
const IT2 &first2,
const bool stableSort=
false) {
562 if(SortDetails::isAlreadySorted(first1, last1)){
566 SortDetails::std_sort2(first1, last1, first2, first2+(last1-first1));
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;
594 template<
class View1,
class View2>
595 void sort2(View1 &view1,
const size_t &size, View2 &view2) {
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);
602 sort2(view1_rcp.begin(),view1_rcp.end(),view2_rcp.begin());
614 void sort(View &view,
const size_t &size) {
618 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
620 std::sort(view_rcp.begin(),view_rcp.end());
635 Teuchos::ArrayRCP<typename View::non_const_value_type> view_rcp = Kokkos::Compat::persistingView(view, 0, size);
637 std::sort(view_rcp.rbegin(),view_rcp.rend());
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)
666 if(SortDetails::isAlreadySorted(first1, last1)){
670 SortDetails::std_sort3(first1, last1, first2, first2+(last1-first1), first3,
671 first3+(last1-first1));
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... !!!!!!" <<
727 template<
class IT1,
class IT2>
729 merge2 (IT1& indResultOut, IT2& valResultOut,
730 IT1 indBeg, IT1 indEnd,
733 if (indBeg == indEnd) {
734 indResultOut = indBeg;
735 valResultOut = valBeg;
738 IT1 indResult = indBeg;
739 IT2 valResult = valBeg;
740 if (indBeg != indEnd) {
743 while (indBeg != indEnd) {
744 if (*indResult == *indBeg) {
745 *valResult += *valBeg;
747 *(++indResult) = *indBeg;
748 *(++valResult) = *valBeg;
763 indResultOut = indResult;
764 valResultOut = valResult;
816 template<
class IT1,
class IT2,
class BinaryFunction>
818 merge2 (IT1& indResultOut, IT2& valResultOut,
819 IT1 indBeg, IT1 indEnd,
820 IT2 valBeg, IT2 valEnd,
823 if (indBeg == indEnd) {
824 indResultOut = indBeg;
825 valResultOut = valBeg;
828 IT1 indResult = indBeg;
829 IT2 valResult = valBeg;
830 if (indBeg != indEnd) {
833 while (indBeg != indEnd) {
834 if (*indResult == *indBeg) {
835 *valResult = f (*valResult, *valBeg);
837 *(++indResult) = *indBeg;
838 *(++valResult) = *valBeg;
848 indResultOut = indResult;
849 valResultOut = valResult;
882 template<
class KeyInputIterType,
class ValueInputIterType,
883 class KeyOutputIterType,
class ValueOutputIterType,
884 class BinaryFunction>
887 ValueInputIterType valBeg1, ValueInputIterType valEnd1,
888 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
889 ValueInputIterType valBeg2, ValueInputIterType valEnd2,
890 KeyOutputIterType keyOut, ValueOutputIterType valOut,
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++;
901 *keyOut++ = *keyBeg1;
902 *valOut++ = f (*valBeg1, *valBeg2);
910 std::copy (keyBeg1, keyEnd1, keyOut);
911 std::copy (valBeg1, valEnd1, valOut);
912 std::copy (keyBeg2, keyEnd2, keyOut);
913 std::copy (valBeg2, valEnd2, valOut);
916 template<
class KeyInputIterType>
918 keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
919 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
922 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
923 if (*keyBeg1 < *keyBeg2) {
925 }
else if (*keyBeg1 > *keyBeg2) {
934 count +=
static_cast<size_t> (keyEnd1 - keyBeg1) +
935 static_cast<size_t> (keyEnd2 - keyBeg2);
960 congruent (
const Teuchos::Comm<int>& comm1,
961 const Teuchos::Comm<int>& comm2);
972 template<
class DualViewType>
973 Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
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 "
984 auto x_host = x.view_host ();
985 typedef typename DualViewType::t_dev::value_type value_type;
989 const auto len = x_host.extent (0);
990 return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () :
nullptr,
1010 template<
class T,
class DT>
1011 Kokkos::DualView<T*, DT>
1014 const bool leaveOnHost)
1016 using Kokkos::MemoryUnmanaged;
1017 typedef typename DT::memory_space DMS;
1018 typedef typename DT::execution_space execution_space;
1019 typedef Kokkos::HostSpace HMS;
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);
1025 x_out.modify_host ();
1030 x_out.template modify<DMS> ();
1044 template<
class DualViewType>
1047 const auto host = dv.need_sync_device();
1048 const auto dev = dv.need_sync_host();
1050 std::ostringstream os;
1051 os << name <<
": {size: " << dv.extent (0)
1052 <<
", sync: {host: " << host <<
", dev: " << dev <<
"}";
1060 template<
class ArrayType>
1065 const size_t maxNumToPrint)
1067 out << name <<
": [";
1069 const size_t numEnt(x.size());
1070 if (maxNumToPrint == 0) {
1076 const size_t numToPrint = numEnt > maxNumToPrint ?
1077 maxNumToPrint : numEnt;
1079 for ( ; k < numToPrint; ++k) {
1081 if (k +
size_t(1) < numToPrint) {
1095 std::unique_ptr<std::string>
1097 const char prefix[]);
1106 std::unique_ptr<std::string>
1108 const char functionName[]);
1116 std::unique_ptr<std::string>
1118 const char className[],
1119 const char methodName[]);
1124 #endif // TPETRA_UTIL_HPP
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
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.