10#ifndef TPETRA_MULTIVECTOR_DEF_HPP
11#define TPETRA_MULTIVECTOR_DEF_HPP
23#include "Tpetra_Vector.hpp"
35#include "Tpetra_Details_Random.hpp"
36#ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
37#include "Teuchos_SerialDenseMatrix.hpp"
39#include "Tpetra_KokkosRefactor_Details_MultiVectorDistObjectKernels.hpp"
40#include "KokkosCompat_View.hpp"
41#include "KokkosBlas.hpp"
42#include "KokkosKernels_Utils.hpp"
43#include "Kokkos_Random.hpp"
44#include "KokkosKernels_ArithTraits.hpp"
48#ifdef HAVE_TPETRA_INST_FLOAT128
51template <
class Generator>
52struct rand<Generator, __float128> {
53 static KOKKOS_INLINE_FUNCTION __float128 max() {
54 return static_cast<__float128
>(1.0);
56 static KOKKOS_INLINE_FUNCTION __float128
57 draw(Generator& gen) {
60 const __float128 scalingFactor =
61 static_cast<__float128
>(std::numeric_limits<double>::min()) /
62 static_cast<__float128
>(2.0);
63 const __float128 higherOrderTerm =
static_cast<__float128
>(gen.drand());
64 const __float128 lowerOrderTerm =
65 static_cast<__float128
>(gen.drand()) * scalingFactor;
66 return higherOrderTerm + lowerOrderTerm;
68 static KOKKOS_INLINE_FUNCTION __float128
69 draw(Generator& gen,
const __float128& range) {
71 const __float128 scalingFactor =
72 static_cast<__float128
>(std::numeric_limits<double>::min()) /
73 static_cast<__float128
>(2.0);
74 const __float128 higherOrderTerm =
75 static_cast<__float128
>(gen.drand(range));
76 const __float128 lowerOrderTerm =
77 static_cast<__float128
>(gen.drand(range)) * scalingFactor;
78 return higherOrderTerm + lowerOrderTerm;
80 static KOKKOS_INLINE_FUNCTION __float128
81 draw(Generator& gen,
const __float128& start,
const __float128& end) {
83 const __float128 scalingFactor =
84 static_cast<__float128
>(std::numeric_limits<double>::min()) /
85 static_cast<__float128
>(2.0);
86 const __float128 higherOrderTerm =
87 static_cast<__float128
>(gen.drand(start, end));
88 const __float128 lowerOrderTerm =
89 static_cast<__float128
>(gen.drand(start, end)) * scalingFactor;
90 return higherOrderTerm + lowerOrderTerm;
112template <
class ST,
class LO,
class GO,
class NT>
113typename Tpetra::MultiVector<ST, LO, GO, NT>::wrapped_dual_view_type
114allocDualView(
const size_t lclNumRows,
115 const size_t numCols,
116 const bool zeroOut =
true,
117 const bool allowPadding =
false) {
118 using Kokkos::AllowPadding;
119 using Kokkos::view_alloc;
120 using Kokkos::WithoutInitializing;
123 typedef typename Tpetra::MultiVector<ST, LO, GO, NT>::wrapped_dual_view_type wrapped_dual_view_type;
124 typedef typename dual_view_type::t_dev dev_view_type;
130 const std::string label(
"MV::DualView");
131 const bool debug = Behavior::debug();
141 dev_view_type d_view;
144 d_view = dev_view_type(view_alloc(label, AllowPadding),
145 lclNumRows, numCols);
147 d_view = dev_view_type(view_alloc(label),
148 lclNumRows, numCols);
152 d_view = dev_view_type(view_alloc(label,
155 lclNumRows, numCols);
157 d_view = dev_view_type(view_alloc(label, WithoutInitializing),
158 lclNumRows, numCols);
169 const ST nan = KokkosKernels::ArithTraits<ST>::nan();
170 KokkosBlas::fill(d_view, nan);
174 TEUCHOS_TEST_FOR_EXCEPTION(
static_cast<size_t>(d_view.extent(0)) != lclNumRows ||
175 static_cast<size_t>(d_view.extent(1)) != numCols,
177 "allocDualView: d_view's dimensions actual dimensions do not match "
178 "requested dimensions. d_view is "
179 << d_view.extent(0) <<
" x " << d_view.extent(1) <<
"; requested " << lclNumRows <<
" x " << numCols
180 <<
". Please report this bug to the Tpetra developers.");
183 return wrapped_dual_view_type(d_view);
190template <
class T,
class ExecSpace>
191struct MakeUnmanagedView {
201 typedef typename std::conditional<
202 Kokkos::SpaceAccessibility<
203 typename ExecSpace::memory_space,
204 Kokkos::HostSpace>::accessible,
205 typename ExecSpace::device_type,
206 typename Kokkos::DualView<T*, ExecSpace>::host_mirror_space>::type host_exec_space;
207 typedef Kokkos::LayoutLeft array_layout;
208 typedef Kokkos::View<T*, array_layout, host_exec_space,
209 Kokkos::MemoryUnmanaged>
212 static view_type getView(
const Teuchos::ArrayView<T>& x_in) {
213 const size_t numEnt =
static_cast<size_t>(x_in.size());
217 return view_type(x_in.getRawPtr(), numEnt);
222template <
class WrappedDualViewType>
224takeSubview(
const WrappedDualViewType& X,
225 const std::pair<size_t, size_t>& rowRng,
226 const Kokkos::ALL_t& colRng)
230 return WrappedDualViewType(X, rowRng, colRng);
233template <
class WrappedDualViewType>
235takeSubview(
const WrappedDualViewType& X,
236 const Kokkos::ALL_t& rowRng,
237 const std::pair<size_t, size_t>& colRng) {
238 using DualViewType =
typename WrappedDualViewType::DVT;
241 if (X.extent(0) == 0 && X.extent(1) != 0) {
242 return WrappedDualViewType(DualViewType(
"MV::DualView", 0, colRng.second - colRng.first));
244 return WrappedDualViewType(X, rowRng, colRng);
248template <
class WrappedDualViewType>
250takeSubview(
const WrappedDualViewType& X,
251 const std::pair<size_t, size_t>& rowRng,
252 const std::pair<size_t, size_t>& colRng) {
253 using DualViewType =
typename WrappedDualViewType::DVT;
263 if (X.extent(0) == 0 && X.extent(1) != 0) {
264 return WrappedDualViewType(DualViewType(
"MV::DualView", 0, colRng.second - colRng.first));
266 return WrappedDualViewType(X, rowRng, colRng);
270template <
class WrappedOrNotDualViewType>
272getDualViewStride(
const WrappedOrNotDualViewType& dv) {
277 size_t strides[WrappedOrNotDualViewType::t_dev::rank + 1];
279 const size_t LDA = strides[1];
280 const size_t numRows = dv.extent(0);
283 return (numRows == 0) ? size_t(1) : numRows;
289template <
class ViewType>
291getViewStride(
const ViewType& view) {
292 const size_t LDA = view.stride(1);
293 const size_t numRows = view.extent(0);
296 return (numRows == 0) ? size_t(1) : numRows;
302template <
class impl_scalar_type,
class buffer_device_type>
304 Kokkos::DualView<impl_scalar_type*, buffer_device_type> imports) {
305 if (!imports.need_sync_device()) {
309 size_t localLengthThreshold =
311 return imports.extent(0) <= localLengthThreshold;
315template <
class SC,
class LO,
class GO,
class NT>
316bool runKernelOnHost(const ::Tpetra::MultiVector<SC, LO, GO, NT>& X) {
317 if (!X.need_sync_device()) {
321 size_t localLengthThreshold =
323 return X.getLocalLength() <= localLengthThreshold;
327template <
class SC,
class LO,
class GO,
class NT>
328void multiVectorNormImpl(typename ::Tpetra::MultiVector<SC, LO, GO, NT>::mag_type norms[],
330 const ::Tpetra::Details::EWhichNorm whichNorm) {
334 using val_type =
typename MV::impl_scalar_type;
335 using mag_type =
typename MV::mag_type;
336 using dual_view_type =
typename MV::dual_view_type;
339 auto comm = map.is_null() ? nullptr : map->getComm().getRawPtr();
340 auto whichVecs = getMultiVectorWhichVectors(X);
344 const bool runOnHost = runKernelOnHost(X);
346 using view_type =
typename dual_view_type::t_host;
347 using array_layout =
typename view_type::array_layout;
348 using device_type =
typename view_type::device_type;
352 mag_type>(norms, X_lcl, whichNorm, whichVecs,
353 isConstantStride, isDistributed, comm);
355 using view_type =
typename dual_view_type::t_dev;
356 using array_layout =
typename view_type::array_layout;
357 using device_type =
typename view_type::device_type;
361 mag_type>(norms, X_lcl, whichNorm, whichVecs,
362 isConstantStride, isDistributed, comm);
370template <
typename DstView,
typename SrcView>
371struct AddAssignFunctor {
374 AddAssignFunctor(DstView& tgt_, SrcView& src_)
378 KOKKOS_INLINE_FUNCTION
void
379 operator()(
const size_t k)
const { tgt(k) += src(k); }
386template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
389 return (VectorIndex < 1 && VectorIndex != 0) || VectorIndex >= getNumVectors();
392template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
395 : base_type(Teuchos::rcp(new
map_type())) {}
397template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
399 MultiVector(
const Teuchos::RCP<const map_type>& map,
400 const size_t numVecs,
407 view_ = allocDualView<Scalar, LocalOrdinal, GlobalOrdinal, Node>(lclNumRows, numVecs, zeroOut);
410template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
413 const Teuchos::DataAccess copyOrView)
418 const char tfecfFuncName[] =
419 "MultiVector(const MultiVector&, "
420 "const Teuchos::DataAccess): ";
424 if (copyOrView == Teuchos::Copy) {
428 this->
view_ = cpy.view_;
430 }
else if (copyOrView == Teuchos::View) {
432 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
433 true, std::invalid_argument,
434 "Second argument 'copyOrView' has an "
436 << copyOrView <<
". Valid values include "
438 << Teuchos::Copy <<
" and Teuchos::View = "
439 << Teuchos::View <<
".");
443template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
445 MultiVector(
const Teuchos::RCP<const map_type>& map,
448 ,
view_(wrapped_dual_view_type(view)) {
449 const char tfecfFuncName[] =
"MultiVector(Map,DualView): ";
450 const size_t lclNumRows_map = map.is_null() ?
size_t(0) : map->getLocalNumElements();
451 const size_t lclNumRows_view = view.extent(0);
452 const size_t LDA = getDualViewStride(
view_);
454 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows_map || lclNumRows_map != lclNumRows_view,
455 std::invalid_argument,
456 "Kokkos::DualView does not match Map. "
457 "map->getLocalNumElements() = "
459 <<
", view.extent(0) = " << lclNumRows_view
460 <<
", and getStride() = " << LDA <<
".");
463 const bool debug = Behavior::debug();
465 using ::Tpetra::Details::checkGlobalDualViewValidity;
466 std::ostringstream gblErrStrm;
467 const bool verbose = Behavior::verbose();
468 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
469 const bool gblValid =
470 checkGlobalDualViewValidity(&gblErrStrm, view, verbose,
472 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
476template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
478 MultiVector(
const Teuchos::RCP<const map_type>& map,
479 const wrapped_dual_view_type& view)
482 const char tfecfFuncName[] =
"MultiVector(Map,DualView): ";
483 const size_t lclNumRows_map = map.is_null() ?
size_t(0) : map->getLocalNumElements();
484 const size_t lclNumRows_view = view.extent(0);
485 const size_t LDA = getDualViewStride(view);
487 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows_map || lclNumRows_map != lclNumRows_view,
488 std::invalid_argument,
489 "Kokkos::DualView does not match Map. "
490 "map->getLocalNumElements() = "
492 <<
", view.extent(0) = " << lclNumRows_view
493 <<
", and getStride() = " << LDA <<
".");
496 const bool debug = Behavior::debug();
498 using ::Tpetra::Details::checkGlobalWrappedDualViewValidity;
499 std::ostringstream gblErrStrm;
500 const bool verbose = Behavior::verbose();
501 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
502 const bool gblValid =
503 checkGlobalWrappedDualViewValidity(&gblErrStrm, view, verbose,
505 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
509template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
511 MultiVector(
const Teuchos::RCP<const map_type>& map,
512 const typename dual_view_type::t_dev& d_view)
514 using Teuchos::ArrayRCP;
516 const char tfecfFuncName[] =
"MultiVector(map,d_view): ";
520 const size_t LDA = getViewStride(d_view);
521 const size_t lclNumRows = map->getLocalNumElements();
522 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows, std::invalid_argument,
523 "Map does not match "
524 "Kokkos::View. map->getLocalNumElements() = "
526 <<
", View's column stride = " << LDA
527 <<
", and View's extent(0) = " << d_view.extent(0) <<
".");
529 auto h_view = Kokkos::create_mirror_view(d_view);
531 view_ = wrapped_dual_view_type(dual_view);
534 const bool debug = Behavior::debug();
536 using ::Tpetra::Details::checkGlobalWrappedDualViewValidity;
537 std::ostringstream gblErrStrm;
538 const bool verbose = Behavior::verbose();
539 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
540 const bool gblValid =
541 checkGlobalWrappedDualViewValidity(&gblErrStrm,
view_, verbose,
543 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
548 dual_view.modify_device();
551template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
553 MultiVector(
const Teuchos::RCP<const map_type>& map,
557 ,
view_(wrapped_dual_view_type(view, origView)) {
558 const char tfecfFuncName[] =
"MultiVector(map,view,origView): ";
560 const size_t LDA = getDualViewStride(origView);
562 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
563 LDA < lclNumRows, std::invalid_argument,
564 "The input Kokkos::DualView's "
565 "column stride LDA = "
566 << LDA <<
" < getLocalLength() = " << lclNumRows
567 <<
". This may also mean that the input origView's first dimension (number "
569 << origView.extent(0) <<
") does not not match the number "
570 "of entries in the Map on the calling process.");
573 const bool debug = Behavior::debug();
575 using ::Tpetra::Details::checkGlobalDualViewValidity;
576 std::ostringstream gblErrStrm;
577 const bool verbose = Behavior::verbose();
578 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
579 const bool gblValid_0 =
580 checkGlobalDualViewValidity(&gblErrStrm, view, verbose,
582 const bool gblValid_1 =
583 checkGlobalDualViewValidity(&gblErrStrm, origView, verbose,
585 const bool gblValid = gblValid_0 && gblValid_1;
586 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
590template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
592 MultiVector(
const Teuchos::RCP<const map_type>& map,
594 const Teuchos::ArrayView<const size_t>& whichVectors)
599 using Kokkos::subview;
600 const char tfecfFuncName[] =
"MultiVector(map,view,whichVectors): ";
603 const bool debug = Behavior::debug();
605 using ::Tpetra::Details::checkGlobalDualViewValidity;
606 std::ostringstream gblErrStrm;
607 const bool verbose = Behavior::verbose();
608 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
609 const bool gblValid =
610 checkGlobalDualViewValidity(&gblErrStrm, view, verbose,
612 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
615 const size_t lclNumRows = map.is_null() ? size_t(0) : map->getLocalNumElements();
622 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
623 view.extent(1) != 0 &&
static_cast<size_t>(view.extent(0)) < lclNumRows,
624 std::invalid_argument,
"view.extent(0) = " << view.extent(0) <<
" < map->getLocalNumElements() = " << lclNumRows <<
".");
625 if (whichVectors.size() != 0) {
626 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
627 view.extent(1) != 0 && view.extent(1) == 0,
628 std::invalid_argument,
629 "view.extent(1) = 0, but whichVectors.size()"
631 << whichVectors.size() <<
" > 0.");
632 size_t maxColInd = 0;
633 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
634 for (size_type k = 0; k < whichVectors.size(); ++k) {
635 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
636 whichVectors[k] == Teuchos::OrdinalTraits<size_t>::invalid(),
637 std::invalid_argument,
"whichVectors[" << k <<
"] = "
638 "Teuchos::OrdinalTraits<size_t>::invalid().");
639 maxColInd = std::max(maxColInd, whichVectors[k]);
641 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
642 view.extent(1) != 0 &&
static_cast<size_t>(view.extent(1)) <= maxColInd,
643 std::invalid_argument,
"view.extent(1) = " << view.extent(1) <<
" <= max(whichVectors) = " << maxColInd <<
".");
648 const size_t LDA = getDualViewStride(view);
649 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows, std::invalid_argument,
650 "LDA = " << LDA <<
" < this->getLocalLength() = " << lclNumRows <<
".");
652 if (whichVectors.size() == 1) {
662 const std::pair<size_t, size_t> colRng(whichVectors[0],
663 whichVectors[0] + 1);
670template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
672 MultiVector(
const Teuchos::RCP<const map_type>& map,
673 const wrapped_dual_view_type& view,
674 const Teuchos::ArrayView<const size_t>& whichVectors)
679 using Kokkos::subview;
680 const char tfecfFuncName[] =
"MultiVector(map,view,whichVectors): ";
683 const bool debug = Behavior::debug();
685 using ::Tpetra::Details::checkGlobalWrappedDualViewValidity;
686 std::ostringstream gblErrStrm;
687 const bool verbose = Behavior::verbose();
688 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
689 const bool gblValid =
690 checkGlobalWrappedDualViewValidity(&gblErrStrm, view, verbose,
692 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
695 const size_t lclNumRows = map.is_null() ? size_t(0) : map->getLocalNumElements();
702 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
703 view.extent(1) != 0 &&
static_cast<size_t>(view.extent(0)) < lclNumRows,
704 std::invalid_argument,
"view.extent(0) = " << view.extent(0) <<
" < map->getLocalNumElements() = " << lclNumRows <<
".");
705 if (whichVectors.size() != 0) {
706 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
707 view.extent(1) != 0 && view.extent(1) == 0,
708 std::invalid_argument,
709 "view.extent(1) = 0, but whichVectors.size()"
711 << whichVectors.size() <<
" > 0.");
712 size_t maxColInd = 0;
713 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
714 for (size_type k = 0; k < whichVectors.size(); ++k) {
715 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
716 whichVectors[k] == Teuchos::OrdinalTraits<size_t>::invalid(),
717 std::invalid_argument,
"whichVectors[" << k <<
"] = "
718 "Teuchos::OrdinalTraits<size_t>::invalid().");
719 maxColInd = std::max(maxColInd, whichVectors[k]);
721 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
722 view.extent(1) != 0 &&
static_cast<size_t>(view.extent(1)) <= maxColInd,
723 std::invalid_argument,
"view.extent(1) = " << view.extent(1) <<
" <= max(whichVectors) = " << maxColInd <<
".");
728 const size_t LDA = getDualViewStride(view);
729 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows, std::invalid_argument,
730 "LDA = " << LDA <<
" < this->getLocalLength() = " << lclNumRows <<
".");
732 if (whichVectors.size() == 1) {
742 const std::pair<size_t, size_t> colRng(whichVectors[0],
743 whichVectors[0] + 1);
750template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
752 MultiVector(
const Teuchos::RCP<const map_type>& map,
755 const Teuchos::ArrayView<const size_t>& whichVectors)
757 ,
view_(wrapped_dual_view_type(view, origView))
760 using Kokkos::subview;
761 const char tfecfFuncName[] =
"MultiVector(map,view,origView,whichVectors): ";
764 const bool debug = Behavior::debug();
766 using ::Tpetra::Details::checkGlobalDualViewValidity;
767 std::ostringstream gblErrStrm;
768 const bool verbose = Behavior::verbose();
769 const auto comm = map.is_null() ? Teuchos::null : map->getComm();
770 const bool gblValid_0 =
771 checkGlobalDualViewValidity(&gblErrStrm, view, verbose,
773 const bool gblValid_1 =
774 checkGlobalDualViewValidity(&gblErrStrm, origView, verbose,
776 const bool gblValid = gblValid_0 && gblValid_1;
777 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!gblValid, std::runtime_error, gblErrStrm.str());
787 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
788 view.extent(1) != 0 &&
static_cast<size_t>(view.extent(0)) < lclNumRows,
789 std::invalid_argument,
"view.extent(0) = " << view.extent(0) <<
" < map->getLocalNumElements() = " << lclNumRows <<
".");
790 if (whichVectors.size() != 0) {
791 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
792 view.extent(1) != 0 && view.extent(1) == 0,
793 std::invalid_argument,
794 "view.extent(1) = 0, but whichVectors.size()"
796 << whichVectors.size() <<
" > 0.");
797 size_t maxColInd = 0;
798 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
799 for (size_type k = 0; k < whichVectors.size(); ++k) {
800 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
801 whichVectors[k] == Teuchos::OrdinalTraits<size_t>::invalid(),
802 std::invalid_argument,
"whichVectors[" << k <<
"] = "
803 "Teuchos::OrdinalTraits<size_t>::invalid().");
804 maxColInd = std::max(maxColInd, whichVectors[k]);
806 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
807 view.extent(1) != 0 &&
static_cast<size_t>(view.extent(1)) <= maxColInd,
808 std::invalid_argument,
"view.extent(1) = " << view.extent(1) <<
" <= max(whichVectors) = " << maxColInd <<
".");
813 const size_t LDA = getDualViewStride(origView);
814 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows, std::invalid_argument,
815 "Map and DualView origView "
816 "do not match. LDA = "
817 << LDA <<
" < this->getLocalLength() = " << lclNumRows <<
". origView.extent(0) = " << origView.extent(0)
818 <<
", origView.stride(1) = " << origView.view_device().stride(1) <<
".");
820 if (whichVectors.size() == 1) {
829 const std::pair<size_t, size_t> colRng(whichVectors[0],
830 whichVectors[0] + 1);
838template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
840 MultiVector(
const Teuchos::RCP<const map_type>& map,
841 const Teuchos::ArrayView<const Scalar>& data,
843 const size_t numVecs)
845 typedef LocalOrdinal LO;
846 typedef GlobalOrdinal GO;
847 const char tfecfFuncName[] =
"MultiVector(map,data,LDA,numVecs): ";
853 const size_t lclNumRows =
854 map.is_null() ? size_t(0) : map->getLocalNumElements();
855 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < lclNumRows, std::invalid_argument,
"LDA = " << LDA <<
" < "
856 "map->getLocalNumElements() = "
857 << lclNumRows <<
".");
859 const size_t minNumEntries = LDA * (numVecs - 1) + lclNumRows;
860 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(data.size()) < minNumEntries,
861 std::invalid_argument,
862 "Input Teuchos::ArrayView does not have enough "
863 "entries, given the input Map and number of vectors in the MultiVector."
865 << data.size() <<
" < (LDA*(numVecs-1)) + "
866 "map->getLocalNumElements () = "
867 << minNumEntries <<
".");
870 this->
view_ = allocDualView<Scalar, LO, GO, Node>(lclNumRows, numVecs);
882 Kokkos::MemoryUnmanaged>
883 X_in_orig(X_in_raw, LDA, numVecs);
884 const Kokkos::pair<size_t, size_t> rowRng(0, lclNumRows);
885 auto X_in = Kokkos::subview(X_in_orig, rowRng, Kokkos::ALL());
890 const size_t outStride =
891 X_out.extent(1) == 0 ? size_t(1) : X_out.stride(1);
892 if (LDA == outStride) {
898 typedef decltype(Kokkos::subview(X_out, Kokkos::ALL(), 0))
900 typedef decltype(Kokkos::subview(X_in, Kokkos::ALL(), 0))
902 for (
size_t j = 0; j < numVecs; ++j) {
903 out_col_view_type X_out_j = Kokkos::subview(X_out, Kokkos::ALL(), j);
904 in_col_view_type X_in_j = Kokkos::subview(X_in, Kokkos::ALL(), j);
911template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
913 MultiVector(
const Teuchos::RCP<const map_type>& map,
914 const Teuchos::ArrayView<
const Teuchos::ArrayView<const Scalar> >& ArrayOfPtrs,
915 const size_t numVecs)
918 typedef LocalOrdinal LO;
919 typedef GlobalOrdinal GO;
920 const char tfecfFuncName[] =
"MultiVector(map,ArrayOfPtrs,numVecs): ";
923 const size_t lclNumRows =
924 map.is_null() ? size_t(0) : map->getLocalNumElements();
925 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numVecs < 1 || numVecs !=
static_cast<size_t>(ArrayOfPtrs.size()),
926 std::runtime_error,
"Either numVecs (= " << numVecs <<
") < 1, or "
927 "ArrayOfPtrs.size() (= "
928 << ArrayOfPtrs.size() <<
") != numVecs.");
929 for (
size_t j = 0; j < numVecs; ++j) {
930 Teuchos::ArrayView<const Scalar> X_j_av = ArrayOfPtrs[j];
931 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
932 static_cast<size_t>(X_j_av.size()) < lclNumRows,
933 std::invalid_argument,
"ArrayOfPtrs[" << j <<
"].size() = " << X_j_av.size() <<
" < map->getLocalNumElements() = " << lclNumRows <<
".");
936 view_ = allocDualView<Scalar, LO, GO, Node>(lclNumRows, numVecs);
941 using array_layout =
typename decltype(X_out)::array_layout;
942 using input_col_view_type =
typename Kokkos::View<
const IST*,
945 Kokkos::MemoryUnmanaged>;
947 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
948 for (
size_t j = 0; j < numVecs; ++j) {
949 Teuchos::ArrayView<const IST> X_j_av =
950 Teuchos::av_reinterpret_cast<const IST>(ArrayOfPtrs[j]);
951 input_col_view_type X_j_in(X_j_av.getRawPtr(), lclNumRows);
952 auto X_j_out = Kokkos::subview(X_out, rowRng, j);
958template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
964template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
968 if (this->
getMap().is_null()) {
969 return static_cast<size_t>(0);
971 return this->
getMap()->getLocalNumElements();
975template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
979 if (this->
getMap().is_null()) {
980 return static_cast<size_t>(0);
982 return this->
getMap()->getGlobalNumElements();
986template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
993template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
997 auto thisData =
view_.getDualView().view_host().data();
998 auto otherData = other.
view_.getDualView().view_host().data();
999 size_t thisSpan =
view_.getDualView().view_host().span();
1000 size_t otherSpan = other.
view_.getDualView().view_host().span();
1001 return (otherData <= thisData && thisData < otherData + otherSpan) || (thisData <= otherData && otherData < thisData + thisSpan);
1004template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1011 const MV* src =
dynamic_cast<const MV*
>(&sourceObj);
1012 if (src ==
nullptr) {
1025template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1032template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1035 const size_t numSameIDs,
1036 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
1037 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs,
1040 using Kokkos::Compat::create_const_view;
1041 using KokkosRefactor::Details::permute_array_multi_column;
1042 using KokkosRefactor::Details::permute_array_multi_column_variable_stride;
1050 MV& sourceMV =
const_cast<MV&
>(
dynamic_cast<const MV&
>(sourceObj));
1058 copyOnHost = !Behavior::assumeMpiIsGPUAware();
1061 copyOnHost = runKernelOnHost(sourceMV);
1063 const char longFuncNameHost[] =
"Tpetra::MultiVector::copyAndPermute[Host]";
1064 const char longFuncNameDevice[] =
"Tpetra::MultiVector::copyAndPermute[Device]";
1065 const char tfecfFuncName[] =
"copyAndPermute: ";
1066 ProfilingRegion regionCAP(copyOnHost ? longFuncNameHost : longFuncNameDevice);
1068 const bool verbose = Behavior::verbose();
1069 std::unique_ptr<std::string> prefix;
1071 auto map = this->getMap();
1072 auto comm = map.is_null() ? Teuchos::null : map->getComm();
1073 const int myRank = comm.is_null() ? -1 : comm->getRank();
1074 std::ostringstream os;
1075 os <<
"Proc " << myRank <<
": MV::copyAndPermute: ";
1076 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
1077 os <<
"Start" << endl;
1078 std::cerr << os.str();
1081 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(permuteToLIDs.extent(0) != permuteFromLIDs.extent(0),
1082 std::logic_error,
"permuteToLIDs.extent(0) = " << permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " << permuteFromLIDs.extent(0) <<
".");
1083 const size_t numCols = this->getNumVectors();
1087 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(sourceMV.need_sync_device() && sourceMV.need_sync_host(),
1089 "Input MultiVector needs sync to both host "
1092 std::ostringstream os;
1093 os << *prefix <<
"copyOnHost=" << (copyOnHost ?
"true" :
"false") << endl;
1094 std::cerr << os.str();
1098 std::ostringstream os;
1099 os << *prefix <<
"Copy first " << numSameIDs <<
" elements" << endl;
1100 std::cerr << os.str();
1125 if (numSameIDs > 0) {
1126 const std::pair<size_t, size_t> rows(0, numSameIDs);
1128 ProfilingRegion regionC(
"Tpetra::MultiVector::copy[Host]");
1130 auto src_h = sourceMV.getLocalViewHost(Access::ReadOnly);
1132 for (
size_t j = 0; j < numCols; ++j) {
1134 const size_t srcCol =
1135 sourceMV.isConstantStride() ? j : sourceMV.whichVectors_[j];
1137 auto tgt_j = Kokkos::subview(tgt_h, rows, tgtCol);
1138 auto src_j = Kokkos::subview(src_h, rows, srcCol);
1142 Kokkos::RangePolicy<execution_space, size_t>;
1143 range_t rp(space, 0, numSameIDs);
1144 Tpetra::Details::AddAssignFunctor<
decltype(tgt_j),
decltype(src_j)>
1146 Kokkos::parallel_for(rp, aaf);
1150 Kokkos::deep_copy(space, tgt_j, src_j);
1151 space.fence(
"Tpetra::MultiVector::copyAndPermute-1");
1155 ProfilingRegion regionC(
"Tpetra::MultiVector::copy[Device]");
1156 auto tgt_d = this->getLocalViewDevice(Access::ReadWrite);
1157 auto src_d = sourceMV.getLocalViewDevice(Access::ReadOnly);
1159 for (
size_t j = 0; j < numCols; ++j) {
1160 const size_t tgtCol = isConstantStride() ? j : whichVectors_[j];
1161 const size_t srcCol =
1162 sourceMV.isConstantStride() ? j : sourceMV.whichVectors_[j];
1164 auto tgt_j = Kokkos::subview(tgt_d, rows, tgtCol);
1165 auto src_j = Kokkos::subview(src_d, rows, srcCol);
1169 Kokkos::RangePolicy<execution_space, size_t>;
1170 range_t rp(space, 0, numSameIDs);
1171 Tpetra::Details::AddAssignFunctor<
decltype(tgt_j),
decltype(src_j)>
1173 Kokkos::parallel_for(rp, aaf);
1177 Kokkos::deep_copy(space, tgt_j, src_j);
1178 space.fence(
"Tpetra::MultiVector::copyAndPermute-2");
1194 if (permuteFromLIDs.extent(0) == 0 ||
1195 permuteToLIDs.extent(0) == 0) {
1197 std::ostringstream os;
1198 os << *prefix <<
"No permutations. Done!" << endl;
1199 std::cerr << os.str();
1203 ProfilingRegion regionP(
"Tpetra::MultiVector::permute");
1206 std::ostringstream os;
1207 os << *prefix <<
"Permute" << endl;
1208 std::cerr << os.str();
1213 const bool nonConstStride =
1214 !this->isConstantStride() || !sourceMV.isConstantStride();
1217 std::ostringstream os;
1218 os << *prefix <<
"nonConstStride="
1219 << (nonConstStride ?
"true" :
"false") << endl;
1220 std::cerr << os.str();
1227 Kokkos::DualView<const size_t*, device_type> srcWhichVecs;
1228 Kokkos::DualView<const size_t*, device_type> tgtWhichVecs;
1229 if (nonConstStride) {
1230 if (this->whichVectors_.size() == 0) {
1231 Kokkos::DualView<size_t*, device_type> tmpTgt(
"tgtWhichVecs", numCols);
1232 tmpTgt.modify_host();
1233 for (
size_t j = 0; j < numCols; ++j) {
1234 tmpTgt.view_host()(j) = j;
1237 tmpTgt.sync_device();
1239 tgtWhichVecs = tmpTgt;
1241 Teuchos::ArrayView<const size_t> tgtWhichVecsT = this->whichVectors_();
1243 getDualViewCopyFromArrayView<size_t, device_type>(tgtWhichVecsT,
1247 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(tgtWhichVecs.extent(0)) !=
1248 this->getNumVectors(),
1249 std::logic_error,
"tgtWhichVecs.extent(0) = " << tgtWhichVecs.extent(0) <<
" != this->getNumVectors() = " << this->getNumVectors() <<
".");
1251 if (sourceMV.whichVectors_.size() == 0) {
1252 Kokkos::DualView<size_t*, device_type> tmpSrc(
"srcWhichVecs", numCols);
1253 tmpSrc.modify_host();
1254 for (
size_t j = 0; j < numCols; ++j) {
1255 tmpSrc.view_host()(j) = j;
1258 tmpSrc.sync_device();
1260 srcWhichVecs = tmpSrc;
1262 Teuchos::ArrayView<const size_t> srcWhichVecsT =
1263 sourceMV.whichVectors_();
1265 getDualViewCopyFromArrayView<size_t, device_type>(srcWhichVecsT,
1269 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(srcWhichVecs.extent(0)) !=
1270 sourceMV.getNumVectors(),
1272 "srcWhichVecs.extent(0) = " << srcWhichVecs.extent(0)
1273 <<
" != sourceMV.getNumVectors() = " << sourceMV.getNumVectors()
1279 std::ostringstream os;
1280 os << *prefix <<
"Get permute LIDs on host" << std::endl;
1281 std::cerr << os.str();
1283 auto tgt_h = this->getLocalViewHost(Access::ReadWrite);
1284 auto src_h = sourceMV.getLocalViewHost(Access::ReadOnly);
1286 TEUCHOS_ASSERT(!permuteToLIDs.need_sync_host());
1287 auto permuteToLIDs_h = create_const_view(permuteToLIDs.view_host());
1288 TEUCHOS_ASSERT(!permuteFromLIDs.need_sync_host());
1289 auto permuteFromLIDs_h =
1290 create_const_view(permuteFromLIDs.view_host());
1293 std::ostringstream os;
1294 os << *prefix <<
"Permute on host" << endl;
1295 std::cerr << os.str();
1297 if (nonConstStride) {
1300 auto tgtWhichVecs_h =
1301 create_const_view(tgtWhichVecs.view_host());
1302 auto srcWhichVecs_h =
1303 create_const_view(srcWhichVecs.view_host());
1305 using op_type = KokkosRefactor::Details::AddOp;
1306 permute_array_multi_column_variable_stride(tgt_h, src_h,
1310 srcWhichVecs_h, numCols,
1313 using op_type = KokkosRefactor::Details::InsertOp;
1314 permute_array_multi_column_variable_stride(tgt_h, src_h,
1318 srcWhichVecs_h, numCols,
1323 using op_type = KokkosRefactor::Details::AddOp;
1324 permute_array_multi_column(tgt_h, src_h, permuteToLIDs_h,
1325 permuteFromLIDs_h, numCols, op_type());
1327 using op_type = KokkosRefactor::Details::InsertOp;
1328 permute_array_multi_column(tgt_h, src_h, permuteToLIDs_h,
1329 permuteFromLIDs_h, numCols, op_type());
1334 std::ostringstream os;
1335 os << *prefix <<
"Get permute LIDs on device" << endl;
1336 std::cerr << os.str();
1338 auto tgt_d = this->getLocalViewDevice(Access::ReadWrite);
1339 auto src_d = sourceMV.getLocalViewDevice(Access::ReadOnly);
1341 TEUCHOS_ASSERT(!permuteToLIDs.need_sync_device());
1342 auto permuteToLIDs_d = create_const_view(permuteToLIDs.view_device());
1343 TEUCHOS_ASSERT(!permuteFromLIDs.need_sync_device());
1344 auto permuteFromLIDs_d =
1345 create_const_view(permuteFromLIDs.view_device());
1348 std::ostringstream os;
1349 os << *prefix <<
"Permute on device" << endl;
1350 std::cerr << os.str();
1352 if (nonConstStride) {
1355 auto tgtWhichVecs_d = create_const_view(tgtWhichVecs.view_device());
1356 auto srcWhichVecs_d = create_const_view(srcWhichVecs.view_device());
1358 using op_type = KokkosRefactor::Details::AddOp;
1359 permute_array_multi_column_variable_stride(space, tgt_d, src_d,
1363 srcWhichVecs_d, numCols,
1366 using op_type = KokkosRefactor::Details::InsertOp;
1367 permute_array_multi_column_variable_stride(space, tgt_d, src_d,
1371 srcWhichVecs_d, numCols,
1376 using op_type = KokkosRefactor::Details::AddOp;
1377 permute_array_multi_column(space, tgt_d, src_d, permuteToLIDs_d,
1378 permuteFromLIDs_d, numCols, op_type());
1380 using op_type = KokkosRefactor::Details::InsertOp;
1381 permute_array_multi_column(space, tgt_d, src_d, permuteToLIDs_d,
1382 permuteFromLIDs_d, numCols, op_type());
1388 std::ostringstream os;
1389 os << *prefix <<
"Done!" << endl;
1390 std::cerr << os.str();
1394template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1397 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
1398 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs,
1400 copyAndPermute(sourceObj, numSameIDs, permuteToLIDs, permuteFromLIDs, CM,
1404template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1407 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
1408 Kokkos::DualView<impl_scalar_type*, buffer_device_type>& exports,
1409 Kokkos::DualView<size_t*, buffer_device_type> ,
1410 size_t& constantNumPackets,
1412 using Kokkos::Compat::create_const_view;
1413 using Kokkos::Compat::getKokkosViewDeepCopy;
1421 MV& sourceMV =
const_cast<MV&
>(
dynamic_cast<const MV&
>(sourceObj));
1423 const bool packOnHost = runKernelOnHost(sourceMV);
1424 const char longFuncNameHost[] =
"Tpetra::MultiVector::packAndPrepare[Host]";
1425 const char longFuncNameDevice[] =
"Tpetra::MultiVector::packAndPrepare[Device]";
1426 const char tfecfFuncName[] =
"packAndPrepare: ";
1427 ProfilingRegion regionPAP(packOnHost ? longFuncNameHost : longFuncNameDevice);
1435 const bool debugCheckIndices = Behavior::debug();
1440 const bool printDebugOutput = Behavior::verbose();
1442 std::unique_ptr<std::string> prefix;
1443 if (printDebugOutput) {
1444 auto map = this->
getMap();
1445 auto comm = map.is_null() ? Teuchos::null : map->getComm();
1446 const int myRank = comm.is_null() ? -1 : comm->getRank();
1447 std::ostringstream os;
1448 os <<
"Proc " << myRank <<
": MV::packAndPrepare: ";
1449 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
1450 os <<
"Start" << endl;
1451 std::cerr << os.str();
1454 const size_t numCols = sourceMV.getNumVectors();
1459 constantNumPackets = numCols;
1463 if (exportLIDs.extent(0) == 0) {
1464 if (printDebugOutput) {
1465 std::ostringstream os;
1466 os << *prefix <<
"No exports on this proc, DONE" << std::endl;
1467 std::cerr << os.str();
1487 const size_t numExportLIDs = exportLIDs.extent(0);
1488 const size_t newExportsSize = numCols * numExportLIDs;
1489 if (printDebugOutput) {
1490 std::ostringstream os;
1491 os << *prefix <<
"realloc: "
1492 <<
"numExportLIDs: " << numExportLIDs
1493 <<
", exports.extent(0): " << exports.extent(0)
1494 <<
", newExportsSize: " << newExportsSize << std::endl;
1495 std::cerr << os.str();
1501 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(sourceMV.need_sync_device() && sourceMV.need_sync_host(),
1503 "Input MultiVector needs sync to both host "
1505 if (printDebugOutput) {
1506 std::ostringstream os;
1507 os << *prefix <<
"packOnHost=" << (packOnHost ?
"true" :
"false") << endl;
1508 std::cerr << os.str();
1520 exports.clear_sync_state();
1521 exports.modify_host();
1528 exports.clear_sync_state();
1529 exports.modify_device();
1545 if (sourceMV.isConstantStride()) {
1546 using KokkosRefactor::Details::pack_array_single_column;
1547 if (printDebugOutput) {
1548 std::ostringstream os;
1549 os << *prefix <<
"Pack numCols=1 const stride" << endl;
1550 std::cerr << os.str();
1553 auto src_host = sourceMV.getLocalViewHost(Access::ReadOnly);
1554 pack_array_single_column(exports.view_host(),
1556 exportLIDs.view_host(),
1560 auto src_dev = sourceMV.getLocalViewDevice(Access::ReadOnly);
1561 pack_array_single_column(exports.view_device(),
1563 exportLIDs.view_device(),
1569 using KokkosRefactor::Details::pack_array_single_column;
1570 if (printDebugOutput) {
1571 std::ostringstream os;
1572 os << *prefix <<
"Pack numCols=1 nonconst stride" << endl;
1573 std::cerr << os.str();
1576 auto src_host = sourceMV.getLocalViewHost(Access::ReadOnly);
1577 pack_array_single_column(exports.view_host(),
1579 exportLIDs.view_host(),
1580 sourceMV.whichVectors_[0],
1583 auto src_dev = sourceMV.getLocalViewDevice(Access::ReadOnly);
1584 pack_array_single_column(exports.view_device(),
1586 exportLIDs.view_device(),
1587 sourceMV.whichVectors_[0],
1593 if (sourceMV.isConstantStride()) {
1594 using KokkosRefactor::Details::pack_array_multi_column;
1595 if (printDebugOutput) {
1596 std::ostringstream os;
1597 os << *prefix <<
"Pack numCols=" << numCols <<
" const stride" << endl;
1598 std::cerr << os.str();
1601 auto src_host = sourceMV.getLocalViewHost(Access::ReadOnly);
1602 pack_array_multi_column(exports.view_host(),
1604 exportLIDs.view_host(),
1608 auto src_dev = sourceMV.getLocalViewDevice(Access::ReadOnly);
1609 pack_array_multi_column(exports.view_device(),
1611 exportLIDs.view_device(),
1617 using KokkosRefactor::Details::pack_array_multi_column_variable_stride;
1618 if (printDebugOutput) {
1619 std::ostringstream os;
1620 os << *prefix <<
"Pack numCols=" << numCols <<
" nonconst stride"
1622 std::cerr << os.str();
1628 using DV = Kokkos::DualView<IST*, device_type>;
1629 using HES =
typename DV::t_host::execution_space;
1630 using DES =
typename DV::t_dev::execution_space;
1631 Teuchos::ArrayView<const size_t> whichVecs = sourceMV.whichVectors_();
1633 auto src_host = sourceMV.getLocalViewHost(Access::ReadOnly);
1634 pack_array_multi_column_variable_stride(exports.view_host(),
1636 exportLIDs.view_host(),
1637 getKokkosViewDeepCopy<HES>(whichVecs),
1641 auto src_dev = sourceMV.getLocalViewDevice(Access::ReadOnly);
1642 pack_array_multi_column_variable_stride(exports.view_device(),
1644 exportLIDs.view_device(),
1645 getKokkosViewDeepCopy<DES>(whichVecs),
1647 debugCheckIndices, space);
1652 if (printDebugOutput) {
1653 std::ostringstream os;
1654 os << *prefix <<
"Done!" << endl;
1655 std::cerr << os.str();
1659template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1662 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
1663 Kokkos::DualView<impl_scalar_type*, buffer_device_type>& exports,
1664 Kokkos::DualView<size_t*, buffer_device_type> numExportPacketsPerLID,
1665 size_t& constantNumPackets) {
1666 packAndPrepare(sourceObj, exportLIDs, exports, numExportPacketsPerLID, constantNumPackets,
execution_space());
1669template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1671typename std::enable_if<std::is_same<typename Tpetra::Details::DefaultTypes::CommBufferMemorySpace<typename NO::execution_space>::type,
1672 typename NO::device_type::memory_space>::value,
1677 const std::string* prefix,
1678 const bool areRemoteLIDsContiguous,
1686 std::ostringstream os;
1687 os << *prefix <<
"Realloc (if needed) imports_ from "
1688 << this->
imports_.extent(0) <<
" to " << newSize << std::endl;
1689 std::cerr << os.str();
1692 bool reallocated =
false;
1695 using DV = Kokkos::DualView<IST*, Kokkos::LayoutLeft, buffer_device_type>;
1707 if ((std::is_same_v<typename dual_view_type::t_dev::device_type, typename dual_view_type::t_host::device_type> ||
1710 areRemoteLIDsContiguous &&
1715 reallocated = this->
imports_.view_device().data() !=
view_.getDualView().view_device().data() + offset;
1717 typedef std::pair<size_t, size_t> range_type;
1723 std::ostringstream os;
1724 os << *prefix <<
"Aliased imports_ to MV.view_" << std::endl;
1725 std::cerr << os.str();
1733 reallocDualViewIfNeeded(this->unaliased_imports_, newSize,
"imports");
1735 std::ostringstream os;
1736 os << *prefix <<
"Finished realloc'ing unaliased_imports_" << std::endl;
1737 std::cerr << os.str();
1739 this->imports_ = this->unaliased_imports_;
1744template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1746typename std::enable_if<!std::is_same<typename Tpetra::Details::DefaultTypes::CommBufferMemorySpace<typename NO::execution_space>::type,
1747 typename NO::device_type::memory_space>::value,
1752 const std::string* prefix,
1753 const bool areRemoteLIDsContiguous,
1758template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1762 const std::string* prefix,
1763 const bool areRemoteLIDsContiguous,
1766 return reallocImportsIfNeededImpl<Node>(newSize, verbose, prefix, areRemoteLIDsContiguous, CM);
1769template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1772 return (this->imports_.view_device().data() + this->imports_.view_device().extent(0) ==
1773 view_.getDualView().view_device().data() + view_.getDualView().view_device().extent(0));
1776template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1778 unpackAndCombine(
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& importLIDs,
1779 Kokkos::DualView<impl_scalar_type*, buffer_device_type> imports,
1780 Kokkos::DualView<size_t*, buffer_device_type> ,
1781 const size_t constantNumPackets,
1784 using Kokkos::Compat::getKokkosViewDeepCopy;
1785 using KokkosRefactor::Details::unpack_array_multi_column;
1786 using KokkosRefactor::Details::unpack_array_multi_column_variable_stride;
1791 const bool unpackOnHost = runKernelOnHost(imports);
1793 const char longFuncNameHost[] =
"Tpetra::MultiVector::unpackAndCombine[Host]";
1794 const char longFuncNameDevice[] =
"Tpetra::MultiVector::unpackAndCombine[Device]";
1795 const char* longFuncName = unpackOnHost ? longFuncNameHost : longFuncNameDevice;
1796 const char tfecfFuncName[] =
"unpackAndCombine: ";
1804 const bool debugCheckIndices = Behavior::debug();
1806 const bool printDebugOutput = Behavior::verbose();
1807 std::unique_ptr<std::string> prefix;
1808 if (printDebugOutput) {
1809 auto map = this->
getMap();
1810 auto comm = map.is_null() ? Teuchos::null : map->getComm();
1811 const int myRank = comm.is_null() ? -1 : comm->getRank();
1812 std::ostringstream os;
1813 os <<
"Proc " << myRank <<
": " << longFuncName <<
": ";
1814 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
1815 os <<
"Start" << endl;
1816 std::cerr << os.str();
1820 if (importLIDs.extent(0) == 0) {
1821 if (printDebugOutput) {
1822 std::ostringstream os;
1823 os << *prefix <<
"No imports. Done!" << endl;
1824 std::cerr << os.str();
1830 if (importsAreAliased()) {
1831 if (printDebugOutput) {
1832 std::ostringstream os;
1833 os << *prefix <<
"Skipping unpack, since imports_ is aliased to MV.view_. Done!" << endl;
1834 std::cerr << os.str();
1839 ProfilingRegion regionUAC(longFuncName);
1841 const size_t numVecs = getNumVectors();
1842 if (debugCheckIndices) {
1843 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(imports.extent(0)) !=
1844 numVecs * importLIDs.extent(0),
1846 "imports.extent(0) = " << imports.extent(0)
1847 <<
" != getNumVectors() * importLIDs.extent(0) = " << numVecs
1848 <<
" * " << importLIDs.extent(0) <<
" = "
1849 << numVecs * importLIDs.extent(0) <<
".");
1851 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(constantNumPackets ==
static_cast<size_t>(0), std::runtime_error,
1852 "constantNumPackets input argument must be nonzero.");
1854 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(numVecs) !=
1855 static_cast<size_t>(constantNumPackets),
1856 std::runtime_error,
"constantNumPackets must equal numVecs.");
1865 if (this->imports_.need_sync_host()) this->imports_.sync_host();
1867 if (this->imports_.need_sync_device()) this->imports_.sync_device();
1870 if (printDebugOutput) {
1871 std::ostringstream os;
1872 os << *prefix <<
"unpackOnHost=" << (unpackOnHost ?
"true" :
"false")
1874 std::cerr << os.str();
1879 auto imports_d = imports.view_device();
1880 auto imports_h = imports.view_host();
1881 auto importLIDs_d = importLIDs.view_device();
1882 auto importLIDs_h = importLIDs.view_host();
1884 Kokkos::DualView<size_t*, device_type> whichVecs;
1885 if (!isConstantStride()) {
1886 Kokkos::View<
const size_t*, Kokkos::HostSpace,
1887 Kokkos::MemoryUnmanaged>
1888 whichVecsIn(whichVectors_.getRawPtr(),
1890 whichVecs = Kokkos::DualView<size_t*, device_type>(
"whichVecs", numVecs);
1892 whichVecs.modify_host();
1894 Kokkos::deep_copy(whichVecs.view_host(), whichVecsIn);
1896 whichVecs.modify_device();
1898 Kokkos::deep_copy(whichVecs.view_device(), whichVecsIn);
1901 auto whichVecs_d = whichVecs.view_device();
1902 auto whichVecs_h = whichVecs.view_host();
1912 if (numVecs > 0 && importLIDs.extent(0) > 0) {
1913 using dev_exec_space =
typename dual_view_type::t_dev::execution_space;
1914 using host_exec_space =
typename dual_view_type::t_host::execution_space;
1917 const bool use_atomic_updates = unpackOnHost ? host_exec_space().concurrency() != 1 : dev_exec_space().concurrency() != 1;
1919 if (printDebugOutput) {
1920 std::ostringstream os;
1922 std::cerr << os.str();
1929 using op_type = KokkosRefactor::Details::InsertOp;
1930 if (isConstantStride()) {
1932 auto X_h = this->getLocalViewHost(Access::ReadWrite);
1933 unpack_array_multi_column(host_exec_space(),
1934 X_h, imports_h, importLIDs_h,
1940 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
1941 unpack_array_multi_column(space,
1942 X_d, imports_d, importLIDs_d,
1949 auto X_h = this->getLocalViewHost(Access::ReadWrite);
1950 unpack_array_multi_column_variable_stride(host_exec_space(),
1959 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
1960 unpack_array_multi_column_variable_stride(space,
1971 using op_type = KokkosRefactor::Details::AddOp;
1972 if (isConstantStride()) {
1974 auto X_h = this->getLocalViewHost(Access::ReadWrite);
1975 unpack_array_multi_column(host_exec_space(),
1976 X_h, imports_h, importLIDs_h,
1981 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
1982 unpack_array_multi_column(space,
1983 X_d, imports_d, importLIDs_d,
1990 auto X_h = this->getLocalViewHost(Access::ReadWrite);
1991 unpack_array_multi_column_variable_stride(host_exec_space(),
2000 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
2001 unpack_array_multi_column_variable_stride(space,
2011 }
else if (CM ==
ABSMAX) {
2012 using op_type = KokkosRefactor::Details::AbsMaxOp;
2016 unpack_array_multi_column(host_exec_space(),
2017 X_h, imports_h, importLIDs_h,
2022 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
2023 unpack_array_multi_column(space,
2024 X_d, imports_d, importLIDs_d,
2032 unpack_array_multi_column_variable_stride(host_exec_space(),
2041 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
2042 unpack_array_multi_column_variable_stride(space,
2053 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
"Invalid CombineMode");
2056 if (printDebugOutput) {
2057 std::ostringstream os;
2058 os << *prefix <<
"Nothing to unpack" << endl;
2059 std::cerr << os.str();
2063 if (printDebugOutput) {
2064 std::ostringstream os;
2065 os << *prefix <<
"Done!" << endl;
2066 std::cerr << os.str();
2070template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2072 unpackAndCombine(
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& importLIDs,
2073 Kokkos::DualView<impl_scalar_type*, buffer_device_type> imports,
2074 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
2075 const size_t constantNumPackets,
2080template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2085 return static_cast<size_t>(
view_.extent(1));
2094void gblDotImpl(
const RV& dotsOut,
2095 const Teuchos::RCP<
const Teuchos::Comm<int> >& comm,
2096 const bool distributed) {
2097 using Teuchos::REDUCE_MAX;
2098 using Teuchos::REDUCE_SUM;
2099 using Teuchos::reduceAll;
2100 typedef typename RV::non_const_value_type
dot_type;
2104 const size_t numVecs = dotsOut.extent(0);
2119 if (distributed && !comm.is_null()) {
2122 const int nv =
static_cast<int>(numVecs);
2125 if (commIsInterComm) {
2129 typename RV::non_const_type lclDots(Kokkos::ViewAllocateWithoutInitializing(
"tmp"), numVecs);
2131 Kokkos::deep_copy(lclDots, dotsOut);
2132 const dot_type*
const lclSum = lclDots.data();
2133 dot_type*
const gblSum = dotsOut.data();
2134 reduceAll<int, dot_type>(*comm, REDUCE_SUM, nv, lclSum, gblSum);
2136 dot_type*
const inout = dotsOut.data();
2137 reduceAll<int, dot_type>(*comm, REDUCE_SUM, nv, inout, inout);
2143template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2146 const Kokkos::View<dot_type*, Kokkos::HostSpace>& dots)
const {
2147 using Kokkos::subview;
2148 using Teuchos::Comm;
2149 using Teuchos::null;
2153 typedef Kokkos::View<dot_type*, Kokkos::HostSpace> RV;
2154 typedef typename dual_view_type::t_dev_const XMV;
2155 const char tfecfFuncName[] =
"Tpetra::MultiVector::dot: ";
2163 const size_t lclNumRows = this->getLocalLength();
2164 const size_t numDots =
static_cast<size_t>(dots.extent(0));
2165 const bool debug = Behavior::debug();
2168 const bool compat = this->getMap()->isCompatible(*(A.
getMap()));
2169 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!compat, std::invalid_argument,
2170 "'*this' MultiVector is not "
2171 "compatible with the input MultiVector A. We only test for this "
2182 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2184 "MultiVectors do not have the same local length. "
2185 "this->getLocalLength() = "
2186 << lclNumRows <<
" != "
2187 "A.getLocalLength() = "
2189 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2191 "MultiVectors must have the same number of columns (vectors). "
2192 "this->getNumVectors() = "
2193 << numVecs <<
" != "
2194 "A.getNumVectors() = "
2196 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2197 numDots != numVecs, std::runtime_error,
2198 "The output array 'dots' must have the same number of entries as the "
2199 "number of columns (vectors) in *this and A. dots.extent(0) = "
2200 << numDots <<
" != this->getNumVectors() = " << numVecs <<
".");
2202 const std::pair<size_t, size_t> colRng(0, numVecs);
2203 RV dotsOut = subview(dots, colRng);
2204 RCP<const Comm<int> > comm = this->getMap().is_null() ? null : this->getMap()->getComm();
2206 auto thisView = this->getLocalViewDevice(Access::ReadOnly);
2209 ::Tpetra::Details::lclDot<RV, XMV>(dotsOut, thisView, A_view, lclNumRows, numVecs,
2221 exec_space_instance.fence(
"Tpetra::MultiVector::dot");
2223 gblDotImpl(dotsOut, comm, this->isDistributed());
2227template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2233 using dot_type =
typename MV::dot_type;
2234 ProfilingRegion region(
"Tpetra::multiVectorSingleColumnDot");
2237 Teuchos::RCP<const Teuchos::Comm<int> > comm =
2238 map.is_null() ? Teuchos::null : map->getComm();
2239 if (comm.is_null()) {
2240 return KokkosKernels::ArithTraits<dot_type>::zero();
2242 dot_type lclDot = KokkosKernels::ArithTraits<dot_type>::zero();
2243 dot_type gblDot = KokkosKernels::ArithTraits<dot_type>::zero();
2245 ProfilingRegion regionLclDot(
"Tpetra::multiVectorSingleColumnDot::lclDot");
2246 using LO = LocalOrdinal;
2250 const LO lclNumRows =
static_cast<LO
>(std::min(x.
getLocalLength(),
2252 const Kokkos::pair<LO, LO> rowRng(0, lclNumRows);
2259 auto x_1d = Kokkos::subview(x_2d, rowRng, 0);
2261 auto y_1d = Kokkos::subview(y_2d, rowRng, 0);
2262 lclDot = KokkosBlas::dot(x_1d, y_1d);
2266 ProfilingRegion regionReduce(
"Tpetra::multiVectorSingleColumnDot::reduce");
2267 using Teuchos::outArg;
2268 using Teuchos::REDUCE_SUM;
2269 using Teuchos::reduceAll;
2270 reduceAll<int, dot_type>(*comm, REDUCE_SUM, lclDot, outArg(gblDot));
2279template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2282 const Teuchos::ArrayView<dot_type>& dots)
const {
2283 const char tfecfFuncName[] =
"dot: ";
2288 const size_t numDots =
static_cast<size_t>(dots.size());
2298 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclNumRows != A.
getLocalLength(), std::runtime_error,
2299 "MultiVectors do not have the same local length. "
2300 "this->getLocalLength() = "
2301 << lclNumRows <<
" != "
2302 "A.getLocalLength() = "
2304 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numVecs != A.
getNumVectors(), std::runtime_error,
2305 "MultiVectors must have the same number of columns (vectors). "
2306 "this->getNumVectors() = "
2307 << numVecs <<
" != "
2308 "A.getNumVectors() = "
2310 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numDots != numVecs, std::runtime_error,
2311 "The output array 'dots' must have the same number of entries as the "
2312 "number of columns (vectors) in *this and A. dots.extent(0) = "
2313 << numDots <<
" != this->getNumVectors() = " << numVecs <<
".");
2316 const dot_type gblDot = multiVectorSingleColumnDot(*
this, A);
2319 this->dot(A, Kokkos::View<dot_type*, Kokkos::HostSpace>(dots.getRawPtr(), numDots));
2323template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2325 norm2(
const Teuchos::ArrayView<mag_type>& norms)
const {
2327 using ::Tpetra::Details::NORM_TWO;
2329 ProfilingRegion region(
"Tpetra::MV::norm2 (host output)");
2332 MV& X =
const_cast<MV&
>(*this);
2333 multiVectorNormImpl(norms.getRawPtr(), X, NORM_TWO);
2336template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2338 norm2(
const Kokkos::View<mag_type*, Kokkos::HostSpace>& norms)
const {
2339 Teuchos::ArrayView<mag_type> norms_av(norms.data(), norms.extent(0));
2340 this->
norm2(norms_av);
2343template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2345 norm1(
const Teuchos::ArrayView<mag_type>& norms)
const {
2347 using ::Tpetra::Details::NORM_ONE;
2349 ProfilingRegion region(
"Tpetra::MV::norm1 (host output)");
2352 MV& X =
const_cast<MV&
>(*this);
2353 multiVectorNormImpl(norms.data(), X, NORM_ONE);
2356template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2358 norm1(
const Kokkos::View<mag_type*, Kokkos::HostSpace>& norms)
const {
2359 Teuchos::ArrayView<mag_type> norms_av(norms.data(), norms.extent(0));
2360 this->
norm1(norms_av);
2363template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2365 normInf(
const Teuchos::ArrayView<mag_type>& norms)
const {
2367 using ::Tpetra::Details::NORM_INF;
2369 ProfilingRegion region(
"Tpetra::MV::normInf (host output)");
2372 MV& X =
const_cast<MV&
>(*this);
2373 multiVectorNormImpl(norms.getRawPtr(), X, NORM_INF);
2376template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2378 normInf(
const Kokkos::View<mag_type*, Kokkos::HostSpace>& norms)
const {
2379 Teuchos::ArrayView<mag_type> norms_av(norms.data(), norms.extent(0));
2383template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2385 meanValue(
const Teuchos::ArrayView<impl_scalar_type>& means)
const {
2388 using Kokkos::subview;
2389 using Teuchos::Comm;
2391 using Teuchos::REDUCE_SUM;
2392 using Teuchos::reduceAll;
2393 typedef KokkosKernels::ArithTraits<impl_scalar_type> ATS;
2397 const size_t numMeans =
static_cast<size_t>(means.size());
2399 TEUCHOS_TEST_FOR_EXCEPTION(
2400 numMeans != numVecs, std::runtime_error,
2401 "Tpetra::MultiVector::meanValue: means.size() = " << numMeans
2402 <<
" != this->getNumVectors() = " << numVecs <<
".");
2404 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
2405 const std::pair<size_t, size_t> colRng(0, numVecs);
2410 typedef Kokkos::View<impl_scalar_type*, device_type> local_view_type;
2412 typename local_view_type::host_mirror_type::array_layout,
2414 Kokkos::MemoryTraits<Kokkos::Unmanaged> >
2415 host_local_view_type;
2416 host_local_view_type meansOut(means.getRawPtr(), numMeans);
2418 RCP<const Comm<int> > comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
2422 if (useHostVersion) {
2425 rowRng, Kokkos::ALL());
2427 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace> lclSums(
"MV::meanValue tmp", numVecs);
2429 KokkosBlas::sum(lclSums, X_lcl);
2431 for (
size_t j = 0; j < numVecs; ++j) {
2433 KokkosBlas::sum(subview(lclSums, j), subview(X_lcl, ALL(), col));
2440 if (!comm.is_null() && this->isDistributed()) {
2441 reduceAll(*comm, REDUCE_SUM,
static_cast<int>(numVecs),
2442 lclSums.data(), meansOut.data());
2445 Kokkos::deep_copy(meansOut, lclSums);
2450 rowRng, Kokkos::ALL());
2453 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace> lclSums(
"MV::meanValue tmp", numVecs);
2455 KokkosBlas::sum(lclSums, X_lcl);
2457 for (
size_t j = 0; j < numVecs; ++j) {
2459 KokkosBlas::sum(subview(lclSums, j), subview(X_lcl, ALL(), col));
2469 exec_space_instance.fence(
"Tpetra::MultiVector::mean");
2475 if (!comm.is_null() && this->isDistributed()) {
2476 reduceAll(*comm, REDUCE_SUM,
static_cast<int>(numVecs),
2477 lclSums.data(), meansOut.data());
2480 Kokkos::deep_copy(meansOut, lclSums);
2489 for (
size_t k = 0; k < numMeans; ++k) {
2490 meansOut(k) = meansOut(k) * OneOverN;
2494template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2498 typedef KokkosKernels::ArithTraits<IST> ATS;
2499 typedef Kokkos::Random_XorShift64_Pool<typename device_type::execution_space> pool_type;
2500 typedef typename pool_type::generator_type generator_type;
2502 const IST max = Kokkos::rand<generator_type, IST>::max();
2503 const IST min = ATS::is_signed ? IST(-max) : ATS::zero();
2505 this->
randomize(
static_cast<Scalar
>(min),
static_cast<Scalar
>(max));
2508template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2510 randomize(
const Scalar& minVal,
const Scalar& maxVal) {
2512 typedef Tpetra::Details::Static_Random_XorShift64_Pool<typename device_type::execution_space> tpetra_pool_type;
2513 typedef Kokkos::Random_XorShift64_Pool<typename device_type::execution_space> pool_type;
2516 if (!tpetra_pool_type::isSet())
2517 tpetra_pool_type::resetPool(this->
getMap()->getComm()->getRank());
2519 pool_type& rand_pool = tpetra_pool_type::getPool();
2520 const IST max =
static_cast<IST
>(maxVal);
2521 const IST min =
static_cast<IST
>(minVal);
2526 Kokkos::fill_random(thisView, rand_pool, min, max);
2529 for (
size_t k = 0; k < numVecs; ++k) {
2531 auto X_k = Kokkos::subview(thisView, Kokkos::ALL(), col);
2532 Kokkos::fill_random(X_k, rand_pool, min, max);
2537template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2542 using DES =
typename dual_view_type::t_dev::execution_space;
2543 using HES =
typename dual_view_type::t_host::execution_space;
2544 using LO = LocalOrdinal;
2545 ProfilingRegion region(
"Tpetra::MultiVector::putScalar");
2557 const bool runOnHost = runKernelOnHost(*
this);
2560 if (this->isConstantStride()) {
2561 fill(DES(), X, theAlpha, lclNumRows, numVecs);
2563 fill(DES(), X, theAlpha, lclNumRows, numVecs,
2568 if (this->isConstantStride()) {
2569 fill(HES(), X, theAlpha, lclNumRows, numVecs);
2571 fill(HES(), X, theAlpha, lclNumRows, numVecs,
2577template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2579 replaceMap(
const Teuchos::RCP<const map_type>& newMap) {
2580 using Teuchos::ArrayRCP;
2581 using Teuchos::Comm;
2584 using LO = LocalOrdinal;
2585 using GO = GlobalOrdinal;
2591 TEUCHOS_TEST_FOR_EXCEPTION(
2592 !this->isConstantStride(), std::logic_error,
2593 "Tpetra::MultiVector::replaceMap: This method does not currently work "
2594 "if the MultiVector is a column view of another MultiVector (that is, if "
2595 "isConstantStride() == false).");
2625 if (this->
getMap().is_null()) {
2630 TEUCHOS_TEST_FOR_EXCEPTION(
2631 newMap.is_null(), std::invalid_argument,
2632 "Tpetra::MultiVector::replaceMap: both current and new Maps are null. "
2633 "This probably means that the input Map is incorrect.");
2637 const size_t newNumRows = newMap->getLocalNumElements();
2638 const size_t origNumRows =
view_.extent(0);
2641 if (origNumRows != newNumRows ||
view_.extent(1) != numCols) {
2642 view_ = allocDualView<ST, LO, GO, Node>(newNumRows, numCols);
2644 }
else if (newMap.is_null()) {
2647 const size_t newNumRows =
static_cast<size_t>(0);
2649 view_ = allocDualView<ST, LO, GO, Node>(newNumRows, numCols);
2652 this->
map_ = newMap;
2655template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2657 scale(
const Scalar& alpha) {
2661 const IST theAlpha =
static_cast<IST
>(alpha);
2662 if (theAlpha == KokkosKernels::ArithTraits<IST>::one()) {
2667 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
2668 const std::pair<size_t, size_t> colRng(0, numVecs);
2677 if (useHostVersion) {
2678 auto Y_lcl = Kokkos::subview(
getLocalViewHost(Access::ReadWrite), rowRng, ALL());
2680 KokkosBlas::scal(Y_lcl, theAlpha, Y_lcl);
2682 for (
size_t k = 0; k < numVecs; ++k) {
2684 auto Y_k = Kokkos::subview(Y_lcl, ALL(), Y_col);
2685 KokkosBlas::scal(Y_k, theAlpha, Y_k);
2691 KokkosBlas::scal(Y_lcl, theAlpha, Y_lcl);
2693 for (
size_t k = 0; k < numVecs; ++k) {
2695 auto Y_k = Kokkos::subview(Y_lcl, ALL(), Y_col);
2696 KokkosBlas::scal(Y_k, theAlpha, Y_k);
2702template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2704 scale(
const Teuchos::ArrayView<const Scalar>& alphas) {
2706 const size_t numAlphas =
static_cast<size_t>(alphas.size());
2707 TEUCHOS_TEST_FOR_EXCEPTION(
2708 numAlphas != numVecs, std::invalid_argument,
2709 "Tpetra::MultiVector::"
2710 "scale: alphas.size() = "
2711 << numAlphas <<
" != this->getNumVectors() = "
2715 using k_alphas_type = Kokkos::DualView<impl_scalar_type*, device_type>;
2716 k_alphas_type k_alphas(
"alphas::tmp", numAlphas);
2717 k_alphas.modify_host();
2718 for (
size_t i = 0; i < numAlphas; ++i) {
2721 k_alphas.sync_device();
2723 this->
scale(k_alphas.view_device());
2726template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2728 scale(
const Kokkos::View<const impl_scalar_type*, device_type>& alphas) {
2730 using Kokkos::subview;
2734 TEUCHOS_TEST_FOR_EXCEPTION(
2735 static_cast<size_t>(alphas.extent(0)) != numVecs,
2736 std::invalid_argument,
2737 "Tpetra::MultiVector::scale(alphas): "
2738 "alphas.extent(0) = "
2740 <<
" != this->getNumVectors () = " << numVecs <<
".");
2741 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
2742 const std::pair<size_t, size_t> colRng(0, numVecs);
2753 if (useHostVersion) {
2756 auto alphas_h = Kokkos::create_mirror_view(alphas);
2758 Kokkos::deep_copy(alphas_h, alphas);
2760 auto Y_lcl = subview(this->
getLocalViewHost(Access::ReadWrite), rowRng, ALL());
2762 KokkosBlas::scal(Y_lcl, alphas_h, Y_lcl);
2764 for (
size_t k = 0; k < numVecs; ++k) {
2765 const size_t Y_col = this->isConstantStride() ? k : this->
whichVectors_[k];
2766 auto Y_k = subview(Y_lcl, ALL(), Y_col);
2769 KokkosBlas::scal(Y_k, alphas_h(k), Y_k);
2775 KokkosBlas::scal(Y_lcl, alphas, Y_lcl);
2781 auto alphas_h = Kokkos::create_mirror_view(alphas);
2783 Kokkos::deep_copy(alphas_h, alphas);
2785 for (
size_t k = 0; k < numVecs; ++k) {
2786 const size_t Y_col = this->isConstantStride() ? k : this->
whichVectors_[k];
2787 auto Y_k = subview(Y_lcl, ALL(), Y_col);
2788 KokkosBlas::scal(Y_k, alphas_h(k), Y_k);
2794template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2796 scale(
const Scalar& alpha,
2799 using Kokkos::subview;
2800 const char tfecfFuncName[] =
"scale: ";
2805 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2807 "this->getLocalLength() = " << lclNumRows <<
" != A.getLocalLength() = "
2809 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2811 "this->getNumVectors() = " << numVecs <<
" != A.getNumVectors() = "
2815 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
2816 const std::pair<size_t, size_t> colRng(0, numVecs);
2820 auto Y_lcl = subview(Y_lcl_orig, rowRng, ALL());
2821 auto X_lcl = subview(X_lcl_orig, rowRng, ALL());
2824 KokkosBlas::scal(Y_lcl, theAlpha, X_lcl);
2827 for (
size_t k = 0; k < numVecs; ++k) {
2828 const size_t Y_col = this->isConstantStride() ? k : this->
whichVectors_[k];
2830 auto Y_k = subview(Y_lcl, ALL(), Y_col);
2831 auto X_k = subview(X_lcl, ALL(), X_col);
2833 KokkosBlas::scal(Y_k, theAlpha, X_k);
2838template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2841 const char tfecfFuncName[] =
"reciprocal: ";
2843 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2845 "MultiVectors do not have the same local length. "
2846 "this->getLocalLength() = "
2849 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2850 A.
getNumVectors() != this->getNumVectors(), std::runtime_error,
2851 ": MultiVectors do not have the same number of columns (vectors). "
2852 "this->getNumVectors() = "
2862 KokkosBlas::reciprocal(this_view_dev, A_view_dev);
2865 using Kokkos::subview;
2866 for (
size_t k = 0; k < numVecs; ++k) {
2868 auto vector_k = subview(this_view_dev, ALL(), this_col);
2870 auto vector_Ak = subview(A_view_dev, ALL(), A_col);
2871 KokkosBlas::reciprocal(vector_k, vector_Ak);
2876template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2879 const char tfecfFuncName[] =
"abs";
2881 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2883 ": MultiVectors do not have the same local length. "
2884 "this->getLocalLength() = "
2887 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2888 A.
getNumVectors() != this->getNumVectors(), std::runtime_error,
2889 ": MultiVectors do not have the same number of columns (vectors). "
2890 "this->getNumVectors() = "
2899 KokkosBlas::abs(this_view_dev, A_view_dev);
2902 using Kokkos::subview;
2904 for (
size_t k = 0; k < numVecs; ++k) {
2906 auto vector_k = subview(this_view_dev, ALL(), this_col);
2908 auto vector_Ak = subview(A_view_dev, ALL(), A_col);
2909 KokkosBlas::abs(vector_k, vector_Ak);
2914template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2916 update(
const Scalar& alpha,
2918 const Scalar& beta) {
2919 const char tfecfFuncName[] =
"update: ";
2921 using Kokkos::subview;
2929 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2931 "this->getLocalLength() = " << lclNumRows <<
" != A.getLocalLength() = "
2933 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2935 "this->getNumVectors() = " << numVecs <<
" != A.getNumVectors() = "
2941 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
2942 const std::pair<size_t, size_t> colRng(0, numVecs);
2945 auto Y_lcl = subview(Y_lcl_orig, rowRng, Kokkos::ALL());
2947 auto X_lcl = subview(X_lcl_orig, rowRng, Kokkos::ALL());
2951 KokkosBlas::axpby(theAlpha, X_lcl, theBeta, Y_lcl);
2954 for (
size_t k = 0; k < numVecs; ++k) {
2955 const size_t Y_col = this->isConstantStride() ? k : this->
whichVectors_[k];
2957 auto Y_k = subview(Y_lcl, ALL(), Y_col);
2958 auto X_k = subview(X_lcl, ALL(), X_col);
2960 KokkosBlas::axpby(theAlpha, X_k, theBeta, Y_k);
2965template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2967 update(
const Scalar& alpha,
2971 const Scalar& gamma) {
2973 using Kokkos::subview;
2975 const char tfecfFuncName[] =
"update(alpha,A,beta,B,gamma): ";
2983 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2985 "The input MultiVector A has " << A.
getLocalLength() <<
" local "
2986 "row(s), but this MultiVector has "
2987 << lclNumRows <<
" local "
2989 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2991 "The input MultiVector B has " << B.
getLocalLength() <<
" local "
2992 "row(s), but this MultiVector has "
2993 << lclNumRows <<
" local "
2995 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2997 "The input MultiVector A has " << A.
getNumVectors() <<
" column(s), "
2998 "but this MultiVector has "
2999 << numVecs <<
" column(s).");
3000 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3002 "The input MultiVector B has " << B.
getNumVectors() <<
" column(s), "
3003 "but this MultiVector has "
3004 << numVecs <<
" column(s).");
3011 const std::pair<size_t, size_t> rowRng(0, lclNumRows);
3012 const std::pair<size_t, size_t> colRng(0, numVecs);
3022 KokkosBlas::update(theAlpha, A_lcl, theBeta, B_lcl, theGamma, C_lcl);
3026 for (
size_t k = 0; k < numVecs; ++k) {
3030 KokkosBlas::update(theAlpha, subview(A_lcl, rowRng, A_col),
3031 theBeta, subview(B_lcl, rowRng, B_col),
3032 theGamma, subview(C_lcl, rowRng, this_col));
3037template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3038Teuchos::ArrayRCP<const Scalar>
3043 const char tfecfFuncName[] =
"getData: ";
3052 auto hostView_j = Kokkos::subview(hostView, ALL(), col);
3053 Teuchos::ArrayRCP<const IST> dataAsArcp =
3056 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(hostView_j.extent(0)) <
3057 static_cast<size_t>(dataAsArcp.size()),
3059 "hostView_j.extent(0) = " << hostView_j.extent(0)
3060 <<
" < dataAsArcp.size() = " << dataAsArcp.size() <<
". "
3061 "Please report this bug to the Tpetra developers.");
3063 return Teuchos::arcp_reinterpret_cast<const Scalar>(dataAsArcp);
3066template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3067Teuchos::ArrayRCP<Scalar>
3071 using Kokkos::subview;
3073 const char tfecfFuncName[] =
"getDataNonConst: ";
3077 auto hostView_j = subview(hostView, ALL(), col);
3078 Teuchos::ArrayRCP<IST> dataAsArcp =
3081 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(hostView_j.extent(0)) <
3082 static_cast<size_t>(dataAsArcp.size()),
3084 "hostView_j.extent(0) = " << hostView_j.extent(0)
3085 <<
" < dataAsArcp.size() = " << dataAsArcp.size() <<
". "
3086 "Please report this bug to the Tpetra developers.");
3088 return Teuchos::arcp_reinterpret_cast<Scalar>(dataAsArcp);
3091template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3092Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3094 subCopy(
const Teuchos::ArrayView<const size_t>& cols)
const {
3100 bool contiguous =
true;
3101 const size_t numCopyVecs =
static_cast<size_t>(cols.size());
3102 for (
size_t j = 1; j < numCopyVecs; ++j) {
3103 if (cols[j] != cols[j - 1] +
static_cast<size_t>(1)) {
3108 if (contiguous && numCopyVecs > 0) {
3109 return this->
subCopy(Teuchos::Range1D(cols[0], cols[numCopyVecs - 1]));
3111 RCP<const MV> X_sub = this->
subView(cols);
3112 RCP<MV> Y(
new MV(this->
getMap(), numCopyVecs,
false));
3118template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3119Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3121 subCopy(
const Teuchos::Range1D& colRng)
const {
3125 RCP<const MV> X_sub = this->
subView(colRng);
3126 RCP<MV> Y(
new MV(this->
getMap(),
static_cast<size_t>(colRng.size()),
false));
3131template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3135 return view_.origExtent(0);
3138template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3142 return view_.origExtent(1);
3145template <
class Scalar,
class LO,
class GO,
class Node>
3148 const Teuchos::RCP<const map_type>& subMap,
3150 : base_type(subMap) {
3152 using Kokkos::subview;
3154 using Teuchos::outArg;
3157 using Teuchos::REDUCE_MIN;
3158 using Teuchos::reduceAll;
3160 const char prefix[] =
"Tpetra::MultiVector constructor (offsetView): ";
3161 const char suffix[] =
"Please report this bug to the Tpetra developers.";
3164 std::unique_ptr<std::ostringstream> errStrm;
3171 const auto comm = subMap->getComm();
3172 TEUCHOS_ASSERT(!comm.is_null());
3173 const int myRank = comm->getRank();
3177 const LO newNumRows =
static_cast<LO
>(subMap->getLocalNumElements());
3179 std::ostringstream os;
3180 os <<
"Proc " << myRank <<
": " << prefix
3181 <<
"X: {lclNumRows: " << lclNumRowsBefore
3183 <<
", numCols: " << numCols <<
"}, "
3184 <<
"subMap: {lclNumRows: " << newNumRows <<
"}" << endl;
3185 std::cerr << os.str();
3190 const bool tooManyElts =
3193 errStrm = std::unique_ptr<std::ostringstream>(
new std::ostringstream);
3194 *errStrm <<
" Proc " << myRank <<
": subMap->getLocalNumElements() (="
3195 << newNumRows <<
") + rowOffset (=" << rowOffset
3199 TEUCHOS_TEST_FOR_EXCEPTION(!debug && tooManyElts, std::invalid_argument,
3200 prefix << errStrm->str() << suffix);
3204 reduceAll<int, int>(*comm, REDUCE_MIN, lclGood, outArg(gblGood));
3206 std::ostringstream gblErrStrm;
3207 const std::string myErrStr =
3208 errStrm.get() !=
nullptr ? errStrm->str() : std::string(
"");
3210 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, gblErrStrm.str());
3214 using range_type = std::pair<LO, LO>;
3215 const range_type origRowRng(rowOffset,
static_cast<LO
>(X.
view_.origExtent(0)));
3216 const range_type rowRng(rowOffset, rowOffset + newNumRows);
3218 wrapped_dual_view_type newView = takeSubview(X.
view_, rowRng, ALL());
3225 if (newView.extent(0) == 0 &&
3226 newView.extent(1) != X.
view_.extent(1)) {
3234 const LO lclNumRowsRet =
static_cast<LO
>(subViewMV.getLocalLength());
3235 const LO numColsRet =
static_cast<LO
>(subViewMV.getNumVectors());
3236 if (newNumRows != lclNumRowsRet || numCols != numColsRet) {
3238 if (errStrm.get() ==
nullptr) {
3239 errStrm = std::unique_ptr<std::ostringstream>(
new std::ostringstream);
3241 *errStrm <<
" Proc " << myRank <<
": subMap.getLocalNumElements(): " << newNumRows <<
", subViewMV.getLocalLength(): " << lclNumRowsRet <<
", X.getNumVectors(): " << numCols <<
", subViewMV.getNumVectors(): " << numColsRet << endl;
3243 reduceAll<int, int>(*comm, REDUCE_MIN, lclGood, outArg(gblGood));
3245 std::ostringstream gblErrStrm;
3247 gblErrStrm << prefix <<
"Returned MultiVector has the wrong local "
3248 "dimensions on one or more processes:"
3251 const std::string myErrStr =
3252 errStrm.get() !=
nullptr ? errStrm->str() : std::string(
"");
3254 gblErrStrm << suffix << endl;
3255 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, gblErrStrm.str());
3260 std::ostringstream os;
3261 os <<
"Proc " << myRank <<
": " << prefix <<
"Call op=" << endl;
3262 std::cerr << os.str();
3268 std::ostringstream os;
3269 os <<
"Proc " << myRank <<
": " << prefix <<
"Done!" << endl;
3270 std::cerr << os.str();
3274template <
class Scalar,
class LO,
class GO,
class Node>
3278 const size_t rowOffset)
3282template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3283Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3285 offsetView(
const Teuchos::RCP<const map_type>& subMap,
3286 const size_t offset)
const {
3288 return Teuchos::rcp(
new MV(*
this, *subMap, offset));
3291template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3292Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3295 const size_t offset) {
3297 return Teuchos::rcp(
new MV(*
this, *subMap, offset));
3300template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3301Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3303 subView(
const Teuchos::ArrayView<const size_t>& cols)
const {
3304 using Teuchos::Array;
3308 const size_t numViewCols =
static_cast<size_t>(cols.size());
3309 TEUCHOS_TEST_FOR_EXCEPTION(
3310 numViewCols < 1, std::runtime_error,
3311 "Tpetra::MultiVector::subView"
3312 "(const Teuchos::ArrayView<const size_t>&): The input array cols must "
3313 "contain at least one entry, but cols.size() = "
3319 bool contiguous =
true;
3320 for (
size_t j = 1; j < numViewCols; ++j) {
3321 if (cols[j] != cols[j - 1] +
static_cast<size_t>(1)) {
3327 if (numViewCols == 0) {
3329 return rcp(
new MV(this->
getMap(), numViewCols));
3332 return this->
subView(Teuchos::Range1D(cols[0], cols[numViewCols - 1]));
3339 Array<size_t> newcols(cols.size());
3340 for (
size_t j = 0; j < numViewCols; ++j) {
3343 return rcp(
new MV(this->
getMap(),
view_, newcols()));
3347template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3348Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3350 subView(
const Teuchos::Range1D& colRng)
const {
3352 using Kokkos::subview;
3353 using Teuchos::Array;
3358 const char tfecfFuncName[] =
"subView(Range1D): ";
3365 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3366 static_cast<size_t>(colRng.size()) > numVecs, std::runtime_error,
3367 "colRng.size() = " << colRng.size() <<
" > this->getNumVectors() = "
3369 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3370 numVecs != 0 && colRng.size() != 0 &&
3371 (colRng.lbound() <
static_cast<Teuchos::Ordinal
>(0) ||
3372 static_cast<size_t>(colRng.ubound()) >= numVecs),
3373 std::invalid_argument,
"Nonempty input range [" << colRng.lbound() <<
"," << colRng.ubound() <<
"] exceeds the valid range of column indices "
3375 << numVecs <<
"].");
3377 RCP<const MV> X_ret;
3387 const std::pair<size_t, size_t> rows(0, lclNumRows);
3388 if (colRng.size() == 0) {
3389 const std::pair<size_t, size_t> cols(0, 0);
3390 wrapped_dual_view_type X_sub = takeSubview(this->
view_, ALL(), cols);
3391 X_ret = rcp(
new MV(this->
getMap(), X_sub));
3395 const std::pair<size_t, size_t> cols(colRng.lbound(),
3396 colRng.ubound() + 1);
3397 wrapped_dual_view_type X_sub = takeSubview(this->
view_, ALL(), cols);
3398 X_ret = rcp(
new MV(this->
getMap(), X_sub));
3400 if (
static_cast<size_t>(colRng.size()) ==
static_cast<size_t>(1)) {
3403 const std::pair<size_t, size_t> col(
whichVectors_[0] + colRng.lbound(),
3405 wrapped_dual_view_type X_sub = takeSubview(
view_, ALL(), col);
3406 X_ret = rcp(
new MV(this->
getMap(), X_sub));
3408 Array<size_t> which(
whichVectors_.begin() + colRng.lbound(),
3410 X_ret = rcp(
new MV(this->
getMap(),
view_, which));
3415 const bool debug = Behavior::debug();
3417 using Teuchos::Comm;
3418 using Teuchos::outArg;
3419 using Teuchos::REDUCE_MIN;
3420 using Teuchos::reduceAll;
3422 RCP<const Comm<int> > comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
3423 if (!comm.is_null()) {
3427 if (X_ret.is_null()) {
3430 reduceAll<int, int>(*comm, REDUCE_MIN, lclSuccess, outArg(gblSuccess));
3431 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclSuccess != 1, std::logic_error,
3432 "X_ret (the subview of this "
3433 "MultiVector; the return value of this method) is null on some MPI "
3434 "process in this MultiVector's communicator. This should never "
3435 "happen. Please report this bug to the Tpetra developers.");
3436 if (!X_ret.is_null() &&
3437 X_ret->getNumVectors() !=
static_cast<size_t>(colRng.size())) {
3440 reduceAll<int, int>(*comm, REDUCE_MIN, lclSuccess,
3441 outArg(gblSuccess));
3442 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclSuccess != 1, std::logic_error,
3443 "X_ret->getNumVectors() != "
3444 "colRng.size(), on at least one MPI process in this MultiVector's "
3445 "communicator. This should never happen. "
3446 "Please report this bug to the Tpetra developers.");
3452template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3453Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3457 return Teuchos::rcp_const_cast<MV>(this->
subView(cols));
3460template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3461Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3465 return Teuchos::rcp_const_cast<MV>(this->
subView(colRng));
3468template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3472 : base_type(X.
getMap()) {
3473 using Kokkos::subview;
3474 typedef std::pair<size_t, size_t> range_type;
3475 const char tfecfFuncName[] =
"MultiVector(const MultiVector&, const size_t): ";
3478 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(j >= numCols, std::invalid_argument,
"Input index j (== " << j <<
") exceeds valid column index range [0, " << numCols <<
" - 1].");
3480 this->
view_ = takeSubview(X.
view_, Kokkos::ALL(), range_type(jj, jj + 1));
3491 const size_t newSize = X.
imports_.extent(0) / numCols;
3492 const size_t offset = jj * newSize;
3493 auto device_view = subview(X.
imports_.view_device(),
3494 range_type(offset, offset + newSize));
3495 auto host_view = subview(X.
imports_.view_host(),
3496 range_type(offset, offset + newSize));
3500 const size_t newSize = X.
exports_.extent(0) / numCols;
3501 const size_t offset = jj * newSize;
3502 auto device_view = subview(X.
exports_.view_device(),
3503 range_type(offset, offset + newSize));
3504 auto host_view = subview(X.
exports_.view_host(),
3505 range_type(offset, offset + newSize));
3515template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3516Teuchos::RCP<const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3520 return Teuchos::rcp(
new V(*
this, j));
3523template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3524Teuchos::RCP<Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3528 return Teuchos::rcp(
new V(*
this, j));
3531template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3533 get1dCopy(
const Teuchos::ArrayView<Scalar>& A,
const size_t LDA)
const {
3535 using input_view_type = Kokkos::View<IST**, Kokkos::LayoutLeft,
3537 Kokkos::MemoryUnmanaged>;
3538 const char tfecfFuncName[] =
"get1dCopy: ";
3543 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(LDA < numRows, std::runtime_error,
3544 "LDA = " << LDA <<
" < numRows = " << numRows <<
".");
3545 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numRows >
size_t(0) && numCols >
size_t(0) &&
3546 size_t(A.size()) < LDA * (numCols - 1) + numRows,
3548 "A.size() = " << A.size() <<
", but its size must be at least "
3549 << (LDA * (numCols - 1) + numRows) <<
" to hold all the entries.");
3551 const std::pair<size_t, size_t> rowRange(0, numRows);
3552 const std::pair<size_t, size_t> colRange(0, numCols);
3554 input_view_type A_view_orig(
reinterpret_cast<IST*
>(A.getRawPtr()),
3556 auto A_view = Kokkos::subview(A_view_orig, rowRange, colRange);
3572 throw std::runtime_error(
"Tpetra::MultiVector: A non-const view is alive outside and we cannot give a copy where host or device view can be modified outside");
3574 const bool useHostView =
view_.host_view_use_count() >=
view_.device_view_use_count();
3575 if (this->isConstantStride()) {
3579 Kokkos::deep_copy(A_view, srcView_host);
3583 Kokkos::deep_copy(A_view, srcView_device);
3586 for (
size_t j = 0; j < numCols; ++j) {
3588 auto dstColView = Kokkos::subview(A_view, rowRange, j);
3592 auto srcColView_host = Kokkos::subview(srcView_host, rowRange, srcCol);
3594 Kokkos::deep_copy(dstColView, srcColView_host);
3597 auto srcColView_device = Kokkos::subview(srcView_device, rowRange, srcCol);
3599 Kokkos::deep_copy(dstColView, srcColView_device);
3606template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3608 get2dCopy(
const Teuchos::ArrayView<
const Teuchos::ArrayView<Scalar> >& ArrayOfPtrs)
const {
3610 const char tfecfFuncName[] =
"get2dCopy: ";
3614 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3615 static_cast<size_t>(ArrayOfPtrs.size()) != numCols,
3617 "Input array of pointers must contain as many "
3618 "entries (arrays) as the MultiVector has columns. ArrayOfPtrs.size() = "
3619 << ArrayOfPtrs.size() <<
" != getNumVectors() = " << numCols <<
".");
3621 if (numRows != 0 && numCols != 0) {
3623 for (
size_t j = 0; j < numCols; ++j) {
3624 const size_t dstLen =
static_cast<size_t>(ArrayOfPtrs[j].size());
3625 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3626 dstLen < numRows, std::invalid_argument,
"Array j = " << j <<
" of "
3627 "the input array of arrays is not long enough to fit all entries in "
3628 "that column of the MultiVector. ArrayOfPtrs[j].size() = "
3629 << dstLen <<
" < getLocalLength() = " << numRows <<
".");
3633 for (
size_t j = 0; j < numCols; ++j) {
3634 Teuchos::RCP<const V> X_j = this->
getVector(j);
3635 const size_t LDA =
static_cast<size_t>(ArrayOfPtrs[j].size());
3636 X_j->get1dCopy(ArrayOfPtrs[j], LDA);
3641template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3642Teuchos::ArrayRCP<const Scalar>
3646 return Teuchos::null;
3648 TEUCHOS_TEST_FOR_EXCEPTION(
3650 "Tpetra::MultiVector::"
3651 "get1dView: This MultiVector does not have constant stride, so it is "
3652 "not possible to view its data as a single array. You may check "
3653 "whether a MultiVector has constant stride by calling "
3654 "isConstantStride().");
3659 Teuchos::ArrayRCP<const impl_scalar_type> dataAsArcp =
3660 Kokkos::Compat::persistingView(X_lcl);
3661 return Teuchos::arcp_reinterpret_cast<const Scalar>(dataAsArcp);
3665template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3666Teuchos::ArrayRCP<Scalar>
3670 return Teuchos::null;
3673 "Tpetra::MultiVector::"
3674 "get1dViewNonConst: This MultiVector does not have constant stride, "
3675 "so it is not possible to view its data as a single array. You may "
3676 "check whether a MultiVector has constant stride by calling "
3677 "isConstantStride().");
3679 Teuchos::ArrayRCP<impl_scalar_type> dataAsArcp =
3680 Kokkos::Compat::persistingView(X_lcl);
3681 return Teuchos::arcp_reinterpret_cast<Scalar>(dataAsArcp);
3685template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3686Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> >
3697 const Kokkos::pair<size_t, size_t> rowRange(0, myNumRows);
3699 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > views(numCols);
3700 for (
size_t j = 0; j < numCols; ++j) {
3701 const size_t col = this->isConstantStride() ? j : this->
whichVectors_[j];
3702 auto X_lcl_j = Kokkos::subview(X_lcl, rowRange, col);
3703 Teuchos::ArrayRCP<impl_scalar_type> X_lcl_j_arcp =
3704 Kokkos::Compat::persistingView(X_lcl_j);
3705 views[j] = Teuchos::arcp_reinterpret_cast<Scalar>(X_lcl_j_arcp);
3710template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3714 return view_.getHostView(s);
3717template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3721 return view_.getHostView(s);
3724template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3728 return view_.getHostView(s);
3731template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3735 return view_.getDeviceView(s);
3738template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3742 return view_.getDeviceView(s);
3745template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3749 return view_.getDeviceView(s);
3752template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3753typename MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::wrapped_dual_view_type
3759template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3760Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> >
3774 const Kokkos::pair<size_t, size_t> rowRange(0, myNumRows);
3776 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > views(numCols);
3777 for (
size_t j = 0; j < numCols; ++j) {
3778 const size_t col = this->isConstantStride() ? j : this->
whichVectors_[j];
3779 auto X_lcl_j = Kokkos::subview(X_lcl, rowRange, col);
3780 Teuchos::ArrayRCP<const impl_scalar_type> X_lcl_j_arcp =
3781 Kokkos::Compat::persistingView(X_lcl_j);
3782 views[j] = Teuchos::arcp_reinterpret_cast<const Scalar>(X_lcl_j_arcp);
3787template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3790 Teuchos::ETransp transB,
3791 const Scalar& alpha,
3794 const Scalar& beta) {
3796 using Teuchos::CONJ_TRANS;
3797 using Teuchos::NO_TRANS;
3800 using Teuchos::rcpFromRef;
3801 using Teuchos::TRANS;
3803 using ATS = KokkosKernels::ArithTraits<impl_scalar_type>;
3805 using STS = Teuchos::ScalarTraits<Scalar>;
3807 const char tfecfFuncName[] =
"multiply: ";
3808 ProfilingRegion region(
"Tpetra::MV::multiply");
3840 const bool C_is_local = !this->isDistributed();
3850 auto myMap = this->
getMap();
3851 if (!myMap.is_null() && !myMap->getComm().is_null()) {
3852 using Teuchos::outArg;
3853 using Teuchos::REDUCE_MIN;
3854 using Teuchos::reduceAll;
3856 auto comm = myMap->getComm();
3857 const size_t A_nrows =
3859 const size_t A_ncols =
3861 const size_t B_nrows =
3863 const size_t B_ncols =
3869 const int myRank = comm->getRank();
3870 std::ostringstream errStrm;
3872 errStrm <<
"Proc " << myRank <<
": this->getLocalLength()="
3874 <<
"." << std::endl;
3877 errStrm <<
"Proc " << myRank <<
": this->getNumVectors()="
3879 <<
"." << std::endl;
3881 if (A_ncols != B_nrows) {
3882 errStrm <<
"Proc " << myRank <<
": A_ncols="
3883 << A_ncols <<
" != B_nrows=" << B_nrows
3884 <<
"." << std::endl;
3887 const int lclGood = lclBad ? 0 : 1;
3889 reduceAll<int, int>(*comm, REDUCE_MIN, lclGood, outArg(gblGood));
3891 std::ostringstream os;
3894 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3895 "Inconsistent local dimensions on at "
3896 "least one process in this object's communicator."
3899 <<
"C(" << (C_is_local ?
"local" :
"distr") <<
") = "
3901 << (transA == Teuchos::TRANS ?
"^T" : (transA == Teuchos::CONJ_TRANS ?
"^H" :
""))
3902 <<
"(" << (A_is_local ?
"local" :
"distr") <<
") * "
3904 << (transA == Teuchos::TRANS ?
"^T" : (transA == Teuchos::CONJ_TRANS ?
"^H" :
""))
3905 <<
"(" << (B_is_local ?
"local" :
"distr") <<
")." << std::endl
3916 const bool Case1 = C_is_local && A_is_local && B_is_local;
3918 const bool Case2 = C_is_local && !A_is_local && !B_is_local &&
3919 transA != NO_TRANS &&
3922 const bool Case3 = !C_is_local && !A_is_local && B_is_local &&
3926 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!Case1 && !Case2 && !Case3, std::runtime_error,
3927 "Multiplication of op(A) and op(B) into *this is not a "
3928 "supported use case.");
3930 if (beta != STS::zero() && Case2) {
3936 const int myRank = this->
getMap()->getComm()->getRank();
3938 beta_local = ATS::zero();
3948 C_tmp = rcp(
new MV(*
this, Teuchos::Copy));
3950 C_tmp = rcp(
this,
false);
3953 RCP<const MV> A_tmp;
3955 A_tmp = rcp(
new MV(A, Teuchos::Copy));
3957 A_tmp = rcpFromRef(A);
3960 RCP<const MV> B_tmp;
3962 B_tmp = rcp(
new MV(B, Teuchos::Copy));
3964 B_tmp = rcpFromRef(B);
3967 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!C_tmp->isConstantStride() || !B_tmp->isConstantStride() ||
3968 !A_tmp->isConstantStride(),
3970 "Failed to make temporary constant-stride copies of MultiVectors.");
3973 const LO A_lclNumRows = A_tmp->getLocalLength();
3974 const LO A_numVecs = A_tmp->getNumVectors();
3975 auto A_lcl = A_tmp->getLocalViewDevice(Access::ReadOnly);
3976 auto A_sub = Kokkos::subview(A_lcl,
3977 std::make_pair(LO(0), A_lclNumRows),
3978 std::make_pair(LO(0), A_numVecs));
3980 const LO B_lclNumRows = B_tmp->getLocalLength();
3981 const LO B_numVecs = B_tmp->getNumVectors();
3982 auto B_lcl = B_tmp->getLocalViewDevice(Access::ReadOnly);
3983 auto B_sub = Kokkos::subview(B_lcl,
3984 std::make_pair(LO(0), B_lclNumRows),
3985 std::make_pair(LO(0), B_numVecs));
3987 const LO C_lclNumRows = C_tmp->getLocalLength();
3988 const LO C_numVecs = C_tmp->getNumVectors();
3990 auto C_lcl = C_tmp->getLocalViewDevice(Access::ReadWrite);
3991 auto C_sub = Kokkos::subview(C_lcl,
3992 std::make_pair(LO(0), C_lclNumRows),
3993 std::make_pair(LO(0), C_numVecs));
3994 const char ctransA = (transA == Teuchos::NO_TRANS ?
'N' : (transA == Teuchos::TRANS ?
'T' :
'C'));
3995 const char ctransB = (transB == Teuchos::NO_TRANS ?
'N' : (transB == Teuchos::TRANS ?
'T' :
'C'));
3998 ProfilingRegion regionGemm(
"Tpetra::MV::multiply-call-gemm");
4000 KokkosBlas::gemm(&ctransA, &ctransB, alpha_IST, A_sub, B_sub,
4009 A_tmp = Teuchos::null;
4010 B_tmp = Teuchos::null;
4018template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4023 Scalar scalarThis) {
4025 using Kokkos::subview;
4026 const char tfecfFuncName[] =
"elementWiseMultiply: ";
4032 std::runtime_error,
"MultiVectors do not have the same local length.");
4033 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4035 "this->getNumVectors"
4037 << numVecs <<
" != B.getNumVectors() = " << B.
getNumVectors()
4050 KokkosBlas::mult(scalarThis,
4053 subview(A_view, ALL(), 0),
4056 for (
size_t j = 0; j < numVecs; ++j) {
4059 KokkosBlas::mult(scalarThis,
4060 subview(this_view, ALL(), C_col),
4062 subview(A_view, ALL(), 0),
4063 subview(B_view, ALL(), B_col));
4068template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4073 ProfilingRegion region(
"Tpetra::MV::reduce");
4075 const auto map = this->
getMap();
4076 if (map.get() ==
nullptr) {
4079 const auto comm = map->getComm();
4080 if (comm.get() ==
nullptr) {
4087 if (changed_on_device) {
4091 Kokkos::fence(
"MultiVector::reduce");
4093 allReduceView(X_lcl, X_lcl, *comm);
4096 allReduceView(X_lcl, X_lcl, *comm);
4100template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4106 const LocalOrdinal minLocalIndex = this->
getMap()->getMinLocalIndex();
4107 const LocalOrdinal maxLocalIndex = this->
getMap()->getMaxLocalIndex();
4108 TEUCHOS_TEST_FOR_EXCEPTION(
4109 lclRow < minLocalIndex || lclRow > maxLocalIndex,
4111 "Tpetra::MultiVector::replaceLocalValue: row index " << lclRow
4112 <<
" is invalid. The range of valid row indices on this process "
4113 << this->
getMap()->getComm()->getRank() <<
" is [" << minLocalIndex
4114 <<
", " << maxLocalIndex <<
"].");
4115 TEUCHOS_TEST_FOR_EXCEPTION(
4116 vectorIndexOutOfRange(col),
4118 "Tpetra::MultiVector::replaceLocalValue: vector index " << col
4119 <<
" of the multivector is invalid.");
4124 view(lclRow, colInd) = ScalarValue;
4127template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4132 const bool atomic) {
4134 const LocalOrdinal minLocalIndex = this->
getMap()->getMinLocalIndex();
4135 const LocalOrdinal maxLocalIndex = this->
getMap()->getMaxLocalIndex();
4136 TEUCHOS_TEST_FOR_EXCEPTION(
4137 lclRow < minLocalIndex || lclRow > maxLocalIndex,
4139 "Tpetra::MultiVector::sumIntoLocalValue: row index " << lclRow
4140 <<
" is invalid. The range of valid row indices on this process "
4141 << this->
getMap()->getComm()->getRank() <<
" is [" << minLocalIndex
4142 <<
", " << maxLocalIndex <<
"].");
4143 TEUCHOS_TEST_FOR_EXCEPTION(
4144 vectorIndexOutOfRange(col),
4146 "Tpetra::MultiVector::sumIntoLocalValue: vector index " << col
4147 <<
" of the multivector is invalid.");
4154 Kokkos::atomic_add(&(view(lclRow, colInd)), value);
4156 view(lclRow, colInd) += value;
4160template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4167 const LocalOrdinal lclRow = this->
map_->getLocalElement(gblRow);
4170 const char tfecfFuncName[] =
"replaceGlobalValue: ";
4171 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid(),
4173 "Global row index " << gblRow <<
" is not present on this process "
4174 << this->
getMap()->getComm()->getRank() <<
".");
4175 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->vectorIndexOutOfRange(col), std::runtime_error,
4176 "Vector index " << col <<
" of the MultiVector is invalid.");
4182template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4187 const bool atomic) {
4190 const LocalOrdinal lclRow = this->
map_->getLocalElement(globalRow);
4193 TEUCHOS_TEST_FOR_EXCEPTION(
4194 lclRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid(),
4196 "Tpetra::MultiVector::sumIntoGlobalValue: Global row index " << globalRow
4197 <<
" is not present on this process "
4198 << this->
getMap()->getComm()->getRank() <<
".");
4199 TEUCHOS_TEST_FOR_EXCEPTION(
4200 vectorIndexOutOfRange(col),
4202 "Tpetra::MultiVector::sumIntoGlobalValue: Vector index " << col
4203 <<
" of the multivector is invalid.");
4209template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4216 typename dual_view_type::array_layout,
4220 col_dual_view_type X_col =
4221 Kokkos::subview(
view_, Kokkos::ALL(), col);
4222 return Kokkos::Compat::persistingView(X_col.view_device());
4225template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4228 return view_.need_sync_host();
4231template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4234 return view_.need_sync_device();
4237template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4241 using Teuchos::TypeNameTraits;
4243 std::ostringstream out;
4244 out <<
"\"" << className <<
"\": {";
4245 out <<
"Template parameters: {Scalar: " << TypeNameTraits<Scalar>::name()
4246 <<
", LocalOrdinal: " << TypeNameTraits<LocalOrdinal>::name()
4247 <<
", GlobalOrdinal: " << TypeNameTraits<GlobalOrdinal>::name()
4248 <<
", Node" << Node::name()
4250 if (this->getObjectLabel() !=
"") {
4251 out <<
"Label: \"" << this->getObjectLabel() <<
"\", ";
4254 if (className !=
"Tpetra::Vector") {
4256 <<
", isConstantStride: " << this->isConstantStride();
4258 if (this->isConstantStride()) {
4259 out <<
", columnStride: " << this->
getStride();
4266template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4274template <
typename ViewType>
4275void print_vector(Teuchos::FancyOStream& out,
const char* prefix,
const ViewType& v) {
4277 static_assert(Kokkos::SpaceAccessibility<Kokkos::HostSpace, typename ViewType::memory_space>::accessible,
4278 "Tpetra::MultiVector::localDescribeToString: Details::print_vector should be given a host-accessible view.");
4279 static_assert(ViewType::rank == 2,
4280 "Tpetra::MultiVector::localDescribeToString: Details::print_vector should be given a rank-2 view.");
4283 out <<
"Values(" << prefix <<
"): " << std::endl
4285 const size_t numRows = v.extent(0);
4286 const size_t numCols = v.extent(1);
4288 for (
size_t i = 0; i < numRows; ++i) {
4290 if (i + 1 < numRows) {
4295 for (
size_t i = 0; i < numRows; ++i) {
4296 for (
size_t j = 0; j < numCols; ++j) {
4298 if (j + 1 < numCols) {
4302 if (i + 1 < numRows) {
4311template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4315 typedef LocalOrdinal LO;
4318 if (vl <= Teuchos::VERB_LOW) {
4319 return std::string();
4321 auto map = this->
getMap();
4322 if (map.is_null()) {
4323 return std::string();
4325 auto outStringP = Teuchos::rcp(
new std::ostringstream());
4326 auto outp = Teuchos::getFancyOStream(outStringP);
4327 Teuchos::FancyOStream& out = *outp;
4328 auto comm = map->getComm();
4329 const int myRank = comm->getRank();
4330 const int numProcs = comm->getSize();
4332 out <<
"Process " << myRank <<
" of " << numProcs <<
":" << endl;
4333 Teuchos::OSTab tab1(out);
4337 out <<
"Local number of rows: " << lclNumRows << endl;
4339 if (vl > Teuchos::VERB_MEDIUM) {
4343 out <<
"isConstantStride: " << this->isConstantStride() << endl;
4345 if (this->isConstantStride()) {
4346 out <<
"Column stride: " << this->
getStride() << endl;
4349 if (vl > Teuchos::VERB_HIGH && lclNumRows > 0) {
4357 auto X_dev =
view_.getDeviceCopy();
4358 auto X_host =
view_.getHostCopy();
4360 if (X_dev.data() == X_host.data()) {
4362 Details::print_vector(out,
"unified", X_host);
4364 Details::print_vector(out,
"host", X_host);
4365 Details::print_vector(out,
"dev", X_dev);
4370 return outStringP->str();
4373template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4376 const std::string& className,
4377 const Teuchos::EVerbosityLevel verbLevel)
const {
4379 using Teuchos::TypeNameTraits;
4380 using Teuchos::VERB_DEFAULT;
4381 using Teuchos::VERB_LOW;
4382 using Teuchos::VERB_NONE;
4383 const Teuchos::EVerbosityLevel vl =
4384 (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
4386 if (vl == VERB_NONE) {
4393 auto map = this->
getMap();
4394 if (map.is_null()) {
4397 auto comm = map->getComm();
4398 if (comm.is_null()) {
4402 const int myRank = comm->getRank();
4411 Teuchos::RCP<Teuchos::OSTab> tab0, tab1;
4415 tab0 = Teuchos::rcp(
new Teuchos::OSTab(out));
4416 out <<
"\"" << className <<
"\":" << endl;
4417 tab1 = Teuchos::rcp(
new Teuchos::OSTab(out));
4419 out <<
"Template parameters:" << endl;
4420 Teuchos::OSTab tab2(out);
4421 out <<
"Scalar: " << TypeNameTraits<Scalar>::name() << endl
4422 <<
"LocalOrdinal: " << TypeNameTraits<LocalOrdinal>::name() << endl
4423 <<
"GlobalOrdinal: " << TypeNameTraits<GlobalOrdinal>::name() << endl
4424 <<
"Node: " << Node::name() << endl;
4426 if (this->getObjectLabel() !=
"") {
4427 out <<
"Label: \"" << this->getObjectLabel() <<
"\", ";
4430 if (className !=
"Tpetra::Vector") {
4431 out <<
"Number of columns: " << this->
getNumVectors() << endl;
4438 if (vl > VERB_LOW) {
4444template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4446 describe(Teuchos::FancyOStream& out,
4447 const Teuchos::EVerbosityLevel verbLevel)
const {
4448 this->
describeImpl(out,
"Tpetra::MultiVector", verbLevel);
4451template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4457template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4461 const char prefix[] =
"Tpetra::MultiVector::assign: ";
4465 std::invalid_argument,
4466 prefix <<
"Global dimensions of the two Tpetra::MultiVector "
4467 "objects do not match. src has dimensions ["
4469 <<
"," << src.
getNumVectors() <<
"], and *this has dimensions ["
4470 << this->getGlobalLength() <<
"," << this->getNumVectors() <<
"].");
4473 prefix <<
"The local row counts of the two Tpetra::MultiVector "
4474 "objects do not match. src has "
4476 <<
" and *this has " << this->getLocalLength() <<
" row(s).");
4490 if (src_last_updated_on_host) {
4493 this->isConstantStride(),
4495 this->whichVectors_(),
4500 this->isConstantStride(),
4502 this->whichVectors_(),
4507template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4509Teuchos::RCP<MultiVector<T, LocalOrdinal, GlobalOrdinal, Node> >
4521template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4535template <
class ST,
class LO,
class GO,
class NT>
4538 std::swap(mv.
map_, this->map_);
4539 std::swap(mv.
view_, this->view_);
4543#ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4544template <
class ST,
class LO,
class GO,
class NT>
4546 const Teuchos::SerialDenseMatrix<int, ST>& src) {
4549 using IST =
typename MV::impl_scalar_type;
4550 using input_view_type =
4551 Kokkos::View<
const IST**, Kokkos::LayoutLeft,
4552 Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
4553 using pair_type = std::pair<LO, LO>;
4555 const LO numRows =
static_cast<LO
>(src.numRows());
4556 const LO numCols =
static_cast<LO
>(src.numCols());
4558 TEUCHOS_TEST_FOR_EXCEPTION(numRows !=
static_cast<LO
>(dst.
getLocalLength()) ||
4560 std::invalid_argument,
"Tpetra::deep_copy: On Process " << dst.
getMap()->getComm()->getRank() <<
", dst is " << dst.
getLocalLength() <<
" x " << dst.
getNumVectors() <<
", but src is " << numRows <<
" x " << numCols <<
".");
4562 const IST* src_raw =
reinterpret_cast<const IST*
>(src.values());
4563 input_view_type src_orig(src_raw, src.stride(), numCols);
4564 input_view_type src_view =
4565 Kokkos::subview(src_orig, pair_type(0, numRows), Kokkos::ALL());
4567 constexpr bool src_isConstantStride =
true;
4568 Teuchos::ArrayView<const size_t> srcWhichVectors(
nullptr, 0);
4572 src_isConstantStride,
4573 getMultiVectorWhichVectors(dst),
4577template <
class ST,
class LO,
class GO,
class NT>
4578void deep_copy(Teuchos::SerialDenseMatrix<int, ST>& dst,
4582 using IST =
typename MV::impl_scalar_type;
4583 using output_view_type =
4584 Kokkos::View<IST**, Kokkos::LayoutLeft,
4585 Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
4586 using pair_type = std::pair<LO, LO>;
4588 const LO numRows =
static_cast<LO
>(dst.numRows());
4589 const LO numCols =
static_cast<LO
>(dst.numCols());
4591 TEUCHOS_TEST_FOR_EXCEPTION(numRows !=
static_cast<LO
>(src.
getLocalLength()) ||
4593 std::invalid_argument,
"Tpetra::deep_copy: On Process " << src.
getMap()->getComm()->getRank() <<
", src is " << src.
getLocalLength() <<
" x " << src.
getNumVectors() <<
", but dst is " << numRows <<
" x " << numCols <<
".");
4595 IST* dst_raw =
reinterpret_cast<IST*
>(dst.values());
4596 output_view_type dst_orig(dst_raw, dst.stride(), numCols);
4598 Kokkos::subview(dst_orig, pair_type(0, numRows), Kokkos::ALL());
4600 constexpr bool dst_isConstantStride =
true;
4601 Teuchos::ArrayView<const size_t> dstWhichVectors(
nullptr, 0);
4604 localDeepCopy(dst_view,
4606 dst_isConstantStride,
4609 getMultiVectorWhichVectors(src));
4613template <
class Scalar,
class LO,
class GO,
class NT>
4614Teuchos::RCP<MultiVector<Scalar, LO, GO, NT> >
4616 size_t numVectors) {
4618 return Teuchos::rcp(
new MV(map, numVectors));
4621template <
class ST,
class LO,
class GO,
class NT>
4638#ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4639#define TPETRA_MULTIVECTOR_INSTANT(SCALAR, LO, GO, NODE) \
4640 template class MultiVector<SCALAR, LO, GO, NODE>; \
4641 template MultiVector<SCALAR, LO, GO, NODE> createCopy(const MultiVector<SCALAR, LO, GO, NODE>& src); \
4642 template Teuchos::RCP<MultiVector<SCALAR, LO, GO, NODE> > createMultiVector(const Teuchos::RCP<const Map<LO, GO, NODE> >& map, size_t numVectors); \
4643 template void deep_copy(MultiVector<SCALAR, LO, GO, NODE>& dst, const Teuchos::SerialDenseMatrix<int, SCALAR>& src); \
4644 template void deep_copy(Teuchos::SerialDenseMatrix<int, SCALAR>& dst, const MultiVector<SCALAR, LO, GO, NODE>& src);
4647#define TPETRA_MULTIVECTOR_INSTANT(SCALAR, LO, GO, NODE) \
4648 template class MultiVector<SCALAR, LO, GO, NODE>; \
4649 template MultiVector<SCALAR, LO, GO, NODE> createCopy(const MultiVector<SCALAR, LO, GO, NODE>& src);
4653#define TPETRA_MULTIVECTOR_CONVERT_INSTANT(SO, SI, LO, GO, NODE) \
4655 template Teuchos::RCP<MultiVector<SO, LO, GO, NODE> > \
4656 MultiVector<SI, LO, GO, NODE>::convert<SO>() const;
Functions for initializing and finalizing Tpetra.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declaration and generic definition of traits class that tells Tpetra::CrsMatrix how to pack and unpac...
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
All-reduce a 1-D or 2-D Kokkos::View.
Declaration of functions for checking whether a given pointer is accessible from a given Kokkos execu...
Declaration and definition of Tpetra::Details::Blas::fill, an implementation detail of Tpetra::MultiV...
void fill(const ExecutionSpace &execSpace, const ViewType &X, const ValueType &alpha, const IndexType numRows, const IndexType numCols)
Fill the entries of the given 1-D or 2-D Kokkos::View with the given scalar value alpha.
Declaration of a function that prints strings from each process.
Declaration of Tpetra::Details::isInterComm.
Declaration and definition of Tpetra::Details::lclDot, an implementation detail of Tpetra::MultiVecto...
Declaration and definition of Tpetra::Details::normImpl, which is an implementation detail of Tpetra:...
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
void unpackAndCombine(const RowView &row_ptrs_beg, const RowView &row_ptrs_end, IndicesView &indices, const Kokkos::View< const GlobalOrdinal *, BufferDevice, Kokkos::MemoryUnmanaged > &imports, const Kokkos::View< const size_t *, BufferDevice, Kokkos::MemoryUnmanaged > &num_packets_per_lid, const Kokkos::View< const LocalOrdinal *, BufferDevice, Kokkos::MemoryUnmanaged > &import_lids, const typename CrsGraph< LocalOrdinal, GlobalOrdinal, Node >::padding_type &padding, const bool unpack_pids, const int myRank, const bool verbose)
Perform the unpack operation for the graph.
Stand-alone utility functions and macros.
Description of Tpetra's behavior.
static bool assumeMpiIsGPUAware()
Whether to assume that MPI is CUDA aware.
static bool debug()
Whether Tpetra is in debug mode.
static bool verbose()
Whether Tpetra is in verbose mode.
static size_t multivectorKernelLocationThreshold()
the threshold for transitioning from device to host
virtual bool reallocImportsIfNeeded(const size_t newSize, const bool verbose, const std::string *prefix, const bool remoteLIDsContiguous=false, const CombineMode CM=INSERT)
Reallocate imports_ if needed.
Kokkos::DualView< size_t *, buffer_device_type > numImportPacketsPerLID_
Kokkos::DualView< packet_type *, buffer_device_type > exports_
Buffer from which packed data are exported (sent to other processes).
Kokkos::DualView< packet_type *, buffer_device_type > imports_
Kokkos::DualView< size_t *, buffer_device_type > numExportPacketsPerLID_
Teuchos::RCP< const map_type > map_
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
bool isDistributed() const
Whether this is a globally distributed object.
A parallel distribution of indices over processes.
One or more distributed dense vectors.
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,...
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 get1dCopy(const Teuchos::ArrayView< Scalar > &A, const size_t LDA) const
Fill the given array with a copy of this multivector's local values.
size_t getStride() const
Stride between columns in the multivector.
MultiVector< ST, LO, GO, NT > createCopy(const MultiVector< ST, LO, GO, NT > &src)
Return a deep copy of the given MultiVector.
virtual bool reallocImportsIfNeeded(const size_t newSize, const bool verbose, const std::string *prefix, const bool areRemoteLIDsContiguous=false, const CombineMode CM=INSERT) override
Reallocate imports_ if needed.
void reduce()
Sum values of a locally replicated multivector across all processes.
virtual bool checkSizes(const SrcDistObject &sourceObj) override
Whether data redistribution between sourceObj and this object is legal.
void randomize()
Set all values in the multivector to pseudorandom numbers.
typename map_type::local_ordinal_type local_ordinal_type
The type of local indices that this class uses.
void scale(const Scalar &alpha)
Scale in place: this = alpha*this.
Teuchos::RCP< const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > subView(const Teuchos::Range1D &colRng) const
Return a const MultiVector with const views of selected columns.
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.
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.
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.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Map and their communicator.
Teuchos::ArrayRCP< Scalar > get1dViewNonConst()
Nonconst persisting (1-D) view of this multivector's local values.
void assign(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &src)
Copy the contents of src into *this (deep copy).
Teuchos::RCP< Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getVectorNonConst(const size_t j)
Return a Vector which is a nonconst view of column j.
void meanValue(const Teuchos::ArrayView< impl_scalar_type > &means) const
Compute mean (average) value of each column.
Kokkos::DualView< impl_scalar_type **, Kokkos::LayoutLeft, device_type > dual_view_type
Kokkos::DualView specialization used by this class.
std::string descriptionImpl(const std::string &className) const
Implementation of description() for this class, and its subclass Vector.
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).
bool need_sync_device() const
wrapped_dual_view_type view_
The Kokkos::DualView containing the MultiVector's data.
void replaceLocalValue(const LocalOrdinal lclRow, const size_t col, const impl_scalar_type &value)
Replace value in host memory, using local (row) index.
typename KokkosKernels::ArithTraits< Scalar >::val_type impl_scalar_type
The type used internally in place of Scalar.
void swap(MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &mv)
Swap contents of mv with contents of *this.
size_t getLocalLength() const
Local number of rows on the calling process.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > subCopy(const Teuchos::Range1D &colRng) const
Return a MultiVector with copies of selected columns.
Teuchos::ArrayRCP< const Scalar > getData(size_t j) const
Const view of the local values in a particular vector of this multivector.
bool need_sync_host() const
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.
virtual void copyAndPermute(const SrcDistObject &sourceObj, const size_t numSameIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteToLIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteFromLIDs, const CombineMode CM, const execution_space &space) override
Same as copyAndPermute, but do operations in space.
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.
global_size_t getGlobalLength() const
Global number of rows in the multivector.
Teuchos::ArrayRCP< const Scalar > get1dView() const
Const persisting (1-D) view of this multivector's local values.
Teuchos::ArrayRCP< T > getSubArrayRCP(Teuchos::ArrayRCP< T > arr, size_t j) const
Persisting view of j-th column in the given ArrayRCP.
void replaceGlobalValue(const GlobalOrdinal gblRow, const size_t col, const impl_scalar_type &value)
Replace value in host memory, using global row index.
typename KokkosKernels::ArithTraits< impl_scalar_type >::mag_type mag_type
Type of a norm result.
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.
size_t getNumVectors() const
Number of columns in the multivector.
Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The type of the Map specialization used by this class.
virtual size_t constantNumberOfPackets() const override
Number of packets to send per LID.
wrapped_dual_view_type getWrappedDualView() const
Return the wrapped dual view holding this MultiVector's local data.
void sumIntoLocalValue(const LocalOrdinal lclRow, const size_t col, const impl_scalar_type &val, const bool atomic=useAtomicUpdatesByDefault)
Update (+=) a value in host memory, using local row index.
typename KokkosKernels::Details::InnerProductSpaceTraits< impl_scalar_type >::dot_type dot_type
Type of an inner ("dot") product result.
void replaceMap(const Teuchos::RCP< const map_type > &map)
Replace the underlying Map in place.
Teuchos::RCP< MultiVector< T, LocalOrdinal, GlobalOrdinal, Node > > convert() const
Return another MultiVector with the same entries, but converted to a different Scalar type T.
MultiVector()
Default constructor: makes a MultiVector with no rows or columns.
dual_view_type::t_dev::const_type getLocalViewDevice(Access::ReadOnlyStruct) const
Return a read-only, up-to-date view of this MultiVector's local data on device. This requires that th...
typename device_type::execution_space execution_space
Type of the (new) Kokkos execution space.
void abs(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
Put element-wise absolute values of input Multi-vector in target: A = abs(this).
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.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Print the object with the given verbosity level to a FancyOStream.
void get2dCopy(const Teuchos::ArrayView< const Teuchos::ArrayView< Scalar > > &ArrayOfPtrs) const
Fill the given array with a copy of this multivector's local values.
void sumIntoGlobalValue(const GlobalOrdinal gblRow, const size_t col, const impl_scalar_type &value, const bool atomic=useAtomicUpdatesByDefault)
Update (+=) a value in host memory, using global row index.
bool aliases(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &other) const
Whether this multivector's memory might alias other. This is conservative: if either this or other is...
dual_view_type::t_host::const_type getLocalViewHost(Access::ReadOnlyStruct) const
Return a read-only, up-to-date view of this MultiVector's local data on host. This requires that ther...
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > subViewNonConst(const Teuchos::Range1D &colRng)
Return a MultiVector with views of selected columns.
Teuchos::Array< size_t > whichVectors_
Indices of columns this multivector is viewing.
Teuchos::ArrayRCP< Scalar > getDataNonConst(size_t j)
View of the local values in a particular vector of this multivector.
bool isConstantStride() const
Whether this multivector has constant stride between columns.
size_t getOrigNumLocalCols() const
"Original" number of columns in the (local) data.
Teuchos::ArrayRCP< Teuchos::ArrayRCP< Scalar > > get2dViewNonConst()
Return non-const persisting pointers to values.
virtual std::string description() const override
A simple one-line description of this object.
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.
std::string localDescribeToString(const Teuchos::EVerbosityLevel vl) const
Print the calling process' verbose describe() information to the returned string.
bool isSameSize(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &vec) const
size_t getOrigNumLocalRows() const
"Original" number of rows in the (local) data.
Teuchos::ArrayRCP< Teuchos::ArrayRCP< const Scalar > > get2dView() const
Return const persisting pointers to values.
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
void update(const Scalar &alpha, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta)
Update: this = beta*this + alpha*A.
Abstract base class for objects that can be the source of an Import or Export operation.
A distributed dense vector.
base_type::impl_scalar_type impl_scalar_type
base_type::dot_type dot_type
Implementation details of Tpetra.
Nonmember function that computes a residual Computes R = B - A * X.
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.
static void allReduceView(const OutputViewType &output, const InputViewType &input, const Teuchos::Comm< int > &comm)
All-reduce from input Kokkos::View to output Kokkos::View.
bool isInterComm(const Teuchos::Comm< int > &)
Return true if and only if the input communicator wraps an MPI intercommunicator.
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...
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.
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.
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator,...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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.
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.
size_t global_size_t
Global size_t object.
std::string combineModeToString(const CombineMode combineMode)
Human-readable string representation of the given CombineMode.
MultiVector< ST, LO, GO, NT > createCopy(const MultiVector< ST, LO, GO, NT > &src)
Return a deep copy of the given MultiVector.
CombineMode
Rule for combining data in an Import or Export.
@ REPLACE
Replace existing values with new values.
@ ABSMAX
Replace old value with maximum of magnitudes of old and new values.
@ ADD_ASSIGN
Accumulate new values into existing values (may not be supported in all classes).
@ INSERT
Insert new values that don't currently exist.
Traits class for packing / unpacking data of type T.