Teko Version of the Day
Loading...
Searching...
No Matches
Teko_EpetraOperatorWrapper.cpp
1// @HEADER
2// *****************************************************************************
3// Teko: A package for block and physics based preconditioning
4//
5// Copyright 2010 NTESS and the Teko contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#include "Teko_EpetraOperatorWrapper.hpp"
11#include "Thyra_SpmdVectorBase.hpp"
12#include "Thyra_MultiVectorStdOps.hpp"
13#ifdef HAVE_MPI
14#include "Teuchos_DefaultMpiComm.hpp"
15#endif
16#include "Teuchos_DefaultSerialComm.hpp"
17#include "Thyra_EpetraLinearOp.hpp"
18#include "Epetra_SerialComm.h"
19#include "Epetra_Vector.h"
20#ifdef HAVE_MPI
21#include "Epetra_MpiComm.h"
22#endif
23#include "Thyra_EpetraThyraWrappers.hpp"
24
25// #include "Thyra_LinearOperator.hpp"
26#include "Thyra_BlockedLinearOpBase.hpp"
27#include "Thyra_ProductVectorSpaceBase.hpp"
28#include "Thyra_get_Epetra_Operator.hpp"
29
30#include "Teko_EpetraThyraConverter.hpp"
31#include "Teuchos_Ptr.hpp"
32
33namespace Teko {
34namespace Epetra {
35
36using namespace Teuchos;
37using namespace Thyra;
38
39DefaultMappingStrategy::DefaultMappingStrategy(
40 const RCP<const Thyra::LinearOpBase<double> >& thyraOp, const Epetra_Comm& comm) {
41 RCP<Epetra_Comm> newComm = rcp(comm.Clone());
42
43 // extract vector spaces from linear operator
44 domainSpace_ = thyraOp->domain();
45 rangeSpace_ = thyraOp->range();
46
47 domainMap_ = Teko::Epetra::thyraVSToEpetraMap(*domainSpace_, newComm);
48 rangeMap_ = Teko::Epetra::thyraVSToEpetraMap(*rangeSpace_, newComm);
49}
50
52 const Epetra_MultiVector& x, const Ptr<Thyra::MultiVectorBase<double> >& thyraVec) const {
53 Teko::Epetra::blockEpetraToThyra(x, thyraVec);
54}
55
57 const RCP<const Thyra::MultiVectorBase<double> >& thyraVec, Epetra_MultiVector& v) const {
58 Teko::Epetra::blockThyraToEpetra(thyraVec, v);
59}
60
61EpetraOperatorWrapper::EpetraOperatorWrapper() {
62 useTranspose_ = false;
63 mapStrategy_ = Teuchos::null;
64 thyraOp_ = Teuchos::null;
65 comm_ = Teuchos::null;
66 label_ = Teuchos::null;
67}
68
69EpetraOperatorWrapper::EpetraOperatorWrapper(
70 const RCP<const Thyra::LinearOpBase<double> >& thyraOp) {
71 SetOperator(thyraOp);
72}
73
74EpetraOperatorWrapper::EpetraOperatorWrapper(const RCP<const Thyra::LinearOpBase<double> >& thyraOp,
75 const RCP<const MappingStrategy>& mapStrategy)
76 : mapStrategy_(mapStrategy) {
77 SetOperator(thyraOp);
78}
79
80EpetraOperatorWrapper::EpetraOperatorWrapper(const RCP<const MappingStrategy>& mapStrategy)
81 : mapStrategy_(mapStrategy) {
82 useTranspose_ = false;
83 thyraOp_ = Teuchos::null;
84 comm_ = Teuchos::null;
85 label_ = Teuchos::null;
86}
87
88void EpetraOperatorWrapper::SetOperator(const RCP<const LinearOpBase<double> >& thyraOp,
89 bool buildMap) {
90 useTranspose_ = false;
91 thyraOp_ = thyraOp;
92 comm_ = getEpetraComm(*thyraOp);
93 label_ = thyraOp_->description();
94 if (mapStrategy_ == Teuchos::null && buildMap)
95 mapStrategy_ = Teuchos::rcp(new DefaultMappingStrategy(thyraOp, *comm_));
96}
97
98double EpetraOperatorWrapper::NormInf() const {
99 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
100 "EpetraOperatorWrapper::NormInf not implemated");
101 return 1.0;
102}
103
104int EpetraOperatorWrapper::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const {
105 if (!useTranspose_) {
106 // allocate space for each vector
107 RCP<Thyra::MultiVectorBase<double> > tX;
108 RCP<Thyra::MultiVectorBase<double> > tY;
109
110 tX = Thyra::createMembers(thyraOp_->domain(), X.NumVectors());
111 tY = Thyra::createMembers(thyraOp_->range(), X.NumVectors());
112
113 Thyra::assign(tX.ptr(), 0.0);
114 Thyra::assign(tY.ptr(), 0.0);
115
116 // copy epetra X into thyra X
117 mapStrategy_->copyEpetraIntoThyra(X, tX.ptr());
118 mapStrategy_->copyEpetraIntoThyra(
119 Y, tY.ptr()); // if this matrix isn't block square, this probably won't work!
120
121 // perform matrix vector multiplication
122 thyraOp_->apply(Thyra::NOTRANS, *tX, tY.ptr(), 1.0, 0.0);
123
124 // copy thyra Y into epetra Y
125 mapStrategy_->copyThyraIntoEpetra(tY, Y);
126 } else {
127 TEUCHOS_ASSERT(false);
128 }
129
130 return 0;
131}
132
133int EpetraOperatorWrapper::ApplyInverse(const Epetra_MultiVector& /* X */,
134 Epetra_MultiVector& /* Y */) const {
135 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
136 "EpetraOperatorWrapper::ApplyInverse not implemented");
137 return 1;
138}
139
140RCP<const Epetra_Comm> EpetraOperatorWrapper::getEpetraComm(
141 const Thyra::LinearOpBase<double>& inOp) const {
142 RCP<const VectorSpaceBase<double> > vs = inOp.domain();
143
144 RCP<const SpmdVectorSpaceBase<double> > spmd;
145 RCP<const VectorSpaceBase<double> > current = vs;
146 while (current != Teuchos::null) {
147 // try to cast to a product vector space first
148 RCP<const ProductVectorSpaceBase<double> > prod =
149 rcp_dynamic_cast<const ProductVectorSpaceBase<double> >(current);
150
151 // figure out what type it is
152 if (prod == Teuchos::null) {
153 // hopfully this is a SPMD vector space
154 spmd = rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(current);
155
156 break;
157 } else // get first convenient vector space
158 current = prod->getBlock(0);
159 }
160
161 TEUCHOS_TEST_FOR_EXCEPTION(spmd == Teuchos::null, std::runtime_error,
162 "EpetraOperatorWrapper requires std::vector space "
163 "blocks to be SPMD std::vector spaces");
164
165 return Thyra::get_Epetra_Comm(*spmd->getComm());
166 /*
167 const Thyra::ConstLinearOperator<double> thyraOp = rcpFromRef(inOp);
168
169 RCP<Epetra_Comm> rtn;
170 // VectorSpace<double> vs = thyraOp.domain().getBlock(0);
171 RCP<const VectorSpaceBase<double> > vs = thyraOp.domain().getBlock(0).constPtr();
172
173 // search for an SpmdVectorSpaceBase object
174 RCP<const SpmdVectorSpaceBase<double> > spmd;
175 RCP<const VectorSpaceBase<double> > current = vs;
176 while(current!=Teuchos::null) {
177 // try to cast to a product vector space first
178 RCP<const ProductVectorSpaceBase<double> > prod
179 = rcp_dynamic_cast<const ProductVectorSpaceBase<double> >(current);
180
181 // figure out what type it is
182 if(prod==Teuchos::null) {
183 // hopfully this is a SPMD vector space
184 spmd = rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(current);
185
186 break;
187 }
188 else {
189 // get first convenient vector space
190 current = prod->getBlock(0);
191 }
192 }
193
194 TEUCHOS_TEST_FOR_EXCEPTION(spmd==Teuchos::null, std::runtime_error,
195 "EpetraOperatorWrapper requires std::vector space "
196 "blocks to be SPMD std::vector spaces");
197
198 const SerialComm<Thyra::Ordinal>* serialComm
199 = dynamic_cast<const SerialComm<Thyra::Ordinal>*>(spmd->getComm().get());
200
201 #ifdef HAVE_MPI
202 const MpiComm<Thyra::Ordinal>* mpiComm
203 = dynamic_cast<const MpiComm<Thyra::Ordinal>*>(spmd->getComm().get());
204
205 TEUCHOS_TEST_FOR_EXCEPTION(mpiComm==0 && serialComm==0, std::runtime_error,
206 "SPMD std::vector space has a communicator that is "
207 "neither a serial comm nor an MPI comm");
208
209 if (mpiComm != 0)
210 {
211 rtn = rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
212 }
213 else
214 {
215 rtn = rcp(new Epetra_SerialComm());
216 }
217 #else
218 TEUCHOS_TEST_FOR_EXCEPTION(serialComm==0, std::runtime_error,
219 "SPMD std::vector space has a communicator that is "
220 "neither a serial comm nor an MPI comm");
221 rtn = rcp(new Epetra_SerialComm());
222
223 #endif
224
225 TEUCHOS_TEST_FOR_EXCEPTION(rtn.get()==0, std::runtime_error, "null communicator created");
226 return rtn;
227 */
228}
229
231 const RCP<const Thyra::BlockedLinearOpBase<double> > blkOp =
232 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(getThyraOp());
233
234 return blkOp->productRange()->numBlocks();
235}
236
238 const RCP<const Thyra::BlockedLinearOpBase<double> > blkOp =
239 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(getThyraOp());
240
241 return blkOp->productDomain()->numBlocks();
242}
243
244Teuchos::RCP<const Epetra_Operator> EpetraOperatorWrapper::GetBlock(int i, int j) const {
245 const RCP<const Thyra::BlockedLinearOpBase<double> > blkOp =
246 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(getThyraOp());
247
248 return Thyra::get_Epetra_Operator(*blkOp->getBlock(i, j));
249}
250
251} // namespace Epetra
252} // namespace Teko
RCP< const Thyra::VectorSpaceBase< double > > rangeSpace_
Range space object.
RCP< const Epetra_Map > domainMap_
Pointer to the constructed domain map.
RCP< const Thyra::VectorSpaceBase< double > > domainSpace_
Domain space object.
RCP< const Epetra_Map > rangeMap_
Pointer to the constructed range map.
virtual void copyEpetraIntoThyra(const Epetra_MultiVector &epetraX, const Teuchos::Ptr< Thyra::MultiVectorBase< double > > &thyraX) const
Copy an Epetra_MultiVector into a Thyra::MultiVectorBase.
virtual void copyThyraIntoEpetra(const RCP< const Thyra::MultiVectorBase< double > > &thyraX, Epetra_MultiVector &epetraX) const
Copy an Thyra::MultiVectorBase into a Epetra_MultiVector.
Teuchos::RCP< const Epetra_Operator > GetBlock(int i, int j) const
Grab the i,j block.
virtual int GetBlockRowCount()
Get the number of block rows in this operator.
virtual int GetBlockColCount()
Get the number of block columns in this operator.
const RCP< const Thyra::LinearOpBase< double > > getThyraOp() const
Return the thyra operator associated with this wrapper.