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