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_SPACE_HPP
00030 #define THYRA_DEFAULT_PRODUCT_VECTOR_SPACE_HPP
00031
00032
00033 #include "Thyra_DefaultProductVectorSpace_decl.hpp"
00034 #include "Thyra_DefaultProductVector.hpp"
00035 #include "Thyra_DefaultProductMultiVector.hpp"
00036 #include "Thyra_ProductMultiVectorBase.hpp"
00037 #include "Teuchos_Workspace.hpp"
00038 #include "Teuchos_dyn_cast.hpp"
00039
00040
00041 namespace Thyra {
00042
00043
00044
00045
00046
00047 template<class Scalar>
00048 DefaultProductVectorSpace<Scalar>::DefaultProductVectorSpace()
00049 : numBlocks_(-1), dim_(-1)
00050 {}
00051
00052
00053 template<class Scalar>
00054 DefaultProductVectorSpace<Scalar>::DefaultProductVectorSpace(
00055 const ArrayView<const RCP<const VectorSpaceBase<Scalar> > > &vecSpaces_in
00056 )
00057 : numBlocks_(-1), dim_(-1)
00058 {
00059 initialize(vecSpaces_in);
00060 }
00061
00062
00063 template<class Scalar>
00064 void DefaultProductVectorSpace<Scalar>::initialize(
00065 const ArrayView<const RCP<const VectorSpaceBase<Scalar> > > &vecSpaces_in
00066 )
00067 {
00068
00069
00070
00071
00072 const int nBlocks = vecSpaces_in.size();
00073 #ifdef TEUCHOS_DEBUG
00074 TEST_FOR_EXCEPT( nBlocks == 0 );
00075 #endif
00076 bool overallHasInCoreView = true;
00077 for (int k = 0; k < nBlocks; ++k) {
00078 #ifdef TEUCHOS_DEBUG
00079 TEST_FOR_EXCEPTION(
00080 vecSpaces_in[k].get() == NULL, std::invalid_argument
00081 ,"Error, the smart pointer vecSpaces["<<k<<"] can not be NULL!"
00082 );
00083 #endif
00084 if (!vecSpaces_in[k]->hasInCoreView()) overallHasInCoreView = false;
00085 }
00086
00087
00088
00089
00090 numBlocks_ = nBlocks;
00091 vecSpaces_ = Teuchos::rcp(new vecSpaces_t);
00092 *vecSpaces_ = vecSpaces_in;
00093 vecSpacesOffsets_ = Teuchos::rcp(new vecSpacesOffsets_t(nBlocks+1));
00094 (*vecSpacesOffsets_)[0] = 0;
00095 dim_ = 0;
00096 for( int k = 1; k <= nBlocks; ++k ) {
00097 const Ordinal dim_km1 = vecSpaces_in[k-1]->dim();
00098 (*vecSpacesOffsets_)[k] = (*vecSpacesOffsets_)[k-1] + dim_km1;
00099 dim_ += dim_km1;
00100 }
00101 isInCore_ = overallHasInCoreView;
00102
00103 }
00104
00105
00106 template<class Scalar>
00107 void DefaultProductVectorSpace<Scalar>::uninitialize(
00108 const ArrayView<RCP<const VectorSpaceBase<Scalar> > > &vecSpaces_in
00109 )
00110 {
00111 TEST_FOR_EXCEPT(!is_null(vecSpaces_in));
00112 vecSpaces_ = Teuchos::null;
00113 vecSpacesOffsets_ = Teuchos::null;
00114 numBlocks_ = -1;
00115 dim_ = -1;
00116 isInCore_ = false;
00117 }
00118
00119
00120 template<class Scalar>
00121 void DefaultProductVectorSpace<Scalar>::getVecSpcPoss(
00122 Ordinal i, int* kth_vector_space, Ordinal* kth_global_offset
00123 ) const
00124 {
00125
00126 #ifdef TEUCHOS_DEBUG
00127 TEST_FOR_EXCEPTION(
00128 !(0 <= i && i < this->dim()), std::out_of_range
00129 ,"VectorSpaceBlocked::get_vector_space_position(...): Error, i = "
00130 << i << " is not in range [0,"<<(this->dim()-1)<<"]"
00131 );
00132 #endif
00133 *kth_vector_space = 0;
00134 *kth_global_offset = 0;
00135 while( *kth_vector_space < numBlocks_ ) {
00136 const Ordinal off_kp1 = (*vecSpacesOffsets_)[*kth_vector_space+1];
00137 if( off_kp1 > i ) {
00138 *kth_global_offset = (*vecSpacesOffsets_)[*kth_vector_space];
00139 break;
00140 }
00141 ++(*kth_vector_space);
00142 }
00143 TEST_FOR_EXCEPT( !(*kth_vector_space < numBlocks_) );
00144 }
00145
00146
00147
00148
00149
00150 template<class Scalar>
00151 int DefaultProductVectorSpace<Scalar>::numBlocks() const
00152 {
00153 return numBlocks_;
00154 }
00155
00156
00157 template<class Scalar>
00158 Teuchos::RCP<const VectorSpaceBase<Scalar> >
00159 DefaultProductVectorSpace<Scalar>::getBlock(const int k) const
00160 {
00161 TEST_FOR_EXCEPT( k < 0 || numBlocks_ < k );
00162 return (*vecSpaces_)[k];
00163 }
00164
00165
00166
00167
00168
00169 template<class Scalar>
00170 Ordinal DefaultProductVectorSpace<Scalar>::dim() const
00171 {
00172 return dim_;
00173 }
00174
00175
00176 template<class Scalar>
00177 bool DefaultProductVectorSpace<Scalar>::isCompatible(
00178 const VectorSpaceBase<Scalar>& vecSpc ) const
00179 {
00180
00181 using Teuchos::ptrFromRef;
00182 using Teuchos::ptr_dynamic_cast;
00183
00184 const int nBlocks = this->numBlocks();
00185
00186
00187 const Ptr<const ProductVectorSpaceBase<Scalar> > pvsb =
00188 ptr_dynamic_cast<const ProductVectorSpaceBase<Scalar> >(ptrFromRef(vecSpc));
00189
00190 if (nonnull(pvsb)) {
00191
00192 if( nBlocks != pvsb->numBlocks() )
00193 return false;
00194 for( int i = 0; i < nBlocks; ++i ) {
00195 if( !this->getBlock(i)->isCompatible(*pvsb->getBlock(i)) )
00196 return false;
00197 }
00198 return true;
00199 }
00200
00201
00202 if (nBlocks == 1) {
00203 return this->getBlock(0)->isCompatible(vecSpc);
00204 }
00205
00206
00207 if (this->hasInCoreView(Range1D(), VIEW_TYPE_DETACHED, STRIDE_TYPE_NONUNIT)
00208 && vecSpc.hasInCoreView() && ( this->dim() == vecSpc.dim() ) )
00209 {
00210 return true;
00211 }
00212
00213
00214
00215
00216
00217
00218 return false;
00219
00220 }
00221
00222
00223 template<class Scalar>
00224 Teuchos::RCP< VectorBase<Scalar> >
00225 DefaultProductVectorSpace<Scalar>::createMember() const
00226 {
00227 return defaultProductVector<Scalar>(Teuchos::rcpFromRef(*this));
00228 }
00229
00230
00231 template<class Scalar>
00232 Scalar DefaultProductVectorSpace<Scalar>::scalarProd(
00233 const VectorBase<Scalar> &x_in,
00234 const VectorBase<Scalar> &y_in
00235 ) const
00236 {
00237 const int nBlocks = this->numBlocks();
00238 const ProductVectorBase<Scalar>
00239 &x = Teuchos::dyn_cast<const ProductVectorBase<Scalar> >(x_in),
00240 &y = Teuchos::dyn_cast<const ProductVectorBase<Scalar> >(y_in);
00241 #ifdef TEUCHOS_DEBUG
00242 TEST_FOR_EXCEPT(
00243 nBlocks!=x.productSpace()->numBlocks()
00244 || nBlocks!=y.productSpace()->numBlocks()
00245 );
00246 #endif
00247 Scalar scalarProd_rtn = Teuchos::ScalarTraits<Scalar>::zero();
00248 for( int k = 0; k < nBlocks; ++k )
00249 scalarProd_rtn += (*vecSpaces_)[k]->scalarProd(
00250 *x.getVectorBlock(k),*y.getVectorBlock(k)
00251 );
00252 return scalarProd_rtn;
00253 }
00254
00255
00256 template<class Scalar>
00257 void DefaultProductVectorSpace<Scalar>::scalarProdsImpl(
00258 const MultiVectorBase<Scalar> &X_in,
00259 const MultiVectorBase<Scalar> &Y_in,
00260 const ArrayView<Scalar> &scalarProds_out
00261 ) const
00262 {
00263 using Teuchos::as;
00264 using Teuchos::Workspace;
00265 const VectorSpaceBase<Scalar> &domain = *X_in.domain();
00266 const Ordinal m = domain.dim();
00267 #ifdef TEUCHOS_DEBUG
00268 TEST_FOR_EXCEPT(is_null(scalarProds_out));
00269 TEST_FOR_EXCEPT( !domain.isCompatible(*Y_in.domain()) );
00270 TEUCHOS_ASSERT_EQUALITY( as<Ordinal>(scalarProds_out.size()),
00271 as<Ordinal>(m) )
00272 #endif
00273 if(m==1) {
00274 scalarProds_out[0] = this->scalarProd(*X_in.col(0),*Y_in.col(0));
00275 return;
00276
00277 }
00278 Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00279 const int nBlocks = this->numBlocks();
00280 const ProductMultiVectorBase<Scalar>
00281 &X = Teuchos::dyn_cast<const ProductMultiVectorBase<Scalar> >(X_in),
00282 &Y = Teuchos::dyn_cast<const ProductMultiVectorBase<Scalar> >(Y_in);
00283 #ifdef TEUCHOS_DEBUG
00284 TEST_FOR_EXCEPT( nBlocks!=X.productSpace()->numBlocks() || nBlocks!=Y.productSpace()->numBlocks() );
00285 #endif
00286 Workspace<Scalar> _scalarProds_out(wss, m, false);
00287 std::fill( scalarProds_out.begin(), scalarProds_out.end(),
00288 ScalarTraits<Scalar>::zero() );
00289 for( int k = 0; k < nBlocks; ++k ) {
00290 (*vecSpaces_)[k]->scalarProds(
00291 *X.getMultiVectorBlock(k), *Y.getMultiVectorBlock(k), _scalarProds_out());
00292 for( int j = 0; j < m; ++j )
00293 scalarProds_out[j] += _scalarProds_out[j];
00294 }
00295 }
00296
00297
00298 template<class Scalar>
00299 bool DefaultProductVectorSpace<Scalar>::hasInCoreView(const Range1D& rng_in, const EViewType viewType, const EStrideType strideType) const
00300 {
00301 const Range1D rng = full_range(rng_in,0,dim_-1);
00302
00303 int kth_vector_space = -1;
00304 Ordinal kth_global_offset = 0;
00305 this->getVecSpcPoss(rng.lbound(),&kth_vector_space,&kth_global_offset);
00306 #ifdef TEUCHOS_DEBUG
00307 TEST_FOR_EXCEPT( !( 0 <= kth_vector_space && kth_vector_space <= numBlocks_ ) );
00308 #endif
00309 if( rng.lbound() + rng.size() <= kth_global_offset + (*vecSpaces_)[kth_vector_space]->dim() ) {
00310 return (*vecSpaces_)[kth_vector_space]->hasInCoreView(rng_in-kth_global_offset,viewType,strideType);
00311 }
00312
00313
00314
00315
00316
00317 if( viewType == VIEW_TYPE_DIRECT )
00318 return false;
00319
00320
00321
00322 if(isInCore_)
00323 return true;
00324
00325
00326
00327
00328
00329
00330 return false;
00331 }
00332
00333
00334 template<class Scalar>
00335 Teuchos::RCP< const VectorSpaceFactoryBase<Scalar> >
00336 DefaultProductVectorSpace<Scalar>::smallVecSpcFcty() const
00337 {
00338 if (dim_)
00339 return (*vecSpaces_)[0]->smallVecSpcFcty();
00340 return Teuchos::null;
00341 }
00342
00343
00344 template<class Scalar>
00345 Teuchos::RCP< MultiVectorBase<Scalar> >
00346 DefaultProductVectorSpace<Scalar>::createMembers(int numMembers) const
00347 {
00348 return defaultProductMultiVector<Scalar>(Teuchos::rcpFromRef(*this),
00349 numMembers);
00350 }
00351
00352
00353 template<class Scalar>
00354 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00355 DefaultProductVectorSpace<Scalar>::clone() const
00356 {
00357
00358
00359
00360 Teuchos::RCP<DefaultProductVectorSpace<Scalar> >
00361 pvs = productVectorSpace<Scalar>();
00362 pvs->numBlocks_ = numBlocks_;
00363 pvs->vecSpaces_ = vecSpaces_;
00364 pvs->vecSpacesOffsets_ = vecSpacesOffsets_;
00365 pvs->dim_ = dim_;
00366 pvs->isInCore_ = isInCore_;
00367 return pvs;
00368 }
00369
00370
00371
00372
00373
00374 template<class Scalar>
00375 std::string DefaultProductVectorSpace<Scalar>::description() const
00376 {
00377 std::ostringstream oss;
00378 oss
00379 << Teuchos::Describable::description() << "{"
00380 << "dim="<<dim_
00381 << ",numBlocks="<<numBlocks_
00382 << "}";
00383 return oss.str();
00384 }
00385
00386
00387 template<class Scalar>
00388 void DefaultProductVectorSpace<Scalar>::describe(
00389 Teuchos::FancyOStream &out_arg
00390 ,const Teuchos::EVerbosityLevel verbLevel
00391 ) const
00392 {
00393 typedef Teuchos::ScalarTraits<Scalar> ST;
00394 using Teuchos::RCP;
00395 using Teuchos::FancyOStream;
00396 using Teuchos::OSTab;
00397 RCP<FancyOStream> out = rcpFromRef(out_arg);
00398 OSTab tab(out);
00399 switch(verbLevel) {
00400 case Teuchos::VERB_NONE:
00401 break;
00402 case Teuchos::VERB_DEFAULT:
00403 case Teuchos::VERB_LOW:
00404 *out << this->description() << std::endl;
00405 break;
00406 case Teuchos::VERB_MEDIUM:
00407 case Teuchos::VERB_HIGH:
00408 case Teuchos::VERB_EXTREME:
00409 {
00410 *out << this->description() << std::endl;
00411 if (numBlocks_ <= 0)
00412 break;
00413 OSTab tab2(out);
00414 *out
00415 << "Constituent vector spaces V[0], V[1], ... V[numBlocks-1]:\n";
00416 OSTab tab3(out);
00417 for( int k = 0; k < numBlocks_; ++k ) {
00418 *out << "V["<<k<<"] = " << Teuchos::describe(*(*vecSpaces_)[k],verbLevel);
00419 }
00420 break;
00421 }
00422 default:
00423 TEST_FOR_EXCEPT(true);
00424 }
00425 }
00426
00427
00428 }
00429
00430
00431 #endif // THYRA_DEFAULT_PRODUCT_VECTOR_SPACE_HPP