TSFEpetraVector.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 "TSFEpetraVector.hpp"
00028 #include "TSFEpetraVectorSpace.hpp"
00029 #include "Teuchos_TestForException.hpp"
00030 #include "Teuchos_dyn_cast.hpp"
00031 #include "Teuchos_Workspace.hpp"
00032 #include "Thyra_DefaultSpmdVector.hpp"
00033 #ifdef HAVE_MPI
00034 #include "Teuchos_DefaultMpiComm.hpp"
00035 #endif
00036 #include "Teuchos_DefaultSerialComm.hpp"
00037 
00038 #include "Thyra_apply_op_helper.hpp"
00039 #include "RTOpPack_SPMD_apply_op.hpp"
00040 #include "RTOp_parallel_helpers.h"
00041 
00042 
00043 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00044 #include "TSFVectorImpl.hpp"
00045 #include "TSFLinearOperatorImpl.hpp"
00046 #endif
00047 
00048 using namespace Teuchos;
00049 using namespace TSFExtended;
00050 using namespace Thyra;
00051 
00052 using Teuchos::Range1D;
00053 
00054 
00055 EpetraVector::EpetraVector(
00056   const RCP<const VectorSpaceBase<double> >& vs)
00057   : VectorDefaultBase<double>(), 
00058     epetraVec_(), 
00059     vecSpace_(vs), 
00060     epetraVecSpace_(), 
00061     epetraMap_(),
00062     localOffset_(),
00063     localSubDim_(),
00064     globalDim_(vs->dim()),
00065     in_applyOpImpl_(false)
00066 {
00067   const EpetraVectorSpace* epvs 
00068     = dynamic_cast<const EpetraVectorSpace*>(vs.get());
00069   TEST_FOR_EXCEPTION(epvs==0, std::runtime_error,
00070     "could not cast vector space to EpetraVectorSpace in "
00071     "EpetraVector ctor");
00072 
00073   epetraVecSpace_ = rcp_dynamic_cast<const EpetraVectorSpace>(vs);
00074   epetraMap_ = epvs->epetraMap();
00075   epetraVec_ = rcp(new Epetra_Vector(*epetraMap_, true));
00076 
00077   localOffset_ = epetraMap_->MinMyGID();
00078   localSubDim_ = epetraMap_->NumMyElements();
00079 }
00080 
00081 
00082 
00083 EpetraVector
00084 ::EpetraVector(const RCP<const VectorSpaceBase<double> >& vs,
00085   const RCP<Epetra_Vector>& vec)
00086   : VectorDefaultBase<double>(), 
00087     epetraVec_(vec), 
00088     vecSpace_(vs), 
00089     epetraVecSpace_(), 
00090     epetraMap_(),
00091     localOffset_(),
00092     localSubDim_(),
00093     globalDim_(vs->dim()),
00094     in_applyOpImpl_(false)
00095 {
00096   const EpetraVectorSpace* epvs 
00097     = dynamic_cast<const EpetraVectorSpace*>(vs.get());
00098   TEST_FOR_EXCEPTION(epvs==0, std::runtime_error,
00099     "could not cast vector space to EpetraVectorSpace in "
00100     "EpetraVector ctor");
00101 
00102 
00103   epetraVecSpace_ = rcp_dynamic_cast<const EpetraVectorSpace>(vs);
00104   epetraMap_ = epvs->epetraMap();
00105   if (vec.get() == 0) epetraVec_ = rcp(new Epetra_Vector(*epetraMap_, true));
00106 
00107   localOffset_ = epetraMap_->MinMyGID();
00108   localSubDim_ = epetraMap_->NumMyElements();
00109 }
00110 
00111 
00112 
00113 
00114 
00115 #ifndef TRILINOS_8
00116 
00117 void EpetraVector::applyOpImpl(const RTOpPack::RTOpT< double >& op,
00118     const ArrayView< const Ptr< const VectorBase< double > > > &    vecs,
00119     const ArrayView< const Ptr< VectorBase< double > > > &    targ_vecs,
00120     const Ptr< RTOpPack::ReductTarget > &   reduct_obj,
00121     const OrdType   global_offset_in   
00122   ) const 
00123 {
00124   
00125   // ToDo: Remove this!
00126   const OrdType first_ele_offset_in = 0;
00127   const OrdType sub_dim_in = -1;
00128 
00129   using Teuchos::null;
00130   using Teuchos::dyn_cast;
00131   using Teuchos::Workspace;
00132 
00133   const int num_vecs = vecs.size();
00134   const int num_targ_vecs = targ_vecs.size();
00135 
00136 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00137   Teuchos::RCP<Teuchos::FancyOStream>
00138     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00139   Teuchos::OSTab tab(out);
00140   if(show_dump) {
00141     *out << "\nEntering SpmdVectorBase<double>::applyOp(...) ...\n";
00142     *out
00143       << "\nop = " << typeName(op)
00144       << "\nnum_vecs = " << num_vecs
00145       << "\nnum_targ_vecs = " << num_targ_vecs
00146       << "\nreduct_obj = " << reduct_obj
00147       << "\nfirst_ele_offset_in = " << first_ele_offset_in
00148       << "\nsub_dim_in = " << sub_dim_in
00149       << "\nglobal_offset_in = " << global_offset_in
00150       << "\n"
00151       ;
00152   }
00153 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00154 
00155   Ptr<Teuchos::WorkspaceStore> wss = Teuchos::get_default_workspace_store().ptr();
00156 
00157 #ifdef TEUCHOS_DEBUG
00158   // ToDo: Validate input!
00159   TEST_FOR_EXCEPTION(
00160     in_applyOpImpl_, std::invalid_argument
00161     ,"SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a "
00162     "clear sign that one of the methods acquireDetachedView(...), releaseDetachedView(...) or commitDetachedView(...) "
00163     "was not implemented properly!"
00164     );
00165   Thyra::apply_op_validate_input(
00166     "SpmdVectorBase<>::applyOp(...)",*space(),
00167     op, vecs, targ_vecs, reduct_obj,
00168     global_offset_in
00169     );
00170 #endif
00171 
00172   const Teuchos::RCP<const Teuchos::Comm<OrdType> >& comm
00173     = epetraVecSpace_->getComm();
00174 
00175   const SerialComm<OrdType>* serialComm = 
00176     dynamic_cast<const SerialComm<OrdType>* >(comm.get());
00177 
00178 
00179   // Flag that we are in applyOp()
00180   in_applyOpImpl_ = true;
00181 
00182   // First see if this is a locally replicated vector in which case
00183   // we treat this as a local operation only.
00184   const bool locallyReplicated = ( serialComm != 0 && localSubDim_ == globalDim_ );
00185 
00186   // Get the overlap in the current process with the input logical sub-vector
00187   // from (first_ele_offset_in,sub_dim_in,global_offset_in)
00188   OrdType  overlap_first_local_ele_off = 0;
00189   OrdType  overlap_local_sub_dim = 0;
00190   OrdType  overlap_global_off = 0;
00191   if(localSubDim_) {
00192     RTOp_parallel_calc_overlap(
00193       globalDim_, localSubDim_, localOffset_,
00194       first_ele_offset_in, sub_dim_in, global_offset_in,
00195       &overlap_first_local_ele_off, &overlap_local_sub_dim, &overlap_global_off
00196       );
00197   }
00198   const Range1D local_rng = (
00199     overlap_first_local_ele_off>=0
00200     ? Range1D( localOffset_ + overlap_first_local_ele_off, localOffset_
00201       + overlap_first_local_ele_off + overlap_local_sub_dim - 1 )
00202     : Range1D::Invalid
00203     );
00204 
00205 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00206   if(show_dump) {
00207     *out
00208       << "\noverlap_first_local_ele_off = " << overlap_first_local_ele_off
00209       << "\noverlap_local_sub_dim = " << overlap_local_sub_dim
00210       << "\noverlap_global_off = " << overlap_global_off
00211       << "\nlocal_rng = ["<<local_rng.lbound()<<","<<local_rng.ubound()<<"]"
00212       << "\n"
00213       ;
00214   }
00215 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00216 
00217   // Create sub-vector views of all of the *participating* local data
00218   Workspace<RTOpPack::ConstSubVectorView<double> > sub_vecs(wss.get(),num_vecs);
00219   Workspace<RTOpPack::SubVectorView<double> > sub_targ_vecs(wss.get(),num_targ_vecs);
00220   if( overlap_first_local_ele_off >= 0 ) {
00221     {for(int k = 0; k < num_vecs; ++k ) {
00222       vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] );
00223       sub_vecs[k].setGlobalOffset( overlap_global_off );
00224     }}
00225     {for(int k = 0; k < num_targ_vecs; ++k ) {
00226       targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] );
00227       sub_targ_vecs[k].setGlobalOffset( overlap_global_off );
00228     }}
00229   }
00230 
00231   
00232 
00233   // Apply the RTOp operator object (all processors must participate)
00234   RTOpPack::SPMD_apply_op(
00235     locallyReplicated ? NULL : &*comm,     // comm
00236     op,                                    // op
00237     num_vecs,                              // num_vecs
00238     sub_vecs.getRawPtr(),                  // sub_vecs
00239     num_targ_vecs,                         // num_targ_vecs
00240     sub_targ_vecs.getRawPtr(),             // targ_sub_vecs
00241     reduct_obj.get()                       // reduct_obj
00242     );
00243 
00244   // Free and commit the local data
00245   if (overlap_first_local_ele_off >= 0) {
00246     for (int k = 0; k < num_vecs; ++k ) {
00247       sub_vecs[k].setGlobalOffset(local_rng.lbound());
00248       vecs[k]->releaseDetachedView( &sub_vecs[k] );
00249     }
00250     for (int k = 0; k < num_targ_vecs; ++k ) {
00251       sub_targ_vecs[k].setGlobalOffset(local_rng.lbound());
00252       targ_vecs[k]->commitDetachedView( &sub_targ_vecs[k] );
00253     }
00254   }
00255 
00256   // Flag that we are leaving applyOp()
00257   in_applyOpImpl_ = false;
00258 
00259 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00260   if(show_dump) {
00261     *out << "\nLeaving SpmdVectorBase<double>::applyOp(...) ...\n";
00262   }
00263 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00264 
00265 }
00266 
00267 #else
00268 
00269 void EpetraVector::applyOp(
00270   const RTOpPack::RTOpT<double> &op,
00271   const int num_vecs,
00272   const VectorBase<double>*const vecs[],
00273   const int num_targ_vecs,
00274   VectorBase<double>*const targ_vecs[],
00275   RTOpPack::ReductTarget *reduct_obj,
00276   const OrdType first_ele_offset_in,
00277   const OrdType sub_dim_in,
00278   const OrdType global_offset_in
00279   ) const 
00280 {
00281 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00282   Teuchos::RCP<Teuchos::FancyOStream>
00283     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00284   Teuchos::OSTab tab(out);
00285   if(show_dump) {
00286     *out << "\nEntering SpmdVectorBase<double>::applyOp(...) ...\n";
00287     *out
00288       << "\nop = " << typeName(op)
00289       << "\nnum_vecs = " << num_vecs
00290       << "\nnum_targ_vecs = " << num_targ_vecs
00291       << "\nreduct_obj = " << reduct_obj
00292       << "\nfirst_ele_offset_in = " << first_ele_offset_in
00293       << "\nsub_dim_in = " << sub_dim_in
00294       << "\nglobal_offset_in = " << global_offset_in
00295       << "\n"
00296       ;
00297   }
00298 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00299   using Teuchos::dyn_cast;
00300   using Teuchos::Workspace;
00301   Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get();
00302 
00303 #ifdef TEUCHOS_DEBUG
00304   // ToDo: Validate input!
00305   TEST_FOR_EXCEPTION(
00306     in_applyOpImpl_, std::invalid_argument
00307     ,"SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a "
00308     "clear sign that one of the methods acquireDetachedView(...), releaseDetachedView(...) or commitDetachedView(...) "
00309     "was not implemented properly!"
00310     );
00311   Thyra::apply_op_validate_input(
00312     "SpmdVectorBase<>::applyOp(...)",*space()
00313     ,op,num_vecs,vecs,num_targ_vecs,targ_vecs,reduct_obj,first_ele_offset_in,sub_dim_in,global_offset_in
00314     );
00315 #endif  
00316 
00317   const Teuchos::RCP<const Teuchos::Comm<OrdType> >& comm
00318     = epetraVecSpace_->getComm();
00319 
00320   const SerialComm<OrdType>* serialComm = 
00321     dynamic_cast<const SerialComm<OrdType>* >(comm.get());
00322 
00323 
00324   // Flag that we are in applyOp()
00325   in_applyOpImpl_ = true;
00326 
00327   // First see if this is a locally replicated vector in which case
00328   // we treat this as a local operation only.
00329   const bool locallyReplicated = ( serialComm != 0 && localSubDim_ == globalDim_ );
00330   
00331   // Get the overlap in the current process with the input logical sub-vector
00332   // from (first_ele_offset_in,sub_dim_in,global_offset_in)
00333   OrdType  overlap_first_local_ele_off  = 0;
00334   OrdType  overlap_local_sub_dim        = 0;
00335   OrdType  overlap_global_off           = 0;
00336   if(localSubDim_) {
00337     RTOp_parallel_calc_overlap(
00338       globalDim_, localSubDim_, localOffset_, first_ele_offset_in, sub_dim_in, global_offset_in
00339       ,&overlap_first_local_ele_off, &overlap_local_sub_dim, &overlap_global_off
00340       );
00341   }
00342   const Range1D local_rng = (
00343     overlap_first_local_ele_off>=0
00344     ? Range1D( localOffset_ + overlap_first_local_ele_off, localOffset_ + overlap_first_local_ele_off + overlap_local_sub_dim - 1 )
00345     : Range1D::Invalid
00346     );
00347 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00348   if(show_dump) {
00349     *out
00350       << "\noverlap_first_local_ele_off = " << overlap_first_local_ele_off
00351       << "\noverlap_local_sub_dim = " << overlap_local_sub_dim
00352       << "\noverlap_global_off = " << overlap_global_off
00353       << "\nlocal_rng = ["<<local_rng.lbound()<<","<<local_rng.ubound()<<"]"
00354       << "\n"
00355       ;
00356   }
00357 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00358   // Create sub-vector views of all of the *participating* local data
00359   Workspace<RTOpPack::ConstSubVectorView<double> > sub_vecs(wss,num_vecs);
00360   Workspace<RTOpPack::SubVectorView<double> > sub_targ_vecs(wss,num_targ_vecs);
00361   if( overlap_first_local_ele_off >= 0 ) {
00362     {for(int k = 0; k < num_vecs; ++k ) {
00363       vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] );
00364       sub_vecs[k].setGlobalOffset( overlap_global_off );
00365     }}
00366     {for(int k = 0; k < num_targ_vecs; ++k ) {
00367       targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] );
00368       sub_targ_vecs[k].setGlobalOffset( overlap_global_off );
00369     }}
00370   }
00371   // Apply the RTOp operator object (all processors must participate)
00372   const bool validSubVecs = ( localSubDim_ > 0 && overlap_first_local_ele_off >= 0 );
00373   RTOpPack::SPMD_apply_op(
00374     locallyReplicated ? NULL : comm.get()                       // comm
00375     ,op                                                         // op
00376     ,num_vecs                                                   // num_vecs
00377     ,num_vecs && validSubVecs ? &sub_vecs[0] : NULL             // sub_vecs
00378     ,num_targ_vecs                                              // num_targ_vecs
00379     ,num_targ_vecs && validSubVecs ? &sub_targ_vecs[0] : NULL   // targ_sub_vecs
00380     ,reduct_obj                                                 // reduct_obj
00381     );
00382   // Free and commit the local data
00383   if( overlap_first_local_ele_off >= 0 ) {
00384     {for(int k = 0; k < num_vecs; ++k ) {
00385       sub_vecs[k].setGlobalOffset(local_rng.lbound());
00386       vecs[k]->releaseDetachedView( &sub_vecs[k] );
00387     }}
00388     {for(int k = 0; k < num_targ_vecs; ++k ) {
00389       sub_targ_vecs[k].setGlobalOffset(local_rng.lbound());
00390       targ_vecs[k]->commitDetachedView( &sub_targ_vecs[k] );
00391     }}
00392   }
00393   // Flag that we are leaving applyOp()
00394   in_applyOpImpl_ = false;
00395 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00396   if(show_dump) {
00397     *out << "\nLeaving SpmdVectorBase<double>::applyOp(...) ...\n";
00398   }
00399 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00400 }
00401 
00402 
00403 
00404 #endif
00405 
00406 
00407 
00408 
00409 void EpetraVector::acquireDetachedVectorViewImpl(
00410   const Teuchos::Range1D& rng_in,
00411   RTOpPack::ConstSubVectorView<double>* sub_vec) const
00412 {
00413   /* if range is empty, return a null view */
00414   if (rng_in == Range1D::Invalid)
00415   {
00416     sub_vec->initialize(rng_in.lbound(), 0, Teuchos::ArrayRCP<double>(), 1);
00417     return ;
00418   }
00419 
00420   /* */
00421   const Range1D rng = validateRange(rng_in);
00422 
00423   /* If any requested elements are off-processor, fall back to slow 
00424    * VDB implementation */ 
00425   if ( 
00426     rng.lbound() < localOffset_ 
00427     || localOffset_ + localSubDim_ - 1 < rng.ubound())
00428   {
00429     VectorDefaultBase<double>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00430     return ;
00431   }
00432 
00433   /* All requested elements are on-processor. */
00434   const double* localValues = &(epetraVec_->operator[](0));
00435   Teuchos::ArrayRCP<const double> locVals(localValues, rng.lbound()-localOffset_,
00436     rng.size(), false);
00437 //    rng.ubound()-localOffset_, false);
00438 
00439   OrdType stride = 1;
00440   
00441   sub_vec->initialize(rng.lbound(), rng.size(),
00442     locVals, stride);
00443 //    localValues+(rng.lbound()-localOffset_), stride);
00444 }
00445 
00446 
00447 
00448 
00449 void EpetraVector::releaseDetachedVectorViewImpl(
00450   RTOpPack::ConstSubVectorView<double>* sub_vec) const
00451 {
00452   if(
00453     sub_vec->globalOffset() < localOffset_ 
00454     || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
00455     )
00456   {
00457     // Let the default implementation handle it!
00458     VectorDefaultBase<double>::releaseDetachedVectorViewImpl(sub_vec);
00459     return;
00460   }
00461   // Nothing to deallocate!
00462   sub_vec->uninitialize();
00463 }
00464 
00465 
00466 
00467 
00468 void EpetraVector::acquireNonconstDetachedVectorViewImpl(
00469   const Teuchos::Range1D& rng_in, 
00470   RTOpPack::SubVectorView<double>* sub_vec) 
00471 {
00472   if( rng_in == Range1D::Invalid ) {
00473     // Just return an null view
00474     sub_vec->initialize(rng_in.lbound(), 0, Teuchos::ArrayRCP<double>(), 1);
00475     return;
00476   }
00477   
00478   const Range1D rng = validateRange(rng_in);
00479   if(
00480     rng.lbound() < localOffset_ 
00481     ||
00482     localOffset_+localSubDim_-1 < rng.ubound()
00483     )
00484   {
00485     /* rng consists of off-processor elements so use the 
00486      * default implementation! */
00487     VectorDefaultBase<double>::acquireNonconstDetachedVectorViewImpl(rng_in,
00488       sub_vec);
00489     return;
00490   }
00491 
00492   /* All requested elements are on-processor. */
00493   double* localValues = &(epetraVec_->operator[](0));
00494   Teuchos::ArrayRCP<double> locVals(localValues, rng.lbound()-localOffset_,
00495 //    rng.ubound()-localOffset_, false);
00496     rng.size(), false);
00497   OrdType stride = 1;
00498 
00499   sub_vec->initialize(rng.lbound(), rng.size(),
00500     locVals, stride);
00501 //    localValues+(rng.lbound()-localOffset_),stride);
00502 }
00503 
00504 
00505 
00506 void EpetraVector::commitNonconstDetachedVectorViewImpl(
00507   RTOpPack::SubVectorView<double>* sub_vec
00508   )
00509 {
00510   if(
00511     sub_vec->globalOffset() < localOffset_
00512     ||
00513     localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
00514     )
00515   {
00516     // Let the default implementation handle it!
00517     VectorDefaultBase<double>::commitNonconstDetachedVectorViewImpl(sub_vec);
00518     return;
00519   }
00520   sub_vec->uninitialize();  // Nothing to deallocate!
00521 }
00522 
00523 
00524 
00525 
00526 Teuchos::Range1D EpetraVector::validateRange(const Teuchos::Range1D& rng_in) const 
00527 {
00528   const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
00529   TEST_FOR_EXCEPTION(
00530     !( 0 <= rng.lbound() && rng.ubound() < globalDim_ ), std::invalid_argument
00531     ,"EpetraVector::validateRange(rowRng): Error, the range rng = ["
00532     <<rng.lbound()<<","<<rng.ubound()<<"] is not "
00533     "in the range [0,"<<(globalDim_-1)<<"]!"
00534     );
00535   return rng;
00536 }
00537 
00538 
00539 
00540 
00541 
00542 double& EpetraVector::operator[](OrdType globalIndex) 
00543 {
00544   const Epetra_BlockMap& myMap = epetraVec()->Map();
00545   return (*epetraVec())[myMap.LID(globalIndex)];
00546 }
00547 
00548 void EpetraVector::setElement(OrdType index, const double& value)
00549 {
00550   int loc_index[1] = { index };
00551   epetraVec()->ReplaceGlobalValues(1, const_cast<double*>(&value), 
00552     loc_index);
00553 }
00554 
00555 void EpetraVector::addToElement(OrdType index, const double& value)
00556 {
00557 //  cout << "adding (" << index << ", " << value << ")" << std::endl;
00558   int loc_index[1] = { index };
00559   epetraVec()->SumIntoGlobalValues(1, const_cast<double*>(&value), 
00560     loc_index);
00561 }
00562 
00563 const double& EpetraVector::getElement(OrdType index) const 
00564 {
00565   const Epetra_BlockMap& myMap = epetraVec()->Map();
00566   return (*epetraVec())[myMap.LID(index)];
00567 }
00568 
00569 void EpetraVector::getElements(const OrdType* globalIndices, int numElems,
00570   Teuchos::Array<double>& elems) const
00571 {
00572   elems.resize(numElems);
00573   const Epetra_BlockMap& myMap = epetraVec()->Map();
00574   RCP<const Epetra_Vector> epv = epetraVec();
00575 
00576   for (int i=0; i<numElems; i++)
00577   {
00578     elems[i] = (*epv)[myMap.LID(globalIndices[i])];
00579   }
00580 }
00581 
00582 void EpetraVector::setElements(int numElems, const int* globalIndices,
00583   const double* values)
00584 {
00585   Epetra_FEVector* vec = dynamic_cast<Epetra_FEVector*>(epetraVec().get());
00586   int ierr = vec->ReplaceGlobalValues(numElems, globalIndices, values);
00587   TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, "ReplaceGlobalValues returned "
00588     "ierr=" << ierr << " in EpetraVector::setElements()");
00589 }
00590 
00591 void EpetraVector::addToElements(int numElems, const int* globalIndices,
00592   const double* values)
00593 {
00594   Epetra_FEVector* vec = dynamic_cast<Epetra_FEVector*>(epetraVec().get());
00595   int ierr = vec->SumIntoGlobalValues(numElems, globalIndices, values);
00596   TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, "SumIntoGlobalValues returned "
00597     "ierr=" << ierr << " in EpetraVector::addToElements()");
00598 }
00599 
00600 void EpetraVector::finalizeAssembly()
00601 {
00602   Epetra_FEVector* vec = dynamic_cast<Epetra_FEVector*>(epetraVec().get());
00603   vec->GlobalAssemble();
00604 }
00605 
00606 
00607 void EpetraVector::print(std::ostream& os) const 
00608 {
00609   epetraVec()->Print(os);
00610 }
00611 
00612 
00613 const Epetra_Vector& EpetraVector::getConcrete(const TSFExtended::Vector<double>& tsfVec)
00614 {
00615   const EpetraVector* epv 
00616     = dynamic_cast<const EpetraVector*>(tsfVec.ptr().get());
00617   TEST_FOR_EXCEPTION(epv==0, std::runtime_error,
00618     "EpetraVector::getConcrete called on a vector that "
00619     "could not be cast to an EpetraVector");
00620   return *(epv->epetraVec());
00621 }
00622 
00623 Epetra_Vector& EpetraVector::getConcrete(TSFExtended::Vector<double>& tsfVec)
00624 {
00625   EpetraVector* epv 
00626     = dynamic_cast<EpetraVector*>(tsfVec.ptr().get());
00627   TEST_FOR_EXCEPTION(epv==0, std::runtime_error,
00628     "EpetraVector::getConcrete called on a vector that "
00629     "could not be cast to an EpetraVector");
00630   return *(epv->epetraVec());
00631 }
00632 
00633 
00634 Epetra_Vector* EpetraVector::getConcretePtr(TSFExtended::Vector<double>& tsfVec)
00635 {
00636   EpetraVector* epv 
00637     = dynamic_cast<EpetraVector*>(tsfVec.ptr().get());
00638   TEST_FOR_EXCEPTION(epv==0, std::runtime_error,
00639     "EpetraVector::getConcrete called on a vector that "
00640     "could not be cast to an EpetraVector");
00641   return epv->epetraVec().get();
00642 }
00643 
00644 
00645 
00646 

Site Contact