42 #ifndef BELOS_TPETRA_ADAPTER_MP_VECTOR_HPP 
   43 #define BELOS_TPETRA_ADAPTER_MP_VECTOR_HPP 
   45 #include "BelosTpetraAdapter.hpp" 
   47 #include "KokkosBlas.hpp" 
   49 #ifdef HAVE_BELOS_TSQR 
   51 #endif // HAVE_BELOS_TSQR 
   71   template<
class Storage, 
class LO, 
class GO, 
class Node>
 
   73                        Tpetra::MultiVector< Sacado::MP::Vector<Storage>,
 
   79     typedef Tpetra::MultiVector<Scalar, LO, GO, Node> 
MV;
 
   81     typedef typename Tpetra::MultiVector<Scalar,LO,GO,Node>::dot_type 
dot_type;
 
   82     typedef typename Tpetra::MultiVector<Scalar,LO,GO,Node>::mag_type 
mag_type;
 
  126 #ifdef HAVE_TPETRA_DEBUG 
  127       const char fnName[] = 
"Belos::MultiVecTraits::CloneCopy(mv,index)";
 
  128       const size_t inNumVecs = mv.getNumVectors ();
 
  130         index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
 
  131         std::runtime_error, fnName << 
": All indices must be nonnegative.");
 
  134         static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= inNumVecs,
 
  136         fnName << 
": All indices must be strictly less than the number of " 
  137         "columns " << inNumVecs << 
" of the input multivector mv.");
 
  138 #endif // HAVE_TPETRA_DEBUG 
  142       for (std::vector<int>::size_type 
j = 0; 
j < index.size (); ++
j) {
 
  143         columns[
j] = index[
j];
 
  162       const bool validRange = index.
size() > 0 &&
 
  164         index.
ubound() < GetNumberVecs(mv);
 
  166         std::ostringstream os;
 
  167         os << 
"Belos::MultiVecTraits::CloneCopy(mv,index=[" 
  170           index.
size() == 0, std::invalid_argument,
 
  171           os.str() << 
"Empty index range is not allowed.");
 
  173           index.
lbound() < 0, std::invalid_argument,
 
  174           os.str() << 
"Index range includes negative index/ices, which is not " 
  177           index.
ubound() >= GetNumberVecs(mv), std::invalid_argument,
 
  178           os.str() << 
"Index range exceeds number of vectors " 
  179           << mv.getNumVectors() << 
" in the input multivector.");
 
  181           os.str() << 
"Should never get here!");
 
  192 #ifdef HAVE_TPETRA_DEBUG 
  193       const char fnName[] = 
"Belos::MultiVecTraits::CloneViewNonConst(mv,index)";
 
  194       const size_t numVecs = mv.getNumVectors ();
 
  196         index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
 
  197         std::invalid_argument,
 
  198         fnName << 
": All indices must be nonnegative.");
 
  201         static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
 
  202         std::invalid_argument,
 
  203         fnName << 
": All indices must be strictly less than the number of " 
  204         "columns " << numVecs << 
" in the input MultiVector mv.");
 
  205 #endif // HAVE_TPETRA_DEBUG 
  209       for (std::vector<int>::size_type 
j = 0; 
j < index.size (); ++
j) {
 
  210         columns[
j] = index[
j];
 
  226       const int numCols = 
static_cast<int> (mv.getNumVectors());
 
  227       const bool validRange = index.
size() > 0 &&
 
  230         std::ostringstream os;
 
  231         os << 
"Belos::MultiVecTraits::CloneViewNonConst(mv,index=[" 
  234           index.
size() == 0, std::invalid_argument,
 
  235           os.str() << 
"Empty index range is not allowed.");
 
  237           index.
lbound() < 0, std::invalid_argument,
 
  238           os.str() << 
"Index range includes negative inde{x,ices}, which is " 
  241           index.
ubound() >= numCols, std::invalid_argument,
 
  242           os.str() << 
