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_SPMD_VECTOR_BASE_HPP
00030 #define THYRA_SPMD_VECTOR_BASE_HPP
00031
00032
00033 #include "Thyra_SpmdVectorBaseDecl.hpp"
00034 #include "Thyra_VectorDefaultBase.hpp"
00035 #include "Thyra_SpmdVectorSpaceDefaultBase.hpp"
00036 #include "Thyra_apply_op_helper.hpp"
00037 #include "RTOp_parallel_helpers.h"
00038 #include "RTOpPack_SPMD_apply_op.hpp"
00039 #include "Teuchos_Workspace.hpp"
00040 #include "Teuchos_TestForException.hpp"
00041 #include "Teuchos_dyn_cast.hpp"
00042
00043
00044 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00045 # include "Teuchos_VerboseObject.hpp"
00046 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00047
00048
00049 namespace Thyra {
00050
00051
00052 template<class Scalar>
00053 SpmdVectorBase<Scalar>::SpmdVectorBase()
00054 :in_applyOp_(false)
00055 ,globalDim_(0)
00056 ,localOffset_(-1)
00057 ,localSubDim_(0)
00058 {}
00059
00060
00061
00062
00063
00064 template<class Scalar>
00065 void SpmdVectorBase<Scalar>::getLocalData( const Scalar** values, Index* stride ) const
00066 {
00067 const_cast<SpmdVectorBase<Scalar>*>(this)->getLocalData(const_cast<Scalar**>(values),stride);
00068 }
00069
00070
00071 template<class Scalar>
00072 void SpmdVectorBase<Scalar>::freeLocalData( const Scalar* values ) const
00073 {
00074 const_cast<SpmdVectorBase<Scalar>*>(this)->commitLocalData(const_cast<Scalar*>(values));
00075 }
00076
00077
00078 template<class Scalar>
00079 void SpmdVectorBase<Scalar>::applyOp(
00080 const Teuchos::Comm<Index> *comm_in
00081 ,const RTOpPack::RTOpT<Scalar> &op
00082 ,const int num_vecs
00083 ,const VectorBase<Scalar>*const vecs[]
00084 ,const int num_targ_vecs
00085 ,VectorBase<Scalar>*const targ_vecs[]
00086 ,RTOpPack::ReductTarget *reduct_obj
00087 ,const Index first_ele_offset_in
00088 ,const Index sub_dim_in
00089 ,const Index global_offset_in
00090 ) const
00091 {
00092 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00093 Teuchos::RCP<Teuchos::FancyOStream>
00094 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00095 Teuchos::OSTab tab(out);
00096 if(show_dump) {
00097 *out << "\nEntering SpmdVectorBase<Scalar>::applyOp(...) ...\n";
00098 *out
00099 << "\nop = " << typeName(op)
00100 << "\nnum_vecs = " << num_vecs
00101 << "\nnum_targ_vecs = " << num_targ_vecs
00102 << "\nreduct_obj = " << reduct_obj
00103 << "\nfirst_ele_offset_in = " << first_ele_offset_in
00104 << "\nsub_dim_in = " << sub_dim_in
00105 << "\nglobal_offset_in = " << global_offset_in
00106 << "\n"
00107 ;
00108 }
00109 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00110 using Teuchos::dyn_cast;
00111 using Teuchos::Workspace;
00112 Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00113 const SpmdVectorSpaceBase<Scalar> &spmdSpc = *spmdSpace();
00114 #ifdef TEUCHOS_DEBUG
00115
00116 TEST_FOR_EXCEPTION(
00117 in_applyOp_, std::invalid_argument
00118 ,"SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a "
00119 "clear sign that one of the methods acquireDetachedView(...), releaseDetachedView(...) or commitDetachedView(...) "
00120 "was not implemented properly!"
00121 );
00122 Thyra::apply_op_validate_input(
00123 "SpmdVectorBase<>::applyOp(...)",*space()
00124 ,op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj,first_ele_offset_in,sub_dim_in,global_offset_in
00125 );
00126 #endif
00127 Teuchos::RCP<const Teuchos::Comm<Index> > comm;
00128 if( comm_in != NULL )
00129 comm = Teuchos::rcp(comm_in,false);
00130 else
00131 comm = spmdSpc.getComm();
00132
00133 in_applyOp_ = true;
00134
00135
00136 const bool locallyReplicated = ( comm_in == NULL && localSubDim_ == globalDim_ );
00137
00138
00139 Index overlap_first_local_ele_off = 0;
00140 Index overlap_local_sub_dim = 0;
00141 Index overlap_global_off = 0;
00142 if(localSubDim_) {
00143 RTOp_parallel_calc_overlap(
00144 globalDim_, localSubDim_, localOffset_, first_ele_offset_in, sub_dim_in, global_offset_in
00145 ,&overlap_first_local_ele_off, &overlap_local_sub_dim, &overlap_global_off
00146 );
00147 }
00148 const Range1D local_rng = (
00149 overlap_first_local_ele_off>=0
00150 ? Range1D( localOffset_ + overlap_first_local_ele_off, localOffset_ + overlap_first_local_ele_off + overlap_local_sub_dim - 1 )
00151 : Range1D::Invalid
00152 );
00153 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00154 if(show_dump) {
00155 *out
00156 << "\noverlap_first_local_ele_off = " << overlap_first_local_ele_off
00157 << "\noverlap_local_sub_dim = " << overlap_local_sub_dim
00158 << "\noverlap_global_off = " << overlap_global_off
00159 << "\nlocal_rng = ["<<local_rng.lbound()<<","<<local_rng.ubound()<<"]"
00160 << "\n"
00161 ;
00162 }
00163 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00164
00165 Workspace<RTOpPack::ConstSubVectorView<Scalar> > sub_vecs(wss,num_vecs);
00166 Workspace<RTOpPack::SubVectorView<Scalar> > sub_targ_vecs(wss,num_targ_vecs);
00167 if( overlap_first_local_ele_off >= 0 ) {
00168 {for(int k = 0; k < num_vecs; ++k ) {
00169 vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] );
00170 sub_vecs[k].setGlobalOffset( overlap_global_off );
00171 }}
00172 {for(int k = 0; k < num_targ_vecs; ++k ) {
00173 targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] );
00174 sub_targ_vecs[k].setGlobalOffset( overlap_global_off );
00175 }}
00176 }
00177
00178 const bool validSubVecs = ( localSubDim_ > 0 && overlap_first_local_ele_off >= 0 );
00179 RTOpPack::SPMD_apply_op(
00180 locallyReplicated ? NULL : comm.get()
00181 ,op
00182 ,num_vecs
00183 ,num_vecs && validSubVecs ? &sub_vecs[0] : NULL
00184 ,num_targ_vecs
00185 ,num_targ_vecs && validSubVecs ? &sub_targ_vecs[0] : NULL
00186 ,reduct_obj
00187 );
00188
00189 if( overlap_first_local_ele_off >= 0 ) {
00190 {for(int k = 0; k < num_vecs; ++k ) {
00191 sub_vecs[k].setGlobalOffset(local_rng.lbound());
00192 vecs[k]->releaseDetachedView( &sub_vecs[k] );
00193 }}
00194 {for(int k = 0; k < num_targ_vecs; ++k ) {
00195 sub_targ_vecs[k].setGlobalOffset(local_rng.lbound());
00196 targ_vecs[k]->commitDetachedView( &sub_targ_vecs[k] );
00197 }}
00198 }
00199
00200 in_applyOp_ = false;
00201 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00202 if(show_dump) {
00203 *out << "\nLeaving SpmdVectorBase<Scalar>::applyOp(...) ...\n";
00204 }
00205 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00206 }
00207
00208
00209
00210
00211
00212 template<class Scalar>
00213 std::string SpmdVectorBase<Scalar>::description() const
00214 {
00215 using Teuchos::RCP; using Teuchos::Comm; using Teuchos::null;
00216 using Teuchos::typeName;
00217 std::ostringstream ostr;
00218 ostr<<typeName(*this)<<"{spmdSpace="<<spmdSpace()->description()<<"}";
00219 return ostr.str();
00220 }
00221
00222
00223
00224
00225 template<class Scalar>
00226 Teuchos::RCP<const VectorSpaceBase<Scalar> >
00227 SpmdVectorBase<Scalar>::space() const
00228 {
00229 return spmdSpace();
00230 }
00231
00232
00233 template<class Scalar>
00234 void SpmdVectorBase<Scalar>::applyOp(
00235 const RTOpPack::RTOpT<Scalar> &op
00236 ,const int num_vecs
00237 ,const VectorBase<Scalar>*const vecs[]
00238 ,const int num_targ_vecs
00239 ,VectorBase<Scalar>*const targ_vecs[]
00240 ,RTOpPack::ReductTarget *reduct_obj
00241 ,const Index first_ele_offset
00242 ,const Index sub_dim
00243 ,const Index global_offset
00244 ) const
00245 {
00246 applyOp(
00247 NULL
00248 ,op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj
00249 ,first_ele_offset,sub_dim,global_offset
00250 );
00251 }
00252
00253
00254 template<class Scalar>
00255 void SpmdVectorBase<Scalar>::acquireDetachedVectorViewImpl(
00256 const Range1D& rng_in, RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00257 ) const
00258 {
00259 if( rng_in == Range1D::Invalid ) {
00260
00261 sub_vec->initialize(
00262 rng_in.lbound()
00263 ,0
00264 ,0
00265 ,1
00266 );
00267 return;
00268 }
00269 const Range1D rng = validateRange(rng_in);
00270 if(
00271 rng.lbound() < localOffset_
00272 ||
00273 localOffset_+localSubDim_-1 < rng.ubound()
00274 )
00275 {
00276
00277 VectorDefaultBase<Scalar>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00278 return;
00279 }
00280
00281 const Scalar *localValues = NULL;
00282 Index stride = 0;
00283 this->getLocalData(&localValues,&stride);
00284 sub_vec->initialize(
00285 rng.lbound()
00286 ,rng.size()
00287 ,localValues+(rng.lbound()-localOffset_)
00288 ,stride
00289 );
00290 }
00291
00292
00293 template<class Scalar>
00294 void SpmdVectorBase<Scalar>::releaseDetachedVectorViewImpl(
00295 RTOpPack::ConstSubVectorView<Scalar>* sub_vec
00296 ) const
00297 {
00298 #ifdef TEUCHOS_DEBUG
00299 TEST_FOR_EXCEPTION(
00300 sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
00301 ,std::logic_error
00302 ,"SpmdVectorBase<Scalar>::releaseDetachedVectorViewImpl(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
00303 );
00304 #endif
00305 if(
00306 sub_vec->globalOffset() < localOffset_
00307 || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
00308 )
00309 {
00310
00311 VectorDefaultBase<Scalar>::releaseDetachedVectorViewImpl(sub_vec);
00312 return;
00313 }
00314
00315 sub_vec->set_uninitialized();
00316 }
00317
00318
00319 template<class Scalar>
00320 void SpmdVectorBase<Scalar>::acquireNonconstDetachedVectorViewImpl(
00321 const Range1D& rng_in, RTOpPack::SubVectorView<Scalar>* sub_vec
00322 )
00323 {
00324 if( rng_in == Range1D::Invalid ) {
00325
00326 sub_vec->initialize(
00327 rng_in.lbound()
00328 ,0
00329 ,0
00330 ,1
00331 );
00332 return;
00333 }
00334 const Range1D rng = validateRange(rng_in);
00335 if(
00336 rng.lbound() < localOffset_
00337 ||
00338 localOffset_+localSubDim_-1 < rng.ubound()
00339 )
00340 {
00341
00342 VectorDefaultBase<Scalar>::acquireNonconstDetachedVectorViewImpl(rng_in,sub_vec);
00343 return;
00344 }
00345
00346 Scalar *localValues = NULL;
00347 Index stride = 0;
00348 this->getLocalData(&localValues,&stride);
00349 sub_vec->initialize(
00350 rng.lbound()
00351 ,rng.size()
00352 ,localValues+(rng.lbound()-localOffset_)
00353 ,stride
00354 );
00355 }
00356
00357
00358 template<class Scalar>
00359 void SpmdVectorBase<Scalar>::commitNonconstDetachedVectorViewImpl(
00360 RTOpPack::SubVectorView<Scalar>* sub_vec
00361 )
00362 {
00363 #ifdef TEUCHOS_DEBUG
00364 TEST_FOR_EXCEPTION(
00365 sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
00366 ,std::logic_error
00367 ,"SpmdVectorBase<Scalar>::commitDetachedView(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
00368 );
00369 #endif
00370 if(
00371 sub_vec->globalOffset() < localOffset_
00372 ||
00373 localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
00374 )
00375 {
00376
00377 VectorDefaultBase<Scalar>::commitNonconstDetachedVectorViewImpl(sub_vec);
00378 return;
00379 }
00380 sub_vec->set_uninitialized();
00381 }
00382
00383
00384
00385
00386
00387 template<class Scalar>
00388 void SpmdVectorBase<Scalar>::updateSpmdSpace()
00389 {
00390 if(globalDim_ == 0) {
00391 const SpmdVectorSpaceBase<Scalar> *spmdSpace = this->spmdSpace().get();
00392 if(spmdSpace) {
00393 globalDim_ = spmdSpace->dim();
00394 localOffset_ = spmdSpace->localOffset();
00395 localSubDim_ = spmdSpace->localSubDim();
00396 }
00397 else {
00398 globalDim_ = 0;
00399 localOffset_ = -1;
00400 localSubDim_ = 0;
00401 }
00402 }
00403 }
00404
00405
00406
00407
00408
00409 template<class Scalar>
00410 Range1D SpmdVectorBase<Scalar>::validateRange( const Range1D &rng_in ) const
00411 {
00412 const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
00413 #ifdef TEUCHOS_DEBUG
00414 TEST_FOR_EXCEPTION(
00415 !(0 <= rng.lbound() && rng.ubound() < globalDim_), std::invalid_argument
00416 ,"SpmdVectorBase<Scalar>::validateRange(...): Error, the range ["
00417 <<rng.lbound()<<","<<rng.ubound()<<"] is not "
00418 "in the range [0,"<<(globalDim_-1)<<"]!"
00419 );
00420 #endif
00421 return rng;
00422 }
00423
00424
00425 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00426 template<class Scalar>
00427 bool SpmdVectorBase<Scalar>::show_dump = false;
00428 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00429
00430
00431 }
00432
00433
00434 #endif // THYRA_SPMD_VECTOR_BASE_HPP