Thyra Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Thyra_EpetraLinearOp.cpp
Go to the documentation of this file.
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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Thyra_EpetraLinearOp.hpp"
00043 #include "Thyra_EpetraThyraWrappers.hpp"
00044 #include "Thyra_SpmdMultiVectorBase.hpp"
00045 #include "Thyra_MultiVectorStdOps.hpp"
00046 #include "Thyra_AssertOp.hpp"
00047 #include "Teuchos_dyn_cast.hpp"
00048 #include "Teuchos_Assert.hpp"
00049 #include "Teuchos_getConst.hpp"
00050 #include "Teuchos_as.hpp"
00051 #include "Teuchos_TimeMonitor.hpp"
00052 
00053 #include "Epetra_Map.h"
00054 #include "Epetra_Vector.h"
00055 #include "Epetra_Operator.h"
00056 #include "Epetra_CrsMatrix.h" // Printing and absolute row sums only!
00057 
00058 
00059 namespace Thyra {
00060 
00061 
00062 // Constructors / initializers / accessors
00063 
00064 
00065 EpetraLinearOp::EpetraLinearOp()
00066   :isFullyInitialized_(false),
00067    opTrans_(NOTRANS),
00068    applyAs_(EPETRA_OP_APPLY_APPLY),
00069    adjointSupport_(EPETRA_OP_ADJOINT_UNSUPPORTED)
00070 {}
00071 
00072 
00073 void EpetraLinearOp::initialize(
00074   const RCP<Epetra_Operator> &op,
00075   EOpTransp opTrans,
00076   EApplyEpetraOpAs applyAs,
00077   EAdjointEpetraOp adjointSupport,
00078   const RCP< const VectorSpaceBase<double> > &range_in,
00079   const RCP< const VectorSpaceBase<double> > &domain_in
00080   )
00081 {
00082   
00083   using Teuchos::rcp_dynamic_cast;
00084   typedef SpmdVectorSpaceBase<double> SPMDVSB;
00085 
00086   // Validate input, allocate spaces, validate ...
00087 #ifdef TEUCHOS_DEBUG
00088   TEUCHOS_TEST_FOR_EXCEPTION( is_null(op), std::invalid_argument,
00089     "Thyra::EpetraLinearOp::initialize(...): Error!" );
00090   // ToDo: Validate spmdRange, spmdDomain against op maps!
00091 #endif
00092 
00093   RCP<const SPMDVSB> l_spmdRange;
00094   if(!is_null(range_in))
00095     l_spmdRange = rcp_dynamic_cast<const SPMDVSB>(range_in,true);
00096   else
00097     l_spmdRange = ( applyAs==EPETRA_OP_APPLY_APPLY
00098       ? allocateRange(op,opTrans) : allocateDomain(op,opTrans) );
00099 
00100   RCP<const SPMDVSB> l_spmdDomain;
00101   if(!is_null(domain_in))
00102     l_spmdDomain = rcp_dynamic_cast<const SPMDVSB>(domain_in,true);
00103   else
00104     l_spmdDomain = ( applyAs==EPETRA_OP_APPLY_APPLY
00105       ? allocateDomain(op,opTrans) : allocateRange(op,opTrans) );
00106   
00107   // Set data (no exceptions should be thrown now)
00108   isFullyInitialized_ = true;
00109   op_ = op;
00110   rowMatrix_ = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(op_);
00111   opTrans_ = opTrans;
00112   applyAs_ = applyAs;
00113   adjointSupport_ = adjointSupport;
00114   range_ = l_spmdRange;
00115   domain_ = l_spmdDomain;
00116 
00117 }
00118 
00119 
00120 void EpetraLinearOp::partiallyInitialize(
00121   const RCP<const VectorSpaceBase<double> > &range_in,
00122   const RCP<const VectorSpaceBase<double> > &domain_in,
00123   const RCP<Epetra_Operator> &op,
00124   EOpTransp opTrans,
00125   EApplyEpetraOpAs applyAs,
00126   EAdjointEpetraOp adjointSupport
00127   )
00128 {
00129   
00130   using Teuchos::rcp_dynamic_cast;
00131   typedef SpmdVectorSpaceBase<double> SPMDVSB;
00132 
00133   // Validate input, allocate spaces, validate ...
00134 #ifdef TEUCHOS_DEBUG
00135   TEUCHOS_TEST_FOR_EXCEPTION( is_null(range_in), std::invalid_argument,
00136     "Thyra::EpetraLinearOp::partiallyInitialize(...): Error!" );
00137   TEUCHOS_TEST_FOR_EXCEPTION( is_null(domain_in), std::invalid_argument,
00138     "Thyra::EpetraLinearOp::partiallyInitialize(...): Error!" );
00139   TEUCHOS_TEST_FOR_EXCEPTION( is_null(op), std::invalid_argument,
00140     "Thyra::EpetraLinearOp::partiallyInitialize(...): Error!" );
00141 #endif
00142 
00143   RCP<const SPMDVSB>
00144     l_spmdRange = rcp_dynamic_cast<const SPMDVSB>(range_in,true);
00145   RCP<const SPMDVSB>
00146     l_spmdDomain = rcp_dynamic_cast<const SPMDVSB>(domain_in,true);
00147   
00148   // Set data (no exceptions should be thrown now)
00149   isFullyInitialized_ = false;
00150   op_ = op;
00151   rowMatrix_ = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(op_);
00152   opTrans_ = opTrans;
00153   applyAs_ = applyAs;
00154   adjointSupport_ = adjointSupport;
00155   range_ = l_spmdRange;
00156   domain_ = l_spmdDomain;
00157   
00158 }
00159 
00160 
00161 void EpetraLinearOp::setFullyInitialized(bool isFullyInitialized)
00162 {
00163   // ToDo: Validate that everything matches up!
00164   isFullyInitialized_ = true;
00165 }
00166 
00167 
00168 void EpetraLinearOp::uninitialize(
00169   RCP<Epetra_Operator> *op,
00170   EOpTransp *opTrans,
00171   EApplyEpetraOpAs *applyAs,
00172   EAdjointEpetraOp *adjointSupport,
00173   RCP<const VectorSpaceBase<double> > *range_out,
00174   RCP<const VectorSpaceBase<double> > *domain_out
00175   )
00176 {
00177 
00178   if(op) *op = op_;
00179   if(opTrans) *opTrans = opTrans_;
00180   if(applyAs) *applyAs = applyAs_;
00181   if(adjointSupport) *adjointSupport = adjointSupport_;
00182   if(range_out) *range_out = range_;
00183   if(domain_out) *domain_out = domain_;
00184 
00185   isFullyInitialized_ = false;
00186   op_ = Teuchos::null;
00187   rowMatrix_ = Teuchos::null;
00188   opTrans_ = NOTRANS;
00189   applyAs_ = EPETRA_OP_APPLY_APPLY;
00190   adjointSupport_ = EPETRA_OP_ADJOINT_SUPPORTED;
00191   range_ = Teuchos::null;
00192   domain_ = Teuchos::null;
00193 
00194 }
00195 
00196 
00197 RCP< const SpmdVectorSpaceBase<double> >
00198 EpetraLinearOp::spmdRange() const
00199 {
00200   return range_;
00201 }
00202 
00203 
00204 RCP< const SpmdVectorSpaceBase<double> >
00205 EpetraLinearOp::spmdDomain() const
00206 {
00207   return domain_;
00208 }
00209 
00210 
00211 RCP<Epetra_Operator>
00212 EpetraLinearOp::epetra_op() 
00213 {
00214   return op_;
00215 }
00216 
00217 
00218 RCP<const Epetra_Operator>
00219 EpetraLinearOp::epetra_op() const 
00220 {
00221   return op_;
00222 }
00223 
00224 
00225 // Overridden from EpetraLinearOpBase
00226 
00227 
00228 void EpetraLinearOp::getNonconstEpetraOpView(
00229   const Ptr<RCP<Epetra_Operator> > &epetraOp,
00230   const Ptr<EOpTransp> &epetraOpTransp,
00231   const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
00232   const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
00233   )
00234 {
00235   *epetraOp = op_;
00236   *epetraOpTransp = opTrans_;
00237   *epetraOpApplyAs = applyAs_;
00238   *epetraOpAdjointSupport = adjointSupport_;
00239 }
00240 
00241 
00242 void EpetraLinearOp::getEpetraOpView(
00243   const Ptr<RCP<const Epetra_Operator> > &epetraOp,
00244   const Ptr<EOpTransp> &epetraOpTransp,
00245   const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
00246   const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
00247   ) const
00248 {
00249   *epetraOp = op_;
00250   *epetraOpTransp = opTrans_;
00251   *epetraOpApplyAs = applyAs_;
00252   *epetraOpAdjointSupport = adjointSupport_;
00253 }
00254 
00255 
00256 // Overridden from LinearOpBase
00257 
00258 
00259 RCP<const VectorSpaceBase<double> >
00260 EpetraLinearOp::range() const
00261 {
00262   return range_;
00263 }
00264 
00265 
00266 RCP<const VectorSpaceBase<double> >
00267 EpetraLinearOp::domain() const
00268 {
00269   return domain_;
00270 }
00271 
00272 
00273 RCP<const LinearOpBase<double> >
00274 EpetraLinearOp::clone() const
00275 {
00276   assert(0); // ToDo: Implement when needed
00277   return Teuchos::null;
00278 }
00279 
00280 
00281 // Overridden from Teuchos::Describable
00282 
00283 
00284 std::string EpetraLinearOp::description() const
00285 {
00286   std::ostringstream oss;
00287   oss << Teuchos::Describable::description() << "{";
00288   if(op_.get()) {
00289     oss << "op=\'"<<typeName(*op_)<<"\'";
00290     oss << ",rangeDim="<<this->range()->dim();
00291     oss << ",domainDim="<<this->domain()->dim();
00292   }
00293   else {
00294     oss << "op=NULL";
00295   }
00296   oss << "}";
00297   return oss.str();
00298 }
00299 
00300 
00301 void EpetraLinearOp::describe(
00302   FancyOStream &out,
00303   const Teuchos::EVerbosityLevel verbLevel
00304   ) const
00305 {
00306   using Teuchos::includesVerbLevel;
00307   using Teuchos::as;
00308   using Teuchos::rcp_dynamic_cast;
00309   using Teuchos::OSTab;
00310   using Teuchos::describe;
00311   OSTab tab(out);
00312   if ( as<int>(verbLevel) == as<int>(Teuchos::VERB_LOW) || is_null(op_)) {
00313     out << this->description() << std::endl;
00314   }
00315   else if (includesVerbLevel(verbLevel,Teuchos::VERB_MEDIUM)) {
00316     out
00317       << Teuchos::Describable::description()
00318       << "{"
00319       << "rangeDim=" << this->range()->dim()
00320       << ",domainDim=" << this->domain()->dim()
00321       << "}\n";
00322     OSTab tab2(out);
00323     if (op_.get()) {
00324       if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00325         out << "opTrans="<<toString(opTrans_)<<"\n";
00326         out << "applyAs="<<toString(applyAs_)<<"\n";
00327         out << "adjointSupport="<<toString(adjointSupport_)<<"\n";
00328         out << "op="<<typeName(*op_)<<"\n";
00329       }
00330       if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME) ) {
00331         OSTab tab3(out);
00332         RCP<const Epetra_CrsMatrix>
00333           csr_op = rcp_dynamic_cast<const Epetra_CrsMatrix>(op_);
00334         if (!is_null(csr_op)) {
00335           csr_op->Print(out);
00336         }
00337       }
00338     }
00339     else {
00340       out << "op=NULL"<<"\n";
00341     }
00342   }
00343 }
00344 
00345 
00346 // protected
00347 
00348 
00349 // Protected member functions overridden from LinearOpBase
00350 
00351 
00352 bool EpetraLinearOp::opSupportedImpl(EOpTransp M_trans) const
00353 {
00354   if (!isFullyInitialized_)
00355     return false;
00356   return ( M_trans == NOTRANS
00357     ? true : adjointSupport_==EPETRA_OP_ADJOINT_SUPPORTED );
00358 }
00359 
00360 
00361 void EpetraLinearOp::applyImpl(
00362   const EOpTransp M_trans,
00363   const MultiVectorBase<double> &X_in,
00364   const Ptr<MultiVectorBase<double> > &Y_inout,
00365   const double alpha,
00366   const double beta
00367   ) const
00368 {
00369 
00370   THYRA_FUNC_TIME_MONITOR("Thyra::EpetraLinearOp::euclideanApply");
00371 
00372   const EOpTransp real_M_trans = real_trans(M_trans);
00373 
00374 #ifdef TEUCHOS_DEBUG
00375   TEUCHOS_TEST_FOR_EXCEPT(!isFullyInitialized_);
00376   THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(
00377     "EpetraLinearOp::euclideanApply(...)", *this, M_trans, X_in, Y_inout
00378     );
00379   TEUCHOS_TEST_FOR_EXCEPTION(
00380     real_M_trans==TRANS && adjointSupport_==EPETRA_OP_ADJOINT_UNSUPPORTED,
00381     Exceptions::OpNotSupported,
00382     "EpetraLinearOp::apply(...): *this was informed that adjoints "
00383     "are not supported when initialized." 
00384     );
00385 #endif
00386 
00387   const RCP<const VectorSpaceBase<double> > XY_domain = X_in.domain();
00388   const int numCols = XY_domain->dim();
00389  
00390   //
00391   // Get Epetra_MultiVector objects for the arguments
00392   //
00393   // 2007/08/18: rabartl: Note: After profiling, I found that calling the more
00394   // general functions get_Epetra_MultiVector(...) was too slow. These
00395   // functions must ensure that memory is being remembered efficiently and the
00396   // use of extra data with the RCP and other things is slow.
00397   //
00398   RCP<const Epetra_MultiVector> X;
00399   RCP<Epetra_MultiVector> Y;
00400   {
00401     THYRA_FUNC_TIME_MONITOR_DIFF(
00402       "Thyra::EpetraLinearOp::euclideanApply: Convert MultiVectors", MultiVectors);
00403     // X
00404     X = get_Epetra_MultiVector(
00405       real_M_trans==NOTRANS ? getDomainMap() : getRangeMap(), X_in );
00406     // Y
00407     if( beta == 0 ) {
00408       Y = get_Epetra_MultiVector(
00409         real_M_trans==NOTRANS ? getRangeMap() : getDomainMap(), *Y_inout );
00410     }
00411   }
00412 
00413   //
00414   // Set the operator mode
00415   //
00416 
00417   /* We need to save the transpose state here, and then reset it after 
00418    * application. The reason for this is that if we later apply the 
00419    * operator outside Thyra (in Aztec, for instance), it will remember
00420    * the transpose flag set here. */
00421   bool oldState = op_->UseTranspose();
00422   op_->SetUseTranspose(
00423     real_trans(trans_trans(opTrans_,M_trans)) == NOTRANS ? false : true );
00424 
00425   //
00426   // Perform the apply operation
00427   //
00428   {
00429     THYRA_FUNC_TIME_MONITOR_DIFF(
00430       "Thyra::EpetraLinearOp::euclideanApply: Apply", Apply);
00431     if( beta == 0.0 ) {
00432       // Y = M * X
00433       if( applyAs_ == EPETRA_OP_APPLY_APPLY ) {
00434         THYRA_FUNC_TIME_MONITOR_DIFF(
00435           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta==0): Apply",
00436           ApplyApply);
00437         op_->Apply( *X, *Y );
00438       }
00439       else if( applyAs_ == EPETRA_OP_APPLY_APPLY_INVERSE ) {
00440         THYRA_FUNC_TIME_MONITOR_DIFF(
00441           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta==0): ApplyInverse",
00442           ApplyApplyInverse);
00443         op_->ApplyInverse( *X, *Y );
00444       }
00445       else {
00446 #ifdef TEUCHOS_DEBUG
00447         TEUCHOS_TEST_FOR_EXCEPT(true);
00448 #endif
00449       }
00450       // Y = alpha * Y
00451       if( alpha != 1.0 ) {
00452         THYRA_FUNC_TIME_MONITOR_DIFF(
00453           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta==0): Scale Y",
00454           Scale);
00455         Y->Scale(alpha);
00456       }
00457     }
00458     else {  // beta != 0.0
00459       // Y_inout = beta * Y_inout
00460       if(beta != 0.0) {
00461         THYRA_FUNC_TIME_MONITOR_DIFF(
00462           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Scale Y",
00463           Scale);
00464         scale( beta, Y_inout );
00465       }
00466       else {
00467         THYRA_FUNC_TIME_MONITOR_DIFF(
00468           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Y=0",
00469           Apply2);
00470         assign( Y_inout, 0.0 );
00471       }
00472       // T = M * X
00473       Epetra_MultiVector T(op_->OperatorRangeMap(), numCols, false);
00474       // NOTE: Above, op_->OperatorRange() will be right for either
00475       // non-transpose or transpose because we have already set the
00476       // UseTranspose flag correctly.
00477       if( applyAs_ == EPETRA_OP_APPLY_APPLY ) {
00478         THYRA_FUNC_TIME_MONITOR_DIFF(
00479           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Apply",
00480           Apply2);
00481         op_->Apply( *X, T );
00482       }
00483       else if( applyAs_ == EPETRA_OP_APPLY_APPLY_INVERSE ) {
00484         THYRA_FUNC_TIME_MONITOR_DIFF(
00485           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): ApplyInverse",
00486           ApplyInverse);
00487         op_->ApplyInverse( *X, T );
00488       }
00489       else {
00490 #ifdef TEUCHOS_DEBUG
00491         TEUCHOS_TEST_FOR_EXCEPT(true);
00492 #endif
00493       }
00494       // Y_inout += alpha * T
00495       {
00496         THYRA_FUNC_TIME_MONITOR_DIFF(
00497           "Thyra::EpetraLinearOp::euclideanApply: Apply(beta!=0): Update Y",
00498           Update);
00499         update(
00500           alpha,
00501           *create_MultiVector(
00502             Teuchos::rcp(&Teuchos::getConst(T),false),
00503             Y_inout->range(),
00504             XY_domain
00505             ),
00506           Y_inout
00507           );
00508       }
00509     }
00510   }
00511 
00512   // Reset the transpose state
00513   op_->SetUseTranspose(oldState);
00514 
00515   // 2009/04/14: ToDo: This will not reset the transpose flag correctly if an
00516   // exception is thrown!
00517 
00518 }
00519 
00520 
00521 // Protected member functions overridden from ScaledLinearOpBase
00522 
00523 
00524 bool EpetraLinearOp::supportsScaleLeftImpl() const
00525 {
00526   return nonnull(rowMatrix_);
00527 }
00528 
00529 
00530 bool EpetraLinearOp::supportsScaleRightImpl() const
00531 {
00532   return nonnull(rowMatrix_);
00533 }
00534 
00535 
00536 void EpetraLinearOp::scaleLeftImpl(const VectorBase<double> &row_scaling_in)
00537 {
00538   using Teuchos::rcpFromRef;
00539   const RCP<const Epetra_Vector> row_scaling =
00540     get_Epetra_Vector(getRangeMap(), rcpFromRef(row_scaling_in));
00541   rowMatrix_->LeftScale(*row_scaling);
00542 }
00543 
00544 
00545 void EpetraLinearOp::scaleRightImpl(const VectorBase<double> &col_scaling_in)
00546 {
00547   using Teuchos::rcpFromRef;
00548   const RCP<const Epetra_Vector> col_scaling =
00549     get_Epetra_Vector(getDomainMap(), rcpFromRef(col_scaling_in));
00550   rowMatrix_->RightScale(*col_scaling);
00551 }
00552 
00553 
00554 // Protected member functions overridden from RowStatLinearOpBase
00555 
00556 
00557 bool EpetraLinearOp::rowStatIsSupportedImpl(
00558   const RowStatLinearOpBaseUtils::ERowStat rowStat) const
00559 {
00560   if (is_null(rowMatrix_)) {
00561     return false;
00562   }
00563   switch (rowStat) {
00564     case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
00565     case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
00566       return true;
00567     default:
00568       TEUCHOS_TEST_FOR_EXCEPT(true);
00569   }
00570   return false; // Will never be called!
00571 }
00572 
00573 
00574 void EpetraLinearOp::getRowStatImpl(
00575   const RowStatLinearOpBaseUtils::ERowStat rowStat,
00576   const Ptr<VectorBase<double> > &rowStatVec_in
00577   ) const
00578 {
00579   using Teuchos::rcpFromPtr;
00580   const RCP<Epetra_Vector> rowStatVec =
00581     get_Epetra_Vector(getRangeMap(), rcpFromPtr(rowStatVec_in));
00582   switch (rowStat) {
00583     case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
00584       rowMatrix_->InvRowSums(*rowStatVec);
00585       break;
00586     case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
00587       // compute absolute row sum
00588       computeAbsRowSum(*rowStatVec);
00589       break;
00590     default:
00591       TEUCHOS_TEST_FOR_EXCEPT(true);
00592   }
00593 }
00594 
00595 
00596 // Allocators for domain and range spaces
00597 
00598 
00599 RCP< const SpmdVectorSpaceBase<double> > 
00600 EpetraLinearOp::allocateDomain(
00601   const RCP<Epetra_Operator> &op,
00602   EOpTransp op_trans
00603   ) const
00604 {
00605   return Teuchos::rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(
00606     create_VectorSpace(Teuchos::rcp(&op->OperatorDomainMap(),false))
00607     );
00608   // ToDo: What about the transpose argument???, test this!!!
00609 }
00610 
00611 
00612 RCP<const SpmdVectorSpaceBase<double> > 
00613 EpetraLinearOp::allocateRange(
00614   const RCP<Epetra_Operator> &op,
00615   EOpTransp op_trans
00616   ) const
00617 {
00618   return Teuchos::rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(
00619     create_VectorSpace(Teuchos::rcp(&op->OperatorRangeMap(),false))
00620     );
00621   // ToDo: What about the transpose argument???, test this!!!
00622 }
00623 
00624 // private
00625 
00626 
00627 const Epetra_Map& EpetraLinearOp::getRangeMap() const
00628 {
00629   return ( applyAs_ == EPETRA_OP_APPLY_APPLY
00630     ? op_->OperatorRangeMap() : op_->OperatorDomainMap() );
00631   // ToDo: What about the transpose argument???, test this!!!
00632 }
00633 
00634 
00635 const Epetra_Map& EpetraLinearOp::getDomainMap() const
00636 {
00637   return ( applyAs_ == EPETRA_OP_APPLY_APPLY
00638     ? op_->OperatorDomainMap() : op_->OperatorRangeMap() );
00639   // ToDo: What about the transpose argument???, test this!!!
00640 }
00641 
00642 void EpetraLinearOp::computeAbsRowSum(Epetra_Vector & x) const
00643 {
00644   TEUCHOS_ASSERT(!is_null(rowMatrix_));
00645 
00646   RCP<Epetra_CrsMatrix> crsMatrix 
00647     = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(rowMatrix_);
00648 
00649   TEUCHOS_TEST_FOR_EXCEPTION(is_null(crsMatrix),
00650     Exceptions::OpNotSupported,
00651     "EpetraLinearOp::computeAbsRowSum(...): wrapped matrix must be of type "
00652     "Epetra_CrsMatrix for this method. Other operator types are not supported."
00653     );
00654 
00655   //
00656   // Put inverse of the sum of absolute values of the ith row of A in x[i].
00657   // (this is a modified copy of Epetra_CrsMatrix::InvRowSums)
00658   //
00659 
00660   if (crsMatrix->Filled()) {
00661     TEUCHOS_TEST_FOR_EXCEPTION(is_null(crsMatrix),
00662       std::invalid_argument,
00663       "EpetraLinearOp::computeAbsRowSum(...): Epetra_CrsMatrix must be filled"
00664     );
00665   } 
00666   int i, j;
00667   x.PutScalar(0.0); // Make sure we sum into a vector of zeros.
00668   double * xp = (double*)x.Values();
00669   if (crsMatrix->Graph().RangeMap().SameAs(x.Map()) && crsMatrix->Exporter() != 0) {
00670     Epetra_Vector x_tmp(crsMatrix->RowMap());
00671     x_tmp.PutScalar(0.0);
00672     double * x_tmp_p = (double*)x_tmp.Values();
00673     for (i=0; i < crsMatrix->NumMyRows(); i++) {
00674       int      NumEntries = 0;
00675       double * RowValues  = 0;
00676       crsMatrix->ExtractMyRowView(i,NumEntries,RowValues);
00677       for (j=0; j < NumEntries; j++)  x_tmp_p[i] += std::abs(RowValues[j]);
00678     }
00679     TEUCHOS_TEST_FOR_EXCEPT(0!=x.Export(x_tmp, *crsMatrix->Exporter(), Add)); //Export partial row sums to x.
00680   }
00681   else if (crsMatrix->Graph().RowMap().SameAs(x.Map())) {
00682     for (i=0; i < crsMatrix->NumMyRows(); i++) {
00683       int      NumEntries = 0;
00684       double * RowValues  = 0;
00685       crsMatrix->ExtractMyRowView(i,NumEntries,RowValues);
00686       double scale = 0.0;
00687       for (j=0; j < NumEntries; j++) scale += std::abs(RowValues[j]);
00688       xp[i] = scale;
00689     }
00690   }
00691   else { // x.Map different than both crsMatrix->Graph().RowMap() and crsMatrix->Graph().RangeMap()
00692     TEUCHOS_TEST_FOR_EXCEPT(true); // The map of x must be the RowMap or RangeMap of A.
00693   }
00694 }
00695 
00696 } // end namespace Thyra
00697 
00698 
00699 // Nonmembers
00700 
00701 
00702 Teuchos::RCP<Thyra::EpetraLinearOp>
00703 Thyra::nonconstEpetraLinearOp()
00704 {
00705   return Teuchos::rcp(new EpetraLinearOp());
00706 }
00707 
00708 
00709 Teuchos::RCP<Thyra::EpetraLinearOp>
00710 Thyra::partialNonconstEpetraLinearOp(
00711   const RCP<const VectorSpaceBase<double> > &range,
00712   const RCP<const VectorSpaceBase<double> > &domain,
00713   const RCP<Epetra_Operator> &op,
00714   EOpTransp opTrans,
00715   EApplyEpetraOpAs applyAs,
00716   EAdjointEpetraOp adjointSupport
00717   )
00718 {
00719   RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp());
00720   thyraEpetraOp->partiallyInitialize(
00721     range, domain,op,opTrans, applyAs, adjointSupport
00722     );
00723   return thyraEpetraOp;
00724 }
00725 
00726 
00727 Teuchos::RCP<Thyra::EpetraLinearOp>
00728 Thyra::nonconstEpetraLinearOp(
00729   const RCP<Epetra_Operator> &op,
00730   EOpTransp opTrans,
00731   EApplyEpetraOpAs applyAs,
00732   EAdjointEpetraOp adjointSupport,
00733   const RCP< const VectorSpaceBase<double> > &range,
00734   const RCP< const VectorSpaceBase<double> > &domain
00735   )
00736 {
00737   RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp());
00738   thyraEpetraOp->initialize(
00739     op,opTrans, applyAs, adjointSupport, range, domain
00740     );
00741   return thyraEpetraOp;
00742 }
00743 
00744 
00745 Teuchos::RCP<const Thyra::EpetraLinearOp>
00746 Thyra::epetraLinearOp(
00747   const RCP<const Epetra_Operator> &op,
00748   EOpTransp opTrans,
00749   EApplyEpetraOpAs applyAs,
00750   EAdjointEpetraOp adjointSupport,
00751   const RCP<const VectorSpaceBase<double> > &range,
00752   const RCP<const VectorSpaceBase<double> > &domain
00753   )
00754 {
00755   RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp());
00756   thyraEpetraOp->initialize(
00757     Teuchos::rcp_const_cast<Epetra_Operator>(op), // Safe cast due to return type!
00758     opTrans, applyAs, adjointSupport, range, domain
00759     );
00760   return thyraEpetraOp;
00761 }
00762 
00763 
00764 Teuchos::RCP<Thyra::EpetraLinearOp>
00765 Thyra::nonconstEpetraLinearOp(
00766   const RCP<Epetra_Operator> &op,
00767   const std::string &label,
00768   EOpTransp opTrans,
00769   EApplyEpetraOpAs applyAs,
00770   EAdjointEpetraOp adjointSupport,
00771   const RCP<const VectorSpaceBase<double> > &range,
00772   const RCP<const VectorSpaceBase<double> > &domain
00773   )
00774 {
00775   RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp());
00776   thyraEpetraOp->initialize(
00777     op,opTrans, applyAs, adjointSupport, range, domain
00778     );
00779   thyraEpetraOp->setObjectLabel(label);
00780   return thyraEpetraOp;
00781 }
00782 
00783 
00784 Teuchos::RCP<const Thyra::EpetraLinearOp>
00785 Thyra::epetraLinearOp(
00786   const RCP<const Epetra_Operator> &op,
00787   const std::string &label,
00788   EOpTransp opTrans,
00789   EApplyEpetraOpAs applyAs,
00790   EAdjointEpetraOp adjointSupport,
00791   const RCP< const SpmdVectorSpaceBase<double> > &range,
00792   const RCP< const SpmdVectorSpaceBase<double> > &domain
00793   )
00794 {
00795   RCP<EpetraLinearOp> thyraEpetraOp = Teuchos::rcp(new EpetraLinearOp());
00796   thyraEpetraOp->initialize(
00797     Teuchos::rcp_const_cast<Epetra_Operator>(op), // Safe cast due to return type!
00798     opTrans, applyAs, adjointSupport, range, domain
00799     );
00800   thyraEpetraOp->setObjectLabel(label);
00801   return thyraEpetraOp;
00802 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines