TSFVectorSpaceImpl.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 /* ***********************************************************************
00003 // 
00004 //           TSFExtended: Trilinos Solver Framework Extended
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 TSFVECTORSPACEIMPL_HPP
00030 #define TSFVECTORSPACEIMPL_HPP
00031 
00032 
00033 #include "Thyra_ProductVectorSpaceBase.hpp"
00034 #include "TSFVectorSpaceDecl.hpp"
00035 #include "TSFVectorDecl.hpp"
00036 #include "Thyra_SpmdVectorSpaceBase.hpp"
00037 #include "Teuchos_Describable.hpp"
00038 #include "Teuchos_Time.hpp"
00039 #include "Teuchos_TimeMonitor.hpp"
00040 
00041 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00042 #include "TSFSequentialIteratorImpl.hpp"
00043 #endif
00044 
00045 using namespace TSFExtended;
00046 using namespace Teuchos;
00047 
00048 
00049 static inline Time& createVecTimer() 
00050 {
00051   static RCP<Time> rtn 
00052     = TimeMonitor::getNewTimer("vector allocation"); 
00053   return *rtn;
00054 }
00055 
00056  
00057 //========================================================================
00058 template <class Scalar>
00059 bool VectorSpace<Scalar>::operator==(const VectorSpace<Scalar>& other) const 
00060 {
00061   return isCompatible(other);  
00062 }
00063 
00064 
00065 //========================================================================
00066 template <class Scalar>
00067 bool VectorSpace<Scalar>::operator!=(const VectorSpace<Scalar>& other) const 
00068 {
00069   return !(operator==(other));
00070 }
00071     
00072 
00073 
00074 //========================================================================
00075 template <class Scalar>
00076 Vector<Scalar> VectorSpace<Scalar>::createMember() const 
00077 {
00078   TimeMonitor timer(createVecTimer());
00079   Vector<Scalar> rtn = Thyra::createMember(this->ptr());
00080   rtn.setToConstant(0.0);
00081   return rtn;
00082 }
00083     
00084 
00085 
00086 //========================================================================
00087 template <class Scalar>
00088 int VectorSpace<Scalar>::lowestLocallyOwnedIndex() const
00089 {
00090   const Thyra::SpmdVectorSpaceBase<Scalar>* mpiSpace 
00091     = dynamic_cast<const Thyra::SpmdVectorSpaceBase<Scalar>*>(this->ptr().get());
00092   if (mpiSpace != 0)
00093     {
00094       return mpiSpace->localOffset();
00095     }
00096   const Thyra::SpmdVectorSpaceBase<Scalar>* serialSpace 
00097     = dynamic_cast<const Thyra::SpmdVectorSpaceBase<Scalar>*>(this->ptr().get());
00098    if (serialSpace != 0)
00099      {
00100        return 0;
00101      }
00102    TEST_FOR_EXCEPTION(mpiSpace == 0 && serialSpace==0, std::runtime_error,
00103           "don't know how to compute lowest local index for "
00104           "a vector space that is neither MPI nor serial");
00105    return 0;
00106 }
00107 
00108 //========================================================================
00109 template <class Scalar>
00110 int VectorSpace<Scalar>::numLocalElements() const
00111 {
00112   if (numBlocks() > 1)
00113   {
00114     int rtn = 0;
00115     for (int b=0; b<numBlocks(); b++) 
00116     {
00117       rtn += getBlock(b).numLocalElements();
00118     } 
00119     return rtn;
00120   }
00121   
00122   const Thyra::SpmdVectorSpaceBase<Scalar>* mpiSpace 
00123     = dynamic_cast<const Thyra::SpmdVectorSpaceBase<Scalar>*>(this->ptr().get());
00124   if (mpiSpace != 0)
00125     {
00126       return mpiSpace->localSubDim();
00127     }
00128    const Thyra::SpmdVectorSpaceBase<Scalar>* serialSpace 
00129     = dynamic_cast<const Thyra::SpmdVectorSpaceBase<Scalar>*>(this->ptr().get());
00130    if (serialSpace != 0)
00131      {
00132        return dim();
00133      }
00134    TEST_FOR_EXCEPTION(mpiSpace == 0 && serialSpace==0, std::runtime_error,
00135           "don't know how to compute number of local elements for "
00136           "a vector space that is neither MPI nor serial");
00137    return 0;
00138 }
00139     
00140 
00141 
00142 
00143 //========================================================================
00144 template <class Scalar>
00145 bool VectorSpace<Scalar>::isCompatible(const VectorSpace<Scalar>& vecSpc) const 
00146 {
00147   TEST_FOR_EXCEPTION(vecSpc.ptr().get() == 0, std::runtime_error,
00148                      "null argument in VectorSpace<Scalar>::isCompatible()");
00149   return this->ptr().get()->isCompatible(*(vecSpc.ptr().get()));
00150 }
00151 
00152 
00153 
00154 
00155 
00156 //========================================================================
00157 template <class Scalar>
00158 bool VectorSpace<Scalar>::contains(const Vector<Scalar> &vec) const
00159 {
00160   return (operator==(vec.space()));
00161 }
00162 
00163 
00164 //========================================================================
00165 template <class Scalar>
00166 int VectorSpace<Scalar>::numBlocks() const
00167 {
00168   const Thyra::ProductVectorSpaceBase<Scalar>* pvs = 
00169     dynamic_cast<const Thyra::ProductVectorSpaceBase<Scalar>* > (this->ptr().get());
00170   if (pvs != 0)
00171     {
00172       return pvs->numBlocks();
00173     }
00174   return 1;
00175 }
00176 
00177 
00178 
00179 //========================================================================
00180 template <class Scalar>
00181 VectorSpace<Scalar> VectorSpace<Scalar>::getBlock(const int i) const
00182 {
00183   const Thyra::ProductVectorSpaceBase<Scalar>* pvs = 
00184     dynamic_cast<const Thyra::ProductVectorSpaceBase<Scalar>* > (this->ptr().get());
00185   TEST_FOR_EXCEPTION(pvs == 0 && numBlocks()!=1, std::runtime_error,
00186          "Space not a ProductVectorSpace" << std::endl);
00187   if (pvs != 0)
00188     {
00189       return pvs->getBlock(i);
00190     }
00191   return *this;
00192 }
00193 
00194 
00195 // //========================================================================
00196 // template <class Scalar>
00197 // void VectorSpace<Scalar>::setBlock(int i, 
00198 //           const VectorSpace<Scalar>& space)
00199 // {
00200 //   const Thyra::ProductVectorSpace<Scalar>*  pvs = 
00201 //     dynamic_cast<const Thyra::ProductVectorSpace<Scalar>* >  (this->ptr().get());
00202 
00203 //   TEST_FOR_EXCEPTION(pvs == 0, std::runtime_error,
00204 //         "Can't set block of vector space that is " <<
00205 //         "not a ProductVectorSpace.");
00206 
00207 //   Thyra::ProductVectorSpace<Scalar>* pvsc = const_cast<ProductVectorSpace<Scalar>*> (pvs);
00208 //   pvsc->setBlock(i, space);
00209 // }
00210 
00211 
00212 //========================================================================
00213 template <class Scalar> inline
00214 SequentialIterator<Scalar> VectorSpace<Scalar>::begin() const
00215 {
00216   OrdType blockIndex = -1;
00217   OrdType indexInCurrentBlock = -1;
00218   OrdType globalIndex = -1;
00219 
00220   /* we need to check for remaining data to deal with the case where 
00221    * a space is empty */
00222   bool dataRemains = advanceIndex(blockIndex, indexInCurrentBlock, globalIndex);
00223 
00224   if (dataRemains)
00225   {
00226     return SequentialIterator<Scalar>(*this, blockIndex, indexInCurrentBlock, globalIndex);
00227   }
00228   else
00229   {
00230     return end();
00231   }
00232 }
00233 
00234 
00235 //========================================================================
00236 template <class Scalar> inline
00237 SequentialIterator<Scalar> VectorSpace<Scalar>::end() const
00238 {
00239   return SequentialIterator<Scalar>(*this);
00240 }
00241 
00242 
00243 
00244 
00245 
00246 template <class Scalar> inline
00247 bool VectorSpace<Scalar>::advanceIndex(
00248   OrdType& blockIndex, 
00249   OrdType& indexInCurrentBlock,
00250   OrdType& globalIndex) const 
00251 {
00252   /* block index == -1 indicates the initialization call */
00253   if (blockIndex < 0)
00254   {
00255     /* Find the start of the first nonempty block */
00256     for (int i=0; i<numBlocks(); i++)
00257     {
00258       if (getBlock(i).dim()==0) continue;
00259       blockIndex = i;
00260       indexInCurrentBlock = 0;
00261       globalIndex = lowestLocallyOwnedIndex();
00262       return true;
00263     }
00264     /* if we've made it to this point, all blocks are empty so there's
00265      * no data. */
00266     return false;
00267   }
00268 
00269   /* If we're not a product space, then all we need to do is increment
00270    * the index and then check whether we've run off the end. 
00271    * Note: at this point, we can only deal with unit stride increments.
00272    * To do anything else would require more intimate communication with
00273    * the underlying VectorSpaceBase object, perhaps through something
00274    * like an advanceIndex() function. 
00275    */
00276   bool isProductSpace = (0 != 
00277     dynamic_cast<const Thyra::ProductVectorSpaceBase<Scalar>* > (this->ptr().get()));
00278   if (!isProductSpace)
00279   {
00280     indexInCurrentBlock++;
00281     globalIndex++;
00282     if (indexInCurrentBlock >= numLocalElements())
00283     {
00284       return false;
00285     }
00286     return true;
00287   }
00288   else 
00289   {
00290     /* If we are a product space, first try to advance within 
00291      * the current block. */
00292     OrdType subBlock = 0;
00293     if (getBlock(blockIndex).advanceIndex(subBlock, indexInCurrentBlock, globalIndex))
00294     {
00295       /* Advance was successful. */
00296       return true;
00297     }
00298     else
00299     {
00300       /* If no data remains in the current block, find the next block
00301        * the contains data, and restart the indexing within that block. 
00302        */
00303       for (int i=blockIndex+1; i<numBlocks(); i++)
00304       {
00305         if (getBlock(i).dim()==0) continue;
00306         indexInCurrentBlock = 0;
00307         globalIndex++;
00308         blockIndex = i;
00309         return true;
00310       }
00311       /* no data remaining in any block */
00312       return false;
00313     }
00314   }
00315 }
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 #endif

Site Contact