Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
56 namespace Thyra {
57 
58 
59 #ifdef HAVE_THYRA_TPETRA_EPETRA
60 
61 // Utilites
62 
63 
65  template<class Scalar, class LocalOrdinal, class GlobalOrdinal>
66 class GetTpetraEpetraRowMatrixWrapper {
67 public:
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
80 template<>
81 class GetTpetraEpetraRowMatrixWrapper<double, int, int> {
82 public:
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 
102 template <class Scalar>
103 inline
105 convertConjNoTransToTeuchosTransMode()
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 
117 template <class Scalar>
118 inline
120 convertToTeuchosTransMode(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 
137 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
139 {}
140 
141 
142 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
144  const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
145  const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
147  )
148 {
149  initializeImpl(rangeSpace, domainSpace, tpetraOperator);
150 }
151 
152 
153 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
155  const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
156  const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
158  )
159 {
160  initializeImpl(rangeSpace, domainSpace, tpetraOperator);
161 }
162 
163 
164 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
167 {
168  return tpetraOperator_.getNonconstObj();
169 }
170 
171 
172 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
175 {
176  return tpetraOperator_;
177 }
178 
179 
180 // Public Overridden functions from LinearOpBase
181 
182 
183 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
186 {
187  return rangeSpace_;
188 }
189 
190 
191 template <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 
205 template <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 
217 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
218 void 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;
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 
250 template <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 
270 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
272  const Thyra::EOpTransp M_trans,
273  const Thyra::MultiVectorBase<Scalar> &X_in,
275  const Scalar alpha,
276  const Scalar beta
277  ) const
278 {
279  using Teuchos::rcpFromRef;
280  using Teuchos::rcpFromPtr;
282  ConverterT;
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 
305 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
307 {
308  return true;
309 }
310 
311 
312 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
314 {
315  return true;
316 }
317 
318 
319 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
320 void
322 scaleLeftImpl(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 
337 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
338 void
340 scaleRightImpl(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 
357 template <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 
376 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
378  const RowStatLinearOpBaseUtils::ERowStat rowStat,
379  const Ptr<VectorBase<Scalar> > &rowStatVec_in
380  ) const
381 {
383  TpetraVector_t;
384  typedef Teuchos::ScalarTraits<Scalar> STS;
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 
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 
455 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
456 template<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
bool is_null(const boost::shared_ptr< T > &p)
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
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.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Use the non-transposed operator.
virtual void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat, const Ptr< VectorBase< Scalar > > &rowStatVec) const
bool opSupportedImpl(Thyra::EOpTransp M_trans) const
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types)...
Abstract interface for objects that represent a space for vectors.
Traits class that enables the extraction of Tpetra operator/vector objects wrapped in Thyra operator/...
Use the non-transposed operator with complex-conjugate elements (same as NOTRANS for real scalar type...
RCP< const Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getConstTpetraOperator() const
Get embedded const Tpetra::Operator.
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
Use the transposed operator.
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.
virtual bool rowStatIsSupportedImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Interface for a collection of column vectors called a multi-vector.
virtual bool supportsScaleLeftImpl() const
RCP< const Thyra::VectorSpaceBase< Scalar > > range() const
RCP< Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getTpetraOperator()
Get embedded non-const Tpetra::Operator.
Abstract interface for finite-dimensional dense vectors.
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.
TpetraLinearOp()
Construct to uninitialized.
RCP< const Teuchos::Comm< Ordinal > > convertTpetraToThyraComm(const RCP< const Teuchos::Comm< int > > &tpetraComm)
Given an Tpetra Teuchos::Comm&lt;int&gt; object, return an equivalent Teuchos::Comm&lt;Ordinal&gt; object...
RCP< const Epetra_Comm > get_Epetra_Comm(const Teuchos::Comm< Ordinal > &comm)
Get (or create) and Epetra_Comm given a Teuchos::Comm object.
virtual void scaleLeftImpl(const VectorBase< Scalar > &row_scaling)
bool nonnull(const boost::shared_ptr< T > &p)
virtual void scaleRightImpl(const VectorBase< Scalar > &col_scaling)
virtual bool supportsScaleRightImpl() const
void initialize(const RCP< const VectorSpaceBase< Scalar > > &rangeSpace, const RCP< const VectorSpaceBase< Scalar > > &domainSpace, const RCP< Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraOperator)
Initialize.
#define TEUCHOS_ASSERT(assertion_test)
RCP< const Thyra::VectorSpaceBase< Scalar > > domain() const
Concrete Thyra::LinearOpBase subclass for Tpetra::Operator.
Apply using Epetra_Operator::Apply(...)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)