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_MPI_VECTOR_BASE_HPP
00030 #define THYRA_MPI_VECTOR_BASE_HPP
00031
00032 #include "Thyra_MPIVectorBaseDecl.hpp"
00033 #include "Thyra_MPIVectorSpaceBase.hpp"
00034 #include "RTOp_parallel_helpers.h"
00035 #include "RTOpPack_MPI_apply_op.hpp"
00036 #include "Teuchos_Workspace.hpp"
00037 #include "Teuchos_TestForException.hpp"
00038 #include "Teuchos_dyn_cast.hpp"
00039
00040 namespace Thyra {
00041
00042 template<class Scalar>
00043 MPIVectorBase<Scalar>::MPIVectorBase()
00044 :in_applyOp_(false)
00045 ,globalDim_(0)
00046 ,localOffset_(-1)
00047 ,localSubDim_(0)
00048 {}
00049
00050
00051
00052 template<class Scalar>
00053 void MPIVectorBase<Scalar>::getLocalData( const Scalar** values, Index* stride ) const
00054 {
00055 const_cast<MPIVectorBase<Scalar>*>(this)->getLocalData(const_cast<Scalar**>(values),stride);
00056 }
00057
00058 template<class Scalar>
00059 void MPIVectorBase<Scalar>::freeLocalData( const Scalar* values ) const
00060 {
00061 const_cast<MPIVectorBase<Scalar>*>(this)->commitLocalData(const_cast<Scalar*>(values));
00062 }
00063
00064
00065
00066 template<class Scalar>
00067 Teuchos::RefCountPtr<const VectorSpaceBase<Scalar> >
00068 MPIVectorBase<Scalar>::space() const
00069 {
00070 return mpiSpace();
00071 }
00072
00073 template<class Scalar>
00074 void MPIVectorBase<Scalar>::applyOp(
00075 const RTOpPack::RTOpT<Scalar> &op
00076 ,const int num_vecs
00077 ,const VectorBase<Scalar>* vecs[]
00078 ,const int num_targ_vecs
00079 ,VectorBase<Scalar>* targ_vecs[]
00080 ,RTOpPack::ReductTarget *reduct_obj
00081 ,const Index first_ele_in
00082 ,const Index sub_dim_in
00083 ,const Index global_offset_in
00084 ) const
00085 {
00086 using Teuchos::dyn_cast;
00087 using Teuchos::Workspace;
00088 Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00089 const MPIVectorSpaceBase<Scalar> &mpiSpc = *mpiSpace();
00090 #ifdef _DEBUG
00091
00092 TEST_FOR_EXCEPTION(
00093 in_applyOp_, std::invalid_argument
00094 ,"MPIVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a "
00095 "clear sign that one of the methods getSubVector(...), freeSubVector(...) or commitSubVector(...) "
00096 "was not implemented properly!"
00097 );
00098 Thyra::apply_op_validate_input(
00099 "MPIVectorBase<>::applyOp(...)",*space()
00100 ,op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj,first_ele_in,sub_dim_in,global_offset_in
00101 );
00102 #endif
00103
00104 in_applyOp_ = true;
00105
00106
00107 const bool locallyReplicated = (localSubDim_ == globalDim_);
00108
00109
00110 RTOp_index_type overlap_first_local_ele = 0;
00111 RTOp_index_type overalap_local_sub_dim = 0;
00112 RTOp_index_type overlap_global_offset = 0;
00113 RTOp_parallel_calc_overlap(
00114 globalDim_, localSubDim_, localOffset_, first_ele_in, sub_dim_in, global_offset_in
00115 ,&overlap_first_local_ele, &overalap_local_sub_dim, &overlap_global_offset
00116 );
00117 const Range1D local_rng = (
00118 overlap_first_local_ele!=0
00119 ? Range1D( localOffset_ + overlap_first_local_ele, localOffset_ + overlap_first_local_ele + overalap_local_sub_dim - 1 )
00120 : Range1D::Invalid
00121 );
00122
00123 Workspace<RTOpPack::SubVectorT<Scalar> > sub_vecs(wss,num_vecs);
00124 Workspace<RTOpPack::MutableSubVectorT<Scalar> > sub_targ_vecs(wss,num_targ_vecs);
00125 if( overlap_first_local_ele != 0 ) {
00126 if(1){for(int k = 0; k < num_vecs; ++k ) {
00127 vecs[k]->getSubVector( local_rng, &sub_vecs[k] );
00128 sub_vecs[k].setGlobalOffset( overlap_global_offset );
00129 }}
00130 if(1){for(int k = 0; k < num_targ_vecs; ++k ) {
00131 targ_vecs[k]->getSubVector( local_rng, &sub_targ_vecs[k] );
00132 sub_targ_vecs[k].setGlobalOffset( overlap_global_offset );
00133 }}
00134 }
00135
00136 RTOpPack::MPI_apply_op(
00137 locallyReplicated ? MPI_COMM_NULL : mpiSpc.mpiComm()
00138 ,op
00139 ,-1
00140 ,num_vecs
00141 ,num_vecs && overlap_first_local_ele ? &sub_vecs[0] : NULL
00142 ,num_targ_vecs
00143 ,num_targ_vecs && overlap_first_local_ele ? &sub_targ_vecs[0] : NULL
00144 ,reduct_obj
00145 );
00146
00147 if( overlap_first_local_ele != 0 ) {
00148 if(1){for(int k = 0; k < num_vecs; ++k ) {
00149 sub_vecs[k].setGlobalOffset(local_rng.lbound()-1);
00150 vecs[k]->freeSubVector( &sub_vecs[k] );
00151 }}
00152 if(1){for(int k = 0; k < num_targ_vecs; ++k ) {
00153 sub_targ_vecs[k].setGlobalOffset(local_rng.lbound()-1);
00154 targ_vecs[k]->commitSubVector( &sub_targ_vecs[k] );
00155 }}
00156 }
00157
00158 in_applyOp_ = false;
00159 }
00160
00161 template<class Scalar>
00162 void MPIVectorBase<Scalar>::getSubVector( const Range1D& rng_in, RTOpPack::SubVectorT<Scalar>* sub_vec ) const
00163 {
00164 const Range1D rng = validateRange(rng_in);
00165 if( rng.lbound() < localOffset_+1 || localOffset_+localSubDim_ < rng.ubound() ) {
00166
00167 VectorBase<Scalar>::getSubVector(rng_in,sub_vec);
00168 return;
00169 }
00170
00171 const Scalar *localValues = NULL;
00172 Index stride = 0;
00173 this->getLocalData(&localValues,&stride);
00174 sub_vec->initialize(
00175 rng.lbound()-1
00176 ,rng.size()
00177 ,localValues+(rng.lbound()-localOffset_-1)
00178 ,stride
00179 );
00180 }
00181
00182 template<class Scalar>
00183 void MPIVectorBase<Scalar>::freeSubVector( RTOpPack::SubVectorT<Scalar>* sub_vec ) const
00184 {
00185 #ifdef _DEBUG
00186 TEST_FOR_EXCEPTION(
00187 sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
00188 ,std::logic_error
00189 ,"MPIVectorBase<Scalar>::freeSubVector(...) : Error, this sub vector was not gotten from getSubVector(...)!"
00190 );
00191 #endif
00192 if( sub_vec->globalOffset() < localOffset_ || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim() ) {
00193
00194 VectorBase<Scalar>::freeSubVector(sub_vec);
00195 return;
00196 }
00197
00198 sub_vec->set_uninitialized();
00199 }
00200
00201 template<class Scalar>
00202 void MPIVectorBase<Scalar>::getSubVector( const Range1D& rng_in, RTOpPack::MutableSubVectorT<Scalar>* sub_vec )
00203 {
00204 const Range1D rng = validateRange(rng_in);
00205 if( rng.lbound() < localOffset_+1 || localOffset_+localSubDim_ < rng.ubound() ) {
00206
00207 VectorBase<Scalar>::getSubVector(rng_in,sub_vec);
00208 return;
00209 }
00210
00211 Scalar *localValues = NULL;
00212 Index stride = 0;
00213 this->getLocalData(&localValues,&stride);
00214 sub_vec->initialize(
00215 rng.lbound()-1
00216 ,rng.size()
00217 ,localValues+(rng.lbound()-localOffset_-1)
00218 ,stride
00219 );
00220 }
00221
00222 template<class Scalar>
00223 void MPIVectorBase<Scalar>::commitSubVector( RTOpPack::MutableSubVectorT<Scalar>* sub_vec )
00224 {
00225 #ifdef _DEBUG
00226 TEST_FOR_EXCEPTION(
00227 sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
00228 ,std::logic_error
00229 ,"MPIVectorBase<Scalar>::commitSubVector(...) : Error, this sub vector was not gotten from getSubVector(...)!"
00230 );
00231 #endif
00232 if( sub_vec->globalOffset() < localOffset_ || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim() ) {
00233
00234 VectorBase<Scalar>::commitSubVector(sub_vec);
00235 return;
00236 }
00237 sub_vec->set_uninitialized();
00238 }
00239
00240
00241
00242 template<class Scalar>
00243 void MPIVectorBase<Scalar>::updateMpiSpace()
00244 {
00245 if(globalDim_ == 0) {
00246 const MPIVectorSpaceBase<Scalar> *mpiSpace = this->mpiSpace().get();
00247 if(mpiSpace) {
00248 globalDim_ = mpiSpace->dim();
00249 localOffset_ = mpiSpace->localOffset();
00250 localSubDim_ = mpiSpace->localSubDim();
00251 }
00252 else {
00253 globalDim_ = 0;
00254 localOffset_ = -1;
00255 localSubDim_ = 0;
00256 }
00257 }
00258 }
00259
00260
00261
00262 template<class Scalar>
00263 Range1D MPIVectorBase<Scalar>::validateRange( const Range1D &rng_in ) const
00264 {
00265 const Range1D rng = RangePack::full_range(rng_in,1,globalDim_);
00266 #ifdef _DEBUG
00267 TEST_FOR_EXCEPTION(
00268 rng.lbound() < 1 || globalDim_ < rng.ubound(), std::invalid_argument
00269 ,"MPIVectorBase<Scalar>::validateRange(...): Error, the range ["
00270 <<rng.lbound()<<","<<rng.ubound()<<"] is not "
00271 "in the range [1,"<<globalDim_<<"]!"
00272 );
00273 #endif
00274 return rng;
00275 }
00276
00277 }
00278
00279 #endif // THYRA_MPI_VECTOR_BASE_HPP