void EpetraVector::applyOp( const RTOpPack::RTOpT<double> &op, const int num_vecs, const VectorBase<double>*const vecs[], const int num_targ_vecs, VectorBase<double>*const targ_vecs[], RTOpPack::ReductTarget *reduct_obj, const OrdType first_ele_offset_in, const OrdType sub_dim_in, const OrdType global_offset_in ) const { #ifdef THYRA_SPMD_VECTOR_BASE_DUMP Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); Teuchos::OSTab tab(out); if(show_dump) { *out << "\nEntering SpmdVectorBase<double>::applyOp(...) ...\n"; *out << "\nop = " << typeName(op) << "\nnum_vecs = " << num_vecs << "\nnum_targ_vecs = " << num_targ_vecs << "\nreduct_obj = " << reduct_obj << "\nfirst_ele_offset_in = " << first_ele_offset_in << "\nsub_dim_in = " << sub_dim_in << "\nglobal_offset_in = " << global_offset_in << "\n" ; } #endif // THYRA_SPMD_VECTOR_BASE_DUMP using Teuchos::dyn_cast; using Teuchos::Workspace; Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get(); #ifdef TEUCHOS_DEBUG // ToDo: Validate input! TEST_FOR_EXCEPTION( in_applyOpImpl_, std::invalid_argument ,"SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a " "clear sign that one of the methods acquireDetachedView(...), releaseDetachedView(...) or commitDetachedView(...) " "was not implemented properly!" ); Thyra::apply_op_validate_input( "SpmdVectorBase<>::applyOp(...)",*space() ,op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj,first_ele_offset_in,sub_dim_in,global_offset_in ); #endif const Teuchos::RCP<const Teuchos::Comm<OrdType> >& comm = epetraVecSpace_->getComm(); const SerialComm<OrdType>* serialComm = dynamic_cast<const SerialComm<OrdType>* >(comm.get()); // Flag that we are in applyOp() in_applyOpImpl_ = true; // First see if this is a locally replicated vector in which case // we treat this as a local operation only. const bool locallyReplicated = ( serialComm != 0 && localSubDim_ == globalDim_ ); // Get the overlap in the current process with the input logical sub-vector // from (first_ele_offset_in,sub_dim_in,global_offset_in) OrdType overlap_first_local_ele_off = 0; OrdType overlap_local_sub_dim = 0; OrdType overlap_global_off = 0; if(localSubDim_) { RTOp_parallel_calc_overlap( globalDim_, localSubDim_, localOffset_, first_ele_offset_in, sub_dim_in, global_offset_in ,&overlap_first_local_ele_off, &overlap_local_sub_dim, &overlap_global_off ); } const Range1D local_rng = ( overlap_first_local_ele_off>=0 ? Range1D( localOffset_ + overlap_first_local_ele_off, localOffset_ + overlap_first_local_ele_off + overlap_local_sub_dim - 1 ) : Range1D::Invalid ); #ifdef THYRA_SPMD_VECTOR_BASE_DUMP if(show_dump) { *out << "\noverlap_first_local_ele_off = " << overlap_first_local_ele_off << "\noverlap_local_sub_dim = " << overlap_local_sub_dim << "\noverlap_global_off = " << overlap_global_off << "\nlocal_rng = ["<<local_rng.lbound()<<","<<local_rng.ubound()<<"]" << "\n" ; } #endif // THYRA_SPMD_VECTOR_BASE_DUMP // Create sub-vector views of all of the *participating* local data Workspace<RTOpPack::ConstSubVectorView<double> > sub_vecs(wss,num_vecs); Workspace<RTOpPack::SubVectorView<double> > sub_targ_vecs(wss,num_targ_vecs); if( overlap_first_local_ele_off >= 0 ) { {for(int k = 0; k < num_vecs; ++k ) { vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] ); sub_vecs[k].setGlobalOffset( overlap_global_off ); }} {for(int k = 0; k < num_targ_vecs; ++k ) { targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] ); sub_targ_vecs[k].setGlobalOffset( overlap_global_off ); }} } // Apply the RTOp operator object (all processors must participate) const bool validSubVecs = ( localSubDim_ > 0 && overlap_first_local_ele_off >= 0 ); RTOpPack::SPMD_apply_op( locallyReplicated ? NULL : comm.get() // comm ,op // op ,num_vecs // num_vecs ,num_vecs && validSubVecs ? &sub_vecs[0] : NULL // sub_vecs ,num_targ_vecs // num_targ_vecs ,num_targ_vecs && validSubVecs ? &sub_targ_vecs[0] : NULL // targ_sub_vecs ,reduct_obj // reduct_obj ); // Free and commit the local data if( overlap_first_local_ele_off >= 0 ) { {for(int k = 0; k < num_vecs; ++k ) { sub_vecs[k].setGlobalOffset(local_rng.lbound()); vecs[k]->releaseDetachedView( &sub_vecs[k] ); }} {for(int k = 0; k < num_targ_vecs; ++k ) { sub_targ_vecs[k].setGlobalOffset(local_rng.lbound()); targ_vecs[k]->commitDetachedView( &sub_targ_vecs[k] ); }} } // Flag that we are leaving applyOp() in_applyOpImpl_ = false; #ifdef THYRA_SPMD_VECTOR_BASE_DUMP if(show_dump) { *out << "\nLeaving SpmdVectorBase<double>::applyOp(...) ...\n"; } #endif // THYRA_SPMD_VECTOR_BASE_DUMP }