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;
2122 const int nv =
static_cast<int>(
numVecs);
2129 typename RV::non_const_type
lclDots(Kokkos::ViewAllocateWithoutInitializing(
"tmp"),
numVecs);
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;
2151 using ::Tpetra::Details::Behavior;
2153 typedef Kokkos::View<dot_type*, Kokkos::HostSpace>
RV;
2154 typedef typename dual_view_type::t_dev_const
XMV;
2159 const size_t numVecs = this->getNumVectors();
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()));
2170 "'*this' MultiVector is not "
2171 "compatible with the input MultiVector A. We only test for this "
2183 lclNumRows !=
A.getLocalLength(), std::runtime_error,
2184 "MultiVectors do not have the same local length. "
2185 "this->getLocalLength() = "
2187 "A.getLocalLength() = "
2188 <<
A.getLocalLength() <<
".");
2190 numVecs !=
A.getNumVectors(), std::runtime_error,
2191 "MultiVectors must have the same number of columns (vectors). "
2192 "this->getNumVectors() = "
2194 "A.getNumVectors() = "
2195 <<
A.getNumVectors() <<
".");
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) = "
2206 auto thisView = this->getLocalViewDevice(Access::ReadOnly);
2207 auto A_view =
A.getLocalViewDevice(Access::ReadOnly);
2210 this->whichVectors_.getRawPtr(),
2211 A.whichVectors_.getRawPtr(),
2212 this->isConstantStride(),
A.isConstantStride());
2227template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2231 using ::Tpetra::Details::ProfilingRegion;
2233 using dot_type =
typename MV::dot_type;
2234 ProfilingRegion
region(
"Tpetra::multiVectorSingleColumnDot");
2236 auto map =
x.getMap();
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");
2250 const LO
lclNumRows =
static_cast<LO
>(std::min(
x.getLocalLength(),
2251 y.getLocalLength()));
2258 auto x_2d =
x.getLocalViewDevice(Access::ReadOnly);
2260 auto y_2d =
y.getLocalViewDevice(Access::ReadOnly);
2262 lclDot = KokkosBlas::dot(
x_1d,
y_1d);
2265 if (
x.isDistributed()) {
2266 ProfilingRegion
regionReduce(
"Tpetra::multiVectorSingleColumnDot::reduce");
2267 using Teuchos::outArg;
2268 using Teuchos::REDUCE_SUM;
2269 using Teuchos::reduceAll;
2279template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2282 const Teuchos::ArrayView<dot_type>&
dots)
const {
2286 const size_t numVecs = this->getNumVectors();
2287 const size_t lclNumRows = this->getLocalLength();
2288 const size_t numDots =
static_cast<size_t>(
dots.size());
2299 "MultiVectors do not have the same local length. "
2300 "this->getLocalLength() = "
2302 "A.getLocalLength() = "
2303 <<
A.getLocalLength() <<
".");
2305 "MultiVectors must have the same number of columns (vectors). "
2306 "this->getNumVectors() = "
2308 "A.getNumVectors() = "
2309 <<
A.getNumVectors() <<
".");
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) = "
2315 if (
numVecs == 1 && this->isConstantStride() &&
A.isConstantStride()) {
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;
2328 using ::Tpetra::Details::ProfilingRegion;
2329 ProfilingRegion
region(
"Tpetra::MV::norm2 (host output)");
2332 MV&
X =
const_cast<MV&
>(*this);
2336template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2338 norm2(
const Kokkos::View<mag_type*, Kokkos::HostSpace>&
norms)
const {
2343template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2345 norm1(
const Teuchos::ArrayView<mag_type>&
norms)
const {
2347 using ::Tpetra::Details::NORM_ONE;
2348 using ::Tpetra::Details::ProfilingRegion;
2349 ProfilingRegion
region(
"Tpetra::MV::norm1 (host output)");
2352 MV&
X =
const_cast<MV&
>(*this);
2356template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2358 norm1(
const Kokkos::View<mag_type*, Kokkos::HostSpace>&
norms)
const {
2363template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2365 normInf(
const Teuchos::ArrayView<mag_type>&
norms)
const {
2367 using ::Tpetra::Details::NORM_INF;
2368 using ::Tpetra::Details::ProfilingRegion;
2369 ProfilingRegion
region(
"Tpetra::MV::normInf (host output)");
2372 MV&
X =
const_cast<MV&
>(*this);
2376template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2378 normInf(
const Kokkos::View<mag_type*, Kokkos::HostSpace>&
norms)
const {
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;
2395 const size_t lclNumRows = this->getLocalLength();
2396 const size_t numVecs = this->getNumVectors();
2401 "Tpetra::MultiVector::meanValue: means.size() = " <<
numMeans
2402 <<
" != this->getNumVectors() = " <<
numVecs <<
".");
2412 typename local_view_type::host_mirror_type::array_layout,
2414 Kokkos::MemoryTraits<Kokkos::Unmanaged> >
2418 RCP<const Comm<int> > comm = this->getMap().is_null() ? Teuchos::null : this->getMap()->getComm();
2424 auto X_lcl =
subview(getLocalViewHost(Access::ReadOnly),
2427 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace>
lclSums(
"MV::meanValue tmp",
numVecs);
2428 if (isConstantStride()) {
2432 const size_t col = whichVectors_[
j];
2440 if (!comm.is_null() &&
this->isDistributed()) {
2449 auto X_lcl =
subview(this->getLocalViewDevice(Access::ReadOnly),
2453 Kokkos::View<impl_scalar_type*, Kokkos::HostSpace>
lclSums(
"MV::meanValue tmp",
numVecs);
2454 if (isConstantStride()) {
2458 const size_t col = whichVectors_[
j];
2475 if (!comm.is_null() &&
this->isDistributed()) {
2488 ATS::one() /
static_cast<mag_type>(this->getGlobalLength());
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;
2502 const IST
max = Kokkos::rand<generator_type, IST>::max();
2503 const IST
min = ATS::is_signed ? IST(-
max) : ATS::zero();
2508template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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());
2520 const IST
max =
static_cast<IST
>(maxVal);
2521 const IST
min =
static_cast<IST
>(minVal);
2523 auto thisView = this->getLocalViewDevice(Access::OverwriteAll);
2525 if (isConstantStride()) {
2528 const size_t numVecs = getNumVectors();
2530 const size_t col = whichVectors_[
k];
2531 auto X_k = Kokkos::subview(
thisView, Kokkos::ALL(), col);
2537template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2540 using ::Tpetra::Details::ProfilingRegion;
2541 using ::Tpetra::Details::Blas::fill;
2542 using DES =
typename dual_view_type::t_dev::execution_space;
2543 using HES =
typename dual_view_type::t_host::execution_space;
2545 ProfilingRegion
region(
"Tpetra::MultiVector::putScalar");
2550 const LO
lclNumRows =
static_cast<LO
>(this->getLocalLength());
2551 const LO
numVecs =
static_cast<LO
>(this->getNumVectors());
2559 auto X = this->getLocalViewDevice(Access::OverwriteAll);
2560 if (this->isConstantStride()) {
2564 this->whichVectors_.getRawPtr());
2567 auto X = this->getLocalViewHost(Access::OverwriteAll);
2568 if (this->isConstantStride()) {
2572 this->whichVectors_.getRawPtr());
2577template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2580 using Teuchos::ArrayRCP;
2581 using Teuchos::Comm;
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()) {
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.");
2639 const size_t numCols = this->getNumVectors();
2644 }
else if (
newMap.is_null()) {
2647 const size_t newNumRows =
static_cast<size_t>(0);
2648 const size_t numCols = this->getNumVectors();
2655template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2662 if (
theAlpha == KokkosKernels::ArithTraits<IST>::one()) {
2666 const size_t numVecs = getNumVectors();
2678 auto Y_lcl = Kokkos::subview(getLocalViewHost(Access::ReadWrite),
rowRng,
ALL());
2679 if (isConstantStride()) {
2683 const size_t Y_col = whichVectors_[
k];
2689 auto Y_lcl = Kokkos::subview(getLocalViewDevice(Access::ReadWrite),
rowRng,
ALL());
2690 if (isConstantStride()) {
2694 const size_t Y_col = isConstantStride() ?
k : whichVectors_[
k];
2702template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2704 scale(
const Teuchos::ArrayView<const Scalar>&
alphas) {
2705 const size_t numVecs = this->getNumVectors();
2709 "Tpetra::MultiVector::"
2710 "scale: alphas.size() = "
2711 <<
numAlphas <<
" != this->getNumVectors() = "
2715 using k_alphas_type = Kokkos::DualView<impl_scalar_type*, device_type>;
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;
2732 const size_t lclNumRows = this->getLocalLength();
2733 const size_t numVecs = this->getNumVectors();
2736 std::invalid_argument,
2737 "Tpetra::MultiVector::scale(alphas): "
2738 "alphas.extent(0) = "
2740 <<
" != this->getNumVectors () = " <<
numVecs <<
".");
2761 if (isConstantStride()) {
2765 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2774 if (isConstantStride()) {
2786 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2794template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2799 using Kokkos::subview;
2803 const size_t numVecs = getNumVectors();
2806 lclNumRows !=
A.getLocalLength(), std::invalid_argument,
2807 "this->getLocalLength() = " <<
lclNumRows <<
" != A.getLocalLength() = "
2808 <<
A.getLocalLength() <<
".");
2810 numVecs !=
A.getNumVectors(), std::invalid_argument,
2811 "this->getNumVectors() = " <<
numVecs <<
" != A.getNumVectors() = "
2812 <<
A.getNumVectors() <<
".");
2818 auto Y_lcl_orig = this->getLocalViewDevice(Access::ReadWrite);
2819 auto X_lcl_orig =
A.getLocalViewDevice(Access::ReadOnly);
2823 if (isConstantStride() &&
A.isConstantStride()) {
2828 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2829 const size_t X_col =
A.isConstantStride() ?
k :
A.whichVectors_[
k];
2838template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2844 getLocalLength() !=
A.getLocalLength(), std::runtime_error,
2845 "MultiVectors do not have the same local length. "
2846 "this->getLocalLength() = "
2848 <<
" != A.getLocalLength() = " <<
A.getLocalLength() <<
".");
2850 A.getNumVectors() !=
this->getNumVectors(), std::runtime_error,
2851 ": MultiVectors do not have the same number of columns (vectors). "
2852 "this->getNumVectors() = "
2854 <<
" != A.getNumVectors() = " <<
A.getNumVectors() <<
".");
2856 const size_t numVecs = getNumVectors();
2858 auto this_view_dev = this->getLocalViewDevice(Access::ReadWrite);
2859 auto A_view_dev =
A.getLocalViewDevice(Access::ReadOnly);
2861 if (isConstantStride() &&
A.isConstantStride()) {
2865 using Kokkos::subview;
2867 const size_t this_col = isConstantStride() ?
k : whichVectors_[
k];
2869 const size_t A_col = isConstantStride() ?
k :
A.whichVectors_[
k];
2876template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2882 getLocalLength() !=
A.getLocalLength(), std::runtime_error,
2883 ": MultiVectors do not have the same local length. "
2884 "this->getLocalLength() = "
2886 <<
" != A.getLocalLength() = " <<
A.getLocalLength() <<
".");
2888 A.getNumVectors() !=
this->getNumVectors(), std::runtime_error,
2889 ": MultiVectors do not have the same number of columns (vectors). "
2890 "this->getNumVectors() = "
2892 <<
" != A.getNumVectors() = " <<
A.getNumVectors() <<
".");
2893 const size_t numVecs = getNumVectors();
2895 auto this_view_dev = this->getLocalViewDevice(Access::ReadWrite);
2896 auto A_view_dev =
A.getLocalViewDevice(Access::ReadOnly);
2898 if (isConstantStride() &&
A.isConstantStride()) {
2902 using Kokkos::subview;
2905 const size_t this_col = isConstantStride() ?
k : whichVectors_[
k];
2907 const size_t A_col = isConstantStride() ?
k :
A.whichVectors_[
k];
2914template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2921 using Kokkos::subview;
2926 const size_t numVecs = getNumVectors();
2930 lclNumRows !=
A.getLocalLength(), std::invalid_argument,
2931 "this->getLocalLength() = " <<
lclNumRows <<
" != A.getLocalLength() = "
2932 <<
A.getLocalLength() <<
".");
2934 numVecs !=
A.getNumVectors(), std::invalid_argument,
2935 "this->getNumVectors() = " <<
numVecs <<
" != A.getNumVectors() = "
2936 <<
A.getNumVectors() <<
".");
2944 auto Y_lcl_orig = this->getLocalViewDevice(Access::ReadWrite);
2946 auto X_lcl_orig =
A.getLocalViewDevice(Access::ReadOnly);
2950 if (isConstantStride() &&
A.isConstantStride()) {
2955 const size_t Y_col = this->isConstantStride() ?
k : this->whichVectors_[
k];
2956 const size_t X_col =
A.isConstantStride() ?
k :
A.whichVectors_[
k];
2965template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2973 using Kokkos::subview;
2975 const char tfecfFuncName[] =
"update(alpha,A,beta,B,gamma): ";
2979 const size_t lclNumRows = this->getLocalLength();
2980 const size_t numVecs = getNumVectors();
2984 lclNumRows !=
A.getLocalLength(), std::invalid_argument,
2985 "The input MultiVector A has " <<
A.getLocalLength() <<
" local "
2986 "row(s), but this MultiVector has "
2990 lclNumRows !=
B.getLocalLength(), std::invalid_argument,
2991 "The input MultiVector B has " <<
B.getLocalLength() <<
" local "
2992 "row(s), but this MultiVector has "
2996 A.getNumVectors() !=
numVecs, std::invalid_argument,
2997 "The input MultiVector A has " <<
A.getNumVectors() <<
" column(s), "
2998 "but this MultiVector has "
3001 B.getNumVectors() !=
numVecs, std::invalid_argument,
3002 "The input MultiVector B has " <<
B.getNumVectors() <<
" column(s), "
3003 "but this MultiVector has "
3021 if (isConstantStride() &&
A.isConstantStride() &&
B.isConstantStride()) {
3027 const size_t this_col = isConstantStride() ?
k : whichVectors_[
k];
3028 const size_t A_col =
A.isConstantStride() ?
k :
A.whichVectors_[
k];
3029 const size_t B_col =
B.isConstantStride() ?
k :
B.whichVectors_[
k];
3037template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3038Teuchos::ArrayRCP<const Scalar>
3050 auto hostView = getLocalViewHost(Access::ReadOnly);
3051 const size_t col = isConstantStride() ?
j : whichVectors_[
j];
3054 Kokkos::Compat::persistingView(
hostView_j, 0, getLocalLength());
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;
3075 auto hostView = getLocalViewHost(Access::ReadWrite);
3076 const size_t col = isConstantStride() ?
j : whichVectors_[
j];
3079 Kokkos::Compat::persistingView(
hostView_j, 0, getLocalLength());
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 {
3103 if (
cols[
j] !=
cols[
j - 1] +
static_cast<size_t>(1)) {
3118template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3119Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
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,
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();
3173 const int myRank = comm->getRank();
3176 const LO numCols =
static_cast<LO
>(
X.getNumVectors());
3179 std::ostringstream
os;
3182 <<
", origLclNumRows: " <<
X.getOrigNumLocalRows()
3183 <<
", numCols: " << numCols <<
"}, "
3185 std::cerr <<
os.str();
3193 errStrm = std::unique_ptr<std::ostringstream>(
new std::ostringstream);
3194 *
errStrm <<
" Proc " <<
myRank <<
": subMap->getLocalNumElements() (="
3196 <<
") > X.getOrigNumLocalRows() (=" <<
X.getOrigNumLocalRows()
3214 using range_type = std::pair<LO, LO>;
3226 newView.extent(1) !=
X.view_.extent(1)) {
3238 if (
errStrm.get() ==
nullptr) {
3239 errStrm = std::unique_ptr<std::ostringstream>(
new std::ostringstream);
3248 "dimensions on one or more processes:"
3260 std::ostringstream
os;
3262 std::cerr <<
os.str();
3268 std::ostringstream
os;
3270 std::cerr <<
os.str();
3274template <
class Scalar,
class LO,
class GO,
class Node>
3282template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3283Teuchos::RCP<const MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
3286 const size_t offset)
const {
3291template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3292Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
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;
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() = "
3321 if (
cols[
j] !=
cols[
j - 1] +
static_cast<size_t>(1)) {
3336 if (isConstantStride()) {
3337 return rcp(
new MV(this->getMap(), view_,
cols));
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> >
3352 using Kokkos::subview;
3353 using Teuchos::Array;
3356 using ::Tpetra::Details::Behavior;
3360 const size_t lclNumRows = this->getLocalLength();
3361 const size_t numVecs = this->getNumVectors();
3366 static_cast<size_t>(
colRng.size()) >
numVecs, std::runtime_error,
3367 "colRng.size() = " <<
colRng.size() <<
" > this->getNumVectors() = "
3371 (
colRng.lbound() <
static_cast<Teuchos::Ordinal
>(0) ||
3373 std::invalid_argument,
"Nonempty input range [" <<
colRng.lbound() <<
"," <<
colRng.ubound() <<
"] exceeds the valid range of column indices "
3388 if (
colRng.size() == 0) {
3389 const std::pair<size_t, size_t>
cols(0, 0);
3394 if (isConstantStride()) {
3395 const std::pair<size_t, size_t>
cols(
colRng.lbound(),
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(),
3404 whichVectors_[0] +
colRng.ubound() + 1);
3409 whichVectors_.begin() +
colRng.ubound() + 1);
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()) {
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())) {
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>
3473 using Kokkos::subview;
3474 typedef std::pair<size_t, size_t> range_type;
3475 const char tfecfFuncName[] =
"MultiVector(const MultiVector&, const size_t): ";
3477 const size_t numCols =
X.getNumVectors();
3479 const size_t jj =
X.isConstantStride() ?
static_cast<size_t>(
j) :
static_cast<size_t>(
X.whichVectors_[
j]);
3491 const size_t newSize =
X.imports_.extent(0) / numCols;
3500 const size_t newSize =
X.exports_.extent(0) / numCols;
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>;
3540 const size_t numRows = this->getLocalLength();
3541 const size_t numCols = this->getNumVectors();
3544 "LDA = " <<
LDA <<
" < numRows = " <<
numRows <<
".");
3548 "A.size() = " <<
A.size() <<
", but its size must be at least "
3549 << (
LDA * (numCols - 1) +
numRows) <<
" to hold all the entries.");
3552 const std::pair<size_t, size_t>
colRange(0, numCols);
3554 input_view_type
A_view_orig(
reinterpret_cast<IST*
>(
A.getRawPtr()),
3569 if (this->need_sync_host() && this->need_sync_device()) {
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()) {
3577 auto srcView_host = this->getLocalViewHost(Access::ReadOnly);
3581 auto srcView_device = this->getLocalViewDevice(Access::ReadOnly);
3586 for (
size_t j = 0;
j < numCols; ++
j) {
3587 const size_t srcCol = this->whichVectors_[
j];
3591 auto srcView_host = this->getLocalViewHost(Access::ReadOnly);
3596 auto srcView_device = this->getLocalViewDevice(Access::ReadOnly);
3606template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3611 const size_t numRows = this->getLocalLength();
3612 const size_t numCols = this->getNumVectors();
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) {
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() = "
3633 for (
size_t j = 0;
j < numCols; ++
j) {
3634 Teuchos::RCP<const V>
X_j = this->getVector(
j);
3641template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3642Teuchos::ArrayRCP<const Scalar>
3645 if (getLocalLength() == 0 || getNumVectors() == 0) {
3646 return Teuchos::null;
3649 !isConstantStride(), std::runtime_error,
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().");
3658 auto X_lcl = getLocalViewHost(Access::ReadOnly);
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>
3669 if (this->getLocalLength() == 0 || this->getNumVectors() == 0) {
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().");
3678 auto X_lcl = getLocalViewHost(Access::ReadWrite);
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> >
3689 auto X_lcl = getLocalViewHost(Access::ReadWrite);
3695 const size_t myNumRows = this->getLocalLength();
3696 const size_t numCols = this->getNumVectors();
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];
3704 Kokkos::Compat::persistingView(
X_lcl_j);
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>
3759template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3760Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> >
3766 auto X_lcl = getLocalViewHost(Access::ReadOnly);
3772 const size_t myNumRows = this->getLocalLength();
3773 const size_t numCols = this->getNumVectors();
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];
3780 Teuchos::ArrayRCP<const impl_scalar_type>
X_lcl_j_arcp =
3781 Kokkos::Compat::persistingView(
X_lcl_j);
3787template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3796 using Teuchos::CONJ_TRANS;
3797 using Teuchos::NO_TRANS;
3800 using Teuchos::rcpFromRef;
3801 using Teuchos::TRANS;
3802 using ::Tpetra::Details::ProfilingRegion;
3803 using ATS = KokkosKernels::ArithTraits<impl_scalar_type>;
3805 using STS = Teuchos::ScalarTraits<Scalar>;
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();
3869 const int myRank = comm->getRank();
3871 if (this->getLocalLength() !=
A_nrows) {
3873 << this->getLocalLength() <<
" != A_nrows=" <<
A_nrows
3874 <<
"." << std::endl;
3876 if (this->getNumVectors() !=
B_ncols) {
3878 << this->getNumVectors() <<
" != B_ncols=" <<
B_ncols
3879 <<
"." << std::endl;
3884 <<
"." << std::endl;
3891 std::ostringstream
os;
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
3906 <<
"Global dimensions: C(" << this->getGlobalLength() <<
", "
3907 << this->getNumVectors() <<
"), A(" <<
A.getGlobalLength()
3908 <<
", " <<
A.getNumVectors() <<
"), B(" <<
B.getGlobalLength()
3909 <<
", " <<
B.getNumVectors() <<
")." << std::endl
3927 "Multiplication of op(A) and op(B) into *this is not a "
3928 "supported use case.");
3936 const int myRank = this->getMap()->getComm()->getRank();
3947 if (!isConstantStride()) {
3948 C_tmp =
rcp(
new MV(*
this, Teuchos::Copy));
3954 if (!
A.isConstantStride()) {
3961 if (!
B.isConstantStride()) {
3968 !
A_tmp->isConstantStride(),
3970 "Failed to make temporary constant-stride copies of MultiVectors.");
3975 auto A_lcl =
A_tmp->getLocalViewDevice(Access::ReadOnly);
3976 auto A_sub = Kokkos::subview(A_lcl,
3982 auto B_lcl =
B_tmp->getLocalViewDevice(Access::ReadOnly);
3983 auto B_sub = Kokkos::subview(B_lcl,
3990 auto C_lcl =
C_tmp->getLocalViewDevice(Access::ReadWrite);
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");
4004 if (!isConstantStride()) {
4009 A_tmp = Teuchos::null;
4010 B_tmp = Teuchos::null;
4018template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4025 using Kokkos::subview;
4028 const size_t lclNumRows = this->getLocalLength();
4029 const size_t numVecs = this->getNumVectors();
4032 std::runtime_error,
"MultiVectors do not have the same local length.");
4034 numVecs !=
B.getNumVectors(), std::runtime_error,
4035 "this->getNumVectors"
4037 <<
numVecs <<
" != B.getNumVectors() = " <<
B.getNumVectors()
4040 auto this_view = this->getLocalViewDevice(Access::ReadWrite);
4041 auto A_view =
A.getLocalViewDevice(Access::ReadOnly);
4042 auto B_view =
B.getLocalViewDevice(Access::ReadOnly);
4044 if (isConstantStride() &&
B.isConstantStride()) {
4057 const size_t C_col = isConstantStride() ?
j : whichVectors_[
j];
4058 const size_t B_col =
B.isConstantStride() ?
j :
B.whichVectors_[
j];
4068template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4071 using ::Tpetra::Details::allReduceView;
4072 using ::Tpetra::Details::ProfilingRegion;
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) {
4091 Kokkos::fence(
"MultiVector::reduce");
4092 auto X_lcl = this->getLocalViewDevice(Access::ReadWrite);
4095 auto X_lcl = this->getLocalViewHost(Access::ReadWrite);
4100template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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
4116 vectorIndexOutOfRange(col),
4118 "Tpetra::MultiVector::replaceLocalValue: vector index " << col
4119 <<
" of the multivector is invalid.");
4122 auto view = this->getLocalViewHost(Access::ReadWrite);
4123 const size_t colInd = isConstantStride() ? col : whichVectors_[col];
4127template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4132 const bool atomic) {
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
4144 vectorIndexOutOfRange(col),
4146 "Tpetra::MultiVector::sumIntoLocalValue: vector index " << col
4147 <<
" of the multivector is invalid.");
4150 const size_t colInd = isConstantStride() ? col : whichVectors_[col];
4152 auto view = this->getLocalViewHost(Access::ReadWrite);
4160template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4173 "Global row index " <<
gblRow <<
" is not present on this process "
4174 << this->getMap()->getComm()->getRank() <<
".");
4176 "Vector index " << col <<
" of the MultiVector is invalid.");
4182template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4187 const bool atomic) {
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() <<
".");
4200 vectorIndexOutOfRange(col),
4202 "Tpetra::MultiVector::sumIntoGlobalValue: Vector index " << col
4203 <<
" of the multivector is invalid.");
4206 this->sumIntoLocalValue(
lclRow, col, value, atomic);
4209template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4216 typename dual_view_type::array_layout,
4219 const size_t col = isConstantStride() ?
j : whichVectors_[
j];
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;
4248 <<
", Node" << Node::name()
4253 out <<
", numRows: " << this->getGlobalLength();
4255 out <<
", numCols: " << this->getNumVectors()
4256 <<
", isConstantStride: " << this->isConstantStride();
4258 if (this->isConstantStride()) {
4259 out <<
", columnStride: " << this->getStride();
4266template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4270 return this->descriptionImpl(
"Tpetra::MultiVector");
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);
4296 for (
size_t j = 0;
j < numCols; ++
j) {
4298 if (
j + 1 < numCols) {
4311template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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());
4327 Teuchos::FancyOStream&
out = *
outp;
4328 auto comm =
map->getComm();
4329 const int myRank = comm->getRank();
4330 const int numProcs = comm->getSize();
4336 const LO
lclNumRows =
static_cast<LO
>(this->getLocalLength());
4339 if (
vl > Teuchos::VERB_MEDIUM) {
4342 if (this->getNumVectors() !=
static_cast<size_t>(1)) {
4343 out <<
"isConstantStride: " << this->isConstantStride() <<
endl;
4345 if (this->isConstantStride()) {
4346 out <<
"Column stride: " << this->getStride() <<
endl;
4357 auto X_dev = view_.getDeviceCopy();
4358 auto X_host = view_.getHostCopy();
4362 Details::print_vector(
out,
"unified",
X_host);
4364 Details::print_vector(
out,
"host",
X_host);
4365 Details::print_vector(
out,
"dev",
X_dev);
4373template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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 =
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));
4417 tab1 = Teuchos::rcp(
new Teuchos::OSTab(
out));
4419 out <<
"Template parameters:" <<
endl;
4424 <<
"Node: " << Node::name() <<
endl;
4429 out <<
"Global number of rows: " << this->getGlobalLength() <<
endl;
4431 out <<
"Number of columns: " << this->getNumVectors() <<
endl;
4439 const std::string
lclStr = this->localDescribeToString(
vl);
4444template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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>
4460 using ::Tpetra::Details::localDeepCopy;
4461 const char prefix[] =
"Tpetra::MultiVector::assign: ";
4464 this->getNumVectors() != src.getNumVectors(),
4465 std::invalid_argument,
4466 prefix <<
"Global dimensions of the two Tpetra::MultiVector "
4467 "objects do not match. src has dimensions ["
4468 << src.getGlobalLength()
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 "
4475 << src.getLocalLength() <<
" row(s) "
4476 <<
" and *this has " <<
this->getLocalLength() <<
" row(s).");
4491 localDeepCopy(this->getLocalViewHost(Access::ReadWrite),
4492 src.getLocalViewHost(Access::ReadOnly),
4493 this->isConstantStride(),
4494 src.isConstantStride(),
4495 this->whichVectors_(),
4496 src.whichVectors_());
4498 localDeepCopy(this->getLocalViewDevice(Access::ReadWrite),
4499 src.getLocalViewDevice(Access::ReadOnly),
4500 this->isConstantStride(),
4501 src.isConstantStride(),
4502 this->whichVectors_(),
4503 src.whichVectors_());
4507template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4509Teuchos::RCP<MultiVector<T, LocalOrdinal, GlobalOrdinal, Node> >
4515 this->getNumVectors(),
4521template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4524 using ::Tpetra::Details::PackTraits;
4526 const size_t l1 = this->getLocalLength();
4527 const size_t l2 =
vec.getLocalLength();
4528 if ((
l1 !=
l2) || (this->getNumVectors() !=
vec.getNumVectors())) {
4535template <
class ST,
class LO,
class GO,
class NT>
4538 std::swap(
mv.map_,
this->map_);
4539 std::swap(
mv.view_,
this->view_);
4540 std::swap(
mv.whichVectors_,
this->whichVectors_);
4543#ifdef HAVE_TPETRACORE_TEUCHOSNUMERICS
4544template <
class ST,
class LO,
class GO,
class NT>
4546 const Teuchos::SerialDenseMatrix<int, ST>& src) {
4547 using ::Tpetra::Details::localDeepCopy;
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());
4559 numCols !=
static_cast<LO
>(dst.getNumVectors()),
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());
4569 localDeepCopy(dst.getLocalViewHost(Access::ReadWrite),
4571 dst.isConstantStride(),
4573 getMultiVectorWhichVectors(dst),
4577template <
class ST,
class LO,
class GO,
class NT>
4578void deep_copy(Teuchos::SerialDenseMatrix<int, ST>& dst,
4580 using ::Tpetra::Details::localDeepCopy;
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());
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());
4609 getMultiVectorWhichVectors(src));
4613template <
class Scalar,
class LO,
class GO,
class NT>
4614Teuchos::RCP<MultiVector<Scalar, LO, GO, NT> >
4621template <
class ST,
class LO,
class GO,
class NT>
4625 MV
cpy(src.getMap(), src.getNumVectors(),
false);
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...
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.