72 typedef Thyra::MultiVectorBase<ScalarType> TMVB;
73 typedef Teuchos::ScalarTraits<ScalarType> ST;
74 typedef typename ST::magnitudeType magType;
77#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
78 using TpMap = Tpetra::Map<Tpetra::MultiVector<>::local_ordinal_type,
79 Tpetra::MultiVector<>::global_ordinal_type,
80 Tpetra::MultiVector<>::node_type>;
81 using TpMV = Tpetra::MultiVector<ScalarType, Tpetra::MultiVector<>::local_ordinal_type,
82 Tpetra::MultiVector<>::global_ordinal_type,
83 Tpetra::MultiVector<>::node_type>;
84 using Extraction = Thyra::TpetraOperatorVectorExtraction<ScalarType,
85 Tpetra::MultiVector<>::local_ordinal_type,
86 Tpetra::MultiVector<>::global_ordinal_type,
87 Tpetra::MultiVector<>::node_type>;
91 static Teuchos::RCP<TMVB> BuildProductMultiVectorMaybe(Teuchos::RCP<const TMVB> &mv_rcp,
const int numvecs) {
92 auto pmv_rcp = Teuchos::rcp_dynamic_cast<const Thyra::DefaultProductMultiVector<ScalarType>>(mv_rcp);
93 if (!pmv_rcp.is_null()) {
94 auto ps = Teuchos::rcp_dynamic_cast<const Thyra::DefaultProductVectorSpace<ScalarType>>(pmv_rcp->range());
95 const int numBlocks = ps->numBlocks();
96 Teuchos::Array<Teuchos::RCP<Thyra::MultiVectorBase<ScalarType>>> multiVecs;
97 for (
int k = 0; k < numBlocks; ++k) {
98 auto vs = ps->getBlock(k);
99 Teuchos::RCP<const TpMap> map = Extraction::getTpetraMap(vs);
102 auto tp_mv = impl::getMultiVectorFromPool<ScalarType>(map, numvecs);
103 auto thy_mv = createMultiVector(tp_mv, vs);
104 multiVecs.push_back(thy_mv);
106 if (multiVecs.size() == numBlocks)
107 return Thyra::defaultProductMultiVector<ScalarType>(ps, multiVecs);
109 return Teuchos::null;
122 static Teuchos::RCP<TMVB>
Clone(
const TMVB& mv,
const int numvecs )
124 Teuchos::RCP<TMVB> c;
125#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
126 auto mv_rcp = Teuchos::rcpFromRef(mv);
128 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
130 c = Thyra::createMultiVector(X_copy);
131 }
catch (std::logic_error&)
134#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
135 c = BuildProductMultiVectorMaybe(mv_rcp, numvecs);
139 c = Thyra::createMembers(mv.range(), numvecs);
151 Teuchos::RCP< TMVB > cc;
152#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
153 auto mv_rcp = Teuchos::rcpFromRef(mv);
155 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
157 cc = Thyra::createMultiVector(X_copy);
158 }
catch (std::logic_error&)
161 int numvecs = mv.domain()->dim();
163#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
164 cc = BuildProductMultiVectorMaybe(mv_rcp, numvecs);
168 cc = Thyra::createMembers(mv.range(), numvecs);
171 Thyra::assign(cc.ptr(), mv);
181 static Teuchos::RCP<TMVB>
CloneCopy(
const TMVB& mv,
const std::vector<int>& index )
183 Teuchos::RCP<TMVB> cc;
184#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
185 auto mv_rcp = Teuchos::rcpFromRef(mv);
187 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
189 cc = Thyra::createMultiVector(X_copy);
190 }
catch (std::logic_error&)
193 int numvecs = index.size();
195#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
196 cc = BuildProductMultiVectorMaybe(mv_rcp, numvecs);
200 cc = Thyra::createMembers(mv.range(), numvecs);
203 Teuchos::RCP<const TMVB> view = mv.subView(index);
205 Thyra::assign(cc.ptr(), *view);
210 static Teuchos::RCP<TMVB>
211 CloneCopy (
const TMVB& mv,
const Teuchos::Range1D& index)
213 Teuchos::RCP<TMVB> cc;
214#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
215 auto mv_rcp = Teuchos::rcpFromRef(mv);
217 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
219 cc = Thyra::createMultiVector(X_copy);
220 }
catch (std::logic_error&)
223 const int numVecs = index.size();
225#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
226 cc = BuildProductMultiVectorMaybe(mv_rcp, numVecs);
230 cc = Thyra::createMembers(mv.range(), numVecs);
233 Teuchos::RCP<const TMVB> view = mv.subView (index);
235 Thyra::assign (cc.ptr(), *view);
247 int numvecs = index.size();
263 for (
int i=0; i<numvecs; i++) {
264 if (lb+i != index[i]) contig =
false;
267 Teuchos::RCP< TMVB > cc;
269 const Thyra::Range1D rng(lb,lb+numvecs-1);
271 cc = mv.subView(rng);
275 cc = mv.subView(index);
280 static Teuchos::RCP<TMVB>
288 return mv.subView (index);
297 static Teuchos::RCP<const TMVB>
CloneView(
const TMVB& mv,
const std::vector<int>& index )
299 int numvecs = index.size();
315 for (
int i=0; i<numvecs; i++) {
316 if (lb+i != index[i]) contig =
false;
319 Teuchos::RCP< const TMVB > cc;
321 const Thyra::Range1D rng(lb,lb+numvecs-1);
323 cc = mv.subView(rng);
327 cc = mv.subView(index);
332 static Teuchos::RCP<const TMVB>
333 CloneView (
const TMVB& mv,
const Teuchos::Range1D& index)
340 return mv.subView (index);
350 return Teuchos::as<ptrdiff_t>(mv.range()->dim());
355 {
return mv.domain()->dim(); }
366 const ScalarType beta, TMVB& mv )
368 using Teuchos::arrayView;
using Teuchos::arcpFromArrayView;
369 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvTimesMatAddMv");
371#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
372 auto A_rcp = Teuchos::rcpFromRef(A);
373 auto mv_rcp = Teuchos::rcpFromRef(mv);
375 Teuchos::RCP<const TpMV> A_tp = Extraction::getConstTpetraMultiVector(A_rcp);
376 Teuchos::RCP<TpMV> mv_tp = Extraction::getTpetraMultiVector(mv_rcp);
377 TpMVT::MvTimesMatAddMv(alpha, *A_tp, B, beta, *mv_tp);
379 }
catch (std::logic_error&)
382 const int m = DMT::GetNumRows(B);
383 const int n = DMT::GetNumCols(B);
385 if ((m == 1) && (n == 1)) {
386 using Teuchos::tuple;
using Teuchos::ptrInArg;
using Teuchos::inoutArg;
387 auto B_ptr = DMT::GetConstRawHostPtr(B);
388 const ScalarType alphaNew = alpha * (*B_ptr);
389 Thyra::linear_combination<ScalarType>(tuple(alphaNew)(), tuple(ptrInArg(A))(), beta, inoutArg(mv));
392 auto vs = A.domain();
393 auto B_ptr = DMT::GetConstRawHostPtr(B);
394 auto stride = DMT::GetStride(B);
396 Teuchos::RCP< const TMVB >
397 B_thyra = vs->createCachedMembersView(
400 arcpFromArrayView(arrayView(B_ptr, stride*n)), stride
403 Thyra::apply<ScalarType>(A, Thyra::NOTRANS, *B_thyra, Teuchos::outArg(mv), alpha, beta);
410 static void MvAddMv(
const ScalarType alpha,
const TMVB& A,
411 const ScalarType beta,
const TMVB& B, TMVB& mv )
413 using Teuchos::tuple;
using Teuchos::ptrInArg;
using Teuchos::inoutArg;
414 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvAddMv");
416 Thyra::linear_combination<ScalarType>(
417 tuple(alpha, beta)(), tuple(ptrInArg(A), ptrInArg(B))(), Teuchos::ScalarTraits<ScalarType>::zero(), inoutArg(mv));
422 static void MvScale ( TMVB& mv,
const ScalarType alpha )
424 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvScale");
426 Thyra::scale(alpha, Teuchos::inoutArg(mv));
431 static void MvScale (TMVB& mv,
const std::vector<ScalarType>& alpha)
433 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvScale");
435 for (
unsigned int i=0; i<alpha.size(); i++) {
436 Thyra::scale<ScalarType> (alpha[i], mv.col(i).ptr());
442 static void MvTransMv(
const ScalarType alpha,
const TMVB& A,
const TMVB& mv,
445 using Teuchos::arrayView;
using Teuchos::arcpFromArrayView;
446 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvTransMv");
448#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
449 auto A_rcp = Teuchos::rcpFromRef(A);
450 auto mv_rcp = Teuchos::rcpFromRef(mv);
452 Teuchos::RCP<const TpMV> A_tp = Extraction::getConstTpetraMultiVector(A_rcp);
453 Teuchos::RCP<const TpMV> mv_tp = Extraction::getConstTpetraMultiVector(mv_rcp);
454 TpMVT::MvTransMv(alpha, *A_tp, *mv_tp, B);
456 }
catch (std::logic_error&)
460 int m = A.domain()->dim();
461 int n = mv.domain()->dim();
462 auto vs = A.domain();
463 auto stride = DMT::GetStride(B);
464 auto B_cols = DMT::GetNumCols(B);
465 auto B_ptr = DMT::GetRawHostPtr(B);
468 B_thyra = vs->createCachedMembersView(
471 arcpFromArrayView(arrayView(B_ptr, stride*B_cols)), stride
475 Thyra::apply<ScalarType>(A, Thyra::CONJTRANS, mv, B_thyra.ptr(), alpha);
482 static void MvDot(
const TMVB& mv,
const TMVB& A, std::vector<ScalarType>& b )
484 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvDot");
486 Thyra::dots(mv, A, Teuchos::arrayViewFromVector(b));
497 static void MvNorm(
const TMVB& mv, std::vector<magType>& normvec,
499 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::MvNorm");
502 Thyra::norms_2(mv, Teuchos::arrayViewFromVector(normvec));
504 Thyra::norms_1(mv, Teuchos::arrayViewFromVector(normvec));
506 Thyra::norms_inf(mv, Teuchos::arrayViewFromVector(normvec));
508 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
509 "Belos::MultiVecTraits::MvNorm (Thyra specialization): "
510 "invalid norm type. Must be either TwoNorm, OneNorm or InfNorm");
520 static void SetBlock(
const TMVB& A,
const std::vector<int>& index, TMVB& mv )
523 int numvecs = index.size();
524 std::vector<int> indexA(numvecs);
525 int numAcols = A.domain()->dim();
526 for (
int i=0; i<numvecs; i++) {
531 if ( numAcols < numvecs ) {
536 else if ( numAcols > numvecs ) {
538 indexA.resize( numAcols );
541 Teuchos::RCP< const TMVB > relsource = A.subView(indexA);
543 Teuchos::RCP< TMVB > reldest = mv.subView(index);
545 Thyra::assign(reldest.ptr(), *relsource);
549 SetBlock (
const TMVB& A,
const Teuchos::Range1D& index, TMVB& mv)
551 const int numColsA = A.domain()->dim();
552 const int numColsMv = mv.domain()->dim();
554 const bool validIndex = index.lbound() >= 0 && index.ubound() < numColsMv;
556 const bool validSource = index.size() <= numColsA;
558 if (! validIndex || ! validSource)
560 std::ostringstream os;
561 os <<
"Belos::MultiVecTraits<Scalar, Thyra::MultiVectorBase<Scalar> "
562 ">::SetBlock(A, [" << index.lbound() <<
", " << index.ubound()
564 TEUCHOS_TEST_FOR_EXCEPTION(index.lbound() < 0, std::invalid_argument,
565 os.str() <<
"Range lower bound must be nonnegative.");
566 TEUCHOS_TEST_FOR_EXCEPTION(index.ubound() >= numColsMv, std::invalid_argument,
567 os.str() <<
"Range upper bound must be less than "
568 "the number of columns " << numColsA <<
" in the "
569 "'mv' output argument.");
570 TEUCHOS_TEST_FOR_EXCEPTION(index.size() > numColsA, std::invalid_argument,
571 os.str() <<
"Range must have no more elements than"
572 " the number of columns " << numColsA <<
" in the "
573 "'A' input argument.");
574 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Should never get here!");
580 Teuchos::RCP<TMVB> mv_view;
581 if (index.lbound() == 0 && index.ubound()+1 == numColsMv)
582 mv_view = Teuchos::rcpFromRef (mv);
584 mv_view = mv.subView (index);
589 Teuchos::RCP<const TMVB> A_view;
590 if (index.size() == numColsA)
591 A_view = Teuchos::rcpFromRef (A);
593 A_view = A.subView (Teuchos::Range1D(0, index.size()-1));
596 Thyra::assign(mv_view.ptr(), *A_view);
600 Assign (
const TMVB& A, TMVB& mv)
602 STRATIMIKOS_TIME_MONITOR(
"Belos::MVT::Assign");
604 const int numColsA = A.domain()->dim();
605 const int numColsMv = mv.domain()->dim();
606 if (numColsA > numColsMv)
608 std::ostringstream os;
609 os <<
"Belos::MultiVecTraits<Scalar, Thyra::MultiVectorBase<Scalar>"
610 " >::Assign(A, mv): ";
611 TEUCHOS_TEST_FOR_EXCEPTION(numColsA > numColsMv, std::invalid_argument,
612 os.str() <<
"Input multivector 'A' has "
613 << numColsA <<
" columns, but output multivector "
614 "'mv' has only " << numColsMv <<
" columns.");
615 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Should never get here!");
618 if (numColsA == numColsMv) {
619 Thyra::assign (Teuchos::outArg (mv), A);
621 Teuchos::RCP<TMVB> mv_view =
623 Thyra::assign (mv_view.ptr(), A);
633 Thyra::randomize<ScalarType>(
634 -Teuchos::ScalarTraits<ScalarType>::one(),
635 Teuchos::ScalarTraits<ScalarType>::one(),
636 Teuchos::outArg(mv));
641 MvInit (TMVB& mv, ScalarType alpha = Teuchos::ScalarTraits<ScalarType>::zero())
643 Thyra::assign (Teuchos::outArg (mv), alpha);
653 static void MvPrint(
const TMVB& mv, std::ostream& os )
654 { os << describe(mv,Teuchos::VERB_EXTREME); }
658#ifdef HAVE_BELOS_TSQR