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_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
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
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
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);
00179 }
00180 }
00181
00182
00183
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
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
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
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
00298
00299
00300
00301
00302
00303
00304 using Teuchos::ptr_dynamic_cast;
00305 using Teuchos::describe;
00306 using Teuchos::null;
00307
00308
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
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
00353
00354
00355
00356
00357
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
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
00406
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
00423
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
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
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,
00470 local_sub_dim,
00471 g_off < 0 ? global_offset_in : global_offset_in + g_off
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
00482
00483
00484
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
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
00513
00514
00515
00516
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
00540 sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00541 vecs_[kth_vector_space].getConstObj()->releaseDetachedView(sub_vec);
00542 }
00543 else {
00544
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
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
00576
00577
00578
00579
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
00603 sub_vec->setGlobalOffset( sub_vec->globalOffset() - kth_global_offset );
00604 vecs_[kth_vector_space].getNonconstObj()->commitDetachedView(sub_vec);
00605 }
00606 else {
00607
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
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
00636
00637
00638 VectorDefaultBase<Scalar>::setSubVector(sub_vec);
00639 }
00640 }
00641
00642
00643 }
00644
00645
00646 #endif // THYRA_DEFAULT_PRODUCT_VECTOR_DEF_HPP