10 #ifndef BELOS_TPETRA_ADAPTER_MP_VECTOR_HPP
11 #define BELOS_TPETRA_ADAPTER_MP_VECTOR_HPP
13 #include "BelosTpetraAdapter.hpp"
16 #include "KokkosBlas.hpp"
18 #ifdef HAVE_BELOS_TSQR
20 #endif // HAVE_BELOS_TSQR
40 template<
class Storage,
class LO,
class GO,
class Node>
42 Tpetra::MultiVector< Sacado::MP::Vector<Storage>,
48 typedef Tpetra::MultiVector<Scalar, LO, GO, Node>
MV;
50 typedef typename Tpetra::MultiVector<Scalar,LO,GO,Node>::dot_type
dot_type;
51 typedef typename Tpetra::MultiVector<Scalar,LO,GO,Node>::mag_type
mag_type;
95 #ifdef HAVE_TPETRA_DEBUG
96 const char fnName[] =
"Belos::MultiVecTraits::CloneCopy(mv,index)";
97 const size_t inNumVecs = mv.getNumVectors ();
99 index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
100 std::runtime_error, fnName <<
": All indices must be nonnegative.");
103 static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= inNumVecs,
105 fnName <<
": All indices must be strictly less than the number of "
106 "columns " << inNumVecs <<
" of the input multivector mv.");
107 #endif // HAVE_TPETRA_DEBUG
111 for (std::vector<int>::size_type
j = 0;
j < index.size (); ++
j) {
112 columns[
j] = index[
j];
131 const bool validRange = index.
size() > 0 &&
133 index.
ubound() < GetNumberVecs(mv);
135 std::ostringstream os;
136 os <<
"Belos::MultiVecTraits::CloneCopy(mv,index=["
139 index.
size() == 0, std::invalid_argument,
140 os.str() <<
"Empty index range is not allowed.");
142 index.
lbound() < 0, std::invalid_argument,
143 os.str() <<
"Index range includes negative index/ices, which is not "
146 index.
ubound() >= GetNumberVecs(mv), std::invalid_argument,
147 os.str() <<
"Index range exceeds number of vectors "
148 << mv.getNumVectors() <<
" in the input multivector.");
150 os.str() <<
"Should never get here!");
161 #ifdef HAVE_TPETRA_DEBUG
162 const char fnName[] =
"Belos::MultiVecTraits::CloneViewNonConst(mv,index)";
163 const size_t numVecs = mv.getNumVectors ();
165 index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
166 std::invalid_argument,
167 fnName <<
": All indices must be nonnegative.");
170 static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
171 std::invalid_argument,
172 fnName <<
": All indices must be strictly less than the number of "
173 "columns " << numVecs <<
" in the input MultiVector mv.");
174 #endif // HAVE_TPETRA_DEBUG
178 for (std::vector<int>::size_type
j = 0;
j < index.size (); ++
j) {
179 columns[
j] = index[
j];
195 const int numCols =
static_cast<int> (mv.getNumVectors());
196 const bool validRange = index.
size() > 0 &&
199 std::ostringstream os;
200 os <<
"Belos::MultiVecTraits::CloneViewNonConst(mv,index=["
203 index.
size() == 0, std::invalid_argument,
204 os.str() <<
"Empty index range is not allowed.");
206 index.
lbound() < 0, std::invalid_argument,
207 os.str() <<
"Index range includes negative inde{x,ices}, which is "
210 index.
ubound() >= numCols, std::invalid_argument,
211 os.str() <<
"Index range exceeds number of vectors " << numCols
212 <<
" in the input multivector.");
214 true, std::logic_error,
215 os.str() <<
"Should never get here!");
225 #ifdef HAVE_TPETRA_DEBUG
226 const char fnName[] =
"Belos::MultiVecTraits<Scalar, "
227 "Tpetra::MultiVector<...> >::CloneView(mv,index)";
228 const size_t numVecs = mv.getNumVectors ();
230 *std::min_element (index.begin (), index.end ()) < 0,
231 std::invalid_argument,
232 fnName <<
": All indices must be nonnegative.");
234 static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
235 std::invalid_argument,
236 fnName <<
": All indices must be strictly less than the number of "
237 "columns " << numVecs <<
" in the input MultiVector mv.");
238 #endif // HAVE_TPETRA_DEBUG
242 for (std::vector<int>::size_type
j = 0;
j < index.size (); ++
j) {
243 columns[
j] = index[
j];
259 const int numCols =
static_cast<int> (mv.getNumVectors());
260 const bool validRange = index.
size() > 0 &&
263 std::ostringstream os;
264 os <<
"Belos::MultiVecTraits::CloneView(mv, index=["
267 os.str() <<
"Empty index range is not allowed.");
269 os.str() <<
"Index range includes negative index/ices, which is not "
272 index.
ubound() >= numCols, std::invalid_argument,
273 os.str() <<
"Index range exceeds number of vectors " << numCols
274 <<
" in the input multivector.");
276 os.str() <<
"Should never get here!");
284 return static_cast<ptrdiff_t
> (mv.getGlobalLength ());
288 return static_cast<int> (mv.getNumVectors ());
292 return mv.isConstantStride ();
295 template <
class DstType,
class SrcType>
301 if (std::is_same<typename SrcType::memory_space, Kokkos::HostSpace>::value)
304 for (
size_t i = 0; i < src.extent(0); i++)
306 for (
size_t j = 0;
j < src.extent(1);
j++)
308 dst_i(i,
j) = src(i,
j);
317 for (
size_t i = 0; i < src.extent(0); i++)
319 for (
size_t j = 0;
j < src.extent(1);
j++)
321 dst(i,
j) = src_i(i,
j);
329 const Tpetra::MultiVector<Scalar,LO,GO,Node>&
A,
332 Tpetra::MultiVector<Scalar,LO,GO,Node>&
C)
338 const int numRowsB = B.
numRows ();
339 const int numColsB = B.
numCols ();
340 const int strideB = B.
stride ();
341 if (numRowsB == 1 && numColsB == 1) {
342 C.update (alpha*B(0,0), A, beta);
350 else Atmp =
rcp(&A,
false);
353 else Ctmp =
rcp(&C,
false);
356 typedef Tpetra::MultiVector<dot_type,LO,GO,Node> FMV;
357 typedef typename FMV::dual_view_type::t_dev flat_view_type;
359 typename flat_view_type::const_type flat_A_view = Atmp->getLocalViewDevice(Tpetra::Access::ReadOnly);
360 flat_view_type flat_C_view = Ctmp->getLocalViewDevice(Tpetra::Access::OverwriteAll);
363 typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, Kokkos::HostSpace> b_host_view_type;
364 b_host_view_type B_view_host_input( B.
values(), strideB, numColsB);
365 auto B_view_host = Kokkos::subview(B_view_host_input,
366 Kokkos::pair<int,int>(0,numRowsB),
367 Kokkos::pair<int,int>(0,numColsB));
371 typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, execution_space> b_view_type;
372 typedef Kokkos::View<dot_type*, Kokkos::LayoutLeft, execution_space> b_1d_view_type;
373 b_1d_view_type B_1d_view_dev(Kokkos::ViewAllocateWithoutInitializing(
"B"), numRowsB*numColsB);
374 b_view_type B_view_dev( B_1d_view_dev.data(), numRowsB, numColsB);
376 if (Kokkos::SpaceAccessibility<Kokkos::HostSpace, typename execution_space::memory_space>::accessible)
382 deep_copy_2d_view_with_intercessory_space(B_view_dev, B_view_host);
387 const char ctransA =
'N', ctransB =
'N';
390 alpha, flat_A_view, B_view_dev, beta, flat_C_view);
393 if (C.isConstantStride() ==
false)
406 const Tpetra::MultiVector<Scalar,LO,GO,Node>&
A,
408 const Tpetra::MultiVector<Scalar,LO,GO,Node>&
B,
409 Tpetra::MultiVector<Scalar,LO,GO,Node>& mv)
415 MvScale (Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
422 MvScale (Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
423 const std::vector<BaseScalar>& alphas)
425 std::vector<Scalar> alphas_mp(alphas.size());
426 const size_t sz = alphas.size();
427 for (
size_t i=0; i<sz; ++i)
428 alphas_mp[i] = alphas[i];
429 mv.scale (alphas_mp);
433 MvScale (Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
434 const std::vector<Scalar>& alphas)
441 const Tpetra::MultiVector<Scalar,LO,GO,Node>&
A,
442 const Tpetra::MultiVector<Scalar,LO,GO,Node>&
B,
449 using Teuchos::reduceAll;
452 const int numRowsC = C.
numRows ();
453 const int numColsC = C.
numCols ();
454 const int strideC = C.
stride ();
455 if (numRowsC == 1 && numColsC == 1) {
469 RCP<const MV> Atmp, Btmp;
471 else Atmp =
rcp(&A,
false);
474 else Btmp =
rcp(&B,
false);
477 typedef Tpetra::MultiVector<dot_type,LO,GO,Node> FMV;
478 typedef typename FMV::dual_view_type::t_dev flat_view_type;
480 typename flat_view_type::const_type flat_A_view = Atmp->getLocalViewDevice(Tpetra::Access::ReadOnly);
481 typename flat_view_type::const_type flat_B_view = Btmp->getLocalViewDevice(Tpetra::Access::ReadOnly);
484 typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, Kokkos::HostSpace> c_host_view_type;
485 c_host_view_type C_view_host_input( C.
values(), strideC, numColsC);
486 auto C_view_host = Kokkos::subview(C_view_host_input,
487 Kokkos::pair<int,int>(0,numRowsC),
488 Kokkos::pair<int,int>(0,numColsC));
492 typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, execution_space> c_view_type;
493 typedef Kokkos::View<dot_type*, Kokkos::LayoutLeft, execution_space> c_1d_view_type;
494 c_1d_view_type C_1d_view_dev(
"C", numRowsC*numColsC);
495 c_view_type C_view_dev( C_1d_view_dev.data(), numRowsC, numColsC);
499 const char ctransA =
'C', ctransB =
'N';
502 alpha, flat_A_view, flat_B_view,
503 Kokkos::ArithTraits<dot_type>::zero(),
508 RCP<const Comm<int> > pcomm = A.getMap()->getComm ();
509 if (pcomm->getSize () == 1)
511 if (Kokkos::SpaceAccessibility<execution_space, Kokkos::HostSpace>::accessible)
517 deep_copy_2d_view_with_intercessory_space(C_view_host, C_view_dev);
522 typedef Kokkos::View<dot_type*, Kokkos::LayoutLeft, Kokkos::HostSpace> c_1d_host_view_type;
523 c_1d_host_view_type C_1d_view_tmp(Kokkos::ViewAllocateWithoutInitializing(
"C_tmp"), strideC*numColsC);
524 c_host_view_type C_view_tmp_input( C_1d_view_tmp.data(), strideC, numColsC);
525 auto C_view_tmp = Kokkos::subview(C_view_tmp_input,
526 Kokkos::pair<int,int>(0,numRowsC),
527 Kokkos::pair<int,int>(0,numColsC));
529 if (Kokkos::SpaceAccessibility<execution_space, Kokkos::HostSpace>::accessible)
535 deep_copy_2d_view_with_intercessory_space(C_view_tmp, C_view_dev);
538 reduceAll<int> (*pcomm, REDUCE_SUM, strideC*numColsC,
546 MvDot (
const Tpetra::MultiVector<Scalar,LO,GO,Node>&
A,
547 const Tpetra::MultiVector<Scalar,LO,GO,Node>&
B,
548 std::vector<dot_type>& dots)
550 const size_t numVecs = A.getNumVectors ();
553 numVecs != B.getNumVectors (), std::invalid_argument,
554 "Belos::MultiVecTraits<Scalar,Tpetra::MultiVector>::MvDot(A,B,dots): "
555 "A and B must have the same number of columns. "
556 "A has " << numVecs <<
" column(s), "
557 "but B has " << B.getNumVectors () <<
" column(s).");
558 #ifdef HAVE_TPETRA_DEBUG
560 dots.size() < numVecs, std::invalid_argument,
561 "Belos::MultiVecTraits<Scalar,Tpetra::MultiVector>::MvDot(A,B,dots): "
562 "The output array 'dots' must have room for all dot products. "
563 "A and B each have " << numVecs <<
" column(s), "
564 "but 'dots' only has " << dots.size() <<
" entry(/ies).");
565 #endif // HAVE_TPETRA_DEBUG
568 A.dot (B, av (0, numVecs));
573 MvNorm (
const Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
574 std::vector<mag_type> &normvec,
575 NormType type=TwoNorm)
578 #ifdef HAVE_TPETRA_DEBUG
579 typedef std::vector<int>::size_type size_type;
581 normvec.size () <
static_cast<size_type
> (mv.getNumVectors ()),
582 std::invalid_argument,
583 "Belos::MultiVecTraits::MvNorm(mv,normvec): The normvec output "
584 "argument must have at least as many entries as the number of vectors "
585 "(columns) in the MultiVector mv. normvec.size() = " << normvec.size ()
586 <<
" < mv.getNumVectors() = " << mv.getNumVectors () <<
".");
592 mv.norm1(av(0,mv.getNumVectors()));
595 mv.norm2(av(0,mv.getNumVectors()));
598 mv.normInf(av(0,mv.getNumVectors()));
605 true, std::logic_error,
606 "Belos::MultiVecTraits::MvNorm: Invalid NormType value " << type
607 <<
". Valid values are OneNorm=" << OneNorm <<
", TwoNorm="
608 << TwoNorm <<
", and InfNorm=" << InfNorm <<
". If you are a Belos "
609 "user and have not modified Belos in any way, and you get this "
610 "message, then this is probably a bug in the Belos solver you were "
611 "using. Please report this to the Belos developers.");
620 const size_t inNumVecs = A.getNumVectors ();
621 #ifdef HAVE_TPETRA_DEBUG
623 inNumVecs < static_cast<size_t> (index.size ()), std::invalid_argument,
624 "Belos::MultiVecTraits::SetBlock(A,index,mv): 'index' argument must "
625 "have no more entries as the number of columns in the input MultiVector"
626 " A. A.getNumVectors() = " << inNumVecs <<
" < index.size () = "
627 << index.size () <<
".");
628 #endif // HAVE_TPETRA_DEBUG
629 RCP<MV> mvsub = CloneViewNonConst (mv, index);
630 if (inNumVecs > static_cast<size_t> (index.size ())) {
631 RCP<const MV> Asub = A.subView (Range1D (0, index.size () - 1));
648 const size_t maxInt =
650 const bool overflow =
651 maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
653 std::ostringstream os;
654 os <<
"Belos::MultiVecTraits::SetBlock(A, index=[" << index.
lbound ()
655 <<
", " << index.
ubound () <<
"], mv): ";
657 maxInt < A.getNumVectors (), std::range_error, os.str () <<
"Number "
658 "of columns (size_t) in the input MultiVector 'A' overflows int.");
660 maxInt < mv.getNumVectors (), std::range_error, os.str () <<
"Number "
661 "of columns (size_t) in the output MultiVector 'mv' overflows int.");
664 const int numColsA =
static_cast<int> (A.getNumVectors ());
665 const int numColsMv =
static_cast<int> (mv.getNumVectors ());
667 const bool validIndex =
670 const bool validSource = index.
size () <= numColsA;
672 if (! validIndex || ! validSource) {
673 std::ostringstream os;
674 os <<
"Belos::MultiVecTraits::SetBlock(A, index=[" << index.
lbound ()
675 <<
", " << index.
ubound () <<
"], mv): ";
677 index.
lbound() < 0, std::invalid_argument,
678 os.str() <<
"Range lower bound must be nonnegative.");
680 index.
ubound() >= numColsMv, std::invalid_argument,
681 os.str() <<
"Range upper bound must be less than the number of "
682 "columns " << numColsA <<
" in the 'mv' output argument.");
684 index.
size() > numColsA, std::invalid_argument,
685 os.str() <<
"Range must have no more elements than the number of "
686 "columns " << numColsA <<
" in the 'A' input argument.");
688 true, std::logic_error,
"Should never get here!");
695 if (index.
lbound () == 0 && index.
ubound () + 1 == numColsMv) {
696 mv_view = Teuchos::rcpFromRef (mv);
698 mv_view = CloneViewNonConst (mv, index);
705 if (index.
size () == numColsA) {
706 A_view = Teuchos::rcpFromRef (A);
716 const char errPrefix[] =
"Belos::MultiVecTraits::Assign(A, mv): ";
725 const size_t maxInt =
727 const bool overflow =
728 maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
731 maxInt < A.getNumVectors(), std::range_error,
732 errPrefix <<
"Number of columns in the input multivector 'A' "
733 "(a size_t) overflows int.");
735 maxInt < mv.getNumVectors(), std::range_error,
736 errPrefix <<
"Number of columns in the output multivector 'mv' "
737 "(a size_t) overflows int.");
739 true, std::logic_error,
"Should never get here!");
742 const int numColsA =
static_cast<int> (A.getNumVectors ());
743 const int numColsMv =
static_cast<int> (mv.getNumVectors ());
744 if (numColsA > numColsMv) {
746 numColsA > numColsMv, std::invalid_argument,
747 errPrefix <<
"Input multivector 'A' has " << numColsA <<
" columns, "
748 "but output multivector 'mv' has only " << numColsMv <<
" columns.");
751 if (numColsA == numColsMv) {
768 mv.putScalar (alpha);
776 #ifdef HAVE_BELOS_TSQR
777 typedef Tpetra::TsqrAdaptor< Tpetra::MultiVector< Scalar, LO, GO, Node > > tsqr_adaptor_type;
781 #endif // HAVE_BELOS_TSQR
791 template <
class Storage,
class LO,
class GO,
class Node>
793 Tpetra::MultiVector<Sacado::MP::Vector<Storage>,
795 Tpetra::Operator<Sacado::MP::Vector<Storage>,
801 Apply (
const Tpetra::Operator<Scalar,LO,GO,Node>& Op,
802 const Tpetra::MultiVector<Scalar,LO,GO,Node>& X,
803 Tpetra::MultiVector<Scalar,LO,GO,Node>& Y,
804 ETrans trans=NOTRANS)
821 const std::string otName =
"Belos::OperatorTraits<" + scalarName
822 +
"," + loName +
"," + goName +
"," + nodeName +
">";
824 "get here; fell through a switch statement. "
825 "Please report this bug to the Belos developers.");
832 return Op.hasTransposeApply ();
ScalarType * values() const
Tpetra::MultiVector< Scalar, LO, GO, Node >::mag_type mag_type
static int GetNumberVecs(const MV &mv)
static bool HasApplyTranspose(const Tpetra::Operator< Scalar, LO, GO, Node > &Op)
static void Assign(const MV &A, MV &mv)
static Teuchos::RCP< MV > CloneCopy(const MV &mv, const std::vector< int > &index)
Create and return a deep copy of the given columns of mv.
static void MvScale(Tpetra::MultiVector< Scalar, LO, GO, Node > &mv, const std::vector< BaseScalar > &alphas)
Kokkos::DefaultExecutionSpace execution_space
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Storage::ordinal_type s_ordinal
Tpetra::MultiVector< Scalar, LO, GO, Node > MV
Sacado::MP::Vector< Storage > Scalar
static bool HasConstantStride(const MV &mv)
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const Teuchos::Range1D &index)
static void MvTimesMatAddMv(const dot_type &alpha, const Tpetra::MultiVector< Scalar, LO, GO, Node > &A, const Teuchos::SerialDenseMatrix< int, dot_type > &B, const dot_type &beta, Tpetra::MultiVector< Scalar, LO, GO, Node > &C)
static void deep_copy_2d_view_with_intercessory_space(const DstType &dst, const SrcType &src)
static void MvScale(Tpetra::MultiVector< Scalar, LO, GO, Node > &mv, const Scalar &alpha)
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
static void MvPrint(const MV &mv, std::ostream &os)
static void MvScale(Tpetra::MultiVector< Scalar, LO, GO, Node > &mv, const std::vector< Scalar > &alphas)
static void MvTransMv(dot_type alpha, const Tpetra::MultiVector< Scalar, LO, GO, Node > &A, const Tpetra::MultiVector< Scalar, LO, GO, Node > &B, Teuchos::SerialDenseMatrix< int, dot_type > &C)
static ptrdiff_t GetGlobalLength(const MV &mv)
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
static void MvNorm(const Tpetra::MultiVector< Scalar, LO, GO, Node > &mv, std::vector< mag_type > &normvec, NormType type=TwoNorm)
For all columns j of mv, set normvec[j] = norm(mv[j]).
Storage::value_type BaseScalar
Tpetra::MultiVector< Scalar, LO, GO, Node >::dot_type dot_type
static Teuchos::RCP< MV > CloneCopy(const MV &X)
Create and return a deep copy of X.
static Teuchos::RCP< MV > Clone(const MV &X, const int numVecs)
Create a new MultiVector with numVecs columns.
OrdinalType numCols() const
static void Apply(const Tpetra::Operator< Scalar, LO, GO, Node > &Op, const Tpetra::MultiVector< Scalar, LO, GO, Node > &X, Tpetra::MultiVector< Scalar, LO, GO, Node > &Y, ETrans trans=NOTRANS)
static Teuchos::RCP< MV > CloneCopy(const MV &mv, const Teuchos::Range1D &index)
Create and return a deep copy of the given columns of mv.
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
std::enable_if< Kokkos::is_view_mp_vector< Kokkos::View< DA, PA...> >::value &&Kokkos::is_view_mp_vector< Kokkos::View< DB, PB...> >::value &&Kokkos::is_view_mp_vector< Kokkos::View< DC, PC...> >::value >::type gemm(const char transA[], const char transB[], typename Kokkos::View< DA, PA...>::const_value_type &alpha, const Kokkos::View< DA, PA...> &A, const Kokkos::View< DB, PB...> &B, typename Kokkos::View< DC, PC...>::const_value_type &beta, const Kokkos::View< DC, PC...> &C)
Sacado::MP::Vector< Storage > Scalar
static void MvRandom(MV &mv)
Stokhos::CrsMatrix< ValueType, Device, Layout >::HostMirror create_mirror(const Stokhos::CrsMatrix< ValueType, Device, Layout > &A)
static Teuchos::RCP< const MV > CloneView(const MV &mv, const Teuchos::Range1D &index)
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
OrdinalType stride() const
static std::string name()
OrdinalType numRows() const
static void MvDot(const Tpetra::MultiVector< Scalar, LO, GO, Node > &A, const Tpetra::MultiVector< Scalar, LO, GO, Node > &B, std::vector< dot_type > &dots)
For all columns j of A, set dots[j] := A[j]^T * B[j].
static void SetBlock(const MV &A, const Teuchos::Range1D &index, MV &mv)
static void MvAddMv(Scalar alpha, const Tpetra::MultiVector< Scalar, LO, GO, Node > &A, Scalar beta, const Tpetra::MultiVector< Scalar, LO, GO, Node > &B, Tpetra::MultiVector< Scalar, LO, GO, Node > &mv)
mv := alpha*A + beta*B