Thyra_MultiVectorDefaultBase.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_MULTI_VECTOR_DEFAULT_BASE_HPP
00030 #define THYRA_MULTI_VECTOR_DEFAULT_BASE_HPP
00031 
00032 
00033 #include "Thyra_MultiVectorDefaultBaseDecl.hpp"
00034 #include "Thyra_LinearOpDefaultBase.hpp"
00035 #include "Thyra_MultiVectorBase.hpp"
00036 #include "Thyra_MultiVectorStdOps.hpp"
00037 #include "Thyra_VectorSpaceBase.hpp"
00038 #include "Thyra_VectorBase.hpp"
00039 #include "Thyra_AssertOp.hpp"
00040 #include "Thyra_DefaultColumnwiseMultiVector.hpp"
00041 #include "Teuchos_Workspace.hpp"
00042 #include "Teuchos_TestForException.hpp"
00043 #include "Teuchos_as.hpp"
00044 
00045 
00046 namespace Thyra {
00047 
00048 
00049 // Overridden public member functions from MultiVectorBase
00050 
00051 
00052 template<class Scalar>
00053 RCP<MultiVectorBase<Scalar> >
00054 MultiVectorDefaultBase<Scalar>::clone_mv() const
00055 {
00056   const VectorSpaceBase<Scalar>
00057     &l_domain = *this->domain(),
00058     &l_range = *this->range();
00059   RCP<MultiVectorBase<Scalar> >
00060     copy = createMembers(l_range,l_domain.dim());
00061   assign( copy.ptr(), *this );
00062   return copy;
00063 }
00064 
00065 
00066 // protected
00067 
00068 
00069 // Overridden protected member functions from MultiVectorBase
00070 
00071 
00072 template<class Scalar>
00073 RCP<const MultiVectorBase<Scalar> >
00074 MultiVectorDefaultBase<Scalar>::contigSubViewImpl( const Range1D& colRng_in ) const
00075 {
00076   using Teuchos::Workspace;
00077   using Teuchos::as;
00078   Teuchos::WorkspaceStore *wss = Teuchos::get_default_workspace_store().get();
00079   const VectorSpaceBase<Scalar> &l_domain = *this->domain();
00080   const VectorSpaceBase<Scalar> &l_range = *this->range();
00081   const Index dimDomain = l_domain.dim();
00082   const Range1D colRng = Teuchos::full_range(colRng_in,0,dimDomain-1);
00083   if( colRng.lbound() == 0 && as<Index>(colRng.ubound()) == dimDomain-1 )
00084     return Teuchos::rcp(this,false); // Takes all of the columns!
00085   if( colRng.size() ) {
00086     // We have to create a view of a subset of the columns
00087     Workspace< RCP< VectorBase<Scalar> > > col_vecs(wss,colRng.size());
00088     for( Index j = colRng.lbound(); j <= colRng.ubound(); ++j )
00089       col_vecs[j-colRng.lbound()] = Teuchos::rcp_const_cast<VectorBase<Scalar> >(this->col(j));
00090     return Teuchos::rcp(
00091       new DefaultColumnwiseMultiVector<Scalar>(
00092         this->range(),l_range.smallVecSpcFcty()->createVecSpc(colRng.size()),col_vecs
00093         )
00094       );
00095   }
00096   return Teuchos::null; // There was an empty set in colRng_in!
00097 }
00098 
00099 
00100 template<class Scalar>
00101 RCP<MultiVectorBase<Scalar> >
00102 MultiVectorDefaultBase<Scalar>::nonconstContigSubViewImpl( const Range1D& colRng_in )
00103 {
00104   using Teuchos::Workspace;
00105   using Teuchos::as;
00106   Teuchos::WorkspaceStore *wss = Teuchos::get_default_workspace_store().get();
00107   const VectorSpaceBase<Scalar> &l_domain = *this->domain();
00108   const VectorSpaceBase<Scalar> &l_range = *this->range();
00109   const Index dimDomain = l_domain.dim();
00110   const Range1D colRng = Teuchos::full_range(colRng_in,0,dimDomain-1);
00111   if( colRng.lbound() == 0 && as<Index>(colRng.ubound()) == dimDomain-1 )
00112     return Teuchos::rcp(this,false); // Takes all of the columns!
00113   if( colRng.size() ) {
00114     // We have to create a view of a subset of the columns
00115     Workspace< RCP< VectorBase<Scalar> > > col_vecs(wss,colRng.size());
00116     for( Index j = colRng.lbound(); j <= colRng.ubound(); ++j )
00117       col_vecs[j-colRng.lbound()] = this->col(j);
00118     return Teuchos::rcp(
00119       new DefaultColumnwiseMultiVector<Scalar>(
00120         this->range(),l_range.smallVecSpcFcty()->createVecSpc(colRng.size()),col_vecs
00121         )
00122       );
00123   }
00124   return Teuchos::null; // There was an empty set in colRng_in!
00125 }
00126 
00127 
00128 template<class Scalar>
00129 RCP<const MultiVectorBase<Scalar> >
00130 MultiVectorDefaultBase<Scalar>::nonContigSubViewImpl(
00131   const ArrayView<const int> &cols
00132   ) const
00133 {
00134   using Teuchos::Workspace;
00135   Teuchos::WorkspaceStore *wss = Teuchos::get_default_workspace_store().get();
00136   const VectorSpaceBase<Scalar> &l_range = *this->range();
00137   const int numCols = cols.size();
00138 #ifdef TEUCHOS_DEBUG
00139   const VectorSpaceBase<Scalar> &l_domain = *this->domain();
00140   const Index dimDomain = l_domain.dim();
00141   const char msg_err[] = "MultiVectorDefaultBase<Scalar>::subView(numCols,cols[]): Error!";
00142   TEST_FOR_EXCEPTION( numCols < 1 || dimDomain < numCols, std::invalid_argument, msg_err );
00143 #endif
00144   // We have to create a view of a subset of the columns
00145   Workspace< RCP< VectorBase<Scalar> > > col_vecs(wss,numCols);
00146   for( int k = 0; k < numCols; ++k ) {
00147     const int col_k = cols[k];
00148 #ifdef TEUCHOS_DEBUG
00149     TEST_FOR_EXCEPTION(
00150       !( 0 <= col_k && col_k < dimDomain ), std::invalid_argument
00151       ,msg_err << " col["<<k<<"] = " << col_k << " is not in the range [0,"<<(dimDomain-1)<<"]!"
00152       );
00153 #endif
00154     col_vecs[k] = Teuchos::rcp_const_cast<VectorBase<Scalar> >(this->col(col_k));
00155   }
00156   return Teuchos::rcp(
00157     new DefaultColumnwiseMultiVector<Scalar>(
00158       this->range(), l_range.smallVecSpcFcty()->createVecSpc(numCols), col_vecs
00159       )
00160     );
00161 }
00162 
00163 
00164 template<class Scalar>
00165 RCP<MultiVectorBase<Scalar> >
00166 MultiVectorDefaultBase<Scalar>::nonconstNonContigSubViewImpl(
00167   const ArrayView<const int> &cols
00168   )
00169 {
00170   using Teuchos::Workspace;
00171   Teuchos::WorkspaceStore *wss = Teuchos::get_default_workspace_store().get();
00172   const VectorSpaceBase<Scalar> &l_range = *this->range();
00173   const int numCols = cols.size();
00174 #ifdef TEUCHOS_DEBUG
00175   const VectorSpaceBase<Scalar> &l_domain = *this->domain();
00176   const Index dimDomain = l_domain.dim();
00177   const char msg_err[] = "MultiVectorDefaultBase<Scalar>::subView(numCols,cols[]): Error!";
00178   TEST_FOR_EXCEPTION( numCols < 1 || dimDomain < numCols, std::invalid_argument, msg_err );
00179 #endif
00180   // We have to create a view of a subset of the columns
00181   Workspace< RCP< VectorBase<Scalar> > > col_vecs(wss,numCols);
00182   for( int k = 0; k < numCols; ++k ) {
00183     const int col_k = cols[k];
00184 #ifdef TEUCHOS_DEBUG
00185     TEST_FOR_EXCEPTION(
00186       !( 0 <= col_k && col_k < dimDomain ), std::invalid_argument
00187       ,msg_err << " col["<<k<<"] = " << col_k << " is not in the range [0,"<<(dimDomain-1)<<"]!"
00188       );
00189 #endif
00190     col_vecs[k] = this->col(col_k);
00191   }
00192   return Teuchos::rcp(
00193     new DefaultColumnwiseMultiVector<Scalar>(
00194       this->range(), l_range.smallVecSpcFcty()->createVecSpc(numCols), col_vecs
00195       )
00196     );
00197 }
00198 
00199 
00200 template<class Scalar>
00201 void MultiVectorDefaultBase<Scalar>::mvMultiReductApplyOpImpl(
00202   const RTOpPack::RTOpT<Scalar> &prim_op,
00203   const ArrayView<const Ptr<const MultiVectorBase<Scalar> > > &multi_vecs,
00204   const ArrayView<const Ptr<MultiVectorBase<Scalar> > > &targ_multi_vecs,
00205   const ArrayView<const Ptr<RTOpPack::ReductTarget> > &reduct_objs,
00206   const Index prim_first_ele_offset_in,
00207   const Index prim_sub_dim_in,
00208   const Index prim_global_offset_in,
00209   const Index sec_first_ele_offset_in,
00210   const Index sec_sub_dim_in
00211   ) const
00212 {
00213 
00214   using Teuchos::Workspace;
00215   using Teuchos::as;
00216   Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00217 
00218   const int num_multi_vecs = multi_vecs.size();
00219   const int num_targ_multi_vecs = targ_multi_vecs.size();
00220 
00221   // ToDo: Validate the input!
00222 
00223   const VectorSpaceBase<Scalar> &l_domain = *this->domain();
00224 
00225   // Get the primary and secondary dimensions.
00226 
00227   const Index sec_dim = l_domain.dim();
00228   const Index sec_sub_dim = ( sec_sub_dim_in >= 0 ? sec_sub_dim_in : sec_dim - sec_first_ele_offset_in );
00229 #ifdef TEUCHOS_DEBUG
00230   const VectorSpaceBase<Scalar> &l_range = *this->range();
00231   const Index prim_dim = l_range.dim();
00232   const Index prim_sub_dim = ( prim_sub_dim_in >= 0 ? prim_sub_dim_in : prim_dim - prim_first_ele_offset_in );
00233   const char err_msg[] = "MultiVectorDefaultBase<Scalar>::mvMultiReductApplyOpImpl(...): Error!";
00234   TEST_FOR_EXCEPTION( !(0 < prim_sub_dim && prim_sub_dim <= prim_dim), std::invalid_argument, err_msg );
00235   TEST_FOR_EXCEPTION( !(0 < sec_sub_dim && sec_sub_dim <= sec_dim), std::invalid_argument, err_msg );
00236 #endif
00237 
00238   //
00239   // Apply the reduction/transformation operator and transform the
00240   // target vectors and reduce each of the reduction objects.
00241   //
00242 
00243   Workspace<RCP<const VectorBase<Scalar> > > vecs_s(wss, num_multi_vecs);
00244   Workspace<Ptr<const VectorBase<Scalar> > > vecs(wss, num_multi_vecs);
00245   Workspace<RCP<VectorBase<Scalar> > > targ_vecs_s(wss, num_targ_multi_vecs);
00246   Workspace<Ptr<VectorBase<Scalar> > > targ_vecs(wss, num_targ_multi_vecs);
00247 
00248   for(Index j = sec_first_ele_offset_in; j < sec_first_ele_offset_in + sec_sub_dim; ++j) {
00249     // Fill the arrays of vector arguments
00250     {for(Index k = 0; k < as<Index>(num_multi_vecs); ++k) {
00251         vecs_s[k] = multi_vecs[k]->col(j);
00252         vecs[k] = vecs_s[k].ptr();
00253       }}
00254     {for(Index k = 0; k < as<Index>(num_targ_multi_vecs); ++k) {
00255         targ_vecs_s[k] = targ_multi_vecs[k]->col(j);
00256         targ_vecs[k] = targ_vecs_s[k].ptr();
00257       }}
00258     // Apply the reduction/transformation operator
00259     Thyra::applyOp(
00260       prim_op,
00261       vecs().getConst(),
00262       targ_vecs().getConst(),
00263       reduct_objs.size() ? reduct_objs[j] : Ptr<RTOpPack::ReductTarget>(),
00264       prim_first_ele_offset_in, prim_sub_dim_in, prim_global_offset_in
00265       );
00266   }
00267   // At this point all of the designated targ vectors in the target multi-vectors have
00268   // been transformed and all the reduction objects in reduct_obj[] have accumulated
00269   // the reductions.
00270 }
00271 
00272 
00273 template<class Scalar>
00274 void MultiVectorDefaultBase<Scalar>::mvSingleReductApplyOpImpl(
00275   const RTOpPack::RTOpT<Scalar> &prim_op,
00276   const RTOpPack::RTOpT<Scalar> &sec_op,
00277   const ArrayView<const Ptr<const MultiVectorBase<Scalar> > > &multi_vecs,
00278   const ArrayView<const Ptr<MultiVectorBase<Scalar> > > &targ_multi_vecs,
00279   const Ptr<RTOpPack::ReductTarget> &reduct_obj,
00280   const Index prim_first_ele_offset_in,
00281   const Index prim_sub_dim_in,
00282   const Index prim_global_offset_in,
00283   const Index sec_first_ele_offset_in,
00284   const Index sec_sub_dim_in
00285   ) const
00286 {
00287   using Teuchos::Workspace;
00288   Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00289 
00290   // ToDo: Validate the input!
00291 
00292   const VectorSpaceBase<Scalar> &l_domain = *this->domain();
00293 
00294   // Get the primary and secondary dimensions.
00295   const Index sec_dim = l_domain.dim();
00296   const Index sec_sub_dim = ( sec_sub_dim_in >= 0 ? sec_sub_dim_in : sec_dim - sec_first_ele_offset_in );
00297 #ifdef TEUCHOS_DEBUG
00298   const VectorSpaceBase<Scalar> &l_range = *this->range();
00299   const Index prim_dim = l_range.dim();
00300   const Index prim_sub_dim = ( prim_sub_dim_in >= 0 ? prim_sub_dim_in : prim_dim - prim_first_ele_offset_in );
00301   const char err_msg[] = "MultiVectorDefaultBase<Scalar>::mvSingleReductApplyOpImpl(...): Error!";
00302   TEST_FOR_EXCEPTION( !(0 < prim_sub_dim && prim_sub_dim <= prim_dim), std::invalid_argument, err_msg );
00303   TEST_FOR_EXCEPTION( !(0 < sec_sub_dim && sec_sub_dim <= sec_dim), std::invalid_argument, err_msg );
00304 #endif
00305 
00306   // Create a temporary buffer for the reduction objects of the primary reduction
00307   // so that we can call the companion version of this method.
00308   const int reduct_objs_size = (!is_null(reduct_obj) ? sec_sub_dim : 0);
00309   Workspace<RCP<RTOpPack::ReductTarget> > rcp_reduct_objs(wss, reduct_objs_size);
00310   Workspace<Ptr<RTOpPack::ReductTarget> > reduct_objs(wss, reduct_objs_size);
00311   if (!is_null(reduct_obj)) {
00312     for(Index k = 0; k < sec_sub_dim; ++k) {
00313       rcp_reduct_objs[k] = prim_op.reduct_obj_create();
00314       reduct_objs[k] = rcp_reduct_objs[k].ptr();
00315     }
00316   }
00317  
00318   // Call the companion version that accepts an array of reduction objects
00319   this->applyOp(
00320     prim_op, multi_vecs, targ_multi_vecs, reduct_objs,
00321     prim_first_ele_offset_in, prim_sub_dim_in, prim_global_offset_in,
00322     sec_first_ele_offset_in, sec_sub_dim_in
00323     );
00324 
00325   // Reduce all the reduction objects using the secondary reduction operator
00326   // into one reduction object and free the intermediate reduction objects.
00327   if (!is_null(reduct_obj)) {
00328     for (Index k = 0; k < sec_sub_dim; ++k) {
00329       sec_op.reduce_reduct_objs( *reduct_objs[k], reduct_obj );
00330     }
00331   }
00332 }
00333 
00334 
00335 template<class Scalar>
00336 void MultiVectorDefaultBase<Scalar>::acquireDetachedMultiVectorViewImpl(
00337   const Range1D &rowRng_in,
00338   const Range1D &colRng_in,
00339   RTOpPack::ConstSubMultiVectorView<Scalar> *sub_mv
00340   ) const
00341 {
00342   const Index
00343     rangeDim = this->range()->dim(),
00344     domainDim = this->domain()->dim();
00345   const Range1D
00346     rowRng = rowRng_in.full_range() ? Range1D(0,rangeDim-1) : rowRng_in,
00347     colRng = colRng_in.full_range() ? Range1D(0,domainDim-1) : colRng_in;
00348 #ifdef TEUCHOS_DEBUG
00349   TEST_FOR_EXCEPTION(
00350     !(rowRng.ubound() < rangeDim), std::out_of_range
00351     ,"MultiVectorDefaultBase<Scalar>::acquireDetachedMultiVectorViewImpl(...): Error, rowRng = ["
00352     <<rowRng.lbound()<<","<<rowRng.ubound()<<"] is not in the range = [0,"
00353     <<(rangeDim-1)<<"]!"
00354     );
00355   TEST_FOR_EXCEPTION(
00356     !(colRng.ubound() < domainDim), std::out_of_range
00357     ,"MultiVectorDefaultBase<Scalar>::acquireDetachedMultiVectorViewImpl(...): Error, colRng = ["
00358     <<colRng.lbound()<<","<<colRng.ubound()<<"] is not in the range = [0,"
00359     <<(domainDim-1)<<"]!"
00360     );
00361 #endif
00362   // Allocate storage for the multi-vector (stored column-major)
00363   Scalar *values = new Scalar[ rowRng.size() * colRng.size() ];
00364   // Extract multi-vector values column by column
00365   RTOpPack::ConstSubVectorView<Scalar> sv; // uninitialized by default
00366   for( int k = colRng.lbound(); k <= colRng.ubound(); ++k ) {
00367     RCP<const VectorBase<Scalar> > col_k = this->col(k);
00368     col_k->acquireDetachedView( rowRng, &sv );
00369     for( int i = 0; i < rowRng.size(); ++i )
00370       values[ i + k*rowRng.size() ] = sv[i];
00371     col_k->releaseDetachedView( &sv );
00372   }
00373   // Initialize the multi-vector view object
00374   sub_mv->initialize(
00375     rowRng.lbound() // globalOffset
00376     ,rowRng.size() // subDim
00377     ,colRng.lbound() // colOffset
00378     ,colRng.size() // numSubCols
00379     ,values // values
00380     ,rowRng.size() // leadingDim
00381     );
00382 }
00383 
00384 
00385 template<class Scalar>
00386 void MultiVectorDefaultBase<Scalar>::releaseDetachedMultiVectorViewImpl(
00387   RTOpPack::ConstSubMultiVectorView<Scalar>* sub_mv
00388   ) const
00389 {
00390   // Here we just need to free the view and that is it!
00391   delete [] const_cast<Scalar*>(sub_mv->values().get());
00392   sub_mv->set_uninitialized();
00393 }
00394 
00395 
00396 template<class Scalar>
00397 void MultiVectorDefaultBase<Scalar>::acquireNonconstDetachedMultiVectorViewImpl(
00398   const Range1D &rowRng,
00399   const Range1D &colRng,
00400   RTOpPack::SubMultiVectorView<Scalar> *sub_mv
00401   )
00402 {
00403   using Teuchos::as;
00404   // Use the non-const implementation since it does exactly the
00405   // correct thing in this case also!
00406   MultiVectorDefaultBase<Scalar>::acquireDetachedMultiVectorViewImpl(
00407     rowRng, colRng,
00408     as<RTOpPack::ConstSubMultiVectorView<Scalar>*>(sub_mv)
00409     // This cast will work as long as SubMultiVectorView
00410     // maintains no extra state over ConstSubMultiVectorView (which it
00411     // currently does not) but this is something that I should
00412     // technically check for some how.
00413     );
00414 }
00415 
00416 
00417 template<class Scalar>
00418 void MultiVectorDefaultBase<Scalar>::commitNonconstDetachedMultiVectorViewImpl(
00419   RTOpPack::SubMultiVectorView<Scalar>* sub_mv
00420   )
00421 {
00422 #ifdef TEUCHOS_DEBUG
00423   TEST_FOR_EXCEPTION(
00424     sub_mv==NULL, std::logic_error,
00425     "MultiVectorDefaultBase<Scalar>::commitNonconstDetachedMultiVectorViewImpl(...): Error!"
00426     );
00427 #endif
00428   // Set back the multi-vector values column by column
00429   const Range1D rowRng(sub_mv->globalOffset(),sub_mv->globalOffset()+sub_mv->subDim()-1);
00430   RTOpPack::SubVectorView<Scalar> msv; // uninitialized by default
00431   for( int k = sub_mv->colOffset(); k < sub_mv->numSubCols(); ++k ) {
00432     RCP<VectorBase<Scalar> > col_k = this->col(k);
00433     col_k->acquireDetachedView( rowRng, &msv );
00434     for( int i = 0; i < rowRng.size(); ++i )
00435       msv[i] = sub_mv->values()[ i + k*rowRng.size() ];
00436     col_k->commitDetachedView( &msv );
00437   }
00438   // Free the memory
00439   delete [] const_cast<Scalar*>(sub_mv->values().get());
00440   // Zero out the view
00441   sub_mv->set_uninitialized();
00442 }
00443 
00444 
00445 } // end namespace Thyra
00446 
00447 
00448 #endif // THYRA_MULTI_VECTOR_DEFAULT_BASE_HPP

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