"Index range exceeds number of vectors " << numCols
 
  243           << 
" in the input multivector.");
 
  245           true, std::logic_error,
 
  246           os.str() << 
"Should never get here!");
 
  256 #ifdef HAVE_TPETRA_DEBUG 
  257       const char fnName[] = 
"Belos::MultiVecTraits<Scalar, " 
  258         "Tpetra::MultiVector<...> >::CloneView(mv,index)";
 
  259       const size_t numVecs = mv.getNumVectors ();
 
  261         *std::min_element (index.begin (), index.end ()) < 0,
 
  262         std::invalid_argument,
 
  263         fnName << 
": All indices must be nonnegative.");
 
  265         static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
 
  266         std::invalid_argument,
 
  267         fnName << 
": All indices must be strictly less than the number of " 
  268         "columns " << numVecs << 
" in the input MultiVector mv.");
 
  269 #endif // HAVE_TPETRA_DEBUG 
  273       for (std::vector<int>::size_type 
j = 0; 
j < index.size (); ++
j) {
 
  274         columns[
j] = index[
j];
 
  290       const int numCols = 
static_cast<int> (mv.getNumVectors());
 
  291       const bool validRange = index.
size() > 0 &&
 
  294         std::ostringstream os;
 
  295         os << 
"Belos::MultiVecTraits::CloneView(mv, index=[" 
  298           os.str() << 
"Empty index range is not allowed.");
 
  300           os.str() << 
"Index range includes negative index/ices, which is not " 
  303           index.
ubound() >= numCols, std::invalid_argument,
 
  304           os.str() << 
"Index range exceeds number of vectors " << numCols
 
  305           << 
" in the input multivector.");
 
  307           os.str() << 
"Should never get here!");
 
  315       return static_cast<ptrdiff_t
> (mv.getGlobalLength ());
 
  319       return static_cast<int> (mv.getNumVectors ());
 
  323       return mv.isConstantStride ();
 
  328                      const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
A,
 
  331                      Tpetra::MultiVector<Scalar,LO,GO,Node>& 
C)
 
  337       const int numRowsB = B.
numRows ();
 
  338       const int numColsB = B.
numCols ();
 
  339       const int strideB  = B.
stride ();
 
  340       if (numRowsB == 1 && numColsB == 1) {
 
  341         C.update (alpha*B(0,0), A, beta);
 
  346       RCP<const MV> Atmp, Ctmp;
 
  348       else Atmp = 
rcp(&A,
false);
 
  351       else Ctmp = 
rcp(&C,
false);
 
  354       typedef Tpetra::MultiVector<dot_type,LO,GO,Node> FMV;
 
  355       typedef typename FMV::dual_view_type::t_dev flat_view_type;
 
  357       flat_view_type flat_A_view = Atmp->template getLocalView<execution_space>();
 
  358       flat_view_type flat_C_view = Ctmp->template getLocalView<execution_space>();
 
  361       typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, Kokkos::HostSpace> b_host_view_type;
 
  362       b_host_view_type B_view_host_input( B.
values(), strideB, numColsB);
 
  363       auto B_view_host = Kokkos::subview(B_view_host_input,
 
  364                                          Kokkos::pair<int,int>(0,numRowsB),
 
  365                                          Kokkos::pair<int,int>(0,numColsB));
 
  369       typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, execution_space> b_view_type;
 
  370       typedef Kokkos::View<dot_type*, Kokkos::LayoutLeft, execution_space> b_1d_view_type;
 
  371       b_1d_view_type B_1d_view_dev(Kokkos::ViewAllocateWithoutInitializing(
"B"), numRowsB*numColsB);
 
  372       b_view_type B_view_dev( B_1d_view_dev.data(), numRowsB, numColsB);
 
  377         const char ctransA = 
'N', ctransB = 
'N';
 
  380           alpha, flat_A_view, B_view_dev, beta, flat_C_view);
 
  383       if (C.isConstantStride() == 
false)
 
  396              const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
