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

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