42 #ifndef ANASAZI_TPETRA_ADAPTER_HPP 43 #define ANASAZI_TPETRA_ADAPTER_HPP 82 #include <Tpetra_MultiVector.hpp> 83 #include <Tpetra_Operator.hpp> 85 #include <Teuchos_Array.hpp> 86 #include <Teuchos_Assert.hpp> 87 #include <Teuchos_DefaultSerialComm.hpp> 88 #include <Teuchos_ScalarTraits.hpp> 95 #ifdef HAVE_ANASAZI_TSQR 96 # include <Tpetra_TsqrAdaptor.hpp> 97 #endif // HAVE_ANASAZI_TSQR 113 template<
class Scalar,
class LO,
class GO,
class Node>
115 typedef Tpetra::MultiVector<Scalar, LO, GO, Node> MV;
122 static Teuchos::RCP<MV>
Clone (
const MV& X,
const int numVecs) {
123 Teuchos::RCP<MV> Y (
new MV (X.getMap (), numVecs,
false));
124 Y->setCopyOrView (Teuchos::View);
134 Teuchos::RCP<MV> X_copy (
new MV (X, Teuchos::Copy));
141 X_copy->setCopyOrView (Teuchos::View);
156 static Teuchos::RCP<MV>
159 #ifdef HAVE_TPETRA_DEBUG 160 const char fnName[] =
"Anasazi::MultiVecTraits::CloneCopy(mv,index)";
161 const size_t inNumVecs = mv.getNumVectors ();
162 TEUCHOS_TEST_FOR_EXCEPTION(
163 index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
164 std::runtime_error, fnName <<
": All indices must be nonnegative.");
165 TEUCHOS_TEST_FOR_EXCEPTION(
167 static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= inNumVecs,
169 fnName <<
": All indices must be strictly less than the number of " 170 "columns " << inNumVecs <<
" of the input multivector mv.");
171 #endif // HAVE_TPETRA_DEBUG 174 Teuchos::Array<size_t> columns (index.size ());
175 for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
176 columns[j] = index[j];
181 Teuchos::RCP<MV> X_copy = mv.subCopy (columns ());
182 X_copy->setCopyOrView (Teuchos::View);
192 static Teuchos::RCP<MV>
195 const bool validRange = index.size() > 0 &&
196 index.lbound() >= 0 &&
199 std::ostringstream os;
200 os <<
"Anasazi::MultiVecTraits::CloneCopy(mv,index=[" 201 << index.lbound() <<
"," << index.ubound() <<
"]): ";
202 TEUCHOS_TEST_FOR_EXCEPTION(
203 index.size() == 0, std::invalid_argument,
204 os.str() <<
"Empty index range is not allowed.");
205 TEUCHOS_TEST_FOR_EXCEPTION(
206 index.lbound() < 0, std::invalid_argument,
207 os.str() <<
"Index range includes negative index/ices, which is not " 209 TEUCHOS_TEST_FOR_EXCEPTION(
211 os.str() <<
"Index range exceeds number of vectors " 212 << mv.getNumVectors() <<
" in the input multivector.");
213 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
214 os.str() <<
"Should never get here!");
216 Teuchos::RCP<MV> X_copy = mv.subCopy (index);
217 X_copy->setCopyOrView (Teuchos::View);
221 static Teuchos::RCP<MV>
224 #ifdef HAVE_TPETRA_DEBUG 225 const char fnName[] =
"Anasazi::MultiVecTraits::CloneViewNonConst(mv,index)";
226 const size_t numVecs = mv.getNumVectors ();
227 TEUCHOS_TEST_FOR_EXCEPTION(
228 index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
229 std::invalid_argument,
230 fnName <<
": All indices must be nonnegative.");
231 TEUCHOS_TEST_FOR_EXCEPTION(
233 static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
234 std::invalid_argument,
235 fnName <<
": All indices must be strictly less than the number of " 236 "columns " << numVecs <<
" in the input MultiVector mv.");
237 #endif // HAVE_TPETRA_DEBUG 240 Teuchos::Array<size_t> columns (index.size ());
241 for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
242 columns[j] = index[j];
247 Teuchos::RCP<MV> X_view = mv.subViewNonConst (columns ());
248 X_view->setCopyOrView (Teuchos::View);
252 static Teuchos::RCP<MV>
258 const int numCols =
static_cast<int> (mv.getNumVectors());
259 const bool validRange = index.size() > 0 &&
260 index.lbound() >= 0 && index.ubound() < numCols;
262 std::ostringstream os;
263 os <<
"Belos::MultiVecTraits::CloneViewNonConst(mv,index=[" 264 << index.lbound() <<
", " << index.ubound() <<
"]): ";
265 TEUCHOS_TEST_FOR_EXCEPTION(
266 index.size() == 0, std::invalid_argument,
267 os.str() <<
"Empty index range is not allowed.");
268 TEUCHOS_TEST_FOR_EXCEPTION(
269 index.lbound() < 0, std::invalid_argument,
270 os.str() <<
"Index range includes negative inde{x,ices}, which is " 272 TEUCHOS_TEST_FOR_EXCEPTION(
273 index.ubound() >= numCols, std::invalid_argument,
274 os.str() <<
"Index range exceeds number of vectors " << numCols
275 <<
" in the input multivector.");
276 TEUCHOS_TEST_FOR_EXCEPTION(
277 true, std::logic_error,
278 os.str() <<
"Should never get here!");
280 Teuchos::RCP<MV> X_view = mv.subViewNonConst (index);
281 X_view->setCopyOrView (Teuchos::View);
285 static Teuchos::RCP<const MV>
286 CloneView (
const MV& mv,
const std::vector<int>& index)
288 #ifdef HAVE_TPETRA_DEBUG 289 const char fnName[] =
"Belos::MultiVecTraits<Scalar, " 290 "Tpetra::MultiVector<...> >::CloneView(mv,index)";
291 const size_t numVecs = mv.getNumVectors ();
292 TEUCHOS_TEST_FOR_EXCEPTION(
293 *std::min_element (index.begin (), index.end ()) < 0,
294 std::invalid_argument,
295 fnName <<
": All indices must be nonnegative.");
296 TEUCHOS_TEST_FOR_EXCEPTION(
297 static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
298 std::invalid_argument,
299 fnName <<
": All indices must be strictly less than the number of " 300 "columns " << numVecs <<
" in the input MultiVector mv.");
301 #endif // HAVE_TPETRA_DEBUG 304 Teuchos::Array<size_t> columns (index.size ());
305 for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
306 columns[j] = index[j];
311 Teuchos::RCP<const MV> X_view = mv.subView (columns);
312 Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
316 static Teuchos::RCP<const MV>
317 CloneView (
const MV& mv,
const Teuchos::Range1D& index)
322 const int numCols =
static_cast<int> (mv.getNumVectors());
323 const bool validRange = index.size() > 0 &&
324 index.lbound() >= 0 && index.ubound() < numCols;
326 std::ostringstream os;
327 os <<
"Anasazi::MultiVecTraits::CloneView(mv, index=[" 328 << index.lbound () <<
", " << index.ubound() <<
"]): ";
329 TEUCHOS_TEST_FOR_EXCEPTION(index.size() == 0, std::invalid_argument,
330 os.str() <<
"Empty index range is not allowed.");
331 TEUCHOS_TEST_FOR_EXCEPTION(index.lbound() < 0, std::invalid_argument,
332 os.str() <<
"Index range includes negative index/ices, which is not " 334 TEUCHOS_TEST_FOR_EXCEPTION(
335 index.ubound() >= numCols, std::invalid_argument,
336 os.str() <<
"Index range exceeds number of vectors " << numCols
337 <<
" in the input multivector.");
338 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
339 os.str() <<
"Should never get here!");
341 Teuchos::RCP<const MV> X_view = mv.subView (index);
342 Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
347 return static_cast<ptrdiff_t
> (mv.getGlobalLength ());
351 return static_cast<int> (mv.getNumVectors ());
357 const Teuchos::SerialDenseMatrix<int, Scalar>& B,
361 using Teuchos::ArrayView;
363 using Teuchos::rcpFromRef;
364 typedef Tpetra::Map<LO, GO, Node> map_type;
366 #ifdef HAVE_ANASAZI_TPETRA_TIMERS 367 const std::string timerName (
"Anasazi::MVT::MvTimesMatAddMv");
368 Teuchos::RCP<Teuchos::Time> timer =
369 Teuchos::TimeMonitor::lookupCounter (timerName);
370 if (timer.is_null ()) {
371 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
373 TEUCHOS_TEST_FOR_EXCEPTION(
374 timer.is_null (), std::logic_error,
375 "Anasazi::MultiVecTraits::MvTimesMatAddMv: " 376 "Failed to look up timer \"" << timerName <<
"\". " 377 "Please report this bug to the Belos developers.");
380 Teuchos::TimeMonitor timeMon (*timer);
384 if (B.numRows () == 1 && B.numCols () == 1) {
385 mv.update (alpha*B(0,0), A, beta);
390 Teuchos::SerialComm<int> serialComm;
391 map_type LocalMap (B.numRows (), A.getMap ()->getIndexBase (),
392 rcpFromRef<const Comm<int> > (serialComm),
393 Tpetra::LocallyReplicated, A.getMap ()->getNode ());
395 ArrayView<const Scalar> Bvalues (B.values (), B.stride () * B.numCols ());
397 MV B_mv (rcpFromRef (LocalMap), Bvalues, B.stride (), B.numCols ());
398 mv.multiply (Teuchos::NO_TRANS, Teuchos::NO_TRANS, alpha, A, B_mv, beta);
415 mv.update (alpha, A, beta, B, Teuchos::ScalarTraits<Scalar>::zero ());
418 static void MvScale (MV& mv, Scalar alpha) {
422 static void MvScale (MV& mv,
const std::vector<Scalar>& alphas) {
430 Teuchos::SerialDenseMatrix<int,Scalar>& C)
432 using Tpetra::LocallyReplicated;
436 using Teuchos::TimeMonitor;
437 typedef Tpetra::Map<LO,GO,Node> map_type;
439 #ifdef HAVE_ANASAZI_TPETRA_TIMERS 440 const std::string timerName (
"Anasazi::MVT::MvTransMv");
441 RCP<Teuchos::Time> timer = TimeMonitor::lookupCounter (timerName);
442 if (timer.is_null ()) {
443 timer = TimeMonitor::getNewCounter (timerName);
445 TEUCHOS_TEST_FOR_EXCEPTION(
446 timer.is_null (), std::logic_error,
"Anasazi::MvTransMv: " 447 "Failed to look up timer \"" << timerName <<
"\". " 448 "Please report this bug to the Belos developers.");
451 TimeMonitor timeMon (*timer);
452 #endif // HAVE_ANASAZI_TPETRA_TIMERS 462 const int numRowsC = C.numRows ();
463 const int numColsC = C.numCols ();
464 const int strideC = C.stride ();
467 if (numRowsC == 1 && numColsC == 1) {
468 if (alpha == Teuchos::ScalarTraits<Scalar>::zero ()) {
473 A.dot (B, Teuchos::ArrayView<Scalar> (C.values (), 1));
474 if (alpha != Teuchos::ScalarTraits<Scalar>::one ()) {
481 RCP<const Comm<int> > pcomm = A.getMap ()->getComm ();
484 RCP<const map_type> LocalMap =
485 rcp (
new map_type (numRowsC, 0, pcomm, LocallyReplicated,
486 A.getMap ()->getNode ()));
488 const bool INIT_TO_ZERO =
true;
489 MV C_mv (LocalMap, numColsC, INIT_TO_ZERO);
492 C_mv.multiply (Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, alpha, A, B,
493 Teuchos::ScalarTraits<Scalar>::zero ());
496 Teuchos::ArrayView<Scalar> C_view (C.values (), strideC * numColsC);
501 C_mv.get1dCopy (C_view, strideC);
506 MvDot (
const MV& A,
const MV& B, std::vector<Scalar> &dots)
508 const size_t numVecs = A.getNumVectors ();
509 TEUCHOS_TEST_FOR_EXCEPTION(
510 numVecs != B.getNumVectors (), std::invalid_argument,
511 "Anasazi::MultiVecTraits::MvDot(A,B,dots): " 512 "A and B must have the same number of columns. " 513 "A has " << numVecs <<
" column(s), " 514 "but B has " << B.getNumVectors () <<
" column(s).");
515 #ifdef HAVE_TPETRA_DEBUG 516 TEUCHOS_TEST_FOR_EXCEPTION(
517 dots.size() < numVecs, std::invalid_argument,
518 "Anasazi::MultiVecTraits::MvDot(A,B,dots): " 519 "The output array 'dots' must have room for all dot products. " 520 "A and B each have " << numVecs <<
" column(s), " 521 "but 'dots' only has " << dots.size() <<
" entry(/ies).");
522 #endif // HAVE_TPETRA_DEBUG 524 Teuchos::ArrayView<Scalar> av (dots);
525 A.dot (B, av (0, numVecs));
531 std::vector<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &normvec)
533 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
534 #ifdef HAVE_TPETRA_DEBUG 535 TEUCHOS_TEST_FOR_EXCEPTION(
536 normvec.size () <
static_cast<std::vector<int>::size_type
> (mv.getNumVectors ()),
537 std::invalid_argument,
538 "Anasazi::MultiVecTraits::MvNorm(mv,normvec): The normvec output " 539 "argument must have at least as many entries as the number of vectors " 540 "(columns) in the MultiVector mv. normvec.size() = " << normvec.size ()
541 <<
" < mv.getNumVectors() = " << mv.getNumVectors () <<
".");
542 #endif // HAVE_TPETRA_DEBUG 543 Teuchos::ArrayView<magnitude_type> av (normvec);
544 mv.norm2 (av (0, mv.getNumVectors ()));
548 SetBlock (
const MV& A,
const std::vector<int>& index, MV& mv)
550 using Teuchos::Range1D;
552 const size_t inNumVecs = A.getNumVectors ();
553 #ifdef HAVE_TPETRA_DEBUG 554 TEUCHOS_TEST_FOR_EXCEPTION(
555 inNumVecs < static_cast<size_t> (index.size ()), std::invalid_argument,
556 "Anasazi::MultiVecTraits::SetBlock(A,index,mv): 'index' argument must " 557 "have no more entries as the number of columns in the input MultiVector" 558 " A. A.getNumVectors() = " << inNumVecs <<
" < index.size () = " 559 << index.size () <<
".");
560 #endif // HAVE_TPETRA_DEBUG 562 if (inNumVecs > static_cast<size_t> (index.size ())) {
563 RCP<const MV> Asub = A.subView (Range1D (0, index.size () - 1));
564 Tpetra::deep_copy (*mvsub, *Asub);
566 Tpetra::deep_copy (*mvsub, A);
571 SetBlock (
const MV& A,
const Teuchos::Range1D& index, MV& mv)
580 const size_t maxInt =
581 static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
582 const bool overflow =
583 maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
585 std::ostringstream os;
586 os <<
"Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
587 <<
", " << index.ubound () <<
"], mv): ";
588 TEUCHOS_TEST_FOR_EXCEPTION(
589 maxInt < A.getNumVectors (), std::range_error, os.str () <<
"Number " 590 "of columns (size_t) in the input MultiVector 'A' overflows int.");
591 TEUCHOS_TEST_FOR_EXCEPTION(
592 maxInt < mv.getNumVectors (), std::range_error, os.str () <<
"Number " 593 "of columns (size_t) in the output MultiVector 'mv' overflows int.");
596 const int numColsA =
static_cast<int> (A.getNumVectors ());
597 const int numColsMv =
static_cast<int> (mv.getNumVectors ());
599 const bool validIndex =
600 index.lbound () >= 0 && index.ubound () < numColsMv;
602 const bool validSource = index.size () <= numColsA;
604 if (! validIndex || ! validSource) {
605 std::ostringstream os;
606 os <<
"Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
607 <<
", " << index.ubound () <<
"], mv): ";
608 TEUCHOS_TEST_FOR_EXCEPTION(
609 index.lbound() < 0, std::invalid_argument,
610 os.str() <<
"Range lower bound must be nonnegative.");
611 TEUCHOS_TEST_FOR_EXCEPTION(
612 index.ubound() >= numColsMv, std::invalid_argument,
613 os.str() <<
"Range upper bound must be less than the number of " 614 "columns " << numColsA <<
" in the 'mv' output argument.");
615 TEUCHOS_TEST_FOR_EXCEPTION(
616 index.size() > numColsA, std::invalid_argument,
617 os.str() <<
"Range must have no more elements than the number of " 618 "columns " << numColsA <<
" in the 'A' input argument.");
619 TEUCHOS_TEST_FOR_EXCEPTION(
620 true, std::logic_error,
"Should never get here!");
626 Teuchos::RCP<MV> mv_view;
627 if (index.lbound () == 0 && index.ubound () + 1 == numColsMv) {
628 mv_view = Teuchos::rcpFromRef (mv);
636 Teuchos::RCP<const MV> A_view;
637 if (index.size () == numColsA) {
638 A_view = Teuchos::rcpFromRef (A);
640 A_view =
CloneView (A, Teuchos::Range1D (0, index.size () - 1));
643 Tpetra::deep_copy (*mv_view, *A_view);
646 static void Assign (
const MV& A, MV& mv)
648 const char errPrefix[] =
"Anasazi::MultiVecTraits::Assign(A, mv): ";
657 const size_t maxInt =
658 static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
659 const bool overflow =
660 maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
662 TEUCHOS_TEST_FOR_EXCEPTION(
663 maxInt < A.getNumVectors(), std::range_error,
664 errPrefix <<
"Number of columns in the input multivector 'A' " 665 "(a size_t) overflows int.");
666 TEUCHOS_TEST_FOR_EXCEPTION(
667 maxInt < mv.getNumVectors(), std::range_error,
668 errPrefix <<
"Number of columns in the output multivector 'mv' " 669 "(a size_t) overflows int.");
670 TEUCHOS_TEST_FOR_EXCEPTION(
671 true, std::logic_error,
"Should never get here!");
674 const int numColsA =
static_cast<int> (A.getNumVectors ());
675 const int numColsMv =
static_cast<int> (mv.getNumVectors ());
676 if (numColsA > numColsMv) {
677 TEUCHOS_TEST_FOR_EXCEPTION(
678 numColsA > numColsMv, std::invalid_argument,
679 errPrefix <<
"Input multivector 'A' has " << numColsA <<
" columns, " 680 "but output multivector 'mv' has only " << numColsMv <<
" columns.");
681 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Should never get here!");
683 if (numColsA == numColsMv) {
684 Tpetra::deep_copy (mv, A);
686 Teuchos::RCP<MV> mv_view =
688 Tpetra::deep_copy (*mv_view, A);
697 MvInit (MV& mv,
const Scalar alpha = Teuchos::ScalarTraits<Scalar>::zero ())
699 mv.putScalar (alpha);
702 static void MvPrint (
const MV& mv, std::ostream& os) {
706 #ifdef HAVE_ANASAZI_TSQR 707 typedef Tpetra::TsqrAdaptor<Tpetra::MultiVector<Scalar, LO, GO, Node> > tsqr_adaptor_type;
710 #endif // HAVE_ANASAZI_TSQR 715 template <
class Scalar,
class LO,
class GO,
class Node>
717 Tpetra::MultiVector<Scalar,LO,GO,Node>,
718 Tpetra::Operator<Scalar,LO,GO,Node> >
722 Apply (
const Tpetra::Operator<Scalar,LO,GO,Node>& Op,
723 const Tpetra::MultiVector<Scalar,LO,GO,Node>& X,
724 Tpetra::MultiVector<Scalar,LO,GO,Node>& Y)
726 Op.apply (X, Y, Teuchos::NO_TRANS);
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
static void MvDot(const MV &A, const MV &B, std::vector< Scalar > &dots)
For all columns j of A, set dots[j] := A[j]^T * B[j].
static void MvInit(MV &mv, const ScalarType alpha=Teuchos::ScalarTraits< ScalarType >::zero())
Replace each element of the vectors in mv with alpha.
static void MvRandom(MV &mv)
Replace the vectors in mv with random vectors.
static void MvTimesMatAddMv(const ScalarType alpha, const MV &A, const Teuchos::SerialDenseMatrix< int, ScalarType > &B, const ScalarType beta, MV &mv)
Update mv with .
static Teuchos::RCP< MV > Clone(const MV &X, const int numVecs)
Create a new MultiVector with numVecs columns.
static void MvAddMv(Scalar alpha, const MV &A, Scalar beta, const MV &B, MV &mv)
mv := alpha*A + beta*B
Declaration of basic traits for the multivector type.
Virtual base class which defines basic traits for the operator type.
static void Assign(const MV &A, MV &mv)
mv := A
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.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package...
static void MvNorm(const MV &mv, std::vector< typename Teuchos::ScalarTraits< Scalar >::magnitudeType > &normvec)
For all columns j of mv, set normvec[j] = norm(mv[j]).
static Teuchos::RCP< MV > CloneCopy(const MV &X)
Create and return a deep copy of X.
Traits class which defines basic operations on multivectors.
static void MvTransMv(const ScalarType alpha, const MV &A, const MV &B, Teuchos::SerialDenseMatrix< int, ScalarType > &C)
Compute C := alpha * A^H B.
Virtual base class which defines basic traits for the operator type.
static void MvScale(MV &mv, const ScalarType alpha)
Scale each element of the vectors in mv with alpha.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
Creates a new MV that shares the selected contents of mv (shallow copy).
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
Creates a new const MV that shares the selected contents of mv (shallow copy).
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index...
static int GetNumberVecs(const MV &mv)
Obtain the number of vectors in mv.
Types and exceptions used within Anasazi solvers and interfaces.
static void MvPrint(const MV &mv, std::ostream &os)
Print the mv multi-vector to the os output stream.
static Teuchos::RCP< MV > CloneCopy(const MV &mv, const Teuchos::Range1D &index)
Create and return a deep copy of the given columns of mv.