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