Thyra_DefaultProductVector_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_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   std::ostringstream oss;
00130   oss
00131     << Teuchos::Describable::description()
00132     << "{"
00133     << "dim="<<this->space()->dim()
00134     << ", numBlocks = "<<numBlocks_
00135     << "}";
00136   return oss.str();
00137 }
00138 
00139 
00140 template<class Scalar>
00141 void DefaultProductVector<Scalar>::describe(
00142   Teuchos::FancyOStream &out_arg,
00143   const Teuchos::EVerbosityLevel verbLevel
00144   ) const
00145 {
00146   typedef Teuchos::ScalarTraits<Scalar>  ST;
00147   using Teuchos::FancyOStream;
00148   using Teuchos::OSTab;
00149   using Teuchos::describe;
00150   RCP<FancyOStream> out = rcp(&out_arg,false);
00151   OSTab tab(out);
00152   switch(verbLevel) {
00153     case Teuchos::VERB_NONE:
00154       break;
00155     case Teuchos::VERB_DEFAULT:
00156     case Teuchos::VERB_LOW:
00157       *out << this->description() << std::endl;
00158       break;
00159     case Teuchos::VERB_MEDIUM:
00160     case Teuchos::VERB_HIGH:
00161     case Teuchos::VERB_EXTREME:
00162     {
00163       *out
00164         << Teuchos::Describable::description() << "{"
00165         << "dim=" << this->space()->dim()
00166         << "}\n";
00167       OSTab tab2(out);
00168       *out
00169         <<  "numBlocks="<< numBlocks_ << std::endl
00170         <<  "Constituent vector objects v[0], v[1], ... v[numBlocks-1]:\n";
00171       OSTab tab3(out);
00172       for( int k = 0; k < numBlocks_; ++k ) {
00173         *out << "v["<<k<<"] = " << describe(*vecs_[k].getConstObj(),verbLevel);
00174       }
00175       break;
00176     }
00177     default:
00178       TEST_FOR_EXCEPT(true); // Should never get here!
00179   }
00180 }
00181 
00182 
00183 // Extensions to ProductVectorBase suitable for physically-blocked vectors
00184 
00185 
00186 template <class Scalar>
00187 void DefaultProductVector<Scalar>::setBlock(
00188   int i, const RCP<const VectorBase<Scalar> >& b
00189   )
00190 {
00191 #ifdef TEUCHOS_DEBUG
00192   TEST_FOR_EXCEPT(i < 0 || i >= numBlocks_);
00193   TEST_FOR_EXCEPT(!productSpace_->getBlock(i)->isCompatible(*(b->space())));
00194 #endif
00195   vecs_[i] = b;
00196 }
00197 
00198 
00199 template <class Scalar>
00200 void DefaultProductVector<Scalar>::setNonconstBlock(
00201   int i, const RCP<VectorBase<Scalar> >& b
00202   )
00203 {
00204 #ifdef TEUCHOS_DEBUG
00205   TEST_FOR_EXCEPT(i < 0 || i >= numBlocks_);
00206   TEST_FOR_EXCEPT(!productSpace_->getBlock(i)->isCompatible(*(b->space())));
00207 #endif
00208   vecs_[i] = b;
00209 }
00210 
00211 
00212 // Overridden from ProductVectorBase
00213 
00214 
00215 template <class Scalar>
00216 RCP<VectorBase<Scalar> >
00217 DefaultProductVector<Scalar>::getNonconstVectorBlock(const int k)
00218 {
00219 #ifdef TEUCHOS_DEBUG
00220   TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00221 #endif
00222   return vecs_[k].getNonconstObj();
00223 }
00224 
00225 
00226 template <class Scalar>
00227 RCP<const VectorBase<Scalar> >
00228 DefaultProductVector<Scalar>::getVectorBlock(const int k) const
00229 {
00230 #ifdef TEUCHOS_DEBUG
00231   TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00232 #endif
00233   return vecs_[k].getConstObj();
00234 }
00235 
00236 
00237 // Overridden from ProductMultiVectorBase
00238 
00239 
00240 template <class Scalar>
00241 RCP<const ProductVectorSpaceBase<Scalar> >
00242 DefaultProductVector<Scalar>::productSpace() const
00243 {
00244   return productSpace_;
00245 }
00246 
00247 
00248 template <class Scalar>
00249 bool DefaultProductVector<Scalar>::blockIsConst(const int k) const
00250 {
00251 #ifdef TEUCHOS_DEBUG
00252   TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00253 #endif
00254   return vecs_[k].isConst();
00255 }
00256 
00257 
00258 template <class Scalar>
00259 RCP<MultiVectorBase<Scalar> >
00260 DefaultProductVector<Scalar>::getNonconstMultiVectorBlock(const int k)
00261 {
00262   return getNonconstVectorBlock(k);
00263 }
00264 
00265 
00266 template <class Scalar>
00267 RCP<const MultiVectorBase<Scalar> >
00268 DefaultProductVector<Scalar>::getMultiVectorBlock(const int k) const
00269 {
00270   return getVectorBlock(k);
00271 }
00272 
00273 
00274 // Overridden from VectorBase
00275 
00276 
00277 template <class Scalar>
00278 RCP< const VectorSpaceBase<Scalar> >
00279 DefaultProductVector<Scalar>::space() const
00280 {
00281   return productSpace_;
00282 }
00283 
00284 
00285 template <class Scalar>
00286 void DefaultProductVector<Scalar>::applyOpImpl(
00287   const RTOpPack::RTOpT<Scalar> &op,
00288   const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
00289   const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
00290   const Ptr<RTOpPack::ReductTarget> &reduct_obj,
00291   const Index first_ele_offset_in,
00292   const Index sub_dim_in,
00293   const Index global_offset_in
00294   ) const
00295 {
00296 
00297   // 2008/02/20: rabartl: ToDo: Upgrade Teuchos::Workspace<T> to implicitly
00298   // convert to Teuchos::ArrayView<T>.  This will allow the calls to
00299   // applyOp(...) with sub_vecs and sub_targ_vecs to work without trouble!
00300   // For now, I just want to get this done.  It is likely that this function
00301   // is going to change in major ways soon anyway!
00302 
00303   //using Teuchos::Workspace;
00304   using Teuchos::ptr_dynamic_cast;
00305   using Teuchos::describe;
00306   using Teuchos::null;
00307 
00308   //Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00309 
00310   const Index n = productSpace_->dim();
00311   const int num_vecs = vecs.size();
00312   const int num_targ_vecs = targ_vecs.size();
00313 
00314   // Validate the compatibility of the vectors!
00315 #ifdef TEUCHOS_DEBUG
00316   TEST_FOR_EXCEPTION(
00317     !(0 <= first_ele_offset_in && first_ele_offset_in < n), std::out_of_range
00318     ,"DefaultProductVector::applyOp(...): Error, "
00319     "first_ele_offset_in = " << first_ele_offset_in << " is not in range [0,"<<(n-1)<<"]" );
00320   TEST_FOR_EXCEPTION(
00321     global_offset_in < 0, std::invalid_argument
00322     ,"DefaultProductVector::applyOp(...): Error, "
00323     "global_offset_in = " << global_offset_in << " is not acceptable" );
00324   TEST_FOR_EXCEPTION(
00325     sub_dim_in >= 0 && sub_dim_in - first_ele_offset_in > n, std::length_error
00326     ,"DefaultProductVector::applyOp(...): Error, "
00327     "global_offset_in = " << global_offset_in << ", sub_dim_in = " << sub_dim_in
00328     << "first_ele_offset_in = " << first_ele_offset_in << " and n = " << n
00329     << " are not compatible" );
00330   bool test_failed;
00331   for(int k = 0; k < num_vecs; ++k) {
00332     test_failed = !this->space()->isCompatible(*vecs[k]->space());
00333     TEST_FOR_EXCEPTION(
00334       test_failed, Exceptions::IncompatibleVectorSpaces
00335       ,"DefaultProductVector::applyOp(...): Error vecs["<<k<<"]->space() = "
00336       <<vecs[k]->space()->description()<<"\' is not compatible with this "
00337       <<"vector space = "<<this->space()->description()<<"!"
00338       );
00339   }
00340   for(int k = 0; k < num_targ_vecs; ++k) {
00341     test_failed = !this->space()->isCompatible(*targ_vecs[k]->space());
00342     TEST_FOR_EXCEPTION(
00343       test_failed, Exceptions::IncompatibleVectorSpaces
00344       ,"DefaultProductVector::applyOp(...): Error targ_vecs["<<k<<"]->space() = "
00345       <<targ_vecs[k]->space()->description()<<"\' is not compatible with this "
00346       <<"vector space = "<<this->space()->description()<<"!"
00347       );
00348   }
00349 #endif
00350 
00351   //
00352   // The first thing that we do is to see if all of the vectors involved are
00353   // incore, serial vectors. In this case, the vectors should be compatible.
00354   // To accomplish this we will pick the continguous vector to implement
00355   // the applyOp(...) function.
00356   //
00357   // Get the index of an incore-only input vector and input/output vector?
00358   const bool this_isInCore = productSpace_->hasInCoreView(
00359     Range1D(),VIEW_TYPE_DETACHED,STRIDE_TYPE_NONUNIT
00360     );
00361   int incore_vec_k = -1, incore_targ_vec_k = -1;
00362 
00363   // Dynamic cast the pointers for the vector arguments
00364   Array<Ptr<const ProductVectorBase<Scalar> > >
00365     vecs_args(num_vecs);
00366   for(int k = 0; k < num_vecs; ++k) {
00367     vecs_args[k] = ptr_dynamic_cast<const ProductVectorBase<Scalar> >(vecs[k]);
00368     if( vecs_args[k] == null ) {
00369       const bool isInCore_k = vecs[k]->space()->hasInCoreView();
00370       if( this_isInCore && isInCore_k ) {
00371         incore_vec_k = k;
00372         break;
00373       }
00374       TEST_FOR_EXCEPTION(
00375         !this_isInCore || (this_isInCore && !isInCore_k),
00376         Exceptions::IncompatibleVectorSpaces
00377         ,"DefaultProductVector::applyOp(...): Error vecs["<<k<<"] "
00378         <<"of type \'"<<typeName(*vecs[k])<<"\' does not support the "
00379         <<"\'DefaultProductVector<Scalar>\' interface and is not an incore"
00380         "vector or this is not an incore vector!"
00381         );
00382     }
00383   }
00384   Array<Ptr<ProductVectorBase<Scalar> > >
00385     targ_vecs_args(num_targ_vecs);
00386   for(int k = 0; k < num_targ_vecs; ++k) {
00387     targ_vecs_args[k] = ptr_dynamic_cast<ProductVectorBase<Scalar> >(targ_vecs[k]);
00388     if( targ_vecs_args[k] == null ) {
00389       const bool isInCore_k = targ_vecs[k]->space()->hasInCoreView();
00390       if( this_isInCore && isInCore_k ) {
00391         incore_targ_vec_k = k;
00392         break;
00393       }
00394       TEST_FOR_EXCEPTION(
00395         !this_isInCore || (this_isInCore && !isInCore_k),
00396         Exceptions::IncompatibleVectorSpaces
00397         ,"DefaultProductVector::applyOp(...): Error targ_vecs["<<k<<"] "
00398         <<"of type \'"<<typeName(*targ_vecs[k])<<"\' does not support the "
00399         <<"\'DefaultProductVector<Scalar>\' interface and is not an incore"
00400         " vector or this is not an incore vector!"
00401         );
00402     }
00403   }
00404 
00405   // Let a incore-only vector with a contiguous view handle this through
00406   // explicit vector access?
00407   if( incore_vec_k >= 0 ) {
00408     vecs[incore_vec_k]->applyOp(
00409       op, vecs, targ_vecs, reduct_obj,
00410       first_ele_offset_in, sub_dim_in, global_offset_in );
00411     return;
00412   }
00413   else if ( incore_targ_vec_k >= 0 ) {
00414     targ_vecs[incore_targ_vec_k]->applyOp(
00415       op, vecs, targ_vecs, reduct_obj,
00416       first_ele_offset_in, sub_dim_in, global_offset_in
00417       );
00418     return;
00419   }
00420 
00421   //
00422   // If we get here, then we will implement the applyOpImpl(...) one vector
00423   // block at a time.
00424   //
00425   const Index this_dim = n;
00426   const Index sub_dim
00427     = (
00428       sub_dim_in < 0
00429       ? this_dim - first_ele_offset_in
00430       : sub_dim_in
00431       );
00432   Index num_elements_remaining = sub_dim;
00433   const int numBlocks = productSpace_->numBlocks();
00434   Array<RCP<const VectorBase<Scalar> > >
00435     sub_vecs_rcps(num_vecs);
00436   Array<Ptr<const VectorBase<Scalar> > >
00437     sub_vecs(num_vecs);
00438   Array<RCP<VectorBase<Scalar> > >
00439     sub_targ_vecs_rcps(num_targ_vecs);
00440   Array<Ptr<VectorBase<Scalar> > >
00441     sub_targ_vecs(num_targ_vecs);
00442   Index g_off = -first_ele_offset_in;
00443   for(int k = 0; k < numBlocks; ++k) {
00444     const Index local_dim = productSpace_->getBlock(k)->dim();
00445     if( g_off < 0 && -g_off+1 > local_dim ) {
00446       g_off += local_dim;
00447       continue;
00448     }
00449     const Index
00450       local_sub_dim
00451       = ( g_off >= 0
00452         ? std::min( local_dim, num_elements_remaining )
00453         : std::min( local_dim + g_off, num_elements_remaining ) );
00454     if( local_sub_dim <= 0 )
00455       break;
00456     // Fill constituent vectors for block k
00457     for( int i = 0; i < num_vecs; ++i ) {
00458       sub_vecs_rcps[i] = vecs_args[i]->getVectorBlock(k);
00459       sub_vecs[i] = sub_vecs_rcps[i].ptr();
00460     }
00461     // Fill constituent target vectors for block k
00462     for( int j = 0; j < num_targ_vecs; ++j ) {
00463       sub_targ_vecs_rcps[j] = targ_vecs_args[j]->getNonconstVectorBlock(k);
00464       sub_targ_vecs[j] = sub_targ_vecs_rcps[j].ptr();
00465     }
00466     Thyra::applyOp<Scalar>(
00467       op, sub_vecs(), sub_targ_vecs(),
00468       reduct_obj,
00469       g_off < 0 ? -g_off : 0, // first_ele_offset
00470       local_sub_dim, // sub_dim
00471       g_off < 0 ? global_offset_in : global_offset_in + g_off // global_offset
00472       );
00473     g_off += local_dim;
00474     num_elements_remaining -= local_sub_dim;
00475   }
00476   TEST_FOR_EXCEPT(!(num_elements_remaining==0));
00477 
00478 }
00479 
00480 
00481 // protected
00482 
00483 
00484 // Overridden protected functions from VectorBase
00485 
00486 
00487 template <class Scalar>
00488 void DefaultProductVector<Scalar>::acquireDetachedVectorViewImpl(
00489   const Range1D& rng_in, RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00490   ) const
00491 {
00492   const Range1D
00493     rng = rng_in.full_range() ? Range1D(0,productSpace_->dim()-1) : rng_in;
00494   int    kth_vector_space  = -1;
00495   Index  kth_global_offset = 0;
00496   productSpace_->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00497 #ifdef TEUCHOS_DEBUG
00498   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00499 #endif
00500   if(
00501     rng.lbound() + rng.size()
00502     <= kth_global_offset + vecs_[kth_vector_space].getConstObj()->space()->dim()
00503     )
00504   {
00505     // This involves only one sub-vector so just return it.
00506     const_cast<const VectorBase<Scalar>*>(
00507       &*vecs_[kth_vector_space].getConstObj()
00508       )->acquireDetachedView( rng - kth_global_offset, sub_vec );
00509     sub_vec->setGlobalOffset( sub_vec->globalOffset() + kth_global_offset );
00510   }
00511   else {
00512     // Just let the default implementation handle this.  ToDo: In the future
00513     // we could manually construct an explicit sub-vector that spanned
00514     // two or more constituent vectors but this would be a lot of work.
00515     // However, this would require the use of temporary memory but
00516     // so what.
00517     VectorDefaultBase<Scalar>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00518   }
00519 }
00520 
00521 
00522 template <class Scalar>
00523 void DefaultProductVector<Scalar>::releaseDetachedVectorViewImpl(
00524   RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00525   ) const
00526 {
00527   if( sub_vec->values().get() == NULL ) return;
00528   int    kth_vector_space  = -1;
00529   Index  kth_global_offset = 0;
00530   productSpace_->getVecSpcPoss(sub_vec->globalOffset(),&kth_vector_space,&kth_global_offset);
00531 #ifdef TEUCHOS_DEBUG
00532   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00533 #endif
00534   if(
00535     sub_vec->globalOffset() + sub_vec->subDim()
00536     <= kth_global_offset +  vecs_[kth_vector_space].getConstObj()->space()->dim()
00537     )
00538   {
00539     // This sub_vec was extracted from a single constituent vector
00540     sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00541     vecs_[kth_vector_space].getConstObj()->releaseDetachedView(sub_vec);
00542   }
00543   else {
00544     // This sub_vec was created by the default implementation!
00545     VectorDefaultBase<Scalar>::releaseDetachedVectorViewImpl(sub_vec);
00546   }
00547 }
00548 
00549 
00550 template <class Scalar>
00551 void DefaultProductVector<Scalar>::acquireNonconstDetachedVectorViewImpl(
00552   const Range1D& rng_in, RTOpPack::SubVectorView<Scalar>* sub_vec
00553   )
00554 {
00555   const Range1D
00556     rng = rng_in.full_range() ? Range1D(0,productSpace_->dim()-1) : rng_in;
00557   int    kth_vector_space  = -1;
00558   Index  kth_global_offset = 0;
00559   productSpace_->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00560 #ifdef TEUCHOS_DEBUG
00561   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00562 #endif
00563   if(
00564     rng.lbound() + rng.size()
00565     <= kth_global_offset + vecs_[kth_vector_space].getConstObj()->space()->dim()
00566     )
00567   {
00568     // This involves only one sub-vector so just return it.
00569     vecs_[kth_vector_space].getConstObj()->acquireDetachedView(
00570       rng - kth_global_offset, sub_vec
00571       );
00572     sub_vec->setGlobalOffset( sub_vec->globalOffset() + kth_global_offset );
00573   }
00574   else {
00575     // Just let the default implementation handle this.  ToDo: In the future
00576     // we could manually construct an explicit sub-vector that spanned
00577     // two or more constituent vectors but this would be a lot of work.
00578     // However, this would require the use of temporary memory but
00579     // so what.
00580     VectorDefaultBase<Scalar>::acquireNonconstDetachedVectorViewImpl(rng_in,sub_vec);
00581   }
00582 }
00583 
00584 
00585 template <class Scalar>
00586 void DefaultProductVector<Scalar>::commitNonconstDetachedVectorViewImpl(
00587   RTOpPack::SubVectorView<Scalar>* sub_vec
00588   )
00589 {
00590   if( sub_vec->values().get() == NULL ) return;
00591   int    kth_vector_space  = -1;
00592   Index  kth_global_offset = 0;
00593   productSpace_->getVecSpcPoss(sub_vec->globalOffset(),&kth_vector_space,&kth_global_offset);
00594 #ifdef TEUCHOS_DEBUG
00595   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00596 #endif
00597   if(
00598     sub_vec->globalOffset() + sub_vec->subDim()
00599     <= kth_global_offset +  vecs_[kth_vector_space].getConstObj()->space()->dim()
00600     )
00601   {
00602     // This sub_vec was extracted from a single constituent vector
00603     sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00604     vecs_[kth_vector_space].getNonconstObj()->commitDetachedView(sub_vec);
00605   }
00606   else {
00607     // This sub_vec was created by the default implementation!
00608     VectorDefaultBase<Scalar>::commitNonconstDetachedVectorViewImpl(sub_vec);
00609   }
00610 }
00611 
00612 
00613 template <class Scalar>
00614 void DefaultProductVector<Scalar>::setSubVectorImpl(
00615   const RTOpPack::SparseSubVectorT<Scalar>& sub_vec
00616   )
00617 {
00618   int    kth_vector_space  = -1;
00619   Index  kth_global_offset = 0;
00620   productSpace_->getVecSpcPoss(sub_vec.globalOffset(),&kth_vector_space,&kth_global_offset);
00621 #ifdef TEUCHOS_DEBUG
00622   TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00623 #endif
00624   if(
00625     sub_vec.globalOffset() + sub_vec.subDim()
00626     <= kth_global_offset + vecs_[kth_vector_space].getConstObj()->space()->dim()
00627     )
00628   {
00629     // This sub-vector fits into a single constituent vector
00630     RTOpPack::SparseSubVectorT<Scalar> sub_vec_g = sub_vec;
00631     sub_vec_g.setGlobalOffset( sub_vec_g.globalOffset() - kth_global_offset );
00632     vecs_[kth_vector_space].getNonconstObj()->setSubVector(sub_vec_g);
00633   }
00634   else {
00635     // Let the default implementation take care of this.  ToDo: In the future
00636     // it would be possible to manually set the relevant constituent
00637     // vectors with no temp memory allocations.
00638     VectorDefaultBase<Scalar>::setSubVector(sub_vec);
00639   }
00640 }
00641 
00642 
00643 } // namespace Thyra
00644 
00645 
00646 #endif // THYRA_DEFAULT_PRODUCT_VECTOR_DEF_HPP

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