TSFSerialVector.cpp
Go to the documentation of this file.
00001 /* ***********************************************************************
00002 // 
00003 //           TSFExtended: Trilinos Solver Framework Extended
00004 //                 Copyright (2004) Sandia Corporation
00005 // 
00006 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00007 // license for use of this work by or on behalf of the U.S. Government.
00008 // 
00009 // This library is free software; you can redistribute it and/or modify
00010 // it under the terms of the GNU Lesser General Public License as
00011 // published by the Free Software Foundation; either version 2.1 of the
00012 // License, or (at your option) any later version.
00013 //  
00014 // This library is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //  
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00022 // USA
00023 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00024 // 
00025 // **********************************************************************/
00026 
00027 #include "TSFSerialVector.hpp"
00028 #include "TSFSerialVectorSpace.hpp"
00029 #include "Teuchos_TestForException.hpp"
00030 #include "Teuchos_dyn_cast.hpp"
00031 #include "Teuchos_Workspace.hpp"
00032 #include "Thyra_DefaultSpmdVector.hpp"
00033 
00034 #include "Thyra_apply_op_helper.hpp"
00035 #include "RTOpPack_SPMD_apply_op.hpp"
00036 #include "RTOp_parallel_helpers.h"
00037 
00038 
00039 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00040 #include "TSFVectorImpl.hpp"
00041 #include "TSFLinearOperatorImpl.hpp"
00042 #endif
00043 
00044 using namespace Teuchos;
00045 using namespace TSFExtended;
00046 using namespace Thyra;
00047 
00048 using Teuchos::Range1D;
00049 
00050 
00051 SerialVector::SerialVector(
00052   const RCP<const VectorSpaceBase<double> >& vs)
00053   : VectorDefaultBase<double>(), 
00054     vecSpace_(vs), 
00055     data_(vs->dim()),
00056     globalDim_(vs->dim()),
00057     in_applyOpImpl_(false)
00058 {
00059   const SerialVectorSpace* rvs 
00060     = dynamic_cast<const SerialVectorSpace*>(vs.get());
00061   TEST_FOR_EXCEPTION(rvs==0, std::runtime_error,
00062     "could not cast vector space to SerialVectorSpace in "
00063     "SerialVector ctor");
00064 }
00065 
00066 
00067 void SerialVector::applyOpImpl(const RTOpPack::RTOpT< double >& op,
00068     const ArrayView< const Ptr< const VectorBase< double > > > &    vecs,
00069     const ArrayView< const Ptr< VectorBase< double > > > &    targ_vecs,
00070     const Ptr< RTOpPack::ReductTarget > &   reduct_obj,
00071     const OrdType   global_offset_in   
00072   ) const 
00073 {
00074   
00075   // ToDo: Remove this!
00076   const OrdType first_ele_offset_in = 0;
00077   const OrdType sub_dim_in = -1;
00078 
00079   using Teuchos::null;
00080   using Teuchos::dyn_cast;
00081   using Teuchos::Workspace;
00082 
00083   const int num_vecs = vecs.size();
00084   const int num_targ_vecs = targ_vecs.size();
00085 
00086 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00087   Teuchos::RCP<Teuchos::FancyOStream>
00088     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00089   Teuchos::OSTab tab(out);
00090   if(show_dump) {
00091     *out << "\nEntering SpmdVectorBase<double>::applyOp(...) ...\n";
00092     *out
00093       << "\nop = " << typeName(op)
00094       << "\nnum_vecs = " << num_vecs
00095       << "\nnum_targ_vecs = " << num_targ_vecs
00096       << "\nreduct_obj = " << reduct_obj
00097       << "\nfirst_ele_offset_in = " << first_ele_offset_in
00098       << "\nsub_dim_in = " << sub_dim_in
00099       << "\nglobal_offset_in = " << global_offset_in
00100       << "\n"
00101       ;
00102   }
00103 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00104 
00105   Ptr<Teuchos::WorkspaceStore> wss = Teuchos::get_default_workspace_store().ptr();
00106 
00107 #ifdef TEUCHOS_DEBUG
00108   // ToDo: Validate input!
00109   TEST_FOR_EXCEPTION(
00110     in_applyOpImpl_, std::invalid_argument
00111     ,"SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a "
00112     "clear sign that one of the methods acquireDetachedView(...), releaseDetachedView(...) or commitDetachedView(...) "
00113     "was not implemented properly!"
00114     );
00115   Thyra::apply_op_validate_input(
00116     "SpmdVectorBase<>::applyOp(...)",*space(),
00117     op, vecs, targ_vecs, reduct_obj,
00118     global_offset_in
00119     );
00120 #endif
00121 
00122 
00123   // Flag that we are in applyOp()
00124   in_applyOpImpl_ = true;
00125 
00126   const bool locallySerial = true;
00127   int localOffset = 0;
00128   int localSubDim = globalDim_;
00129 
00130   // Get the overlap in the current process with the input logical sub-vector
00131   // from (first_ele_offset_in,sub_dim_in,global_offset_in)
00132   OrdType  overlap_first_local_ele_off = 0;
00133   OrdType  overlap_local_sub_dim = 0;
00134   OrdType  overlap_global_off = 0;
00135   if(localSubDim) {
00136     RTOp_parallel_calc_overlap(
00137       globalDim_, localSubDim, localOffset,
00138       first_ele_offset_in, sub_dim_in, global_offset_in,
00139       &overlap_first_local_ele_off, &overlap_local_sub_dim, &overlap_global_off
00140       );
00141   }
00142   const Range1D local_rng = (
00143     overlap_first_local_ele_off>=0
00144     ? Range1D( localOffset + overlap_first_local_ele_off, localOffset
00145       + overlap_first_local_ele_off + overlap_local_sub_dim - 1 )
00146     : Range1D::Invalid
00147     );
00148 
00149 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00150   if(show_dump) {
00151     *out
00152       << "\noverlap_first_local_ele_off = " << overlap_first_local_ele_off
00153       << "\noverlap_local_sub_dim = " << overlap_local_sub_dim
00154       << "\noverlap_global_off = " << overlap_global_off
00155       << "\nlocal_rng = ["<<local_rng.lbound()<<","<<local_rng.ubound()<<"]"
00156       << "\n"
00157       ;
00158   }
00159 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00160 
00161   // Create sub-vector views of all of the *participating* local data
00162   Workspace<RTOpPack::ConstSubVectorView<double> > sub_vecs(wss.get(),num_vecs);
00163   Workspace<RTOpPack::SubVectorView<double> > sub_targ_vecs(wss.get(),num_targ_vecs);
00164   if( overlap_first_local_ele_off >= 0 ) {
00165     {for(int k = 0; k < num_vecs; ++k ) {
00166       vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] );
00167       sub_vecs[k].setGlobalOffset( overlap_global_off );
00168     }}
00169     {for(int k = 0; k < num_targ_vecs; ++k ) {
00170       targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] );
00171       sub_targ_vecs[k].setGlobalOffset( overlap_global_off );
00172     }}
00173   }
00174 
00175   
00176 
00177   // Apply the RTOp operator object (all processors must participate)
00178   RTOpPack::SPMD_apply_op(
00179     NULL ,     // comm
00180     op,                                    // op
00181     num_vecs,                              // num_vecs
00182     sub_vecs.getRawPtr(),                  // sub_vecs
00183     num_targ_vecs,                         // num_targ_vecs
00184     sub_targ_vecs.getRawPtr(),             // targ_sub_vecs
00185     reduct_obj.get()                       // reduct_obj
00186     );
00187 
00188   // Free and commit the local data
00189   if (overlap_first_local_ele_off >= 0) {
00190     for (int k = 0; k < num_vecs; ++k ) {
00191       sub_vecs[k].setGlobalOffset(local_rng.lbound());
00192       vecs[k]->releaseDetachedView( &sub_vecs[k] );
00193     }
00194     for (int k = 0; k < num_targ_vecs; ++k ) {
00195       sub_targ_vecs[k].setGlobalOffset(local_rng.lbound());
00196       targ_vecs[k]->commitDetachedView( &sub_targ_vecs[k] );
00197     }
00198   }
00199 
00200   // Flag that we are leaving applyOp()
00201   in_applyOpImpl_ = false;
00202 
00203 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00204   if(show_dump) {
00205     *out << "\nLeaving SpmdVectorBase<double>::applyOp(...) ...\n";
00206   }
00207 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00208 
00209 }
00210 
00211 
00212 
00213 
00214 void SerialVector::acquireDetachedVectorViewImpl(
00215   const Teuchos::Range1D& rng_in,
00216   RTOpPack::ConstSubVectorView<double>* sub_vec) const
00217 {
00218   /* if range is empty, return a null view */
00219   if (rng_in == Range1D::Invalid)
00220   {
00221     sub_vec->initialize(rng_in.lbound(), 0, Teuchos::ArrayRCP<double>(), 1);
00222     return ;
00223   }
00224 
00225   /* */
00226   const Range1D rng = validateRange(rng_in);
00227   int localOffset = 0;
00228   int localSubDim = globalDim_;
00229 
00230   /* If any requested elements are off-processor, fall back to slow 
00231    * VDB implementation */ 
00232   if ( 
00233     rng.lbound() < localOffset 
00234     || localOffset + localSubDim - 1 < rng.ubound())
00235   {
00236     VectorDefaultBase<double>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00237     return ;
00238   }
00239 
00240   /* All requested elements are on-processor. */
00241   const double* localValues = &(data_[0]);
00242   Teuchos::ArrayRCP<const double> locVals(localValues, rng.lbound()-localOffset,
00243     rng.size(), false);
00244 //    rng.ubound()-localOffset_, false);
00245 
00246   OrdType stride = 1;
00247   
00248   sub_vec->initialize(rng.lbound(), rng.size(),
00249     locVals, stride);
00250 //    localValues+(rng.lbound()-localOffset_), stride);
00251 }
00252 
00253 
00254 
00255 
00256 void SerialVector::releaseDetachedVectorViewImpl(
00257   RTOpPack::ConstSubVectorView<double>* sub_vec) const
00258 {
00259   int localOffset = 0;
00260   int localSubDim = globalDim_;
00261   if(
00262     sub_vec->globalOffset() < localOffset 
00263     || localOffset+localSubDim < sub_vec->globalOffset()+sub_vec->subDim()
00264     )
00265   {
00266     // Let the default implementation handle it!
00267     VectorDefaultBase<double>::releaseDetachedVectorViewImpl(sub_vec);
00268     return;
00269   }
00270   // Nothing to deallocate!
00271   sub_vec->uninitialize();
00272 }
00273 
00274 
00275 
00276 
00277 void SerialVector::acquireNonconstDetachedVectorViewImpl(
00278   const Teuchos::Range1D& rng_in, 
00279   RTOpPack::SubVectorView<double>* sub_vec) 
00280 {
00281   int localOffset = 0;
00282   int localSubDim = globalDim_;
00283 
00284   if( rng_in == Range1D::Invalid ) {
00285     // Just return an null view
00286     sub_vec->initialize(rng_in.lbound(), 0, Teuchos::ArrayRCP<double>(), 1);
00287     return;
00288   }
00289   
00290   const Range1D rng = validateRange(rng_in);
00291   if(
00292     rng.lbound() < localOffset 
00293     ||
00294     localOffset+localSubDim-1 < rng.ubound()
00295     )
00296   {
00297     /* rng consists of off-processor elements so use the 
00298      * default implementation! */
00299     VectorDefaultBase<double>::acquireNonconstDetachedVectorViewImpl(rng_in,
00300       sub_vec);
00301     return;
00302   }
00303 
00304   /* All requested elements are on-processor. */
00305   double* localValues = &(data_[0]);
00306   Teuchos::ArrayRCP<double> locVals(localValues, rng.lbound()-localOffset,
00307 //    rng.ubound()-localOffset_, false);
00308     rng.size(), false);
00309   OrdType stride = 1;
00310 
00311   sub_vec->initialize(rng.lbound(), rng.size(),
00312     locVals, stride);
00313 //    localValues+(rng.lbound()-localOffset_),stride);
00314 }
00315 
00316 
00317 
00318 void SerialVector::commitNonconstDetachedVectorViewImpl(
00319   RTOpPack::SubVectorView<double>* sub_vec
00320   )
00321 {
00322   int localOffset = 0;
00323   int localSubDim = globalDim_;
00324   if(
00325     sub_vec->globalOffset() < localOffset
00326     ||
00327     localOffset+localSubDim < sub_vec->globalOffset()+sub_vec->subDim()
00328     )
00329   {
00330     // Let the default implementation handle it!
00331     VectorDefaultBase<double>::commitNonconstDetachedVectorViewImpl(sub_vec);
00332     return;
00333   }
00334   sub_vec->uninitialize();  // Nothing to deallocate!
00335 }
00336 
00337 
00338 
00339 
00340 Teuchos::Range1D SerialVector::validateRange(const Teuchos::Range1D& rng_in) const 
00341 {
00342   const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
00343   TEST_FOR_EXCEPTION(
00344     !( 0 <= rng.lbound() && rng.ubound() < globalDim_ ), std::invalid_argument
00345     ,"SerialVector::validateRange(rowRng): Error, the range rng = ["
00346     <<rng.lbound()<<","<<rng.ubound()<<"] is not "
00347     "in the range [0,"<<(globalDim_-1)<<"]!"
00348     );
00349   return rng;
00350 }
00351 
00352 
00353 
00354 
00355 
00356 double& SerialVector::operator[](OrdType globalIndex) 
00357 {
00358   return data_[globalIndex];
00359 }
00360 
00361 void SerialVector::setElement(OrdType index, const double& value)
00362 {
00363   data_[index] = value;
00364 }
00365 
00366 void SerialVector::addToElement(OrdType index, const double& value)
00367 {
00368   data_[index] += value;
00369 }
00370 
00371 const double& SerialVector::getElement(OrdType index) const 
00372 {
00373   return data_[index];
00374 }
00375 
00376 void SerialVector::getElements(const OrdType* globalIndices, int numElems,
00377   Teuchos::Array<double>& elems) const
00378 {
00379   elems.resize(numElems);
00380 
00381   for (int i=0; i<numElems; i++)
00382   {
00383     elems[i] = data_[globalIndices[i]];
00384   }
00385 }
00386 
00387 void SerialVector::setElements(int numElems, const int* globalIndices,
00388   const double* values)
00389 {
00390   for (int i=0; i<numElems; i++)
00391   {
00392     data_[globalIndices[i]] = values[i];
00393   }
00394 }
00395 
00396 void SerialVector::addToElements(int numElems, const int* globalIndices,
00397   const double* values)
00398 {
00399   for (int i=0; i<numElems; i++)
00400   {
00401     data_[globalIndices[i]] += values[i];
00402   }
00403 }
00404 
00405 const SerialVector* SerialVector::getConcrete(const Vector<double>& x)
00406 {
00407   const SerialVector* rtn = dynamic_cast<const SerialVector*>(x.ptr().get());
00408   TEST_FOR_EXCEPT(rtn==0);
00409   return rtn;
00410 }
00411 
00412 SerialVector* SerialVector::getConcrete(Vector<double>& x)
00413 {
00414   SerialVector* rtn = dynamic_cast<SerialVector*>(x.ptr().get());
00415   TEST_FOR_EXCEPT(rtn==0);
00416   return rtn;
00417 }
00418 
00419 void SerialVector::finalizeAssembly()
00420 {
00421   // no-op
00422 }
00423 
00424 
00425 void SerialVector::print(std::ostream& os) const 
00426 {
00427   for (int i=0; i<data_.size(); i++)
00428   {
00429     os << std::setw(5) << i << " " << std::setw(20) << data_[i] << std::endl;
00430   }
00431 }
00432 
00433 

Site Contact