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

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