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>
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;
121 using ::Tpetra::Details::Behavior;
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) {
332 using ::Tpetra::Details::normImpl;
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;
338 auto map =
X.getMap();
339 auto comm =
map.is_null() ?
nullptr :
map->getComm().getRawPtr();
340 auto whichVecs = getMultiVectorWhichVectors(
X);
341 const bool isConstantStride =
X.isConstantStride();
342 const bool isDistributed =
X.isDistributed();
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;
350 auto X_lcl =
X.getLocalViewHost(Access::ReadOnly);
351 normImpl<val_type, array_layout, device_type,
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;
359 auto X_lcl =
X.getLocalViewDevice(Access::ReadOnly);
360 normImpl<val_type, array_layout, device_type,
362 isConstantStride, isDistributed, comm);
370template <
typename DstView,
typename SrcView>
371struct AddAssignFunctor {
379 operator()(
const size_t k)
const { tgt(
k) += src(
k); }
386template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
392template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
397template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
410template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
416 , whichVectors_(
source.whichVectors_) {
419 "MultiVector(const MultiVector&, "
420 "const Teuchos::DataAccess): ";
428 this->
view_ = cpy.view_;
433 true, std::invalid_argument,
434 "Second argument 'copyOrView' has an "
438 << Teuchos::Copy <<
" and Teuchos::View = "
439 << Teuchos::View <<
".");
443template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
455 std::invalid_argument,
456 "Kokkos::DualView does not match Map. "
457 "map->getLocalNumElements() = "
460 <<
", and getStride() = " <<
LDA <<
".");
462 using ::Tpetra::Details::Behavior;
463 const bool debug = Behavior::debug();
465 using ::Tpetra::Details::checkGlobalDualViewValidity;
467 const bool verbose = Behavior::verbose();
468 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
470 checkGlobalDualViewValidity(&
gblErrStrm, view, verbose,
476template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
488 std::invalid_argument,
489 "Kokkos::DualView does not match Map. "
490 "map->getLocalNumElements() = "
493 <<
", and getStride() = " <<
LDA <<
".");
495 using ::Tpetra::Details::Behavior;
496 const bool debug = Behavior::debug();
498 using ::Tpetra::Details::checkGlobalWrappedDualViewValidity;
500 const bool verbose = Behavior::verbose();
501 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
503 checkGlobalWrappedDualViewValidity(&
gblErrStrm, view, verbose,
509template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
512 const typename dual_view_type::t_dev&
d_view)
514 using Teuchos::ArrayRCP;
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) <<
".");
533 using ::Tpetra::Details::Behavior;
534 const bool debug = Behavior::debug();
536 using ::Tpetra::Details::checkGlobalWrappedDualViewValidity;
538 const bool verbose = Behavior::verbose();
539 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
541 checkGlobalWrappedDualViewValidity(&
gblErrStrm, view_, verbose,
551template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
558 const char tfecfFuncName[] =
"MultiVector(map,view,origView): ";
561 const size_t lclNumRows = this->getLocalLength();
564 "The input Kokkos::DualView's "
565 "column stride LDA = "
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.");
572 using ::Tpetra::Details::Behavior;
573 const bool debug = Behavior::debug();
575 using ::Tpetra::Details::checkGlobalDualViewValidity;
577 const bool verbose = Behavior::verbose();
578 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
580 checkGlobalDualViewValidity(&
gblErrStrm, view, verbose,
590template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
599 using Kokkos::subview;
600 const char tfecfFuncName[] =
"MultiVector(map,view,whichVectors): ";
602 using ::Tpetra::Details::Behavior;
603 const bool debug = Behavior::debug();
605 using ::Tpetra::Details::checkGlobalDualViewValidity;
607 const bool verbose = Behavior::verbose();
608 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
610 checkGlobalDualViewValidity(&
gblErrStrm, view, verbose,
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 <<
".");
627 view.extent(1) != 0 && view.extent(1) == 0,
628 std::invalid_argument,
629 "view.extent(1) = 0, but whichVectors.size()"
633 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
636 whichVectors[
k] == Teuchos::OrdinalTraits<size_t>::invalid(),
637 std::invalid_argument,
"whichVectors[" <<
k <<
"] = "
638 "Teuchos::OrdinalTraits<size_t>::invalid().");
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 <<
".");
650 "LDA = " <<
LDA <<
" < this->getLocalLength() = " <<
lclNumRows <<
".");
670template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
679 using Kokkos::subview;
680 const char tfecfFuncName[] =
"MultiVector(map,view,whichVectors): ";
682 using ::Tpetra::Details::Behavior;
683 const bool debug = Behavior::debug();
685 using ::Tpetra::Details::checkGlobalWrappedDualViewValidity;
687 const bool verbose = Behavior::verbose();
688 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
690 checkGlobalWrappedDualViewValidity(&
gblErrStrm, view, verbose,
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 <<
".");
707 view.extent(1) != 0 && view.extent(1) == 0,
708 std::invalid_argument,
709 "view.extent(1) = 0, but whichVectors.size()"
713 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
716 whichVectors[
k] == Teuchos::OrdinalTraits<size_t>::invalid(),
717 std::invalid_argument,
"whichVectors[" <<
k <<
"] = "
718 "Teuchos::OrdinalTraits<size_t>::invalid().");
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 <<
".");
730 "LDA = " <<
LDA <<
" < this->getLocalLength() = " <<
lclNumRows <<
".");
746 whichVectors_.clear();
750template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
760 using Kokkos::subview;
761 const char tfecfFuncName[] =
"MultiVector(map,view,origView,whichVectors): ";
763 using ::Tpetra::Details::Behavior;
764 const bool debug = Behavior::debug();
766 using ::Tpetra::Details::checkGlobalDualViewValidity;
768 const bool verbose = Behavior::verbose();
769 const auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
771 checkGlobalDualViewValidity(&
gblErrStrm, view, verbose,
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 <<
".");
792 view.extent(1) != 0 && view.extent(1) == 0,
793 std::invalid_argument,
794 "view.extent(1) = 0, but whichVectors.size()"
798 typedef Teuchos::ArrayView<const size_t>::size_type size_type;
801 whichVectors[
k] == Teuchos::OrdinalTraits<size_t>::invalid(),
802 std::invalid_argument,
"whichVectors[" <<
k <<
"] = "
803 "Teuchos::OrdinalTraits<size_t>::invalid().");
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 <<
".");
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) <<
".");
838template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
841 const Teuchos::ArrayView<const Scalar>&
data,
847 const char tfecfFuncName[] =
"MultiVector(map,data,LDA,numVecs): ";
856 "map->getLocalNumElements() = "
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 () = "
882 Kokkos::MemoryUnmanaged>
898 typedef decltype(Kokkos::subview(
X_out, Kokkos::ALL(), 0))
900 typedef decltype(Kokkos::subview(
X_in, Kokkos::ALL(), 0))
911template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
914 const Teuchos::ArrayView<
const Teuchos::ArrayView<const Scalar> >&
ArrayOfPtrs,
920 const char tfecfFuncName[] =
"MultiVector(map,ArrayOfPtrs,numVecs): ";
926 std::runtime_error,
"Either numVecs (= " <<
numVecs <<
") < 1, or "
927 "ArrayOfPtrs.size() (= "
933 std::invalid_argument,
"ArrayOfPtrs[" <<
j <<
"].size() = " <<
X_j_av.size() <<
" < map->getLocalNumElements() = " <<
lclNumRows <<
".");
941 using array_layout =
typename decltype(
X_out)::array_layout;
945 Kokkos::MemoryUnmanaged>;
949 Teuchos::ArrayView<const IST>
X_j_av =
950 Teuchos::av_reinterpret_cast<const IST>(
ArrayOfPtrs[
j]);
958template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
961 return whichVectors_.empty();
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();
999 size_t thisSpan = view_.getDualView().view_host().span();
1004template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1011 const MV* src =
dynamic_cast<const MV*
>(&
sourceObj);
1012 if (src ==
nullptr) {
1021 return src->getNumVectors() == this->getNumVectors();
1025template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1029 return this->getNumVectors();
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;
1044 using ::Tpetra::Details::Behavior;
1045 using ::Tpetra::Details::getDualViewCopyFromArrayView;
1046 using ::Tpetra::Details::ProfilingRegion;
1053 if (importsAreAliased() && (this->constantNumberOfPackets() != 0) && Behavior::enableGranularTransfers()) {
1058 copyOnHost = !Behavior::assumeMpiIsGPUAware();
1063 const char longFuncNameHost[] =
"Tpetra::MultiVector::copyAndPermute[Host]";
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()));
1078 std::cerr <<
os.str();
1082 std::logic_error,
"permuteToLIDs.extent(0) = " <<
permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " <<
permuteFromLIDs.extent(0) <<
".");
1083 const size_t numCols = this->getNumVectors();
1089 "Input MultiVector needs sync to both host "
1092 std::ostringstream
os;
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]");
1129 auto tgt_h = this->getLocalViewHost(Access::ReadWrite);
1132 for (
size_t j = 0;
j < numCols; ++
j) {
1133 const size_t tgtCol = isConstantStride() ?
j : whichVectors_[
j];
1142 Kokkos::RangePolicy<execution_space, size_t>;
1144 Tpetra::Details::AddAssignFunctor<
decltype(
tgt_j),
decltype(
src_j)>
1146 Kokkos::parallel_for(
rp,
aaf);
1151 space.fence(
"Tpetra::MultiVector::copyAndPermute-1");
1155 ProfilingRegion
regionC(
"Tpetra::MultiVector::copy[Device]");
1156 auto tgt_d = this->getLocalViewDevice(Access::ReadWrite);
1159 for (
size_t j = 0;
j < numCols; ++
j) {
1160 const size_t tgtCol = isConstantStride() ?
j : whichVectors_[
j];
1169 Kokkos::RangePolicy<execution_space, size_t>;
1171 Tpetra::Details::AddAssignFunctor<
decltype(
tgt_j),
decltype(
src_j)>
1173 Kokkos::parallel_for(
rp,
aaf);
1178 space.fence(
"Tpetra::MultiVector::copyAndPermute-2");
1197 std::ostringstream
os;
1203 ProfilingRegion
regionP(
"Tpetra::MultiVector::permute");
1206 std::ostringstream
os;
1208 std::cerr <<
os.str();
1214 !this->isConstantStride() || !
sourceMV.isConstantStride();
1217 std::ostringstream
os;
1220 std::cerr <<
os.str();
1227 Kokkos::DualView<const size_t*, device_type>
srcWhichVecs;
1228 Kokkos::DualView<const size_t*, device_type>
tgtWhichVecs;
1230 if (this->whichVectors_.size() == 0) {
1231 Kokkos::DualView<size_t*, device_type>
tmpTgt(
"tgtWhichVecs", numCols);
1233 for (
size_t j = 0;
j < numCols; ++
j) {
1241 Teuchos::ArrayView<const size_t>
tgtWhichVecsT = this->whichVectors_();
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);
1254 for (
size_t j = 0;
j < numCols; ++
j) {
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);
1293 std::ostringstream
os;
1295 std::cerr <<
os.str();
1305 using op_type = KokkosRefactor::Details::AddOp;
1306 permute_array_multi_column_variable_stride(
tgt_h,
src_h,
1313 using op_type = KokkosRefactor::Details::InsertOp;
1314 permute_array_multi_column_variable_stride(
tgt_h,
src_h,
1323 using op_type = KokkosRefactor::Details::AddOp;
1327 using op_type = KokkosRefactor::Details::InsertOp;
1334 std::ostringstream
os;
1336 std::cerr <<
os.str();
1338 auto tgt_d = this->getLocalViewDevice(Access::ReadWrite);
1348 std::ostringstream
os;
1350 std::cerr <<
os.str();
1358 using op_type = KokkosRefactor::Details::AddOp;
1359 permute_array_multi_column_variable_stride(space,
tgt_d,
src_d,
1366 using op_type = KokkosRefactor::Details::InsertOp;
1367 permute_array_multi_column_variable_stride(space,
tgt_d,
src_d,
1376 using op_type = KokkosRefactor::Details::AddOp;
1380 using op_type = KokkosRefactor::Details::InsertOp;
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,
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> ,
1412 using Kokkos::Compat::create_const_view;
1413 using Kokkos::Compat::getKokkosViewDeepCopy;
1415 using ::Tpetra::Details::Behavior;
1416 using ::Tpetra::Details::ProfilingRegion;
1417 using ::Tpetra::Details::reallocDualViewIfNeeded;
1424 const char longFuncNameHost[] =
"Tpetra::MultiVector::packAndPrepare[Host]";
1442 std::unique_ptr<std::string>
prefix;
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()));
1451 std::cerr <<
os.str();
1454 const size_t numCols =
sourceMV.getNumVectors();
1465 std::ostringstream
os;
1466 os << *
prefix <<
"No exports on this proc, DONE" << std::endl;
1467 std::cerr <<
os.str();
1490 std::ostringstream
os;
1493 <<
", exports.extent(0): " << exports.extent(0)
1495 std::cerr <<
os.str();
1503 "Input MultiVector needs sync to both host "
1506 std::ostringstream
os;
1508 std::cerr <<
os.str();
1520 exports.clear_sync_state();
1521 exports.modify_host();
1528 exports.clear_sync_state();
1529 exports.modify_device();
1546 using KokkosRefactor::Details::pack_array_single_column;
1548 std::ostringstream
os;
1549 os << *
prefix <<
"Pack numCols=1 const stride" <<
endl;
1550 std::cerr <<
os.str();
1554 pack_array_single_column(exports.view_host(),
1561 pack_array_single_column(exports.view_device(),
1569 using KokkosRefactor::Details::pack_array_single_column;
1571 std::ostringstream
os;
1572 os << *
prefix <<
"Pack numCols=1 nonconst stride" <<
endl;
1573 std::cerr <<
os.str();
1577 pack_array_single_column(exports.view_host(),
1584 pack_array_single_column(exports.view_device(),
1594 using KokkosRefactor::Details::pack_array_multi_column;
1596 std::ostringstream
os;
1597 os << *
prefix <<
"Pack numCols=" << numCols <<
" const stride" <<
endl;
1598 std::cerr <<
os.str();
1602 pack_array_multi_column(exports.view_host(),
1609 pack_array_multi_column(exports.view_device(),
1617 using KokkosRefactor::Details::pack_array_multi_column_variable_stride;
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;
1634 pack_array_multi_column_variable_stride(exports.view_host(),
1642 pack_array_multi_column_variable_stride(exports.view_device(),
1653 std::ostringstream
os;
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,
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();
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 &&
1712 (getNumVectors() == 1) &&
1715 reallocated = this->imports_.view_device().data() != view_.getDualView().view_device().data() +
offset;
1717 typedef std::pair<size_t, size_t> range_type;
1718 this->imports_ =
DV(view_.getDualView(),
1719 range_type(
offset, getLocalLength()),
1723 std::ostringstream
os;
1724 os << *
prefix <<
"Aliased imports_ to MV.view_" << std::endl;
1725 std::cerr <<
os.str();
1731 using ::Tpetra::Details::reallocDualViewIfNeeded;
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,
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>
1779 Kokkos::DualView<impl_scalar_type*, buffer_device_type> imports,
1780 Kokkos::DualView<size_t*, buffer_device_type> ,
1783 const execution_space& space) {
1784 using Kokkos::Compat::getKokkosViewDeepCopy;
1785 using KokkosRefactor::Details::unpack_array_multi_column;
1786 using KokkosRefactor::Details::unpack_array_multi_column_variable_stride;
1788 using ::Tpetra::Details::Behavior;
1789 using ::Tpetra::Details::ProfilingRegion;
1793 const char longFuncNameHost[] =
"Tpetra::MultiVector::unpackAndCombine[Host]";
1807 std::unique_ptr<std::string>
prefix;
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;
1814 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
1816 std::cerr <<
os.str();
1822 std::ostringstream
os;
1824 std::cerr <<
os.str();
1830 if (importsAreAliased()) {
1832 std::ostringstream
os;
1833 os << *
prefix <<
"Skipping unpack, since imports_ is aliased to MV.view_. Done!" <<
endl;
1834 std::cerr <<
os.str();
1841 const size_t numVecs = getNumVectors();
1846 "imports.extent(0) = " << imports.extent(0)
1847 <<
" != getNumVectors() * importLIDs.extent(0) = " <<
numVecs
1852 "constantNumPackets input argument must be nonzero.");
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();
1871 std::ostringstream
os;
1874 std::cerr <<
os.str();
1884 Kokkos::DualView<size_t*, device_type>
whichVecs;
1885 if (!isConstantStride()) {
1886 Kokkos::View<
const size_t*, Kokkos::HostSpace,
1887 Kokkos::MemoryUnmanaged>
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;
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(),
1940 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
1941 unpack_array_multi_column(space,
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(),
1981 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
1982 unpack_array_multi_column(space,
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,
2012 using op_type = KokkosRefactor::Details::AbsMaxOp;
2013 if (isConstantStride()) {
2015 auto X_h = this->getLocalViewHost(Access::ReadWrite);
2016 unpack_array_multi_column(host_exec_space(),
2022 auto X_d = this->getLocalViewDevice(Access::ReadWrite);
2023 unpack_array_multi_column(space,
2031 auto X_h = this->getLocalViewHost(Access::ReadWrite);
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,
2057 std::ostringstream
os;
2059 std::cerr <<
os.str();
2064 std::ostringstream
os;
2066 std::cerr <<
os.str();
2070template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2073 Kokkos::DualView<impl_scalar_type*, buffer_device_type> imports,
2080template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2084 if (isConstantStride()) {
2085 return static_cast<size_t>(view_.extent(1));
2087 return static_cast<size_t>(whichVectors_.size());
2095 const Teuchos::RCP<
const Teuchos::Comm<int> >& comm,
2097 using Teuchos::REDUCE_MAX;
2098 using Teuchos::REDUCE_SUM;
2099 using Teuchos::reduceAll;
2100 typedef typename RV::non_const_value_type
dot_type;
2120 const int nv =
static_cast<int>(
numVecs);
2127 typename RV::non_const_type
lclDots(Kokkos::ViewAllocateWithoutInitializing(
"tmp"),
numVecs);
2141template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2144 const Kokkos::View<dot_type*, Kokkos::HostSpace>&
dots)
const {
2145 using Kokkos::subview;
2146 using Teuchos::Comm;
2147 using Teuchos::null;
2149 using ::Tpetra::Details::Behavior;
2151 typedef Kokkos::View<dot_type*, Kokkos::HostSpace>
RV;
2152 typedef typename dual_view_type::t_dev_const
XMV;
2157 const size_t numVecs = this->getNumVectors();
2161 const size_t lclNumRows = this->getLocalLength();
2162 const size_t numDots =
static_cast<size_t>(
dots.extent(0));
2163 const bool debug = Behavior::debug();
2166 const bool compat = this->getMap()->isCompatible(*(
A.getMap()));
2168 "'*this' MultiVector is not "
2169 "compatible with the input MultiVector A. We only test for this "
2181 lclNumRows !=
A.getLocalLength(), std::runtime_error,
2182 "MultiVectors do not have the same local length. "
2183 "this->getLocalLength() = "
2185 "A.getLocalLength() = "
2186 <<
A.getLocalLength() <<
".");
2188 numVecs !=
A.getNumVectors(), std::runtime_error,
2189 "MultiVectors must have the same number of columns (vectors). "
2190 "this->getNumVectors() = "
2192 "A.getNumVectors() = "
2193 <<
A.getNumVectors() <<
".");
2196 "The output array 'dots' must have the same number of entries as the "
2197 "number of columns (vectors) in *this and A. dots.extent(0) = "
2204 auto thisView = this->getLocalViewDevice(Access::ReadOnly);
2205 auto A_view =
A.getLocalViewDevice(Access::ReadOnly);
2208 this->whichVectors_.getRawPtr(),
2209 A.whichVectors_.getRawPtr(),
2210 this->isConstantStride(),
A.isConstantStride());
2225template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2229 using ::Tpetra::Details::ProfilingRegion;
2231 using dot_type =
typename MV::dot_type;
2232 ProfilingRegion
region(
"Tpetra::multiVectorSingleColumnDot");
2234 auto map =
x.getMap();
2235 Teuchos::RCP<const Teuchos::Comm<int> > comm =
2236 map.is_null() ? Teuchos::null :
map->getComm();
2237 if (comm.is_null()) {
2238 return KokkosKernels::ArithTraits<dot_type>::zero();
2244 const LO
lclNumRows =
static_cast<LO
>(std::min(
x.getLocalLength(),
2245 y.getLocalLength()));
2247 dot_type lclDot = KokkosKernels::ArithTraits<dot_type>::zero();
2254 auto x_2d =
x.getLocalViewDevice(Access::ReadOnly);
2256 auto y_2d =
y.getLocalViewDevice(Access::ReadOnly);
2258 lclDot = KokkosBlas::dot(
x_1d,
y_1d);
2260 if (
x.isDistributed()) {
2261 using Teuchos::outArg;
2262 using Teuchos::REDUCE_SUM;
2263 using Teuchos::reduceAll;
2273template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2276 const Teuchos::ArrayView<dot_type>&
dots)
const {
2280 const size_t numVecs = this->getNumVectors();
2281 const size_t lclNumRows = this->getLocalLength();
2282 const size_t numDots =
static_cast<size_t>(
dots.size());
2293 "MultiVectors do not have the same local length. "
2294 "this->getLocalLength() = "
2296 "A.getLocalLength() = "
2297 <<
A.getLocalLength() <<
".");
2299 "MultiVectors must have the same number of columns (vectors). "
2300 "this->getNumVectors() = "
2302 "A.getNumVectors() = "
2303 <<
A.getNumVectors() <<
".");
2305 "The output array 'dots' must have the same number of entries as the "
2306 "number of columns (vectors) in *this and A. dots.extent(0) = "
2309 if (
numVecs == 1 && this->isConstantStride() &&
A.isConstantStride()) {
2313 this->dot(
A, Kokkos::View<dot_type*, Kokkos::HostSpace>(
dots.getRawPtr(),
numDots));
2317template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2319 norm2(
const Teuchos::ArrayView<mag_type>&
norms)
const {
2321 using ::Tpetra::Details::NORM_TWO;
2322 using ::Tpetra::Details::ProfilingRegion;
2323 ProfilingRegion
region(
"Tpetra::MV::norm2 (host output)");
2326 MV&
X =
const_cast<MV&
>(*this);
2330template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2332 norm2(
const Kokkos::View<mag_type*, Kokkos::HostSpace>&
norms)
const {
2337template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2339 norm1(
const Teuchos::ArrayView<mag_type>&
norms)
const {
2341 using ::Tpetra::Details::NORM_ONE;
2342 using ::Tpetra::Details::ProfilingRegion;
2343 ProfilingRegion
region(
"Tpetra::MV::norm1 (host output)");
2346 MV&
X =
const_cast<MV&
>(*this);
2350template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2352 norm1(
const Kokkos::View<mag_type*, Kokkos::HostSpace>&
norms)
const {
2357template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2359 normInf(
const Teuchos::ArrayView<mag_type>&
norms)
const {
2361 using ::Tpetra::Details::NORM_INF;
2362 using ::Tpetra::Details::ProfilingRegion;
2363 ProfilingRegion
region(
"Tpetra::MV::normInf (host output)");
2366 MV&
X =
const_cast<MV&
>(*this);
2370template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2372 normInf(
const Kokkos::View<mag_type*, Kokkos::HostSpace>&
norms)
const {
2377template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2379 meanValue(
const Teuchos::ArrayView<impl_scalar_type>&
means)
const {
2382 using Kokkos::subview;
2383 using Teuchos::Comm;
2385 using Teuchos::REDUCE_SUM;
2386 using Teuchos::reduceAll;
2387 typedef KokkosKernels::ArithTraits<impl_scalar_type> ATS;
2389 const size_t lclNumRows = this->getLocalLength();
2390 const size_t numVecs = this->getNumVectors();
2395 "Tpetra::MultiVector::meanValue: means.size() = " <<
numMeans
2396 <<
" != this->getNumVectors() = " <<
numVecs <<
".");
2406 typename local_view_type::host_mirror_type::array_layout,
2408 Kokkos::MemoryTraits<Kokkos::Unmanaged> >
2412 RCP<const Comm<int> > comm = this->getMap().is_null() ? Teuchos::null : this->getMap()->getComm();
2418 auto X_lcl =
subview(getLocalViewHost(Access::ReadOnly),
2421 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace>
lclSums(
"MV::meanValue tmp",
numVecs);
2422 if (isConstantStride()) {
2426 const size_t col = whichVectors_[
j];
2434 if (!comm.is_null() &&
this->isDistributed()) {
2443 auto X_lcl =
subview(this->getLocalViewDevice(Access::ReadOnly),
2447 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace>
lclSums(
"MV::meanValue tmp",
numVecs);
2448 if (isConstantStride()) {
2452 const size_t col = whichVectors_[
j];
2469 if (!comm.is_null() &&
this->isDistributed()) {
2482 ATS::one() /
static_cast<mag_type>(this->getGlobalLength());
2488template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2492 typedef KokkosKernels::ArithTraits<IST> ATS;
2493 typedef Kokkos::Random_XorShift64_Pool<typename device_type::execution_space>
pool_type;
2496 const IST
max = Kokkos::rand<generator_type, IST>::max();
2497 const IST
min = ATS::is_signed ? IST(-
max) : ATS::zero();
2502template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2506 typedef Tpetra::Details::Static_Random_XorShift64_Pool<typename device_type::execution_space>
tpetra_pool_type;
2507 typedef Kokkos::Random_XorShift64_Pool<typename device_type::execution_space>
pool_type;
2510 if (!tpetra_pool_type::isSet())
2511 tpetra_pool_type::resetPool(this->getMap()->getComm()->getRank());
2514 const IST
max =
static_cast<IST
>(maxVal);
2515 const IST
min =
static_cast<IST
>(minVal);
2517 auto thisView = this->getLocalViewDevice(Access::OverwriteAll);
2519 if (isConstantStride()) {
2522 const size_t numVecs = getNumVectors();
2524 const size_t col = whichVectors_[
k];
2525 auto X_k = Kokkos::subview(
thisView, Kokkos::ALL(), col);
2531template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2534 using ::Tpetra::Details::ProfilingRegion;
2535 using ::Tpetra::Details::Blas::fill;
2536 using DES =
typename dual_view_type::t_dev::execution_space;
2537 using HES =
typename dual_view_type::t_host::execution_space;
2539 ProfilingRegion
region(
"Tpetra::MultiVector::putScalar");
2544 const LO
lclNumRows =
static_cast<LO
>(this->getLocalLength());
2545 const LO
numVecs =
static_cast<LO
>(this->getNumVectors());
2553 auto X = this->getLocalViewDevice(Access::OverwriteAll);
2554 if (this->isConstantStride()) {
2558 this->whichVectors_.getRawPtr());
2561 auto X = this->getLocalViewHost(Access::OverwriteAll);
2562 if (this->isConstantStride()) {
2566 this->whichVectors_.getRawPtr());
2571template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2574 using Teuchos::ArrayRCP;
2575 using Teuchos::Comm;
2586 !this->isConstantStride(), std::logic_error,
2587 "Tpetra::MultiVector::replaceMap: This method does not currently work "
2588 "if the MultiVector is a column view of another MultiVector (that is, if "
2589 "isConstantStride() == false).");
2619 if (this->getMap().
is_null()) {
2625 newMap.is_null(), std::invalid_argument,
2626 "Tpetra::MultiVector::replaceMap: both current and new Maps are null. "
2627 "This probably means that the input Map is incorrect.");
2633 const size_t numCols = this->getNumVectors();
2638 }
else if (
newMap.is_null()) {
2641 const size_t newNumRows =
static_cast<size_t>(0);
2642 const size_t numCols = this->getNumVectors();
2649template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2656 if (
theAlpha == KokkosKernels::ArithTraits<IST>::one()) {
2660 const size_t numVecs = getNumVectors();
2672 auto Y_lcl = Kokkos::subview(getLocalViewHost(Access::ReadWrite),
rowRng,
ALL());
2673 if (isConstantStride()) {
2677 const size_t Y_col = whichVectors_[
k];
2683 auto Y_lcl = Kokkos::subview(getLocalViewDevice(Access::ReadWrite),
rowRng,
ALL());
2684 if (isConstantStride()) {
2688 const size_t Y_col = isConstantStride() ?
k : whichVectors_[
k];
2696template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2698 scale(
const Teuchos::ArrayView<const Scalar>&
alphas) {
2699 const size_t numVecs = this->getNumVectors();
2703 "Tpetra::MultiVector::"
2704 "scale: alphas.size() = "
2705 <<
numAlphas <<
" != this->getNumVectors() = "
2709 using k_alphas_type = Kokkos::DualView<impl_scalar_type*, device_type>;
2717 this->scale(
k_alphas.view_device());
2720template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2722 scale(
const Kokkos::View<const impl_scalar_type*, device_type>&
alphas) {
2724 using Kokkos::subview;
2726 const size_t lclNumRows = this->getLocalLength();
2727 const size_t numVecs = this->getNumVectors();
2730 std::invalid_argument,
2731 "Tpetra::MultiVector::scale(alphas): "
2732 "alphas.extent(0) = "
2734 <<
" != this->getNumVectors () = " <<
numVecs <<
".");
2755 if (isConstantStride()) {
2759 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2768 if (isConstantStride()) {
2780 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2788template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2793 using Kokkos::subview;
2797 const size_t numVecs = getNumVectors();
2800 lclNumRows !=
A.getLocalLength(), std::invalid_argument,
2801 "this->getLocalLength() = " <<
lclNumRows <<
" != A.getLocalLength() = "
2802 <<
A.getLocalLength() <<
".");
2804 numVecs !=
A.getNumVectors(), std::invalid_argument,
2805 "this->getNumVectors() = " <<
numVecs <<
" != A.getNumVectors() = "
2806 <<
A.getNumVectors() <<
".");
2812 auto Y_lcl_orig = this->getLocalViewDevice(Access::ReadWrite);
2813 auto X_lcl_orig =
A.getLocalViewDevice(Access::ReadOnly);
2817 if (isConstantStride() &&
A.isConstantStride()) {
2822 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2823 const size_t X_col =
A.isConstantStride() ?
k :
A.whichVectors_[
k];
2832template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2838 getLocalLength() !=
A.getLocalLength(), std::runtime_error,
2839 "MultiVectors do not have the same local length. "
2840 "this->getLocalLength() = "
2842 <<
" != A.getLocalLength() = " <<
A.getLocalLength() <<
".");
2844 A.getNumVectors() !=
this->getNumVectors(), std::runtime_error,
2845 ": MultiVectors do not have the same number of columns (vectors). "
2846 "this->getNumVectors() = "
2848 <<
" != A.getNumVectors() = " <<
A.getNumVectors() <<
".");
2850 const size_t numVecs = getNumVectors();
2852 auto this_view_dev = this->getLocalViewDevice(Access::ReadWrite);
2853 auto A_view_dev =
A.getLocalViewDevice(Access::ReadOnly);
2855 if (isConstantStride() &&
A.isConstantStride()) {
2859 using Kokkos::subview;
2861 const size_t this_col = isConstantStride() ?
k : whichVectors_[
k];
2863 const size_t A_col = isConstantStride() ?
k :
A.whichVectors_[
k];
2870template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2876 getLocalLength() !=
A.getLocalLength(), std::runtime_error,
2877 ": MultiVectors do not have the same local length. "
2878 "this->getLocalLength() = "
2880 <<
" != A.getLocalLength() = " <<
A.getLocalLength() <<
".");
2882 A.getNumVectors() !=
this->getNumVectors(), std::runtime_error,
2883 ": MultiVectors do not have the same number of columns (vectors). "
2884 "this->getNumVectors() = "
2886 <<
" != A.getNumVectors() = " <<
A.getNumVectors() <<
".");
2887 const size_t numVecs = getNumVectors();
2889 auto this_view_dev = this->getLocalViewDevice(Access::ReadWrite);
2890 auto A_view_dev =
A.getLocalViewDevice(Access::ReadOnly);
2892 if (isConstantStride() &&
A.isConstantStride()) {
2896 using Kokkos::subview;
2899 const size_t this_col = isConstantStride() ?
k : whichVectors_[
k];
2901 const size_t A_col = isConstantStride() ?
k :
A.whichVectors_[
k];
2908template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2915 using Kokkos::subview;
2920 const size_t numVecs = getNumVectors();
2924 lclNumRows !=
A.getLocalLength(), std::invalid_argument,
2925 "this->getLocalLength() = " <<
lclNumRows <<
" != A.getLocalLength() = "
2926 <<
A.getLocalLength() <<
".");
2928 numVecs !=
A.getNumVectors(), std::invalid_argument,
2929 "this->getNumVectors() = " <<
numVecs <<
" != A.getNumVectors() = "
2930 <<
A.getNumVectors() <<
".");
2938 auto Y_lcl_orig = this->getLocalViewDevice(Access::ReadWrite);
2940 auto X_lcl_orig =
A.getLocalViewDevice(Access::ReadOnly);
2944 if (isConstantStride() &&
A.isConstantStride()) {
2949 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2950 const size_t X_col =
A.isConstantStride() ?
k :
A.whichVectors_[
k];
2959template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2967 using Kokkos::subview;
2969 const char tfecfFuncName[] =
"update(alpha,A,beta,B,gamma): ";
2973 const size_t lclNumRows = this->getLocalLength();
2974 const size_t numVecs = getNumVectors();
2978 lclNumRows !=
A.getLocalLength(), std::invalid_argument,
2979 "The input MultiVector A has " <<
A.getLocalLength() <<
" local "
2980 "row(s), but this MultiVector has "
2984 lclNumRows !=
B.getLocalLength(), std::invalid_argument,
2985 "The input MultiVector B has " <<
B.getLocalLength() <<
" local "
2986 "row(s), but this MultiVector has "
2990 A.getNumVectors() !=
numVecs, std::invalid_argument,
2991 "The input MultiVector A has " <<
A.getNumVectors() <<
" column(s), "
2992 "but this MultiVector has "
2995 B.getNumVectors() !=
numVecs, std::invalid_argument,
2996 "The input MultiVector B has " <<
B.getNumVectors() <<
" column(s), "
2997 "but this MultiVector has "
3015 if (isConstantStride() &&
A.isConstantStride() &&
B.isConstantStride()) {
3021 const size_t this_col = isConstantStride() ?
k : whichVectors_[
k];
3022 const size_t A_col =
A.isConstantStride() ?
k :
A.whichVectors_[
k];
3023 const size_t B_col =
B.isConstantStride() ?
k :
B.whichVectors_[
k];
3031template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3032Teuchos::ArrayRCP<const Scalar>
3044 auto hostView = getLocalViewHost(Access::ReadOnly);
3045 const size_t col = isConstantStride() ?
j : whichVectors_[
j];
3048 Kokkos::Compat::persistingView(
hostView_j, 0, getLocalLength());
3053 "hostView_j.extent(0) = " <<
hostView_j.extent(0)
3054 <<
" < dataAsArcp.size() = " <<
dataAsArcp.size() <<
". "
3055 "Please report this bug to the Tpetra developers.");
3057 return Teuchos::arcp_reinterpret_cast<const Scalar>(
dataAsArcp);
3060template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3061Teuchos::ArrayRCP<Scalar>
3065 using Kokkos::subview;
3069 auto hostView = getLocalViewHost(Access::ReadWrite);
3070 const size_t col = isConstantStride() ?
j : whichVectors_[
j];
3073 Kokkos::Compat::persistingView(
hostView_j, 0, getLocalLength());
3078 "hostView_j.extent(0) = " <<
hostView_j.extent(0)
3079 <<
" < dataAsArcp.size() = " <<
dataAsArcp.size() <<
". "
3080 "Please report this bug to the Tpetra developers.");
3082 return Teuchos::arcp_reinterpret_cast<Scalar>(
dataAsArcp);
3085template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3086Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3088 subCopy(
const Teuchos::ArrayView<const size_t>&
cols)
const {
3097 if (
cols[
j] !=
cols[
j - 1] +
static_cast<size_t>(1)) {
3112template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3113Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3120 RCP<MV> Y(
new MV(this->getMap(),
static_cast<size_t>(
colRng.size()),
false));
3125template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3129 return view_.origExtent(0);
3132template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3136 return view_.origExtent(1);
3139template <
class Scalar,
class LO,
class GO,
class Node>
3142 const Teuchos::RCP<const map_type>&
subMap,
3146 using Kokkos::subview;
3148 using Teuchos::outArg;
3151 using Teuchos::REDUCE_MIN;
3152 using Teuchos::reduceAll;
3154 const char prefix[] =
"Tpetra::MultiVector constructor (offsetView): ";
3155 const char suffix[] =
"Please report this bug to the Tpetra developers.";
3158 std::unique_ptr<std::ostringstream>
errStrm;
3165 const auto comm =
subMap->getComm();
3167 const int myRank = comm->getRank();
3170 const LO numCols =
static_cast<LO
>(
X.getNumVectors());
3173 std::ostringstream
os;
3176 <<
", origLclNumRows: " <<
X.getOrigNumLocalRows()
3177 <<
", numCols: " << numCols <<
"}, "
3179 std::cerr <<
os.str();
3187 errStrm = std::unique_ptr<std::ostringstream>(
new std::ostringstream);
3188 *
errStrm <<
" Proc " <<
myRank <<
": subMap->getLocalNumElements() (="
3190 <<
") > X.getOrigNumLocalRows() (=" <<
X.getOrigNumLocalRows()
3208 using range_type = std::pair<LO, LO>;
3220 newView.extent(1) !=
X.view_.extent(1)) {
3232 if (
errStrm.get() ==
nullptr) {
3233 errStrm = std::unique_ptr<std::ostringstream>(
new std::ostringstream);
3242 "dimensions on one or more processes:"
3254 std::ostringstream
os;
3256 std::cerr <<
os.str();
3262 std::ostringstream
os;
3264 std::cerr <<
os.str();
3268template <
class Scalar,
class LO,
class GO,
class Node>
3276template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3277Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3280 const size_t offset)
const {
3285template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3286Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3294template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3295Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3297 subView(
const Teuchos::ArrayView<const size_t>&
cols)
const {
3298 using Teuchos::Array;
3305 "Tpetra::MultiVector::subView"
3306 "(const Teuchos::ArrayView<const size_t>&): The input array cols must "
3307 "contain at least one entry, but cols.size() = "
3315 if (
cols[
j] !=
cols[
j - 1] +
static_cast<size_t>(1)) {
3330 if (isConstantStride()) {
3331 return rcp(
new MV(this->getMap(), view_,
cols));
3337 return rcp(
new MV(this->getMap(), view_,
newcols()));
3341template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3342Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3346 using Kokkos::subview;
3347 using Teuchos::Array;
3350 using ::Tpetra::Details::Behavior;
3354 const size_t lclNumRows = this->getLocalLength();
3355 const size_t numVecs = this->getNumVectors();
3360 static_cast<size_t>(
colRng.size()) >
numVecs, std::runtime_error,
3361 "colRng.size() = " <<
colRng.size() <<
" > this->getNumVectors() = "
3365 (
colRng.lbound() <
static_cast<Teuchos::Ordinal
>(0) ||
3367 std::invalid_argument,
"Nonempty input range [" <<
colRng.lbound() <<
"," <<
colRng.ubound() <<
"] exceeds the valid range of column indices "
3382 if (
colRng.size() == 0) {
3383 const std::pair<size_t, size_t>
cols(0, 0);
3388 if (isConstantStride()) {
3389 const std::pair<size_t, size_t>
cols(
colRng.lbound(),
3394 if (
static_cast<size_t>(
colRng.size()) ==
static_cast<size_t>(1)) {
3397 const std::pair<size_t, size_t> col(whichVectors_[0] +
colRng.lbound(),
3398 whichVectors_[0] +
colRng.ubound() + 1);
3403 whichVectors_.begin() +
colRng.ubound() + 1);
3409 const bool debug = Behavior::debug();
3411 using Teuchos::Comm;
3412 using Teuchos::outArg;
3413 using Teuchos::REDUCE_MIN;
3414 using Teuchos::reduceAll;
3416 RCP<const Comm<int> > comm = this->getMap().is_null() ? Teuchos::null : this->getMap()->getComm();
3417 if (!comm.is_null()) {
3421 if (
X_ret.is_null()) {
3426 "X_ret (the subview of this "
3427 "MultiVector; the return value of this method) is null on some MPI "
3428 "process in this MultiVector's communicator. This should never "
3429 "happen. Please report this bug to the Tpetra developers.");
3430 if (!
X_ret.is_null() &&
3431 X_ret->getNumVectors() !=
static_cast<size_t>(
colRng.size())) {
3437 "X_ret->getNumVectors() != "
3438 "colRng.size(), on at least one MPI process in this MultiVector's "
3439 "communicator. This should never happen. "
3440 "Please report this bug to the Tpetra developers.");
3446template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3447Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3451 return Teuchos::rcp_const_cast<MV>(this->subView(
cols));
3454template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3455Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3459 return Teuchos::rcp_const_cast<MV>(this->subView(
colRng));
3462template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3467 using Kokkos::subview;
3468 typedef std::pair<size_t, size_t> range_type;
3469 const char tfecfFuncName[] =
"MultiVector(const MultiVector&, const size_t): ";
3471 const size_t numCols =
X.getNumVectors();
3473 const size_t jj =
X.isConstantStride() ?
static_cast<size_t>(
j) :
static_cast<size_t>(
X.whichVectors_[
j]);
3485 const size_t newSize =
X.imports_.extent(0) / numCols;
3494 const size_t newSize =
X.exports_.extent(0) / numCols;
3509template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3510Teuchos::RCP<const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3514 return Teuchos::rcp(
new V(*
this,
j));
3517template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3518Teuchos::RCP<Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3522 return Teuchos::rcp(
new V(*
this,
j));
3525template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3527 get1dCopy(
const Teuchos::ArrayView<Scalar>&
A,
const size_t LDA)
const {
3529 using input_view_type = Kokkos::View<IST**, Kokkos::LayoutLeft,
3531 Kokkos::MemoryUnmanaged>;
3534 const size_t numRows = this->getLocalLength();
3535 const size_t numCols = this->getNumVectors();
3538 "LDA = " <<
LDA <<
" < numRows = " <<
numRows <<
".");
3542 "A.size() = " <<
A.size() <<
", but its size must be at least "
3543 << (
LDA * (numCols - 1) +
numRows) <<
" to hold all the entries.");
3546 const std::pair<size_t, size_t>
colRange(0, numCols);
3548 input_view_type
A_view_orig(
reinterpret_cast<IST*
>(
A.getRawPtr()),
3563 if (this->need_sync_host() && this->need_sync_device()) {
3566 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");
3568 const bool useHostView = view_.host_view_use_count() >= view_.device_view_use_count();
3569 if (this->isConstantStride()) {
3571 auto srcView_host = this->getLocalViewHost(Access::ReadOnly);
3575 auto srcView_device = this->getLocalViewDevice(Access::ReadOnly);
3580 for (
size_t j = 0;
j < numCols; ++
j) {
3581 const size_t srcCol = this->whichVectors_[
j];
3585 auto srcView_host = this->getLocalViewHost(Access::ReadOnly);
3590 auto srcView_device = this->getLocalViewDevice(Access::ReadOnly);
3600template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3605 const size_t numRows = this->getLocalLength();
3606 const size_t numCols = this->getNumVectors();
3609 static_cast<size_t>(
ArrayOfPtrs.size()) != numCols,
3611 "Input array of pointers must contain as many "
3612 "entries (arrays) as the MultiVector has columns. ArrayOfPtrs.size() = "
3613 <<
ArrayOfPtrs.size() <<
" != getNumVectors() = " << numCols <<
".");
3615 if (
numRows != 0 && numCols != 0) {
3617 for (
size_t j = 0;
j < numCols; ++
j) {
3620 dstLen <
numRows, std::invalid_argument,
"Array j = " <<
j <<
" of "
3621 "the input array of arrays is not long enough to fit all entries in "
3622 "that column of the MultiVector. ArrayOfPtrs[j].size() = "
3627 for (
size_t j = 0;
j < numCols; ++
j) {
3628 Teuchos::RCP<const V>
X_j = this->getVector(
j);
3635template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3636Teuchos::ArrayRCP<const Scalar>
3639 if (getLocalLength() == 0 || getNumVectors() == 0) {
3640 return Teuchos::null;
3643 !isConstantStride(), std::runtime_error,
3644 "Tpetra::MultiVector::"
3645 "get1dView: This MultiVector does not have constant stride, so it is "
3646 "not possible to view its data as a single array. You may check "
3647 "whether a MultiVector has constant stride by calling "
3648 "isConstantStride().");
3652 auto X_lcl = getLocalViewHost(Access::ReadOnly);
3653 Teuchos::ArrayRCP<const impl_scalar_type>
dataAsArcp =
3654 Kokkos::Compat::persistingView(
X_lcl);
3655 return Teuchos::arcp_reinterpret_cast<const Scalar>(
dataAsArcp);
3659template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3660Teuchos::ArrayRCP<Scalar>
3663 if (this->getLocalLength() == 0 || this->getNumVectors() == 0) {
3664 return Teuchos::null;
3667 "Tpetra::MultiVector::"
3668 "get1dViewNonConst: This MultiVector does not have constant stride, "
3669 "so it is not possible to view its data as a single array. You may "
3670 "check whether a MultiVector has constant stride by calling "
3671 "isConstantStride().");
3672 auto X_lcl = getLocalViewHost(Access::ReadWrite);
3673 Teuchos::ArrayRCP<impl_scalar_type>
dataAsArcp =
3674 Kokkos::Compat::persistingView(
X_lcl);
3675 return Teuchos::arcp_reinterpret_cast<Scalar>(
dataAsArcp);
3679template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3680Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> >
3683 auto X_lcl = getLocalViewHost(Access::ReadWrite);
3689 const size_t myNumRows = this->getLocalLength();
3690 const size_t numCols = this->getNumVectors();
3693 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> >
views(numCols);
3694 for (
size_t j = 0;
j < numCols; ++
j) {
3695 const size_t col = this->isConstantStride() ?
j : this->whichVectors_[
j];
3698 Kokkos::Compat::persistingView(
X_lcl_j);
3704template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3708 return view_.getHostView(
s);
3711template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3715 return view_.getHostView(
s);
3718template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3722 return view_.getHostView(
s);
3725template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3729 return view_.getDeviceView(
s);
3732template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3736 return view_.getDeviceView(
s);
3739template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3743 return view_.getDeviceView(
s);
3746template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3753template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3754Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> >
3760 auto X_lcl = getLocalViewHost(Access::ReadOnly);
3766 const size_t myNumRows = this->getLocalLength();
3767 const size_t numCols = this->getNumVectors();
3770 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> >
views(numCols);
3771 for (
size_t j = 0;
j < numCols; ++
j) {
3772 const size_t col = this->isConstantStride() ?
j : this->whichVectors_[
j];
3774 Teuchos::ArrayRCP<const impl_scalar_type>
X_lcl_j_arcp =
3775 Kokkos::Compat::persistingView(
X_lcl_j);
3781template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3790 using Teuchos::CONJ_TRANS;
3791 using Teuchos::NO_TRANS;
3794 using Teuchos::rcpFromRef;
3795 using Teuchos::TRANS;
3796 using ::Tpetra::Details::ProfilingRegion;
3797 using ATS = KokkosKernels::ArithTraits<impl_scalar_type>;
3799 using STS = Teuchos::ScalarTraits<Scalar>;
3802 ProfilingRegion
region(
"Tpetra::MV::multiply");
3834 const bool C_is_local = !this->isDistributed();
3844 auto myMap = this->getMap();
3845 if (!
myMap.is_null() && !
myMap->getComm().is_null()) {
3846 using Teuchos::outArg;
3847 using Teuchos::REDUCE_MIN;
3848 using Teuchos::reduceAll;
3850 auto comm =
myMap->getComm();
3863 const int myRank = comm->getRank();
3865 if (this->getLocalLength() !=
A_nrows) {
3867 << this->getLocalLength() <<
" != A_nrows=" <<
A_nrows
3868 <<
"." << std::endl;
3870 if (this->getNumVectors() !=
B_ncols) {
3872 << this->getNumVectors() <<
" != B_ncols=" <<
B_ncols
3873 <<
"." << std::endl;
3878 <<
"." << std::endl;
3885 std::ostringstream
os;
3889 "Inconsistent local dimensions on at "
3890 "least one process in this object's communicator."
3893 <<
"C(" << (
C_is_local ?
"local" :
"distr") <<
") = "
3895 << (
transA == Teuchos::TRANS ?
"^T" : (
transA == Teuchos::CONJ_TRANS ?
"^H" :
""))
3896 <<
"(" << (
A_is_local ?
"local" :
"distr") <<
") * "
3898 << (
transA == Teuchos::TRANS ?
"^T" : (
transA == Teuchos::CONJ_TRANS ?
"^H" :
""))
3899 <<
"(" << (
B_is_local ?
"local" :
"distr") <<
")." << std::endl
3900 <<
"Global dimensions: C(" << this->getGlobalLength() <<
", "
3901 << this->getNumVectors() <<
"), A(" <<
A.getGlobalLength()
3902 <<
", " <<
A.getNumVectors() <<
"), B(" <<
B.getGlobalLength()
3903 <<
", " <<
B.getNumVectors() <<
")." << std::endl
3921 "Multiplication of op(A) and op(B) into *this is not a "
3922 "supported use case.");
3930 const int myRank = this->getMap()->getComm()->getRank();
3941 if (!isConstantStride()) {
3942 C_tmp =
rcp(
new MV(*
this, Teuchos::Copy));
3948 if (!
A.isConstantStride()) {
3955 if (!
B.isConstantStride()) {
3962 !
A_tmp->isConstantStride(),
3964 "Failed to make temporary constant-stride copies of MultiVectors.");
3969 auto A_lcl =
A_tmp->getLocalViewDevice(Access::ReadOnly);
3970 auto A_sub = Kokkos::subview(A_lcl,
3976 auto B_lcl =
B_tmp->getLocalViewDevice(Access::ReadOnly);
3977 auto B_sub = Kokkos::subview(B_lcl,
3984 auto C_lcl =
C_tmp->getLocalViewDevice(Access::ReadWrite);
3988 const char ctransA = (
transA == Teuchos::NO_TRANS ?
'N' : (
transA == Teuchos::TRANS ?
'T' :
'C'));
3989 const char ctransB = (
transB == Teuchos::NO_TRANS ?
'N' : (
transB == Teuchos::TRANS ?
'T' :
'C'));
3992 ProfilingRegion
regionGemm(
"Tpetra::MV::multiply-call-gemm");
3998 if (!isConstantStride()) {
4003 A_tmp = Teuchos::null;
4004 B_tmp = Teuchos::null;
4012template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4019 using Kokkos::subview;
4022 const size_t lclNumRows = this->getLocalLength();
4023 const size_t numVecs = this->getNumVectors();
4026 std::runtime_error,
"MultiVectors do not have the same local length.");
4028 numVecs !=
B.getNumVectors(), std::runtime_error,
4029 "this->getNumVectors"
4031 <<
numVecs <<
" != B.getNumVectors() = " <<
B.getNumVectors()
4034 auto this_view = this->getLocalViewDevice(Access::ReadWrite);
4035 auto A_view =
A.getLocalViewDevice(Access::ReadOnly);
4036 auto B_view =
B.getLocalViewDevice(Access::ReadOnly);
4038 if (isConstantStride() &&
B.isConstantStride()) {
4051 const size_t C_col = isConstantStride() ?
j : whichVectors_[
j];
4052 const size_t B_col =
B.isConstantStride() ?
j :
B.whichVectors_[
j];
4062template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4065 using ::Tpetra::Details::allReduceView;
4066 using ::Tpetra::Details::ProfilingRegion;
4067 ProfilingRegion
region(
"Tpetra::MV::reduce");
4069 const auto map = this->getMap();
4070 if (
map.get() ==
nullptr) {
4073 const auto comm =
map->getComm();
4074 if (comm.get() ==
nullptr) {
4085 Kokkos::fence(
"MultiVector::reduce");
4086 auto X_lcl = this->getLocalViewDevice(Access::ReadWrite);
4089 auto X_lcl = this->getLocalViewHost(Access::ReadWrite);
4094template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4105 "Tpetra::MultiVector::replaceLocalValue: row index " <<
lclRow
4106 <<
" is invalid. The range of valid row indices on this process "
4107 << this->getMap()->getComm()->getRank() <<
" is [" <<
minLocalIndex
4110 vectorIndexOutOfRange(col),
4112 "Tpetra::MultiVector::replaceLocalValue: vector index " << col
4113 <<
" of the multivector is invalid.");
4116 auto view = this->getLocalViewHost(Access::ReadWrite);
4117 const size_t colInd = isConstantStride() ? col : whichVectors_[col];
4121template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4126 const bool atomic) {
4133 "Tpetra::MultiVector::sumIntoLocalValue: row index " <<
lclRow
4134 <<
" is invalid. The range of valid row indices on this process "
4135 << this->getMap()->getComm()->getRank() <<
" is [" <<
minLocalIndex
4138 vectorIndexOutOfRange(col),
4140 "Tpetra::MultiVector::sumIntoLocalValue: vector index " << col
4141 <<
" of the multivector is invalid.");
4144 const size_t colInd = isConstantStride() ? col : whichVectors_[col];
4146 auto view = this->getLocalViewHost(Access::ReadWrite);
4154template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4167 "Global row index " <<
gblRow <<
" is not present on this process "
4168 << this->getMap()->getComm()->getRank() <<
".");
4170 "Vector index " << col <<
" of the MultiVector is invalid.");
4176template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4181 const bool atomic) {
4188 lclRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid(),
4190 "Tpetra::MultiVector::sumIntoGlobalValue: Global row index " <<
globalRow
4191 <<
" is not present on this process "
4192 << this->getMap()->getComm()->getRank() <<
".");
4194 vectorIndexOutOfRange(col),
4196 "Tpetra::MultiVector::sumIntoGlobalValue: Vector index " << col
4197 <<
" of the multivector is invalid.");
4200 this->sumIntoLocalValue(
lclRow, col, value, atomic);
4203template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4210 typename dual_view_type::array_layout,
4213 const size_t col = isConstantStride() ?
j : whichVectors_[
j];
4215 Kokkos::subview(view_, Kokkos::ALL(), col);
4216 return Kokkos::Compat::persistingView(
X_col.view_device());
4219template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4222 return view_.need_sync_host();
4225template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4228 return view_.need_sync_device();
4231template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4235 using Teuchos::TypeNameTraits;
4237 std::ostringstream
out;
4242 <<
", Node" << Node::name()
4247 out <<
", numRows: " << this->getGlobalLength();
4249 out <<
", numCols: " << this->getNumVectors()
4250 <<
", isConstantStride: " << this->isConstantStride();
4252 if (this->isConstantStride()) {
4253 out <<
", columnStride: " << this->getStride();
4260template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4264 return this->descriptionImpl(
"Tpetra::MultiVector");
4268template <
typename ViewType>
4269void print_vector(Teuchos::FancyOStream&
out,
const char*
prefix,
const ViewType&
v) {
4271 static_assert(Kokkos::SpaceAccessibility<Kokkos::HostSpace, typename ViewType::memory_space>::accessible,
4272 "Tpetra::MultiVector::localDescribeToString: Details::print_vector should be given a host-accessible view.");
4273 static_assert(ViewType::rank == 2,
4274 "Tpetra::MultiVector::localDescribeToString: Details::print_vector should be given a rank-2 view.");
4277 out <<
"Values(" <<
prefix <<
"): " << std::endl
4279 const size_t numRows =
v.extent(0);
4280 const size_t numCols =
v.extent(1);
4290 for (
size_t j = 0;
j < numCols; ++
j) {
4292 if (
j + 1 < numCols) {
4305template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4312 if (
vl <= Teuchos::VERB_LOW) {
4313 return std::string();
4315 auto map = this->getMap();
4316 if (
map.is_null()) {
4317 return std::string();
4319 auto outStringP = Teuchos::rcp(
new std::ostringstream());
4321 Teuchos::FancyOStream&
out = *
outp;
4322 auto comm =
map->getComm();
4323 const int myRank = comm->getRank();
4324 const int numProcs = comm->getSize();
4330 const LO
lclNumRows =
static_cast<LO
>(this->getLocalLength());
4333 if (
vl > Teuchos::VERB_MEDIUM) {
4336 if (this->getNumVectors() !=
static_cast<size_t>(1)) {
4337 out <<
"isConstantStride: " << this->isConstantStride() <<
endl;
4339 if (this->isConstantStride()) {
4340 out <<
"Column stride: " << this->getStride() <<
endl;
4351 auto X_dev = view_.getDeviceCopy();
4352 auto X_host = view_.getHostCopy();
4356 Details::print_vector(
out,
"unified",
X_host);
4358 Details::print_vector(
out,
"host",
X_host);
4359 Details::print_vector(
out,
"dev",
X_dev);
4367template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4371 const Teuchos::EVerbosityLevel
verbLevel)
const {
4373 using Teuchos::TypeNameTraits;
4374 using Teuchos::VERB_DEFAULT;
4375 using Teuchos::VERB_LOW;
4376 using Teuchos::VERB_NONE;
4377 const Teuchos::EVerbosityLevel
vl =
4387 auto map = this->getMap();
4388 if (
map.is_null()) {
4391 auto comm =
map->getComm();
4392 if (comm.is_null()) {
4396 const int myRank = comm->getRank();
4405 Teuchos::RCP<Teuchos::OSTab>
tab0,
tab1;
4409 tab0 = Teuchos::rcp(
new Teuchos::OSTab(
out));
4411 tab1 = Teuchos::rcp(
new Teuchos::OSTab(
out));
4413 out <<
"Template parameters:" <<
endl;
4418 <<
"Node: " << Node::name() <<
endl;
4423 out <<
"Global number of rows: " << this->getGlobalLength() <<
endl;
4425 out <<
"Number of columns: " << this->getNumVectors() <<
endl;
4433 const std::string
lclStr = this->localDescribeToString(
vl);
4438template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4441 const Teuchos::EVerbosityLevel
verbLevel)
const {
4442 this->describeImpl(
out,
"Tpetra::MultiVector",
verbLevel);
4445template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4451template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4454 using ::Tpetra::Details::localDeepCopy;
4455 const char prefix[] =
"Tpetra::MultiVector::assign: ";
4458 this->getNumVectors() != src.getNumVectors(),
4459 std::invalid_argument,
4460 prefix <<
"Global dimensions of the two Tpetra::MultiVector "
4461 "objects do not match. src has dimensions ["
4462 << src.getGlobalLength()
4463 <<
"," << src.getNumVectors() <<
"], and *this has dimensions ["
4464 <<
this->getGlobalLength() <<
"," <<
this->getNumVectors() <<
"].");
4467 prefix <<
"The local row counts of the two Tpetra::MultiVector "
4468 "objects do not match. src has "
4469 << src.getLocalLength() <<
" row(s) "
4470 <<
" and *this has " <<
this->getLocalLength() <<
" row(s).");
4485 localDeepCopy(this->getLocalViewHost(Access::ReadWrite),
4486 src.getLocalViewHost(Access::ReadOnly),
4487 this->isConstantStride(),
4488 src.isConstantStride(),
4489 this->whichVectors_(),
4490 src.whichVectors_());
4492 localDeepCopy(this->getLocalViewDevice(Access::ReadWrite),
4493 src.getLocalViewDevice(Access::ReadOnly),
4494 this->isConstantStride(),
4495 src.isConstantStride(),
4496 this->whichVectors_(),
4497 src.whichVectors_());
4501template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4503Teuchos::RCP<MultiVector<T, LocalOrdinal, GlobalOrdinal, Node> >
4509 this->getNumVectors(),
4515template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4518 using ::Tpetra::Details::PackTraits;
4520 const size_t l1 = this->getLocalLength();
4521 const size_t l2 =
vec.getLocalLength();
4522 if ((
l1 !=
l2) || (this->getNumVectors() !=
vec.getNumVectors())) {
4529template <
class ST,
class LO,
class GO,
class NT>
4532 std::swap(
mv.map_,
this->map_);
4533 std::swap(
mv.view_,
this->view_);
4534 std::swap(
mv.whichVectors_,
this->whichVectors_);
4537#ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4538template <
class ST,
class LO,
class GO,
class NT>
4540 const Teuchos::SerialDenseMatrix<int, ST>& src) {
4541 using ::Tpetra::Details::localDeepCopy;
4543 using IST =
typename MV::impl_scalar_type;
4544 using input_view_type =
4545 Kokkos::View<
const IST**, Kokkos::LayoutLeft,
4546 Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
4547 using pair_type = std::pair<LO, LO>;
4549 const LO
numRows =
static_cast<LO
>(src.numRows());
4550 const LO numCols =
static_cast<LO
>(src.numCols());
4553 numCols !=
static_cast<LO
>(dst.getNumVectors()),
4554 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 <<
".");
4556 const IST*
src_raw =
reinterpret_cast<const IST*
>(src.values());
4563 localDeepCopy(dst.getLocalViewHost(Access::ReadWrite),
4565 dst.isConstantStride(),
4567 getMultiVectorWhichVectors(dst),
4571template <
class ST,
class LO,
class GO,
class NT>
4572void deep_copy(Teuchos::SerialDenseMatrix<int, ST>& dst,
4574 using ::Tpetra::Details::localDeepCopy;
4576 using IST =
typename MV::impl_scalar_type;
4577 using output_view_type =
4578 Kokkos::View<IST**, Kokkos::LayoutLeft,
4579 Kokkos::HostSpace, Kokkos::MemoryUnmanaged>;
4580 using pair_type = std::pair<LO, LO>;
4582 const LO
numRows =
static_cast<LO
>(dst.numRows());
4583 const LO numCols =
static_cast<LO
>(dst.numCols());
4587 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 <<
".");
4589 IST*
dst_raw =
reinterpret_cast<IST*
>(dst.values());
4603 getMultiVectorWhichVectors(src));
4607template <
class Scalar,
class LO,
class GO,
class NT>
4608Teuchos::RCP<MultiVector<Scalar, LO, GO, NT> >
4615template <
class ST,
class LO,
class GO,
class NT>
4619 MV
cpy(src.getMap(), src.getNumVectors(),
false);
4632#ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4633#define TPETRA_MULTIVECTOR_INSTANT(SCALAR, LO, GO, NODE) \
4634 template class MultiVector<SCALAR, LO, GO, NODE>; \
4635 template MultiVector<SCALAR, LO, GO, NODE> createCopy(const MultiVector<SCALAR, LO, GO, NODE>& src); \
4636 template Teuchos::RCP<MultiVector<SCALAR, LO, GO, NODE> > createMultiVector(const Teuchos::RCP<const Map<LO, GO, NODE> >& map, size_t numVectors); \
4637 template void deep_copy(MultiVector<SCALAR, LO, GO, NODE>& dst, const Teuchos::SerialDenseMatrix<int, SCALAR>& src); \
4638 template void deep_copy(Teuchos::SerialDenseMatrix<int, SCALAR>& dst, const MultiVector<SCALAR, LO, GO, NODE>& src);
4641#define TPETRA_MULTIVECTOR_INSTANT(SCALAR, LO, GO, NODE) \
4642 template class MultiVector<SCALAR, LO, GO, NODE>; \
4643 template MultiVector<SCALAR, LO, GO, NODE> createCopy(const MultiVector<SCALAR, LO, GO, NODE>& src);
4647#define TPETRA_MULTIVECTOR_CONVERT_INSTANT(SO, SI, LO, GO, NODE) \
4649 template Teuchos::RCP<MultiVector<SO, LO, GO, NODE> > \
4650 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...
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...
Stand-alone utility functions and macros.
Struct that holds views of the contents of a CrsMatrix.
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_
Number of packets to receive for each receive operation.
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_
Buffer into which packed data are imported (received from other processes).
Kokkos::DualView< size_t *, buffer_device_type > numExportPacketsPerLID_
Number of packets to send for each send operation.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this 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.
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
Whether this MultiVector needs synchronization to the device.
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.
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.
typename Kokkos::Details::InnerProductSpaceTraits< impl_scalar_type >::dot_type dot_type
Type of an inner ("dot") product result.
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
Whether this MultiVector needs synchronization to the host.
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.
Kokkos::DualView< impl_scalar_type **, Kokkos::LayoutLeft, device_type > dual_view_type
Kokkos::DualView specialization used by this class.
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.
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.
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.
typename KokkosKernels::ArithTraits< Scalar >::val_type impl_scalar_type
The type used internally in place of Scalar.
Abstract base class for objects that can be the source of an Import or Export operation.
Implementation details of Tpetra.
int local_ordinal_type
Default value of Scalar template parameter.
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.
bool isInterComm(const Teuchos::Comm< int > &)
Return true if and only if the input communicator wraps an MPI intercommunicator.
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 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.