Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_TpetraLinearOp_def.hpp
1// @HEADER
2// ***********************************************************************
3//
4// Thyra: Interfaces and Support for Abstract Numerical Algorithms
5// Copyright (2004) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov)
38//
39// ***********************************************************************
40// @HEADER
41
42#ifndef THYRA_TPETRA_LINEAR_OP_HPP
43#define THYRA_TPETRA_LINEAR_OP_HPP
44
45#include "Thyra_TpetraLinearOp_decl.hpp"
46#include "Thyra_TpetraVectorSpace.hpp"
47#include "Teuchos_ScalarTraits.hpp"
48#include "Teuchos_TypeNameTraits.hpp"
49
50#include "Tpetra_CrsMatrix.hpp"
51
52#ifdef HAVE_THYRA_TPETRA_EPETRA
54#endif
55
56namespace Thyra {
57
58
59#ifdef HAVE_THYRA_TPETRA_EPETRA
60
61// Utilites
62
63
65 template<class Scalar, class LocalOrdinal, class GlobalOrdinal>
66class GetTpetraEpetraRowMatrixWrapper {
67public:
68 template<class TpetraMatrixType>
69 static
70 RCP<Tpetra::EpetraRowMatrix<TpetraMatrixType> >
71 get(const RCP<TpetraMatrixType> &tpetraMatrix)
72 {
73 return Teuchos::null;
74 }
75};
76
77
78// NOTE: We could support other ordinal types, but we have to
79// specialize the EpetraRowMatrix
80template<>
81class GetTpetraEpetraRowMatrixWrapper<double, int, int> {
82public:
83 template<class TpetraMatrixType>
84 static
85 RCP<Tpetra::EpetraRowMatrix<TpetraMatrixType> >
86 get(const RCP<TpetraMatrixType> &tpetraMatrix)
87 {
88 return Teuchos::rcp(
89 new Tpetra::EpetraRowMatrix<TpetraMatrixType>(tpetraMatrix,
91 *convertTpetraToThyraComm(tpetraMatrix->getRowMap()->getComm())
92 )
93 )
94 );
95 }
96};
97
98
99#endif // HAVE_THYRA_TPETRA_EPETRA
100
101
102template <class Scalar>
103inline
105convertConjNoTransToTeuchosTransMode()
106{
109 Exceptions::OpNotSupported,
110 "For complex scalars such as " + Teuchos::TypeNameTraits<Scalar>::name() +
111 ", Tpetra does not support conjugation without transposition."
112 );
113 return Teuchos::NO_TRANS; // For non-complex scalars, CONJ is equivalent to NOTRANS.
114}
115
116
117template <class Scalar>
118inline
120convertToTeuchosTransMode(const Thyra::EOpTransp transp)
121{
122 switch (transp) {
123 case NOTRANS: return Teuchos::NO_TRANS;
124 case CONJ: return convertConjNoTransToTeuchosTransMode<Scalar>();
125 case TRANS: return Teuchos::TRANS;
126 case CONJTRANS: return Teuchos::CONJ_TRANS;
127 }
128
129 // Should not escape the switch
131}
132
133
134// Constructors/initializers
135
136
137template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
139{}
140
141
142template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
144 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
145 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
146 const RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
147 )
148{
149 initializeImpl(rangeSpace, domainSpace, tpetraOperator);
150}
151
152
153template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
155 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
156 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
157 const RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
158 )
159{
160 initializeImpl(rangeSpace, domainSpace, tpetraOperator);
161}
162
163
164template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
167{
168 return tpetraOperator_.getNonconstObj();
169}
170
171
172template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
175{
176 return tpetraOperator_;
177}
178
179
180// Public Overridden functions from LinearOpBase
181
182
183template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
186{
187 return rangeSpace_;
188}
189
190
191template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
194{
195 return domainSpace_;
196}
197
198
199// Overridden from EpetraLinearOpBase
200
201
202#ifdef HAVE_THYRA_TPETRA_EPETRA
203
204
205template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
207 const Ptr<RCP<Epetra_Operator> > &epetraOp,
208 const Ptr<EOpTransp> &epetraOpTransp,
209 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
210 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
211 )
212{
214}
215
216
217template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
218void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getEpetraOpView(
219 const Ptr<RCP<const Epetra_Operator> > &epetraOp,
220 const Ptr<EOpTransp> &epetraOpTransp,
221 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
222 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
223 ) const
224{
225 using Teuchos::rcp_dynamic_cast;
226 typedef Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpetraRowMatrix_t;
227 if (nonnull(tpetraOperator_)) {
228 if (is_null(epetraOp_)) {
229 epetraOp_ = GetTpetraEpetraRowMatrixWrapper<Scalar,LocalOrdinal,GlobalOrdinal>::get(
230 rcp_dynamic_cast<const TpetraRowMatrix_t>(tpetraOperator_.getConstObj(), true));
231 }
232 *epetraOp = epetraOp_;
233 *epetraOpTransp = NOTRANS;
234 *epetraOpApplyAs = EPETRA_OP_APPLY_APPLY;
235 *epetraOpAdjointSupport = ( tpetraOperator_->hasTransposeApply()
237 }
238 else {
239 *epetraOp = Teuchos::null;
240 }
241}
242
243
244#endif // HAVE_THYRA_TPETRA_EPETRA
245
246
247// Protected Overridden functions from LinearOpBase
248
249
250template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
252 Thyra::EOpTransp M_trans) const
253{
254 if (is_null(tpetraOperator_))
255 return false;
256
257 if (M_trans == NOTRANS)
258 return true;
259
260 if (M_trans == CONJ) {
261 // For non-complex scalars, CONJ is always supported since it is equivalent to NO_TRANS.
262 // For complex scalars, Tpetra does not support conjugation without transposition.
264 }
265
266 return tpetraOperator_->hasTransposeApply();
267}
268
269
270template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
272 const Thyra::EOpTransp M_trans,
275 const Scalar alpha,
276 const Scalar beta
277 ) const
278{
279 using Teuchos::rcpFromRef;
280 using Teuchos::rcpFromPtr;
282 ConverterT;
283 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
284 TpetraMultiVector_t;
285
286 // Get Tpetra::MultiVector objects for X and Y
287
289 ConverterT::getConstTpetraMultiVector(rcpFromRef(X_in));
290
291 const RCP<TpetraMultiVector_t> tY =
292 ConverterT::getTpetraMultiVector(rcpFromPtr(Y_inout));
293
294 const Teuchos::ETransp tTransp = convertToTeuchosTransMode<Scalar>(M_trans);
295
296 // Apply the operator
297
298 tpetraOperator_->apply(*tX, *tY, tTransp, alpha, beta);
299 Kokkos::fence();
300}
301
302// Protected member functions overridden from ScaledLinearOpBase
303
304
305template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
307{
308 return true;
309}
310
311
312template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
314{
315 return true;
316}
317
318
319template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
320void
322scaleLeftImpl(const VectorBase<Scalar> &row_scaling_in)
323{
324 using Teuchos::rcpFromRef;
325
328
330 Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
331
332 rowMatrix->leftScale(*row_scaling);
333 Kokkos::fence();
334}
335
336
337template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
338void
340scaleRightImpl(const VectorBase<Scalar> &col_scaling_in)
341{
342 using Teuchos::rcpFromRef;
343
346
348 Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
349
350 rowMatrix->rightScale(*col_scaling);
351 Kokkos::fence();
352}
353
354// Protected member functions overridden from RowStatLinearOpBase
355
356
357template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
360 const RowStatLinearOpBaseUtils::ERowStat rowStat) const
361{
362 if (is_null(tpetraOperator_))
363 return false;
364
365 switch (rowStat) {
366 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
367 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
368 return true;
369 default:
370 return false;
371 }
372
373}
374
375
376template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
378 const RowStatLinearOpBaseUtils::ERowStat rowStat,
379 const Ptr<VectorBase<Scalar> > &rowStatVec_in
380 ) const
381{
382 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
383 TpetraVector_t;
385 typedef typename STS::magnitudeType MT;
386 typedef Teuchos::ScalarTraits<MT> STM;
387
388 if ( (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) ||
389 (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM) ) {
390
391 TEUCHOS_ASSERT(nonnull(tpetraOperator_));
392 TEUCHOS_ASSERT(nonnull(rowStatVec_in));
393
394 // Currently we only support the case of row sums for a concrete
395 // Tpetra::CrsMatrix where (1) the entire row is stored on a
396 // single process and (2) that the domain map, the range map and
397 // the row map are the SAME. These checks enforce that. Later on
398 // we hope to add complete support for any mapping to the concrete
399 // tpetra matrix types.
400
401 const RCP<TpetraVector_t> tRowSumVec =
403
405 Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getConstObj(),true);
406
407 // EGP: The following assert fails when row sum scaling is applied to blocked Tpetra operators, but without the assert, the correct row sum scaling is obtained.
408 // Furthermore, no valgrind memory errors occur in this case when the assert is removed.
409 //TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getDomainMap()));
410 TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getRangeMap()));
411 TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tRowSumVec->getMap()));
412
413 size_t numMyRows = tCrsMatrix->getLocalNumRows();
414
415 using crs_t = Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
416 typename crs_t::local_inds_host_view_type indices;
417 typename crs_t::values_host_view_type values;
418
419
420 for (size_t row=0; row < numMyRows; ++row) {
421 MT sum = STM::zero ();
422 tCrsMatrix->getLocalRowView (row, indices, values);
423
424 for (int col = 0; col < (int) values.size(); ++col) {
425 sum += STS::magnitude (values[col]);
426 }
427
428 if (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) {
429 if (sum < STM::sfmin ()) {
430 TEUCHOS_TEST_FOR_EXCEPTION(sum == STM::zero (), std::runtime_error,
431 "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Inverse row sum "
432 << "requested for a matrix where one of the rows has a zero row sum!");
433 sum = STM::one () / STM::sfmin ();
434 }
435 else {
436 sum = STM::one () / sum;
437 }
438 }
439
440 tRowSumVec->replaceLocalValue (row, Scalar (sum));
441 }
442
443 }
444 else {
445 TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
446 "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Column sum support not implemented!");
447 }
448 Kokkos::fence();
449}
450
451
452// private
453
454
455template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
456template<class TpetraOperator_t>
458 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
459 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
460 const RCP<TpetraOperator_t> &tpetraOperator
461 )
462{
463#ifdef THYRA_DEBUG
464 TEUCHOS_ASSERT(nonnull(rangeSpace));
465 TEUCHOS_ASSERT(nonnull(domainSpace));
466 TEUCHOS_ASSERT(nonnull(tpetraOperator));
467 // ToDo: Assert that spaces are comparible with tpetraOperator
468#endif
469 rangeSpace_ = rangeSpace;
470 domainSpace_ = domainSpace;
471 tpetraOperator_ = tpetraOperator;
472}
473
474
475} // namespace Thyra
476
477
478#endif // THYRA_TPETRA_LINEAR_OP_HPP
Interface for a collection of column vectors called a multi-vector.
Concrete Thyra::LinearOpBase subclass for Tpetra::Operator.
virtual bool rowStatIsSupportedImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat) const
void applyImpl(const Thyra::EOpTransp M_trans, const Thyra::MultiVectorBase< Scalar > &X_in, const Teuchos::Ptr< Thyra::MultiVectorBase< Scalar > > &Y_inout, const Scalar alpha, const Scalar beta) const
bool opSupportedImpl(Thyra::EOpTransp M_trans) const
virtual bool supportsScaleLeftImpl() const
RCP< const Thyra::VectorSpaceBase< Scalar > > range() const
TpetraLinearOp()
Construct to uninitialized.
virtual void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat, const Ptr< VectorBase< Scalar > > &rowStatVec) const
virtual void scaleLeftImpl(const VectorBase< Scalar > &row_scaling)
virtual void scaleRightImpl(const VectorBase< Scalar > &col_scaling)
void initialize(const RCP< const VectorSpaceBase< Scalar > > &rangeSpace, const RCP< const VectorSpaceBase< Scalar > > &domainSpace, const RCP< Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraOperator)
Initialize.
RCP< const Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getConstTpetraOperator() const
Get embedded const Tpetra::Operator.
void constInitialize(const RCP< const VectorSpaceBase< Scalar > > &rangeSpace, const RCP< const VectorSpaceBase< Scalar > > &domainSpace, const RCP< const Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraOperator)
Initialize.
virtual bool supportsScaleRightImpl() const
RCP< Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getTpetraOperator()
Get embedded non-const Tpetra::Operator.
RCP< const Thyra::VectorSpaceBase< Scalar > > domain() const
Traits class that enables the extraction of Tpetra operator/vector objects wrapped in Thyra operator/...
static RCP< Tpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getTpetraVector(const RCP< VectorBase< Scalar > > &v)
Get a non-const Tpetra::Vector from a non-const Thyra::VectorBase object.
static RCP< const Tpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getConstTpetraVector(const RCP< const VectorBase< Scalar > > &v)
Get a const Tpetra::Vector from a const Thyra::VectorBase object.
Abstract interface for finite-dimensional dense vectors.
Abstract interface for objects that represent a space for vectors.
RCP< const Epetra_Comm > get_Epetra_Comm(const Teuchos::Comm< Ordinal > &comm)
Get (or create) and Epetra_Comm given a Teuchos::Comm object.
@ EPETRA_OP_APPLY_APPLY
Apply using Epetra_Operator::Apply(...)
@ EPETRA_OP_ADJOINT_UNSUPPORTED
Adjoint not supported.
@ EPETRA_OP_ADJOINT_SUPPORTED
Adjoint supported.
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
@ TRANS
Use the transposed operator.
@ NOTRANS
Use the non-transposed operator.
@ CONJTRANS
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types).
@ CONJ
Use the non-transposed operator with complex-conjugate elements (same as NOTRANS for real scalar type...
RCP< const Teuchos::Comm< Ordinal > > convertTpetraToThyraComm(const RCP< const Teuchos::Comm< int > > &tpetraComm)
Given an Tpetra Teuchos::Comm<int> object, return an equivalent Teuchos::Comm<Ordinal> object.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)