|
Thyra Package Browser (Single Doxygen Collection) Version of the Day
|
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
1.7.4