Thyra_DefaultClusteredSpmdProductVector.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
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 // Constructors/initializers/accessors
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   // ToDo: Validate input!
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 // Overridden from ProductVectorBase
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 // Overridden from ProductVectorBase
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 // Overridden from VectorBase
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 // Overridden protected members from VectorBase
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   // Validate input
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   // Cast all of the vector arguments to DefaultClusteredSpmdProductVector and
00231   // make sure that they are all compatible!
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   // Get the overlap of the element for this cluster that will participate in
00250   // the RTOp operation.
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   // Perform the RTOp for each set of block vectors just within this cluster
00272   // of processes.
00273   //
00274   Teuchos::RCP<RTOpPack::ReductTarget> i_reduct_obj;
00275   if (!is_null(reduct_obj))
00276     i_reduct_obj = op.reduct_obj_create();
00277   // Note: i_reduct_obj will accumulate the reduction within this cluster of
00278   // processes.
00279   const int numBlocks = vecs_.size();
00280   if (overlap_first_cluster_ele_off >=0) {
00281 
00282     //
00283     // There is overlap with at least one element in one block
00284     // vector for this cluster
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       // Load up the constutuent block SPMD vectors
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         ); // ToDo: Fix the below code for numBlocks_ > 1!
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       // Apply RTOp on just this cluster
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   // Perform the global reduction across all of the root processes in each of
00320   // the clusters and then move the global reduction out to each of the
00321   // processes within the cluster.
00322   //
00323   if (!is_null(reduct_obj)) {
00324     Teuchos::RCP<RTOpPack::ReductTarget>
00325       icl_reduct_obj = op.reduct_obj_create();
00326     // First, accumulate the global reduction across all of the elements by
00327     // just performing the global reduction involving the root processes of
00328     // each cluster.
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     // Now the root processes in each cluster have the full global reduction
00339     // across all elements stored in *icl_reduct_obj and the other processes
00340     // in each cluster have empty reductions in *icl_reduct_obj.  The last
00341     // thing to do is to just perform the reduction within each cluster of
00342     // processes and to add into the in/out *reduct_obj.
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     // ToDo: Replace the above operation with a reduction across clustere into
00351     // reduct_obj in the root processes and then broadcast the result to all
00352     // of the slave processes.
00353   }
00354 
00355 }
00356 
00357 
00358 } // namespace Thyra
00359 
00360 
00361 #endif // THYRA_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP

Generated on Wed May 12 21:26:53 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7