42 #ifndef TPETRA_UTIL_HPP
43 #define TPETRA_UTIL_HPP
54 #include "Tpetra_ConfigDefs.hpp"
55 #include "Kokkos_DualView.hpp"
56 #include "Teuchos_Assert.hpp"
57 #include "Teuchos_CommHelpers.hpp"
58 #include "Teuchos_OrdinalTraits.hpp"
59 #include "Teuchos_TypeNameTraits.hpp"
60 #include "Teuchos_Utils.hpp"
65 #if defined(HAVE_TPETRA_THROW_EFFICIENCY_WARNINGS) || defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
66 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg) \
101 const bool tpetraEfficiencyWarningTest = (throw_exception_test); \
102 if (tpetraEfficiencyWarningTest) { \
103 std::ostringstream errStream; \
104 errStream << Teuchos::typeName(*this) << ":" << std::endl; \
105 errStream << "Efficiency warning: " << #throw_exception_test << std::endl; \
107 std::string err = errStream.str(); \
108 if (TPETRA_PRINTS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest) { \
109 std::cerr << err << std::endl; \
111 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_EFFICIENCY_WARNINGS && tpetraEfficiencyWarningTest, Exception, err); \
115 #define TPETRA_EFFICIENCY_WARNING(throw_exception_test,Exception,msg)
152 #if defined(HAVE_TPETRA_THROW_ABUSE_WARNINGS) || defined(HAVE_TPETRA_PRINT_ABUSE_WARNINGS)
153 #define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg) \
156 std::ostringstream errStream; \
157 errStream << Teuchos::typeName(*this) << msg; \
158 std::string err = errStream.str(); \
159 if (TPETRA_PRINTS_ABUSE_WARNINGS && (throw_exception_test)) { \
160 std::cerr << err << std::endl; \
162 TEUCHOS_TEST_FOR_EXCEPTION(TPETRA_THROWS_ABUSE_WARNINGS && (throw_exception_test), Exception, err); \
165 #define TPETRA_ABUSE_WARNING(throw_exception_test,Exception,msg)
198 #define SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
200 using Teuchos::outArg; \
201 const int lcl_throw_exception = (throw_exception_test) ? Teuchos::rank(comm)+1 : 0; \
203 Teuchos::reduceAll(comm,Teuchos::REDUCE_MAX,lcl_throw_exception,outArg(gbl_throw)); \
204 TEUCHOS_TEST_FOR_EXCEPTION(gbl_throw,Exception, \
205 msg << " Failure on at least one process, including process " << gbl_throw-1 << "." << std::endl); \
208 #ifdef HAVE_TEUCHOS_DEBUG
209 #define SWITCHED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
212 SHARED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm); \
215 #define SWITCHED_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg,comm) \
218 TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg); \
235 template<
typename MapType,
typename KeyArgType,
typename ValueArgType>
237 const KeyArgType & k,
238 const ValueArgType & v)
240 typename MapType::iterator lb = m.lower_bound(k);
241 if(lb != m.end() && !(m.key_comp()(k, lb->first))) {
246 typedef typename MapType::value_type MVT;
247 return(m.insert(lb, MVT(k, v)));
258 namespace SortDetails {
269 bool isAlreadySorted(
const IT1& first,
const IT1& last){
270 typedef typename std::iterator_traits<IT1>::difference_type DT;
271 DT myit = Teuchos::OrdinalTraits<DT>::one();
272 const DT sz = last - first;
273 for(;myit < sz; ++myit){
274 if(first[myit] < first[myit-1]){
291 IT getPivot(
const IT& first,
const IT& last){
292 IT pivot(first+(last-first)/2);
293 if(*first<=*pivot && *(last-1)<=*first) pivot=first;
294 else if(*(last-1)<=*pivot && *first<= *(last-1)) pivot = last-1;
312 template<
class IT1,
class IT2>
320 typename std::iterator_traits<IT1>::value_type piv(*pivot);
321 std::swap(*pivot, *(last1-1));
322 std::swap(first2[(pivot-first1)], *(last2-1));
324 for(IT1 it=first1; it!=last1-1; ++it){
326 std::swap(*store1, *it);
327 std::swap(first2[(store1-first1)], first2[(it-first1)]);
331 std::swap(*(last1-1), *store1);
332 std::swap(*(last2-1), first2[store1-first1]);
352 template<
class IT1,
class IT2,
class IT3>
362 typename std::iterator_traits<IT1>::value_type piv(*pivot);
363 std::swap(*pivot, *(last1-1));
364 std::swap(first2[(pivot-first1)], *(last2-1));
365 std::swap(first3[(pivot-first1)], *(last3-1));
367 for(IT1 it=first1; it!=last1-1; ++it){
369 std::swap(*store1, *it);
370 std::swap(first2[(store1-first1)], first2[(it-first1)]);
371 std::swap(first3[(store1-first1)], first3[(it-first1)]);
375 std::swap(*(last1-1), *store1);
376 std::swap(*(last2-1), first2[store1-first1]);
377 std::swap(*(last3-1), first3[store1-first1]);
391 template<
class IT1,
class IT2>
398 typedef typename std::iterator_traits<IT1>::difference_type DT;
399 DT DT1 = Teuchos::OrdinalTraits<DT>::one();
400 if(last1-first1 > DT1){
401 IT1 pivot = getPivot(first1, last1);
402 pivot = partition2(first1, last1, first2, last2, pivot);
403 quicksort2(first1, pivot, first2, first2+(pivot-first1));
404 quicksort2(pivot+1, last1, first2+(pivot-first1)+1, last2);
420 template<
class IT1,
class IT2,
class IT3>
429 typedef typename std::iterator_traits<IT1>::difference_type DT;
430 DT DT1 = Teuchos::OrdinalTraits<DT>::one();
431 if(last1-first1 > DT1){
432 IT1 pivot = getPivot(first1, last1);
433 pivot = partition3(first1, last1, first2, last2, first3, last3, pivot);
434 quicksort3(first1, pivot, first2, first2+(pivot-first1), first3, first3+(pivot-first1));
435 quicksort3(pivot+1, last1, first2+(pivot-first1)+1, last2, first3+(pivot-first1)+1, last3);
445 template<
class IT1,
class IT2,
class IT3>
454 typedef typename std::iterator_traits<IT1>::difference_type DT;
455 DT n = last1 - first1;
457 DT z = Teuchos::OrdinalTraits<DT>::zero();
461 for (DT j = 0; j < max; j++)
463 for (DT k = j; k >= 0; k-=m)
465 if (first1[k+m] >= first1[k])
467 std::swap(first1[k+m], first1[k]);
468 std::swap(first2[k+m], first2[k]);
469 std::swap(first3[k+m], first3[k]);
482 template<
class IT1,
class IT2>
489 typedef typename std::iterator_traits<IT1>::difference_type DT;
490 DT n = last1 - first1;
492 DT z = Teuchos::OrdinalTraits<DT>::zero();
496 for (DT j = 0; j < max; j++)
498 for (DT k = j; k >= 0; k-=m)
500 if (first1[k+m] >= first1[k])
502 std::swap(first1[k+m], first1[k]);
503 std::swap(first2[k+m], first2[k]);
531 template<
class IT1,
class IT2>
532 void sort2(
const IT1 &first1,
const IT1 &last1,
const IT2 &first2) {
537 if(SortDetails::isAlreadySorted(first1, last1)){
540 SortDetails::sh_sort2(first1, last1, first2, first2+(last1-first1));
541 #ifdef HAVE_TPETRA_DEBUG
542 if(!SortDetails::isAlreadySorted(first1, last1)){
543 std::cout <<
"Trouble: sort() did not sort !!" << std::endl;
565 template<
class IT1,
class IT2,
class IT3>
566 void sort3(
const IT1 &first1,
const IT1 &last1,
const IT2 &first2,
573 if(SortDetails::isAlreadySorted(first1, last1)){
576 SortDetails::sh_sort3(first1, last1, first2, first2+(last1-first1), first3,
577 first3+(last1-first1));
579 #ifdef HAVE_TPETRA_DEBUG
580 if(!SortDetails::isAlreadySorted(first1, last1)){
581 std::cout <<
" Trouble sort did not actually sort... !!!!!!" <<
631 template<
class IT1,
class IT2>
633 merge2 (IT1& indResultOut, IT2& valResultOut,
634 IT1 indBeg, IT1 indEnd,
637 if (indBeg == indEnd) {
638 indResultOut = indBeg;
639 valResultOut = valBeg;
642 IT1 indResult = indBeg;
643 IT2 valResult = valBeg;
644 if (indBeg != indEnd) {
647 while (indBeg != indEnd) {
648 if (*indResult == *indBeg) {
649 *valResult += *valBeg;
651 *(++indResult) = *indBeg;
652 *(++valResult) = *valBeg;
667 indResultOut = indResult;
668 valResultOut = valResult;
720 template<
class IT1,
class IT2,
class BinaryFunction>
722 merge2 (IT1& indResultOut, IT2& valResultOut,
723 IT1 indBeg, IT1 indEnd,
724 IT2 valBeg, IT2 valEnd,
727 if (indBeg == indEnd) {
728 indResultOut = indBeg;
729 valResultOut = valBeg;
732 IT1 indResult = indBeg;
733 IT2 valResult = valBeg;
734 if (indBeg != indEnd) {
737 while (indBeg != indEnd) {
738 if (*indResult == *indBeg) {
739 *valResult = f (*valResult, *valBeg);
741 *(++indResult) = *indBeg;
742 *(++valResult) = *valBeg;
752 indResultOut = indResult;
753 valResultOut = valResult;
786 template<
class KeyInputIterType,
class ValueInputIterType,
787 class KeyOutputIterType,
class ValueOutputIterType,
788 class BinaryFunction>
791 ValueInputIterType valBeg1, ValueInputIterType valEnd1,
792 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2,
793 ValueInputIterType valBeg2, ValueInputIterType valEnd2,
794 KeyOutputIterType keyOut, ValueOutputIterType valOut,
797 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
798 if (*keyBeg1 < *keyBeg2) {
799 *keyOut++ = *keyBeg1++;
800 *valOut++ = *valBeg1++;
801 }
else if (*keyBeg1 > *keyBeg2) {
802 *keyOut++ = *keyBeg2++;
803 *valOut++ = *valBeg2++;
805 *keyOut++ = *keyBeg1;
806 *valOut++ = f (*valBeg1, *valBeg2);
814 std::copy (keyBeg1, keyEnd1, keyOut);
815 std::copy (valBeg1, valEnd1, valOut);
816 std::copy (keyBeg2, keyEnd2, keyOut);
817 std::copy (valBeg2, valEnd2, valOut);
820 template<
class KeyInputIterType>
822 keyMergeCount (KeyInputIterType keyBeg1, KeyInputIterType keyEnd1,
823 KeyInputIterType keyBeg2, KeyInputIterType keyEnd2)
826 while (keyBeg1 != keyEnd1 && keyBeg2 != keyEnd2) {
827 if (*keyBeg1 < *keyBeg2) {
829 }
else if (*keyBeg1 > *keyBeg2) {
838 count +=
static_cast<size_t> (keyEnd1 - keyBeg1) +
839 static_cast<size_t> (keyEnd2 - keyBeg2);
864 congruent (
const Teuchos::Comm<int>& comm1,
865 const Teuchos::Comm<int>& comm2);
876 template<
class DualViewType>
877 Teuchos::ArrayView<typename DualViewType::t_dev::value_type>
880 static_assert (static_cast<int> (DualViewType::t_dev::rank) == 1,
881 "The input DualView must have rank 1.");
882 TEUCHOS_TEST_FOR_EXCEPTION
883 (x.need_sync_host (), std::logic_error,
"The "
884 "input Kokkos::DualView was most recently modified on device, but this "
885 "function needs the host view of the data to be the most recently "
888 auto x_host = x.view_host ();
889 typedef typename DualViewType::t_dev::value_type value_type;
893 const auto len = x_host.extent (0);
894 return Teuchos::ArrayView<value_type> (len != 0 ? x_host.data () :
nullptr,
914 template<
class T,
class DT>
915 Kokkos::DualView<T*, DT>
918 const bool leaveOnHost)
920 using Kokkos::MemoryUnmanaged;
921 typedef typename DT::memory_space DMS;
922 typedef Kokkos::HostSpace HMS;
924 const size_t len =
static_cast<size_t> (x_av.size ());
925 Kokkos::View<const T*, HMS, MemoryUnmanaged> x_in (x_av.getRawPtr (), len);
926 Kokkos::DualView<T*, DT> x_out (label, len);
928 x_out.modify_host ();
932 x_out.template modify<DMS> ();
945 template<
class DualViewType>
948 const auto host = dv.need_sync_device();
949 const auto dev = dv.need_sync_host();
951 std::ostringstream os;
952 os << name <<
": {size: " << dv.extent (0)
953 <<
", sync: {host: " << host <<
", dev: " << dev <<
"}";
960 #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)
Sort the first array, and apply the same permutation to the second and third arrays.
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.