Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
AnasaziTpetraAdapter.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Anasazi: Block Eigensolvers Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef ANASAZI_TPETRA_ADAPTER_HPP
00030 #define ANASAZI_TPETRA_ADAPTER_HPP
00031 
00068 
00069 #include <Tpetra_MultiVector.hpp>
00070 #include <Tpetra_Operator.hpp>
00071 
00072 #include <Teuchos_Array.hpp>
00073 #include <Teuchos_Assert.hpp>
00074 #include <Teuchos_DefaultSerialComm.hpp>
00075 #include <Teuchos_ScalarTraits.hpp>
00076 
00077 #include <AnasaziConfigDefs.hpp>
00078 #include <AnasaziTypes.hpp>
00079 #include <AnasaziMultiVecTraits.hpp>
00080 #include <AnasaziOperatorTraits.hpp>
00081 
00082 #ifdef HAVE_ANASAZI_TSQR
00083 #  include <Tpetra_TsqrAdaptor.hpp>
00084 #endif // HAVE_ANASAZI_TSQR
00085 
00086 
00087 namespace Anasazi {
00088 
00100   template<class Scalar, class LO, class GO, class Node>
00101   class MultiVecTraits<Scalar, Tpetra::MultiVector<Scalar,LO,GO,Node> > {
00102     typedef Tpetra::MultiVector<Scalar, LO, GO, Node> MV;
00103   public:
00109     static Teuchos::RCP<MV> Clone (const MV& X, const int numVecs) {
00110       Teuchos::RCP<MV> Y (new MV (X.getMap (), numVecs, false));
00111       Y->setCopyOrView (Teuchos::View);
00112       return Y;
00113     }
00114 
00116     static Teuchos::RCP<MV> CloneCopy (const MV& X)
00117     {
00118       // Make a deep copy of X.  The one-argument copy constructor
00119       // does a shallow copy by default; the second argument tells it
00120       // to do a deep copy.
00121       Teuchos::RCP<MV> X_copy (new MV (X, Teuchos::Copy));
00122       // Make Tpetra::MultiVector use the new view semantics.  This is
00123       // a no-op for the Kokkos refactor version of Tpetra; it only
00124       // does something for the "classic" version of Tpetra.  This
00125       // shouldn't matter because Belos only handles MV through RCP
00126       // and through this interface anyway, but it doesn't hurt to set
00127       // it and make sure that it works.
00128       X_copy->setCopyOrView (Teuchos::View);
00129       return X_copy;
00130     }
00131 
00143     static Teuchos::RCP<MV>
00144     CloneCopy (const MV& mv, const std::vector<int>& index)
00145     {
00146 #ifdef HAVE_TPETRA_DEBUG
00147       const char fnName[] = "Anasazi::MultiVecTraits::CloneCopy(mv,index)";
00148       const size_t inNumVecs = mv.getNumVectors ();
00149       TEUCHOS_TEST_FOR_EXCEPTION(
00150         index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
00151         std::runtime_error, fnName << ": All indices must be nonnegative.");
00152       TEUCHOS_TEST_FOR_EXCEPTION(
00153         index.size () > 0 &&
00154         static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= inNumVecs,
00155         std::runtime_error,
00156         fnName << ": All indices must be strictly less than the number of "
00157         "columns " << inNumVecs << " of the input multivector mv.");
00158 #endif // HAVE_TPETRA_DEBUG
00159 
00160       // Tpetra wants an array of size_t, not of int.
00161       Teuchos::Array<size_t> columns (index.size ());
00162       for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
00163         columns[j] = index[j];
00164       }
00165       // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
00166       // continuous column index range in MultiVector::subCopy, so we
00167       // don't have to check here.
00168       Teuchos::RCP<MV> X_copy = mv.subCopy (columns ());
00169       X_copy->setCopyOrView (Teuchos::View);
00170       return X_copy;
00171     }
00172 
00179     static Teuchos::RCP<MV>
00180     CloneCopy (const MV& mv, const Teuchos::Range1D& index)
00181     {
00182       const bool validRange = index.size() > 0 &&
00183         index.lbound() >= 0 &&
00184         index.ubound() < GetNumberVecs(mv);
00185       if (! validRange) { // invalid range; generate error message
00186         std::ostringstream os;
00187         os << "Anasazi::MultiVecTraits::CloneCopy(mv,index=["
00188            << index.lbound() << "," << index.ubound() << "]): ";
00189         TEUCHOS_TEST_FOR_EXCEPTION(
00190           index.size() == 0, std::invalid_argument,
00191           os.str() << "Empty index range is not allowed.");
00192         TEUCHOS_TEST_FOR_EXCEPTION(
00193           index.lbound() < 0, std::invalid_argument,
00194           os.str() << "Index range includes negative index/ices, which is not "
00195           "allowed.");
00196         TEUCHOS_TEST_FOR_EXCEPTION(
00197           index.ubound() >= GetNumberVecs(mv), std::invalid_argument,
00198           os.str() << "Index range exceeds number of vectors "
00199           << mv.getNumVectors() << " in the input multivector.");
00200         TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00201           os.str() << "Should never get here!");
00202       }
00203       Teuchos::RCP<MV> X_copy = mv.subCopy (index);
00204       X_copy->setCopyOrView (Teuchos::View);
00205       return X_copy;
00206     }
00207 
00208     static Teuchos::RCP<MV>
00209     CloneViewNonConst (MV& mv, const std::vector<int>& index)
00210     {
00211 #ifdef HAVE_TPETRA_DEBUG
00212       const char fnName[] = "Anasazi::MultiVecTraits::CloneViewNonConst(mv,index)";
00213       const size_t numVecs = mv.getNumVectors ();
00214       TEUCHOS_TEST_FOR_EXCEPTION(
00215         index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
00216         std::invalid_argument,
00217         fnName << ": All indices must be nonnegative.");
00218       TEUCHOS_TEST_FOR_EXCEPTION(
00219         index.size () > 0 &&
00220         static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
00221         std::invalid_argument,
00222         fnName << ": All indices must be strictly less than the number of "
00223         "columns " << numVecs << " in the input MultiVector mv.");
00224 #endif // HAVE_TPETRA_DEBUG
00225 
00226       // Tpetra wants an array of size_t, not of int.
00227       Teuchos::Array<size_t> columns (index.size ());
00228       for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
00229         columns[j] = index[j];
00230       }
00231       // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
00232       // continuous column index range in
00233       // MultiVector::subViewNonConst, so we don't have to check here.
00234       Teuchos::RCP<MV> X_view = mv.subViewNonConst (columns ());
00235       X_view->setCopyOrView (Teuchos::View);
00236       return X_view;
00237     }
00238 
00239     static Teuchos::RCP<MV>
00240     CloneViewNonConst (MV& mv, const Teuchos::Range1D& index)
00241     {
00242       // NOTE (mfh 11 Jan 2011) We really should check for possible
00243       // overflow of int here.  However, the number of columns in a
00244       // multivector typically fits in an int.
00245       const int numCols = static_cast<int> (mv.getNumVectors());
00246       const bool validRange = index.size() > 0 &&
00247         index.lbound() >= 0 && index.ubound() < numCols;
00248       if (! validRange) {
00249         std::ostringstream os;
00250         os << "Belos::MultiVecTraits::CloneViewNonConst(mv,index=["
00251            << index.lbound() << ", " << index.ubound() << "]): ";
00252         TEUCHOS_TEST_FOR_EXCEPTION(
00253           index.size() == 0, std::invalid_argument,
00254           os.str() << "Empty index range is not allowed.");
00255         TEUCHOS_TEST_FOR_EXCEPTION(
00256           index.lbound() < 0, std::invalid_argument,
00257           os.str() << "Index range includes negative inde{x,ices}, which is "
00258           "not allowed.");
00259         TEUCHOS_TEST_FOR_EXCEPTION(
00260           index.ubound() >= numCols, std::invalid_argument,
00261           os.str() << "Index range exceeds number of vectors " << numCols
00262           << " in the input multivector.");
00263         TEUCHOS_TEST_FOR_EXCEPTION(
00264           true, std::logic_error,
00265           os.str() << "Should never get here!");
00266       }
00267       Teuchos::RCP<MV> X_view = mv.subViewNonConst (index);
00268       X_view->setCopyOrView (Teuchos::View);
00269       return X_view;
00270     }
00271 
00272     static Teuchos::RCP<const MV>
00273     CloneView (const MV& mv, const std::vector<int>& index)
00274     {
00275 #ifdef HAVE_TPETRA_DEBUG
00276       const char fnName[] = "Belos::MultiVecTraits<Scalar, "
00277         "Tpetra::MultiVector<...> >::CloneView(mv,index)";
00278       const size_t numVecs = mv.getNumVectors ();
00279       TEUCHOS_TEST_FOR_EXCEPTION(
00280         *std::min_element (index.begin (), index.end ()) < 0,
00281         std::invalid_argument,
00282         fnName << ": All indices must be nonnegative.");
00283       TEUCHOS_TEST_FOR_EXCEPTION(
00284         static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
00285         std::invalid_argument,
00286         fnName << ": All indices must be strictly less than the number of "
00287         "columns " << numVecs << " in the input MultiVector mv.");
00288 #endif // HAVE_TPETRA_DEBUG
00289 
00290       // Tpetra wants an array of size_t, not of int.
00291       Teuchos::Array<size_t> columns (index.size ());
00292       for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
00293         columns[j] = index[j];
00294       }
00295       // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
00296       // continuous column index range in MultiVector::subView, so we
00297       // don't have to check here.
00298       Teuchos::RCP<const MV> X_view = mv.subView (columns);
00299       Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
00300       return X_view;
00301     }
00302 
00303     static Teuchos::RCP<const MV>
00304     CloneView (const MV& mv, const Teuchos::Range1D& index)
00305     {
00306       // NOTE (mfh 11 Jan 2011) We really should check for possible
00307       // overflow of int here.  However, the number of columns in a
00308       // multivector typically fits in an int.
00309       const int numCols = static_cast<int> (mv.getNumVectors());
00310       const bool validRange = index.size() > 0 &&
00311         index.lbound() >= 0 && index.ubound() < numCols;
00312       if (! validRange) {
00313         std::ostringstream os;
00314         os << "Anasazi::MultiVecTraits::CloneView(mv, index=["
00315            << index.lbound () << ", " << index.ubound() << "]): ";
00316         TEUCHOS_TEST_FOR_EXCEPTION(index.size() == 0, std::invalid_argument,
00317           os.str() << "Empty index range is not allowed.");
00318         TEUCHOS_TEST_FOR_EXCEPTION(index.lbound() < 0, std::invalid_argument,
00319           os.str() << "Index range includes negative index/ices, which is not "
00320           "allowed.");
00321         TEUCHOS_TEST_FOR_EXCEPTION(
00322           index.ubound() >= numCols, std::invalid_argument,
00323           os.str() << "Index range exceeds number of vectors " << numCols
00324           << " in the input multivector.");
00325         TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00326           os.str() << "Should never get here!");
00327       }
00328       Teuchos::RCP<const MV> X_view = mv.subView (index);
00329       Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
00330       return X_view;
00331     }
00332 
00333     static int GetVecLength (const MV& mv) {
00334       return static_cast<int> (mv.getGlobalLength ());
00335     }
00336 
00337     static int GetNumberVecs (const MV& mv) {
00338       return static_cast<int> (mv.getNumVectors ());
00339     }
00340 
00341     static void
00342     MvTimesMatAddMv (Scalar alpha,
00343                      const MV& A,
00344                      const Teuchos::SerialDenseMatrix<int, Scalar>& B,
00345                      Scalar beta,
00346                      MV& mv)
00347     {
00348       using Teuchos::ArrayView;
00349       using Teuchos::Comm;
00350       using Teuchos::rcpFromRef;
00351       typedef Tpetra::Map<LO, GO, Node> map_type;
00352 
00353 #ifdef HAVE_ANASAZI_TPETRA_TIMERS
00354       const std::string timerName ("Anasazi::MVT::MvTimesMatAddMv");
00355       Teuchos::RCP<Teuchos::Time> timer =
00356         Teuchos::TimeMonitor::lookupCounter (timerName);
00357       if (timer.is_null ()) {
00358         timer = Teuchos::TimeMonitor::getNewCounter (timerName);
00359       }
00360       TEUCHOS_TEST_FOR_EXCEPTION(
00361         timer.is_null (), std::logic_error,
00362         "Anasazi::MultiVecTraits::MvTimesMatAddMv: "
00363         "Failed to look up timer \"" << timerName << "\".  "
00364         "Please report this bug to the Belos developers.");
00365 
00366       // This starts the timer.  It will be stopped on scope exit.
00367       Teuchos::TimeMonitor timeMon (*timer);
00368 #endif
00369 
00370       // Check if B is 1-by-1, in which case we can just call update()
00371       if (B.numRows () == 1 && B.numCols () == 1) {
00372         mv.update (alpha*B(0,0), A, beta);
00373         return;
00374       }
00375 
00376       // Create local map
00377       Teuchos::SerialComm<int> serialComm;
00378       map_type LocalMap (B.numRows (), A.getMap ()->getIndexBase (),
00379                          rcpFromRef<const Comm<int> > (serialComm),
00380                          Tpetra::LocallyReplicated, A.getMap ()->getNode ());
00381       // encapsulate Teuchos::SerialDenseMatrix data in ArrayView
00382       ArrayView<const Scalar> Bvalues (B.values (), B.stride () * B.numCols ());
00383       // create locally replicated MultiVector with a copy of this data
00384       MV B_mv (rcpFromRef (LocalMap), Bvalues, B.stride (), B.numCols ());
00385       mv.multiply (Teuchos::NO_TRANS, Teuchos::NO_TRANS, alpha, A, B_mv, beta);
00386     }
00387 
00395     static void
00396     MvAddMv (Scalar alpha,
00397              const MV& A,
00398              Scalar beta,
00399              const MV& B,
00400              MV& mv)
00401     {
00402       mv.update (alpha, A, beta, B, Teuchos::ScalarTraits<Scalar>::zero ());
00403     }
00404 
00405     static void MvScale (MV& mv, Scalar alpha) {
00406       mv.scale (alpha);
00407     }
00408 
00409     static void MvScale (MV& mv, const std::vector<Scalar>& alphas) {
00410       mv.scale (alphas);
00411     }
00412 
00413     static void
00414     MvTransMv (Scalar alpha,
00415                const MV& A,
00416                const MV& B,
00417                Teuchos::SerialDenseMatrix<int,Scalar>& C)
00418     {
00419       using Tpetra::LocallyReplicated;
00420       using Teuchos::Comm;
00421       using Teuchos::RCP;
00422       using Teuchos::rcp;
00423       using Teuchos::REDUCE_SUM;
00424       using Teuchos::reduceAll;
00425       using Teuchos::SerialComm;
00426       using Teuchos::TimeMonitor;
00427       typedef Tpetra::Map<LO,GO,Node> map_type;
00428 
00429 #ifdef HAVE_ANASAZI_TPETRA_TIMERS
00430       const std::string timerName ("Anasazi::MVT::MvTransMv");
00431       RCP<Teuchos::Time> timer = TimeMonitor::lookupCounter (timerName);
00432       if (timer.is_null ()) {
00433         timer = TimeMonitor::getNewCounter (timerName);
00434       }
00435       TEUCHOS_TEST_FOR_EXCEPTION(
00436         timer.is_null (), std::logic_error, "Anasazi::MvTransMv: "
00437         "Failed to look up timer \"" << timerName << "\".  "
00438         "Please report this bug to the Belos developers.");
00439 
00440       // This starts the timer.  It will be stopped on scope exit.
00441       TimeMonitor timeMon (*timer);
00442 #endif // HAVE_ANASAZI_TPETRA_TIMERS
00443 
00444       // Form alpha * A^H * B, then copy into the SerialDenseMatrix.
00445       // We will create a multivector C_mv from a a local map.  This
00446       // map has a serial comm, the purpose being to short-circuit the
00447       // MultiVector::reduce() call at the end of
00448       // MultiVector::multiply().  Otherwise, the reduced multivector
00449       // data would be copied back to the GPU, only to turn around and
00450       // have to get it back here.  This saves us a round trip for
00451       // this data.
00452       const int numRowsC = C.numRows ();
00453       const int numColsC = C.numCols ();
00454       const int strideC  = C.stride ();
00455 
00456       // Check if numRowsC == numColsC == 1, in which case we can call dot()
00457       if (numRowsC == 1 && numColsC == 1) {
00458         A.dot (B, Teuchos::ArrayView<Scalar> (C.values (), 1));
00459         return;
00460       }
00461 
00462       RCP<Comm<int> > serialComm (new SerialComm<int> ());
00463       // create local map with serial comm
00464       RCP<const map_type> LocalMap =
00465         rcp (new map_type (numRowsC, 0, serialComm, LocallyReplicated,
00466                            A.getMap ()->getNode ()));
00467       // create local multivector to hold the result
00468       const bool INIT_TO_ZERO = true;
00469       MV C_mv (LocalMap, numColsC, INIT_TO_ZERO);
00470 
00471       // multiply result into local multivector
00472       C_mv.multiply (Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, alpha, A, B,
00473                      Teuchos::ScalarTraits<Scalar>::zero ());
00474       // get comm
00475       RCP<const Comm<int> > pcomm = A.getMap ()->getComm ();
00476       // create arrayview encapsulating the Teuchos::SerialDenseMatrix
00477       Teuchos::ArrayView<Scalar> C_view (C.values (), strideC * numColsC);
00478       if (pcomm->getSize() == 1) {
00479         // No accumulation to do; simply extract the multivector data
00480         // into C.  Extract a copy of the result into the array view
00481         // (and therefore, the SerialDenseMatrix).
00482         C_mv.get1dCopy (C_view, strideC);
00483       }
00484       else {
00485         // get a const host view of the data in C_mv
00486         Teuchos::ArrayRCP<const Scalar> C_mv_view = C_mv.get1dView();
00487         if (strideC == numRowsC) {
00488           // sum-all into C
00489           reduceAll<int, Scalar> (*pcomm, REDUCE_SUM, numColsC*numRowsC,
00490                                   C_mv_view.getRawPtr (), C_view.getRawPtr ());
00491         }
00492         else {
00493           // sum-all into temp, copy into C
00494           Teuchos::Array<Scalar> destBuff (numColsC * numRowsC);
00495           reduceAll<int,Scalar> (*pcomm, REDUCE_SUM, numColsC*numRowsC,
00496                                  C_mv_view.getRawPtr (), destBuff.getRawPtr ());
00497           for (int j=0; j < numColsC; ++j) {
00498             for (int i=0; i < numRowsC; ++i) {
00499               C_view[strideC*j+i] = destBuff[numRowsC*j+i];
00500             }
00501           }
00502         }
00503       }
00504     }
00505 
00507     static void
00508     MvDot (const MV& A, const MV& B, std::vector<Scalar> &dots)
00509     {
00510       const size_t numVecs = A.getNumVectors ();
00511       TEUCHOS_TEST_FOR_EXCEPTION(
00512         numVecs != B.getNumVectors (), std::invalid_argument,
00513         "Anasazi::MultiVecTraits::MvDot(A,B,dots): "
00514         "A and B must have the same number of columns.  "
00515         "A has " << numVecs << " column(s), "
00516         "but B has " << B.getNumVectors () << " column(s).");
00517 #ifdef HAVE_TPETRA_DEBUG
00518       TEUCHOS_TEST_FOR_EXCEPTION(
00519         dots.size() < numVecs, std::invalid_argument,
00520         "Anasazi::MultiVecTraits::MvDot(A,B,dots): "
00521         "The output array 'dots' must have room for all dot products.  "
00522         "A and B each have " << numVecs << " column(s), "
00523         "but 'dots' only has " << dots.size() << " entry(/ies).");
00524 #endif // HAVE_TPETRA_DEBUG
00525 
00526       Teuchos::ArrayView<Scalar> av (dots);
00527       A.dot (B, av (0, numVecs));
00528     }
00529 
00531     static void
00532     MvNorm (const MV& mv,
00533             std::vector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &normvec)
00534     {
00535       typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
00536 #ifdef HAVE_TPETRA_DEBUG
00537       TEUCHOS_TEST_FOR_EXCEPTION(
00538         normvec.size () < static_cast<std::vector<int>::size_type> (mv.getNumVectors ()),
00539         std::invalid_argument,
00540         "Anasazi::MultiVecTraits::MvNorm(mv,normvec): The normvec output "
00541         "argument must have at least as many entries as the number of vectors "
00542         "(columns) in the MultiVector mv.  normvec.size() = " << normvec.size ()
00543         << " < mv.getNumVectors() = " << mv.getNumVectors () << ".");
00544 #endif // HAVE_TPETRA_DEBUG
00545       Teuchos::ArrayView<magnitude_type> av (normvec);
00546       mv.norm2 (av (0, mv.getNumVectors ()));
00547     }
00548 
00549     static void
00550     SetBlock (const MV& A, const std::vector<int>& index, MV& mv)
00551     {
00552       using Teuchos::Range1D;
00553       using Teuchos::RCP;
00554       const size_t inNumVecs = A.getNumVectors ();
00555 #ifdef HAVE_TPETRA_DEBUG
00556       TEUCHOS_TEST_FOR_EXCEPTION(
00557         inNumVecs < static_cast<size_t> (index.size ()), std::invalid_argument,
00558         "Anasazi::MultiVecTraits::SetBlock(A,index,mv): 'index' argument must "
00559         "have no more entries as the number of columns in the input MultiVector"
00560         " A.  A.getNumVectors() = " << inNumVecs << " < index.size () = "
00561         << index.size () << ".");
00562 #endif // HAVE_TPETRA_DEBUG
00563       RCP<MV> mvsub = CloneViewNonConst (mv, index);
00564       if (inNumVecs > static_cast<size_t> (index.size ())) {
00565         RCP<const MV> Asub = A.subView (Range1D (0, index.size () - 1));
00566         Tpetra::deep_copy (*mvsub, *Asub);
00567       } else {
00568         Tpetra::deep_copy (*mvsub, A);
00569       }
00570     }
00571 
00572     static void
00573     SetBlock (const MV& A, const Teuchos::Range1D& index, MV& mv)
00574     {
00575       // Range1D bounds are signed; size_t is unsigned.
00576       // Assignment of Tpetra::MultiVector is a deep copy.
00577 
00578       // Tpetra::MultiVector::getNumVectors() returns size_t.  It's
00579       // fair to assume that the number of vectors won't overflow int,
00580       // since the typical use case of multivectors involves few
00581       // columns, but it's friendly to check just in case.
00582       const size_t maxInt =
00583         static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
00584       const bool overflow =
00585         maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
00586       if (overflow) {
00587         std::ostringstream os;
00588         os << "Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
00589            << ", " << index.ubound () << "], mv): ";
00590         TEUCHOS_TEST_FOR_EXCEPTION(
00591           maxInt < A.getNumVectors (), std::range_error, os.str () << "Number "
00592           "of columns (size_t) in the input MultiVector 'A' overflows int.");
00593         TEUCHOS_TEST_FOR_EXCEPTION(
00594           maxInt < mv.getNumVectors (), std::range_error, os.str () << "Number "
00595           "of columns (size_t) in the output MultiVector 'mv' overflows int.");
00596       }
00597       // We've already validated the static casts above.
00598       const int numColsA = static_cast<int> (A.getNumVectors ());
00599       const int numColsMv = static_cast<int> (mv.getNumVectors ());
00600       // 'index' indexes into mv; it's the index set of the target.
00601       const bool validIndex =
00602         index.lbound () >= 0 && index.ubound () < numColsMv;
00603       // We can't take more columns out of A than A has.
00604       const bool validSource = index.size () <= numColsA;
00605 
00606       if (! validIndex || ! validSource) {
00607         std::ostringstream os;
00608         os << "Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
00609            << ", " << index.ubound () << "], mv): ";
00610         TEUCHOS_TEST_FOR_EXCEPTION(
00611           index.lbound() < 0, std::invalid_argument,
00612           os.str() << "Range lower bound must be nonnegative.");
00613         TEUCHOS_TEST_FOR_EXCEPTION(
00614           index.ubound() >= numColsMv, std::invalid_argument,
00615           os.str() << "Range upper bound must be less than the number of "
00616           "columns " << numColsA << " in the 'mv' output argument.");
00617         TEUCHOS_TEST_FOR_EXCEPTION(
00618           index.size() > numColsA, std::invalid_argument,
00619           os.str() << "Range must have no more elements than the number of "
00620           "columns " << numColsA << " in the 'A' input argument.");
00621         TEUCHOS_TEST_FOR_EXCEPTION(
00622           true, std::logic_error, "Should never get here!");
00623       }
00624 
00625       // View of the relevant column(s) of the target multivector mv.
00626       // We avoid view creation overhead by only creating a view if
00627       // the index range is different than [0, (# columns in mv) - 1].
00628       Teuchos::RCP<MV> mv_view;
00629       if (index.lbound () == 0 && index.ubound () + 1 == numColsMv) {
00630         mv_view = Teuchos::rcpFromRef (mv); // Non-const, non-owning RCP
00631       } else {
00632         mv_view = CloneViewNonConst (mv, index);
00633       }
00634 
00635       // View of the relevant column(s) of the source multivector A.
00636       // If A has fewer columns than mv_view, then create a view of
00637       // the first index.size() columns of A.
00638       Teuchos::RCP<const MV> A_view;
00639       if (index.size () == numColsA) {
00640         A_view = Teuchos::rcpFromRef (A); // Const, non-owning RCP
00641       } else {
00642         A_view = CloneView (A, Teuchos::Range1D (0, index.size () - 1));
00643       }
00644 
00645       Tpetra::deep_copy (*mv_view, *A_view);
00646     }
00647 
00648     static void Assign (const MV& A, MV& mv)
00649     {
00650       const char errPrefix[] = "Anasazi::MultiVecTraits::Assign(A, mv): ";
00651 
00652       // Range1D bounds are signed; size_t is unsigned.
00653       // Assignment of Tpetra::MultiVector is a deep copy.
00654 
00655       // Tpetra::MultiVector::getNumVectors() returns size_t.  It's
00656       // fair to assume that the number of vectors won't overflow int,
00657       // since the typical use case of multivectors involves few
00658       // columns, but it's friendly to check just in case.
00659       const size_t maxInt =
00660         static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
00661       const bool overflow =
00662         maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
00663       if (overflow) {
00664         TEUCHOS_TEST_FOR_EXCEPTION(
00665           maxInt < A.getNumVectors(), std::range_error,
00666           errPrefix << "Number of columns in the input multivector 'A' "
00667           "(a size_t) overflows int.");
00668         TEUCHOS_TEST_FOR_EXCEPTION(
00669           maxInt < mv.getNumVectors(), std::range_error,
00670           errPrefix << "Number of columns in the output multivector 'mv' "
00671           "(a size_t) overflows int.");
00672         TEUCHOS_TEST_FOR_EXCEPTION(
00673           true, std::logic_error, "Should never get here!");
00674       }
00675       // We've already validated the static casts above.
00676       const int numColsA = static_cast<int> (A.getNumVectors ());
00677       const int numColsMv = static_cast<int> (mv.getNumVectors ());
00678       if (numColsA > numColsMv) {
00679         TEUCHOS_TEST_FOR_EXCEPTION(
00680           numColsA > numColsMv, std::invalid_argument,
00681           errPrefix << "Input multivector 'A' has " << numColsA << " columns, "
00682           "but output multivector 'mv' has only " << numColsMv << " columns.");
00683         TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Should never get here!");
00684       }
00685       if (numColsA == numColsMv) {
00686         Tpetra::deep_copy (mv, A);
00687       } else {
00688         Teuchos::RCP<MV> mv_view =
00689           CloneViewNonConst (mv, Teuchos::Range1D (0, numColsA - 1));
00690         Tpetra::deep_copy (*mv_view, A);
00691       }
00692     }
00693 
00694     static void MvRandom (MV& mv) {
00695       mv.randomize ();
00696     }
00697 
00698     static void
00699     MvInit (MV& mv, const Scalar alpha = Teuchos::ScalarTraits<Scalar>::zero ())
00700     {
00701       mv.putScalar (alpha);
00702     }
00703 
00704     static void MvPrint (const MV& mv, std::ostream& os) {
00705       mv.print (os);
00706     }
00707 
00708 #ifdef HAVE_ANASAZI_TSQR
00709 
00710 
00711     typedef Tpetra::TsqrAdaptor<Tpetra::MultiVector<Scalar, LO, GO, Node> > tsqr_adaptor_type;
00712 #endif // HAVE_ANASAZI_TSQR
00713   };
00714 
00716   template <class Scalar, class LO, class GO, class Node>
00717   class OperatorTraits<Scalar,
00718                        Tpetra::MultiVector<Scalar,LO,GO,Node>,
00719                        Tpetra::Operator<Scalar,LO,GO,Node> >
00720   {
00721   public:
00722     static void
00723     Apply (const Tpetra::Operator<Scalar,LO,GO,Node>& Op,
00724            const Tpetra::MultiVector<Scalar,LO,GO,Node>& X,
00725            Tpetra::MultiVector<Scalar,LO,GO,Node>& Y)
00726     {
00727       Op.apply (X, Y, Teuchos::NO_TRANS);
00728     }
00729   };
00730 
00731 } // end of Anasazi namespace
00732 
00733 #endif
00734 // end of file ANASAZI_TPETRA_ADAPTER_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends