Thyra Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Thyra_TpetraLinearOp_def.hpp
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 #ifndef THYRA_TPETRA_LINEAR_OP_HPP
00043 #define THYRA_TPETRA_LINEAR_OP_HPP
00044 
00045 #include "Thyra_TpetraLinearOp_decl.hpp"
00046 #include "Thyra_TpetraVectorSpace.hpp"
00047 #include "Teuchos_ScalarTraits.hpp"
00048 #include "Teuchos_TypeNameTraits.hpp"
00049 
00050 #include "Tpetra_CrsMatrix.hpp"
00051 
00052 #ifdef HAVE_THYRA_TPETRA_EPETRA
00053 #  include "Thyra_EpetraThyraWrappers.hpp"
00054 #endif
00055 
00056 namespace Thyra {
00057 
00058 
00059 #ifdef HAVE_THYRA_TPETRA_EPETRA
00060 
00061 // Utilites
00062 
00063 
00065   template<class Scalar, class LocalOrdinal, class GlobalOrdinal>
00066 class GetTpetraEpetraRowMatrixWrapper {
00067 public:
00068   template<class TpetraMatrixType>
00069   static
00070   RCP<Tpetra::EpetraRowMatrix<TpetraMatrixType> >
00071   get(const RCP<TpetraMatrixType> &tpetraMatrix)
00072     {
00073       return Teuchos::null;
00074     }
00075 };
00076 
00077 
00078 // NOTE: We could support other ordinal types, but we have to
00079 // specialize the EpetraRowMatrix
00080 template<>
00081 class GetTpetraEpetraRowMatrixWrapper<double, int, int> {
00082 public:
00083   template<class TpetraMatrixType>
00084   static
00085   RCP<Tpetra::EpetraRowMatrix<TpetraMatrixType> >
00086   get(const RCP<TpetraMatrixType> &tpetraMatrix)
00087     {
00088       return Teuchos::rcp(
00089         new Tpetra::EpetraRowMatrix<TpetraMatrixType>(tpetraMatrix,
00090           *get_Epetra_Comm(
00091             *convertTpetraToThyraComm(tpetraMatrix->getRowMap()->getComm())
00092             )
00093           )
00094         );
00095     }
00096 };
00097 
00098 
00099 #endif // HAVE_THYRA_TPETRA_EPETRA
00100 
00101 
00102 template <class Scalar>
00103 inline
00104 Teuchos::ETransp
00105 convertConjNoTransToTeuchosTransMode()
00106 {
00107   TEUCHOS_TEST_FOR_EXCEPTION(
00108       Teuchos::ScalarTraits<Scalar>::isComplex,
00109       Exceptions::OpNotSupported,
00110       "For complex scalars such as " + Teuchos::TypeNameTraits<Scalar>::name() +
00111       ", Tpetra does not support conjugation without transposition."
00112       );
00113   return Teuchos::NO_TRANS; // For non-complex scalars, CONJ is equivalent to NOTRANS.
00114 }
00115 
00116 
00117 template <class Scalar>
00118 inline
00119 Teuchos::ETransp
00120 convertToTeuchosTransMode(const Thyra::EOpTransp transp)
00121 {
00122   switch (transp) {
00123     case NOTRANS:   return Teuchos::NO_TRANS;
00124     case CONJ:      return convertConjNoTransToTeuchosTransMode<Scalar>();
00125     case TRANS:     return Teuchos::TRANS;
00126     case CONJTRANS: return Teuchos::CONJ_TRANS;
00127   }
00128 
00129   // Should not escape the switch
00130   TEUCHOS_TEST_FOR_EXCEPT(true);
00131 }
00132 
00133 
00134 // Constructors/initializers
00135 
00136 
00137 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00138 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TpetraLinearOp()
00139 {}
00140 
00141 
00142 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00143 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::initialize(
00144   const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
00145   const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
00146   const RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
00147   )
00148 {
00149   initializeImpl(rangeSpace, domainSpace, tpetraOperator);
00150 }
00151 
00152 
00153 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00154 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::constInitialize(
00155   const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
00156   const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
00157   const RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
00158   )
00159 {
00160   initializeImpl(rangeSpace, domainSpace, tpetraOperator);
00161 }
00162 
00163 
00164 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00165 RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
00166 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getTpetraOperator()
00167 {
00168   return tpetraOperator_.getNonconstObj();
00169 }
00170 
00171 
00172 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00173 RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
00174 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraOperator() const
00175 {
00176   return tpetraOperator_;
00177 }
00178 
00179 
00180 // Public Overridden functions from LinearOpBase
00181 
00182 
00183 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00184 RCP<const Thyra::VectorSpaceBase<Scalar> >
00185 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::range() const
00186 {
00187   return rangeSpace_;
00188 }
00189 
00190 
00191 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00192 RCP<const Thyra::VectorSpaceBase<Scalar> >
00193 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::domain() const
00194 {
00195   return domainSpace_;
00196 }
00197 
00198 
00199 // Overridden from EpetraLinearOpBase
00200 
00201 
00202 #ifdef HAVE_THYRA_TPETRA_EPETRA
00203 
00204 
00205 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00206 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getNonconstEpetraOpView(
00207   const Ptr<RCP<Epetra_Operator> > &epetraOp,
00208   const Ptr<EOpTransp> &epetraOpTransp,
00209   const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
00210   const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
00211   )
00212 {
00213   TEUCHOS_TEST_FOR_EXCEPT(true);
00214 }
00215 
00216 
00217 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00218 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getEpetraOpView(
00219   const Ptr<RCP<const Epetra_Operator> > &epetraOp,
00220   const Ptr<EOpTransp> &epetraOpTransp,
00221   const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
00222   const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
00223   ) const
00224 {
00225   using Teuchos::rcp_dynamic_cast;
00226   typedef Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpetraRowMatrix_t;
00227   if (nonnull(tpetraOperator_)) {
00228     if (is_null(epetraOp_)) {
00229       epetraOp_ = GetTpetraEpetraRowMatrixWrapper<Scalar,LocalOrdinal,GlobalOrdinal>::get(
00230         rcp_dynamic_cast<const TpetraRowMatrix_t>(tpetraOperator_.getConstObj(), true));
00231     }
00232     *epetraOp = epetraOp_;
00233     *epetraOpTransp = NOTRANS;
00234     *epetraOpApplyAs = EPETRA_OP_APPLY_APPLY;
00235     *epetraOpAdjointSupport = ( tpetraOperator_->hasTransposeApply()
00236       ? EPETRA_OP_ADJOINT_SUPPORTED : EPETRA_OP_ADJOINT_UNSUPPORTED );
00237   }
00238   else {
00239     *epetraOp = Teuchos::null;
00240   }
00241 }
00242 
00243 
00244 #endif // HAVE_THYRA_TPETRA_EPETRA
00245 
00246 
00247 // Protected Overridden functions from LinearOpBase
00248 
00249 
00250 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00251 bool TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::opSupportedImpl(
00252   Thyra::EOpTransp M_trans) const
00253 {
00254   if (is_null(tpetraOperator_))
00255     return false;
00256 
00257   if (M_trans == NOTRANS)
00258     return true;
00259 
00260   if (M_trans == CONJ) {
00261     // For non-complex scalars, CONJ is always supported since it is equivalent to NO_TRANS.
00262     // For complex scalars, Tpetra does not support conjugation without transposition.
00263     return !Teuchos::ScalarTraits<Scalar>::isComplex;
00264   }
00265 
00266   return tpetraOperator_->hasTransposeApply();
00267 }
00268 
00269 
00270 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00271 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::applyImpl(
00272   const Thyra::EOpTransp M_trans,
00273   const Thyra::MultiVectorBase<Scalar> &X_in,
00274   const Teuchos::Ptr<Thyra::MultiVectorBase<Scalar> > &Y_inout,
00275   const Scalar alpha,
00276   const Scalar beta
00277   ) const
00278 {
00279   using Teuchos::rcpFromRef;
00280   using Teuchos::rcpFromPtr;
00281   typedef TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>
00282     ConverterT;
00283   typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
00284     TpetraMultiVector_t;
00285 
00286   // Get Tpetra::MultiVector objects for X and Y
00287 
00288   const RCP<const TpetraMultiVector_t> tX =
00289     ConverterT::getConstTpetraMultiVector(rcpFromRef(X_in));
00290 
00291   const RCP<TpetraMultiVector_t> tY =
00292     ConverterT::getTpetraMultiVector(rcpFromPtr(Y_inout));
00293 
00294   const Teuchos::ETransp tTransp = convertToTeuchosTransMode<Scalar>(M_trans);
00295 
00296   // Apply the operator
00297 
00298   tpetraOperator_->apply(*tX, *tY, tTransp, alpha, beta);
00299 
00300 }
00301 
00302 // Protected member functions overridden from ScaledLinearOpBase
00303 
00304 
00305 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00306 bool TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::supportsScaleLeftImpl() const
00307 {
00308   return true;
00309 }
00310 
00311 
00312 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00313 bool TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::supportsScaleRightImpl() const
00314 {
00315   return true;
00316 }
00317 
00318 
00319 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00320 void 
00321 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
00322 scaleLeftImpl(const VectorBase<Scalar> &row_scaling_in)
00323 {
00324   using Teuchos::rcpFromRef;
00325 
00326   const RCP<const Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > row_scaling = 
00327     TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(rcpFromRef(row_scaling_in));
00328 
00329   const RCP<typename Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rowMatrix = 
00330     Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
00331 
00332   rowMatrix->leftScale(*row_scaling);
00333 }
00334 
00335 
00336 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00337 void 
00338 TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
00339 scaleRightImpl(const VectorBase<Scalar> &col_scaling_in)
00340 {
00341   using Teuchos::rcpFromRef;
00342 
00343   const RCP<const Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > col_scaling = 
00344     TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(rcpFromRef(col_scaling_in));
00345 
00346   const RCP<typename Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rowMatrix = 
00347     Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
00348 
00349   rowMatrix->rightScale(*col_scaling);
00350 }
00351 
00352 // Protected member functions overridden from RowStatLinearOpBase
00353 
00354 
00355 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00356 bool TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
00357 rowStatIsSupportedImpl(
00358   const RowStatLinearOpBaseUtils::ERowStat rowStat) const
00359 {
00360   if (is_null(tpetraOperator_))
00361     return false;
00362 
00363   switch (rowStat) {
00364     case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
00365     case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
00366       return true;
00367     default:
00368       return false;
00369   }
00370 
00371   return false; // Will never be called!
00372 }
00373 
00374 
00375 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00376 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getRowStatImpl(
00377   const RowStatLinearOpBaseUtils::ERowStat rowStat,
00378   const Ptr<VectorBase<Scalar> > &rowStatVec_in
00379   ) const
00380 {
00381   typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
00382     TpetraVector_t;
00383   
00384   if ( (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) ||
00385        (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM) ) {
00386     
00387     TEUCHOS_ASSERT(nonnull(tpetraOperator_));
00388     TEUCHOS_ASSERT(nonnull(rowStatVec_in));
00389 
00390     // Currently we only support the case of row sums for a concrete
00391     // Tpetra::CrsMatrix where (1) the entire row is stored on a
00392     // single process and (2) that the domain map, the range map and
00393     // the row map are the SAME.  These checks enforce that.  Later on
00394     // we hope to add complete support for any mapping to the concrete
00395     // tpetra matrix types.
00396     
00397     const RCP<TpetraVector_t> tRowSumVec =
00398       TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getTpetraVector(rcpFromPtr(rowStatVec_in));
00399     
00400     const RCP<const typename Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tCrsMatrix = 
00401       Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getConstObj(),true);
00402     
00403     TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getDomainMap()));
00404     TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getRangeMap()));
00405     TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tRowSumVec->getMap()));
00406 
00407     size_t numMyRows = tCrsMatrix->getNodeNumRows();
00408     
00409     Teuchos::ArrayView<const LocalOrdinal> indices;
00410     Teuchos::ArrayView<const Scalar> values;
00411 
00412     for (size_t row=0; row < numMyRows; ++row) {
00413       Scalar sum = Scalar(0.0);
00414       tCrsMatrix->getLocalRowView(row,indices,values);
00415 
00416       for (int col = 0; col < values.size(); ++col)
00417   sum += std::abs(values[col]);
00418       
00419       if (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) {
00420   if (sum < Teuchos::ScalarTraits<Scalar>::sfmin()) {
00421     TEUCHOS_TEST_FOR_EXCEPTION(sum == Teuchos::ScalarTraits<Scalar>::zero(), std::runtime_error,
00422              "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Inverse row sum "
00423              << "requested for a matrix where one of the rows has a zero row sum!");
00424   
00425     sum = Scalar(1.0) / Teuchos::ScalarTraits<Scalar>::sfmin();
00426   }
00427   else 
00428     sum = Scalar(1.0) / sum;
00429       }
00430       
00431       tRowSumVec->replaceLocalValue(row,sum);
00432     }
00433 
00434   }
00435   else {
00436     TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
00437              "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Colum sum support not implemented!");
00438   }
00439 }
00440 
00441 
00442 // private
00443 
00444 
00445 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
00446 template<class TpetraOperator_t>
00447 void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::initializeImpl(
00448   const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
00449   const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
00450   const RCP<TpetraOperator_t> &tpetraOperator
00451   )
00452 {
00453 #ifdef THYRA_DEBUG
00454   TEUCHOS_ASSERT(nonnull(rangeSpace));
00455   TEUCHOS_ASSERT(nonnull(domainSpace));
00456   TEUCHOS_ASSERT(nonnull(tpetraOperator));
00457   // ToDo: Assert that spaces are comparible with tpetraOperator
00458 #endif  
00459   rangeSpace_ = rangeSpace;
00460   domainSpace_ = domainSpace;
00461   tpetraOperator_ = tpetraOperator;
00462 }
00463 
00464 
00465 } // namespace Thyra
00466 
00467 
00468 #endif  // THYRA_TPETRA_LINEAR_OP_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines