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_ADDED_LINEAR_OP_HPP
00030 #define THYRA_DEFAULT_ADDED_LINEAR_OP_HPP
00031
00032 #include "Thyra_DefaultAddedLinearOpDecl.hpp"
00033 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00034 #include "Thyra_AssertOp.hpp"
00035 #include "Teuchos_Utils.hpp"
00036
00037 namespace Thyra {
00038
00039
00040
00041 template<class Scalar>
00042 DefaultAddedLinearOp<Scalar>::DefaultAddedLinearOp()
00043 {}
00044
00045 template<class Scalar>
00046 DefaultAddedLinearOp<Scalar>::DefaultAddedLinearOp(
00047 const int numOps
00048 ,const RCP<LinearOpBase<Scalar> > Ops[]
00049 )
00050 {
00051 initialize(numOps,Ops);
00052 }
00053
00054 template<class Scalar>
00055 DefaultAddedLinearOp<Scalar>::DefaultAddedLinearOp(
00056 const int numOps
00057 ,const RCP<const LinearOpBase<Scalar> > Ops[]
00058 )
00059 {
00060 initialize(numOps,Ops);
00061 }
00062
00063 template<class Scalar>
00064 void DefaultAddedLinearOp<Scalar>::initialize(
00065 const int numOps
00066 ,const RCP<LinearOpBase<Scalar> > Ops[]
00067 )
00068 {
00069 #ifdef TEUCHOS_DEBUG
00070 TEST_FOR_EXCEPT( numOps <= 0 || Ops == NULL );
00071 #endif
00072 Ops_.resize(numOps);
00073 for( int k = 0; k < numOps; ++k )
00074 Ops_[k].initialize(Ops[k]);
00075 validateOps();
00076 setupDefaultObjectLabel();
00077 }
00078
00079 template<class Scalar>
00080 void DefaultAddedLinearOp<Scalar>::initialize(
00081 const int numOps
00082 ,const RCP<const LinearOpBase<Scalar> > Ops[]
00083 )
00084 {
00085 #ifdef TEUCHOS_DEBUG
00086 TEST_FOR_EXCEPT( numOps <= 0 || Ops == NULL );
00087 #endif
00088 Ops_.resize(numOps);
00089 for( int k = 0; k < numOps; ++k )
00090 Ops_[k].initialize(Ops[k]);
00091 validateOps();
00092 setupDefaultObjectLabel();
00093 }
00094
00095 template<class Scalar>
00096 void DefaultAddedLinearOp<Scalar>::uninitialize()
00097 {
00098 Ops_.resize(0);
00099 setupDefaultObjectLabel();
00100 }
00101
00102
00103
00104 template<class Scalar>
00105 int DefaultAddedLinearOp<Scalar>::numOps() const
00106 {
00107 return Ops_.size();
00108 }
00109
00110 template<class Scalar>
00111 bool DefaultAddedLinearOp<Scalar>::opIsConst(const int k) const
00112 {
00113 #ifdef TEUCHOS_DEBUG
00114 TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
00115 #endif
00116 return Ops_[k].isConst();
00117 }
00118
00119 template<class Scalar>
00120 Teuchos::RCP<LinearOpBase<Scalar> >
00121 DefaultAddedLinearOp<Scalar>::getNonconstOp(const int k)
00122 {
00123 #ifdef TEUCHOS_DEBUG
00124 TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
00125 #endif
00126 return Ops_[k].getNonconstObj();
00127 }
00128
00129 template<class Scalar>
00130 Teuchos::RCP<const LinearOpBase<Scalar> >
00131 DefaultAddedLinearOp<Scalar>::getOp(const int k) const
00132 {
00133 #ifdef TEUCHOS_DEBUG
00134 TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
00135 #endif
00136 return Ops_[k];
00137 }
00138
00139
00140
00141 template<class Scalar>
00142 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00143 DefaultAddedLinearOp<Scalar>::range() const
00144 {
00145 assertInitialized();
00146 return getOp(0)->range();
00147 }
00148
00149 template<class Scalar>
00150 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00151 DefaultAddedLinearOp<Scalar>::domain() const
00152 {
00153 assertInitialized();
00154 return getOp(numOps()-1)->domain();
00155 }
00156
00157 template<class Scalar>
00158 Teuchos::RCP<const LinearOpBase<Scalar> >
00159 DefaultAddedLinearOp<Scalar>::clone() const
00160 {
00161 return Teuchos::null;
00162 }
00163
00164
00165
00166 template<class Scalar>
00167 std::string DefaultAddedLinearOp<Scalar>::description() const
00168 {
00169 assertInitialized();
00170 std::ostringstream oss;
00171 oss << Teuchos::Describable::description() << "{numOps = "<<numOps()<<"}";
00172 return oss.str();
00173 }
00174
00175 template<class Scalar>
00176 void DefaultAddedLinearOp<Scalar>::describe(
00177 Teuchos::FancyOStream &out_arg
00178 ,const Teuchos::EVerbosityLevel verbLevel
00179 ) const
00180 {
00181 typedef Teuchos::ScalarTraits<Scalar> ST;
00182 using Teuchos::RCP;
00183 using Teuchos::FancyOStream;
00184 using Teuchos::OSTab;
00185 assertInitialized();
00186 RCP<FancyOStream> out = rcp(&out_arg,false);
00187 OSTab tab(out);
00188 const int numOps = Ops_.size();
00189 switch(verbLevel) {
00190 case Teuchos::VERB_DEFAULT:
00191 case Teuchos::VERB_LOW:
00192 *out << this->description() << std::endl;
00193 break;
00194 case Teuchos::VERB_MEDIUM:
00195 case Teuchos::VERB_HIGH:
00196 case Teuchos::VERB_EXTREME:
00197 {
00198 *out
00199 << Teuchos::Describable::description() << "{"
00200 << "rangeDim=" << this->range()->dim()
00201 << ",domainDim="<< this->domain()->dim() << "}\n";
00202 OSTab tab(out);
00203 *out
00204 << "numOps="<< numOps << std::endl
00205 << "Constituent LinearOpBase objects for M = Op[0]*...*Op[numOps-1]:\n";
00206 tab.incrTab();
00207 for( int k = 0; k < numOps; ++k ) {
00208 *out << "Op["<<k<<"] = " << Teuchos::describe(*getOp(k),verbLevel);
00209 }
00210 break;
00211 }
00212 default:
00213 TEST_FOR_EXCEPT(true);
00214 }
00215 }
00216
00217
00218
00219
00220
00221 template<class Scalar>
00222 bool DefaultAddedLinearOp<Scalar>::opSupported(EOpTransp M_trans) const
00223 {
00224 bool opSupported = true;
00225 for( int k = 0; k < static_cast<int>(Ops_.size()); ++k )
00226 if(!Thyra::opSupported(*getOp(k),M_trans)) opSupported = false;
00227 return opSupported;
00228
00229 }
00230
00231 template<class Scalar>
00232 void DefaultAddedLinearOp<Scalar>::apply(
00233 const EOpTransp M_trans
00234 ,const MultiVectorBase<Scalar> &X
00235 ,MultiVectorBase<Scalar> *Y
00236 ,const Scalar alpha
00237 ,const Scalar beta
00238 ) const
00239 {
00240 typedef Teuchos::ScalarTraits<Scalar> ST;
00241 #ifdef TEUCHOS_DEBUG
00242 THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(
00243 "DefaultAddedLinearOp<Scalar>::apply(...)",*this,M_trans,X,Y
00244 );
00245 #endif // TEUCHOS_DEBUG
00246
00247
00248
00249
00250
00251
00252
00253 const int numOps = Ops_.size();
00254 for( int j = 0; j < numOps; ++j )
00255 Thyra::apply(*getOp(j),M_trans,X,Y,alpha,j==0?beta:ST::one());
00256 }
00257
00258
00259
00260
00261
00262 template<class Scalar>
00263 void DefaultAddedLinearOp<Scalar>::validateOps()
00264 {
00265 typedef std::string s;
00266 using Teuchos::toString;
00267 #ifdef TEUCHOS_DEBUG
00268 try {
00269 const int numOps = Ops_.size();
00270 for( int k = 0; k < numOps; ++k ) {
00271 TEST_FOR_EXCEPT( Ops_[k]().get() == NULL );
00272 if( k > 0 ) {
00273 THYRA_ASSERT_LINEAR_OP_PLUS_LINEAR_OP_SPACES_NAMES(
00274 "DefaultMultipliedLinearOp<Scalar>::initialize(...)"
00275 ,*Ops_[0], NOTRANS, ("Ops[0]")
00276 ,*Ops_[k], NOTRANS, ("Ops["+toString(k)+"]")
00277 );
00278 }
00279 }
00280 }
00281 catch(...) {
00282 uninitialize();
00283 throw;
00284 }
00285 #endif
00286 }
00287
00288
00289 template<class Scalar>
00290 void DefaultAddedLinearOp<Scalar>::setupDefaultObjectLabel()
00291 {
00292 std::ostringstream label;
00293 const int numOps = Ops_.size();
00294 for( int k = 0; k < numOps; ++k ) {
00295 std::string Op_k_label = Ops_[k]->getObjectLabel();
00296 if (Op_k_label.length() == 0)
00297 Op_k_label = "ANYM";
00298 if (k > 0)
00299 label << "+";
00300 label << "("<<Op_k_label<<")";
00301 }
00302 this->setObjectLabel(label.str());
00303 validateOps();
00304 }
00305
00306
00307 }
00308
00309
00310 template<class Scalar>
00311 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00312 Thyra::nonconstAdd(
00313 const RCP<LinearOpBase<Scalar> > &A,
00314 const RCP<LinearOpBase<Scalar> > &B,
00315 const std::string &label
00316 )
00317 {
00318 using Teuchos::arrayArg;
00319 RCP<LinearOpBase<Scalar> >
00320 alo = Teuchos::rcp(
00321 new DefaultAddedLinearOp<Scalar>(
00322 2
00323 ,arrayArg<RCP<LinearOpBase<Scalar> > >(A,B)()
00324 )
00325 );
00326 if (label.length())
00327 alo->setObjectLabel(label);
00328 return alo;
00329 }
00330
00331
00332 template<class Scalar>
00333 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00334 Thyra::add(
00335 const RCP<const LinearOpBase<Scalar> > &A,
00336 const RCP<const LinearOpBase<Scalar> > &B,
00337 const std::string &label
00338 )
00339 {
00340 using Teuchos::arrayArg;
00341 RCP<LinearOpBase<Scalar> >
00342 alo = Teuchos::rcp(
00343 new DefaultAddedLinearOp<Scalar>(
00344 2
00345 ,arrayArg<RCP<const LinearOpBase<Scalar> > >(A,B)()
00346 )
00347 );
00348 if (label.length())
00349 alo->setObjectLabel(label);
00350 return alo;
00351 }
00352
00353
00354 template<class Scalar>
00355 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00356 Thyra::nonconstSubtract(
00357 const RCP<LinearOpBase<Scalar> > &A,
00358 const RCP<LinearOpBase<Scalar> > &B,
00359 const std::string &label
00360 )
00361 {
00362 typedef ScalarTraits<Scalar> ST;
00363 using Teuchos::arrayArg;
00364 RCP<LinearOpBase<Scalar> >
00365 alo = Teuchos::rcp(
00366 new DefaultAddedLinearOp<Scalar>(
00367 2,
00368 arrayArg<RCP<LinearOpBase<Scalar> > >(
00369 A, scale<Scalar>(-ST::one(),B) )()
00370 )
00371 );
00372 if (label.length())
00373 alo->setObjectLabel(label);
00374 return alo;
00375 }
00376
00377
00378 template<class Scalar>
00379 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00380 Thyra::subtract(
00381 const RCP<const LinearOpBase<Scalar> > &A,
00382 const RCP<const LinearOpBase<Scalar> > &B,
00383 const std::string &label
00384 )
00385 {
00386 typedef ScalarTraits<Scalar> ST;
00387 using Teuchos::arrayArg;
00388 RCP<LinearOpBase<Scalar> >
00389 alo = Teuchos::rcp(
00390 new DefaultAddedLinearOp<Scalar>(
00391 2,
00392 arrayArg<RCP<const LinearOpBase<Scalar> > >(
00393 A, scale<Scalar>(-ST::one(),B) )()
00394 )
00395 );
00396 if (label.length())
00397 alo->setObjectLabel(label);
00398 return alo;
00399 }
00400
00401
00402
00403 #endif // THYRA_DEFAULT_ADDED_LINEAR_OP_HPP