42 #ifndef TPETRA_MULTIVECTOR_DEF_HPP
43 #define TPETRA_MULTIVECTOR_DEF_HPP
54 #include "Tpetra_Vector.hpp"
58 #include "Tpetra_Details_gathervPrint.hpp"
61 #include "Tpetra_Details_normImpl.hpp"
65 #ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
66 # include "Teuchos_SerialDenseMatrix.hpp"
67 #endif // HAVE_TPETRACORE_TEUCHOSNUMERICS
68 #include "Tpetra_KokkosRefactor_Details_MultiVectorDistObjectKernels.hpp"
69 #include "KokkosCompat_View.hpp"
70 #include "KokkosBlas.hpp"
71 #include "KokkosKernels_Utils.hpp"
72 #include "Kokkos_Random.hpp"
73 #include "Kokkos_ArithTraits.hpp"
77 #ifdef HAVE_TPETRA_INST_FLOAT128
80 template<
class Generator>
81 struct rand<Generator, __float128> {
82 static KOKKOS_INLINE_FUNCTION __float128 max ()
84 return static_cast<__float128
> (1.0);
86 static KOKKOS_INLINE_FUNCTION __float128
91 const __float128 scalingFactor =
92 static_cast<__float128
> (std::numeric_limits<double>::min ()) /
93 static_cast<__float128> (2.0);
94 const __float128 higherOrderTerm =
static_cast<__float128
> (gen.drand ());
95 const __float128 lowerOrderTerm =
96 static_cast<__float128
> (gen.drand ()) * scalingFactor;
97 return higherOrderTerm + lowerOrderTerm;
99 static KOKKOS_INLINE_FUNCTION __float128
100 draw (Generator& gen,
const __float128& range)
103 const __float128 scalingFactor =
104 static_cast<__float128
> (std::numeric_limits<double>::min ()) /
105 static_cast<__float128> (2.0);
106 const __float128 higherOrderTerm =
107 static_cast<__float128
> (gen.drand (range));
108 const __float128 lowerOrderTerm =
109 static_cast<__float128
> (gen.drand (range)) * scalingFactor;
110 return higherOrderTerm + lowerOrderTerm;
112 static KOKKOS_INLINE_FUNCTION __float128
113 draw (Generator& gen,
const __float128& start,
const __float128& end)
116 const __float128 scalingFactor =
117 static_cast<__float128
> (std::numeric_limits<double>::min ()) /
118 static_cast<__float128> (2.0);
119 const __float128 higherOrderTerm =
120 static_cast<__float128
> (gen.drand (start, end));
121 const __float128 lowerOrderTerm =
122 static_cast<__float128
> (gen.drand (start, end)) * scalingFactor;
123 return higherOrderTerm + lowerOrderTerm;
127 #endif // HAVE_TPETRA_INST_FLOAT128
145 template<
class ST,
class LO,
class GO,
class NT>
147 allocDualView (
const size_t lclNumRows,
148 const size_t numCols,
149 const bool zeroOut =
true,
150 const bool allowPadding =
false)
152 using ::Tpetra::Details::Behavior;
153 using Kokkos::AllowPadding;
154 using Kokkos::view_alloc;
155 using Kokkos::WithoutInitializing;
157 typedef typename dual_view_type::t_dev dev_view_type;
162 const std::string label (
"MV::DualView");
163 const bool debug = Behavior::debug ();
173 dev_view_type d_view;
176 d_view = dev_view_type (view_alloc (label, AllowPadding),
177 lclNumRows, numCols);
180 d_view = dev_view_type (view_alloc (label),
181 lclNumRows, numCols);
186 d_view = dev_view_type (view_alloc (label,
189 lclNumRows, numCols);
192 d_view = dev_view_type (view_alloc (label, WithoutInitializing),
193 lclNumRows, numCols);
204 const ST nan = Kokkos::Details::ArithTraits<ST>::nan ();
205 KokkosBlas::fill (d_view, nan);
209 TEUCHOS_TEST_FOR_EXCEPTION
210 (static_cast<size_t> (d_view.extent (0)) != lclNumRows ||
211 static_cast<size_t> (d_view.extent (1)) != numCols, std::logic_error,
212 "allocDualView: d_view's dimensions actual dimensions do not match "
213 "requested dimensions. d_view is " << d_view.extent (0) <<
" x " <<
214 d_view.extent (1) <<
"; requested " << lclNumRows <<
" x " << numCols
215 <<
". Please report this bug to the Tpetra developers.");
218 dual_view_type dv (d_view, Kokkos::create_mirror_view (d_view));
232 template<
class T,
class ExecSpace>
233 struct MakeUnmanagedView {
246 typedef typename Kokkos::Impl::if_c<
247 Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<
248 typename ExecSpace::memory_space,
249 Kokkos::HostSpace>::value,
250 typename ExecSpace::device_type,
251 typename Kokkos::DualView<T*, ExecSpace>::host_mirror_space>::type host_exec_space;
252 typedef Kokkos::LayoutLeft array_layout;
253 typedef Kokkos::View<T*, array_layout, host_exec_space,
254 Kokkos::MemoryUnmanaged> view_type;
256 static view_type getView (
const Teuchos::ArrayView<T>& x_in)
258 const size_t numEnt =
static_cast<size_t> (x_in.size ());
262 return view_type (x_in.getRawPtr (), numEnt);
270 template<
class DualViewType>
272 takeSubview (
const DualViewType& X,
273 const Kokkos::Impl::ALL_t&,
274 const std::pair<size_t, size_t>& colRng)
276 if (X.extent (0) == 0 && X.extent (1) != 0) {
277 return DualViewType (
"MV::DualView", 0, colRng.second - colRng.first);
280 return subview (X, Kokkos::ALL (), colRng);
287 template<
class DualViewType>
289 takeSubview (
const DualViewType& X,
290 const std::pair<size_t, size_t>& rowRng,
291 const std::pair<size_t, size_t>& colRng)
293 if (X.extent (0) == 0 && X.extent (1) != 0) {
294 return DualViewType (
"MV::DualView", 0, colRng.second - colRng.first);
297 return subview (X, rowRng, colRng);
301 template<
class DualViewType>
303 getDualViewStride (
const DualViewType& dv)
307 const size_t LDA = dv.d_view.stride (1);
308 const size_t numRows = dv.extent (0);
311 return (numRows == 0) ? size_t (1) : numRows;
318 template<
class ViewType>
320 getViewStride (
const ViewType& view)
322 const size_t LDA = view.stride (1);
323 const size_t numRows = view.extent (0);
326 return (numRows == 0) ? size_t (1) : numRows;
333 template <
class SC,
class LO,
class GO,
class NT>
335 multiVectorRunNormOnHost (const ::Tpetra::MultiVector<SC, LO, GO, NT>& X)
337 if (! X.need_sync_device ()) {
341 constexpr
size_t localLengthThreshold = 10000;
342 return X.getLocalLength () <= localLengthThreshold;
346 template <
class SC,
class LO,
class GO,
class NT>
348 multiVectorNormImpl (typename ::Tpetra::MultiVector<SC, LO, GO, NT>::mag_type norms[],
350 const ::Tpetra::Details::EWhichNorm whichNorm)
352 using ::Tpetra::Details::normImpl;
354 using val_type =
typename MV::impl_scalar_type;
355 using mag_type =
typename MV::mag_type;
356 using dual_view_type =
typename MV::dual_view_type;
359 auto comm = map.is_null () ?
nullptr : map->getComm ().getRawPtr ();
360 auto whichVecs = getMultiVectorWhichVectors (X);
364 const bool runOnHost = multiVectorRunNormOnHost (X);
366 using view_type =
typename dual_view_type::t_host;
367 using array_layout =
typename view_type::array_layout;
368 using device_type =
typename view_type::device_type;
374 normImpl<val_type, array_layout, device_type,
375 mag_type> (norms, X_lcl, whichNorm, whichVecs,
376 isConstantStride, isDistributed, comm);
379 using view_type =
typename dual_view_type::t_dev;
380 using array_layout =
typename view_type::array_layout;
381 using device_type =
typename view_type::device_type;
387 normImpl<val_type, array_layout, device_type,
388 mag_type> (norms, X_lcl, whichNorm, whichVecs,
389 isConstantStride, isDistributed, comm);
397 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
399 MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
400 vectorIndexOutOfRange (
const size_t VectorIndex)
const {
401 return (VectorIndex < 1 && VectorIndex != 0) || VectorIndex >= getNumVectors();
404 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
410 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
413 const size_t numVecs,
414 const bool zeroOut) :
420 view_ = allocDualView<Scalar, LocalOrdinal, GlobalOrdinal, Node> (lclNumRows, numVecs, zeroOut);
424 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
427 const Teuchos::DataAccess copyOrView) :
429 view_ (source.view_),
430 origView_ (source.origView_),
431 whichVectors_ (source.whichVectors_)
434 const char tfecfFuncName[] =
"MultiVector(const MultiVector&, "
435 "const Teuchos::DataAccess): ";
439 if (copyOrView == Teuchos::Copy) {
443 this->
view_ = cpy.view_;
447 else if (copyOrView == Teuchos::View) {
450 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
451 true, std::invalid_argument,
"Second argument 'copyOrView' has an "
452 "invalid value " << copyOrView <<
". Valid values include "
453 "Teuchos::Copy = " << Teuchos::Copy <<
" and Teuchos::View = "
454 << Teuchos::View <<
".");
458 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
461 const dual_view_type& view) :
466 const char tfecfFuncName[] =
"MultiVector(Map,DualView): ";
468 const size_t lclNumRows_map = map->getNodeNumElements ();
469 const size_t lclNumRows_view = view.extent (0);
470 const size_t LDA = getDualViewStride (view);
472 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
473 (LDA < lclNumRows_map || lclNumRows_map != lclNumRows_view,
474 std::invalid_argument,
"Kokkos::DualView does not match Map. "
475 "map->getNodeNumElements() = " << lclNumRows_map
476 <<
", view.extent(0) = " << lclNumRows_view
477 <<
", and getStride() = " << LDA <<
".");
481 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
484 const typename dual_view_type::t_dev& d_view) :
487 using Teuchos::ArrayRCP;
489 const char tfecfFuncName[] =
"MultiVector(map,d_view): ";
493 const size_t LDA = getViewStride (d_view);
494 const size_t lclNumRows = map->getNodeNumElements ();
495 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
496 (LDA < lclNumRows, std::invalid_argument,
"Map does not match "
497 "Kokkos::View. map->getNodeNumElements() = " << lclNumRows
498 <<
", View's column stride = " << LDA
499 <<
", and View's extent(0) = " << d_view.extent (0) <<
".");
501 auto h_view = Kokkos::create_mirror_view (d_view);
510 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
513 const dual_view_type& view,
514 const dual_view_type& origView) :
519 const char tfecfFuncName[] =
"MultiVector(map,view,origView): ";
521 const size_t LDA = getDualViewStride (origView);
523 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
524 LDA < lclNumRows, std::invalid_argument,
"The input Kokkos::DualView's "
525 "column stride LDA = " << LDA <<
" < getLocalLength() = " << lclNumRows
526 <<
". This may also mean that the input origView's first dimension (number "
527 "of rows = " << origView.extent (0) <<
") does not not match the number "
528 "of entries in the Map on the calling process.");
532 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
535 const dual_view_type& view,
536 const Teuchos::ArrayView<const size_t>& whichVectors) :
540 whichVectors_ (whichVectors.begin (), whichVectors.end ())
543 using Kokkos::subview;
544 const char tfecfFuncName[] =
"MultiVector(map,view,whichVectors): ";
546 const size_t lclNumRows = map.is_null () ? size_t (0) :
547 map->getNodeNumElements ();
554 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
555 view.extent (1) != 0 &&
static_cast<size_t> (view.extent (0)) < lclNumRows,
556 std::invalid_argument,
"view.extent(0) = " << view.extent (0)
557 <<
" < map->getNodeNumElements() = " << lclNumRows <<
".");
558 if (whichVectors.size () != 0) {
559 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
560 view.extent (1) != 0 && view.extent (1) == 0,
561 std::invalid_argument,
"view.extent(1) = 0, but whichVectors.size()"
562 " = " << whichVectors.size () <<
" > 0.");
563 size_t maxColInd = 0;
564 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
565 for (size_type k = 0; k < whichVectors.size (); ++k) {
566 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
567 whichVectors[k] == Teuchos::OrdinalTraits<size_t>::invalid (),
568 std::invalid_argument,
"whichVectors[" << k <<
"] = "
569 "Teuchos::OrdinalTraits<size_t>::invalid().");
570 maxColInd = std::max (maxColInd, whichVectors[k]);
572 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
573 view.extent (1) != 0 &&
static_cast<size_t> (view.extent (1)) <= maxColInd,
574 std::invalid_argument,
"view.extent(1) = " << view.extent (1)
575 <<
" <= max(whichVectors) = " << maxColInd <<
".");
580 const size_t LDA = getDualViewStride (view);
581 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
582 (LDA < lclNumRows, std::invalid_argument,
583 "LDA = " << LDA <<
" < this->getLocalLength() = " << lclNumRows <<
".");
585 if (whichVectors.size () == 1) {
594 const std::pair<size_t, size_t> colRng (whichVectors[0],
595 whichVectors[0] + 1);
603 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
606 const dual_view_type& view,
607 const dual_view_type& origView,
608 const Teuchos::ArrayView<const size_t>& whichVectors) :
611 origView_ (origView),
612 whichVectors_ (whichVectors.begin (), whichVectors.end ())
615 using Kokkos::subview;
616 const char tfecfFuncName[] =
"MultiVector(map,view,origView,whichVectors): ";
625 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
626 view.extent (1) != 0 &&
static_cast<size_t> (view.extent (0)) < lclNumRows,
627 std::invalid_argument,
"view.extent(0) = " << view.extent (0)
628 <<
" < map->getNodeNumElements() = " << lclNumRows <<
".");
629 if (whichVectors.size () != 0) {
630 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
631 view.extent (1) != 0 && view.extent (1) == 0,
632 std::invalid_argument,
"view.extent(1) = 0, but whichVectors.size()"
633 " = " << whichVectors.size () <<
" > 0.");
634 size_t maxColInd = 0;
635 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
636 for (size_type k = 0; k < whichVectors.size (); ++k) {
637 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
638 whichVectors[k] == Teuchos::OrdinalTraits<size_t>::invalid (),
639 std::invalid_argument,
"whichVectors[" << k <<
"] = "
640 "Teuchos::OrdinalTraits<size_t>::invalid().");
641 maxColInd = std::max (maxColInd, whichVectors[k]);
643 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
644 view.extent (1) != 0 &&
static_cast<size_t> (view.extent (1)) <= maxColInd,
645 std::invalid_argument,
"view.extent(1) = " << view.extent (1)
646 <<
" <= max(whichVectors) = " << maxColInd <<
".");
651 const size_t LDA = getDualViewStride (origView);
652 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
653 (LDA < lclNumRows, std::invalid_argument,
"Map and DualView origView "
654 "do not match. LDA = " << LDA <<
" < this->getLocalLength() = " <<
655 lclNumRows <<
". origView.extent(0) = " << origView.extent(0)
656 <<
", origView.stride(1) = " << origView.d_view.stride(1) <<
".");
658 if (whichVectors.size () == 1) {
667 const std::pair<size_t, size_t> colRng (whichVectors[0],
668 whichVectors[0] + 1);
676 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
679 const Teuchos::ArrayView<const Scalar>& data,
681 const size_t numVecs) :
684 typedef LocalOrdinal LO;
685 typedef GlobalOrdinal GO;
686 const char tfecfFuncName[] =
"MultiVector(map,data,LDA,numVecs): ";
692 const size_t lclNumRows =
693 map.is_null () ? size_t (0) : map->getNodeNumElements ();
694 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
695 (LDA < lclNumRows, std::invalid_argument,
"LDA = " << LDA <<
" < "
696 "map->getNodeNumElements() = " << lclNumRows <<
".");
698 const size_t minNumEntries = LDA * (numVecs - 1) + lclNumRows;
699 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
700 (static_cast<size_t> (data.size ()) < minNumEntries,
701 std::invalid_argument,
"Input Teuchos::ArrayView does not have enough "
702 "entries, given the input Map and number of vectors in the MultiVector."
703 " data.size() = " << data.size () <<
" < (LDA*(numVecs-1)) + "
704 "map->getNodeNumElements () = " << minNumEntries <<
".");
707 this->
view_ = allocDualView<Scalar, LO, GO, Node> (lclNumRows, numVecs);
720 Kokkos::MemoryUnmanaged> X_in_orig (X_in_raw, LDA, numVecs);
721 const Kokkos::pair<size_t, size_t> rowRng (0, lclNumRows);
722 auto X_in = Kokkos::subview (X_in_orig, rowRng, Kokkos::ALL ());
727 const size_t outStride =
728 X_out.extent (1) == 0 ? size_t (1) : X_out.stride (1);
729 if (LDA == outStride) {
735 typedef decltype (Kokkos::subview (X_out, Kokkos::ALL (), 0))
737 typedef decltype (Kokkos::subview (X_in, Kokkos::ALL (), 0))
739 for (
size_t j = 0; j < numVecs; ++j) {
740 out_col_view_type X_out_j = Kokkos::subview (X_out, Kokkos::ALL (), j);
741 in_col_view_type X_in_j = Kokkos::subview (X_in, Kokkos::ALL (), j);
747 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
750 const Teuchos::ArrayView<
const Teuchos::ArrayView<const Scalar> >& ArrayOfPtrs,
751 const size_t numVecs) :
755 typedef LocalOrdinal LO;
756 typedef GlobalOrdinal GO;
757 const char tfecfFuncName[] =
"MultiVector(map,ArrayOfPtrs,numVecs): ";
760 const size_t lclNumRows =
761 map.is_null () ? size_t (0) : map->getNodeNumElements ();
762 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
763 (numVecs < 1 || numVecs != static_cast<size_t> (ArrayOfPtrs.size ()),
764 std::runtime_error,
"Either numVecs (= " << numVecs <<
") < 1, or "
765 "ArrayOfPtrs.size() (= " << ArrayOfPtrs.size () <<
") != numVecs.");
766 for (
size_t j = 0; j < numVecs; ++j) {
767 Teuchos::ArrayView<const Scalar> X_j_av = ArrayOfPtrs[j];
768 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
769 static_cast<size_t> (X_j_av.size ()) < lclNumRows,
770 std::invalid_argument,
"ArrayOfPtrs[" << j <<
"].size() = "
771 << X_j_av.size () <<
" < map->getNodeNumElements() = " << lclNumRows
775 view_ = allocDualView<Scalar, LO, GO, Node> (lclNumRows, numVecs);
781 using array_layout =
typename decltype (X_out)::array_layout;
782 using input_col_view_type =
typename Kokkos::View<
const IST*,
785 Kokkos::MemoryUnmanaged>;
787 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
788 for (
size_t j = 0; j < numVecs; ++j) {
789 Teuchos::ArrayView<const IST> X_j_av =
790 Teuchos::av_reinterpret_cast<
const IST> (ArrayOfPtrs[j]);
791 input_col_view_type X_j_in (X_j_av.getRawPtr (), lclNumRows);
792 auto X_j_out = Kokkos::subview (X_out, rowRng, j);
798 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
801 return whichVectors_.empty ();
804 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
809 if (this->getMap ().is_null ()) {
810 return static_cast<size_t> (0);
812 return this->getMap ()->getNodeNumElements ();
816 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
821 if (this->getMap ().is_null ()) {
822 return static_cast<size_t> (0);
824 return this->getMap ()->getGlobalNumElements ();
828 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
833 return isConstantStride () ? getDualViewStride (origView_) : size_t (0);
836 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
845 const this_type* src =
dynamic_cast<const this_type*
> (&sourceObj);
846 if (src ==
nullptr) {
856 return src->getNumVectors () == this->getNumVectors ();
860 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
864 return this->getNumVectors ();
867 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
870 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
872 #else // TPETRA_ENABLE_DEPRECATED_CODE
874 #endif // TPETRA_ENABLE_DEPRECATED_CODE
876 const size_t numSameIDs,
877 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
878 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs)
880 using ::Tpetra::Details::Behavior;
882 using ::Tpetra::Details::ProfilingRegion;
884 using KokkosRefactor::Details::permute_array_multi_column;
885 using KokkosRefactor::Details::permute_array_multi_column_variable_stride;
886 using Kokkos::Compat::create_const_view;
888 const char tfecfFuncName[] =
"copyAndPermute: ";
889 ProfilingRegion regionCAP (
"Tpetra::MultiVector::copyAndPermute");
891 const bool verbose = Behavior::verbose ();
892 std::unique_ptr<std::string> prefix;
894 auto map = this->getMap ();
895 auto comm = map.is_null () ? Teuchos::null : map->getComm ();
896 const int myRank = comm.is_null () ? -1 : comm->getRank ();
897 std::ostringstream os;
898 os <<
"Proc " << myRank <<
": MV::copyAndPermute: ";
899 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
900 os <<
"Start" << endl;
901 std::cerr << os.str ();
904 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
905 (permuteToLIDs.extent (0) != permuteFromLIDs.extent (0),
906 std::logic_error,
"permuteToLIDs.extent(0) = "
907 << permuteToLIDs.extent (0) <<
" != permuteFromLIDs.extent(0) = "
908 << permuteFromLIDs.extent (0) <<
".");
911 const MV& sourceMV =
dynamic_cast<const MV&
> (sourceObj);
912 const size_t numCols = this->getNumVectors ();
916 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
917 (sourceMV.need_sync_device () && sourceMV.need_sync_host (),
918 std::logic_error,
"Input MultiVector needs sync to both host "
920 const bool copyOnHost = sourceMV.need_sync_device ();
922 std::ostringstream os;
923 os << *prefix <<
"copyOnHost=" << (copyOnHost ?
"true" :
"false") << endl;
924 std::cerr << os.str ();
928 if (this->need_sync_host ()) {
931 this->modify_host ();
934 if (this->need_sync_device ()) {
935 this->sync_device ();
937 this->modify_device ();
941 std::ostringstream os;
942 os << *prefix <<
"Copy" << endl;
943 std::cerr << os.str ();
968 if (numSameIDs > 0) {
969 const std::pair<size_t, size_t> rows (0, numSameIDs);
971 auto tgt_h = this->getLocalViewHost ();
972 auto src_h = create_const_view (sourceMV.getLocalViewHost ());
974 for (
size_t j = 0; j < numCols; ++j) {
975 const size_t tgtCol = isConstantStride () ? j : whichVectors_[j];
976 const size_t srcCol =
977 sourceMV.isConstantStride () ? j : sourceMV.whichVectors_[j];
979 auto tgt_j = Kokkos::subview (tgt_h, rows, tgtCol);
980 auto src_j = Kokkos::subview (src_h, rows, srcCol);
985 auto tgt_d = this->getLocalViewDevice ();
986 auto src_d = create_const_view (sourceMV.getLocalViewDevice ());
988 for (
size_t j = 0; j < numCols; ++j) {
989 const size_t tgtCol = isConstantStride () ? j : whichVectors_[j];
990 const size_t srcCol =
991 sourceMV.isConstantStride () ? j : sourceMV.whichVectors_[j];
993 auto tgt_j = Kokkos::subview (tgt_d, rows, tgtCol);
994 auto src_j = Kokkos::subview (src_d, rows, srcCol);
1010 if (permuteFromLIDs.extent (0) == 0 ||
1011 permuteToLIDs.extent (0) == 0) {
1013 std::ostringstream os;
1014 os << *prefix <<
"No permutations. Done!" << endl;
1015 std::cerr << os.str ();
1021 std::ostringstream os;
1022 os << *prefix <<
"Permute" << endl;
1023 std::cerr << os.str ();
1028 const bool nonConstStride =
1029 ! this->isConstantStride () || ! sourceMV.isConstantStride ();
1032 std::ostringstream os;
1033 os << *prefix <<
"nonConstStride="
1034 << (nonConstStride ?
"true" :
"false") << endl;
1035 std::cerr << os.str ();
1042 Kokkos::DualView<const size_t*, device_type> srcWhichVecs;
1043 Kokkos::DualView<const size_t*, device_type> tgtWhichVecs;
1044 if (nonConstStride) {
1045 if (this->whichVectors_.size () == 0) {
1046 Kokkos::DualView<size_t*, device_type> tmpTgt (
"tgtWhichVecs", numCols);
1047 tmpTgt.modify_host ();
1048 for (
size_t j = 0; j < numCols; ++j) {
1049 tmpTgt.h_view(j) = j;
1052 tmpTgt.sync_device ();
1054 tgtWhichVecs = tmpTgt;
1057 Teuchos::ArrayView<const size_t> tgtWhichVecsT = this->whichVectors_ ();
1059 getDualViewCopyFromArrayView<size_t, device_type> (tgtWhichVecsT,
1063 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1064 (static_cast<size_t> (tgtWhichVecs.extent (0)) !=
1065 this->getNumVectors (),
1066 std::logic_error,
"tgtWhichVecs.extent(0) = " <<
1067 tgtWhichVecs.extent (0) <<
" != this->getNumVectors() = " <<
1068 this->getNumVectors () <<
".");
1070 if (sourceMV.whichVectors_.size () == 0) {
1071 Kokkos::DualView<size_t*, device_type> tmpSrc (
"srcWhichVecs", numCols);
1072 tmpSrc.modify_host ();
1073 for (
size_t j = 0; j < numCols; ++j) {
1074 tmpSrc.h_view(j) = j;
1077 tmpSrc.sync_device ();
1079 srcWhichVecs = tmpSrc;
1082 Teuchos::ArrayView<const size_t> srcWhichVecsT =
1083 sourceMV.whichVectors_ ();
1085 getDualViewCopyFromArrayView<size_t, device_type> (srcWhichVecsT,
1089 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1090 (static_cast<size_t> (srcWhichVecs.extent (0)) !=
1091 sourceMV.getNumVectors (), std::logic_error,
1092 "srcWhichVecs.extent(0) = " << srcWhichVecs.extent (0)
1093 <<
" != sourceMV.getNumVectors() = " << sourceMV.getNumVectors ()
1099 std::ostringstream os;
1100 os << *prefix <<
"Get permute LIDs on host" << std::endl;
1101 std::cerr << os.str ();
1103 auto tgt_h = this->getLocalViewHost ();
1104 auto src_h = create_const_view (sourceMV.getLocalViewHost ());
1106 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host () );
1107 auto permuteToLIDs_h = create_const_view (permuteToLIDs.view_host ());
1108 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host () );
1109 auto permuteFromLIDs_h =
1110 create_const_view (permuteFromLIDs.view_host ());
1113 std::ostringstream os;
1114 os << *prefix <<
"Permute on host" << endl;
1115 std::cerr << os.str ();
1117 if (nonConstStride) {
1120 auto tgtWhichVecs_h =
1121 create_const_view (tgtWhichVecs.view_host ());
1122 auto srcWhichVecs_h =
1123 create_const_view (srcWhichVecs.view_host ());
1124 permute_array_multi_column_variable_stride (tgt_h, src_h,
1128 srcWhichVecs_h, numCols);
1131 permute_array_multi_column (tgt_h, src_h, permuteToLIDs_h,
1132 permuteFromLIDs_h, numCols);
1137 std::ostringstream os;
1138 os << *prefix <<
"Get permute LIDs on device" << endl;
1139 std::cerr << os.str ();
1141 auto tgt_d = this->getLocalViewDevice ();
1142 auto src_d = create_const_view (sourceMV.getLocalViewDevice ());
1144 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_device () );
1145 auto permuteToLIDs_d = create_const_view (permuteToLIDs.view_device ());
1146 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_device () );
1147 auto permuteFromLIDs_d =
1148 create_const_view (permuteFromLIDs.view_device ());
1151 std::ostringstream os;
1152 os << *prefix <<
"Permute on device" << endl;
1153 std::cerr << os.str ();
1155 if (nonConstStride) {
1158 auto tgtWhichVecs_d = create_const_view (tgtWhichVecs.view_device ());
1159 auto srcWhichVecs_d = create_const_view (srcWhichVecs.view_device ());
1160 permute_array_multi_column_variable_stride (tgt_d, src_d,
1164 srcWhichVecs_d, numCols);
1167 permute_array_multi_column (tgt_d, src_d, permuteToLIDs_d,
1168 permuteFromLIDs_d, numCols);
1173 std::ostringstream os;
1174 os << *prefix <<
"Done!" << endl;
1175 std::cerr << os.str ();
1179 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1181 MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1182 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1184 #else // TPETRA_ENABLE_DEPRECATED_CODE
1186 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1187 (
const SrcDistObject& sourceObj,
1188 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
1189 Kokkos::DualView<impl_scalar_type*, buffer_device_type>& exports,
1190 Kokkos::DualView<size_t*, buffer_device_type> ,
1191 size_t& constantNumPackets,
1194 using ::Tpetra::Details::Behavior;
1195 using ::Tpetra::Details::ProfilingRegion;
1197 using Kokkos::Compat::create_const_view;
1198 using Kokkos::Compat::getKokkosViewDeepCopy;
1200 using MV = MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
1201 const char tfecfFuncName[] =
"packAndPrepare: ";
1202 ProfilingRegion regionPAP (
"Tpetra::MultiVector::packAndPrepare");
1210 const bool debugCheckIndices = Behavior::debug ();
1215 const bool printDebugOutput = Behavior::verbose ();
1217 std::unique_ptr<std::string> prefix;
1218 if (printDebugOutput) {
1219 auto map = this->getMap ();
1220 auto comm = map.is_null () ? Teuchos::null : map->getComm ();
1221 const int myRank = comm.is_null () ? -1 : comm->getRank ();
1222 std::ostringstream os;
1223 os <<
"Proc " << myRank <<
": MV::packAndPrepare: ";
1224 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1225 os <<
"Start" << endl;
1226 std::cerr << os.str ();
1230 const MV& sourceMV =
dynamic_cast<const MV&
> (sourceObj);
1232 const size_t numCols = sourceMV.getNumVectors ();
1237 constantNumPackets = numCols;
1241 if (exportLIDs.extent (0) == 0) {
1242 if (printDebugOutput) {
1243 std::ostringstream os;
1244 os << *prefix <<
"No exports on this proc, DONE" << std::endl;
1245 std::cerr << os.str ();
1265 const size_t numExportLIDs = exportLIDs.extent (0);
1266 const size_t newExportsSize = numCols * numExportLIDs;
1267 if (printDebugOutput) {
1268 std::ostringstream os;
1269 os << *prefix <<
"realloc: "
1270 <<
"numExportLIDs: " << numExportLIDs
1271 <<
", exports.extent(0): " << exports.extent (0)
1272 <<
", newExportsSize: " << newExportsSize << std::endl;
1273 std::cerr << os.str ();
1279 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1280 (sourceMV.need_sync_device () && sourceMV.need_sync_host (),
1281 std::logic_error,
"Input MultiVector needs sync to both host "
1283 const bool packOnHost = sourceMV.need_sync_device ();
1284 auto src_dev = sourceMV.getLocalViewHost ();
1285 auto src_host = sourceMV.getLocalViewDevice ();
1286 if (printDebugOutput) {
1287 std::ostringstream os;
1288 os << *prefix <<
"packOnHost=" << (packOnHost ?
"true" :
"false") << endl;
1289 std::cerr << os.str ();
1296 exports.modify_host ();
1299 exports.modify_device ();
1315 if (sourceMV.isConstantStride ()) {
1316 using KokkosRefactor::Details::pack_array_single_column;
1317 if (printDebugOutput) {
1318 std::ostringstream os;
1319 os << *prefix <<
"Pack numCols=1 const stride" << endl;
1320 std::cerr << os.str ();
1323 pack_array_single_column (exports.view_host (),
1324 create_const_view (src_host),
1325 exportLIDs.view_host (),
1330 pack_array_single_column (exports.view_device (),
1331 create_const_view (src_dev),
1332 exportLIDs.view_device (),
1338 using KokkosRefactor::Details::pack_array_single_column;
1339 if (printDebugOutput) {
1340 std::ostringstream os;
1341 os << *prefix <<
"Pack numCols=1 nonconst stride" << endl;
1342 std::cerr << os.str ();
1345 pack_array_single_column (exports.view_host (),
1346 create_const_view (src_host),
1347 exportLIDs.view_host (),
1348 sourceMV.whichVectors_[0],
1352 pack_array_single_column (exports.view_device (),
1353 create_const_view (src_dev),
1354 exportLIDs.view_device (),
1355 sourceMV.whichVectors_[0],
1361 if (sourceMV.isConstantStride ()) {
1362 using KokkosRefactor::Details::pack_array_multi_column;
1363 if (printDebugOutput) {
1364 std::ostringstream os;
1365 os << *prefix <<
"Pack numCols=" << numCols <<
" const stride" << endl;
1366 std::cerr << os.str ();
1369 pack_array_multi_column (exports.view_host (),
1370 create_const_view (src_host),
1371 exportLIDs.view_host (),
1376 pack_array_multi_column (exports.view_device (),
1377 create_const_view (src_dev),
1378 exportLIDs.view_device (),
1384 using KokkosRefactor::Details::pack_array_multi_column_variable_stride;
1385 if (printDebugOutput) {
1386 std::ostringstream os;
1387 os << *prefix <<
"Pack numCols=" << numCols <<
" nonconst stride"
1389 std::cerr << os.str ();
1394 using IST = impl_scalar_type;
1395 using DV = Kokkos::DualView<IST*, device_type>;
1396 using HES =
typename DV::t_host::execution_space;
1397 using DES =
typename DV::t_dev::execution_space;
1398 Teuchos::ArrayView<const size_t> whichVecs = sourceMV.whichVectors_ ();
1400 pack_array_multi_column_variable_stride
1401 (exports.view_host (),
1402 create_const_view (src_host),
1403 exportLIDs.view_host (),
1404 getKokkosViewDeepCopy<HES> (whichVecs),
1409 pack_array_multi_column_variable_stride
1410 (exports.view_device (),
1411 create_const_view (src_dev),
1412 exportLIDs.view_device (),
1413 getKokkosViewDeepCopy<DES> (whichVecs),
1420 if (printDebugOutput) {
1421 std::ostringstream os;
1422 os << *prefix <<
"Done!" << endl;
1423 std::cerr << os.str ();
1428 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1430 MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1431 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1433 #else // TPETRA_ENABLE_DEPRECATED_CODE
1435 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1436 (
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& importLIDs,
1437 Kokkos::DualView<impl_scalar_type*, buffer_device_type> imports,
1438 Kokkos::DualView<size_t*, buffer_device_type> ,
1439 const size_t constantNumPackets,
1443 using ::Tpetra::Details::Behavior;
1444 using ::Tpetra::Details::ProfilingRegion;
1445 using KokkosRefactor::Details::unpack_array_multi_column;
1446 using KokkosRefactor::Details::unpack_array_multi_column_variable_stride;
1447 using Kokkos::Compat::getKokkosViewDeepCopy;
1449 using IST = impl_scalar_type;
1450 const char tfecfFuncName[] =
"unpackAndCombine: ";
1451 ProfilingRegion regionUAC (
"Tpetra::MultiVector::unpackAndCombine");
1459 const bool debugCheckIndices = Behavior::debug ();
1461 const bool printDebugOutput = Behavior::verbose ();
1462 std::unique_ptr<std::string> prefix;
1463 if (printDebugOutput) {
1464 auto map = this->getMap ();
1465 auto comm = map.is_null () ? Teuchos::null : map->getComm ();
1466 const int myRank = comm.is_null () ? -1 : comm->getRank ();
1467 std::ostringstream os;
1468 os <<
"Proc " << myRank <<
": MV::packAndPrepare: ";
1469 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1470 os <<
"Start" << endl;
1471 std::cerr << os.str ();
1475 if (importLIDs.extent (0) == 0) {
1476 if (printDebugOutput) {
1477 std::ostringstream os;
1478 os << *prefix <<
"No imports. Done!" << endl;
1483 const size_t numVecs = getNumVectors ();
1484 if (debugCheckIndices) {
1485 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1486 (static_cast<size_t> (imports.extent (0)) !=
1487 numVecs * importLIDs.extent (0),
1489 "imports.extent(0) = " << imports.extent (0)
1490 <<
" != getNumVectors() * importLIDs.extent(0) = " << numVecs
1491 <<
" * " << importLIDs.extent (0) <<
" = "
1492 << numVecs * importLIDs.extent (0) <<
".");
1494 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1495 (constantNumPackets == static_cast<size_t> (0), std::runtime_error,
1496 "constantNumPackets input argument must be nonzero.");
1498 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1499 (static_cast<size_t> (numVecs) !=
1500 static_cast<size_t> (constantNumPackets),
1501 std::runtime_error,
"constantNumPackets must equal numVecs.");
1507 const bool unpackOnHost = imports.need_sync_device ();
1509 if (printDebugOutput) {
1510 std::ostringstream os;
1511 os << *prefix <<
"unpackOnHost=" << (unpackOnHost ?
"true" :
"false")
1513 std::cerr << os.str ();
1519 if (this->need_sync_host ()) {
1522 this->modify_host ();
1525 if (this->need_sync_device ()) {
1526 this->sync_device ();
1528 this->modify_device ();
1530 auto X_d = this->getLocalViewDevice ();
1531 auto X_h = this->getLocalViewHost ();
1532 auto imports_d = imports.view_device ();
1533 auto imports_h = imports.view_host ();
1534 auto importLIDs_d = importLIDs.view_device ();
1535 auto importLIDs_h = importLIDs.view_host ();
1537 Kokkos::DualView<size_t*, device_type> whichVecs;
1538 if (! isConstantStride ()) {
1539 Kokkos::View<
const size_t*, Kokkos::HostSpace,
1540 Kokkos::MemoryUnmanaged> whichVecsIn (whichVectors_.getRawPtr (),
1542 whichVecs = Kokkos::DualView<size_t*, device_type> (
"whichVecs", numVecs);
1544 whichVecs.modify_host ();
1548 whichVecs.modify_device ();
1552 auto whichVecs_d = whichVecs.view_device ();
1553 auto whichVecs_h = whichVecs.view_host ();
1563 if (numVecs > 0 && importLIDs.extent (0) > 0) {
1564 using dev_exec_space =
typename dual_view_type::t_dev::execution_space;
1565 using host_exec_space =
typename dual_view_type::t_host::execution_space;
1568 const bool use_atomic_updates = unpackOnHost ?
1569 host_exec_space::concurrency () != 1 :
1570 dev_exec_space::concurrency () != 1;
1572 if (printDebugOutput) {
1573 std::ostringstream os;
1575 std::cerr << os.str ();
1582 using op_type = KokkosRefactor::Details::InsertOp<IST>;
1583 if (isConstantStride ()) {
1585 unpack_array_multi_column (host_exec_space (),
1586 X_h, imports_h, importLIDs_h,
1587 op_type (), numVecs,
1593 unpack_array_multi_column (dev_exec_space (),
1594 X_d, imports_d, importLIDs_d,
1595 op_type (), numVecs,
1602 unpack_array_multi_column_variable_stride (host_exec_space (),
1612 unpack_array_multi_column_variable_stride (dev_exec_space (),
1623 else if (CM ==
ADD) {
1624 using op_type = KokkosRefactor::Details::AddOp<IST>;
1625 if (isConstantStride ()) {
1627 unpack_array_multi_column (host_exec_space (),
1628 X_h, imports_h, importLIDs_h,
1629 op_type (), numVecs,
1634 unpack_array_multi_column (dev_exec_space (),
1635 X_d, imports_d, importLIDs_d,
1636 op_type (), numVecs,
1643 unpack_array_multi_column_variable_stride (host_exec_space (),
1653 unpack_array_multi_column_variable_stride (dev_exec_space (),
1665 using op_type = KokkosRefactor::Details::AbsMaxOp<IST>;
1666 if (isConstantStride ()) {
1668 unpack_array_multi_column (host_exec_space (),
1669 X_h, imports_h, importLIDs_h,
1670 op_type (), numVecs,
1675 unpack_array_multi_column (dev_exec_space (),
1676 X_d, imports_d, importLIDs_d,
1677 op_type (), numVecs,
1684 unpack_array_multi_column_variable_stride (host_exec_space (),
1694 unpack_array_multi_column_variable_stride (dev_exec_space (),
1706 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1707 (
true, std::logic_error,
"Invalid CombineMode");
1711 if (printDebugOutput) {
1712 std::ostringstream os;
1713 os << *prefix <<
"Nothing to unpack" << endl;
1714 std::cerr << os.str ();
1718 if (printDebugOutput) {
1719 std::ostringstream os;
1720 os << *prefix <<
"Done!" << endl;
1721 std::cerr << os.str ();
1725 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1730 if (isConstantStride ()) {
1731 return static_cast<size_t> (view_.extent (1));
1733 return static_cast<size_t> (whichVectors_.size ());
1741 gblDotImpl (
const RV& dotsOut,
1742 const Teuchos::RCP<
const Teuchos::Comm<int> >& comm,
1743 const bool distributed)
1745 using Teuchos::REDUCE_MAX;
1746 using Teuchos::REDUCE_SUM;
1747 using Teuchos::reduceAll;
1748 typedef typename RV::non_const_value_type dot_type;
1750 const size_t numVecs = dotsOut.extent (0);
1765 if (distributed && ! comm.is_null ()) {
1768 const int nv =
static_cast<int> (numVecs);
1769 const bool commIsInterComm = ::Tpetra::Details::isInterComm (*comm);
1771 if (commIsInterComm) {
1775 typename RV::non_const_type lclDots (Kokkos::ViewAllocateWithoutInitializing (
"tmp"), numVecs);
1777 const dot_type*
const lclSum = lclDots.data ();
1778 dot_type*
const gblSum = dotsOut.data ();
1779 reduceAll<int, dot_type> (*comm, REDUCE_SUM, nv, lclSum, gblSum);
1782 dot_type*
const inout = dotsOut.data ();
1783 reduceAll<int, dot_type> (*comm, REDUCE_SUM, nv, inout, inout);
1789 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1793 const Kokkos::View<dot_type*, Kokkos::HostSpace>& dots)
const
1795 using ::Tpetra::Details::Behavior;
1796 using Kokkos::subview;
1797 using Teuchos::Comm;
1798 using Teuchos::null;
1801 typedef Kokkos::View<dot_type*, Kokkos::HostSpace> RV;
1803 typedef typename dual_view_type::t_dev XMV;
1804 const char tfecfFuncName[] =
"Tpetra::MultiVector::dot: ";
1808 const size_t numVecs = this->getNumVectors ();
1812 const size_t lclNumRows = this->getLocalLength ();
1813 const size_t numDots =
static_cast<size_t> (dots.extent (0));
1814 const bool debug = Behavior::debug ();
1817 const bool compat = this->getMap ()->isCompatible (* (A.
getMap ()));
1818 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1819 (! compat, std::invalid_argument,
"'*this' MultiVector is not "
1820 "compatible with the input MultiVector A. We only test for this "
1831 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1833 "MultiVectors do not have the same local length. "
1834 "this->getLocalLength() = " << lclNumRows <<
" != "
1836 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1838 "MultiVectors must have the same number of columns (vectors). "
1839 "this->getNumVectors() = " << numVecs <<
" != "
1841 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1842 numDots != numVecs, std::runtime_error,
1843 "The output array 'dots' must have the same number of entries as the "
1844 "number of columns (vectors) in *this and A. dots.extent(0) = " <<
1845 numDots <<
" != this->getNumVectors() = " << numVecs <<
".");
1847 const std::pair<size_t, size_t> colRng (0, numVecs);
1848 RV dotsOut = subview (dots, colRng);
1849 RCP<const Comm<int> > comm = this->getMap ().is_null () ? null :
1850 this->getMap ()->getComm ();
1853 if (this->need_sync_device ()) {
1854 const_cast<MV*
>(
this)->sync_device ();
1857 const_cast<MV&
>(A).sync_device ();
1860 auto thisView = this->getLocalViewDevice ();
1863 ::Tpetra::Details::lclDot<RV, XMV> (dotsOut, thisView, A_view, lclNumRows, numVecs,
1864 this->whichVectors_.getRawPtr (),
1867 gblDotImpl (dotsOut, comm, this->isDistributed ());
1871 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1876 using ::Tpetra::Details::ProfilingRegion;
1878 using dot_type =
typename MV::dot_type;
1879 ProfilingRegion region (
"Tpetra::multiVectorSingleColumnDot");
1882 Teuchos::RCP<const Teuchos::Comm<int> > comm =
1883 map.is_null () ? Teuchos::null : map->getComm ();
1884 if (comm.is_null ()) {
1885 return Kokkos::ArithTraits<dot_type>::zero ();
1888 using LO = LocalOrdinal;
1892 const LO lclNumRows =
static_cast<LO
> (std::min (x.
getLocalLength (),
1894 const Kokkos::pair<LO, LO> rowRng (0, lclNumRows);
1895 dot_type lclDot = Kokkos::ArithTraits<dot_type>::zero ();
1896 dot_type gblDot = Kokkos::ArithTraits<dot_type>::zero ();
1903 const_cast<MV&
>(y).sync_device ();
1908 auto x_1d = Kokkos::subview (x_2d, rowRng, 0);
1910 auto y_1d = Kokkos::subview (y_2d, rowRng, 0);
1911 lclDot = KokkosBlas::dot (x_1d, y_1d);
1914 using Teuchos::outArg;
1915 using Teuchos::REDUCE_SUM;
1916 using Teuchos::reduceAll;
1917 reduceAll<int, dot_type> (*comm, REDUCE_SUM, lclDot, outArg (gblDot));
1929 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1933 const Teuchos::ArrayView<dot_type>& dots)
const
1936 const char tfecfFuncName[] =
"dot: ";
1939 const size_t numVecs = this->getNumVectors ();
1940 const size_t lclNumRows = this->getLocalLength ();
1941 const size_t numDots =
static_cast<size_t> (dots.size ());
1951 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1953 "MultiVectors do not have the same local length. "
1954 "this->getLocalLength() = " << lclNumRows <<
" != "
1956 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1958 "MultiVectors must have the same number of columns (vectors). "
1959 "this->getNumVectors() = " << numVecs <<
" != "
1961 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1962 (numDots != numVecs, std::runtime_error,
1963 "The output array 'dots' must have the same number of entries as the "
1964 "number of columns (vectors) in *this and A. dots.extent(0) = " <<
1965 numDots <<
" != this->getNumVectors() = " << numVecs <<
".");
1968 const dot_type gblDot = multiVectorSingleColumnDot (const_cast<MV&> (*
this), A);
1972 this->dot (A, Kokkos::View<dot_type*, Kokkos::HostSpace>(dots.getRawPtr (), numDots));
1976 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1979 norm2 (
const Teuchos::ArrayView<mag_type>& norms)
const
1982 using ::Tpetra::Details::NORM_TWO;
1983 using ::Tpetra::Details::ProfilingRegion;
1984 ProfilingRegion region (
"Tpetra::MV::norm2 (host output)");
1987 MV& X =
const_cast<MV&
> (*this);
1988 multiVectorNormImpl (norms.getRawPtr (), X, NORM_TWO);
1991 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1994 norm2 (
const Kokkos::View<mag_type*, Kokkos::HostSpace>& norms)
const
1996 Teuchos::ArrayView<mag_type> norms_av (norms.data (), norms.extent (0));
1997 this->norm2 (norms_av);
2000 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
2001 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2002 void TPETRA_DEPRECATED
2005 const Teuchos::ArrayView<mag_type> &norms)
const
2008 using Kokkos::subview;
2009 using Teuchos::Comm;
2010 using Teuchos::null;
2012 using Teuchos::reduceAll;
2013 using Teuchos::REDUCE_SUM;
2014 typedef Kokkos::ArithTraits<impl_scalar_type> ATS;
2015 typedef Kokkos::ArithTraits<mag_type> ATM;
2016 typedef Kokkos::View<mag_type*, Kokkos::HostSpace> norms_view_type;
2018 const char tfecfFuncName[] =
"normWeighted: ";
2020 const size_t numVecs = this->getNumVectors ();
2021 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2022 static_cast<size_t> (norms.size ()) != numVecs, std::runtime_error,
2023 "norms.size() = " << norms.size () <<
" != this->getNumVectors() = "
2027 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2028 ! OneW && weights.
getNumVectors () != numVecs, std::runtime_error,
2029 "The input MultiVector of weights must contain either one column, "
2030 "or must have the same number of columns as *this. "
2032 <<
" and this->getNumVectors() = " << numVecs <<
".");
2037 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2038 (! this->getMap ()->isCompatible (*weights.
getMap ()), std::runtime_error,
2039 "MultiVectors do not have compatible Maps:" << std::endl
2040 <<
"this->getMap(): " << std::endl << *this->getMap()
2041 <<
"weights.getMap(): " << std::endl << *weights.
getMap() << std::endl);
2044 const size_t lclNumRows = this->getLocalLength ();
2045 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2047 "MultiVectors do not have the same local length.");
2050 norms_view_type lclNrms (
"Tpetra::MV::lclNrms", numVecs);
2053 const_cast<MV*
> (
this)->sync_device ();
2054 const_cast<MV&
> (weights).sync_device ();
2056 auto X_lcl = this->getLocalViewDevice ();
2059 if (isConstantStride () && ! OneW) {
2060 KokkosBlas::nrm2w_squared (lclNrms, X_lcl, W_lcl);
2063 for (
size_t j = 0; j < numVecs; ++j) {
2064 const size_t X_col = this->isConstantStride () ? j :
2065 this->whichVectors_[j];
2066 const size_t W_col = OneW ?
static_cast<size_t> (0) :
2068 KokkosBlas::nrm2w_squared (subview (lclNrms, j),
2069 subview (X_lcl, ALL (), X_col),
2070 subview (W_lcl, ALL (), W_col));
2074 const mag_type OneOverN =
2075 ATM::one () /
static_cast<mag_type
> (this->getGlobalLength ());
2076 RCP<const Comm<int> > comm = this->getMap ().is_null () ?
2077 Teuchos::null : this->getMap ()->getComm ();
2079 if (! comm.is_null () && this->isDistributed ()) {
2081 reduceAll<int, mag_type> (*comm, REDUCE_SUM,
static_cast<int> (numVecs),
2082 lclNrms.data (), norms.getRawPtr ());
2083 for (
size_t k = 0; k < numVecs; ++k) {
2084 norms[k] = ATM::sqrt (norms[k] * OneOverN);
2088 for (
size_t k = 0; k < numVecs; ++k) {
2089 norms[k] = ATM::sqrt (ATS::magnitude (lclNrms(k)) * OneOverN);
2093 #endif // TPETRA_ENABLE_DEPRECATED_CODE
2095 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2098 norm1 (
const Teuchos::ArrayView<mag_type>& norms)
const
2101 using ::Tpetra::Details::NORM_ONE;
2102 using ::Tpetra::Details::ProfilingRegion;
2103 ProfilingRegion region (
"Tpetra::MV::norm1 (host output)");
2106 MV& X =
const_cast<MV&
> (*this);
2107 multiVectorNormImpl (norms.data (), X, NORM_ONE);
2110 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2113 norm1 (
const Kokkos::View<mag_type*, Kokkos::HostSpace>& norms)
const
2115 Teuchos::ArrayView<mag_type> norms_av (norms.data (), norms.extent (0));
2116 this->norm1 (norms_av);
2119 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2122 normInf (
const Teuchos::ArrayView<mag_type>& norms)
const
2125 using ::Tpetra::Details::NORM_INF;
2126 using ::Tpetra::Details::ProfilingRegion;
2127 ProfilingRegion region (
"Tpetra::MV::normInf (host output)");
2130 MV& X =
const_cast<MV&
> (*this);
2131 multiVectorNormImpl (norms.getRawPtr (), X, NORM_INF);
2134 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2137 normInf (
const Kokkos::View<mag_type*, Kokkos::HostSpace>& norms)
const
2139 Teuchos::ArrayView<mag_type> norms_av (norms.data (), norms.extent (0));
2140 this->normInf (norms_av);
2143 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2146 meanValue (
const Teuchos::ArrayView<impl_scalar_type>& means)
const
2150 using Kokkos::subview;
2151 using Teuchos::Comm;
2153 using Teuchos::reduceAll;
2154 using Teuchos::REDUCE_SUM;
2155 typedef Kokkos::Details::ArithTraits<impl_scalar_type> ATS;
2157 const size_t lclNumRows = this->getLocalLength ();
2158 const size_t numVecs = this->getNumVectors ();
2159 const size_t numMeans =
static_cast<size_t> (means.size ());
2161 TEUCHOS_TEST_FOR_EXCEPTION(
2162 numMeans != numVecs, std::runtime_error,
2163 "Tpetra::MultiVector::meanValue: means.size() = " << numMeans
2164 <<
" != this->getNumVectors() = " << numVecs <<
".");
2166 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
2167 const std::pair<size_t, size_t> colRng (0, numVecs);
2172 typedef Kokkos::View<impl_scalar_type*, device_type> local_view_type;
2174 typename local_view_type::HostMirror::array_layout,
2176 Kokkos::MemoryTraits<Kokkos::Unmanaged> > host_local_view_type;
2177 host_local_view_type meansOut (means.getRawPtr (), numMeans);
2179 RCP<const Comm<int> > comm = this->getMap ().is_null () ? Teuchos::null :
2180 this->getMap ()->getComm ();
2183 const bool useHostVersion = this->need_sync_device ();
2184 if (useHostVersion) {
2186 auto X_lcl = subview (getLocalViewHost (),
2187 rowRng, Kokkos::ALL ());
2189 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace> lclSums (
"MV::meanValue tmp", numVecs);
2190 if (isConstantStride ()) {
2191 KokkosBlas::sum (lclSums, X_lcl);
2194 for (
size_t j = 0; j < numVecs; ++j) {
2195 const size_t col = whichVectors_[j];
2196 KokkosBlas::sum (subview (lclSums, j), subview (X_lcl, ALL (), col));
2203 if (! comm.is_null () && this->isDistributed ()) {
2204 reduceAll (*comm, REDUCE_SUM, static_cast<int> (numVecs),
2205 lclSums.data (), meansOut.data ());
2213 auto X_lcl = subview (this->getLocalViewDevice (),
2214 rowRng, Kokkos::ALL ());
2217 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace> lclSums (
"MV::meanValue tmp", numVecs);
2218 if (isConstantStride ()) {
2219 KokkosBlas::sum (lclSums, X_lcl);
2222 for (
size_t j = 0; j < numVecs; ++j) {
2223 const size_t col = whichVectors_[j];
2224 KokkosBlas::sum (subview (lclSums, j), subview (X_lcl, ALL (), col));
2232 if (! comm.is_null () && this->isDistributed ()) {
2233 reduceAll (*comm, REDUCE_SUM, static_cast<int> (numVecs),
2234 lclSums.data (), meansOut.data ());
2244 const impl_scalar_type OneOverN =
2245 ATS::one () /
static_cast<mag_type> (this->getGlobalLength ());
2246 for (
size_t k = 0; k < numMeans; ++k) {
2247 meansOut(k) = meansOut(k) * OneOverN;
2252 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2258 typedef Kokkos::Details::ArithTraits<IST> ATS;
2259 typedef Kokkos::Random_XorShift64_Pool<typename device_type::execution_space> pool_type;
2260 typedef typename pool_type::generator_type generator_type;
2262 const IST max = Kokkos::rand<generator_type, IST>::max ();
2263 const IST min = ATS::is_signed ? IST (-max) : ATS::zero ();
2265 this->randomize (static_cast<Scalar> (min), static_cast<Scalar> (max));
2269 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2275 typedef Kokkos::Random_XorShift64_Pool<typename device_type::execution_space> pool_type;
2286 const uint64_t myRank =
2287 static_cast<uint64_t
> (this->getMap ()->getComm ()->getRank ());
2288 uint64_t seed64 =
static_cast<uint64_t
> (std::rand ()) + myRank + 17311uLL;
2289 unsigned int seed =
static_cast<unsigned int> (seed64&0xffffffff);
2291 pool_type rand_pool (seed);
2292 const IST max =
static_cast<IST
> (maxVal);
2293 const IST min =
static_cast<IST
> (minVal);
2298 this->view_.clear_sync_state();
2300 this->modify_device ();
2301 auto thisView = this->getLocalViewDevice ();
2303 if (isConstantStride ()) {
2304 Kokkos::fill_random (thisView, rand_pool, min, max);
2307 const size_t numVecs = getNumVectors ();
2308 for (
size_t k = 0; k < numVecs; ++k) {
2309 const size_t col = whichVectors_[k];
2310 auto X_k = Kokkos::subview (thisView, Kokkos::ALL (), col);
2311 Kokkos::fill_random (X_k, rand_pool, min, max);
2316 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2321 using ::Tpetra::Details::ProfilingRegion;
2322 using ::Tpetra::Details::Blas::fill;
2323 using DES =
typename dual_view_type::t_dev::execution_space;
2324 using HES =
typename dual_view_type::t_host::execution_space;
2325 using LO = LocalOrdinal;
2326 ProfilingRegion region (
"Tpetra::MultiVector::putScalar");
2331 const LO lclNumRows =
static_cast<LO
> (this->getLocalLength ());
2332 const LO numVecs =
static_cast<LO
> (this->getNumVectors ());
2338 const bool runOnHost = this->need_sync_device ();
2341 this->modify_device ();
2342 auto X = this->getLocalViewDevice ();
2343 if (this->isConstantStride ()) {
2344 fill (DES (), X, theAlpha, lclNumRows, numVecs);
2347 fill (DES (), X, theAlpha, lclNumRows, numVecs,
2348 this->whichVectors_.getRawPtr ());
2352 this->modify_host ();
2353 auto X = this->getLocalViewHost ();
2354 if (this->isConstantStride ()) {
2355 fill (HES (), X, theAlpha, lclNumRows, numVecs);
2358 fill (HES (), X, theAlpha, lclNumRows, numVecs,
2359 this->whichVectors_.getRawPtr ());
2365 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2370 using Teuchos::ArrayRCP;
2371 using Teuchos::Comm;
2374 using LO = LocalOrdinal;
2375 using GO = GlobalOrdinal;
2381 TEUCHOS_TEST_FOR_EXCEPTION(
2382 ! this->isConstantStride (), std::logic_error,
2383 "Tpetra::MultiVector::replaceMap: This method does not currently work "
2384 "if the MultiVector is a column view of another MultiVector (that is, if "
2385 "isConstantStride() == false).");
2415 #ifdef HAVE_TEUCHOS_DEBUG
2429 #endif // HAVE_TEUCHOS_DEBUG
2431 if (this->getMap ().is_null ()) {
2436 TEUCHOS_TEST_FOR_EXCEPTION(
2437 newMap.is_null (), std::invalid_argument,
2438 "Tpetra::MultiVector::replaceMap: both current and new Maps are null. "
2439 "This probably means that the input Map is incorrect.");
2443 const size_t newNumRows = newMap->getNodeNumElements ();
2444 const size_t origNumRows = view_.extent (0);
2445 const size_t numCols = this->getNumVectors ();
2447 if (origNumRows != newNumRows || view_.extent (1) != numCols) {
2448 view_ = allocDualView<ST, LO, GO, Node> (newNumRows, numCols);
2451 else if (newMap.is_null ()) {
2454 const size_t newNumRows =
static_cast<size_t> (0);
2455 const size_t numCols = this->getNumVectors ();
2456 view_ = allocDualView<ST, LO, GO, Node> (newNumRows, numCols);
2459 this->map_ = newMap;
2462 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2470 const IST theAlpha =
static_cast<IST
> (alpha);
2471 if (theAlpha == Kokkos::ArithTraits<IST>::one ()) {
2474 const size_t lclNumRows = getLocalLength ();
2475 const size_t numVecs = getNumVectors ();
2476 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
2477 const std::pair<size_t, size_t> colRng (0, numVecs);
2485 const bool useHostVersion = need_sync_device ();
2486 if (useHostVersion) {
2487 auto Y_lcl = Kokkos::subview (getLocalViewHost (), rowRng, ALL ());
2488 if (isConstantStride ()) {
2489 KokkosBlas::scal (Y_lcl, theAlpha, Y_lcl);
2492 for (
size_t k = 0; k < numVecs; ++k) {
2493 const size_t Y_col = isConstantStride () ? k : whichVectors_[k];
2494 auto Y_k = Kokkos::subview (Y_lcl, ALL (), Y_col);
2495 KokkosBlas::scal (Y_k, theAlpha, Y_k);
2500 auto Y_lcl = Kokkos::subview (getLocalViewDevice (), rowRng, ALL ());
2501 if (isConstantStride ()) {
2502 KokkosBlas::scal (Y_lcl, theAlpha, Y_lcl);
2505 for (
size_t k = 0; k < numVecs; ++k) {
2506 const size_t Y_col = isConstantStride () ? k : whichVectors_[k];
2507 auto Y_k = Kokkos::subview (Y_lcl, ALL (), Y_col);
2508 KokkosBlas::scal (Y_k, theAlpha, Y_k);
2515 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2518 scale (
const Teuchos::ArrayView<const Scalar>& alphas)
2520 const size_t numVecs = this->getNumVectors ();
2521 const size_t numAlphas =
static_cast<size_t> (alphas.size ());
2522 TEUCHOS_TEST_FOR_EXCEPTION(
2523 numAlphas != numVecs, std::invalid_argument,
"Tpetra::MultiVector::"
2524 "scale: alphas.size() = " << numAlphas <<
" != this->getNumVectors() = "
2528 using k_alphas_type = Kokkos::DualView<impl_scalar_type*, device_type>;
2529 k_alphas_type k_alphas (
"alphas::tmp", numAlphas);
2530 k_alphas.modify_host ();
2531 for (
size_t i = 0; i < numAlphas; ++i) {
2534 k_alphas.sync_device ();
2536 this->scale (k_alphas.view_device ());
2539 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2542 scale (
const Kokkos::View<const impl_scalar_type*, device_type>& alphas)
2545 using Kokkos::subview;
2547 const size_t lclNumRows = this->getLocalLength ();
2548 const size_t numVecs = this->getNumVectors ();
2549 TEUCHOS_TEST_FOR_EXCEPTION(
2550 static_cast<size_t> (alphas.extent (0)) != numVecs,
2551 std::invalid_argument,
"Tpetra::MultiVector::scale(alphas): "
2552 "alphas.extent(0) = " << alphas.extent (0)
2553 <<
" != this->getNumVectors () = " << numVecs <<
".");
2554 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
2555 const std::pair<size_t, size_t> colRng (0, numVecs);
2565 const bool useHostVersion = this->need_sync_device ();
2566 if (useHostVersion) {
2569 auto alphas_h = Kokkos::create_mirror_view (alphas);
2572 auto Y_lcl = subview (this->getLocalViewHost (), rowRng, ALL ());
2573 if (isConstantStride ()) {
2574 KokkosBlas::scal (Y_lcl, alphas_h, Y_lcl);
2577 for (
size_t k = 0; k < numVecs; ++k) {
2578 const size_t Y_col = this->isConstantStride () ? k :
2579 this->whichVectors_[k];
2580 auto Y_k = subview (Y_lcl, ALL (), Y_col);
2583 KokkosBlas::scal (Y_k, alphas_h(k), Y_k);
2588 auto Y_lcl = subview (this->getLocalViewDevice (), rowRng, ALL ());
2589 if (isConstantStride ()) {
2590 KokkosBlas::scal (Y_lcl, alphas, Y_lcl);
2597 auto alphas_h = Kokkos::create_mirror_view (alphas);
2600 for (
size_t k = 0; k < numVecs; ++k) {
2601 const size_t Y_col = this->isConstantStride () ? k :
2602 this->whichVectors_[k];
2603 auto Y_k = subview (Y_lcl, ALL (), Y_col);
2604 KokkosBlas::scal (Y_k, alphas_h(k), Y_k);
2610 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2617 using Kokkos::subview;
2619 const char tfecfFuncName[] =
"scale: ";
2621 const size_t lclNumRows = getLocalLength ();
2622 const size_t numVecs = getNumVectors ();
2624 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2626 "this->getLocalLength() = " << lclNumRows <<
" != A.getLocalLength() = "
2628 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2630 "this->getNumVectors() = " << numVecs <<
" != A.getNumVectors() = "
2634 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
2635 const std::pair<size_t, size_t> colRng (0, numVecs);
2638 if (this->need_sync_device ()) {
2639 this->sync_device ();
2642 const_cast<MV&
>(A).sync_device ();
2645 this->modify_device ();
2646 auto Y_lcl_orig = this->getLocalViewDevice ();
2648 auto Y_lcl = subview (Y_lcl_orig, rowRng, ALL ());
2649 auto X_lcl = subview (X_lcl_orig, rowRng, ALL ());
2652 KokkosBlas::scal (Y_lcl, theAlpha, X_lcl);
2656 for (
size_t k = 0; k < numVecs; ++k) {
2657 const size_t Y_col = this->isConstantStride () ? k : this->whichVectors_[k];
2659 auto Y_k = subview (Y_lcl, ALL (), Y_col);
2660 auto X_k = subview (X_lcl, ALL (), X_col);
2662 KokkosBlas::scal (Y_k, theAlpha, X_k);
2669 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2675 const char tfecfFuncName[] =
"reciprocal: ";
2677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2679 "MultiVectors do not have the same local length. "
2680 "this->getLocalLength() = " << getLocalLength ()
2682 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2683 A.
getNumVectors () != this->getNumVectors (), std::runtime_error,
2684 ": MultiVectors do not have the same number of columns (vectors). "
2685 "this->getNumVectors() = " << getNumVectors ()
2686 <<
" != A.getNumVectors() = " << A.
getNumVectors () <<
".");
2688 const size_t numVecs = getNumVectors ();
2691 if (this->need_sync_device ()) {
2692 this->sync_device ();
2695 const_cast<MV&
>(A).sync_device ();
2697 this->modify_device ();
2699 auto this_view_dev = this->getLocalViewDevice ();
2703 KokkosBlas::reciprocal (this_view_dev, A_view_dev);
2707 using Kokkos::subview;
2708 for (
size_t k = 0; k < numVecs; ++k) {
2709 const size_t this_col = isConstantStride () ? k : whichVectors_[k];
2710 auto vector_k = subview (this_view_dev, ALL (), this_col);
2711 const size_t A_col = isConstantStride () ? k : A.
whichVectors_[k];
2712 auto vector_Ak = subview (A_view_dev, ALL (), A_col);
2713 KokkosBlas::reciprocal (vector_k, vector_Ak);
2718 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2724 const char tfecfFuncName[] =
"abs";
2726 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2728 ": MultiVectors do not have the same local length. "
2729 "this->getLocalLength() = " << getLocalLength ()
2731 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2732 A.
getNumVectors () != this->getNumVectors (), std::runtime_error,
2733 ": MultiVectors do not have the same number of columns (vectors). "
2734 "this->getNumVectors() = " << getNumVectors ()
2735 <<
" != A.getNumVectors() = " << A.
getNumVectors () <<
".");
2736 const size_t numVecs = getNumVectors ();
2739 if (this->need_sync_device ()) {
2740 this->sync_device ();
2743 const_cast<MV&
>(A).sync_device ();
2745 this->modify_device ();
2747 auto this_view_dev = this->getLocalViewDevice ();
2751 KokkosBlas::abs (this_view_dev, A_view_dev);
2755 using Kokkos::subview;
2757 for (
size_t k=0; k < numVecs; ++k) {
2758 const size_t this_col = isConstantStride () ? k : whichVectors_[k];
2759 auto vector_k = subview (this_view_dev, ALL (), this_col);
2760 const size_t A_col = isConstantStride () ? k : A.
whichVectors_[k];
2761 auto vector_Ak = subview (A_view_dev, ALL (), A_col);
2762 KokkosBlas::abs (vector_k, vector_Ak);
2767 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2774 const char tfecfFuncName[] =
"update: ";
2775 using Kokkos::subview;
2781 const size_t lclNumRows = getLocalLength ();
2782 const size_t numVecs = getNumVectors ();
2784 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2786 "this->getLocalLength() = " << lclNumRows <<
" != A.getLocalLength() = "
2788 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2790 "this->getNumVectors() = " << numVecs <<
" != A.getNumVectors() = "
2794 if (this->need_sync_device ()) {
2795 this->sync_device ();
2798 const_cast<MV&
>(A).sync_device ();
2803 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
2804 const std::pair<size_t, size_t> colRng (0, numVecs);
2806 auto Y_lcl_orig = this->getLocalViewDevice ();
2807 auto Y_lcl = subview (Y_lcl_orig, rowRng, Kokkos::ALL ());
2809 auto X_lcl = subview (X_lcl_orig, rowRng, Kokkos::ALL ());
2812 this->modify_device ();
2814 KokkosBlas::axpby (theAlpha, X_lcl, theBeta, Y_lcl);
2818 for (
size_t k = 0; k < numVecs; ++k) {
2819 const size_t Y_col = this->isConstantStride () ? k : this->whichVectors_[k];
2821 auto Y_k = subview (Y_lcl, ALL (), Y_col);
2822 auto X_k = subview (X_lcl, ALL (), X_col);
2824 KokkosBlas::axpby (theAlpha, X_k, theBeta, Y_k);
2829 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2836 const Scalar& gamma)
2839 using Kokkos::subview;
2842 const char tfecfFuncName[] =
"update(alpha,A,beta,B,gamma): ";
2846 const size_t lclNumRows = this->getLocalLength ();
2847 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2849 "The input MultiVector A has " << A.
getLocalLength () <<
" local "
2850 "row(s), but this MultiVector has " << lclNumRows <<
" local "
2852 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2854 "The input MultiVector B has " << B.
getLocalLength () <<
" local "
2855 "row(s), but this MultiVector has " << lclNumRows <<
" local "
2857 const size_t numVecs = getNumVectors ();
2858 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2860 "The input MultiVector A has " << A.
getNumVectors () <<
" column(s), "
2861 "but this MultiVector has " << numVecs <<
" column(s).");
2862 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2864 "The input MultiVector B has " << B.
getNumVectors () <<
" column(s), "
2865 "but this MultiVector has " << numVecs <<
" column(s).");
2872 if (this->need_sync_device ()) this->sync_device ();
2877 this->modify_device ();
2879 const std::pair<size_t, size_t> rowRng (0, lclNumRows);
2880 const std::pair<size_t, size_t> colRng (0, numVecs);
2885 auto C_lcl = subview (this->getLocalViewDevice (), rowRng, ALL ());
2890 KokkosBlas::update (theAlpha, A_lcl, theBeta, B_lcl, theGamma, C_lcl);
2895 for (
size_t k = 0; k < numVecs; ++k) {
2896 const size_t this_col = isConstantStride () ? k : whichVectors_[k];
2899 KokkosBlas::update (theAlpha, subview (A_lcl, rowRng, A_col),
2900 theBeta, subview (B_lcl, rowRng, B_col),
2901 theGamma, subview (C_lcl, rowRng, this_col));
2906 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2907 Teuchos::ArrayRCP<const Scalar>
2914 const char tfecfFuncName[] =
"getData: ";
2920 const_cast<MV*
> (
this)->sync_host ();
2922 auto hostView = getLocalViewHost ();
2923 const size_t col = isConstantStride () ? j : whichVectors_[j];
2924 auto hostView_j = Kokkos::subview (hostView, ALL (), col);
2925 Teuchos::ArrayRCP<const IST> dataAsArcp =
2926 Kokkos::Compat::persistingView (hostView_j, 0, getLocalLength ());
2928 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2929 (static_cast<size_t> (hostView_j.extent (0)) <
2930 static_cast<size_t> (dataAsArcp.size ()), std::logic_error,
2931 "hostView_j.extent(0) = " << hostView_j.extent (0)
2932 <<
" < dataAsArcp.size() = " << dataAsArcp.size () <<
". "
2933 "Please report this bug to the Tpetra developers.");
2935 return Teuchos::arcp_reinterpret_cast<
const Scalar> (dataAsArcp);
2938 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2939 Teuchos::ArrayRCP<Scalar>
2944 using Kokkos::subview;
2947 const char tfecfFuncName[] =
"getDataNonConst: ";
2953 const_cast<MV*
> (
this)->sync_host ();
2958 auto hostView = getLocalViewHost ();
2959 const size_t col = isConstantStride () ? j : whichVectors_[j];
2960 auto hostView_j = subview (hostView, ALL (), col);
2961 Teuchos::ArrayRCP<IST> dataAsArcp =
2962 Kokkos::Compat::persistingView (hostView_j, 0, getLocalLength ());
2964 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2965 (static_cast<size_t> (hostView_j.extent (0)) <
2966 static_cast<size_t> (dataAsArcp.size ()), std::logic_error,
2967 "hostView_j.extent(0) = " << hostView_j.extent (0)
2968 <<
" < dataAsArcp.size() = " << dataAsArcp.size () <<
". "
2969 "Please report this bug to the Tpetra developers.");
2971 return Teuchos::arcp_reinterpret_cast<Scalar> (dataAsArcp);
2974 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2975 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
2977 subCopy (
const Teuchos::ArrayView<const size_t>& cols)
const
2984 bool contiguous =
true;
2985 const size_t numCopyVecs =
static_cast<size_t> (cols.size ());
2986 for (
size_t j = 1; j < numCopyVecs; ++j) {
2987 if (cols[j] != cols[j-1] + static_cast<size_t> (1)) {
2992 if (contiguous && numCopyVecs > 0) {
2993 return this->subCopy (Teuchos::Range1D (cols[0], cols[numCopyVecs-1]));
2996 RCP<const MV> X_sub = this->subView (cols);
2997 RCP<MV> Y (
new MV (this->getMap (), numCopyVecs,
false));
3003 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3004 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3011 RCP<const MV> X_sub = this->subView (colRng);
3012 RCP<MV> Y (
new MV (this->getMap (), static_cast<size_t> (colRng.size ()),
false));
3017 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3021 return origView_.extent (0);
3024 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3028 return origView_.extent (1);
3031 template <
class Scalar,
class LO,
class GO,
class Node>
3034 const Teuchos::RCP<const map_type>& subMap,
3039 using Kokkos::subview;
3040 using Teuchos::outArg;
3043 using Teuchos::reduceAll;
3044 using Teuchos::REDUCE_MIN;
3047 const char prefix[] =
"Tpetra::MultiVector constructor (offsetView): ";
3048 const char suffix[] =
"Please report this bug to the Tpetra developers.";
3051 std::unique_ptr<std::ostringstream> errStrm;
3058 const auto comm = subMap->getComm ();
3059 TEUCHOS_ASSERT( ! comm.is_null () );
3060 const int myRank = comm->getRank ();
3062 const LO lclNumRowsBefore =
static_cast<LO
> (X.
getLocalLength ());
3064 const LO newNumRows =
static_cast<LO
> (subMap->getNodeNumElements ());
3066 std::ostringstream os;
3067 os <<
"Proc " << myRank <<
": " << prefix
3068 <<
"X: {lclNumRows: " << lclNumRowsBefore
3070 <<
", numCols: " << numCols <<
"}, "
3071 <<
"subMap: {lclNumRows: " << newNumRows <<
"}" << endl;
3072 std::cerr << os.str ();
3077 const bool tooManyElts =
3080 errStrm = std::unique_ptr<std::ostringstream> (
new std::ostringstream);
3081 *errStrm <<
" Proc " << myRank <<
": subMap->getNodeNumElements() (="
3082 << newNumRows <<
") + rowOffset (=" << rowOffset
3086 TEUCHOS_TEST_FOR_EXCEPTION
3087 (! debug && tooManyElts, std::invalid_argument,
3088 prefix << errStrm->str () << suffix);
3092 reduceAll<int, int> (*comm, REDUCE_MIN, lclGood, outArg (gblGood));
3094 std::ostringstream gblErrStrm;
3095 const std::string myErrStr =
3096 errStrm.get () !=
nullptr ? errStrm->str () : std::string (
"");
3097 ::Tpetra::Details::gathervPrint (gblErrStrm, myErrStr, *comm);
3098 TEUCHOS_TEST_FOR_EXCEPTION
3099 (
true, std::invalid_argument, gblErrStrm.str ());
3103 using range_type = std::pair<LO, LO>;
3104 const range_type origRowRng
3105 (rowOffset, static_cast<LO> (X.
origView_.extent (0)));
3106 const range_type rowRng
3107 (rowOffset, rowOffset + newNumRows);
3109 dual_view_type newOrigView = subview (X.
origView_, origRowRng, ALL ());
3120 dual_view_type newView =
3121 subview (rowOffset == 0 ? X.
origView_ : X.
view_, rowRng, ALL ());
3128 if (newOrigView.extent (0) == 0 &&
3129 newOrigView.extent (1) != X.
origView_.extent (1)) {
3131 allocDualView<Scalar, LO, GO, Node> (0, X.
getNumVectors ());
3133 if (newView.extent (0) == 0 &&
3134 newView.extent (1) != X.
view_.extent (1)) {
3136 allocDualView<Scalar, LO, GO, Node> (0, X.
getNumVectors ());
3140 MV (subMap, newView, newOrigView) :
3144 const LO lclNumRowsRet =
static_cast<LO
> (subViewMV.getLocalLength ());
3145 const LO numColsRet =
static_cast<LO
> (subViewMV.getNumVectors ());
3146 if (newNumRows != lclNumRowsRet || numCols != numColsRet) {
3148 if (errStrm.get () ==
nullptr) {
3149 errStrm = std::unique_ptr<std::ostringstream> (
new std::ostringstream);
3151 *errStrm <<
" Proc " << myRank <<
3152 ": subMap.getNodeNumElements(): " << newNumRows <<
3153 ", subViewMV.getLocalLength(): " << lclNumRowsRet <<
3154 ", X.getNumVectors(): " << numCols <<
3155 ", subViewMV.getNumVectors(): " << numColsRet << endl;
3157 reduceAll<int, int> (*comm, REDUCE_MIN, lclGood, outArg (gblGood));
3159 std::ostringstream gblErrStrm;
3161 gblErrStrm << prefix <<
"Returned MultiVector has the wrong local "
3162 "dimensions on one or more processes:" << endl;
3164 const std::string myErrStr =
3165 errStrm.get () !=
nullptr ? errStrm->str () : std::string (
"");
3166 ::Tpetra::Details::gathervPrint (gblErrStrm, myErrStr, *comm);
3167 gblErrStrm << suffix << endl;
3168 TEUCHOS_TEST_FOR_EXCEPTION
3169 (
true, std::invalid_argument, gblErrStrm.str ());
3174 std::ostringstream os;
3175 os <<
"Proc " << myRank <<
": " << prefix <<
"Call op=" << endl;
3176 std::cerr << os.str ();
3182 std::ostringstream os;
3183 os <<
"Proc " << myRank <<
": " << prefix <<
"Done!" << endl;
3184 std::cerr << os.str ();
3188 template <
class Scalar,
class LO,
class GO,
class Node>
3192 const size_t rowOffset) :
3197 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3198 Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3201 const size_t offset)
const
3204 return Teuchos::rcp (
new MV (*
this, *subMap, offset));
3207 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3208 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3211 const size_t offset)
3214 return Teuchos::rcp (
new MV (*
this, *subMap, offset));
3217 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3218 Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3220 subView (
const Teuchos::ArrayView<const size_t>& cols)
const
3222 using Teuchos::Array;
3226 const size_t numViewCols =
static_cast<size_t> (cols.size ());
3227 TEUCHOS_TEST_FOR_EXCEPTION(
3228 numViewCols < 1, std::runtime_error,
"Tpetra::MultiVector::subView"
3229 "(const Teuchos::ArrayView<const size_t>&): The input array cols must "
3230 "contain at least one entry, but cols.size() = " << cols.size ()
3235 bool contiguous =
true;
3236 for (
size_t j = 1; j < numViewCols; ++j) {
3237 if (cols[j] != cols[j-1] + static_cast<size_t> (1)) {
3243 if (numViewCols == 0) {
3245 return rcp (
new MV (this->getMap (), numViewCols));
3248 return this->subView (Teuchos::Range1D (cols[0], cols[numViewCols-1]));
3252 if (isConstantStride ()) {
3253 return rcp (
new MV (this->getMap (), view_, origView_, cols));
3256 Array<size_t> newcols (cols.size ());
3257 for (
size_t j = 0; j < numViewCols; ++j) {
3258 newcols[j] = whichVectors_[cols[j]];
3260 return rcp (
new MV (this->getMap (), view_, origView_, newcols ()));
3265 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3266 Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3270 using ::Tpetra::Details::Behavior;
3272 using Kokkos::subview;
3273 using Teuchos::Array;
3277 const char tfecfFuncName[] =
"subView(Range1D): ";
3279 const size_t lclNumRows = this->getLocalLength ();
3280 const size_t numVecs = this->getNumVectors ();
3284 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3285 static_cast<size_t> (colRng.size ()) > numVecs, std::runtime_error,
3286 "colRng.size() = " << colRng.size () <<
" > this->getNumVectors() = "
3288 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3289 numVecs != 0 && colRng.size () != 0 &&
3290 (colRng.lbound () <
static_cast<Teuchos::Ordinal
> (0) ||
3291 static_cast<size_t> (colRng.ubound ()) >= numVecs),
3292 std::invalid_argument,
"Nonempty input range [" << colRng.lbound () <<
3293 "," << colRng.ubound () <<
"] exceeds the valid range of column indices "
3294 "[0, " << numVecs <<
"].");
3296 RCP<const MV> X_ret;
3306 const std::pair<size_t, size_t> rows (0, lclNumRows);
3307 if (colRng.size () == 0) {
3308 const std::pair<size_t, size_t> cols (0, 0);
3309 dual_view_type X_sub = takeSubview (this->view_, ALL (), cols);
3310 X_ret = rcp (
new MV (this->getMap (), X_sub, origView_));
3314 if (isConstantStride ()) {
3315 const std::pair<size_t, size_t> cols (colRng.lbound (),
3316 colRng.ubound () + 1);
3317 dual_view_type X_sub = takeSubview (this->view_, ALL (), cols);
3318 X_ret = rcp (
new MV (this->getMap (), X_sub, origView_));
3321 if (static_cast<size_t> (colRng.size ()) == static_cast<size_t> (1)) {
3324 const std::pair<size_t, size_t> col (whichVectors_[0] + colRng.lbound (),
3325 whichVectors_[0] + colRng.ubound () + 1);
3326 dual_view_type X_sub = takeSubview (view_, ALL (), col);
3327 X_ret = rcp (
new MV (this->getMap (), X_sub, origView_));
3330 Array<size_t> which (whichVectors_.begin () + colRng.lbound (),
3331 whichVectors_.begin () + colRng.ubound () + 1);
3332 X_ret = rcp (
new MV (this->getMap (), view_, origView_, which));
3337 const bool debug = Behavior::debug ();
3339 using Teuchos::Comm;
3340 using Teuchos::outArg;
3341 using Teuchos::REDUCE_MIN;
3342 using Teuchos::reduceAll;
3344 RCP<const Comm<int> > comm = this->getMap ().is_null () ?
3345 Teuchos::null : this->getMap ()->getComm ();
3346 if (! comm.is_null ()) {
3350 if (X_ret.is_null ()) {
3353 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3354 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3355 (lclSuccess != 1, std::logic_error,
"X_ret (the subview of this "
3356 "MultiVector; the return value of this method) is null on some MPI "
3357 "process in this MultiVector's communicator. This should never "
3358 "happen. Please report this bug to the Tpetra developers.");
3359 if (! X_ret.is_null () &&
3360 X_ret->getNumVectors () !=
static_cast<size_t> (colRng.size ())) {
3363 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
3364 outArg (gblSuccess));
3365 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3366 (lclSuccess != 1, std::logic_error,
"X_ret->getNumVectors() != "
3367 "colRng.size(), on at least one MPI process in this MultiVector's "
3368 "communicator. This should never happen. "
3369 "Please report this bug to the Tpetra developers.");
3376 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3377 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3382 return Teuchos::rcp_const_cast<MV> (this->subView (cols));
3386 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3387 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3392 return Teuchos::rcp_const_cast<MV> (this->subView (colRng));
3396 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3402 using Kokkos::subview;
3403 typedef std::pair<size_t, size_t> range_type;
3404 const char tfecfFuncName[] =
"MultiVector(const MultiVector&, const size_t): ";
3407 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3408 (j >= numCols, std::invalid_argument,
"Input index j (== " << j
3409 <<
") exceeds valid column index range [0, " << numCols <<
" - 1].");
3411 static_cast<size_t> (j) :
3413 this->
view_ = takeSubview (X.
view_, Kokkos::ALL (), range_type (jj, jj+1));
3425 const size_t newSize = X.
imports_.extent (0) / numCols;
3427 newImports.d_view = subview (X.
imports_.d_view, range_type (0, newSize));
3428 newImports.h_view = subview (X.
imports_.h_view, range_type (0, newSize));
3431 const size_t newSize = X.
exports_.extent (0) / numCols;
3433 newExports.d_view = subview (X.
exports_.d_view, range_type (0, newSize));
3434 newExports.h_view = subview (X.
exports_.h_view, range_type (0, newSize));
3444 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3445 Teuchos::RCP<const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3450 return Teuchos::rcp (
new V (*
this, j));
3454 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3455 Teuchos::RCP<Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3460 return Teuchos::rcp (
new V (*
this, j));
3464 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3467 get1dCopy (
const Teuchos::ArrayView<Scalar>& A,
const size_t LDA)
const
3469 using dev_view_type =
typename dual_view_type::t_dev;
3470 using host_view_type =
typename dual_view_type::t_host;
3472 using input_view_type = Kokkos::View<IST**, Kokkos::LayoutLeft,
3474 Kokkos::MemoryUnmanaged>;
3475 const char tfecfFuncName[] =
"get1dCopy: ";
3477 const size_t numRows = this->getLocalLength ();
3478 const size_t numCols = this->getNumVectors ();
3480 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3481 (LDA < numRows, std::runtime_error,
3482 "LDA = " << LDA <<
" < numRows = " << numRows <<
".");
3483 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3484 (numRows >
size_t (0) && numCols >
size_t (0) &&
3485 size_t (A.size ()) < LDA * (numCols - 1) + numRows,
3487 "A.size() = " << A.size () <<
", but its size must be at least "
3488 << (LDA * (numCols - 1) + numRows) <<
" to hold all the entries.");
3490 const std::pair<size_t, size_t> rowRange (0, numRows);
3491 const std::pair<size_t, size_t> colRange (0, numCols);
3493 input_view_type A_view_orig (reinterpret_cast<IST*> (A.getRawPtr ()),
3495 auto A_view = Kokkos::subview (A_view_orig, rowRange, colRange);
3502 const bool useHostVersion = this->need_sync_device ();
3504 dev_view_type srcView_dev;
3505 host_view_type srcView_host;
3506 if (useHostVersion) {
3507 srcView_host = this->getLocalViewHost ();
3510 srcView_dev = this->getLocalViewDevice ();
3513 if (this->isConstantStride ()) {
3514 if (useHostVersion) {
3522 for (
size_t j = 0; j < numCols; ++j) {
3523 const size_t srcCol = this->whichVectors_[j];
3524 auto dstColView = Kokkos::subview (A_view, rowRange, j);
3526 if (useHostVersion) {
3527 auto srcColView_host = Kokkos::subview (srcView_host, rowRange, srcCol);
3531 auto srcColView_dev = Kokkos::subview (srcView_dev, rowRange, srcCol);
3539 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3542 get2dCopy (
const Teuchos::ArrayView<
const Teuchos::ArrayView<Scalar> >& ArrayOfPtrs)
const
3545 const char tfecfFuncName[] =
"get2dCopy: ";
3546 const size_t numRows = this->getLocalLength ();
3547 const size_t numCols = this->getNumVectors ();
3549 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3550 static_cast<size_t> (ArrayOfPtrs.size ()) != numCols,
3551 std::runtime_error,
"Input array of pointers must contain as many "
3552 "entries (arrays) as the MultiVector has columns. ArrayOfPtrs.size() = "
3553 << ArrayOfPtrs.size () <<
" != getNumVectors() = " << numCols <<
".");
3555 if (numRows != 0 && numCols != 0) {
3557 for (
size_t j = 0; j < numCols; ++j) {
3558 const size_t dstLen =
static_cast<size_t> (ArrayOfPtrs[j].size ());
3559 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3560 dstLen < numRows, std::invalid_argument,
"Array j = " << j <<
" of "
3561 "the input array of arrays is not long enough to fit all entries in "
3562 "that column of the MultiVector. ArrayOfPtrs[j].size() = " << dstLen
3563 <<
" < getLocalLength() = " << numRows <<
".");
3567 for (
size_t j = 0; j < numCols; ++j) {
3568 Teuchos::RCP<const V> X_j = this->getVector (j);
3569 const size_t LDA =
static_cast<size_t> (ArrayOfPtrs[j].size ());
3570 X_j->get1dCopy (ArrayOfPtrs[j], LDA);
3576 template <
class SC,
class LO,
class GO,
class NT>
3579 const bool markModified)
3596 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3597 Teuchos::ArrayRCP<const Scalar>
3601 if (getLocalLength () == 0 || getNumVectors () == 0) {
3602 return Teuchos::null;
3604 TEUCHOS_TEST_FOR_EXCEPTION(
3605 ! isConstantStride (), std::runtime_error,
"Tpetra::MultiVector::"
3606 "get1dView: This MultiVector does not have constant stride, so it is "
3607 "not possible to view its data as a single array. You may check "
3608 "whether a MultiVector has constant stride by calling "
3609 "isConstantStride().");
3613 constexpr
bool markModified =
false;
3615 auto X_lcl = syncMVToHostIfNeededAndGetHostView (const_cast<MV&> (*
this),
3617 Teuchos::ArrayRCP<const impl_scalar_type> dataAsArcp =
3618 Kokkos::Compat::persistingView (X_lcl);
3619 return Teuchos::arcp_reinterpret_cast<
const Scalar> (dataAsArcp);
3623 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3624 Teuchos::ArrayRCP<Scalar>
3628 if (this->getLocalLength () == 0 || this->getNumVectors () == 0) {
3629 return Teuchos::null;
3632 TEUCHOS_TEST_FOR_EXCEPTION
3633 (! isConstantStride (), std::runtime_error,
"Tpetra::MultiVector::"
3634 "get1dViewNonConst: This MultiVector does not have constant stride, "
3635 "so it is not possible to view its data as a single array. You may "
3636 "check whether a MultiVector has constant stride by calling "
3637 "isConstantStride().");
3638 constexpr
bool markModified =
true;
3639 auto X_lcl = syncMVToHostIfNeededAndGetHostView (*
this, markModified);
3640 Teuchos::ArrayRCP<impl_scalar_type> dataAsArcp =
3641 Kokkos::Compat::persistingView (X_lcl);
3642 return Teuchos::arcp_reinterpret_cast<Scalar> (dataAsArcp);
3646 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3647 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> >
3651 constexpr
bool markModified =
true;
3652 auto X_lcl = syncMVToHostIfNeededAndGetHostView (*
this, markModified);
3658 const size_t myNumRows = this->getLocalLength ();
3659 const size_t numCols = this->getNumVectors ();
3660 const Kokkos::pair<size_t, size_t> rowRange (0, myNumRows);
3662 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > views (numCols);
3663 for (
size_t j = 0; j < numCols; ++j) {
3664 const size_t col = this->isConstantStride () ? j : this->whichVectors_[j];
3665 auto X_lcl_j = Kokkos::subview (X_lcl, rowRange, col);
3666 Teuchos::ArrayRCP<impl_scalar_type> X_lcl_j_arcp =
3667 Kokkos::Compat::persistingView (X_lcl_j);
3668 views[j] = Teuchos::arcp_reinterpret_cast<Scalar> (X_lcl_j_arcp);
3673 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3674 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> >
3681 constexpr
bool markModified =
false;
3683 auto X_lcl = syncMVToHostIfNeededAndGetHostView (const_cast<MV&> (*
this),
3689 const size_t myNumRows = this->getLocalLength ();
3690 const size_t numCols = this->getNumVectors ();
3691 const Kokkos::pair<size_t, size_t> rowRange (0, myNumRows);
3693 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > views (numCols);
3694 for (
size_t j = 0; j < numCols; ++j) {
3695 const size_t col = this->isConstantStride () ? j : this->whichVectors_[j];
3696 auto X_lcl_j = Kokkos::subview (X_lcl, rowRange, col);
3697 Teuchos::ArrayRCP<const impl_scalar_type> X_lcl_j_arcp =
3698 Kokkos::Compat::persistingView (X_lcl_j);
3699 views[j] = Teuchos::arcp_reinterpret_cast<
const Scalar> (X_lcl_j_arcp);
3704 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3708 Teuchos::ETransp transB,
3709 const Scalar& alpha,
3714 using ::Tpetra::Details::ProfilingRegion;
3715 using Teuchos::CONJ_TRANS;
3716 using Teuchos::NO_TRANS;
3717 using Teuchos::TRANS;
3720 using Teuchos::rcpFromRef;
3722 using ATS = Kokkos::ArithTraits<impl_scalar_type>;
3724 using STS = Teuchos::ScalarTraits<Scalar>;
3726 const char tfecfFuncName[] =
"multiply: ";
3727 ProfilingRegion region (
"Tpetra::MV::multiply");
3759 const bool C_is_local = ! this->isDistributed ();
3769 auto myMap = this->getMap ();
3770 if (! myMap.is_null () && ! myMap->getComm ().is_null ()) {
3771 using Teuchos::REDUCE_MIN;
3772 using Teuchos::reduceAll;
3773 using Teuchos::outArg;
3775 auto comm = myMap->getComm ();
3776 const size_t A_nrows =
3778 const size_t A_ncols =
3780 const size_t B_nrows =
3782 const size_t B_ncols =
3785 const bool lclBad = this->getLocalLength () != A_nrows ||
3786 this->getNumVectors () != B_ncols || A_ncols != B_nrows;
3788 const int myRank = comm->getRank ();
3789 std::ostringstream errStrm;
3790 if (this->getLocalLength () != A_nrows) {
3791 errStrm <<
"Proc " << myRank <<
": this->getLocalLength()="
3792 << this->getLocalLength () <<
" != A_nrows=" << A_nrows
3793 <<
"." << std::endl;
3795 if (this->getNumVectors () != B_ncols) {
3796 errStrm <<
"Proc " << myRank <<
": this->getNumVectors()="
3797 << this->getNumVectors () <<
" != B_ncols=" << B_ncols
3798 <<
"." << std::endl;
3800 if (A_ncols != B_nrows) {
3801 errStrm <<
"Proc " << myRank <<
": A_ncols="
3802 << A_ncols <<
" != B_nrows=" << B_nrows
3803 <<
"." << std::endl;
3806 const int lclGood = lclBad ? 0 : 1;
3808 reduceAll<int, int> (*comm, REDUCE_MIN, lclGood, outArg (gblGood));
3810 std::ostringstream os;
3811 ::Tpetra::Details::gathervPrint (os, errStrm.str (), *comm);
3813 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3814 (
true, std::runtime_error,
"Inconsistent local dimensions on at "
3815 "least one process in this object's communicator." << std::endl
3817 <<
"C(" << (C_is_local ?
"local" :
"distr") <<
") = "
3819 << (transA == Teuchos::TRANS ?
"^T" :
3820 (transA == Teuchos::CONJ_TRANS ?
"^H" :
""))
3821 <<
"(" << (A_is_local ?
"local" :
"distr") <<
") * "
3823 << (transA == Teuchos::TRANS ?
"^T" :
3824 (transA == Teuchos::CONJ_TRANS ?
"^H" :
""))
3825 <<
"(" << (B_is_local ?
"local" :
"distr") <<
")." << std::endl
3826 <<
"Global dimensions: C(" << this->getGlobalLength () <<
", "
3836 const bool Case1 = C_is_local && A_is_local && B_is_local;
3838 const bool Case2 = C_is_local && ! A_is_local && ! B_is_local &&
3839 transA != NO_TRANS &&
3842 const bool Case3 = ! C_is_local && ! A_is_local && B_is_local &&
3846 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3847 (! Case1 && ! Case2 && ! Case3, std::runtime_error,
3848 "Multiplication of op(A) and op(B) into *this is not a "
3849 "supported use case.");
3851 if (beta != STS::zero () && Case2) {
3857 const int myRank = this->getMap ()->getComm ()->getRank ();
3859 beta_local = ATS::zero ();
3868 if (! isConstantStride ()) {
3869 C_tmp = rcp (
new MV (*
this, Teuchos::Copy));
3871 C_tmp = rcp (
this,
false);
3874 RCP<const MV> A_tmp;
3876 A_tmp = rcp (
new MV (A, Teuchos::Copy));
3878 A_tmp = rcpFromRef (A);
3881 RCP<const MV> B_tmp;
3883 B_tmp = rcp (
new MV (B, Teuchos::Copy));
3885 B_tmp = rcpFromRef (B);
3888 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3889 (! C_tmp->isConstantStride () || ! B_tmp->isConstantStride () ||
3890 ! A_tmp->isConstantStride (), std::logic_error,
3891 "Failed to make temporary constant-stride copies of MultiVectors.");
3894 if (A_tmp->need_sync_device ()) {
3895 const_cast<MV&
> (*A_tmp).sync_device ();
3897 const LO A_lclNumRows = A_tmp->getLocalLength ();
3898 const LO A_numVecs = A_tmp->getNumVectors ();
3899 auto A_lcl = A_tmp->getLocalViewDevice ();
3900 auto A_sub = Kokkos::subview (A_lcl,
3901 std::make_pair (LO (0), A_lclNumRows),
3902 std::make_pair (LO (0), A_numVecs));
3904 if (B_tmp->need_sync_device ()) {
3905 const_cast<MV&
> (*B_tmp).sync_device ();
3907 const LO B_lclNumRows = B_tmp->getLocalLength ();
3908 const LO B_numVecs = B_tmp->getNumVectors ();
3909 auto B_lcl = B_tmp->getLocalViewDevice ();
3910 auto B_sub = Kokkos::subview (B_lcl,
3911 std::make_pair (LO (0), B_lclNumRows),
3912 std::make_pair (LO (0), B_numVecs));
3914 if (C_tmp->need_sync_device ()) {
3915 const_cast<MV&
> (*C_tmp).sync_device ();
3917 const LO C_lclNumRows = C_tmp->getLocalLength ();
3918 const LO C_numVecs = C_tmp->getNumVectors ();
3919 auto C_lcl = C_tmp->getLocalViewDevice ();
3920 auto C_sub = Kokkos::subview (C_lcl,
3921 std::make_pair (LO (0), C_lclNumRows),
3922 std::make_pair (LO (0), C_numVecs));
3923 const char ctransA = (transA == Teuchos::NO_TRANS ?
'N' :
3924 (transA == Teuchos::TRANS ?
'T' :
'C'));
3925 const char ctransB = (transB == Teuchos::NO_TRANS ?
'N' :
3926 (transB == Teuchos::TRANS ?
'T' :
'C'));
3929 ProfilingRegion regionGemm (
"Tpetra::MV::multiply-call-gemm");
3930 KokkosBlas::gemm (&ctransA, &ctransB, alpha_IST, A_sub, B_sub,
3934 if (! isConstantStride ()) {
3939 A_tmp = Teuchos::null;
3940 B_tmp = Teuchos::null;
3948 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3957 using Kokkos::subview;
3960 const char tfecfFuncName[] =
"elementWiseMultiply: ";
3962 const size_t lclNumRows = this->getLocalLength ();
3963 const size_t numVecs = this->getNumVectors ();
3965 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3967 std::runtime_error,
"MultiVectors do not have the same local length.");
3968 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3969 numVecs != B.
getNumVectors (), std::runtime_error,
"this->getNumVectors"
3970 "() = " << numVecs <<
" != B.getNumVectors() = " << B.
getNumVectors ()
3974 if (this->need_sync_device ()) {
3975 this->sync_device ();
3978 const_cast<V&
>(A).sync_device ();
3981 const_cast<MV&
>(B).sync_device ();
3983 this->modify_device ();
3985 auto this_view = this->getLocalViewDevice ();
3995 KokkosBlas::mult (scalarThis,
3998 subview (A_view, ALL (), 0),
4002 for (
size_t j = 0; j < numVecs; ++j) {
4003 const size_t C_col = isConstantStride () ? j : whichVectors_[j];
4005 KokkosBlas::mult (scalarThis,
4006 subview (this_view, ALL (), C_col),
4008 subview (A_view, ALL (), 0),
4009 subview (B_view, ALL (), B_col));
4014 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4020 using ::Tpetra::Details::ProfilingRegion;
4021 ProfilingRegion region (
"Tpetra::MV::reduce");
4023 const auto map = this->getMap ();
4024 if (map.get () ==
nullptr) {
4027 const auto comm = map->getComm ();
4028 if (comm.get () ==
nullptr) {
4034 const bool changed_on_device = this->need_sync_host ();
4035 if (changed_on_device) {
4039 this->modify_device ();
4040 auto X_lcl = this->getLocalViewDevice ();
4044 this->modify_host ();
4045 auto X_lcl = this->getLocalViewHost ();
4050 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4057 #ifdef HAVE_TPETRA_DEBUG
4058 const LocalOrdinal minLocalIndex = this->getMap()->getMinLocalIndex();
4059 const LocalOrdinal maxLocalIndex = this->getMap()->getMaxLocalIndex();
4060 TEUCHOS_TEST_FOR_EXCEPTION(
4061 lclRow < minLocalIndex || lclRow > maxLocalIndex,
4063 "Tpetra::MultiVector::replaceLocalValue: row index " << lclRow
4064 <<
" is invalid. The range of valid row indices on this process "
4065 << this->getMap()->getComm()->getRank() <<
" is [" << minLocalIndex
4066 <<
", " << maxLocalIndex <<
"].");
4067 TEUCHOS_TEST_FOR_EXCEPTION(
4068 vectorIndexOutOfRange(col),
4070 "Tpetra::MultiVector::replaceLocalValue: vector index " << col
4071 <<
" of the multivector is invalid.");
4073 const size_t colInd = isConstantStride () ? col : whichVectors_[col];
4074 view_.h_view (lclRow, colInd) = ScalarValue;
4078 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4084 const bool atomic)
const
4086 #ifdef HAVE_TPETRA_DEBUG
4087 const LocalOrdinal minLocalIndex = this->getMap()->getMinLocalIndex();
4088 const LocalOrdinal maxLocalIndex = this->getMap()->getMaxLocalIndex();
4089 TEUCHOS_TEST_FOR_EXCEPTION(
4090 lclRow < minLocalIndex || lclRow > maxLocalIndex,
4092 "Tpetra::MultiVector::sumIntoLocalValue: row index " << lclRow
4093 <<
" is invalid. The range of valid row indices on this process "
4094 << this->getMap()->getComm()->getRank() <<
" is [" << minLocalIndex
4095 <<
", " << maxLocalIndex <<
"].");
4096 TEUCHOS_TEST_FOR_EXCEPTION(
4097 vectorIndexOutOfRange(col),
4099 "Tpetra::MultiVector::sumIntoLocalValue: vector index " << col
4100 <<
" of the multivector is invalid.");
4102 const size_t colInd = isConstantStride () ? col : whichVectors_[col];
4104 Kokkos::atomic_add (& (view_.h_view(lclRow, colInd)), value);
4107 view_.h_view (lclRow, colInd) += value;
4112 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4121 const LocalOrdinal lclRow = this->map_->getLocalElement (gblRow);
4122 #ifdef HAVE_TPETRA_DEBUG
4123 const char tfecfFuncName[] =
"replaceGlobalValue: ";
4124 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4125 (lclRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid (),
4127 "Global row index " << gblRow <<
" is not present on this process "
4128 << this->getMap ()->getComm ()->getRank () <<
".");
4129 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4130 (this->vectorIndexOutOfRange (col), std::runtime_error,
4131 "Vector index " << col <<
" of the MultiVector is invalid.");
4132 #endif // HAVE_TPETRA_DEBUG
4133 this->replaceLocalValue (lclRow, col, ScalarValue);
4136 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4142 const bool atomic)
const
4146 const LocalOrdinal lclRow = this->map_->getLocalElement (globalRow);
4147 #ifdef HAVE_TEUCHOS_DEBUG
4148 TEUCHOS_TEST_FOR_EXCEPTION(
4149 lclRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid (),
4151 "Tpetra::MultiVector::sumIntoGlobalValue: Global row index " << globalRow
4152 <<
" is not present on this process "
4153 << this->getMap ()->getComm ()->getRank () <<
".");
4154 TEUCHOS_TEST_FOR_EXCEPTION(
4155 vectorIndexOutOfRange(col),
4157 "Tpetra::MultiVector::sumIntoGlobalValue: Vector index " << col
4158 <<
" of the multivector is invalid.");
4160 this->sumIntoLocalValue (lclRow, col, value, atomic);
4163 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4165 Teuchos::ArrayRCP<T>
4171 typename dual_view_type::array_layout,
4173 const size_t col = isConstantStride () ? j : whichVectors_[j];
4174 col_dual_view_type X_col =
4175 Kokkos::subview (view_, Kokkos::ALL (), col);
4176 return Kokkos::Compat::persistingView (X_col.d_view);
4179 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
4180 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4187 #endif // TPETRA_ENABLE_DEPRECATED_CODE
4189 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4193 view_.clear_sync_state ();
4196 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4203 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4207 view_.sync_device ();
4210 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4214 return view_.need_sync_host ();
4217 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4221 return view_.need_sync_device ();
4224 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4228 view_.modify_device ();
4231 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4235 view_.modify_host ();
4238 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4242 return view_.view_device ();
4245 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4249 return view_.view_host ();
4252 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4257 using Teuchos::TypeNameTraits;
4259 std::ostringstream out;
4260 out <<
"\"" << className <<
"\": {";
4261 out <<
"Template parameters: {Scalar: " << TypeNameTraits<Scalar>::name ()
4262 <<
", LocalOrdinal: " << TypeNameTraits<LocalOrdinal>::name ()
4263 <<
", GlobalOrdinal: " << TypeNameTraits<GlobalOrdinal>::name ()
4264 <<
", Node" << Node::name ()
4266 if (this->getObjectLabel () !=
"") {
4267 out <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
4269 out <<
", numRows: " << this->getGlobalLength ();
4270 if (className !=
"Tpetra::Vector") {
4271 out <<
", numCols: " << this->getNumVectors ()
4272 <<
", isConstantStride: " << this->isConstantStride ();
4274 if (this->isConstantStride ()) {
4275 out <<
", columnStride: " << this->getStride ();
4282 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4287 return this->descriptionImpl (
"Tpetra::MultiVector");
4290 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4295 typedef LocalOrdinal LO;
4298 if (vl <= Teuchos::VERB_LOW) {
4299 return std::string ();
4301 auto map = this->getMap ();
4302 if (map.is_null ()) {
4303 return std::string ();
4305 auto outStringP = Teuchos::rcp (
new std::ostringstream ());
4306 auto outp = Teuchos::getFancyOStream (outStringP);
4307 Teuchos::FancyOStream& out = *outp;
4308 auto comm = map->getComm ();
4309 const int myRank = comm->getRank ();
4310 const int numProcs = comm->getSize ();
4312 out <<
"Process " << myRank <<
" of " << numProcs <<
":" << endl;
4313 Teuchos::OSTab tab1 (out);
4316 const LO lclNumRows =
static_cast<LO
> (this->getLocalLength ());
4317 out <<
"Local number of rows: " << lclNumRows << endl;
4319 if (vl > Teuchos::VERB_MEDIUM) {
4322 if (this->getNumVectors () !=
static_cast<size_t> (1)) {
4323 out <<
"isConstantStride: " << this->isConstantStride () << endl;
4325 if (this->isConstantStride ()) {
4326 out <<
"Column stride: " << this->getStride () << endl;
4329 if (vl > Teuchos::VERB_HIGH && lclNumRows > 0) {
4333 typename dual_view_type::t_host X_host;
4334 if (need_sync_host ()) {
4340 auto X_dev = getLocalViewDevice ();
4341 auto X_host_copy = Kokkos::create_mirror_view (X_dev);
4343 X_host = X_host_copy;
4349 X_host = getLocalViewHost ();
4353 out <<
"Values: " << endl
4355 const LO numCols =
static_cast<LO
> (this->getNumVectors ());
4357 for (LO i = 0; i < lclNumRows; ++i) {
4359 if (i + 1 < lclNumRows) {
4365 for (LO i = 0; i < lclNumRows; ++i) {
4366 for (LO j = 0; j < numCols; ++j) {
4368 if (j + 1 < numCols) {
4372 if (i + 1 < lclNumRows) {
4382 return outStringP->str ();
4385 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4389 const std::string& className,
4390 const Teuchos::EVerbosityLevel verbLevel)
const
4392 using Teuchos::TypeNameTraits;
4393 using Teuchos::VERB_DEFAULT;
4394 using Teuchos::VERB_NONE;
4395 using Teuchos::VERB_LOW;
4397 const Teuchos::EVerbosityLevel vl =
4398 (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
4400 if (vl == VERB_NONE) {
4407 auto map = this->getMap ();
4408 if (map.is_null ()) {
4411 auto comm = map->getComm ();
4412 if (comm.is_null ()) {
4416 const int myRank = comm->getRank ();
4425 Teuchos::RCP<Teuchos::OSTab> tab0, tab1;
4429 tab0 = Teuchos::rcp (
new Teuchos::OSTab (out));
4430 out <<
"\"" << className <<
"\":" << endl;
4431 tab1 = Teuchos::rcp (
new Teuchos::OSTab (out));
4433 out <<
"Template parameters:" << endl;
4434 Teuchos::OSTab tab2 (out);
4435 out <<
"Scalar: " << TypeNameTraits<Scalar>::name () << endl
4436 <<
"LocalOrdinal: " << TypeNameTraits<LocalOrdinal>::name () << endl
4437 <<
"GlobalOrdinal: " << TypeNameTraits<GlobalOrdinal>::name () << endl
4438 <<
"Node: " << Node::name () << endl;
4440 if (this->getObjectLabel () !=
"") {
4441 out <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
4443 out <<
"Global number of rows: " << this->getGlobalLength () << endl;
4444 if (className !=
"Tpetra::Vector") {
4445 out <<
"Number of columns: " << this->getNumVectors () << endl;
4452 if (vl > VERB_LOW) {
4453 const std::string lclStr = this->localDescribeToString (vl);
4454 ::Tpetra::Details::gathervPrint (out, lclStr, *comm);
4458 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4462 const Teuchos::EVerbosityLevel verbLevel)
const
4464 this->describeImpl (out,
"Tpetra::MultiVector", verbLevel);
4467 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4472 replaceMap (newMap);
4475 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4480 using ::Tpetra::Details::localDeepCopy;
4481 const char prefix[] =
"Tpetra::MultiVector::assign: ";
4483 TEUCHOS_TEST_FOR_EXCEPTION
4485 this->getNumVectors () != src.
getNumVectors (), std::invalid_argument,
4486 prefix <<
"Global dimensions of the two Tpetra::MultiVector "
4487 "objects do not match. src has dimensions [" << src.
getGlobalLength ()
4488 <<
"," << src.
getNumVectors () <<
"], and *this has dimensions ["
4489 << this->getGlobalLength () <<
"," << this->getNumVectors () <<
"].");
4491 TEUCHOS_TEST_FOR_EXCEPTION
4492 (this->getLocalLength () != src.
getLocalLength (), std::invalid_argument,
4493 prefix <<
"The local row counts of the two Tpetra::MultiVector "
4494 "objects do not match. src has " << src.
getLocalLength () <<
" row(s) "
4495 <<
" and *this has " << this->getLocalLength () <<
" row(s).");
4501 this->clear_sync_state();
4502 this->modify_device ();
4507 if (src_last_updated_on_host) {
4508 localDeepCopy (this->getLocalViewDevice (),
4510 this->isConstantStride (),
4512 this->whichVectors_ (),
4516 localDeepCopy (this->getLocalViewDevice (),
4518 this->isConstantStride (),
4520 this->whichVectors_ (),
4525 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4529 using ::Tpetra::Details::PackTraits;
4532 typename Kokkos::View<int*, device_type>::HostMirror::execution_space;
4534 const size_t l1 = this->getLocalLength();
4536 if ((l1!=l2) || (this->getNumVectors() != vec.
getNumVectors())) {
4543 auto v1 = this->getLocalViewHost ();
4545 if (PackTraits<ST, HES>::packValueCount (v1(0,0)) !=
4546 PackTraits<ST, HES>::packValueCount (v2(0,0))) {
4553 template <
class ST,
class LO,
class GO,
class NT>
4556 std::swap(mv.
map_, this->map_);
4557 std::swap(mv.
view_, this->view_);
4558 std::swap(mv.
origView_, this->origView_);
4562 #ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4563 template <
class ST,
class LO,
class GO,
class NT>
4566 const Teuchos::SerialDenseMatrix<int, ST>& src)
4568 using ::Tpetra::Details::localDeepCopy;
4570 using IST =
typename MV::impl_scalar_type;
4571 using input_view_type =
4572 Kokkos::View<
const IST**, Kokkos::LayoutLeft,
4573 Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
4574 using pair_type = std::pair<LO, LO>;
4576 const LO numRows =
static_cast<LO
> (src.numRows ());
4577 const LO numCols =
static_cast<LO
> (src.numCols ());
4579 TEUCHOS_TEST_FOR_EXCEPTION
4582 std::invalid_argument,
"Tpetra::deep_copy: On Process "
4583 << dst.
getMap ()->getComm ()->getRank () <<
", dst is "
4585 <<
", but src is " << numRows <<
" x " << numCols <<
".");
4587 const IST* src_raw =
reinterpret_cast<const IST*
> (src.values ());
4588 input_view_type src_orig (src_raw, src.stride (), numCols);
4589 input_view_type src_view =
4590 Kokkos::subview (src_orig, pair_type (0, numRows), Kokkos::ALL ());
4594 constexpr
bool src_isConstantStride =
true;
4595 Teuchos::ArrayView<const size_t> srcWhichVectors (
nullptr, 0);
4599 src_isConstantStride,
4600 getMultiVectorWhichVectors (dst),
4604 template <
class ST,
class LO,
class GO,
class NT>
4606 deep_copy (Teuchos::SerialDenseMatrix<int, ST>& dst,
4607 const MultiVector<ST, LO, GO, NT>& src)
4609 using ::Tpetra::Details::localDeepCopy;
4610 using MV = MultiVector<ST, LO, GO, NT>;
4611 using IST =
typename MV::impl_scalar_type;
4612 using output_view_type =
4613 Kokkos::View<IST**, Kokkos::LayoutLeft,
4614 Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
4615 using pair_type = std::pair<LO, LO>;
4617 const LO numRows =
static_cast<LO
> (dst.numRows ());
4618 const LO numCols =
static_cast<LO
> (dst.numCols ());
4620 TEUCHOS_TEST_FOR_EXCEPTION
4621 (numRows != static_cast<LO> (src.getLocalLength ()) ||
4622 numCols != static_cast<LO> (src.getNumVectors ()),
4623 std::invalid_argument,
"Tpetra::deep_copy: On Process "
4624 << src.getMap ()->getComm ()->getRank () <<
", src is "
4625 << src.getLocalLength () <<
" x " << src.getNumVectors ()
4626 <<
", but dst is " << numRows <<
" x " << numCols <<
".");
4628 IST* dst_raw =
reinterpret_cast<IST*
> (dst.values ());
4629 output_view_type dst_orig (dst_raw, dst.stride (), numCols);
4631 Kokkos::subview (dst_orig, pair_type (0, numRows), Kokkos::ALL ());
4633 constexpr
bool dst_isConstantStride =
true;
4634 Teuchos::ArrayView<const size_t> dstWhichVectors (
nullptr, 0);
4637 if (src.need_sync_host ()) {
4638 localDeepCopy (dst_view,
4639 src.getLocalViewDevice (),
4640 dst_isConstantStride,
4641 src.isConstantStride (),
4643 getMultiVectorWhichVectors (src));
4647 src.getLocalViewHost (),
4648 dst_isConstantStride,
4649 src.isConstantStride (),
4651 getMultiVectorWhichVectors (src));
4654 #endif // HAVE_TPETRACORE_TEUCHOSNUMERICS
4656 template <
class Scalar,
class LO,
class GO,
class NT>
4657 Teuchos::RCP<MultiVector<Scalar, LO, GO, NT> >
4661 typedef MultiVector<Scalar, LO, GO, NT> MV;
4662 return Teuchos::rcp (
new MV (map, numVectors));
4665 template <
class ST,
class LO,
class GO,
class NT>
4666 MultiVector<ST, LO, GO, NT>
4683 #ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4684 # define TPETRA_MULTIVECTOR_INSTANT(SCALAR,LO,GO,NODE) \
4685 template class MultiVector< SCALAR , LO , GO , NODE >; \
4686 template MultiVector< SCALAR , LO , GO , NODE > createCopy( const MultiVector< SCALAR , LO , GO , NODE >& src); \
4687 template Teuchos::RCP<MultiVector< SCALAR , LO , GO , NODE > > createMultiVector (const Teuchos::RCP<const Map<LO, GO, NODE> >& map, size_t numVectors); \
4688 template void deep_copy (MultiVector<SCALAR, LO, GO, NODE>& dst, const Teuchos::SerialDenseMatrix<int, SCALAR>& src); \
4689 template void deep_copy (Teuchos::SerialDenseMatrix<int, SCALAR>& dst, const MultiVector<SCALAR, LO, GO, NODE>& src);
4692 # define TPETRA_MULTIVECTOR_INSTANT(SCALAR,LO,GO,NODE) \
4693 template class MultiVector< SCALAR , LO , GO , NODE >; \
4694 template MultiVector< SCALAR , LO , GO , NODE > createCopy( const MultiVector< SCALAR , LO , GO , NODE >& src);
4696 #endif // HAVE_TPETRACORE_TEUCHOSNUMERICS
4698 #endif // TPETRA_MULTIVECTOR_DEF_HPP
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > createMultiVector(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &map, const size_t numVectors)
Nonmember MultiVector "constructor": Create a MultiVector from a given Map.
Teuchos::RCP< const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > subView(const Teuchos::Range1D &colRng) const
Return a const MultiVector with const views of selected columns.
dual_view_type::t_host getLocalViewHost() const
A local Kokkos::View of host memory.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with the given verbosity level to a FancyOStream.
dual_view_type view_
The Kokkos::DualView containing the MultiVector's data.
Kokkos::DualView< size_t *, buffer_device_type > numExportPacketsPerLID_
Number of packets to send for each send operation.
Teuchos::ArrayRCP< Scalar > get1dViewNonConst()
Nonconst persisting (1-D) view of this multivector's local values.
void meanValue(const Teuchos::ArrayView< impl_scalar_type > &means) const
Compute mean (average) value of each column.
Teuchos::RCP< const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > offsetView(const Teuchos::RCP< const map_type > &subMap, const size_t offset) const
Return a const view of a subset of rows.
void get2dCopy(const Teuchos::ArrayView< const Teuchos::ArrayView< Scalar > > &ArrayOfPtrs) const
Fill the given array with a copy of this multivector's local values.
Declaration and definition of Tpetra::Details::Blas::fill, an implementation detail of Tpetra::MultiV...
void clear_sync_state()
Clear "modified" flags on both host and device sides.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
typename device_type::execution_space execution_space
Type of the (new) Kokkos execution space.
Kokkos::DualView< impl_scalar_type **, Kokkos::LayoutLeft, execution_space > dual_view_type
Kokkos::DualView specialization used by this class.
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
size_t getNumVectors() const
Number of columns in the multivector.
size_t getLocalLength() const
Local number of rows on the calling process.
void replaceMap(const Teuchos::RCP< const map_type > &map)
Replace the underlying Map in place.
Teuchos::ArrayRCP< Teuchos::ArrayRCP< Scalar > > get2dViewNonConst()
Return non-const persisting pointers to values.
bool isConstantStride() const
Whether this multivector has constant stride between columns.
MultiVector< ST, LO, GO, NT > createCopy(const MultiVector< ST, LO, GO, NT > &src)
Return a deep copy of the given MultiVector.
std::string localDescribeToString(const Teuchos::EVerbosityLevel vl) const
Print the calling process' verbose describe() information to the returned string. ...
One or more distributed dense vectors.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > subCopy(const Teuchos::Range1D &colRng) const
Return a MultiVector with copies of selected columns.
Declaration and generic definition of traits class that tells Tpetra::CrsMatrix how to pack and unpac...
void sumIntoGlobalValue(const GlobalOrdinal gblRow, const size_t col, const impl_scalar_type &value, const bool atomic=useAtomicUpdatesByDefault) const
Update (+=) a value in host memory, using global row index.
bool isDistributed() const
Whether this is a globally distributed object.
void get1dCopy(const Teuchos::ArrayView< Scalar > &A, const size_t LDA) const
Fill the given array with a copy of this multivector's local values.
MultiVector< ST, LO, GO, NT > createCopy(const MultiVector< ST, LO, GO, NT > &src)
Return a deep copy of the given MultiVector.
static bool debug()
Whether Tpetra is in debug mode.
bool need_sync_device() const
Whether this MultiVector needs synchronization to the device.
bool isSameSize(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &vec) const
size_t getOrigNumLocalCols() const
"Original" number of columns in the (local) data.
Teuchos::ArrayRCP< const Scalar > getData(size_t j) const
Const view of the local values in a particular vector of this multivector.
size_t global_size_t
Global size_t object.
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< size_t *, buffer_device_type > numImportPacketsPerLID_
Number of packets to receive for each receive operation.
Insert new values that don't currently exist.
Kokkos::DualView< packet_type *, buffer_device_type > imports_
Buffer into which packed data are imported (received from other processes).
Kokkos::DualView< packet_type *, buffer_device_type > exports_
Buffer from which packed data are exported (sent to other processes).
void sync_host()
Synchronize to Host.
void scale(const Scalar &alpha)
Scale in place: this = alpha*this.
void multiply(Teuchos::ETransp transA, Teuchos::ETransp transB, const Scalar &alpha, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, const Scalar &beta)
Matrix-matrix multiplication: this = beta*this + alpha*op(A)*op(B).
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 update(const Scalar &alpha, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta)
Update: this = beta*this + alpha*A.
void elementWiseMultiply(Scalar scalarAB, const Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, Scalar scalarThis)
Multiply a Vector A elementwise by a MultiVector B.
Teuchos::RCP< Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getVectorNonConst(const size_t j)
Return a Vector which is a nonconst view of column j.
void assign(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &src)
Copy the contents of src into *this (deep copy).
static void allReduceView(const OutputViewType &output, const InputViewType &input, const Teuchos::Comm< int > &comm)
All-reduce from input Kokkos::View to output Kokkos::View.
dual_view_type origView_
The "original view" of the MultiVector's data.
std::string descriptionImpl(const std::string &className) const
Implementation of description() for this class, and its subclass Vector.
void normInf(const Kokkos::View< mag_type *, Kokkos::HostSpace > &norms) const
Compute the infinity-norm of each vector (column), storing the result in a host View.
void replaceGlobalValue(const GlobalOrdinal gblRow, const size_t col, const impl_scalar_type &value) const
Replace value in host memory, using global row index.
typename Kokkos::Details::InnerProductSpaceTraits< impl_scalar_type >::dot_type dot_type
Type of an inner ("dot") product result.
static bool verbose()
Whether Tpetra is in verbose mode.
CombineMode
Rule for combining data in an Import or Export.
Sum new values into existing values.
Teuchos::RCP< const map_type > map_
The Map over which this object is distributed.
bool reallocDualViewIfNeeded(Kokkos::DualView< ValueType *, DeviceType > &dv, const size_t newSize, const char newLabel[], const size_t tooBigFactor=2, const bool needFenceBeforeRealloc=true)
Reallocate the DualView in/out argument, if needed.
Declaration of Tpetra::Details::isInterComm.
void norm2(const Kokkos::View< mag_type *, Kokkos::HostSpace > &norms) const
Compute the two-norm of each vector (column), storing the result in a host View.
void dot(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Teuchos::ArrayView< dot_type > &dots) const
Compute the dot product of each corresponding pair of vectors (columns) in A and B.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > subViewNonConst(const Teuchos::Range1D &colRng)
Return a MultiVector with views of selected columns.
virtual size_t constantNumberOfPackets() const
Number of packets to send per LID.
bool need_sync_host() const
Whether this MultiVector needs synchronization to the host.
void modify_device()
Mark data as modified on the device side.
Replace old value with maximum of magnitudes of old and new values.
typename Kokkos::ArithTraits< impl_scalar_type >::mag_type mag_type
Type of a norm result.
Abstract base class for objects that can be the source of an Import or Export operation.
Teuchos::ArrayRCP< Scalar > getDataNonConst(size_t j)
View of the local values in a particular vector of this multivector.
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
Replace existing values with new values.
void swap(MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &mv)
Return a deep copy of this MultiVector, with a different Node type.
void randomize()
Set all values in the multivector to pseudorandom numbers.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > offsetViewNonConst(const Teuchos::RCP< const map_type > &subMap, const size_t offset)
Return a nonconst view of a subset of rows.
Teuchos::ArrayRCP< T > getSubArrayRCP(Teuchos::ArrayRCP< T > arr, size_t j) const
Persisting view of j-th column in the given ArrayRCP.
std::string combineModeToString(const CombineMode combineMode)
Human-readable string representation of the given CombineMode.
Teuchos::RCP< const Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getVector(const size_t j) const
Return a Vector which is a const view of column j.
void modify_host()
Mark data as modified on the host side.
MultiVector()
Default constructor: makes a MultiVector with no rows or columns.
void replaceLocalValue(const LocalOrdinal lclRow, const size_t col, const impl_scalar_type &value) const
Replace value in host memory, using local (row) index.
typename Kokkos::Details::ArithTraits< Scalar >::val_type impl_scalar_type
The type used internally in place of Scalar.
void norm1(const Kokkos::View< mag_type *, Kokkos::HostSpace > &norms) const
Compute the one-norm of each vector (column), storing the result in a host view.
A parallel distribution of indices over processes.
size_t getStride() const
Stride between columns in the multivector.
A distributed dense vector.
Stand-alone utility functions and macros.
virtual std::string description() const
A simple one-line description of this object.
void reduce()
Sum values of a locally replicated multivector across all processes.
void describeImpl(Teuchos::FancyOStream &out, const std::string &className, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Implementation of describe() for this class, and its subclass Vector.
typename map_type::local_ordinal_type local_ordinal_type
The type of local indices that this class uses.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
virtual bool checkSizes(const SrcDistObject &sourceObj)
Whether data redistribution between sourceObj and this object is legal.
dual_view_type::t_dev getLocalViewDevice() const
A local Kokkos::View of device memory.
void sumIntoLocalValue(const LocalOrdinal lclRow, const size_t col, const impl_scalar_type &val, const bool atomic=useAtomicUpdatesByDefault) const
Update (+=) a value in host memory, using local row index.
Teuchos::ArrayRCP< Teuchos::ArrayRCP< const Scalar > > get2dView() const
Return const persisting pointers to values.
void normImpl(MagnitudeType norms[], const Kokkos::View< const ValueType **, ArrayLayout, DeviceType > &X, const EWhichNorm whichNorm, const Teuchos::ArrayView< const size_t > &whichVecs, const bool isConstantStride, const bool isDistributed, const Teuchos::Comm< int > *comm)
Implementation of MultiVector norms.
void reciprocal(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
Put element-wise reciprocal values of input Multi-vector in target, this(i,j) = 1/A(i,j).
Base class for distributed Tpetra objects that support data redistribution.
void localDeepCopy(const DstViewType &dst, const SrcViewType &src, const bool dstConstStride, const bool srcConstStride, const DstWhichVecsType &dstWhichVecs, const SrcWhichVecsType &srcWhichVecs)
Implementation of Tpetra::MultiVector deep copy of local data.
global_size_t getGlobalLength() const
Global number of rows in the multivector.
void abs(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
Put element-wise absolute values of input Multi-vector in target: A = abs(this)
Teuchos::ArrayRCP< const Scalar > get1dView() const
Const persisting (1-D) view of this multivector's local values.
size_t getOrigNumLocalRows() const
"Original" number of rows in the (local) data.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap)
Remove processes owning zero rows from the Map and their communicator.
All-reduce a 1-D or 2-D Kokkos::View.
Declaration and definition of Tpetra::Details::lclDot, an implementation detail of Tpetra::MultiVecto...
void sync_device()
Synchronize to Device.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Teuchos::Array< size_t > whichVectors_
Indices of columns this multivector is viewing.