Thyra_DefaultMultipliedLinearOp_def.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_DEF_HPP
00030 #define THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_DEF_HPP
00031 
00032 #include "Thyra_DefaultMultipliedLinearOp_decl.hpp"
00033 #include "Thyra_AssertOp.hpp"
00034 #include "Teuchos_Utils.hpp"
00035 
00036 
00037 namespace Thyra {
00038 
00039 
00040 // Constructors/initializers/accessors
00041 
00042 
00043 template<class Scalar>
00044 DefaultMultipliedLinearOp<Scalar>::DefaultMultipliedLinearOp()
00045 {}
00046 
00047 
00048 template<class Scalar>
00049 void DefaultMultipliedLinearOp<Scalar>::initialize(
00050   const ArrayView<const RCP<LinearOpBase<Scalar> > > &Ops )
00051 {
00052   const int nOps = Ops.size();
00053   Ops_.resize(nOps);
00054   for( int k = 0; k < nOps; ++k )
00055     Ops_[k].initialize(Ops[k]);
00056   validateOps();
00057   setupDefaultObjectLabel();
00058 }
00059 
00060 
00061 template<class Scalar>
00062 void DefaultMultipliedLinearOp<Scalar>::initialize(
00063   const ArrayView<const RCP<const LinearOpBase<Scalar> > > &Ops )
00064 {
00065   const int nOps = Ops.size();
00066   Ops_.resize(nOps);
00067   for( int k = 0; k < nOps; ++k )
00068     Ops_[k].initialize(Ops[k]);
00069   validateOps();
00070   setupDefaultObjectLabel();
00071 }
00072 
00073 
00074 template<class Scalar>
00075 void DefaultMultipliedLinearOp<Scalar>::uninitialize()
00076 {
00077   Ops_.resize(0);
00078   setupDefaultObjectLabel();
00079 }
00080 
00081 
00082 // Overridden form MultipliedLinearOpBase
00083 
00084 
00085 template<class Scalar>
00086 int DefaultMultipliedLinearOp<Scalar>::numOps() const
00087 {
00088   return Ops_.size();
00089 }
00090 
00091 
00092 template<class Scalar>
00093 bool DefaultMultipliedLinearOp<Scalar>::opIsConst(const int k) const
00094 {
00095 #ifdef TEUCHOS_DEBUG
00096   TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
00097 #endif
00098   return Ops_[k].isConst();
00099 }
00100 
00101 
00102 template<class Scalar>
00103 RCP<LinearOpBase<Scalar> >
00104 DefaultMultipliedLinearOp<Scalar>::getNonconstOp(const int k)
00105 {
00106 #ifdef TEUCHOS_DEBUG
00107   TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
00108 #endif
00109   return Ops_[k].getNonconstObj();
00110 }
00111 
00112 
00113 template<class Scalar>
00114 RCP<const LinearOpBase<Scalar> >
00115 DefaultMultipliedLinearOp<Scalar>::getOp(const int k) const
00116 {
00117 #ifdef TEUCHOS_DEBUG
00118   TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
00119 #endif
00120   return Ops_[k];
00121 }
00122 
00123 
00124 // Overridden from LinearOpBase
00125 
00126 
00127 template<class Scalar>
00128 RCP< const VectorSpaceBase<Scalar> >
00129 DefaultMultipliedLinearOp<Scalar>::range() const
00130 {
00131   assertInitialized();
00132   return getOp(0)->range();
00133 }
00134 
00135 
00136 template<class Scalar>
00137 RCP< const VectorSpaceBase<Scalar> >
00138 DefaultMultipliedLinearOp<Scalar>::domain() const
00139 {
00140   assertInitialized();
00141   return getOp(numOps()-1)->domain();
00142 }
00143 
00144 
00145 template<class Scalar>
00146 RCP<const LinearOpBase<Scalar> >
00147 DefaultMultipliedLinearOp<Scalar>::clone() const
00148 {
00149   return Teuchos::null; // Not supported yet but could be!
00150 }
00151 
00152 
00153 // Overridden from Teuchos::Describable
00154 
00155                                                 
00156 template<class Scalar>
00157 std::string DefaultMultipliedLinearOp<Scalar>::description() const
00158 {
00159   assertInitialized();
00160   typedef Teuchos::ScalarTraits<Scalar>  ST;
00161   std::ostringstream oss;
00162   oss << Teuchos::Describable::description() << "{numOps = "<<numOps()<<"}";
00163   return oss.str();
00164 }
00165 
00166 template<class Scalar>
00167 void DefaultMultipliedLinearOp<Scalar>::describe(
00168   Teuchos::FancyOStream                &out_arg
00169   ,const Teuchos::EVerbosityLevel      verbLevel
00170   ) const
00171 {
00172   typedef Teuchos::ScalarTraits<Scalar>  ST;
00173   using Teuchos::FancyOStream;
00174   using Teuchos::OSTab;
00175   assertInitialized();
00176   RCP<FancyOStream> out = rcp(&out_arg,false);
00177   OSTab tab(out);
00178   const int nOps = Ops_.size();
00179   switch(verbLevel) {
00180     case Teuchos::VERB_DEFAULT:
00181     case Teuchos::VERB_LOW:
00182       *out << this->description() << std::endl;
00183       break;
00184     case Teuchos::VERB_MEDIUM:
00185     case Teuchos::VERB_HIGH:
00186     case Teuchos::VERB_EXTREME:
00187     {
00188       *out
00189         << Teuchos::Describable::description() << "{"
00190         << "rangeDim=" << this->range()->dim()
00191         << ",domainDim="<< this->domain()->dim() << "}\n";
00192       OSTab tab2(out);
00193       *out
00194         <<  "numOps = "<< nOps << std::endl
00195         <<  "Constituent LinearOpBase objects for M = Op[0]*...*Op[numOps-1]:\n";
00196       OSTab tab3(out);
00197       for( int k = 0; k < nOps; ++k ) {
00198         *out << "Op["<<k<<"] = " << Teuchos::describe(*getOp(k),verbLevel);
00199       }
00200       break;
00201     }
00202     default:
00203       TEST_FOR_EXCEPT(true); // Should never get here!
00204   }
00205 }
00206 
00207 
00208 // protected
00209 
00210 
00211 // Overridden from SingleScalarLinearOpBase
00212 
00213 
00214 template<class Scalar>
00215 bool DefaultMultipliedLinearOp<Scalar>::opSupported(EOpTransp M_trans) const
00216 {
00217   bool overallOpSupported = true;
00218   for( int k = 0; k < static_cast<int>(Ops_.size()); ++k )
00219     if(!Thyra::opSupported(*getOp(k),M_trans)) overallOpSupported = false;
00220   return overallOpSupported;
00221   // ToDo: Cache these?
00222 }
00223 
00224 
00225 template<class Scalar>
00226 void DefaultMultipliedLinearOp<Scalar>::apply(
00227   const EOpTransp                     M_trans
00228   ,const MultiVectorBase<Scalar>    &X
00229   ,MultiVectorBase<Scalar>          *Y
00230   ,const Scalar                     alpha
00231   ,const Scalar                     beta
00232   ) const
00233 {
00234   using Teuchos::rcp;
00235 #ifdef TEUCHOS_DEBUG
00236   THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(
00237     "DefaultMultipliedLinearOp<Scalar>::apply(...)",*this,M_trans,X,Y
00238     );
00239 #endif // TEUCHOS_DEBUG  
00240   const int nOps = Ops_.size();
00241   const Index m = X.domain()->dim();
00242   if( real_trans(M_trans)==NOTRANS ) {
00243     //
00244     // Y = alpha * M * X + beta*Y
00245     // =>
00246     // Y = alpha * op(Op[0]) * op(Op[1]) * ... * op(Op[numOps-1]) * X + beta*Y
00247     //
00248     RCP<MultiVectorBase<Scalar> > T_kp1, T_k; // Temporary propagated between loops 
00249     for( int k = nOps-1; k >= 0; --k ) {
00250       RCP<MultiVectorBase<Scalar> >         Y_k;
00251       RCP<const MultiVectorBase<Scalar> >   X_k;
00252       if(k==0)        Y_k = rcp(Y,false);  else Y_k = T_k = createMembers(getOp(k)->range(),m);
00253       if(k==nOps-1) X_k = rcp(&X,false); else X_k = T_kp1;
00254       if( k > 0 )
00255         Thyra::apply(*getOp(k),M_trans,*X_k,&*Y_k);
00256       else
00257         Thyra::apply(*getOp(k),M_trans,*X_k,&*Y_k,alpha,beta);
00258       T_kp1 = T_k;
00259     }
00260   }
00261   else {
00262     //
00263     // Y = alpha * M' * X + beta*Y
00264     // =>
00265     // Y = alpha * Op[numOps-1]' * Op[1]' * ... * Op[0]' * X + beta * Y
00266     //
00267     RCP<MultiVectorBase<Scalar> > T_km1, T_k; // Temporary propagated between loops 
00268     for( int k = 0; k <= nOps-1; ++k ) {
00269       RCP<MultiVectorBase<Scalar> >         Y_k;
00270       RCP<const MultiVectorBase<Scalar> >   X_k;
00271       if(k==nOps-1)   Y_k = rcp(Y,false);  else Y_k = T_k = createMembers(getOp(k)->domain(),m);
00272       if(k==0)          X_k = rcp(&X,false); else X_k = T_km1;
00273       if( k < nOps-1 )
00274         Thyra::apply(*getOp(k),M_trans,*X_k,&*Y_k);
00275       else
00276         Thyra::apply(*getOp(k),M_trans,*X_k,&*Y_k,alpha,beta);
00277       T_km1 = T_k;
00278     }
00279   }
00280 }
00281 
00282 
00283 // private
00284 
00285 
00286 template<class Scalar>
00287 void DefaultMultipliedLinearOp<Scalar>::validateOps()
00288 {
00289   using Teuchos::toString;
00290 #ifdef TEUCHOS_DEBUG
00291   try {
00292     const int nOps = Ops_.size();
00293     for( int k = 0; k < nOps; ++k ) {
00294       TEST_FOR_EXCEPT( Ops_[k]().get() == NULL );
00295       if( k < nOps-1 ) {
00296         THYRA_ASSERT_LINEAR_OP_TIMES_LINEAR_OP_SPACES_NAMES(
00297           "DefaultMultipliedLinearOp<Scalar>::initialize(...)"
00298           ,*Ops_[k],NOTRANS,("Ops["+toString(k)+"]")
00299           ,*Ops_[k+1],NOTRANS,("Ops["+toString(k+1)+"]")
00300           );
00301       }
00302     }
00303   }
00304   catch(...) {
00305     uninitialize();
00306     throw;
00307   }
00308 #endif
00309 }
00310 
00311 
00312 template<class Scalar>
00313 void DefaultMultipliedLinearOp<Scalar>::setupDefaultObjectLabel()
00314 {
00315   std::ostringstream label;
00316   const int nOps = Ops_.size();
00317   for( int k = 0; k < nOps; ++k ) {
00318     std::string Op_k_label = Ops_[k]->getObjectLabel();
00319     if (Op_k_label.length() == 0)
00320       Op_k_label = "ANYM";
00321     if (k > 0)
00322       label << "*";
00323     label << "("<<Op_k_label<<")";
00324   }
00325   this->setObjectLabel(label.str());
00326   validateOps();
00327 }
00328 
00329 
00330 } // end namespace Thyra
00331 
00332 
00333 //
00334 // Nonmember implementations
00335 //
00336 
00337 template<class Scalar>
00338 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00339 Thyra::nonconstMultiply(
00340   const RCP<LinearOpBase<Scalar> > &A,
00341   const RCP<LinearOpBase<Scalar> > &B,
00342   const std::string &M_label
00343   )
00344 {
00345   using Teuchos::tuple;
00346   RCP<DefaultMultipliedLinearOp<Scalar> > multOp = defaultMultipliedLinearOp<Scalar>();
00347   multOp->initialize(tuple(A,B)());
00348   if(M_label.length())
00349     multOp->setObjectLabel(M_label);
00350   return multOp;
00351 }
00352 
00353 
00354 template<class Scalar>
00355 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00356 Thyra::multiply(
00357   const RCP<const LinearOpBase<Scalar> > &A,
00358   const RCP<const LinearOpBase<Scalar> > &B,
00359   const std::string &M_label
00360   )
00361 {
00362   using Teuchos::tuple;
00363   RCP<DefaultMultipliedLinearOp<Scalar> > multOp = defaultMultipliedLinearOp<Scalar>();
00364   multOp->initialize(tuple(A,B)());
00365   if(M_label.length())
00366     multOp->setObjectLabel(M_label);
00367   return multOp;
00368 }
00369 
00370 
00371 template<class Scalar>
00372 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00373 Thyra::multiply(
00374   const RCP<const LinearOpBase<Scalar> > &A,
00375   const RCP<const LinearOpBase<Scalar> > &B,
00376   const RCP<const LinearOpBase<Scalar> > &C,
00377   const std::string &M_label
00378   )
00379 {
00380   using Teuchos::tuple;
00381   RCP<DefaultMultipliedLinearOp<Scalar> > multOp = defaultMultipliedLinearOp<Scalar>();
00382   multOp->initialize(tuple(A,B,C)());
00383   if(M_label.length())
00384     multOp->setObjectLabel(M_label);
00385   return multOp;
00386 }
00387 
00388 
00389 //
00390 // Explicit instantiation macro
00391 //
00392 // Must be expanded from within the Thyra namespace!
00393 //
00394 
00395 
00396 #define THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_INSTANT(SCALAR) \
00397   \
00398   template class DefaultMultipliedLinearOp<SCALAR >; \
00399  \
00400   template RCP<LinearOpBase<SCALAR > > \
00401   nonconstMultiply( \
00402     const RCP<LinearOpBase<SCALAR > > &A, \
00403     const RCP<LinearOpBase<SCALAR > > &B, \
00404     const std::string &M_label \
00405     ); \
00406    \
00407   template RCP<const LinearOpBase<SCALAR > > \
00408   multiply( \
00409     const RCP<const LinearOpBase<SCALAR > > &A, \
00410     const RCP<const LinearOpBase<SCALAR > > &B, \
00411     const std::string &M_label \
00412     ); \
00413    \
00414   template RCP<const LinearOpBase<SCALAR > > \
00415   multiply( \
00416     const RCP<const LinearOpBase<SCALAR > > &A, \
00417     const RCP<const LinearOpBase<SCALAR > > &B, \
00418     const RCP<const LinearOpBase<SCALAR > > &C, \
00419     const std::string &M_label \
00420     );
00421 
00422 
00423 #endif  // THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_DEF_HPP

Generated on Wed May 12 21:26:54 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7