Stratimikos Version of the Day
Loading...
Searching...
No Matches
BelosThyraAdapter.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Stratimikos: Thyra-based strategies for linear solvers
4//
5// Copyright 2006 NTESS and the Stratimikos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
20#ifndef BELOS_THYRA_ADAPTER_HPP
21#define BELOS_THYRA_ADAPTER_HPP
22
23#include "Stratimikos_Config.h"
24#include "BelosConfigDefs.hpp"
27
28#include <Thyra_DetachedMultiVectorView.hpp>
29#include <Thyra_MultiVectorBase.hpp>
30#include <Thyra_MultiVectorStdOps.hpp>
31#ifdef HAVE_BELOS_TSQR
32# include <Thyra_TsqrAdaptor.hpp>
33#endif // HAVE_BELOS_TSQR
34
35#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
36#include "Thyra_TpetraThyraWrappers.hpp"
37#include "BelosMultiVecTraits_Tpetra.hpp"
38#include "Thyra_DefaultProductMultiVector.hpp"
39#include "Thyra_DefaultProductVectorSpace.hpp"
40#endif
41
42#ifdef HAVE_STRATIMIKOS_BELOS_TIMERS
43# include <Teuchos_TimeMonitor.hpp>
44
45# define STRATIMIKOS_TIME_MONITOR(NAME) \
46 Teuchos::TimeMonitor tM(*Teuchos::TimeMonitor::getNewTimer(std::string(NAME)))
47
48#else
49
50# define STRATIMIKOS_TIME_MONITOR(NAME)
51
52#endif
53
54namespace Belos {
55
57 //
58 // Implementation of the Belos::MultiVecTraits for Thyra::MultiVectorBase
59 //
61
68 template<class ScalarType>
69 class MultiVecTraits< ScalarType, Thyra::MultiVectorBase<ScalarType> >
70 {
71 private:
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>;
89
90 private:
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);
100 if (map.is_null())
101 break;
102 auto tp_mv = impl::getMultiVectorFromPool<ScalarType>(map, numvecs);
103 auto thy_mv = createMultiVector(tp_mv, vs);
104 multiVecs.push_back(thy_mv);
105 }
106 if (multiVecs.size() == numBlocks)
107 return Thyra::defaultProductMultiVector<ScalarType>(ps, multiVecs);
108 }
109 return Teuchos::null;
110 }
111#endif
112
113 public:
114
117
122 static Teuchos::RCP<TMVB> Clone( const TMVB& mv, const int numvecs )
123 {
124 Teuchos::RCP<TMVB> c;
125#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
126 auto mv_rcp = Teuchos::rcpFromRef(mv);
127 try {
128 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
129 auto X_copy = ::Belos::MultiVecTraits<ScalarType, TpMV>::Clone(*X, numvecs);
130 c = Thyra::createMultiVector(X_copy);
131 } catch (std::logic_error&)
132#endif
133 {
134#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
135 c = BuildProductMultiVectorMaybe(mv_rcp, numvecs);
136 if (c.is_null())
137#endif
138 {
139 c = Thyra::createMembers(mv.range(), numvecs);
140 }
141 }
142 return c;
143 }
144
149 static Teuchos::RCP<TMVB> CloneCopy( const TMVB& mv )
150 {
151 Teuchos::RCP< TMVB > cc;
152#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
153 auto mv_rcp = Teuchos::rcpFromRef(mv);
154 try {
155 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
157 cc = Thyra::createMultiVector(X_copy);
158 } catch (std::logic_error&)
159#endif
160 {
161 int numvecs = mv.domain()->dim();
162 // create the new multivector
163#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
164 cc = BuildProductMultiVectorMaybe(mv_rcp, numvecs);
165 if (cc.is_null())
166#endif
167 {
168 cc = Thyra::createMembers(mv.range(), numvecs);
169 }
170 // copy the data from the source multivector to the new multivector
171 Thyra::assign(cc.ptr(), mv);
172 }
173 return cc;
174 }
175
181 static Teuchos::RCP<TMVB> CloneCopy( const TMVB& mv, const std::vector<int>& index )
182 {
183 Teuchos::RCP<TMVB> cc;
184#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
185 auto mv_rcp = Teuchos::rcpFromRef(mv);
186 try {
187 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
189 cc = Thyra::createMultiVector(X_copy);
190 } catch (std::logic_error&)
191#endif
192 {
193 int numvecs = index.size();
194 // create the new multivector
195#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
196 cc = BuildProductMultiVectorMaybe(mv_rcp, numvecs);
197 if (cc.is_null())
198#endif
199 {
200 cc = Thyra::createMembers(mv.range(), numvecs);
201 }
202 // create a view to the relevant part of the source multivector
203 Teuchos::RCP<const TMVB> view = mv.subView(index);
204 // copy the data from the relevant view to the new multivector
205 Thyra::assign(cc.ptr(), *view);
206 }
207 return cc;
208 }
209
210 static Teuchos::RCP<TMVB>
211 CloneCopy (const TMVB& mv, const Teuchos::Range1D& index)
212 {
213 Teuchos::RCP<TMVB> cc;
214#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
215 auto mv_rcp = Teuchos::rcpFromRef(mv);
216 try {
217 Teuchos::RCP<const TpMV> X = Extraction::getConstTpetraMultiVector(mv_rcp);
219 cc = Thyra::createMultiVector(X_copy);
220 } catch (std::logic_error&)
221#endif
222 {
223 const int numVecs = index.size();
224 // Create the new multivector
225#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
226 cc = BuildProductMultiVectorMaybe(mv_rcp, numVecs);
227 if (cc.is_null())
228#endif
229 {
230 cc = Thyra::createMembers(mv.range(), numVecs);
231 }
232 // Create a view to the relevant part of the source multivector
233 Teuchos::RCP<const TMVB> view = mv.subView (index);
234 // Copy the data from the view to the new multivector.
235 Thyra::assign (cc.ptr(), *view);
236 }
237 return cc;
238 }
239
245 static Teuchos::RCP<TMVB> CloneViewNonConst( TMVB& mv, const std::vector<int>& index )
246 {
247 int numvecs = index.size();
248
249 // We do not assume that the indices are sorted, nor do we check that
250 // index.size() > 0. This code is fail-safe, in the sense that a zero
251 // length index std::vector will pass the error on the Thyra.
252
253 // Thyra has two ways to create an indexed View:
254 // * contiguous (via a range of columns)
255 // * indexed (via a std::vector of column indices)
256 // The former is significantly more efficient than the latter, in terms of
257 // computations performed with/against the created view.
258 // We will therefore check to see if the given indices are contiguous, and
259 // if so, we will use the contiguous view creation method.
260
261 int lb = index[0];
262 bool contig = true;
263 for (int i=0; i<numvecs; i++) {
264 if (lb+i != index[i]) contig = false;
265 }
266
267 Teuchos::RCP< TMVB > cc;
268 if (contig) {
269 const Thyra::Range1D rng(lb,lb+numvecs-1);
270 // create a contiguous view to the relevant part of the source multivector
271 cc = mv.subView(rng);
272 }
273 else {
274 // create an indexed view to the relevant part of the source multivector
275 cc = mv.subView(index);
276 }
277 return cc;
278 }
279
280 static Teuchos::RCP<TMVB>
281 CloneViewNonConst (TMVB& mv, const Teuchos::Range1D& index)
282 {
283 // We let Thyra be responsible for checking that the index range
284 // is nonempty.
285 //
286 // Create and return a contiguous view to the relevant part of
287 // the source multivector.
288 return mv.subView (index);
289 }
290
291
297 static Teuchos::RCP<const TMVB> CloneView( const TMVB& mv, const std::vector<int>& index )
298 {
299 int numvecs = index.size();
300
301 // We do not assume that the indices are sorted, nor do we check that
302 // index.size() > 0. This code is fail-safe, in the sense that a zero
303 // length index std::vector will pass the error on the Thyra.
304
305 // Thyra has two ways to create an indexed View:
306 // * contiguous (via a range of columns)
307 // * indexed (via a std::vector of column indices)
308 // The former is significantly more efficient than the latter, in terms of
309 // computations performed with/against the created view.
310 // We will therefore check to see if the given indices are contiguous, and
311 // if so, we will use the contiguous view creation method.
312
313 int lb = index[0];
314 bool contig = true;
315 for (int i=0; i<numvecs; i++) {
316 if (lb+i != index[i]) contig = false;
317 }
318
319 Teuchos::RCP< const TMVB > cc;
320 if (contig) {
321 const Thyra::Range1D rng(lb,lb+numvecs-1);
322 // create a contiguous view to the relevant part of the source multivector
323 cc = mv.subView(rng);
324 }
325 else {
326 // create an indexed view to the relevant part of the source multivector
327 cc = mv.subView(index);
328 }
329 return cc;
330 }
331
332 static Teuchos::RCP<const TMVB>
333 CloneView (const TMVB& mv, const Teuchos::Range1D& index)
334 {
335 // We let Thyra be responsible for checking that the index range
336 // is nonempty.
337 //
338 // Create and return a contiguous view to the relevant part of
339 // the source multivector.
340 return mv.subView (index);
341 }
342
344
347
349 static ptrdiff_t GetGlobalLength( const TMVB& mv ) {
350 return Teuchos::as<ptrdiff_t>(mv.range()->dim());
351 }
352
354 static int GetNumberVecs( const TMVB& mv )
355 { return mv.domain()->dim(); }
356
358
361
364 static void MvTimesMatAddMv( const ScalarType alpha, const TMVB& A,
365 const DM& B,
366 const ScalarType beta, TMVB& mv )
367 {
368 using Teuchos::arrayView; using Teuchos::arcpFromArrayView;
369 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvTimesMatAddMv");
370
371#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
372 auto A_rcp = Teuchos::rcpFromRef(A);
373 auto mv_rcp = Teuchos::rcpFromRef(mv);
374 try {
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);
378 return;
379 } catch (std::logic_error&)
380#endif
381 {
382 const int m = DMT::GetNumRows(B);
383 const int n = DMT::GetNumCols(B);
384 // Check if B is 1-by-1, in which case we can just call MvAddMv()
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));
390 } else {
391 // perform the operation via A: mv <- alpha*A*B_thyra + beta*mv
392 auto vs = A.domain();
393 auto B_ptr = DMT::GetConstRawHostPtr(B);
394 auto stride = DMT::GetStride(B);
395 // Create a view of the B object!
396 Teuchos::RCP< const TMVB >
397 B_thyra = vs->createCachedMembersView(
399 0, m, 0, n,
400 arcpFromArrayView(arrayView(B_ptr, stride*n)), stride
401 )
402 );
403 Thyra::apply<ScalarType>(A, Thyra::NOTRANS, *B_thyra, Teuchos::outArg(mv), alpha, beta);
404 }
405 }
406 }
407
410 static void MvAddMv( const ScalarType alpha, const TMVB& A,
411 const ScalarType beta, const TMVB& B, TMVB& mv )
412 {
413 using Teuchos::tuple; using Teuchos::ptrInArg; using Teuchos::inoutArg;
414 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvAddMv");
415
416 Thyra::linear_combination<ScalarType>(
417 tuple(alpha, beta)(), tuple(ptrInArg(A), ptrInArg(B))(), Teuchos::ScalarTraits<ScalarType>::zero(), inoutArg(mv));
418 }
419
422 static void MvScale ( TMVB& mv, const ScalarType alpha )
423 {
424 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvScale");
425
426 Thyra::scale(alpha, Teuchos::inoutArg(mv));
427 }
428
431 static void MvScale (TMVB& mv, const std::vector<ScalarType>& alpha)
432 {
433 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvScale");
434
435 for (unsigned int i=0; i<alpha.size(); i++) {
436 Thyra::scale<ScalarType> (alpha[i], mv.col(i).ptr());
437 }
438 }
439
442 static void MvTransMv( const ScalarType alpha, const TMVB& A, const TMVB& mv,
443 DM& B )
444 {
445 using Teuchos::arrayView; using Teuchos::arcpFromArrayView;
446 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvTransMv");
447
448#if defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS) && defined(HAVE_BELOS_TPETRA)
449 auto A_rcp = Teuchos::rcpFromRef(A);
450 auto mv_rcp = Teuchos::rcpFromRef(mv);
451 try {
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);
455 return;
456 } catch (std::logic_error&)
457#endif
458 {
459 // Create a multivector to hold the result (m by n)
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);
466 // Create a view of the B object!
467 Teuchos::RCP< TMVB >
468 B_thyra = vs->createCachedMembersView(
470 0, m, 0, n,
471 arcpFromArrayView(arrayView(B_ptr, stride*B_cols)), stride
472 ),
473 false
474 );
475 Thyra::apply<ScalarType>(A, Thyra::CONJTRANS, mv, B_thyra.ptr(), alpha);
476 }
477 }
478
482 static void MvDot( const TMVB& mv, const TMVB& A, std::vector<ScalarType>& b )
483 {
484 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvDot");
485
486 Thyra::dots(mv, A, Teuchos::arrayViewFromVector(b));
487 }
488
490
493
497 static void MvNorm( const TMVB& mv, std::vector<magType>& normvec,
498 NormType type = TwoNorm ) {
499 STRATIMIKOS_TIME_MONITOR("Belos::MVT::MvNorm");
500
501 if(type == TwoNorm)
502 Thyra::norms_2(mv, Teuchos::arrayViewFromVector(normvec));
503 else if(type == OneNorm)
504 Thyra::norms_1(mv, Teuchos::arrayViewFromVector(normvec));
505 else if(type == InfNorm)
506 Thyra::norms_inf(mv, Teuchos::arrayViewFromVector(normvec));
507 else
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");
511 }
512
514
517
520 static void SetBlock( const TMVB& A, const std::vector<int>& index, TMVB& mv )
521 {
522 // Extract the "numvecs" columns of mv indicated by the index std::vector.
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++) {
527 indexA[i] = i;
528 }
529 // Thyra::assign requires that both arguments have the same number of
530 // vectors. Enforce this, by shrinking one to match the other.
531 if ( numAcols < numvecs ) {
532 // A does not have enough columns to satisfy index_plus. Shrink
533 // index_plus.
534 numvecs = numAcols;
535 }
536 else if ( numAcols > numvecs ) {
537 numAcols = numvecs;
538 indexA.resize( numAcols );
539 }
540 // create a view to the relevant part of the source multivector
541 Teuchos::RCP< const TMVB > relsource = A.subView(indexA);
542 // create a view to the relevant part of the destination multivector
543 Teuchos::RCP< TMVB > reldest = mv.subView(index);
544 // copy the data to the destination multivector subview
545 Thyra::assign(reldest.ptr(), *relsource);
546 }
547
548 static void
549 SetBlock (const TMVB& A, const Teuchos::Range1D& index, TMVB& mv)
550 {
551 const int numColsA = A.domain()->dim();
552 const int numColsMv = mv.domain()->dim();
553 // 'index' indexes into mv; it's the index set of the target.
554 const bool validIndex = index.lbound() >= 0 && index.ubound() < numColsMv;
555 // We can't take more columns out of A than A has.
556 const bool validSource = index.size() <= numColsA;
557
558 if (! validIndex || ! validSource)
559 {
560 std::ostringstream os;
561 os << "Belos::MultiVecTraits<Scalar, Thyra::MultiVectorBase<Scalar> "
562 ">::SetBlock(A, [" << index.lbound() << ", " << index.ubound()
563 << "], mv): ";
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!");
575 }
576
577 // View of the relevant column(s) of the target multivector mv.
578 // We avoid view creation overhead by only creating a view if
579 // the index range is different than [0, (# columns in mv) - 1].
580 Teuchos::RCP<TMVB> mv_view;
581 if (index.lbound() == 0 && index.ubound()+1 == numColsMv)
582 mv_view = Teuchos::rcpFromRef (mv); // Non-const, non-owning RCP
583 else
584 mv_view = mv.subView (index);
585
586 // View of the relevant column(s) of the source multivector A.
587 // If A has fewer columns than mv_view, then create a view of
588 // the first index.size() columns of A.
589 Teuchos::RCP<const TMVB> A_view;
590 if (index.size() == numColsA)
591 A_view = Teuchos::rcpFromRef (A); // Const, non-owning RCP
592 else
593 A_view = A.subView (Teuchos::Range1D(0, index.size()-1));
594
595 // Copy the data to the destination multivector.
596 Thyra::assign(mv_view.ptr(), *A_view);
597 }
598
599 static void
600 Assign (const TMVB& A, TMVB& mv)
601 {
602 STRATIMIKOS_TIME_MONITOR("Belos::MVT::Assign");
603
604 const int numColsA = A.domain()->dim();
605 const int numColsMv = mv.domain()->dim();
606 if (numColsA > numColsMv)
607 {
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!");
616 }
617 // Copy the data to the destination multivector.
618 if (numColsA == numColsMv) {
619 Thyra::assign (Teuchos::outArg (mv), A);
620 } else {
621 Teuchos::RCP<TMVB> mv_view =
622 CloneViewNonConst (mv, Teuchos::Range1D(0, numColsA-1));
623 Thyra::assign (mv_view.ptr(), A);
624 }
625 }
626
629 static void MvRandom( TMVB& mv )
630 {
631 // Thyra::randomize generates via a uniform distribution on [l,u]
632 // We will use this to generate on [-1,1]
633 Thyra::randomize<ScalarType>(
634 -Teuchos::ScalarTraits<ScalarType>::one(),
635 Teuchos::ScalarTraits<ScalarType>::one(),
636 Teuchos::outArg(mv));
637 }
638
640 static void
641 MvInit (TMVB& mv, ScalarType alpha = Teuchos::ScalarTraits<ScalarType>::zero())
642 {
643 Thyra::assign (Teuchos::outArg (mv), alpha);
644 }
645
647
650
653 static void MvPrint( const TMVB& mv, std::ostream& os )
654 { os << describe(mv,Teuchos::VERB_EXTREME); }
655
657
658#ifdef HAVE_BELOS_TSQR
664 typedef Thyra::TsqrAdaptor< ScalarType > tsqr_adaptor_type;
665#endif // HAVE_BELOS_TSQR
666 };
667
669 //
670 // Implementation of the Belos::OperatorTraits for Thyra::LinearOpBase
671 //
673
681 template<class ScalarType>
682 class OperatorTraits <ScalarType,
683 Thyra::MultiVectorBase<ScalarType>,
684 Thyra::LinearOpBase<ScalarType> >
685 {
686 private:
687 typedef Thyra::MultiVectorBase<ScalarType> TMVB;
688 typedef Thyra::LinearOpBase<ScalarType> TLOB;
689
690 public:
706 static void
707 Apply (const TLOB& Op,
708 const TMVB& x,
709 TMVB& y,
710 ETrans trans = NOTRANS)
711 {
712 Thyra::EOpTransp whichOp;
713
714 // We don't check here whether the operator implements the
715 // requested operation. Call HasApplyTranspose() to check.
716 // Thyra::LinearOpBase implementations are not required to
717 // implement NOTRANS. However, Belos needs NOTRANS
718 // (obviously!), so we assume that Op implements NOTRANS.
719 if (trans == NOTRANS)
720 whichOp = Thyra::NOTRANS;
721 else if (trans == TRANS)
722 whichOp = Thyra::TRANS;
723 else if (trans == CONJTRANS)
724 whichOp = Thyra::CONJTRANS;
725 else
726 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
727 "Belos::OperatorTraits::Apply (Thyra specialization): "
728 "'trans' argument must be neither NOTRANS=" << NOTRANS
729 << ", TRANS=" << TRANS << ", or CONJTRANS=" << CONJTRANS
730 << ", but instead has an invalid value of " << trans << ".");
731 Thyra::apply<ScalarType>(Op, whichOp, x, Teuchos::outArg(y));
732 }
733
735 static bool HasApplyTranspose (const TLOB& Op)
736 {
737 typedef Teuchos::ScalarTraits<ScalarType> STS;
738
739 // Thyra::LinearOpBase's interface lets you check whether the
740 // operator implements any of all four possible combinations of
741 // conjugation and transpose. Belos only needs transpose
742 // (TRANS) if the operator is real; in that case, Apply() does
743 // the same thing with trans = CONJTRANS or TRANS. If the
744 // operator is complex, Belos needs both transpose and conjugate
745 // transpose (CONJTRANS) if the operator is complex.
746 return Op.opSupported (Thyra::TRANS) &&
747 (! STS::isComplex || Op.opSupported (Thyra::CONJTRANS));
748 }
749 };
750
751} // end of Belos namespace
752
753#endif
754// end of file BELOS_THYRA_ADAPTER_HPP
static void MvPrint(const TMVB &mv, std::ostream &os)
Print the mv multi-std::vector to the os output stream.
static void MvTransMv(const ScalarType alpha, const TMVB &A, const TMVB &mv, DM &B)
Compute a dense matrix B through the matrix-matrix multiply .
static void SetBlock(const TMVB &A, const std::vector< int > &index, TMVB &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index.
static void MvAddMv(const ScalarType alpha, const TMVB &A, const ScalarType beta, const TMVB &B, TMVB &mv)
Replace mv with .
static int GetNumberVecs(const TMVB &mv)
Obtain the number of vectors in mv.
static Teuchos::RCP< TMVB > CloneCopy(const TMVB &mv)
Creates a new MultiVectorBase and copies contents of mv into the new std::vector (deep copy).
static ptrdiff_t GetGlobalLength(const TMVB &mv)
Obtain the std::vector length of mv.
static void MvDot(const TMVB &mv, const TMVB &A, std::vector< ScalarType > &b)
Compute a std::vector b where the components are the individual dot-products of the i-th columns of A...
static Teuchos::RCP< TMVB > CloneCopy(const TMVB &mv, const std::vector< int > &index)
Creates a new MultiVectorBase and copies the selected contents of mv into the new std::vector (deep c...
static Teuchos::RCP< TMVB > CloneViewNonConst(TMVB &mv, const std::vector< int > &index)
Creates a new MultiVectorBase that shares the selected contents of mv (shallow copy).
static Teuchos::RCP< TMVB > Clone(const TMVB &mv, const int numvecs)
Creates a new empty MultiVectorBase containing numvecs columns.
static Teuchos::RCP< const TMVB > CloneView(const TMVB &mv, const std::vector< int > &index)
Creates a new const MultiVectorBase that shares the selected contents of mv (shallow copy).
static void MvScale(TMVB &mv, const ScalarType alpha)
Scale each element of the vectors in *this with alpha.
static void MvScale(TMVB &mv, const std::vector< ScalarType > &alpha)
Scale each element of the i-th vector in *this with alpha[i].
static void MvRandom(TMVB &mv)
Replace the vectors in mv with random vectors.
static void MvTimesMatAddMv(const ScalarType alpha, const TMVB &A, const DM &B, const ScalarType beta, TMVB &mv)
Update mv with .
static void MvNorm(const TMVB &mv, std::vector< magType > &normvec, NormType type=TwoNorm)
Compute the 2-norm of each individual std::vector of mv. Upon return, normvec[i] holds the value of ,...
static void MvInit(TMVB &mv, ScalarType alpha=Teuchos::ScalarTraits< ScalarType >::zero())
Replace each element of the vectors in mv with alpha.
static Teuchos::RCP< MV > CloneCopy(const MV &mv)
static Teuchos::RCP< MV > Clone(const MV &mv, const int numvecs)
static void Assign(const MV &A, MV &mv)
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
static bool HasApplyTranspose(const TLOB &Op)
Whether the operator implements applying the transpose.
static void Apply(const TLOB &Op, const TMVB &x, TMVB &y, ETrans trans=NOTRANS)
Apply Op to x, storing the result in y.
Stub adaptor from Thyra::MultiVectorBase to TSQR.
Teuchos::SerialDenseMatrix< Ordinal, Scalar > DefaultDenseMatrix

Generated for Stratimikos by doxygen 1.9.8