Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_TpetraLinearOp_def.hpp
1// @HEADER
2// *****************************************************************************
3// Thyra: Interfaces and Support for Abstract Numerical Algorithms
4//
5// Copyright 2004 NTESS and the Thyra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef THYRA_TPETRA_LINEAR_OP_HPP
11#define THYRA_TPETRA_LINEAR_OP_HPP
12
13#include "Thyra_TpetraLinearOp_decl.hpp"
14#include "Kokkos_Core.hpp"
15#include "Thyra_TpetraVectorSpace.hpp"
16#include "Thyra_TpetraThyraWrappers.hpp"
17#include "Teuchos_ScalarTraits.hpp"
18#include "Teuchos_TypeNameTraits.hpp"
19
20#ifdef HAVE_THYRA_TPETRA_EPETRA
21# include "Thyra_EpetraThyraWrappers.hpp"
22#endif
23
24namespace Thyra {
25
26
27#ifdef HAVE_THYRA_TPETRA_EPETRA
28
29// Utilites
30
31
33 template<class Scalar, class LocalOrdinal, class GlobalOrdinal>
34class GetTpetraEpetraRowMatrixWrapper {
35public:
36 template<class TpetraMatrixType>
37 static
38 RCP<Tpetra::EpetraRowMatrix<TpetraMatrixType> >
39 get(const RCP<TpetraMatrixType> &tpetraMatrix)
40 {
41 return Teuchos::null;
42 }
43};
44
45
46// NOTE: We could support other ordinal types, but we have to
47// specialize the EpetraRowMatrix
48template<>
49class GetTpetraEpetraRowMatrixWrapper<double, int, int> {
50public:
51 template<class TpetraMatrixType>
52 static
53 RCP<Tpetra::EpetraRowMatrix<TpetraMatrixType> >
54 get(const RCP<TpetraMatrixType> &tpetraMatrix)
55 {
56 return Teuchos::rcp(
57 new Tpetra::EpetraRowMatrix<TpetraMatrixType>(tpetraMatrix,
58 *get_Epetra_Comm(
59 *convertTpetraToThyraComm(tpetraMatrix->getRowMap()->getComm())
60 )
61 )
62 );
63 }
64};
65
66
67#endif // HAVE_THYRA_TPETRA_EPETRA
68
69
70template <class Scalar>
71inline
73convertConjNoTransToTeuchosTransMode()
74{
77 Exceptions::OpNotSupported,
78 "For complex scalars such as " + Teuchos::TypeNameTraits<Scalar>::name() +
79 ", Tpetra does not support conjugation without transposition."
80 );
81 return Teuchos::NO_TRANS; // For non-complex scalars, CONJ is equivalent to NOTRANS.
82}
83
84
85template <class Scalar>
86inline
88convertToTeuchosTransMode(const Thyra::EOpTransp transp)
89{
90 switch (transp) {
91 case NOTRANS: return Teuchos::NO_TRANS;
92 case CONJ: return convertConjNoTransToTeuchosTransMode<Scalar>();
93 case TRANS: return Teuchos::TRANS;
94 case CONJTRANS: return Teuchos::CONJ_TRANS;
95 }
96
97 // Should not escape the switch
99}
100
101
102// Constructors/initializers
103
104
105template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
107
108
109template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
110TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::~TpetraLinearOp() = default;
111
112template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
114 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
115 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
116 const RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
117 )
118{
119 initializeImpl(rangeSpace, domainSpace, tpetraOperator);
120}
121
122
123template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
125 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
126 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
127 const RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
128 )
129{
130 initializeImpl(rangeSpace, domainSpace, tpetraOperator);
131}
132
133
134template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
137{
138 return tpetraOperator_.getNonconstObj();
139}
140
141
142template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
148
149
150// Public Overridden functions from LinearOpBase
151
152
153template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
159
160
161template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
164{
165 return domainSpace_;
166}
167
168
169// Overridden from EpetraLinearOpBase
170
171
172#ifdef HAVE_THYRA_TPETRA_EPETRA
173
174
175template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
177 const Ptr<RCP<Epetra_Operator> > &epetraOp,
178 const Ptr<EOpTransp> &epetraOpTransp,
179 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
180 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
181 )
182{
184}
185
186
187template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
188void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getEpetraOpView(
189 const Ptr<RCP<const Epetra_Operator> > &epetraOp,
190 const Ptr<EOpTransp> &epetraOpTransp,
191 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
192 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
193 ) const
194{
195 using Teuchos::rcp_dynamic_cast;
196 typedef Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpetraRowMatrix_t;
197 if (nonnull(tpetraOperator_)) {
198 if (is_null(epetraOp_)) {
199 epetraOp_ = GetTpetraEpetraRowMatrixWrapper<Scalar,LocalOrdinal,GlobalOrdinal>::get(
200 rcp_dynamic_cast<const TpetraRowMatrix_t>(tpetraOperator_.getConstObj(), true));
201 }
202 *epetraOp = epetraOp_;
203 *epetraOpTransp = NOTRANS;
204 *epetraOpApplyAs = EPETRA_OP_APPLY_APPLY;
205 *epetraOpAdjointSupport = ( tpetraOperator_->hasTransposeApply()
206 ? EPETRA_OP_ADJOINT_SUPPORTED : EPETRA_OP_ADJOINT_UNSUPPORTED );
207 }
208 else {
209 *epetraOp = Teuchos::null;
210 }
211}
212
213
214#endif // HAVE_THYRA_TPETRA_EPETRA
215
216
217// Protected Overridden functions from LinearOpBase
218
219
220template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
222 Thyra::EOpTransp M_trans) const
223{
224 if (is_null(tpetraOperator_))
225 return false;
226
227 if (M_trans == NOTRANS)
228 return true;
229
230 if (M_trans == CONJ) {
231 // For non-complex scalars, CONJ is always supported since it is equivalent to NO_TRANS.
232 // For complex scalars, Tpetra does not support conjugation without transposition.
234 }
235
236 return tpetraOperator_->hasTransposeApply();
237}
238
239
240template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
242 const Thyra::EOpTransp M_trans,
245 const Scalar alpha,
246 const Scalar beta
247 ) const
248{
249 using Teuchos::rcpFromRef;
250 using Teuchos::rcpFromPtr;
252 ConverterT;
253 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
254 TpetraMultiVector_t;
255
256 // Get Tpetra::MultiVector objects for X and Y
257
259 ConverterT::getConstTpetraMultiVector(rcpFromRef(X_in));
260
261 const RCP<TpetraMultiVector_t> tY =
262 ConverterT::getTpetraMultiVector(rcpFromPtr(Y_inout));
263
264 const Teuchos::ETransp tTransp = convertToTeuchosTransMode<Scalar>(M_trans);
265
266 // Apply the operator
267
268 tpetraOperator_->apply(*tX, *tY, tTransp, alpha, beta);
269 // CAG: Commented out since the purpose seems unclear.
270 // Tpetra apply should do all the necessary fencing.
271 // Kokkos::fence();
272}
273
274// Protected member functions overridden from ScaledLinearOpBase
275
276
277template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
282
283
284template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
289
290
291template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
292void
294scaleLeftImpl(const VectorBase<Scalar> &row_scaling_in)
295{
296 using Teuchos::rcpFromRef;
297
300
302 Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
303
304 rowMatrix->leftScale(*row_scaling);
305 Kokkos::fence();
306}
307
308
309template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
310void
312scaleRightImpl(const VectorBase<Scalar> &col_scaling_in)
313{
314 using Teuchos::rcpFromRef;
315
318
320 Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
321
322 rowMatrix->rightScale(*col_scaling);
323 Kokkos::fence();
324}
325
326// Protected member functions overridden from RowStatLinearOpBase
327
328
329template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
332 const RowStatLinearOpBaseUtils::ERowStat rowStat) const
333{
334 if (is_null(tpetraOperator_))
335 return false;
336
337 switch (rowStat) {
338 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
339 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
340 return true;
341 default:
342 return false;
343 }
344
345}
346
347
348template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
350 const RowStatLinearOpBaseUtils::ERowStat rowStat,
351 const Ptr<VectorBase<Scalar> > &rowStatVec_in
352 ) const
353{
354 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
355 TpetraVector_t;
357 typedef typename STS::magnitudeType MT;
358 typedef Teuchos::ScalarTraits<MT> STM;
359
360 if ( (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) ||
361 (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM) ) {
362
363 TEUCHOS_ASSERT(nonnull(tpetraOperator_));
364 TEUCHOS_ASSERT(nonnull(rowStatVec_in));
365
366 // Currently we only support the case of row sums for a concrete
367 // Tpetra::CrsMatrix where (1) the entire row is stored on a
368 // single process and (2) that the domain map, the range map and
369 // the row map are the SAME. These checks enforce that. Later on
370 // we hope to add complete support for any mapping to the concrete
371 // tpetra matrix types.
372
373 const RCP<TpetraVector_t> tRowSumVec =
375
377 Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getConstObj(),true);
378
379 // 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.
380 // Furthermore, no valgrind memory errors occur in this case when the assert is removed.
381 //TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getDomainMap()));
382 TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getRangeMap()));
383 TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tRowSumVec->getMap()));
384
385 size_t numMyRows = tCrsMatrix->getLocalNumRows();
386
387 using crs_t = Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
388 typename crs_t::local_inds_host_view_type indices;
389 typename crs_t::values_host_view_type values;
390
391
392 for (size_t row=0; row < numMyRows; ++row) {
393 MT sum = STM::zero ();
394 tCrsMatrix->getLocalRowView (row, indices, values);
395
396 for (int col = 0; col < (int) values.size(); ++col) {
397 sum += STS::magnitude (values[col]);
398 }
399
400 if (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) {
401 if (sum < STM::sfmin ()) {
402 TEUCHOS_TEST_FOR_EXCEPTION(sum == STM::zero (), std::runtime_error,
403 "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Inverse row sum "
404 << "requested for a matrix where one of the rows has a zero row sum!");
405 sum = STM::one () / STM::sfmin ();
406 }
407 else {
408 sum = STM::one () / sum;
409 }
410 }
411
412 tRowSumVec->replaceLocalValue (row, Scalar (sum));
413 }
414
415 }
416 else {
417 TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
418 "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Column sum support not implemented!");
419 }
420 Kokkos::fence();
421}
422
423
424// private
425
426
427template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
428template<class TpetraOperator_t>
430 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
431 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
432 const RCP<TpetraOperator_t> &tpetraOperator
433 )
434{
435#ifdef THYRA_DEBUG
436 TEUCHOS_ASSERT(nonnull(rangeSpace));
437 TEUCHOS_ASSERT(nonnull(domainSpace));
438 TEUCHOS_ASSERT(nonnull(tpetraOperator));
439 // ToDo: Assert that spaces are comparible with tpetraOperator
440#endif
441 rangeSpace_ = rangeSpace;
442 domainSpace_ = domainSpace;
443 tpetraOperator_ = tpetraOperator;
444}
445
446
447template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
448RCP<TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
449tpetraLinearOp(
450 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
451 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
452 const RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
453 )
454{
457 op->initialize(rangeSpace, domainSpace, tpetraOperator);
458 return op;
459}
460
461
462template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
464constTpetraLinearOp(
465 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
466 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
467 const RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
468 )
469{
472 op->constInitialize(rangeSpace, domainSpace, tpetraOperator);
473 return op;
474}
475
476
477} // namespace Thyra
478
479#define THYRATPETRAADAPTERS_TPETRALINEAROP_INSTANT(S, LO, GO, N) \
480 template class Thyra::TpetraLinearOp<S, LO, GO, N>; \
481 \
482 template Teuchos::RCP<Thyra::TpetraLinearOp<S, LO, GO, N>> \
483 Thyra::tpetraLinearOp(const Teuchos::RCP<const Thyra::VectorSpaceBase<S>> &, \
484 const Teuchos::RCP<const Thyra::VectorSpaceBase<S>> &, \
485 const Teuchos::RCP<Tpetra::Operator<S, LO, GO, N>> &); \
486 \
487 template Teuchos::RCP<const Thyra::TpetraLinearOp<S, LO, GO, N>> \
488 Thyra::constTpetraLinearOp( \
489 const Teuchos::RCP<const Thyra::VectorSpaceBase<S>> &, \
490 const Teuchos::RCP<const Thyra::VectorSpaceBase<S>> &, \
491 const Teuchos::RCP<const Tpetra::Operator<S, LO, GO, N>> &);
492
493#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.
#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)