Thyra Package Browser (Single Doxygen Collection) Version of the Day
Thyra_SpmdVectorBase_def.hpp
Go to the documentation of this file.
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_SPMD_VECTOR_BASE_DEF_HPP
00030 #define THYRA_SPMD_VECTOR_BASE_DEF_HPP
00031 
00032 
00033 #include "Thyra_SpmdVectorBase_decl.hpp"
00034 #include "Thyra_VectorDefaultBase.hpp"
00035 #include "Thyra_SpmdVectorSpaceDefaultBase.hpp"
00036 #include "Thyra_apply_op_helper.hpp"
00037 #include "RTOpPack_SPMD_apply_op.hpp"
00038 #include "Teuchos_Workspace.hpp"
00039 #include "Teuchos_TestForException.hpp"
00040 #include "Teuchos_dyn_cast.hpp"
00041 #include "Teuchos_Assert.hpp"
00042 
00043 
00044 namespace Thyra {
00045 
00046 
00047 // Public interface functions
00048 
00049 
00050 template<class Scalar>
00051 SpmdVectorBase<Scalar>::SpmdVectorBase()
00052   :in_applyOpImpl_(false)
00053   ,globalDim_(0)
00054   ,localOffset_(-1)
00055   ,localSubDim_(0)
00056 {}
00057 
00058 
00059 template<class Scalar>
00060 RTOpPack::SubVectorView<Scalar>
00061 SpmdVectorBase<Scalar>::getNonconstLocalSubVector()
00062 {
00063   ArrayRCP<Scalar> localValues;
00064   this->getNonconstLocalData(Teuchos::outArg(localValues));
00065   return RTOpPack::SubVectorView<Scalar>(
00066     localOffset_,
00067     localSubDim_,
00068     localValues,
00069     1 // stride
00070     );
00071   // ToDo: Refactor to call this function directly!
00072 }
00073 
00074 
00075 template<class Scalar>
00076 RTOpPack::ConstSubVectorView<Scalar>
00077 SpmdVectorBase<Scalar>::getLocalSubVector() const
00078 {
00079   ArrayRCP<const Scalar> localValues;
00080   this->getLocalData(Teuchos::outArg(localValues));
00081   return RTOpPack::ConstSubVectorView<Scalar>(
00082     localOffset_, // globalOffset?
00083     localSubDim_,
00084     localValues,
00085     1 // stride
00086     );
00087   // ToDo: Refactor to call this function directly!
00088 }
00089 
00090 
00091 template<class Scalar>
00092 void SpmdVectorBase<Scalar>::applyOpImplWithComm(
00093   const Ptr<const Teuchos::Comm<Ordinal> > &comm_in,
00094   const RTOpPack::RTOpT<Scalar> &op,
00095   const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
00096   const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
00097   const Ptr<RTOpPack::ReductTarget> &reduct_obj,
00098   const Ordinal global_offset_in
00099   ) const
00100 {
00101 
00102   using Teuchos::null;
00103   using Teuchos::dyn_cast;
00104   using Teuchos::Workspace;
00105 
00106   const int num_vecs = vecs.size();
00107   const int num_targ_vecs = targ_vecs.size();
00108 
00109   Ptr<Teuchos::WorkspaceStore> wss = Teuchos::get_default_workspace_store().ptr();
00110   const SpmdVectorSpaceBase<Scalar> &spmdSpc = *spmdSpace();
00111 
00112 #ifdef TEUCHOS_DEBUG
00113   TEST_FOR_EXCEPTION(
00114     in_applyOpImpl_, std::invalid_argument,
00115     "SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively"
00116     " which is a clear sign that one of the methods acquireDetachedView(...),"
00117     " releaseDetachedView(...) or commitDetachedView(...) was not implemented properly!"
00118     );
00119   Thyra::apply_op_validate_input(
00120     "SpmdVectorBase<>::applyOp(...)",*space(),
00121     op, vecs, targ_vecs, reduct_obj, global_offset_in);
00122 #endif
00123 
00124   Teuchos::RCP<const Teuchos::Comm<Ordinal> > comm;
00125   if (nonnull(comm_in))
00126     comm = Teuchos::rcpFromPtr(comm_in);
00127   else
00128     comm = spmdSpc.getComm();
00129 
00130   // Flag that we are in applyOp()
00131   in_applyOpImpl_ = true;
00132 
00133   // First see if this is a locally replicated vector in which case
00134   // we treat this as a local operation only.
00135   const bool locallyReplicated = ( comm_in == null && localSubDim_ == globalDim_ );
00136 
00137   const Range1D local_rng(localOffset_, localOffset_+localSubDim_-1);
00138 
00139   // Create sub-vector views of all of the *participating* local data
00140   Workspace<RTOpPack::ConstSubVectorView<Scalar> > sub_vecs(wss.get(), num_vecs);
00141   Workspace<RTOpPack::SubVectorView<Scalar> > sub_targ_vecs(wss.get(), num_targ_vecs);
00142   for(int k = 0; k < num_vecs; ++k ) {
00143     vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] );
00144     sub_vecs[k].setGlobalOffset(localOffset_+global_offset_in);
00145   }
00146   for(int k = 0; k < num_targ_vecs; ++k ) {
00147     targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] );
00148     sub_targ_vecs[k].setGlobalOffset(localOffset_+global_offset_in);
00149   }
00150 
00151   // Apply the RTOp operator object (all processors must participate)
00152   RTOpPack::SPMD_apply_op(
00153     locallyReplicated ? NULL : &*comm,     // comm
00154     op,                                    // op
00155     num_vecs,                              // num_vecs
00156     sub_vecs.getRawPtr(),                  // sub_vecs
00157     num_targ_vecs,                         // num_targ_vecs
00158     sub_targ_vecs.getRawPtr(),             // targ_sub_vecs
00159     reduct_obj.get()                       // reduct_obj
00160     );
00161 
00162   // Free and commit the local data
00163   for (int k = 0; k < num_vecs; ++k ) {
00164     sub_vecs[k].setGlobalOffset(local_rng.lbound());
00165     vecs[k]->releaseDetachedView(&sub_vecs[k]);
00166   }
00167   for (int k = 0; k < num_targ_vecs; ++k ) {
00168     sub_targ_vecs[k].setGlobalOffset(local_rng.lbound());
00169     targ_vecs[k]->commitDetachedView(&sub_targ_vecs[k]);
00170   }
00171 
00172   // Flag that we are leaving applyOp()
00173   in_applyOpImpl_ = false;
00174 
00175 }
00176 
00177 
00178 // Overridden from Teuchos::Describable
00179 
00180 
00181 template<class Scalar>
00182 std::string SpmdVectorBase<Scalar>::description() const
00183 {
00184   using Teuchos::RCP; using Teuchos::Comm; using Teuchos::null;
00185   using Teuchos::typeName;
00186   std::ostringstream ostr;
00187   ostr<<typeName(*this)<<"{spmdSpace="<<spmdSpace()->description()<<"}";
00188   return ostr.str();
00189 }
00190 
00191 
00192 // Overridden public functions from VectorBase
00193 
00194 
00195 template<class Scalar>
00196 Teuchos::RCP<const VectorSpaceBase<Scalar> >
00197 SpmdVectorBase<Scalar>::space() const
00198 {
00199   return spmdSpace();
00200 }
00201 
00202 
00203 // Deprecated
00204 
00205 
00206 template<class Scalar>
00207 void SpmdVectorBase<Scalar>::getLocalData( Scalar** localValues, Ordinal* stride )
00208 {
00209 #ifdef THYRA_DEBUG
00210   TEUCHOS_ASSERT(localValues);
00211   TEUCHOS_ASSERT(stride);
00212 #endif
00213   ArrayRCP<Scalar> localValues_arcp;
00214   this->getNonconstLocalData(Teuchos::outArg(localValues_arcp));
00215   *localValues = localValues_arcp.getRawPtr();
00216   *stride = 1;
00217 }
00218 
00219 
00220 template<class Scalar>
00221 void SpmdVectorBase<Scalar>::commitLocalData( Scalar* localValues )
00222 {
00223   // Nothing to do!
00224 }
00225 
00226 
00227 template<class Scalar>
00228 void SpmdVectorBase<Scalar>::getLocalData( const Scalar** localValues, Ordinal* stride ) const
00229 {
00230 #ifdef THYRA_DEBUG
00231   TEUCHOS_ASSERT(localValues);
00232   TEUCHOS_ASSERT(stride);
00233 #endif
00234   ArrayRCP<const Scalar> localValues_arcp;
00235   this->getLocalData(Teuchos::outArg(localValues_arcp));
00236   *localValues = localValues_arcp.getRawPtr();
00237   *stride = 1;
00238 }
00239 
00240 
00241 template<class Scalar>
00242 void SpmdVectorBase<Scalar>::freeLocalData( const Scalar* values ) const
00243 {
00244   // Nothing to do!
00245 }
00246 
00247 
00248 // protected
00249 
00250 
00251 // Overridden protected functions from VectorBase
00252 
00253 
00254 template<class Scalar>
00255 void SpmdVectorBase<Scalar>::applyOpImpl(
00256   const RTOpPack::RTOpT<Scalar> &op,
00257   const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
00258   const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
00259   const Ptr<RTOpPack::ReductTarget> &reduct_obj,
00260   const Ordinal global_offset
00261   ) const
00262 {
00263   applyOpImplWithComm( Teuchos::null, op, vecs, targ_vecs, reduct_obj,
00264     global_offset);
00265 }
00266 
00267 
00268 template<class Scalar>
00269 void SpmdVectorBase<Scalar>::acquireDetachedVectorViewImpl(
00270   const Range1D& rng_in, RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00271   ) const
00272 {
00273 #ifdef THYRA_DEBUG
00274   TEUCHOS_ASSERT(sub_vec);
00275 #endif
00276   if( rng_in == Range1D::Invalid ) {
00277     // Just return an null view
00278     *sub_vec = RTOpPack::ConstSubVectorView<Scalar>();
00279     return;
00280   }
00281   const Range1D rng = validateRange(rng_in);
00282   if(
00283     rng.lbound() < localOffset_ 
00284     ||
00285     localOffset_+localSubDim_-1 < rng.ubound()
00286     )
00287   {
00288     // rng consists of off-processor elements so use the default implementation!
00289     VectorDefaultBase<Scalar>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00290     return;
00291   }
00292   // rng consists of all local data so get it!
00293   ArrayRCP<const Scalar>localValues;
00294   this->getLocalData(Teuchos::outArg(localValues));
00295   sub_vec->initialize(
00296     rng.lbound(),  // globalOffset
00297     rng.size(),  // subDim
00298     localValues.persistingView(rng.lbound()-localOffset_, rng.size()),
00299     1  // stride
00300     );
00301 }
00302 
00303 
00304 template<class Scalar>
00305 void SpmdVectorBase<Scalar>::releaseDetachedVectorViewImpl(
00306   RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00307   ) const
00308 {
00309 #ifdef TEUCHOS_DEBUG
00310   TEST_FOR_EXCEPTION(
00311     sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
00312     ,std::logic_error
00313     ,"SpmdVectorBase<Scalar>::releaseDetachedVectorViewImpl(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
00314     );
00315 #endif
00316   if(
00317     sub_vec->globalOffset() < localOffset_ 
00318     || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
00319     )
00320   {
00321     // Let the default implementation handle it!
00322     VectorDefaultBase<Scalar>::releaseDetachedVectorViewImpl(sub_vec);
00323     return;
00324   }
00325   // Nothing to deallocate!
00326   sub_vec->uninitialize();
00327 }
00328 
00329 
00330 template<class Scalar>
00331 void SpmdVectorBase<Scalar>::acquireNonconstDetachedVectorViewImpl(
00332   const Range1D& rng_in, RTOpPack::SubVectorView<Scalar>* sub_vec
00333   )
00334 {
00335 #ifdef THYRA_DEBUG
00336   TEUCHOS_ASSERT(sub_vec);
00337 #endif
00338   if( rng_in == Range1D::Invalid ) {
00339     // Just return an null view
00340     *sub_vec = RTOpPack::SubVectorView<Scalar>();
00341     return;
00342   }
00343   const Range1D rng = validateRange(rng_in);
00344   if(
00345     rng.lbound() < localOffset_ 
00346     ||
00347     localOffset_+localSubDim_-1 < rng.ubound()
00348     )
00349   {
00350     // rng consists of off-processor elements so use the default implementation!
00351     VectorDefaultBase<Scalar>::acquireNonconstDetachedVectorViewImpl(rng_in,sub_vec);
00352     return;
00353   }
00354   // rng consists of all local data so get it!
00355   ArrayRCP<Scalar> localValues;
00356   this->getNonconstLocalData(Teuchos::outArg(localValues));
00357   sub_vec->initialize(
00358     rng.lbound(),  // globalOffset
00359     rng.size(),  // subDim
00360     localValues.persistingView(rng.lbound()-localOffset_, rng.size()),
00361     1  // stride
00362     );
00363 }
00364 
00365 
00366 template<class Scalar>
00367 void SpmdVectorBase<Scalar>::commitNonconstDetachedVectorViewImpl(
00368   RTOpPack::SubVectorView<Scalar>* sub_vec
00369   )
00370 {
00371 #ifdef TEUCHOS_DEBUG
00372   TEST_FOR_EXCEPTION(
00373     sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
00374     ,std::logic_error
00375     ,"SpmdVectorBase<Scalar>::commitDetachedView(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
00376     );
00377 #endif
00378   if(
00379     sub_vec->globalOffset() < localOffset_
00380     ||
00381     localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
00382     )
00383   {
00384     // Let the default implementation handle it!
00385     VectorDefaultBase<Scalar>::commitNonconstDetachedVectorViewImpl(sub_vec);
00386     return;
00387   }
00388   sub_vec->uninitialize();  // Nothing to deallocate!
00389 }
00390 
00391 
00392 // protected
00393 
00394 
00395 template<class Scalar>
00396 void SpmdVectorBase<Scalar>::updateSpmdSpace()
00397 {
00398   if(globalDim_ == 0) {
00399     const SpmdVectorSpaceBase<Scalar> *l_spmdSpace = this->spmdSpace().get();
00400     if(l_spmdSpace) {
00401       globalDim_    = l_spmdSpace->dim();
00402       localOffset_  = l_spmdSpace->localOffset();
00403       localSubDim_  = l_spmdSpace->localSubDim();
00404     }
00405     else {
00406       globalDim_    = 0;
00407       localOffset_  = -1;
00408       localSubDim_  = 0;
00409     }
00410   }
00411 }
00412 
00413 
00414 // private
00415 
00416 
00417 template<class Scalar>
00418 Range1D SpmdVectorBase<Scalar>::validateRange( const Range1D &rng_in ) const
00419 {
00420   const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
00421 #ifdef TEUCHOS_DEBUG
00422   TEST_FOR_EXCEPTION(
00423     !(0 <= rng.lbound() && rng.ubound() < globalDim_), std::invalid_argument
00424     ,"SpmdVectorBase<Scalar>::validateRange(...): Error, the range ["
00425     <<rng.lbound()<<","<<rng.ubound()<<"] is not "
00426     "in the range [0,"<<(globalDim_-1)<<"]!"
00427     );
00428 #endif
00429   return rng;
00430 }
00431 
00432 
00433 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00434 template<class Scalar>
00435 bool SpmdVectorBase<Scalar>::show_dump = false;
00436 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00437 
00438 
00439 } // end namespace Thyra
00440 
00441 
00442 #endif // THYRA_SPMD_VECTOR_BASE_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines