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_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP
00030 #define THYRA_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP
00031
00032 #include "Thyra_DefaultClusteredSpmdProductVectorDecl.hpp"
00033 #include "Thyra_DefaultClusteredSpmdProductVectorSpace.hpp"
00034 #include "Thyra_SpmdVectorBase.hpp"
00035 #include "RTOp_parallel_helpers.h"
00036 #include "RTOpPack_SPMD_apply_op.hpp"
00037 #include "Teuchos_Workspace.hpp"
00038 #include "Teuchos_dyn_cast.hpp"
00039 #include "Teuchos_arrayArg.hpp"
00040 #include "Teuchos_implicit_cast.hpp"
00041
00042 namespace Thyra {
00043
00044
00045
00046 template <class Scalar>
00047 DefaultClusteredSpmdProductVector<Scalar>::DefaultClusteredSpmdProductVector()
00048 {
00049 uninitialize();
00050 }
00051
00052 template <class Scalar>
00053 DefaultClusteredSpmdProductVector<Scalar>::DefaultClusteredSpmdProductVector(
00054 const Teuchos::RCP<const DefaultClusteredSpmdProductVectorSpace<Scalar> > &productSpace
00055 ,const Teuchos::RCP<VectorBase<Scalar> > vecs[]
00056 )
00057 {
00058 initialize(productSpace,vecs);
00059 }
00060
00061 template <class Scalar>
00062 void DefaultClusteredSpmdProductVector<Scalar>::initialize(
00063 const Teuchos::RCP<const DefaultClusteredSpmdProductVectorSpace<Scalar> > &productSpace
00064 ,const Teuchos::RCP<VectorBase<Scalar> > vecs[]
00065 )
00066 {
00067
00068 productSpace_ = productSpace;
00069 const int numBlocks = productSpace_->numBlocks();
00070 vecs_.resize(numBlocks);
00071 if(vecs) {
00072 std::copy( vecs, vecs + numBlocks, &vecs_[0] );
00073 }
00074 else {
00075 for( int k = 0; k < numBlocks; ++k )
00076 vecs_[k] = createMember(productSpace->getBlock(k));
00077 }
00078 }
00079
00080 template <class Scalar>
00081 void DefaultClusteredSpmdProductVector<Scalar>::uninitialize(
00082 Teuchos::RCP<const DefaultClusteredSpmdProductVectorSpace<Scalar> > *productSpace
00083 ,Teuchos::RCP<VectorBase<Scalar> > vecs[]
00084 )
00085 {
00086 const int numBlocks = vecs_.size();
00087 if(productSpace) *productSpace = productSpace_;
00088 if(vecs) std::copy( &vecs_[0], &vecs_[0]+numBlocks, vecs );
00089 productSpace_ = Teuchos::null;
00090 vecs_.resize(0);
00091 }
00092
00093
00094
00095 template <class Scalar>
00096 Teuchos::RCP<VectorBase<Scalar> >
00097 DefaultClusteredSpmdProductVector<Scalar>::getNonconstVectorBlock(const int k)
00098 {
00099 using Teuchos::implicit_cast;
00100 TEST_FOR_EXCEPT( ! ( 0 <= k && k < implicit_cast<int>(vecs_.size()) ) );
00101 return vecs_[k];
00102 }
00103
00104 template <class Scalar>
00105 Teuchos::RCP<const VectorBase<Scalar> >
00106 DefaultClusteredSpmdProductVector<Scalar>::getVectorBlock(const int k) const
00107 {
00108 using Teuchos::implicit_cast;
00109 TEST_FOR_EXCEPT( ! ( 0 <= k && k < implicit_cast<int>(vecs_.size()) ) );
00110 return vecs_[k];
00111 }
00112
00113
00114
00115 template <class Scalar>
00116 Teuchos::RCP<const ProductVectorSpaceBase<Scalar> >
00117 DefaultClusteredSpmdProductVector<Scalar>::productSpace() const
00118 {
00119 return productSpace_;
00120 }
00121
00122 template <class Scalar>
00123 bool DefaultClusteredSpmdProductVector<Scalar>::blockIsConst(const int k) const
00124 {
00125 using Teuchos::implicit_cast;
00126 TEST_FOR_EXCEPT( ! ( 0 <= k && k < implicit_cast<int>(vecs_.size()) ) );
00127 return false;
00128 }
00129
00130 template <class Scalar>
00131 Teuchos::RCP<MultiVectorBase<Scalar> >
00132 DefaultClusteredSpmdProductVector<Scalar>::getNonconstMultiVectorBlock(const int k)
00133 {
00134 return getNonconstVectorBlock(k);
00135 }
00136
00137 template <class Scalar>
00138 Teuchos::RCP<const MultiVectorBase<Scalar> >
00139 DefaultClusteredSpmdProductVector<Scalar>::getMultiVectorBlock(const int k) const
00140 {
00141 return getVectorBlock(k);
00142 }
00143
00144
00145
00146 template <class Scalar>
00147 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00148 DefaultClusteredSpmdProductVector<Scalar>::space() const
00149 {
00150 return productSpace_;
00151 }
00152
00153 template <class Scalar>
00154 void DefaultClusteredSpmdProductVector<Scalar>::applyOp(
00155 const RTOpPack::RTOpT<Scalar> &op
00156 ,const int num_vecs
00157 ,const VectorBase<Scalar>*const vecs[]
00158 ,const int num_targ_vecs
00159 ,VectorBase<Scalar>*const targ_vecs[]
00160 ,RTOpPack::ReductTarget *reduct_obj
00161 ,const Index first_ele_offset_in
00162 ,const Index sub_dim_in
00163 ,const Index global_offset_in
00164 ) const
00165 {
00166 using Teuchos::dyn_cast;
00167 using Teuchos::Workspace;
00168 Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00169
00170 const Index n = productSpace_->dim();
00171
00172 #ifdef TEUCHOS_DEBUG
00173 TEST_FOR_EXCEPTION(
00174 !(0 <= first_ele_offset_in && first_ele_offset_in < n), std::out_of_range
00175 ,"DefaultClusteredSpmdProductVector::applyOp(...): Error, "
00176 "first_ele_offset_in = " << first_ele_offset_in << " is not in range [0,"<<(n-1)<<"]" );
00177 TEST_FOR_EXCEPTION(
00178 global_offset_in < 0, std::invalid_argument
00179 ,"DefaultClusteredSpmdProductVector::applyOp(...): Error, "
00180 "global_offset_in = " << global_offset_in << " is not acceptable" );
00181 TEST_FOR_EXCEPTION(
00182 sub_dim_in > 0 && sub_dim_in - first_ele_offset_in > n, std::length_error
00183 ,"DefaultClusteredSpmdProductVector::applyOp(...): Error, "
00184 "global_offset_in = " << global_offset_in << ", sub_dim_in = " << sub_dim_in
00185 << "first_ele_offset_in = " << first_ele_offset_in << " and n = " << n
00186 << " are not compatible" );
00187 bool test_failed;
00188 for(int k = 0; k < num_vecs; ++k) {
00189 test_failed = !this->space()->isCompatible(*vecs[k]->space());
00190 TEST_FOR_EXCEPTION(
00191 test_failed, Exceptions::IncompatibleVectorSpaces
00192 ,"DefaultClusteredSpmdProductVector::applyOp(...): Error vecs["<<k<<"]->space() "
00193 <<"of type \'"<<typeName(*vecs[k]->space())<<"\' is not compatible with this "
00194 <<"\'VectorSpaceBlocked\' vector space!"
00195 );
00196 }
00197 for(int k = 0; k < num_targ_vecs; ++k) {
00198 test_failed = !this->space()->isCompatible(*targ_vecs[k]->space());
00199 TEST_FOR_EXCEPTION(
00200 test_failed, Exceptions::IncompatibleVectorSpaces
00201 ,"DefaultClusteredSpmdProductVector::applyOp(...): Error targ_vecs["<<k<<"]->space() "
00202 <<"of type \'"<<typeName(*vecs[k]->space())<<"\' is not compatible with this "
00203 <<"\'VectorSpaceBlocked\' vector space!"
00204 );
00205 }
00206 #endif
00207
00208
00209
00210
00211 Workspace<const DefaultClusteredSpmdProductVector<Scalar>*> cl_vecs(wss,num_vecs);
00212 for( int k = 0; k < num_vecs; ++k ) {
00213 #ifdef TEUCHOS_DEBUG
00214 TEST_FOR_EXCEPT(vecs[k]==NULL);
00215 #endif
00216 cl_vecs[k] = &dyn_cast<const DefaultClusteredSpmdProductVector<Scalar> >(*vecs[k]);
00217 }
00218 Workspace<DefaultClusteredSpmdProductVector<Scalar>*> cl_targ_vecs(wss,num_targ_vecs);
00219 for( int k = 0; k < num_targ_vecs; ++k ) {
00220 #ifdef TEUCHOS_DEBUG
00221 TEST_FOR_EXCEPT(targ_vecs[k]==NULL);
00222 #endif
00223 cl_targ_vecs[k] = &dyn_cast<DefaultClusteredSpmdProductVector<Scalar> >(*targ_vecs[k]);
00224 }
00225
00226
00227
00228
00229 const Teuchos::RCP<const Teuchos::Comm<Index> >
00230 intraClusterComm = productSpace_->intraClusterComm(),
00231 interClusterComm = productSpace_->interClusterComm();
00232 const Index
00233 clusterSubDim = productSpace_->clusterSubDim(),
00234 clusterOffset = productSpace_->clusterOffset(),
00235 globalDim = productSpace_->dim();
00236 Index overlap_first_cluster_ele_off = 0;
00237 Index overlap_cluster_sub_dim = 0;
00238 Index overlap_global_off = 0;
00239 if(clusterSubDim) {
00240 RTOp_parallel_calc_overlap(
00241 globalDim,clusterSubDim,clusterOffset,first_ele_offset_in,sub_dim_in
00242 ,global_offset_in
00243 ,&overlap_first_cluster_ele_off,&overlap_cluster_sub_dim,&overlap_global_off
00244 );
00245 }
00246
00247
00248
00249
00250 Teuchos::RCP<RTOpPack::ReductTarget> i_reduct_obj;
00251 if(reduct_obj) i_reduct_obj = op.reduct_obj_create();
00252
00253
00254 const int numBlocks = vecs_.size();
00255 if( overlap_first_cluster_ele_off >=0 ) {
00256
00257
00258
00259
00260 Workspace<const VectorBase<Scalar>*> v_vecs(wss,num_vecs);
00261 Workspace<VectorBase<Scalar>*> v_targ_vecs(wss,num_targ_vecs);
00262 Index overall_global_offset = overlap_global_off;
00263 for( int j = 0; j < numBlocks; ++j ) {
00264 const VectorBase<Scalar>
00265 &v = *vecs_[j];
00266 const VectorSpaceBase<Scalar>
00267 &v_space = *v.space();
00268
00269 for( int k = 0; k < num_vecs ; ++k )
00270 v_vecs[k] = &*cl_vecs[k]->vecs_[j];
00271 for( int k = 0; k < num_targ_vecs ; ++k )
00272 v_targ_vecs[k] = &*cl_targ_vecs[k]->vecs_[j];
00273 TEST_FOR_EXCEPTION(
00274 numBlocks > 1, std::logic_error
00275 ,"Error, Have not implemented general support for numBlocks > 1!"
00276 );
00277 Index
00278 v_global_offset = overall_global_offset,
00279 v_first_ele_offset = overlap_first_cluster_ele_off,
00280 v_sub_dim = overlap_cluster_sub_dim;
00281
00282 Thyra::applyOp(
00283 op
00284 ,num_vecs, num_vecs ? &v_vecs[0] : NULL
00285 ,num_targ_vecs, num_targ_vecs ? &v_targ_vecs[0] : NULL
00286 ,i_reduct_obj.get() ? &*i_reduct_obj : NULL
00287 ,v_first_ele_offset,v_sub_dim,v_global_offset
00288 );
00289
00290 overall_global_offset += v_space.dim();
00291 }
00292 }
00293
00294
00295
00296
00297
00298 if( reduct_obj ) {
00299 Teuchos::RCP<RTOpPack::ReductTarget>
00300 icl_reduct_obj = op.reduct_obj_create();
00301
00302
00303
00304 if(interClusterComm.get()) {
00305 RTOpPack::SPMD_all_reduce(
00306 &*interClusterComm
00307 ,op
00308 ,1
00309 ,Teuchos::arrayArg<const RTOpPack::ReductTarget*>(&*i_reduct_obj)()
00310 ,Teuchos::arrayArg<RTOpPack::ReductTarget*>(&*icl_reduct_obj)()
00311 );
00312 }
00313
00314
00315
00316
00317
00318 RTOpPack::SPMD_all_reduce(
00319 &*intraClusterComm
00320 ,op
00321 ,1
00322 ,Teuchos::arrayArg<const RTOpPack::ReductTarget*>(&*icl_reduct_obj)()
00323 ,Teuchos::arrayArg<RTOpPack::ReductTarget*>(reduct_obj)()
00324 );
00325
00326
00327
00328 }
00329 }
00330
00331 }
00332
00333 #endif // THYRA_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP