00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef THYRA_PRODUCT_VECTOR_HPP
00030 #define THYRA_PRODUCT_VECTOR_HPP
00031
00032 #include "Thyra_ProductVectorDecl.hpp"
00033 #include "Thyra_ProductVectorSpace.hpp"
00034 #include "Teuchos_Workspace.hpp"
00035
00036 namespace Thyra {
00037
00038
00039
00040 template <class Scalar>
00041 ProductVector<Scalar>::ProductVector()
00042 {
00043 uninitialize();
00044 }
00045
00046 template <class Scalar>
00047 ProductVector<Scalar>::ProductVector(
00048 const Teuchos::RefCountPtr<const ProductVectorSpace<Scalar> > &productSpace
00049 ,const Teuchos::RefCountPtr<VectorBase<Scalar> > vecs[]
00050 )
00051 {
00052 initialize(productSpace,vecs);
00053 }
00054
00055 template <class Scalar>
00056 void ProductVector<Scalar>::initialize(
00057 const Teuchos::RefCountPtr<const ProductVectorSpace<Scalar> > &productSpace
00058 ,const Teuchos::RefCountPtr<VectorBase<Scalar> > vecs[]
00059 )
00060 {
00061
00062 numBlocks_ = productSpace->numBlocks();
00063 productSpace_ = productSpace;
00064 vecs_.resize(numBlocks_);
00065 if(vecs) {
00066 std::copy( vecs, vecs + numBlocks_, &vecs_[0] );
00067 }
00068 else {
00069 for( int k = 0; k < numBlocks_; ++k )
00070 vecs_[k] = createMember(productSpace->getBlock(k));
00071 }
00072 }
00073
00074 template <class Scalar>
00075 void ProductVector<Scalar>::uninitialize(
00076 Teuchos::RefCountPtr<const ProductVectorSpace<Scalar> > *productSpace
00077 ,Teuchos::RefCountPtr<VectorBase<Scalar> > vecs[]
00078 )
00079 {
00080 if(productSpace) *productSpace = productSpace_;
00081 if(vecs) std::copy( &vecs_[0], &vecs_[0]+numBlocks_, vecs );
00082 productSpace_ = Teuchos::null;
00083 vecs_.resize(0);
00084 numBlocks_ = 0;
00085 }
00086
00087
00088
00089 template <class Scalar>
00090 Teuchos::RefCountPtr<const ProductVectorSpaceBase<Scalar> >
00091 ProductVector<Scalar>::productSpace() const
00092 {
00093 return productSpace_;
00094 }
00095
00096 template <class Scalar>
00097 Teuchos::RefCountPtr<VectorBase<Scalar> >
00098 ProductVector<Scalar>::getBlock(const int k)
00099 {
00100 TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00101 return vecs_[k];
00102 }
00103
00104 template <class Scalar>
00105 Teuchos::RefCountPtr<const VectorBase<Scalar> >
00106 ProductVector<Scalar>::getBlock(const int k) const
00107 {
00108 TEST_FOR_EXCEPT( k < 0 || numBlocks_-1 < k);
00109 return vecs_[k];
00110 }
00111
00112
00113
00114 template <class Scalar>
00115 Teuchos::RefCountPtr< const VectorSpaceBase<Scalar> >
00116 ProductVector<Scalar>::space() const
00117 {
00118 return productSpace_;
00119 }
00120
00121 template <class Scalar>
00122 void ProductVector<Scalar>::applyOp(
00123 const RTOpPack::RTOpT<Scalar> &op
00124 ,const int num_vecs
00125 ,const VectorBase<Scalar>* vecs[]
00126 ,const int num_targ_vecs
00127 ,VectorBase<Scalar>* targ_vecs[]
00128 ,RTOpPack::ReductTarget *reduct_obj
00129 ,const Index first_ele_in
00130 ,const Index sub_dim_in
00131 ,const Index global_offset_in
00132 ) const
00133 {
00134 using Teuchos::Workspace;
00135 Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00136
00137 const Index n = productSpace_->dim();
00138
00139 #ifdef _DEBUG
00140 TEST_FOR_EXCEPTION(
00141 !(1 <= first_ele_in && first_ele_in <= n), std::out_of_range
00142 ,"ProductVector::applyOp(...): Error, "
00143 "first_ele_in = " << first_ele_in << " is not in range [1,"<<n<<"]" );
00144 TEST_FOR_EXCEPTION(
00145 sub_dim_in < 0, std::invalid_argument
00146 ,"ProductVector::applyOp(...): Error, "
00147 "sub_dim_in = " << sub_dim_in << " is not acceptable" );
00148 TEST_FOR_EXCEPTION(
00149 global_offset_in < 0, std::invalid_argument
00150 ,"ProductVector::applyOp(...): Error, "
00151 "global_offset_in = " << global_offset_in << " is not acceptable" );
00152 TEST_FOR_EXCEPTION(
00153 sub_dim_in > 0 && sub_dim_in - (first_ele_in - 1) > n, std::length_error
00154 ,"ProductVector::applyOp(...): Error, "
00155 "global_offset_in = " << global_offset_in << ", sub_dim_in = " << sub_dim_in
00156 << "first_ele_in = " << first_ele_in << " and n = " << n
00157 << " are not compatible" );
00158 bool test_failed;
00159 for(int k = 0; k < num_vecs; ++k) {
00160 test_failed = !this->space()->isCompatible(*vecs[k]->space());
00161 TEST_FOR_EXCEPTION(
00162 test_failed, Exceptions::IncompatibleVectorSpaces
00163 ,"ProductVector::applyOp(...): Error vecs["<<k<<"]->space() "
00164 <<"of type \'"<<typeid(*vecs[k]->space()).name()<<"\' is not compatible with this "
00165 <<"\'VectorSpaceBlocked\' vector space!"
00166 );
00167 }
00168 for(int k = 0; k < num_targ_vecs; ++k) {
00169 test_failed = !this->space()->isCompatible(*targ_vecs[k]->space());
00170 TEST_FOR_EXCEPTION(
00171 test_failed, Exceptions::IncompatibleVectorSpaces
00172 ,"ProductVector::applyOp(...): Error targ_vecs["<<k<<"]->space() "
00173 <<"of type \'"<<typeid(*vecs[k]->space()).name()<<"\' is not compatible with this "
00174 <<"\'VectorSpaceBlocked\' vector space!"
00175 );
00176 }
00177 #endif
00178
00179 const bool this_isInCore = productSpace_->isInCore();
00180 int incore_vec_k = -1, incore_targ_vec_k = -1;
00181
00182 Workspace<const ProductVector<Scalar>*>
00183 vecs_args(wss,num_vecs,false);
00184 for(int k = 0; k < num_vecs; ++k) {
00185 vecs_args[k] = dynamic_cast<const ProductVector<Scalar>*>(vecs[k]);
00186 if( vecs_args[k] == NULL ) {
00187 const bool isInCore_k = vecs[k]->space()->isInCore();
00188 if( this_isInCore && isInCore_k ) {
00189 incore_vec_k = k;
00190 break;
00191 }
00192 TEST_FOR_EXCEPTION(
00193 !this_isInCore || (this_isInCore && !isInCore_k), Exceptions::IncompatibleVectorSpaces
00194 ,"ProductVector::applyOp(...): Error vecs["<<k<<"] "
00195 <<"of type \'"<<typeid(*vecs[k]).name()<<"\' does not support the "
00196 <<"\'ProductVector<Scalar>\' interface and is not an incore vector or this is not an incore vector!"
00197 );
00198 }
00199 }
00200 Workspace<ProductVector<Scalar>*>
00201 targ_vecs_args(wss,num_targ_vecs,false);
00202 for(int k = 0; k < num_targ_vecs; ++k) {
00203 targ_vecs_args[k] = dynamic_cast<ProductVector<Scalar>*>(targ_vecs[k]);
00204 if( targ_vecs_args[k] == NULL ) {
00205 const bool isInCore_k = targ_vecs[k]->space()->isInCore();
00206 if( this_isInCore && isInCore_k ) {
00207 incore_targ_vec_k = k;
00208 break;
00209 }
00210 TEST_FOR_EXCEPTION(
00211 !this_isInCore || (this_isInCore && !isInCore_k), Exceptions::IncompatibleVectorSpaces
00212 ,"ProductVector::applyOp(...): Error targ_vecs["<<k<<"] "
00213 <<"of type \'"<<typeid(*targ_vecs[k]).name()<<"\' does not support the "
00214 <<"\'ProductVector<Scalar>\' interface and is not an incore vector or this is not an incore vector!"
00215 );
00216 }
00217 }
00218
00219
00220 if( incore_vec_k >= 0 ) {
00221 vecs[incore_vec_k]->applyOp(
00222 op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj
00223 ,first_ele_in,sub_dim_in,global_offset_in
00224 );
00225 return;
00226 }
00227 else if ( incore_targ_vec_k >= 0 ) {
00228 targ_vecs[incore_targ_vec_k]->applyOp(
00229 op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj
00230 ,first_ele_in,sub_dim_in,global_offset_in
00231 );
00232 return;
00233 }
00234
00235 const Index this_dim = n;
00236 const Index sub_dim = ( sub_dim_in == 0
00237 ? this_dim - (first_ele_in - 1)
00238 : sub_dim_in );
00239 Index num_elements_remaining = sub_dim;
00240 const int numBlocks = productSpace_->numBlocks();
00241 Workspace<const VectorBase<Scalar>*>
00242 sub_vecs(wss,num_vecs,false);
00243 Workspace<VectorBase<Scalar>*>
00244 sub_targ_vecs(wss,num_targ_vecs,false);
00245 Index g_off = -first_ele_in + 1;
00246 for(int k = 0; k < numBlocks; ++k) {
00247 const Index local_dim = productSpace_->getBlock(k)->dim();
00248 if( g_off < 0 && -g_off > local_dim ) {
00249 g_off += local_dim;
00250 continue;
00251 }
00252 const Index
00253 local_sub_dim = ( g_off >= 0
00254 ? std::min( local_dim, num_elements_remaining )
00255 : std::min( local_dim + g_off, num_elements_remaining ) );
00256 if( local_sub_dim <= 0 )
00257 break;
00258 for( int i = 0; i < num_vecs; ++i )
00259 sub_vecs[i] = &*vecs_args[i]->vecs_[k];
00260 for( int j = 0; j < num_targ_vecs; ++j )
00261 sub_targ_vecs[j] = &*targ_vecs_args[j]->vecs_[k];
00262 Thyra::applyOp(
00263 op
00264 ,num_vecs,num_vecs?&sub_vecs[0]:NULL
00265 ,num_targ_vecs,num_targ_vecs?&sub_targ_vecs[0]:NULL
00266 ,reduct_obj
00267 ,g_off < 0 ? -g_off + 1 : 1
00268 ,local_sub_dim
00269 ,g_off < 0 ? global_offset_in : global_offset_in + g_off
00270 );
00271 g_off += local_dim;
00272 num_elements_remaining -= local_sub_dim;
00273 }
00274 TEST_FOR_EXCEPT(!(num_elements_remaining==0));
00275 }
00276
00277 template <class Scalar>
00278 void ProductVector<Scalar>::getSubVector(
00279 const Range1D& rng_in, RTOpPack::SubVectorT<Scalar>* sub_vec
00280 ) const
00281 {
00282 const Range1D
00283 rng = rng_in.full_range() ? Range1D( 1, productSpace_->dim()) : rng_in;
00284 int kth_vector_space = -1;
00285 Index kth_global_offset = 0;
00286 productSpace_->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00287 #ifdef _DEBUG
00288 TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00289 #endif
00290 if( rng.lbound() + rng.size() <= kth_global_offset + 1 + vecs_[kth_vector_space]->space()->dim() ) {
00291
00292 const_cast<const VectorBase<Scalar>*>(&*vecs_[kth_vector_space])->getSubVector(
00293 rng - kth_global_offset, sub_vec );
00294 sub_vec->setGlobalOffset( sub_vec->globalOffset() + kth_global_offset );
00295 }
00296 else {
00297
00298
00299
00300
00301
00302 VectorBase<Scalar>::getSubVector(rng_in,sub_vec);
00303 }
00304 }
00305
00306 template <class Scalar>
00307 void ProductVector<Scalar>::freeSubVector(
00308 RTOpPack::SubVectorT<Scalar>* sub_vec
00309 ) const
00310 {
00311 if( sub_vec->values() == NULL ) return;
00312 int kth_vector_space = -1;
00313 Index kth_global_offset = 0;
00314 productSpace_->getVecSpcPoss(sub_vec->globalOffset()+1,&kth_vector_space,&kth_global_offset);
00315 #ifdef _DEBUG
00316 TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00317 #endif
00318 if( sub_vec->globalOffset() + sub_vec->subDim() <= kth_global_offset + vecs_[kth_vector_space]->space()->dim() ) {
00319
00320 sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00321 vecs_[kth_vector_space]->freeSubVector(sub_vec);
00322 }
00323 else {
00324
00325 VectorBase<Scalar>::freeSubVector(sub_vec);
00326 }
00327 }
00328
00329 template <class Scalar>
00330 void ProductVector<Scalar>::getSubVector(
00331 const Range1D& rng_in, RTOpPack::MutableSubVectorT<Scalar>* sub_vec
00332 )
00333 {
00334 const Range1D
00335 rng = rng_in.full_range() ? Range1D( 1, productSpace_->dim()) : rng_in;
00336 int kth_vector_space = -1;
00337 Index kth_global_offset = 0;
00338 productSpace_->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00339 #ifdef _DEBUG
00340 TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00341 #endif
00342 if( rng.lbound() + rng.size() <= kth_global_offset + 1 + vecs_[kth_vector_space]->space()->dim() ) {
00343
00344 vecs_[kth_vector_space]->getSubVector(
00345 rng - kth_global_offset, sub_vec );
00346 sub_vec->setGlobalOffset( sub_vec->globalOffset() + kth_global_offset );
00347 }
00348 else {
00349
00350
00351
00352
00353
00354 VectorBase<Scalar>::getSubVector(rng_in,sub_vec);
00355 }
00356 }
00357
00358 template <class Scalar>
00359 void ProductVector<Scalar>::commitSubVector(
00360 RTOpPack::MutableSubVectorT<Scalar>* sub_vec
00361 )
00362 {
00363 if( sub_vec->values() == NULL ) return;
00364 int kth_vector_space = -1;
00365 Index kth_global_offset = 0;
00366 productSpace_->getVecSpcPoss(sub_vec->globalOffset()+1,&kth_vector_space,&kth_global_offset);
00367 #ifdef _DEBUG
00368 TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00369 #endif
00370 if( sub_vec->globalOffset() + sub_vec->subDim() <= kth_global_offset + vecs_[kth_vector_space]->space()->dim() ) {
00371
00372 sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00373 vecs_[kth_vector_space]->commitSubVector(sub_vec);
00374 }
00375 else {
00376
00377 VectorBase<Scalar>::commitSubVector(sub_vec);
00378 }
00379 }
00380
00381 template <class Scalar>
00382 void ProductVector<Scalar>::setSubVector(
00383 const RTOpPack::SparseSubVectorT<Scalar>& sub_vec
00384 )
00385 {
00386 int kth_vector_space = -1;
00387 Index kth_global_offset = 0;
00388 productSpace_->getVecSpcPoss(sub_vec.globalOffset()+1,&kth_vector_space,&kth_global_offset);
00389 #ifdef _DEBUG
00390 TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00391 #endif
00392 if( sub_vec.globalOffset() + sub_vec.subDim() <= kth_global_offset + vecs_[kth_vector_space]->space()->dim() ) {
00393
00394 RTOpPack::SparseSubVectorT<Scalar> sub_vec_g = sub_vec;
00395 sub_vec_g.setGlobalOffset( sub_vec_g.globalOffset() - kth_global_offset );
00396 vecs_[kth_vector_space]->setSubVector(sub_vec_g);
00397 }
00398 else {
00399
00400
00401
00402 VectorBase<Scalar>::setSubVector(sub_vec);
00403 }
00404 }
00405
00406 }
00407
00408 #endif // THYRA_PRODUCT_VECTOR_HPP