00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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
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;
00150 }
00151
00152
00153
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);
00204 }
00205 }
00206
00207
00208
00209
00210
00211
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
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
00245
00246
00247
00248 RCP<MultiVectorBase<Scalar> > T_kp1, T_k;
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
00264
00265
00266
00267 RCP<MultiVectorBase<Scalar> > T_km1, T_k;
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
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 }
00331
00332
00333
00334
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
00391
00392
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