Thyra_DefaultProductMultiVector.hpp

Go to the documentation of this file.
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_PRODUCT_MULTI_VECTOR_HPP
00030 #define THYRA_DEFAULT_PRODUCT_MULTI_VECTOR_HPP
00031 
00032 #include "Thyra_DefaultProductMultiVectorDecl.hpp"
00033 #include "Thyra_DefaultProductVectorSpace.hpp"
00034 #include "Thyra_DefaultProductVector.hpp"
00035 #include "Thyra_AssertOp.hpp"
00036 
00037 
00038 namespace Thyra {
00039 
00040 
00041 // Constructors/initializers/accessors
00042 
00043 
00044 template<class Scalar>
00045 DefaultProductMultiVector<Scalar>::DefaultProductMultiVector(
00046   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00047   const int numMembers
00048   )
00049   :numBlocks_(0)
00050 {
00051   initialize(productSpace,numMembers);
00052 }
00053 
00054 
00055 template<class Scalar>
00056 DefaultProductMultiVector<Scalar>::DefaultProductMultiVector(
00057   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00058   const Teuchos::RCP<MultiVectorBase<Scalar> > multiVecs[]
00059   )
00060   :numBlocks_(0)
00061 {
00062   initialize(productSpace,multiVecs);
00063 }
00064 
00065 
00066 template<class Scalar>
00067 DefaultProductMultiVector<Scalar>::DefaultProductMultiVector(
00068   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00069   const Teuchos::RCP<const MultiVectorBase<Scalar> > multiVecs[]
00070   )
00071   :numBlocks_(0)
00072 {
00073   initialize(productSpace,multiVecs);
00074 }
00075 
00076 
00077 template<class Scalar>
00078 void DefaultProductMultiVector<Scalar>::initialize(
00079   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00080   const int numMembers
00081   )
00082 {
00083 #ifdef TEUCHOS_DEBUG
00084   TEST_FOR_EXCEPT( is_null(productSpace) );
00085   TEST_FOR_EXCEPT( numMembers <= 0 );
00086 #endif
00087   Teuchos::Array<Teuchos::RCP<MultiVectorBase<Scalar> > >
00088     multiVecs;
00089   const int numBlocks = productSpace->numBlocks();
00090   for ( int k = 0; k < numBlocks; ++k )
00091     multiVecs.push_back(createMembers(productSpace->getBlock(k),numMembers));
00092   initialize(productSpace,&multiVecs[0]);
00093 }
00094 
00095 
00096 template<class Scalar>
00097 void DefaultProductMultiVector<Scalar>::initialize(
00098   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00099   const Teuchos::RCP<MultiVectorBase<Scalar> > multiVecs[]
00100   )
00101 {
00102   initializeImpl(productSpace,multiVecs);
00103 }
00104 
00105 
00106 template<class Scalar>
00107 void DefaultProductMultiVector<Scalar>::initialize(
00108   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00109   const Teuchos::RCP<const MultiVectorBase<Scalar> > multiVecs[]
00110   )
00111 {
00112   initializeImpl(productSpace,multiVecs);
00113 }
00114 
00115 
00116 template<class Scalar>
00117 void DefaultProductMultiVector<Scalar>::uninitialize()
00118 {
00119   productSpace_ = Teuchos::null;
00120   multiVecs_.resize(0);
00121   numBlocks_ = 0;
00122 }
00123 
00124 
00125 // Overridden from Teuchos::Describable
00126 
00127                                                 
00128 template<class Scalar>
00129 std::string DefaultProductMultiVector<Scalar>::description() const
00130 {
00131   std::ostringstream oss;
00132   oss
00133     << Teuchos::Describable::description()
00134     << "{"
00135     << "rangeDim="<<this->range()->dim()
00136     << ",domainDim="<<this->domain()->dim()
00137     << ",numBlocks = "<<numBlocks_
00138     << "}";
00139   return oss.str();
00140 }
00141 
00142 
00143 template<class Scalar>
00144 void DefaultProductMultiVector<Scalar>::describe(
00145   Teuchos::FancyOStream &out_arg,
00146   const Teuchos::EVerbosityLevel verbLevel
00147   ) const
00148 {
00149   typedef Teuchos::ScalarTraits<Scalar>  ST;
00150   using Teuchos::RCP;
00151   using Teuchos::FancyOStream;
00152   using Teuchos::OSTab;
00153   using Teuchos::describe;
00154   if (verbLevel == Teuchos::VERB_NONE)
00155     return;
00156   RCP<FancyOStream> out = rcp(&out_arg,false);
00157   OSTab tab(out);
00158   switch(verbLevel) {
00159     case Teuchos::VERB_DEFAULT: // fall through
00160     case Teuchos::VERB_LOW: // fall through
00161       *out << this->description() << std::endl;
00162       break;
00163     case Teuchos::VERB_MEDIUM: // fall through
00164     case Teuchos::VERB_HIGH: // fall through
00165     case Teuchos::VERB_EXTREME:
00166     {
00167       *out
00168         << Teuchos::Describable::description() << "{"
00169         << "rangeDim="<<this->range()->dim()
00170         << ",domainDim="<<this->domain()->dim()
00171         << "}\n";
00172       OSTab tab(out);
00173       *out
00174         <<  "numBlocks="<< numBlocks_ << std::endl
00175         <<  "Constituent multi-vector objects V[0], V[1], ... V[numBlocks-1]:\n";
00176       tab.incrTab();
00177       for( int k = 0; k < numBlocks_; ++k ) {
00178         *out << "V["<<k<<"] = "
00179              << Teuchos::describe(*multiVecs_[k].getConstObj(),verbLevel);
00180       }
00181       break;
00182     }
00183     default:
00184       TEST_FOR_EXCEPT(true); // Should never get here!
00185   }
00186 }
00187 
00188 
00189 // Overridden from ProductMultiVectorBase
00190 
00191 
00192 template<class Scalar>
00193 Teuchos::RCP<const ProductVectorSpaceBase<Scalar> >
00194 DefaultProductMultiVector<Scalar>::productSpace() const
00195 {
00196   return productSpace_;
00197 }
00198 
00199 
00200 template<class Scalar>
00201 bool DefaultProductMultiVector<Scalar>::blockIsConst(const int k) const
00202 {
00203   return multiVecs_[k].isConst();
00204 }
00205 
00206 
00207 template<class Scalar>
00208 Teuchos::RCP<MultiVectorBase<Scalar> >
00209 DefaultProductMultiVector<Scalar>::getNonconstMultiVectorBlock(const int k)
00210 {
00211   return multiVecs_[k].getNonconstObj();
00212 }
00213 
00214 
00215 template<class Scalar>
00216 Teuchos::RCP<const MultiVectorBase<Scalar> >
00217 DefaultProductMultiVector<Scalar>::getMultiVectorBlock(const int k) const
00218 {
00219   return multiVecs_[k].getConstObj();
00220 }
00221 
00222 
00223 // Overriden from MultiVectorBase
00224 
00225 
00226 template<class Scalar>
00227 Teuchos::RCP<const VectorBase<Scalar> >
00228 DefaultProductMultiVector<Scalar>::col(Index j) const
00229 {
00230   validateColIndex(j);
00231   Teuchos::Array<Teuchos::RCP<const VectorBase<Scalar> > > cols_;
00232   for ( int k = 0; k < numBlocks_; ++k )
00233     cols_.push_back(multiVecs_[k].getConstObj()->col(j));
00234   return defaultProductVector<Scalar>(productSpace_,&cols_[0]);
00235 }
00236 
00237 
00238 template<class Scalar>
00239 Teuchos::RCP<VectorBase<Scalar> >
00240 DefaultProductMultiVector<Scalar>::col(Index j)
00241 {
00242   validateColIndex(j);
00243   Teuchos::Array<Teuchos::RCP<VectorBase<Scalar> > > cols_;
00244   for ( int k = 0; k < numBlocks_; ++k )
00245     cols_.push_back(multiVecs_[k].getNonconstObj()->col(j));
00246   return defaultProductVector<Scalar>(productSpace_,&cols_[0]);
00247 }
00248 
00249 
00250 template<class Scalar>
00251 Teuchos::RCP<const MultiVectorBase<Scalar> >
00252 DefaultProductMultiVector<Scalar>::subView( const Range1D& colRng ) const
00253 {
00254   assertInitialized();
00255   Teuchos::Array<Teuchos::RCP<const MultiVectorBase<Scalar> > > blocks_;
00256   for ( int k = 0; k < numBlocks_; ++k )
00257     blocks_.push_back(multiVecs_[k].getConstObj()->subView(colRng));
00258   return defaultProductMultiVector<Scalar>(productSpace_,&blocks_[0]);
00259 }
00260 
00261 
00262 template<class Scalar>
00263 Teuchos::RCP<MultiVectorBase<Scalar> >
00264 DefaultProductMultiVector<Scalar>::subView( const Range1D& colRng )
00265 {
00266   assertInitialized();
00267   Teuchos::Array<Teuchos::RCP<MultiVectorBase<Scalar> > > blocks_;
00268   for ( int k = 0; k < numBlocks_; ++k )
00269     blocks_.push_back(multiVecs_[k].getNonconstObj()->subView(colRng));
00270   return defaultProductMultiVector<Scalar>(productSpace_,&blocks_[0]);
00271 }
00272 
00273 
00274 template<class Scalar>
00275 Teuchos::RCP<const MultiVectorBase<Scalar> >
00276 DefaultProductMultiVector<Scalar>::subView(
00277   const int numCols, const int cols[]
00278   ) const
00279 {
00280   assertInitialized();
00281   Teuchos::Array<Teuchos::RCP<const MultiVectorBase<Scalar> > > blocks_;
00282   for ( int k = 0; k < numBlocks_; ++k )
00283     blocks_.push_back(multiVecs_[k].getConstObj()->subView(numCols,cols));
00284   return defaultProductMultiVector<Scalar>(productSpace_,&blocks_[0]);
00285 }
00286 
00287 
00288 template<class Scalar>
00289 Teuchos::RCP<MultiVectorBase<Scalar> >
00290 DefaultProductMultiVector<Scalar>::subView(
00291   const int numCols, const int cols[]
00292   )
00293 {
00294   assertInitialized();
00295   Teuchos::Array<Teuchos::RCP<MultiVectorBase<Scalar> > > blocks_;
00296   for ( int k = 0; k < numBlocks_; ++k )
00297     blocks_.push_back(multiVecs_[k].getNonconstObj()->subView(numCols,cols));
00298   return defaultProductMultiVector<Scalar>(productSpace_,&blocks_[0]);
00299 }
00300 
00301 
00302 template<class Scalar>
00303 void DefaultProductMultiVector<Scalar>::mvMultiReductApplyOpImpl(
00304   const RTOpPack::RTOpT<Scalar> &primary_op,
00305   const int num_multi_vecs,
00306   const MultiVectorBase<Scalar>*const multi_vecs_in[],
00307   const int num_targ_multi_vecs,
00308   MultiVectorBase<Scalar>*const targ_multi_vecs_inout[],
00309   RTOpPack::ReductTarget*const reduct_objs[],
00310   const Index primary_first_ele_offset_in,
00311   const Index primary_sub_dim_in,
00312   const Index primary_global_offset_in,
00313   const Index secondary_first_ele_offset_in,
00314   const Index secondary_sub_dim_in
00315   ) const
00316 {
00317   
00318   using Teuchos::Array;
00319   using Teuchos::RCP;
00320   using Thyra::applyOp;
00321 
00322   assertInitialized();
00323 
00324   const Index domainDim = this->domain()->dim();
00325   const Index rangeDim = this->range()->dim();
00326 
00327 #ifdef TEUCHOS_DEBUG
00328   TEST_FOR_EXCEPT( num_multi_vecs < 0 );
00329   TEST_FOR_EXCEPT( num_multi_vecs > 0 && multi_vecs_in == 0 );
00330   for ( int j = 0; j < num_multi_vecs; ++j ) {
00331     THYRA_ASSERT_VEC_SPACES(
00332       "DefaultProductMultiVector<Scalar>::mvMultiReductApplyOpImpl(...)",
00333       *this->range(), *multi_vecs_in[j]->range()
00334       );
00335     THYRA_ASSERT_VEC_SPACES(
00336       "DefaultProductMultiVector<Scalar>::mvMultiReductApplyOpImpl(...)",
00337       *this->domain(), *multi_vecs_in[j]->domain()
00338       );
00339   }
00340   TEST_FOR_EXCEPT( num_targ_multi_vecs < 0 );
00341   TEST_FOR_EXCEPT( num_targ_multi_vecs > 0 && targ_multi_vecs_inout == 0 );
00342   for ( int j = 0; j < num_targ_multi_vecs; ++j ) {
00343     THYRA_ASSERT_VEC_SPACES(
00344       "DefaultProductMultiVector<Scalar>::mvMultiReductApplyOpImpl(...)",
00345       *this->range(), *targ_multi_vecs_inout[j]->range()
00346       );
00347     THYRA_ASSERT_VEC_SPACES(
00348       "DefaultProductMultiVector<Scalar>::mvMultiReductApplyOpImpl(...)",
00349       *this->domain(), *targ_multi_vecs_inout[j]->domain()
00350       );
00351   }
00352   TEST_FOR_EXCEPT(
00353     !(
00354       0 <= primary_first_ele_offset_in
00355       &&
00356       primary_first_ele_offset_in < rangeDim
00357       )
00358     );
00359   TEST_FOR_EXCEPT(
00360     primary_sub_dim_in > 0
00361     &&
00362     primary_first_ele_offset_in + primary_sub_dim_in > rangeDim
00363     );
00364   TEST_FOR_EXCEPT(
00365     !(
00366       0 <= secondary_first_ele_offset_in
00367       &&
00368       secondary_first_ele_offset_in < domainDim
00369       )
00370     );
00371   TEST_FOR_EXCEPT(
00372     secondary_sub_dim_in > 0
00373     &&
00374     secondary_first_ele_offset_in + secondary_sub_dim_in > domainDim
00375     );
00376 #endif //  TEUCHOS_DEBUG
00377 
00378   const Index primary_sub_dim
00379     = (
00380       primary_sub_dim_in < 0
00381       ? rangeDim - primary_first_ele_offset_in
00382       : primary_sub_dim_in
00383       );
00384   const Index secondary_sub_dim
00385     = (
00386       secondary_sub_dim_in < 0
00387       ? domainDim - secondary_first_ele_offset_in
00388       : secondary_sub_dim_in
00389       );
00390 
00391   //
00392   // Try to dynamic cast all of the multi-vector objects to the
00393   // ProductMultiVectoBase interface.
00394   //
00395 
00396   bool allProductMultiVectors = true;
00397 
00398   Array<const ProductMultiVectorBase<Scalar>*> multi_vecs;
00399   for ( int j = 0; j < num_multi_vecs && allProductMultiVectors; ++j ) {
00400 #ifdef TEUCHOS_DEBUG
00401     TEST_FOR_EXCEPT( multi_vecs_in[j] == 0 );
00402 #endif
00403     const ProductMultiVectorBase<Scalar>
00404       *multi_vecs_k = dynamic_cast<const ProductMultiVectorBase<Scalar>*>(
00405         multi_vecs_in[j]
00406         );
00407     if ( multi_vecs_k ) {
00408       multi_vecs.push_back(multi_vecs_k);
00409     }
00410     else {
00411       allProductMultiVectors = false;
00412     }
00413   }
00414 
00415   Array<ProductMultiVectorBase<Scalar>*> targ_multi_vecs;
00416   for ( int j = 0; j < num_targ_multi_vecs && allProductMultiVectors; ++j )
00417   {
00418 #ifdef TEUCHOS_DEBUG
00419     TEST_FOR_EXCEPT( targ_multi_vecs_inout[j] == 0 );
00420 #endif
00421     ProductMultiVectorBase<Scalar>
00422       *targ_multi_vecs_k = dynamic_cast<ProductMultiVectorBase<Scalar>*>(
00423         targ_multi_vecs_inout[j]
00424         );
00425     if ( targ_multi_vecs_k ) {
00426       targ_multi_vecs.push_back(targ_multi_vecs_k);
00427     }
00428     else {
00429       allProductMultiVectors = false;
00430     }
00431   }
00432 
00433   //
00434   // Do the reduction operations
00435   //
00436   
00437   if ( allProductMultiVectors ) {
00438 
00439     // All of the multi-vector objects support the ProductMultiVectorBase
00440     // interface so we can do the reductions block by block.  Note, this is
00441     // not the most efficient implementation in an SPMD program but this is
00442     // easy to code up and use!
00443 
00444     // We must set up temporary arrays for the pointers to the MultiVectorBase
00445     // blocks for each block of objects!  What a mess!
00446     Array<RCP<const MultiVectorBase<Scalar> > >
00447       multi_vecs_rcp_block_k(num_multi_vecs);
00448     Array<const MultiVectorBase<Scalar>*>
00449       multi_vecs_block_k(num_multi_vecs);
00450     Array<RCP<MultiVectorBase<Scalar> > >
00451       targ_multi_vecs_rcp_block_k(num_targ_multi_vecs);
00452     Array<MultiVectorBase<Scalar>*>
00453       targ_multi_vecs_block_k(num_targ_multi_vecs);
00454 
00455     Index num_rows_remaining = primary_sub_dim;
00456     Index g_off = -primary_first_ele_offset_in;
00457 
00458     for ( int k = 0; k < numBlocks_; ++k ) {
00459 
00460       // See if this block involves any of the requested rows and if so get
00461       // the local context.
00462       const Index local_dim = productSpace_->getBlock(k)->dim();
00463       if( g_off < 0 && -g_off+1 > local_dim ) {
00464         g_off += local_dim;
00465         continue;
00466       }
00467       const Index local_sub_dim
00468         = (
00469           g_off >= 0
00470           ? std::min( local_dim, num_rows_remaining )
00471           : std::min( local_dim + g_off, num_rows_remaining )
00472           );
00473       if( local_sub_dim <= 0 )
00474         break;
00475 
00476       // Fill the MultiVector array objects for this block
00477 
00478       for ( int j = 0; j < num_multi_vecs; ++j ) {
00479         RCP<const MultiVectorBase<Scalar> >
00480           multi_vecs_rcp_block_k_j = multi_vecs[j]->getMultiVectorBlock(k);
00481         multi_vecs_rcp_block_k[j] = multi_vecs_rcp_block_k_j;
00482         multi_vecs_block_k[j] = &*multi_vecs_rcp_block_k_j;
00483       }
00484 
00485       for ( int j = 0; j < num_targ_multi_vecs; ++j ) {
00486         RCP<MultiVectorBase<Scalar> >
00487           targ_multi_vecs_rcp_block_k_j = targ_multi_vecs[j]->getNonconstMultiVectorBlock(k);
00488         targ_multi_vecs_rcp_block_k[j] = targ_multi_vecs_rcp_block_k_j;
00489         targ_multi_vecs_block_k[j] = &*targ_multi_vecs_rcp_block_k_j;
00490       }
00491 
00492       // Apply the RTOp object to the MultiVectors for this block
00493 
00494       Thyra::applyOp<Scalar>(
00495         primary_op,
00496         num_multi_vecs, num_multi_vecs ? &multi_vecs_block_k[0] : 0,
00497         num_targ_multi_vecs, num_targ_multi_vecs ? &targ_multi_vecs_block_k[0] : 0,
00498         reduct_objs,
00499         g_off < 0 ? -g_off : 0, // primary_first_ele_offset
00500         local_sub_dim,  // primary_sub_dim
00501         g_off < 0 ? primary_global_offset_in : primary_global_offset_in + g_off, // primary_global_offset,
00502         secondary_first_ele_offset_in, secondary_sub_dim
00503         );
00504     }
00505 
00506   }
00507   else {
00508 
00509     // All of the multi-vector objects do not support the
00510     // ProductMultiVectorBase interface but if we got here (in debug mode)
00511     // then the spaces said that they are compatible so fall back on the
00512     // column-by-column implementation that will work correctly in serial.
00513 
00514     MultiVectorDefaultBase<Scalar>::mvMultiReductApplyOpImpl(
00515       primary_op,
00516       num_multi_vecs, multi_vecs_in,
00517       num_targ_multi_vecs, targ_multi_vecs_inout,
00518       reduct_objs,
00519       primary_first_ele_offset_in, primary_sub_dim_in, primary_global_offset_in,
00520       secondary_first_ele_offset_in, secondary_sub_dim_in
00521       );
00522 
00523   }
00524 
00525 }
00526 
00527 
00528 template<class Scalar>
00529 void DefaultProductMultiVector<Scalar>::acquireDetachedMultiVectorViewImpl(
00530   const Range1D &rowRng,
00531   const Range1D &colRng,
00532   RTOpPack::ConstSubMultiVectorView<Scalar> *sub_mv
00533   ) const
00534 {
00535   return MultiVectorDefaultBase<Scalar>::acquireDetachedMultiVectorViewImpl(
00536     rowRng, colRng, sub_mv );
00537   // ToDo: Override this implementation if needed!
00538 }
00539 
00540 
00541 template<class Scalar>
00542 void DefaultProductMultiVector<Scalar>::releaseDetachedMultiVectorViewImpl(
00543   RTOpPack::ConstSubMultiVectorView<Scalar>* sub_mv
00544   ) const
00545 {
00546   return MultiVectorDefaultBase<Scalar>::releaseDetachedMultiVectorViewImpl(
00547     sub_mv );
00548   // ToDo: Override this implementation if needed!
00549 }
00550 
00551 
00552 template<class Scalar>
00553 void DefaultProductMultiVector<Scalar>::acquireNonconstDetachedMultiVectorViewImpl(
00554   const Range1D &rowRng,
00555   const Range1D &colRng,
00556   RTOpPack::SubMultiVectorView<Scalar> *sub_mv
00557   )
00558 {
00559   return MultiVectorDefaultBase<Scalar>::acquireNonconstDetachedMultiVectorViewImpl(
00560     rowRng,colRng,sub_mv );
00561   // ToDo: Override this implementation if needed!
00562 }
00563 
00564 
00565 template<class Scalar>
00566 void DefaultProductMultiVector<Scalar>::commitNonconstDetachedMultiVectorViewImpl(
00567   RTOpPack::SubMultiVectorView<Scalar>* sub_mv
00568   )
00569 {
00570   return MultiVectorDefaultBase<Scalar>::commitNonconstDetachedMultiVectorViewImpl(sub_mv);
00571   // ToDo: Override this implementation if needed!
00572 }
00573 
00574 
00575 template<class Scalar>
00576 Teuchos::RCP<MultiVectorBase<Scalar> >
00577 DefaultProductMultiVector<Scalar>::clone_mv() const
00578 {
00579   assertInitialized();
00580   Teuchos::Array<Teuchos::RCP<MultiVectorBase<Scalar> > > blocks_;
00581   for ( int k = 0; k < numBlocks_; ++k )
00582     blocks_.push_back(multiVecs_[k].getConstObj()->clone_mv());
00583   return defaultProductMultiVector<Scalar>(productSpace_,&blocks_[0]);
00584   
00585 
00586   return Teuchos::null;
00587   // ToDo: Override when needed!
00588   TEST_FOR_EXCEPT(true);
00589 }
00590 
00591 
00592 // Overriden from LinearOpBase
00593 
00594 
00595 template<class Scalar>
00596 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00597 DefaultProductMultiVector<Scalar>::range() const
00598 {
00599   return productSpace_;
00600 }
00601 
00602 
00603 template<class Scalar>
00604 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00605 DefaultProductMultiVector<Scalar>::domain() const
00606 {
00607   if (is_null(productSpace_))
00608     return Teuchos::null;
00609   return multiVecs_[0].getConstObj()->domain();
00610 }
00611 
00612 
00613 // Overridden from SingleScalarLinearOpBase
00614 
00615 
00616 template<class Scalar>
00617 bool DefaultProductMultiVector<Scalar>::opSupported(ETransp M_trans) const
00618 {
00619   return true; // We can do it all!
00620 }
00621 
00622 
00623 template<class Scalar>
00624 void DefaultProductMultiVector<Scalar>::apply(
00625   const ETransp M_trans,
00626   const MultiVectorBase<Scalar> &X_in,
00627   MultiVectorBase<Scalar> *Y_inout,
00628   const Scalar alpha,
00629   const Scalar beta
00630   ) const
00631 {
00632 
00633   typedef Teuchos::ScalarTraits<Scalar> ST;
00634   using Teuchos::dyn_cast;
00635   using Thyra::apply;
00636 
00637 #ifdef TEUCHOS_DEBUG
00638   THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(
00639     "DefaultProductMultiVector<Scalar>::apply(...)",
00640     *this, M_trans, X_in, Y_inout );
00641 #endif
00642 
00643   if ( real_trans(M_trans) == NOTRANS ) {
00644     //
00645     // Y = b*Y + a*M*X
00646     //
00647     //    =>
00648     //
00649     // Y[k] = b*Y[k] + a*M[k]*X, k = 0...numBlocks-1
00650     //
00651     ProductMultiVectorBase<Scalar>
00652       &Y = dyn_cast<ProductMultiVectorBase<Scalar> >(*Y_inout);
00653     for ( int k = 0; k < numBlocks_; ++k ) {
00654       Thyra::apply(
00655         *multiVecs_[k].getConstObj(), M_trans,
00656         X_in, &*Y.getNonconstMultiVectorBlock(k),
00657         alpha, beta
00658         ); 
00659     }
00660   }
00661   else {
00662     //
00663     // Y = b*Y + a*trans(M)*X
00664     //
00665     //    =>
00666     //
00667     // Y = b*Y + sum( a * trans(M[k]) * X[k], k=0...numBlocks-1 )
00668     //
00669     const ProductMultiVectorBase<Scalar>
00670       &X = dyn_cast<const ProductMultiVectorBase<Scalar> >(X_in);
00671     for ( int k = 0; k < numBlocks_; ++k ) {
00672       Teuchos::RCP<const MultiVectorBase<Scalar> >
00673         M_k = multiVecs_[k].getConstObj(),
00674         X_k = X.getMultiVectorBlock(k);
00675       if ( 0 == k ) {
00676         Thyra::apply( *M_k, M_trans, *X_k, &*Y_inout, alpha, beta ); 
00677       }
00678       else {
00679         Thyra::apply( *M_k, M_trans, *X_k, &*Y_inout, alpha, ST::one() ); 
00680       }
00681     }
00682   }
00683 }
00684 
00685 
00686 // private
00687 
00688 
00689 template<class Scalar>
00690 template<class MultiVectorType>
00691 void DefaultProductMultiVector<Scalar>::initializeImpl(
00692   const Teuchos::RCP<const DefaultProductVectorSpace<Scalar> > &productSpace,
00693   const Teuchos::RCP<MultiVectorType> multiVecs[]
00694   )
00695 {
00696   // This function provides the "strong" guarantee (i.e. if an exception is
00697   // thrown, then *this will be left in the original state as before the
00698   // function was called)!
00699 #ifdef TEUCHOS_DEBUG
00700   TEST_FOR_EXCEPT( is_null(productSpace) );
00701   TEST_FOR_EXCEPT( 0==multiVecs );
00702 #endif // TEUCHOS_DEBUG
00703   const Teuchos::RCP<const VectorSpaceBase<Scalar> >
00704     theDomain = multiVecs[0]->domain();
00705   const int numBlocks = productSpace->numBlocks();
00706 #ifdef TEUCHOS_DEBUG
00707   for ( int k = 0; k < numBlocks; ++k ) {
00708     THYRA_ASSERT_VEC_SPACES(
00709       Teuchos::TypeNameTraits<DefaultProductMultiVector<Scalar> >::name(),
00710       *theDomain, *multiVecs[k]->domain()
00711       );
00712   }
00713 #endif
00714   productSpace_ = productSpace;
00715   numBlocks_ = numBlocks;
00716   multiVecs_.resize(0);
00717   for ( int k = 0; k < numBlocks; ++k ) {
00718     multiVecs_.push_back(multiVecs[k]);
00719   }
00720 }
00721 
00722 
00723 #ifdef TEUCHOS_DEBUG
00724 
00725 
00726 template<class Scalar>
00727 void DefaultProductMultiVector<Scalar>::assertInitialized() const
00728 {
00729   TEST_FOR_EXCEPTION(
00730     is_null(productSpace_), std::logic_error,
00731     "Error, this DefaultProductMultiVector object is not intialized!"
00732     );
00733 }
00734 
00735 
00736 template<class Scalar>
00737 void DefaultProductMultiVector<Scalar>::validateColIndex(const int j) const
00738 {
00739   assertInitialized();
00740   const int domainDim = multiVecs_[0].getConstObj()->domain()->dim();
00741   TEST_FOR_EXCEPTION(
00742     ! ( 0 <= j && j < domainDim ), std::logic_error,
00743     "Error, the column index j = " << j << " does not fall in the range [0,"<<domainDim<<"]!"
00744     );
00745 }
00746 
00747 
00748 #endif // TEUCHOS_DEBUG
00749 
00750 } // namespace Thyra
00751 
00752 
00753 #endif // THYRA_DEFAULT_PRODUCT_MULTI_VECTOR_HPP

Generated on Tue Oct 20 12:47:25 2009 for Thyra Package Browser (Single Doxygen Collection) by doxygen 1.4.7