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 "Thyra_TpetraVectorSpace.hpp"
17
18#include "Tpetra_CrsMatrix.hpp"
19
20#ifdef HAVE_THYRA_TPETRA_EPETRA
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,
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{
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>
108
109
110template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
112 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
113 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
114 const RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
115 )
116{
117 initializeImpl(rangeSpace, domainSpace, tpetraOperator);
118}
119
120
121template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
124 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
125 const RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
126 )
127{
128 initializeImpl(rangeSpace, domainSpace, tpetraOperator);
129}
130
131
132template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
135{
136 return tpetraOperator_.getNonconstObj();
137}
138
139
140template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
146
147
148// Public Overridden functions from LinearOpBase
149
150
151template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
157
158
159template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
162{
163 return domainSpace_;
164}
165
166
167// Overridden from EpetraLinearOpBase
168
169
170#ifdef HAVE_THYRA_TPETRA_EPETRA
171
172
173template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
175 const Ptr<RCP<Epetra_Operator> > &epetraOp,
176 const Ptr<EOpTransp> &epetraOpTransp,
177 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
178 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
179 )
180{
182}
183
184
185template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
186void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getEpetraOpView(
187 const Ptr<RCP<const Epetra_Operator> > &epetraOp,
188 const Ptr<EOpTransp> &epetraOpTransp,
189 const Ptr<EApplyEpetraOpAs> &epetraOpApplyAs,
190 const Ptr<EAdjointEpetraOp> &epetraOpAdjointSupport
191 ) const
192{
193 using Teuchos::rcp_dynamic_cast;
194 typedef Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpetraRowMatrix_t;
195 if (nonnull(tpetraOperator_)) {
196 if (is_null(epetraOp_)) {
197 epetraOp_ = GetTpetraEpetraRowMatrixWrapper<Scalar,LocalOrdinal,GlobalOrdinal>::get(
198 rcp_dynamic_cast<const TpetraRowMatrix_t>(tpetraOperator_.getConstObj(), true));
199 }
200 *epetraOp = epetraOp_;
201 *epetraOpTransp = NOTRANS;
202 *epetraOpApplyAs = EPETRA_OP_APPLY_APPLY;
203 *epetraOpAdjointSupport = ( tpetraOperator_->hasTransposeApply()
205 }
206 else {
207 *epetraOp = Teuchos::null;
208 }
209}
210
211
212#endif // HAVE_THYRA_TPETRA_EPETRA
213
214
215// Protected Overridden functions from LinearOpBase
216
217
218template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
220 Thyra::EOpTransp M_trans) const
221{
222 if (is_null(tpetraOperator_))
223 return false;
224
225 if (M_trans == NOTRANS)
226 return true;
227
228 if (M_trans == CONJ) {
229 // For non-complex scalars, CONJ is always supported since it is equivalent to NO_TRANS.
230 // For complex scalars, Tpetra does not support conjugation without transposition.
232 }
233
234 return tpetraOperator_->hasTransposeApply();
235}
236
237
238template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
240 const Thyra::EOpTransp M_trans,
243 const Scalar alpha,
244 const Scalar beta
245 ) const
246{
247 using Teuchos::rcpFromRef;
248 using Teuchos::rcpFromPtr;
250 ConverterT;
251 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
252 TpetraMultiVector_t;
253
254 // Get Tpetra::MultiVector objects for X and Y
255
257 ConverterT::getConstTpetraMultiVector(rcpFromRef(X_in));
258
259 const RCP<TpetraMultiVector_t> tY =
260 ConverterT::getTpetraMultiVector(rcpFromPtr(Y_inout));
261
262 const Teuchos::ETransp tTransp = convertToTeuchosTransMode<Scalar>(M_trans);
263
264 // Apply the operator
265
266 tpetraOperator_->apply(*tX, *tY, tTransp, alpha, beta);
267 Kokkos::fence();
268}
269
270// Protected member functions overridden from ScaledLinearOpBase
271
272
273template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
278
279
280template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
285
286
287template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
288void
290scaleLeftImpl(const VectorBase<Scalar> &row_scaling_in)
291{
292 using Teuchos::rcpFromRef;
293
296
298 Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
299
300 rowMatrix->leftScale(*row_scaling);
301 Kokkos::fence();
302}
303
304
305template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
306void
308scaleRightImpl(const VectorBase<Scalar> &col_scaling_in)
309{
310 using Teuchos::rcpFromRef;
311
314
316 Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
317
318 rowMatrix->rightScale(*col_scaling);
319 Kokkos::fence();
320}
321
322// Protected member functions overridden from RowStatLinearOpBase
323
324
325template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
328 const RowStatLinearOpBaseUtils::ERowStat rowStat) const
329{
330 if (is_null(tpetraOperator_))
331 return false;
332
333 switch (rowStat) {
334 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
335 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
336 return true;
337 default:
338 return false;
339 }
340
341}
342
343
344template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
346 const RowStatLinearOpBaseUtils::ERowStat rowStat,
347 const Ptr<VectorBase<Scalar> > &rowStatVec_in
348 ) const
349{
350 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
351 TpetraVector_t;
353 typedef typename STS::magnitudeType MT;
354 typedef Teuchos::ScalarTraits<MT> STM;
355
356 if ( (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) ||
357 (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM) ) {
358
359 TEUCHOS_ASSERT(nonnull(tpetraOperator_));
360 TEUCHOS_ASSERT(nonnull(rowStatVec_in));
361
362 // Currently we only support the case of row sums for a concrete
363 // Tpetra::CrsMatrix where (1) the entire row is stored on a
364 // single process and (2) that the domain map, the range map and
365 // the row map are the SAME. These checks enforce that. Later on
366 // we hope to add complete support for any mapping to the concrete
367 // tpetra matrix types.
368
369 const RCP<TpetraVector_t> tRowSumVec =
371
373 Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getConstObj(),true);
374
375 // 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.
376 // Furthermore, no valgrind memory errors occur in this case when the assert is removed.
377 //TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getDomainMap()));
378 TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getRangeMap()));
379 TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tRowSumVec->getMap()));
380
381 size_t numMyRows = tCrsMatrix->getLocalNumRows();
382
383 using crs_t = Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
384 typename crs_t::local_inds_host_view_type indices;
385 typename crs_t::values_host_view_type values;
386
387
388 for (size_t row=0; row < numMyRows; ++row) {
389 MT sum = STM::zero ();
390 tCrsMatrix->getLocalRowView (row, indices, values);
391
392 for (int col = 0; col < (int) values.size(); ++col) {
393 sum += STS::magnitude (values[col]);
394 }
395
396 if (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) {
397 if (sum < STM::sfmin ()) {
398 TEUCHOS_TEST_FOR_EXCEPTION(sum == STM::zero (), std::runtime_error,
399 "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Inverse row sum "
400 << "requested for a matrix where one of the rows has a zero row sum!");
401 sum = STM::one () / STM::sfmin ();
402 }
403 else {
404 sum = STM::one () / sum;
405 }
406 }
407
408 tRowSumVec->replaceLocalValue (row, Scalar (sum));
409 }
410
411 }
412 else {
413 TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
414 "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Column sum support not implemented!");
415 }
416 Kokkos::fence();
417}
418
419
420// private
421
422
423template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
424template<class TpetraOperator_t>
425void TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node>::initializeImpl(
426 const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
427 const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
428 const RCP<TpetraOperator_t> &tpetraOperator
429 )
430{
431#ifdef THYRA_DEBUG
432 TEUCHOS_ASSERT(nonnull(rangeSpace));
433 TEUCHOS_ASSERT(nonnull(domainSpace));
434 TEUCHOS_ASSERT(nonnull(tpetraOperator));
435 // ToDo: Assert that spaces are comparible with tpetraOperator
436#endif
437 rangeSpace_ = rangeSpace;
438 domainSpace_ = domainSpace;
439 tpetraOperator_ = tpetraOperator;
440}
441
442
443} // namespace Thyra
444
445
446#endif // THYRA_TPETRA_LINEAR_OP_HPP
static std::string name()
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.
Scalar sum(const VectorBase< Scalar > &v)
Sum of vector elements: result = sum( v(i), i = 0...v.space()->dim()-1 ).
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)
NOTRANS
Type for the dimension of a vector space. `**/ typedef Teuchos::Ordinal Ordinal;.
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)
static const bool isComplex