A,
 
  398              const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
B,
 
  399              Tpetra::MultiVector<Scalar,LO,GO,Node>& mv)
 
  405     MvScale (Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
 
  412     MvScale (Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
 
  413              const std::vector<BaseScalar>& alphas)
 
  415       std::vector<Scalar> alphas_mp(alphas.size());
 
  416       const size_t sz = alphas.size();
 
  417       for (
size_t i=0; i<sz; ++i)
 
  418         alphas_mp[i] = alphas[i];
 
  419       mv.scale (alphas_mp);
 
  423     MvScale (Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
 
  424              const std::vector<Scalar>& alphas)
 
  431                const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
A,
 
  432                const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
B,
 
  442       const int numRowsC = C.
numRows ();
 
  443       const int numColsC = C.
numCols ();
 
  444       const int strideC  = C.
stride ();
 
  445       if (numRowsC == 1 && numColsC == 1) {
 
  459       RCP<const MV> Atmp, Btmp;
 
  461       else Atmp = 
rcp(&A,
false);
 
  464       else Btmp = 
rcp(&B,
false);
 
  467       typedef Tpetra::MultiVector<dot_type,LO,GO,Node> FMV;
 
  468       typedef typename FMV::dual_view_type::t_dev flat_view_type;
 
  470       flat_view_type flat_A_view = Atmp->template getLocalView<execution_space>();
 
  471       flat_view_type flat_B_view = Btmp->template getLocalView<execution_space>();
 
  474       typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, Kokkos::HostSpace> c_host_view_type;
 
  475       c_host_view_type C_view_host_input( C.
values(), strideC, numColsC);
 
  476       auto C_view_host = Kokkos::subview(C_view_host_input, 
 
  477                                          Kokkos::pair<int,int>(0,numRowsC), 
 
  478                                          Kokkos::pair<int,int>(0,numColsC));
 
  482       typedef Kokkos::View<dot_type**, Kokkos::LayoutLeft, execution_space> c_view_type;
 
  483       typedef Kokkos::View<dot_type*, Kokkos::LayoutLeft, execution_space> c_1d_view_type;
 
  484       c_1d_view_type C_1d_view_dev(
"C", numRowsC*numColsC);
 
  485       c_view_type C_view_dev( C_1d_view_dev.data(), numRowsC, numColsC);
 
  489         const char ctransA = 
'C', ctransB = 
'N';
 
  492           alpha, flat_A_view, flat_B_view,
 
  493           Kokkos::Details::ArithTraits<dot_type>::zero(),
 
  498       RCP<const Comm<int> > pcomm = A.getMap()->getComm ();
 
  499       if (pcomm->getSize () == 1)
 
  502         typedef Kokkos::View<dot_type*, Kokkos::LayoutLeft, Kokkos::HostSpace> c_1d_host_view_type;
 
  503         c_1d_host_view_type C_1d_view_tmp(Kokkos::ViewAllocateWithoutInitializing(
"C_tmp"), strideC*numColsC);
 
  504         c_host_view_type C_view_tmp( C_1d_view_tmp.data(),
 
  507                                           Kokkos::pair<int,int>(0,numRowsC), 
 
  508                                           Kokkos::pair<int,int>(0,numColsC)) , 
 
  510         reduceAll<int> (*pcomm, REDUCE_SUM, strideC*numColsC,
 
  518     MvDot (
const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
A,
 
  519            const Tpetra::MultiVector<Scalar,LO,GO,Node>& 
B,
 
  520            std::vector<dot_type>& dots)
 
  522       const size_t numVecs = A.getNumVectors ();
 
  525         numVecs != B.getNumVectors (), std::invalid_argument,
 
  526         "Belos::MultiVecTraits<Scalar,Tpetra::MultiVector>::MvDot(A,B,dots): " 
  527         "A and B must have the same number of columns.  " 
  528         "A has " << numVecs << 
" column(s), " 
  529         "but B has " << B.getNumVectors () << 
" column(s).");
 
  530 #ifdef HAVE_TPETRA_DEBUG 
  532         dots.size() < numVecs, std::invalid_argument,
 
  533         "Belos::MultiVecTraits<Scalar,Tpetra::MultiVector>::MvDot(A,B,dots): " 
  534         "The output array 'dots' must have room for all dot products.  " 
  535         "A and B each have " << numVecs << 
" column(s), " 
  536         "but 'dots' only has " << dots.size() << 
" entry(/ies).");
 
  537 #endif // HAVE_TPETRA_DEBUG 
  540       A.dot (B, av (0, numVecs));
 
  545     MvNorm (
const Tpetra::MultiVector<Scalar,LO,GO,Node>& mv,
 
  546             std::vector<mag_type> &normvec,
 
  547             NormType type=TwoNorm)
 
  550 #ifdef HAVE_TPETRA_DEBUG 
  551       typedef std::vector<int>::size_type size_type;
 
  553         normvec.size () < 
static_cast<size_type
> (mv.getNumVectors ()),
 
  554         std::invalid_argument,
 
  555         "Belos::MultiVecTraits::MvNorm(mv,normvec): The normvec output " 
  556         "argument must have at least as many entries as the number of vectors " 
  557         "(columns) in the MultiVector mv.  normvec.size() = " << normvec.size ()
 
  558         << 
" < mv.getNumVectors() = " << mv.getNumVectors () << 
".");
 
  564         mv.norm1(av(0,mv.getNumVectors()));
 
  567         mv.norm2(av(0,mv.getNumVectors()));
 
  570         mv.normInf(av(0,mv.getNumVectors()));
 
  577           true, std::logic_error,
 
  578           "Belos::MultiVecTraits::MvNorm: Invalid NormType value " << type
 
  579           << 
