Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_EpetraOperatorWrapper.cpp
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 #include "Thyra_EpetraOperatorWrapper.hpp"
12 #include "Thyra_DetachedSpmdVectorView.hpp"
13 #include "Thyra_DefaultProductVector.hpp"
14 #include "Thyra_ProductVectorSpaceBase.hpp"
15 #include "Thyra_SpmdVectorBase.hpp"
16 #include "Thyra_EpetraLinearOp.hpp"
17 
18 #ifdef HAVE_MPI
19 # include "Epetra_MpiComm.h"
20 #endif
21 #include "Epetra_SerialComm.h"
22 #include "Epetra_Vector.h"
23 
24 #ifdef HAVE_MPI
25 # include "Teuchos_DefaultMpiComm.hpp"
26 #endif
27 #include "Teuchos_DefaultSerialComm.hpp"
28 
29 
30 namespace Thyra {
31 
32 
33 // Constructor, utilties
34 
35 
37  const RCP<const LinearOpBase<double> > &thyraOp
38  )
39  : useTranspose_(false),
40  thyraOp_(thyraOp),
41  range_(thyraOp->range()),
42  domain_(thyraOp->domain()),
43  comm_(getEpetraComm(*thyraOp)),
44  rangeMap_(get_Epetra_Map(*range_, comm_)),
45  domainMap_(get_Epetra_Map(*domain_, comm_)),
46  label_(thyraOp->description())
47 {;}
48 
49 
51  const Ptr<VectorBase<double> > &thyraVec) const
52 {
53 
54  using Teuchos::rcpFromPtr;
55  using Teuchos::rcp_dynamic_cast;
56 
57  const int numVecs = x.NumVectors();
58 
59  TEUCHOS_TEST_FOR_EXCEPTION(numVecs != 1, std::runtime_error,
60  "epetraToThyra does not work with MV dimension != 1");
61 
62  const RCP<ProductVectorBase<double> > prodThyraVec =
63  castOrCreateNonconstProductVectorBase(rcpFromPtr(thyraVec));
64 
65  const ArrayView<const double> epetraData(x[0], x.Map().NumMyElements());
66  // NOTE: I tried using Epetra_MultiVector::operator()(int) to return an
67  // Epetra_Vector object but it has a defect when Reset(...) is called which
68  // results in a memory access error (see bug 4700).
69 
70  int offset = 0;
71  const int numBlocks = prodThyraVec->productSpace()->numBlocks();
72  for (int b = 0; b < numBlocks; ++b) {
73  const RCP<VectorBase<double> > vec_b = prodThyraVec->getNonconstVectorBlock(b);
74  const RCP<const SpmdVectorSpaceBase<double> > spmd_vs_b =
75  rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(vec_b->space(), true);
77  const ArrayRCP<double> thyraData = view.sv().values();
78  const int localNumElems = spmd_vs_b->localSubDim();
79  for (int i=0; i < localNumElems; ++i) {
80  thyraData[i] = epetraData[i+offset];
81  }
82  offset += localNumElems;
83  }
84 
85 }
86 
87 
89  const VectorBase<double>& thyraVec, Epetra_MultiVector& x) const
90 {
91 
92  using Teuchos::rcpFromRef;
93  using Teuchos::rcp_dynamic_cast;
94 
95  const int numVecs = x.NumVectors();
96 
97  TEUCHOS_TEST_FOR_EXCEPTION(numVecs != 1, std::runtime_error,
98  "epetraToThyra does not work with MV dimension != 1");
99 
100  const RCP<const ProductVectorBase<double> > prodThyraVec =
101  castOrCreateProductVectorBase(rcpFromRef(thyraVec));
102 
103  const ArrayView<double> epetraData(x[0], x.Map().NumMyElements());
104  // NOTE: See above!
105 
106  int offset = 0;
107  const int numBlocks = prodThyraVec->productSpace()->numBlocks();
108  for (int b = 0; b < numBlocks; ++b) {
109  const RCP<const VectorBase<double> > vec_b = prodThyraVec->getVectorBlock(b);
110  const RCP<const SpmdVectorSpaceBase<double> > spmd_vs_b =
111  rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(vec_b->space(), true);
113  const ArrayRCP<const double> thyraData = view.sv().values();
114  const int localNumElems = spmd_vs_b->localSubDim();
115  for (int i=0; i < localNumElems; ++i) {
116  epetraData[i+offset] = thyraData[i];
117  }
118  offset += localNumElems;
119  }
120 
121 }
122 
123 
124 // Overridden from Epetra_Operator
125 
126 
128  Epetra_MultiVector& Y) const
129 {
130 
132  opRange = ( !useTranspose_ ? range_ : domain_ ),
133  opDomain = ( !useTranspose_ ? domain_ : range_ );
134 
135  const RCP<VectorBase<double> > tx = createMember(opDomain);
136  copyEpetraIntoThyra(X, tx.ptr());
137 
138  const RCP<VectorBase<double> > ty = createMember(opRange);
139 
140  Thyra::apply<double>( *thyraOp_, !useTranspose_ ? NOTRANS : CONJTRANS, *tx, ty.ptr());
141 
142  copyThyraIntoEpetra(*ty, Y);
143 
144  return 0;
145 
146 }
147 
148 
150  Epetra_MultiVector& /* Y */) const
151 {
152  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
153  "EpetraOperatorWrapper::ApplyInverse not implemented");
155 }
156 
157 
159 {
160  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
161  "EpetraOperatorWrapper::NormInf not implemated");
163 }
164 
165 
166 // private
167 
168 
170 EpetraOperatorWrapper::getEpetraComm(const LinearOpBase<double>& thyraOp)
171 {
172 
173  using Teuchos::rcp;
174  using Teuchos::rcp_dynamic_cast;
175  using Teuchos::SerialComm;
176 #ifdef HAVE_MPI
177  using Teuchos::MpiComm;
178 #endif
179 
180  RCP<const VectorSpaceBase<double> > vs = thyraOp.range();
181 
183  rcp_dynamic_cast<const ProductVectorSpaceBase<double> >(vs);
184 
185  if (nonnull(prod_vs))
186  vs = prod_vs->getBlock(0);
187 
188  const RCP<const SpmdVectorSpaceBase<double> > spmd_vs =
189  rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(vs, true);
190 
191  return get_Epetra_Comm(*spmd_vs->getComm());
192 
193 }
194 
195 
196 } // namespace Thyra
197 
198 
200 Thyra::makeEpetraWrapper(const RCP<const LinearOpBase<double> > &thyraOp)
201 {
202  return epetraLinearOp(
203  Teuchos::rcp(new EpetraOperatorWrapper(thyraOp))
204  );
205 }
Create an explicit detached mutable (non-const) view of all of the local elements on this process of ...
virtual RCP< const VectorSpaceBase< Scalar > > range() const =0
Return a smart pointer for the range space for this operator.
void copyEpetraIntoThyra(const Epetra_MultiVector &x, const Ptr< VectorBase< double > > &thyraVec) const
EpetraOperatorWrapper(const RCP< const LinearOpBase< double > > &thyraOp)
RCP< const Epetra_Map > get_Epetra_Map(const VectorSpaceBase< double > &vs, const RCP< const Epetra_Comm > &comm)
Get (or create) an Epetra_Map object given an VectorSpaceBase object an optionally an extra Epetra_Co...
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Use the non-transposed operator.
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types)...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Ptr< T > ptr() const
Abstract interface for finite-dimensional dense vectors.
RCP< const EpetraLinearOp > epetraLinearOp(const RCP< const Epetra_Operator > &op, EOpTransp opTrans=NOTRANS, EApplyEpetraOpAs applyAs=EPETRA_OP_APPLY_APPLY, EAdjointEpetraOp adjointSupport=EPETRA_OP_ADJOINT_SUPPORTED, const RCP< const VectorSpaceBase< double > > &range=Teuchos::null, const RCP< const VectorSpaceBase< double > > &domain=Teuchos::null)
Dynamically allocate a nonconst EpetraLinearOp to wrap a const Epetra_Operator object.
int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
RCP< const Epetra_Comm > get_Epetra_Comm(const Teuchos::Comm< Ordinal > &comm)
Get (or create) and Epetra_Comm given a Teuchos::Comm object.
void copyThyraIntoEpetra(const VectorBase< double > &thyraVec, Epetra_MultiVector &x) const
bool nonnull(const boost::shared_ptr< T > &p)
#define TEUCHOS_UNREACHABLE_RETURN(dummyReturnVal)
int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Create an explicit detached non-mutable (const) view of all of the local elements on this process of ...
Base abstract VectorSpaceBase class for all SPMD-based vector spaces.