|
Thyra Package Browser (Single Doxygen Collection) Version of the Day
|
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
1.7.4