".  Valid values are OneNorm=" << OneNorm << 
", TwoNorm=" 
  580           << TwoNorm <<
", and InfNorm=" << InfNorm << 
".  If you are a Belos " 
  581           "user and have not modified Belos in any way, and you get this " 
  582           "message, then this is probably a bug in the Belos solver you were " 
  583           "using.  Please report this to the Belos developers.");
 
  592       const size_t inNumVecs = A.getNumVectors ();
 
  593 #ifdef HAVE_TPETRA_DEBUG 
  595         inNumVecs < static_cast<size_t> (index.size ()), std::invalid_argument,
 
  596         "Belos::MultiVecTraits::SetBlock(A,index,mv): 'index' argument must " 
  597         "have no more entries as the number of columns in the input MultiVector" 
  598         " A.  A.getNumVectors() = " << inNumVecs << 
" < index.size () = " 
  599         << index.size () << 
".");
 
  600 #endif // HAVE_TPETRA_DEBUG 
  601       RCP<MV> mvsub = CloneViewNonConst (mv, index);
 
  602       if (inNumVecs > static_cast<size_t> (index.size ())) {
 
  603         RCP<const MV> Asub = A.subView (Range1D (0, index.size () - 1));
 
  620       const size_t maxInt =
 
  622       const bool overflow =
 
  623         maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
 
  625         std::ostringstream os;
 
  626         os << 
"Belos::MultiVecTraits::SetBlock(A, index=[" << index.
lbound ()
 
  627            << 
", " << index.
ubound () << 
"], mv): ";
 
  629           maxInt < A.getNumVectors (), std::range_error, os.str () << 
"Number " 
  630           "of columns (size_t) in the input MultiVector 'A' overflows int.");
 
  632           maxInt < mv.getNumVectors (), std::range_error, os.str () << 
"Number " 
  633           "of columns (size_t) in the output MultiVector 'mv' overflows int.");
 
  636       const int numColsA = 
static_cast<int> (A.getNumVectors ());
 
  637       const int numColsMv = 
