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,
146  const RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
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,
157  const RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &tpetraOperator
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;
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 
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;
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 
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 }
334 
335 
336 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
337 void
339 scaleRightImpl(const VectorBase<Scalar> &col_scaling_in)
340 {
341  using Teuchos::rcpFromRef;
342 
345 
347  Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getNonconstObj(),true);
348 
349  rowMatrix->rightScale(*col_scaling);
350 }
351 
352 // Protected member functions overridden from RowStatLinearOpBase
353 
354 
355 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
358  const RowStatLinearOpBaseUtils::ERowStat rowStat) const
359 {
360  if (is_null(tpetraOperator_))
361  return false;
362 
363  switch (rowStat) {
364  case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
365  case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
366  return true;
367  default:
368  return false;
369  }
370 
372 }
373 
374 
375 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
377  const RowStatLinearOpBaseUtils::ERowStat rowStat,
378  const Ptr<VectorBase<Scalar> > &rowStatVec_in
379  ) const
380 {
381  typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>
382  TpetraVector_t;
383  typedef Teuchos::ScalarTraits<Scalar> STS;
384  typedef typename STS::magnitudeType MT;
385  typedef Teuchos::ScalarTraits<MT> STM;
386 
387  if ( (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) ||
388  (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM) ) {
389 
390  TEUCHOS_ASSERT(nonnull(tpetraOperator_));
391  TEUCHOS_ASSERT(nonnull(rowStatVec_in));
392 
393  // Currently we only support the case of row sums for a concrete
394  // Tpetra::CrsMatrix where (1) the entire row is stored on a
395  // single process and (2) that the domain map, the range map and
396  // the row map are the SAME. These checks enforce that. Later on
397  // we hope to add complete support for any mapping to the concrete
398  // tpetra matrix types.
399 
400  const RCP<TpetraVector_t> tRowSumVec =
402 
404  Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetraOperator_.getConstObj(),true);
405 
406  // 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.
407  // Furthermore, no valgrind memory errors occur in this case when the assert is removed.
408  //TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getDomainMap()));
409  TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tCrsMatrix->getRangeMap()));
410  TEUCHOS_ASSERT(tCrsMatrix->getRowMap()->isSameAs(*tRowSumVec->getMap()));
411 
412  size_t numMyRows = tCrsMatrix->getNodeNumRows();
413 
416 
417  for (size_t row=0; row < numMyRows; ++row) {
418  MT sum = STM::zero ();
419  tCrsMatrix->getLocalRowView (row, indices, values);
420 
421  for (int col = 0; col < values.size(); ++col) {
422  sum += STS::magnitude (values[col]);
423  }
424 
425  if (rowStat == RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM) {
426  if (sum < STM::sfmin ()) {
427  TEUCHOS_TEST_FOR_EXCEPTION(sum == STM::zero (), std::runtime_error,
428  "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Inverse row sum "
429  << "requested for a matrix where one of the rows has a zero row sum!");
430  sum = STM::one () / STM::sfmin ();
431  }
432  else {
433  sum = STM::one () / sum;
434  }
435  }
436 
437  tRowSumVec->replaceLocalValue (row, Scalar (sum));
438  }
439 
440  }
441  else {
442  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
443  "Error - Thyra::TpetraLinearOp::getRowStatImpl() - Column sum support not implemented!");
444  }
445 }
446 
447 
448 // private
449 
450 
451 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
452 template<class TpetraOperator_t>
454  const RCP<const VectorSpaceBase<Scalar> > &rangeSpace,
455  const RCP<const VectorSpaceBase<Scalar> > &domainSpace,
456  const RCP<TpetraOperator_t> &tpetraOperator
457  )
458 {
459 #ifdef THYRA_DEBUG
460  TEUCHOS_ASSERT(nonnull(rangeSpace));
461  TEUCHOS_ASSERT(nonnull(domainSpace));
462  TEUCHOS_ASSERT(nonnull(tpetraOperator));
463  // ToDo: Assert that spaces are comparible with tpetraOperator
464 #endif
465  rangeSpace_ = rangeSpace;
466  domainSpace_ = domainSpace;
467  tpetraOperator_ = tpetraOperator;
468 }
469 
470 
471 } // namespace Thyra
472 
473 
474 #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.
size_type size() const
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)
#define TEUCHOS_UNREACHABLE_RETURN(dummyReturnVal)
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)