PlayaAnasaziAdapter.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                 Playa: Programmable Linear Algebra
00005 //                 Copyright 2012 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #ifndef ANASAZI_PLAYA_ADAPTER_HPP
00043 #define ANASAZI_PLAYA_ADAPTER_HPP
00044 
00045 #include "AnasaziMultiVecTraits.hpp"
00046 #include "AnasaziOperatorTraits.hpp"
00047 #include "AnasaziConfigDefs.hpp"
00048 
00049 
00050 #include "PlayaVectorImpl.hpp"
00051 #include "PlayaLinearOperatorImpl.hpp"
00052 #include "PlayaSimpleTransposedOpImpl.hpp"
00053 #include "PlayaLinearCombinationImpl.hpp"
00054 
00055 #include "Teuchos_Array.hpp"
00056 #include "Teuchos_RCP.hpp"
00057 
00058 #include "PlayaTabs.hpp"
00059 
00060 namespace Anasazi 
00061 {
00062 using Playa::Vector;
00063 using Teuchos::RCP;
00064 using Teuchos::Array;
00065 
00066 class SimpleMV
00067 {
00068 public:
00069   SimpleMV() : data_() {}
00070 
00071   SimpleMV(int n) : data_(rcp(new Array<Vector<double> >(n))) {}
00072 
00073   SimpleMV(const Array<Vector<double> >& data) 
00074     : data_(rcp(new Array<Vector<double> >(data.size())))
00075     {
00076       for (int i=0; i<data.size(); i++)
00077       {
00078         (*data_)[i] = data[i].copy();
00079       }
00080     }
00081 
00082   SimpleMV clone() const
00083     {
00084       return SimpleMV(*data_);
00085     }
00086 
00087   Vector<double>& operator[](int i) {return (*data_)[i];}
00088 
00089   const Vector<double>& operator[](int i) const {return (*data_)[i];}
00090 
00091   int size() const {return data_->size();}
00092 
00093   void resize(int n)
00094     {
00095       data_->resize(n);
00096     }
00097 
00098   void randomize() 
00099     {
00100       for (int i=0; i<size(); i++) (*data_)[i].randomize();
00101     }
00102   
00103 private:
00104   RCP<Array<Vector<double> > > data_;
00105 };
00106 
00107 
00108 
00109 inline std::ostream& operator<<(std::ostream& os, const SimpleMV& mv)
00110 {
00111   os << "MV (size=" << mv.size() << ")" << std::endl;
00112   for (int i=0; i<mv.size(); i++)
00113   {
00114     os << "ptr=" << mv[i].ptr().get() << std::endl;
00115     os << mv[i] << std::endl;
00116   }
00117 
00118   return os;
00119 }
00120 
00121 /** */
00122 template<>
00123 class MultiVecTraits<double, SimpleMV >
00124 {
00125 public:
00126   typedef SimpleMV _MV;
00127   typedef Teuchos::ScalarTraits<double> SCT;
00128 
00129   static double one() {static double rtn = SCT::one(); return rtn;}
00130   static double zero() {static double rtn = SCT::zero(); return rtn;}
00131 
00132   /** \name Creation methods */
00133   //@{
00134 
00135   /**
00136    */
00137   static RCP<_MV> Clone( const  _MV & mv, const int numvecs )
00138     { 
00139       //Out::os() << "Clone(nv == " << numvecs << ")" << endl;
00140       TEUCHOS_TEST_FOR_EXCEPT(mv.size() <= 0);
00141       TEUCHOS_TEST_FOR_EXCEPT(numvecs <= 0);
00142 
00143       RCP<_MV> rtn = rcp(new _MV(numvecs));
00144       for (int i=0; i<numvecs; i++)
00145       {
00146         (*rtn)[i] = mv[0].copy();
00147         (*rtn)[i].setToConstant(zero());
00148       }
00149       return rtn;
00150     }
00151 
00152   /**
00153    *
00154    */
00155   static RCP< _MV > CloneCopy( const  _MV & mv )
00156     { 
00157       //Out::os() << "CloneCopy()" << endl;
00158       int numvecs = mv.size();
00159       TEUCHOS_TEST_FOR_EXCEPT(numvecs <= 0);
00160 
00161       // create the new multivector
00162       RCP<_MV> rtn = rcp(new _MV(numvecs));
00163       for (int i=0; i<numvecs; i++)
00164       {
00165         (*rtn)[i] = mv[i].copy();
00166       }
00167       return rtn;
00168     }
00169 
00170   /** 
00171       
00172   */
00173   static RCP< _MV > CloneCopy( const  _MV & mv, const std::vector<int>& index )
00174     { 
00175       //Out::os() << "CloneCopy() indexed" << endl;
00176       int numvecs = index.size();
00177       TEUCHOS_TEST_FOR_EXCEPT(numvecs <= 0);
00178       TEUCHOS_TEST_FOR_EXCEPT((int) index.size() > mv.size());
00179 
00180 //      TEUCHOS_TEST_FOR_EXCEPT(detectRepeatedIndex(index));
00181 
00182       // create the new multivector
00183       RCP<  _MV  > rtn = rcp(new _MV(numvecs));
00184 
00185       for (int i=0; i<numvecs; i++)
00186       {
00187         (*rtn)[i] = mv[index[i]].copy();
00188       }
00189       return rtn;
00190     }
00191 
00192   /**
00193 
00194   */      
00195   static RCP< _MV > CloneViewNonConst(  _MV & mv, const std::vector<int>& index )
00196     {
00197       int numvecs = index.size();
00198       //Out::os() << "index.size() = " << numvecs << endl;
00199       //Out::os() << "input size = " << mv.size() << endl;
00200       TEUCHOS_TEST_FOR_EXCEPT(numvecs <= 0);
00201       TEUCHOS_TEST_FOR_EXCEPT((int) index.size() > mv.size());
00202 
00203 //      TEUCHOS_TEST_FOR_EXCEPT(detectRepeatedIndex(index));
00204 
00205       // create the new multivector
00206       RCP<  _MV  > rtn = rcp(new _MV(numvecs));
00207 
00208       for (int i=0; i<numvecs; i++)
00209       {
00210         (*rtn)[i] = mv[index[i]]; // shallow copy
00211       }
00212 
00213       return rtn;
00214     }
00215 
00216   static RCP<_MV> 
00217   CloneViewNonConst (_MV & mv, const Teuchos::Range1D& index) 
00218   {
00219     typedef std::vector<int>::size_type size_type;
00220     std::vector<int> ind (index.size ());
00221     for (size_type i = 0; i < static_cast<size_type> (index.size ()); ++i) {
00222       ind[i] = index.lbound () + i;
00223     }
00224     return CloneViewNonConst (mv, ind);
00225   }
00226 
00227   /**
00228    *
00229    */      
00230   static RCP<const _MV > CloneView( const _MV & mv, const std::vector<int>& index )
00231     {
00232       //Out::os() << "CloneView()" << endl;
00233       int numvecs = index.size();
00234       //Out::os() << "index size = " << numvecs << endl;
00235       //Out::os() << "input size = " << mv.size() << endl;
00236       TEUCHOS_TEST_FOR_EXCEPT(numvecs <= 0);
00237       TEUCHOS_TEST_FOR_EXCEPT((int) index.size() > mv.size());
00238 
00239 //      TEUCHOS_TEST_FOR_EXCEPT(detectRepeatedIndex(index));
00240 
00241       // create the new multivector
00242       RCP<  const _MV  > rtn = rcp(new _MV(numvecs));
00243 
00244       for (int i=0; i<numvecs; i++)
00245       {
00246         (*(rcp_const_cast<_MV>(rtn)))[i] = mv[index[i]]; // shallow copy
00247       }
00248       return rtn;
00249     }
00250 
00251   static RCP<const _MV> 
00252   CloneView (const _MV & mv, const Teuchos::Range1D& index) 
00253   {
00254     typedef std::vector<int>::size_type size_type;
00255     std::vector<int> ind (index.size ());
00256     for (size_type i = 0; i < static_cast<size_type> (index.size ()); ++i) {
00257       ind[i] = index.lbound () + i;
00258     }
00259     return CloneView (mv, ind);
00260   }
00261 
00262   //@}
00263 
00264   /** \name Attribute methods */
00265   //@{
00266 
00267   /** Obtain the vector length of \c mv. */
00268   static int GetVecLength( const  _MV & mv )
00269     {
00270       TEUCHOS_TEST_FOR_EXCEPT(mv.size() <= 0);
00271       return mv[0].space().dim(); 
00272     }
00273 
00274   /** Obtain the number of vectors in \c mv */
00275   static int GetNumberVecs( const  _MV & mv )
00276     {
00277       //Out::os() << "GetNumVec(" << mv.size() << ")" << endl;
00278       return mv.size(); 
00279     }
00280 
00281   //@}
00282 
00283   /** \name Update methods */
00284   //@{
00285 
00286   /*! \brief Update \c mv with \f$ \alpha A B + \beta mv \f$.
00287    */
00288   static void MvTimesMatAddMv( const double alpha, const  _MV & A, 
00289     const Teuchos::SerialDenseMatrix<int,double>& B, 
00290     const double beta,  _MV & mv )
00291     {
00292 //      Out::os() << "MvTimesMatAddMv()" << endl;
00293       int n = B.numCols();
00294 //      Out::os() << "B.numCols()=" << n << endl;
00295 
00296       TEUCHOS_TEST_FOR_EXCEPT(mv.size() != n);
00297 
00298       for (int j=0; j<mv.size(); j++)
00299       {
00300         Vector<double> tmp;
00301         if (beta==one())
00302         {
00303           tmp = mv[j].copy();
00304         }
00305         else if (beta==zero())
00306         {
00307           tmp = mv[j].copy();
00308           tmp.setToConstant(zero());
00309         }
00310         else
00311         {
00312           tmp = beta * mv[j];
00313         }
00314         if (alpha != zero())
00315         {
00316           for (int i=0; i<A.size(); i++)
00317           {
00318             tmp = tmp + alpha*B(i,j)*A[i];
00319           }
00320         }
00321         mv[j].acceptCopyOf(tmp);
00322       }
00323     }
00324 
00325   /*! \brief Replace \c mv with \f$\alpha A + \beta B\f$.
00326    */
00327   static void MvAddMv( const double alpha, const  _MV & A, 
00328     const double beta,  const  _MV & B,  _MV & mv )
00329     { 
00330       TEUCHOS_TEST_FOR_EXCEPT(A.size() != B.size());
00331       mv.resize(A.size());
00332       for (int i=0; i<A.size(); i++)
00333       {
00334         if (alpha==zero() && beta != zero()) mv[i]=beta*B[i];
00335         else if (beta==zero() && alpha != zero()) mv[i]=alpha*A[i];
00336         else if (alpha!=zero() && beta!=zero())
00337           mv[i]= alpha*A[i] + beta*B[i] ;
00338         else
00339         {
00340           mv[i].acceptCopyOf(A[i]);
00341           mv[i].setToConstant(zero());
00342         }
00343       }
00344     }
00345 
00346   /*! \brief Compute a dense matrix \c B through the matrix-matrix multiply \f$ \alpha A^Tmv \f$.
00347    */
00348   static void MvTransMv( const double alpha, const  _MV & A, const  _MV & mv, 
00349     Teuchos::SerialDenseMatrix<int,double>& B )
00350     { 
00351       // Create a multivector to hold the result (m by n)
00352       int m = A.size();
00353       int n = mv.size();
00354 //      B.shape(m, n);
00355       //Out::os() << "m=" << m << ", n=" << n << endl;
00356       for (int i=0; i<m; i++)
00357       {
00358         for (int j=0; j<n; j++)
00359         {
00360           B(i,j) = alpha * (A[i] * mv[j]);
00361         }
00362       }
00363     
00364     }
00365 
00366   /**
00367    * Dot product
00368   */
00369   static void MvDot( const  _MV & mv, const  _MV & A, std::vector<double> &b )
00370     {
00371       //Out::os() << "MvDot()" << endl;
00372       TEUCHOS_TEST_FOR_EXCEPT(mv.size() != A.size());
00373       b.resize(A.size());
00374       for (int i=0; i<mv.size(); i++) 
00375         b[i] = mv[i] * A[i];
00376     }
00377 
00378   /** Scale each element of the vectors in \c *this with \c alpha.
00379    */
00380   static void MvScale (  _MV & mv, const double alpha )
00381     { 
00382       //Out::os() << "MvScale()" << endl;
00383       for (int i=0; i<mv.size(); i++) mv[i].scale(alpha);
00384     }
00385     
00386   /** Scale each element of the \c i-th vector in \c *this with \c alpha[i].
00387    */
00388   static void MvScale (  _MV & mv, const std::vector<double>& alpha ) 
00389     { 
00390       //Out::os() << "MvScale() vector" << endl;
00391       for (int i=0; i<mv.size(); i++) mv[i].scale(alpha[i]);
00392     }
00393     
00394   //@}
00395 
00396   /** \name Norm method */
00397   //@{
00398 
00399   /** Compute the 2-norm of each individual vector of \c mv. */
00400   static void MvNorm( const  _MV & mv, 
00401     std::vector<Teuchos::ScalarTraits<double>::magnitudeType> &normvec )
00402     { 
00403 //      Out::os() << "MvNorm()" << endl;
00404       normvec.resize(mv.size());
00405       for (int i=0; i<mv.size(); i++) 
00406       {
00407         normvec[i] = mv[i].norm2();
00408         //      Out::os() << "i=" << i << " |v|=" << normvec[i] << endl;
00409       }
00410       
00411     }
00412 
00413   //@}
00414 
00415   /** \name Initialization methods */
00416   //@{
00417 
00418   /*! \brief Copy the vectors in \c A to a set of vectors in \c mv indicated by the indices given in \c index.
00419    */
00420   static void SetBlock( const  _MV & A, const std::vector<int>& index,  _MV & mv )
00421     { 
00422       //Out::os() << "SetBlock()" << endl;
00423       TEUCHOS_TEST_FOR_EXCEPT(A.size() < (int) index.size());
00424 //      mv.resize(index.size());
00425 //      TEUCHOS_TEST_FOR_EXCEPT(detectRepeatedIndex(index));
00426       for (unsigned int i=0; i<index.size(); i++)
00427       {
00428         mv[index[i]].acceptCopyOf(A[i]);
00429       }
00430     }
00431 
00432   //! Replace the vectors in \c mv with random vectors.
00433   static void MvRandom(  _MV & mv )
00434     { 
00435       for (int i=0; i<mv.size(); i++) mv[i].randomize(); 
00436     }
00437 
00438   //! Assign (deep copy) A into mv.
00439   static void Assign( const _MV& A, _MV& mv ) {
00440     for (unsigned int i = 0; i < mv.size(); ++i) {
00441       mv[i].acceptCopyOf (A[i]);
00442     }
00443   }
00444 
00445   //! Replace each element of the vectors in \c mv with \c alpha.
00446   static void MvInit(  _MV & mv, double alpha = Teuchos::ScalarTraits<double>::zero() )
00447     { 
00448       //Out::os() << "MvInit()" << endl;
00449       for (int i=0; i<mv.size(); i++) mv[i].setToConstant(alpha); 
00450     }
00451 
00452   //@}
00453 
00454   /** \name Print method */
00455   //@{
00456 
00457   /** Print the \c mv multi-vector to the \c os output stream. */
00458   static void MvPrint( const  _MV & mv, std::ostream& os )
00459     { 
00460       os << mv << std::endl;
00461     }
00462 
00463   //@}
00464 
00465 #ifdef HAVE_ANASAZI_TSQR
00466   /// \typedef tsqr_adaptor_type
00467   /// \brief TSQR adapter for the multivector type SimpleMV.
00468   ///
00469   /// For now, we provide a "stub" implementation.  It has the right
00470   /// methods and typedefs, but its constructors and methods all throw
00471   /// std::logic_error.  If you plan to use TSQR in Anasazi (e.g.,
00472   /// through TsqrOrthoManager) with SimpleMV, you must implement a
00473   /// functional TSQR adapter for SimpleMV.  Please refer to
00474   /// Epetra::TsqrAdapter (for Epetra_MultiVector) or
00475   /// Tpetra::TsqrAdaptor (for Tpetra::MultiVector) for examples of
00476   /// how to implement a TSQR adapter.
00477   typedef Anasazi::details::StubTsqrAdapter<SimpleMV> tsqr_adaptor_type;
00478 #endif // HAVE_ANASAZI_TSQR
00479 
00480   /** */
00481   static bool detectRepeatedIndex(const std::vector<int>& index)
00482     {
00483       std::set<int> s;
00484       bool rtn = false;
00485 
00486       for (unsigned int i=0; i<index.size(); i++)
00487       {
00488         if (s.find(index[i]) != s.end())
00489         {
00490           //Out::os() << "detected repeated index " << index[i] << endl;
00491           rtn = true;
00492         }
00493         s.insert(index[i]);
00494       }
00495       
00496       return rtn;
00497     }
00498 
00499 };        
00500 
00501 
00502 /**
00503 
00504 */
00505 template <>  
00506 class OperatorTraits < double, SimpleMV, LinearOperator<double> >
00507 {
00508 public:
00509   typedef SimpleMV _MV;  
00510   /**
00511   */    
00512   static void Apply ( 
00513     const LinearOperator< double >& Op, 
00514     const  _MV & x,  
00515     _MV & y )
00516     {
00517       //Out::os() << "Apply()" << endl;
00518       y.resize(x.size());
00519       for (int i=0; i<x.size(); i++) 
00520       {
00521 //        y[i] = Op * x[i];
00522         y[i].acceptCopyOf(Op * x[i]);
00523 //        Out::os() << "i=" << i << " x=" << endl;
00524 //        Out::os() << x[i] << endl;
00525 //        Out::os() << "i=" << i << " y=" << endl;
00526 //        Out::os() << y[i] << endl;
00527 //        TEUCHOS_TEST_FOR_EXCEPT(x[i].norm2() < 1.0e-12);
00528       }
00529     }
00530     
00531 };
00532 
00533 
00534 
00535 } // end of Anasazi namespace 
00536 
00537 #endif 

Site Contact