static_cast<int> (mv.getNumVectors ());
 
  639       const bool validIndex =
 
  642       const bool validSource = index.
size () <= numColsA;
 
  644       if (! validIndex || ! validSource) {
 
  645         std::ostringstream os;
 
  646         os << 
"Belos::MultiVecTraits::SetBlock(A, index=[" << index.
lbound ()
 
  647            << 
", " << index.
ubound () << 
"], mv): ";
 
  649           index.
lbound() < 0, std::invalid_argument,
 
  650           os.str() << 
"Range lower bound must be nonnegative.");
 
  652           index.
ubound() >= numColsMv, std::invalid_argument,
 
  653           os.str() << 
"Range upper bound must be less than the number of " 
  654           "columns " << numColsA << 
" in the 'mv' output argument.");
 
  656           index.
size() > numColsA, std::invalid_argument,
 
  657           os.str() << 
"Range must have no more elements than the number of " 
  658           "columns " << numColsA << 
" in the 'A' input argument.");
 
  660           true, std::logic_error, 
"Should never get here!");
 
  667       if (index.
lbound () == 0 && index.
ubound () + 1 == numColsMv) {
 
  668         mv_view = Teuchos::rcpFromRef (mv); 
 
  670         mv_view = CloneViewNonConst (mv, index);
 
  677       if (index.
size () == numColsA) {
 
  678         A_view = Teuchos::rcpFromRef (A); 
 
  688       const char errPrefix[] = 
"Belos::MultiVecTraits::Assign(A, mv): ";
 
  697       const size_t maxInt =
 
  699       const bool overflow =
 
  700         maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
 
  703           maxInt < A.getNumVectors(), std::range_error,
 
  704           errPrefix << 
"Number of columns in the input multivector 'A' " 
  705           "(a size_t) overflows int.");
 
  707           maxInt < mv.getNumVectors(), std::range_error,
 
  708           errPrefix << 
"Number of columns in the output multivector 'mv' " 
  709           "(a size_t) overflows int.");
 
  711           true, std::logic_error, 
"Should never get here!");
 
  714       const int numColsA = 
static_cast<int> (A.getNumVectors ());
 
  715       const int numColsMv = 
static_cast<int> (mv.getNumVectors ());
 
  716       if (numColsA > numColsMv) {
 
  718           numColsA > numColsMv, std::invalid_argument,
 
  719           errPrefix << 
"Input multivector 'A' has " << numColsA << 
" columns, " 
  720           "but output multivector 'mv' has only " << numColsMv << 
" columns.");
 
  723       if (numColsA == numColsMv) {
 
  740       mv.putScalar (alpha);
 
  748 #ifdef HAVE_BELOS_TSQR 
  749     typedef Tpetra::TsqrAdaptor< Tpetra::MultiVector< Scalar, LO, GO, Node > > tsqr_adaptor_type;
 
  753 #endif // HAVE_BELOS_TSQR 
  763   template <
class Storage, 
class LO, 
class GO, 
class Node>
 
  765                         Tpetra::MultiVector<Sacado::MP::Vector<Storage>,
 
  767                         Tpetra::Operator<Sacado::MP::Vector<Storage>,
 
  773     Apply (
const Tpetra::Operator<Scalar,LO,GO,Node>& Op,
 
  774            const Tpetra::MultiVector<Scalar,LO,GO,Node>& X,
 
  775            Tpetra::MultiVector<Scalar,LO,GO,Node>& Y,
 
  776            ETrans trans=NOTRANS)
 
  793         const std::string otName = 
"Belos::OperatorTraits<" + scalarName
 
  794           + 
"," + loName + 
"," + goName + 
"," + nodeName + 
">";
 
  796                            "get here; fell through a switch statement.  " 
  797                            "Please report this bug to the Belos developers.");
 
  804       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 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)
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
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)
Sacado::MP::Vector< Storage > Scalar
static void MvRandom(MV &mv)
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