Thyra Package Browser (Single Doxygen Collection) Version of the Day
Thyra_DefaultProductVector_def.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_VECTOR_DEF_HPP
00030 #define THYRA_DEFAULT_PRODUCT_VECTOR_DEF_HPP
00031 
00032 
00033 #include "Thyra_DefaultProductVector_decl.hpp"
00034 #include "Thyra_DefaultProductVectorSpace.hpp"
00035 #include "Teuchos_Workspace.hpp"
00036 
00037 
00038 namespace Thyra {
00039 
00040 
00041 // Constructors/initializers/accessors
00042 
00043 
00044 template <class Scalar>
00045 DefaultProductVector<Scalar>::DefaultProductVector()
00046   : numBlocks_(0)
00047 {
00048   uninitialize();
00049 }
00050 
00051 
00052 template <class Scalar>
00053 DefaultProductVector<Scalar>::DefaultProductVector(
00054   const RCP<const DefaultProductVectorSpace<Scalar> >  &productSpace_in
00055   )
00056   : numBlocks_(0)
00057 {
00058   initialize(productSpace_in);
00059 }
00060 
00061 
00062 template <class Scalar>
00063 void DefaultProductVector<Scalar>::initialize(
00064   const RCP<const DefaultProductVectorSpace<Scalar> >  &productSpace_in
00065   )
00066 {
00067   // ToDo: Validate input!
00068   numBlocks_ = productSpace_in->numBlocks();
00069   productSpace_ = productSpace_in;
00070   vecs_.resize(numBlocks_);
00071   for( int k = 0; k < numBlocks_; ++k )
00072     vecs_[k].initialize(createMember(productSpace_in->getBlock(k)));
00073 }
00074 
00075 
00076 template <class Scalar>
00077 void DefaultProductVector<Scalar>::initialize(
00078   const RCP<const DefaultProductVectorSpace<Scalar> > &productSpace_in,
00079   const ArrayView<const RCP<VectorBase<Scalar> > > &vecs
00080   )
00081 {
00082   using Teuchos::as;
00083 #ifdef TEUCHOS_DEBUG
00084   TEUCHOS_ASSERT_EQUALITY( as<Ordinal>(productSpace_in->numBlocks()),
00085     as<Ordinal>(vecs.size()) );
00086 #endif
00087   numBlocks_ = productSpace_in->numBlocks();
00088   productSpace_ = productSpace_in;
00089   vecs_.resize(numBlocks_);
00090   for( int k = 0; k < numBlocks_; ++k )
00091     vecs_[k].initialize(vecs[k]);
00092 }
00093 
00094 
00095 template <class Scalar>
00096 void DefaultProductVector<Scalar>::initialize(
00097   const RCP<const DefaultProductVectorSpace<Scalar> > &productSpace_in,
00098   const ArrayView<const RCP<const VectorBase<Scalar> > > &vecs
00099   )
00100 {
00101   using Teuchos::as;
00102 #ifdef TEUCHOS_DEBUG
00103   TEUCHOS_ASSERT_EQUALITY( as<Ordinal>(productSpace_in->numBlocks()),
00104     as<Ordinal>(vecs.size()) );
00105 #endif
00106   numBlocks_ = productSpace_in->numBlocks();
00107   productSpace_ = productSpace_in;
00108   vecs_.resize(numBlocks_);
00109   for( int k = 0; k < numBlocks_; ++k )
00110     vecs_[k].initialize(vecs[k]);
00111 }
00112 
00113 
00114 template <class Scalar>
00115 void DefaultProductVector<Scalar>::uninitialize()
00116 {
00117   productSpace_ = Teuchos::null;
00118   vecs_.resize(0);
00119   numBlocks_ = 0;
00120 }
00121 
00122 
00123 // Overridden from Teuchos::Describable
00124 
00125                                                 
00126 template<class Scalar>
00127 std::string DefaultProductVector<Scalar>::description() const
00128 {
00129   const RCP<const VectorSpaceBase<Scalar> > vs = this->space();
00130   std::ostringstream oss;
00131   oss
00132     << Teuchos::Describable::description()
00133     << "{"
00134     << "dim="<<(nonnull(vs) ? vs->dim() : 0)
00135     << ", numBlocks = "<<numBlocks_
00136     << "}";
00137   return oss.str();
00138 }
00139 
00140 
00141 template<class Scalar>
00142 void DefaultProductVector<Scalar>::describe(
00143   Teuchos::FancyOStream &out_arg,
00144   const Teuchos::EVerbosityLevel verbLevel
00145   ) const
00146 {
00147   typedef Teuchos::ScalarTraits<Scalar>  ST;
00148   using Teuchos::FancyOStream;
00149   using Teuchos::OSTab;
00150   using Teuchos::describe;
00151   RCP<FancyOStream> out = rcp(&out_arg,false);
00152   OSTab tab(out);
00153   switch(verbLevel) {
00154     case Teuchos::VERB_NONE:
00155       break;
00156     case Teuchos::VERB_DEFAULT:
00157     case Teuchos::VERB_LOW:
00158       *out << this->description() << std::endl;
00159       break;
00160     case Teuchos::VERB_MEDIUM:
00161     case Teuchos::VERB_HIGH:
00162     case Teuchos::VERB_EXTREME:
00163     {
00164       *out
00165         << Teuchos::Describable::description() << "{"
00166         << "dim=" << this->space()->dim()
00167         << "}\n";
00168       OSTab tab2(out);
00169       *out
00170         <<  "numBlocks="<< numBlocks_ << std::endl
00171         <<  "Constituent vector objects v[0], v[1], ... v[numBlocks-1]:\n";
00172       OSTab tab3(out);
00173       for( int k = 0; k < numBlocks_; ++k ) {
00174         *out << "v["<<k<<"] = " << describe(*vecs_[k].getConstObj(),verbLevel);
00175       }
00176       break;
00177     }
00178     default:
00179       TEST_FOR_EXCEPT(true); // Should never get here!
00180   }
00181 }
00182 
00183 
00184 // Extensions to ProductVectorBase suitable for physically-blocked vectors
00185 
00186 
00187 template <class Scalar>
00188 void DefaultProductVector<Scalar>::setBlock(
00189   int i, const RCP<const VectorBase<Scalar> >& b
00190   )
00191 {
00192 #ifdef TEUCHOS_DEBUG
00193   TEST_FOR_EXCEPT(i < 0 || i >= numBlocks_);
00194   TEST_FOR_EXCEPT(!productSpace_->getBlock(i)->isCompatible(*(b->space())));
00195 #endif
00196   vecs_[i] = b;
00197 }
00198 
00199 
00200 template <class Scalar>
00201 void DefaultProductVector<Scalar>::setNonconstBlock(
00202   int i, const RCP<VectorBase<Scalar> >& b
00203   )
00204 {
00205 #ifdef TEUCHOS_DEBUG
00206   TEST_FOR_EXCEPT(i < 0 || i >= numBlocks_);
00207   TEST_FOR_EXCEPT(!productSpace_->getBlock(i)->isCompatible(*(b->space())));
00208 #endif
00209   vecs_[i] = b;
00210 }
00211 
00212 
00213 // Overridden from ProductVectorBase
00214 
00215 
00216 template <class Scalar>
00217 RCP<VectorBase<Scalar> >
00218 DefaultProductVector<Scalar>::getNonconstVectorBlock(const int k)
00219 {
00220 #ifdef TEUCHOS_DEBUG
00221   TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00222 #endif
00223   return vecs_[k].getNonconstObj();
00224 }
00225 
00226 
00227 template <class Scalar>
00228 RCP<const VectorBase<Scalar> >
00229 DefaultProductVector<Scalar>::getVectorBlock(const int k) const
00230 {
00231 #ifdef TEUCHOS_DEBUG
00232   TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00233 #endif
00234   return vecs_[k].getConstObj();
00235 }
00236 
00237 
00238 // Overridden from ProductMultiVectorBase
00239 
00240 
00241 template <class Scalar>
00242 RCP<const ProductVectorSpaceBase<Scalar> >
00243 DefaultProductVector<Scalar>::productSpace() const
00244 {
00245   return productSpace_;
00246 }
00247 
00248 
00249 template <class Scalar>
00250 bool DefaultProductVector<Scalar>::blockIsConst(const int k) const
00251 {
00252 #ifdef TEUCHOS_DEBUG
00253   TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00254 #endif
00255   return vecs_[k].isConst();
00256 }
00257 
00258 
00259 template <class Scalar>
00260 RCP<MultiVectorBase<Scalar> >
00261 DefaultProductVector<Scalar>::getNonconstMultiVectorBlock(const int k)
00262 {
00263   return getNonconstVectorBlock(k);
00264 }
00265 
00266 
00267 template <class Scalar>
00268 RCP<const MultiVectorBase<Scalar> >
00269 DefaultProductVector<Scalar>::getMultiVectorBlock(const int k) const
00270 {
00271   return getVectorBlock(k);
00272 }
00273 
00274 
00275 // Overridden from VectorBase
00276 
00277 
00278 template <class Scalar>
00279 RCP< const VectorSpaceBase<Scalar> >
00280 DefaultProductVector<Scalar>::space() const
00281 {
00282   return productSpace_;
00283 }
00284 
00285 
00286 template <class Scalar>
00287 void DefaultProductVector<Scalar>::applyOpImpl(
00288   const RTOpPack::RTOpT<Scalar> &op,
00289   const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
00290   const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
00291   const Ptr<RTOpPack::ReductTarget> &reduct_obj,
00292   const Ordinal global_offset_in
00293   ) const
00294 {
00295 
00296   // 2008/02/20: rabartl: ToDo: Upgrade Teuchos::Workspace<T> to implicitly
00297   // convert to Teuchos::ArrayView<T>.  This will allow the calls to
00298   // applyOp(...) with sub_vecs and sub_targ_vecs to work without trouble!
00299   // For now, I just want to get this done.  It is likely that this function
00300   // is going to change in major ways soon anyway!
00301 
00302   //using Teuchos::Workspace;
00303   using Teuchos::ptr_dynamic_cast;
00304   using Teuchos::describe;
00305   using Teuchos::null;
00306 
00307   //Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00308 
00309   const Ordinal n = productSpace_->dim();
00310   const int num_vecs = vecs.size();
00311   const int num_targ_vecs = targ_vecs.size();
00312 
00313   // Validate the compatibility of the vectors!
00314 #ifdef TEUCHOS_DEBUG
00315   bool test_failed;
00316   for(int k = 0; k < num_vecs; ++k) {
00317     test_failed = !this->space()->isCompatible(*vecs[k]->space());
00318     TEST_FOR_EXCEPTION(
00319       test_failed, Exceptions::IncompatibleVectorSpaces
00320       ,"DefaultProductVector::applyOp(...): Error vecs["<<k<<"]->space() = "
00321       <<vecs[k]->space()->description()<<"\' is not compatible with this "
00322       <<"vector space = "<<this->space()->description()<<"!"
00323       );
00324   }
00325   for(int k = 0; k < num_targ_vecs; ++k) {
00326     test_failed = !this->space()->isCompatible(*targ_vecs[k]->space());
00327     TEST_FOR_EXCEPTION(
00328       test_failed, Exceptions::IncompatibleVectorSpaces
00329       ,"DefaultProductVector::applyOp(...): Error targ_vecs["<<k<<"]->space() = "
00330       <<targ_vecs[k]->space()->description()<<"\' is not compatible with this "
00331       <<"vector space = "<<this->space()->description()<<"!"
00332       );
00333   }
00334 #endif
00335 
00336   //
00337   // Dynamic cast each of the vector arguments to the ProductVectorBase interface
00338   //
00339   // NOTE: If the constituent vector is not a product vector, then a product
00340   // vector of one component is created.
00341   //
00342 
00343   Array<RCP<const ProductVectorBase<Scalar> > > vecs_args_store(num_vecs);
00344   Array<Ptr<const ProductVectorBase<Scalar> > > vecs_args(num_vecs);
00345   for(int k = 0; k < num_vecs; ++k) {
00346     vecs_args_store[k] =
00347       castOrCreateProductVectorBase<Scalar>(rcpFromPtr(vecs[k]));
00348     vecs_args[k] = vecs_args_store[k].ptr();
00349   }
00350 
00351   Array<RCP<ProductVectorBase<Scalar> > > targ_vecs_args_store(num_targ_vecs);
00352   Array<Ptr<ProductVectorBase<Scalar> > > targ_vecs_args(num_targ_vecs);
00353   for(int k = 0; k < num_targ_vecs; ++k) {
00354     targ_vecs_args_store[k] =
00355       castOrCreateNonconstProductVectorBase<Scalar>(rcpFromPtr(targ_vecs[k]));
00356     targ_vecs_args[k] = targ_vecs_args_store[k].ptr();
00357   }
00358 
00359   //
00360   // If we get here, then we will implement the applyOpImpl(...) one vector
00361   // block at a time.
00362   //
00363   const Ordinal dim = n;
00364   Ordinal num_elements_remaining = dim;
00365   const int numBlocks = productSpace_->numBlocks();
00366   Array<RCP<const VectorBase<Scalar> > >
00367     sub_vecs_rcps(num_vecs);
00368   Array<Ptr<const VectorBase<Scalar> > >
00369     sub_vecs(num_vecs);
00370   Array<RCP<VectorBase<Scalar> > >
00371     sub_targ_vecs_rcps(num_targ_vecs);
00372   Array<Ptr<VectorBase<Scalar> > >
00373     sub_targ_vecs(num_targ_vecs);
00374   Ordinal g_off = 0;
00375   for(int k = 0; k < numBlocks; ++k) {
00376     const Ordinal dim_k = productSpace_->getBlock(k)->dim();
00377     // Fill constituent vectors for block k
00378     for( int i = 0; i < num_vecs; ++i ) {
00379       sub_vecs_rcps[i] = vecs_args[i]->getVectorBlock(k);
00380       sub_vecs[i] = sub_vecs_rcps[i].ptr();
00381     }
00382     // Fill constituent target vectors for block k
00383     for( int j = 0; j < num_targ_vecs; ++j ) {
00384       sub_targ_vecs_rcps[j] = targ_vecs_args[j]->getNonconstVectorBlock(k);
00385       sub_targ_vecs[j] = sub_targ_vecs_rcps[j].ptr();
00386     }
00387     Thyra::applyOp<Scalar>(
00388       op, sub_vecs(), sub_targ_vecs(),
00389       reduct_obj,
00390       global_offset_in + g_off
00391       );
00392     g_off += dim_k;
00393     num_elements_remaining -= dim_k;
00394   }
00395   TEST_FOR_EXCEPT(!(num_elements_remaining==0));
00396 
00397 }
00398 
00399 
00400 // protected
00401 
00402 
00403 // Overridden protected functions from VectorBase
00404 
00405 
00406 template <class Scalar>
00407 void DefaultProductVector<Scalar>::acquireDetachedVectorViewImpl(
00408   const Range1D& rng_in, RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00409   ) const
00410 {
00411   const Range1D
00412     rng = rng_in.full_range() ? Range1D(0,productSpace_->dim()-1) : rng_in;
00413   int    kth_vector_space  = -1;
00414   Ordinal  kth_global_offset = 0;
00415   productSpace_->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00416 #ifdef TEUCHOS_DEBUG
00417   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00418 #endif
00419   if(
00420     rng.lbound() + rng.size()
00421     <= kth_global_offset + vecs_[kth_vector_space].getConstObj()->space()->dim()
00422     )
00423   {
00424     // This involves only one sub-vector so just return it.
00425     const_cast<const VectorBase<Scalar>*>(
00426       &*vecs_[kth_vector_space].getConstObj()
00427       )->acquireDetachedView( rng - kth_global_offset, sub_vec );
00428     sub_vec->setGlobalOffset( sub_vec->globalOffset() + kth_global_offset );
00429   }
00430   else {
00431     // Just let the default implementation handle this.  ToDo: In the future
00432     // we could manually construct an explicit sub-vector that spanned
00433     // two or more constituent vectors but this would be a lot of work.
00434     // However, this would require the use of temporary memory but
00435     // so what.
00436     VectorDefaultBase<Scalar>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00437   }
00438 }
00439 
00440 
00441 template <class Scalar>
00442 void DefaultProductVector<Scalar>::releaseDetachedVectorViewImpl(
00443   RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00444   ) const
00445 {
00446   if( sub_vec->values().get() == NULL ) return;
00447   int    kth_vector_space  = -1;
00448   Ordinal  kth_global_offset = 0;
00449   productSpace_->getVecSpcPoss(sub_vec->globalOffset(),&kth_vector_space,&kth_global_offset);
00450 #ifdef TEUCHOS_DEBUG
00451   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00452 #endif
00453   if(
00454     sub_vec->globalOffset() + sub_vec->subDim()
00455     <= kth_global_offset +  vecs_[kth_vector_space].getConstObj()->space()->dim()
00456     )
00457   {
00458     // This sub_vec was extracted from a single constituent vector
00459     sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00460     vecs_[kth_vector_space].getConstObj()->releaseDetachedView(sub_vec);
00461   }
00462   else {
00463     // This sub_vec was created by the default implementation!
00464     VectorDefaultBase<Scalar>::releaseDetachedVectorViewImpl(sub_vec);
00465   }
00466 }
00467 
00468 
00469 template <class Scalar>
00470 void DefaultProductVector<Scalar>::acquireNonconstDetachedVectorViewImpl(
00471   const Range1D& rng_in, RTOpPack::SubVectorView<Scalar>* sub_vec
00472   )
00473 {
00474   const Range1D
00475     rng = rng_in.full_range() ? Range1D(0,productSpace_->dim()-1) : rng_in;
00476   int    kth_vector_space  = -1;
00477   Ordinal  kth_global_offset = 0;
00478   productSpace_->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00479 #ifdef TEUCHOS_DEBUG
00480   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00481 #endif
00482   if(
00483     rng.lbound() + rng.size()
00484     <= kth_global_offset + vecs_[kth_vector_space].getConstObj()->space()->dim()
00485     )
00486   {
00487     // This involves only one sub-vector so just return it.
00488     vecs_[kth_vector_space].getConstObj()->acquireDetachedView(
00489       rng - kth_global_offset, sub_vec
00490       );
00491     sub_vec->setGlobalOffset( sub_vec->globalOffset() + kth_global_offset );
00492   }
00493   else {
00494     // Just let the default implementation handle this.  ToDo: In the future
00495     // we could manually construct an explicit sub-vector that spanned
00496     // two or more constituent vectors but this would be a lot of work.
00497     // However, this would require the use of temporary memory but
00498     // so what.
00499     VectorDefaultBase<Scalar>::acquireNonconstDetachedVectorViewImpl(rng_in,sub_vec);
00500   }
00501 }
00502 
00503 
00504 template <class Scalar>
00505 void DefaultProductVector<Scalar>::commitNonconstDetachedVectorViewImpl(
00506   RTOpPack::SubVectorView<Scalar>* sub_vec
00507   )
00508 {
00509   if( sub_vec->values().get() == NULL ) return;
00510   int    kth_vector_space  = -1;
00511   Ordinal  kth_global_offset = 0;
00512   productSpace_->getVecSpcPoss(sub_vec->globalOffset(),&kth_vector_space,&kth_global_offset);
00513 #ifdef TEUCHOS_DEBUG
00514   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00515 #endif
00516   if(
00517     sub_vec->globalOffset() + sub_vec->subDim()
00518     <= kth_global_offset +  vecs_[kth_vector_space].getConstObj()->space()->dim()
00519     )
00520   {
00521     // This sub_vec was extracted from a single constituent vector
00522     sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00523     vecs_[kth_vector_space].getNonconstObj()->commitDetachedView(sub_vec);
00524   }
00525   else {
00526     // This sub_vec was created by the default implementation!
00527     VectorDefaultBase<Scalar>::commitNonconstDetachedVectorViewImpl(sub_vec);
00528   }
00529 }
00530 
00531 
00532 template <class Scalar>
00533 void DefaultProductVector<Scalar>::setSubVectorImpl(
00534   const RTOpPack::SparseSubVectorT<Scalar>& sub_vec
00535   )
00536 {
00537   int    kth_vector_space  = -1;
00538   Ordinal  kth_global_offset = 0;
00539   productSpace_->getVecSpcPoss(sub_vec.globalOffset(),&kth_vector_space,&kth_global_offset);
00540 #ifdef TEUCHOS_DEBUG
00541   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00542 #endif
00543   if(
00544     sub_vec.globalOffset() + sub_vec.subDim()
00545     <= kth_global_offset + vecs_[kth_vector_space].getConstObj()->space()->dim()
00546     )
00547   {
00548     // This sub-vector fits into a single constituent vector
00549     RTOpPack::SparseSubVectorT<Scalar> sub_vec_g = sub_vec;
00550     sub_vec_g.setGlobalOffset( sub_vec_g.globalOffset() - kth_global_offset );
00551     vecs_[kth_vector_space].getNonconstObj()->setSubVector(sub_vec_g);
00552   }
00553   else {
00554     // Let the default implementation take care of this.  ToDo: In the future
00555     // it would be possible to manually set the relevant constituent
00556     // vectors with no temp memory allocations.
00557     VectorDefaultBase<Scalar>::setSubVector(sub_vec);
00558   }
00559 }
00560 
00561 
00562 } // namespace Thyra
00563 
00564 
00565 template<class Scalar>
00566 Teuchos::RCP<Thyra::ProductVectorBase<Scalar> >
00567 Thyra::castOrCreateNonconstProductVectorBase(const RCP<VectorBase<Scalar> > v)
00568 {
00569   using Teuchos::rcp_dynamic_cast;
00570   using Teuchos::tuple;
00571   const RCP<ProductVectorBase<Scalar> > prod_v =
00572     rcp_dynamic_cast<ProductVectorBase<Scalar> >(v);
00573   if (nonnull(prod_v)) {
00574     return prod_v;
00575   }
00576   return defaultProductVector<Scalar>(
00577     productVectorSpace<Scalar>(tuple(v->space())()),
00578     tuple(v)()
00579     );
00580 }
00581 
00582 
00583 template<class Scalar>
00584 Teuchos::RCP<const Thyra::ProductVectorBase<Scalar> >
00585 Thyra::castOrCreateProductVectorBase(const RCP<const VectorBase<Scalar> > v)
00586 {
00587   using Teuchos::rcp_dynamic_cast;
00588   using Teuchos::tuple;
00589   const RCP<const ProductVectorBase<Scalar> > prod_v =
00590     rcp_dynamic_cast<const ProductVectorBase<Scalar> >(v);
00591   if (nonnull(prod_v)) {
00592     return prod_v;
00593   }
00594   return defaultProductVector<Scalar>(
00595     productVectorSpace<Scalar>(tuple(v->space())()),
00596     tuple(v)()
00597     );
00598 }
00599 
00600 
00601 //
00602 // Explicit instant macro
00603 //
00604 
00605 #define THYRA_DEFAULT_PRODUCT_VECTOR_INSTANT(SCALAR) \
00606   \
00607   template class DefaultProductVector<SCALAR >; \
00608   \
00609   template RCP<ProductVectorBase<SCALAR > >  \
00610   castOrCreateNonconstProductVectorBase(const RCP<VectorBase<SCALAR > > v);  \
00611   \
00612   template RCP<const ProductVectorBase<SCALAR > >  \
00613   castOrCreateProductVectorBase(const RCP<const VectorBase<SCALAR > > v);  \
00614 
00615 
00616 
00617 #endif // THYRA_DEFAULT_PRODUCT_VECTOR_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines