|
Thyra Package Browser (Single Doxygen Collection)
Version of the Day
|
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
1.7.6.1