Xpetra Version of the Day
Loading...
Searching...
No Matches
Xpetra_ThyraUtils.hpp
Go to the documentation of this file.
1// @HEADER
2//
3// ***********************************************************************
4//
5// Xpetra: A linear algebra interface package
6// Copyright 2012 Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact
39// Jonathan Hu (jhu@sandia.gov)
40// Andrey Prokopenko (aprokop@sandia.gov)
41// Ray Tuminaro (rstumin@sandia.gov)
42// Tobias Wiesner (tawiesn@sandia.gov)
43//
44// ***********************************************************************
45//
46// @HEADER
47#ifndef XPETRA_THYRAUTILS_HPP
48#define XPETRA_THYRAUTILS_HPP
49
50#include "Xpetra_ConfigDefs.hpp"
51#ifdef HAVE_XPETRA_THYRA
52
53#include <typeinfo>
54
55#ifdef HAVE_XPETRA_TPETRA
56#include "Tpetra_ConfigDefs.hpp"
57#endif
58
59#ifdef HAVE_XPETRA_EPETRA
60#include "Epetra_config.h"
61#include "Epetra_CombineMode.h"
62#endif
63
64#include "Xpetra_Map.hpp"
65#include "Xpetra_BlockedMap.hpp"
66#include "Xpetra_BlockedMultiVector.hpp"
68#include "Xpetra_MapUtils.hpp"
69#include "Xpetra_StridedMap.hpp"
70#include "Xpetra_StridedMapFactory.hpp"
71#include "Xpetra_MapExtractor.hpp"
72#include "Xpetra_Matrix.hpp"
74#include "Xpetra_CrsMatrixWrap.hpp"
75#include "Xpetra_MultiVectorFactory.hpp"
76
77#include <Thyra_VectorSpaceBase.hpp>
78#include <Thyra_SpmdVectorSpaceBase.hpp>
79#include <Thyra_ProductVectorSpaceBase.hpp>
80#include <Thyra_ProductMultiVectorBase.hpp>
81#include <Thyra_VectorSpaceBase.hpp>
82#include <Thyra_DefaultProductVectorSpace.hpp>
83#include <Thyra_DefaultBlockedLinearOp.hpp>
84#include <Thyra_LinearOpBase.hpp>
85#include "Thyra_DiagonalLinearOpBase.hpp"
86#include <Thyra_DetachedMultiVectorView.hpp>
87#include <Thyra_MultiVectorStdOps.hpp>
88
89#ifdef HAVE_XPETRA_TPETRA
90#include <Thyra_TpetraThyraWrappers.hpp>
91#include <Thyra_TpetraVector.hpp>
92#include <Thyra_TpetraMultiVector.hpp>
93#include <Thyra_TpetraVectorSpace.hpp>
94#include <Tpetra_Map.hpp>
95#include <Tpetra_Vector.hpp>
96#include <Tpetra_CrsMatrix.hpp>
97#include <Xpetra_TpetraMap.hpp>
99#include <Xpetra_TpetraCrsMatrix.hpp>
100#endif
101#ifdef HAVE_XPETRA_EPETRA
102#include <Thyra_EpetraLinearOp.hpp>
103#include <Thyra_EpetraThyraWrappers.hpp>
104#include <Thyra_SpmdVectorBase.hpp>
105#include <Thyra_get_Epetra_Operator.hpp>
106#include <Epetra_Map.h>
107#include <Epetra_Vector.h>
108#include <Epetra_CrsMatrix.h>
109#include <Xpetra_EpetraMap.hpp>
111#endif
112
113namespace Xpetra {
114
115template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node> class BlockedCrsMatrix;
116
117template <class Scalar,
118class LocalOrdinal = int,
119class GlobalOrdinal = LocalOrdinal,
120class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
121class ThyraUtils {
122
123private:
124#undef XPETRA_THYRAUTILS_SHORT
126
127public:
128 static Teuchos::RCP<Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> >
129 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm, std::vector<size_t>& stridingInfo, LocalOrdinal stridedBlockId = -1, GlobalOrdinal offset = 0) {
130
131 Teuchos::RCP<Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map = toXpetra(vectorSpace);
132
133 if(stridedBlockId == -1) {
134 TEUCHOS_TEST_FOR_EXCEPT(map->getLocalNumElements() % stridingInfo.size() != 0);
135 }
136 else {
137 TEUCHOS_TEST_FOR_EXCEPT(map->getLocalNumElements() % stridingInfo[stridedBlockId] != 0);
138 }
139
140 Teuchos::RCP<Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> > ret = Xpetra::StridedMapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(map, stridingInfo, stridedBlockId, offset);
141 return ret;
142 }
143
144 static Teuchos::RCP<Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
145 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
146 using Teuchos::RCP;
147 using Teuchos::rcp_dynamic_cast;
148 using Teuchos::as;
149 using ThyVecSpaceBase = Thyra::VectorSpaceBase<Scalar>;
150 using ThyProdVecSpaceBase = Thyra::ProductVectorSpaceBase<Scalar>;
151 using ThyUtils = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
152
153
154 RCP<Map> resultMap = Teuchos::null;
155 RCP<const ThyProdVecSpaceBase > prodVectorSpace = rcp_dynamic_cast<const ThyProdVecSpaceBase >(vectorSpace);
156 if(prodVectorSpace != Teuchos::null) {
157 // SPECIAL CASE: product Vector space
158 // collect all submaps to store them in a hierarchical BlockedMap object
159 TEUCHOS_TEST_FOR_EXCEPTION(prodVectorSpace->numBlocks()==0, std::logic_error, "Found a product vector space with zero blocks.");
160 std::vector<RCP<const Map> > mapsThyra(prodVectorSpace->numBlocks(), Teuchos::null);
161 std::vector<RCP<const Map> > mapsXpetra(prodVectorSpace->numBlocks(), Teuchos::null);
162 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
163 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
164 // can be of type Map or BlockedMap (containing Thyra GIDs)
165 mapsThyra[b] = ThyUtils::toXpetra(bv, comm); // recursive call
166 }
167
168 // get offsets for submap GIDs
169 // we need that for the full map (Xpetra GIDs)
170 std::vector<GlobalOrdinal> gidOffsets(prodVectorSpace->numBlocks(),0);
171 for(int i = 1; i < prodVectorSpace->numBlocks(); ++i) {
172 gidOffsets[i] = mapsThyra[i-1]->getMaxAllGlobalIndex() + gidOffsets[i-1] + 1;
173 }
174
175 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
176 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
177 // map can be of type Map or BlockedMap (containing Xpetra style GIDs)
178 mapsXpetra[b] = MapUtils::transformThyra2XpetraGIDs(*mapsThyra[b], gidOffsets[b]);
179 }
180
181 resultMap = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node>(mapsXpetra, mapsThyra));
182 } else {
183#ifdef HAVE_XPETRA_TPETRA
184 // STANDARD CASE: no product map
185 // check whether we have a Tpetra based Thyra operator
186 Teuchos::RCP<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_vsc = Teuchos::rcp_dynamic_cast<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(vectorSpace);
187 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::is_null(tpetra_vsc)==true, Xpetra::Exceptions::RuntimeError, "toXpetra failed to convert provided vector space to Thyra::TpetraVectorSpace. This is the general implementation for Tpetra only.");
188
189 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
190 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
191 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
192 typedef Thyra::VectorBase<Scalar> ThyVecBase;
193 RCP<ThyVecBase> rgVec = Thyra::createMember<Scalar>(vectorSpace, std::string("label"));
195 RCP<const TpVector> rgTpetraVec = TOE::getTpetraVector(rgVec);
197 RCP<const TpMap> rgTpetraMap = rgTpetraVec->getMap();
199 resultMap = Xpetra::toXpetraNonConst(rgTpetraMap);
200#else
201 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "Cannot transform Thyra::VectorSpace to Xpetra::Map. This is the general implementation for Tpetra only, but Tpetra is disabled.");
202#endif
203 } // end standard case (no product map)
205 return resultMap;
206 }
207
208 // const version
209 static Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
210 toXpetra(Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
211 using Teuchos::RCP;
212 using Teuchos::rcp_dynamic_cast;
213 using Teuchos::as;
214
215 using ThyMultVecBase = Thyra::MultiVectorBase<Scalar>;
216 using ThyProdMultVecBase = Thyra::ProductMultiVectorBase<Scalar>;
217 using ThyUtils = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
218
219 // return value
220 RCP<MultiVector> xpMultVec = Teuchos::null;
221
222 // check whether v is a product multi vector
223 Teuchos::RCP<const ThyProdMultVecBase> thyProdVec = rcp_dynamic_cast<const ThyProdMultVecBase >(v);
224 if(thyProdVec != Teuchos::null) {
225 // SPECIAL CASE: create a nested BlockedMultiVector
226 // generate nested BlockedMap (containing Thyra and Xpetra GIDs)
227 RCP<Map> fullMap = ThyUtils::toXpetra(v->range(), comm);
228 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(Teuchos::rcp_dynamic_cast<BlockedMap>(fullMap)));
229
230 // create new Xpetra::BlockedMultiVector
231 xpMultVec = MultiVectorFactory::Build(fullMap, as<size_t>(thyProdVec->domain()->dim()));
232
233 RCP<BlockedMultiVector> xpBlockedMultVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xpMultVec, true);
234
235 // loop over all blocks, transform Thyra MultiVectors to Xpetra MultiVectors recursively
236 for (int b = 0; b < thyProdVec->productSpace()->numBlocks(); ++b){
237 RCP<const ThyMultVecBase> thyBlockMV = thyProdVec->getMultiVectorBlock(b);
238 // xpBlockMV can be of type MultiVector or BlockedMultiVector
239 RCP<const MultiVector> xpBlockMV = ThyUtils::toXpetra(thyBlockMV, comm); //recursive call
240 xpBlockedMultVec->setMultiVector(b, xpBlockMV, true /* Thyra mode */);
241 }
242 } else {
243 // STANDARD CASE: no product vector
244#ifdef HAVE_XPETRA_TPETRA
245 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> ConverterT;
246 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpMultVec;
247 typedef Xpetra::TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpTpMultVec;
248 typedef Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyTpMultVec;
249 typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
250
251 RCP<const ThySpmdMultVecBase> thyraSpmdMultiVector = rcp_dynamic_cast<const ThySpmdMultVecBase>(v);
252 RCP<const ThyTpMultVec> thyraTpetraMultiVector = rcp_dynamic_cast<const ThyTpMultVec>(thyraSpmdMultiVector);
253 TEUCHOS_TEST_FOR_EXCEPTION(thyraTpetraMultiVector == Teuchos::null, Xpetra::Exceptions::RuntimeError, "toXpetra failed to convert provided multi vector to Thyra::TpetraMultiVector. This is the general implementation for Tpetra only.");
254 const RCP<const TpMultVec> tpMultVec = ConverterT::getConstTpetraMultiVector(v);
256 RCP<TpMultVec> tpNonConstMultVec = Teuchos::rcp_const_cast<TpMultVec>(tpMultVec);
257 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpNonConstMultVec));
258 xpMultVec = rcp(new XpTpMultVec(tpNonConstMultVec));
259#else
260 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "Cannot transform Thyra::MultiVector to Xpetra::MultiVector. This is the general implementation for Tpetra only, but Teptra is disabled.");
261#endif
262 } // end standard case
264 return xpMultVec;
265 }
266
267 // non-const version
268 static Teuchos::RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
269 toXpetra(Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
270 Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > cv =
271 Teuchos::rcp_const_cast<const Thyra::MultiVectorBase<Scalar> >(v);
272 Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > r =
273 toXpetra(cv,comm);
274 return Teuchos::rcp_const_cast<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(r);
275 }
276
277
278 static bool isTpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
280
281 // check whether we have a Tpetra based Thyra operator
282 bool bIsTpetra = false;
283#ifdef HAVE_XPETRA_TPETRA
284 Teuchos::RCP<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_op = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(op);
285 bIsTpetra = Teuchos::is_null(tpetra_op) ? false : true;
286
287 // for debugging purposes: find out why dynamic cast failed
288 if(!bIsTpetra &&
289#ifdef HAVE_XPETRA_EPETRA
290 Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op) == Teuchos::null &&
291#endif
292 Teuchos::rcp_dynamic_cast<const Thyra::DefaultBlockedLinearOp<Scalar> >(op) == Teuchos::null) {
293 // If op is not blocked and not an Epetra object, it should be in fact an Tpetra object
294 typedef Thyra::TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> TpetraLinearOp_t;
295 if(Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op) == Teuchos::null) {
296 std::cout << "ATTENTION: The dynamic cast to the TpetraLinearOp failed even though it should be a TpetraLinearOp." << std::endl;
297 std::cout << " If you are using Panzer or Stratimikos you might check that the template parameters are " << std::endl;
298 std::cout << " properly set!" << std::endl;
299 std::cout << Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op, true) << std::endl;
300 }
301 }
302#endif
303
304#if 0
305 // Check whether it is a blocked operator.
306 // If yes, grab the (0,0) block and check the underlying linear algebra
307 // Note: we expect that the (0,0) block exists!
308 if(bIsTpetra == false) {
309 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
310 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
311 if(ThyBlockedOp != Teuchos::null) {
312 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
313 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > b00 =
314 ThyBlockedOp->getBlock(0,0);
316 bIsTpetra = isTpetra(b00);
317 }
318 }
319#endif
320
321 return bIsTpetra;
322 }
323
324 static bool isEpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
325 return false;
326 }
327
328 static bool isBlockedOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
329 // Check whether it is a blocked operator.
330 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
331 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
332 if(ThyBlockedOp != Teuchos::null) {
333 return true;
334 }
335 return false;
336 }
337
338 static Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
339 toXpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
340
341#ifdef HAVE_XPETRA_TPETRA
342 if(isTpetra(op)) {
343 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
344 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
345 // we should also add support for the const versions!
346 //getConstTpetraOperator(const RCP<const LinearOpBase<Scalar> > &op);
348 Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp, true);
349 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat, true);
350 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraNcnstCrsMat = Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraCrsMat);
351 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(TpetraNcnstCrsMat));
352
353 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraCrsMat =
354 Teuchos::rcp(new Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraNcnstCrsMat));
356
357 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
358 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat, true);
359 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
360 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
361 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
362 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
363 return xpMat;
364 }
365#endif
366
367#ifdef HAVE_XPETRA_EPETRA
368 if(isEpetra(op)) {
369 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
370 }
371#endif
372 return Teuchos::null;
373 }
374
375 static Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
376 toXpetra(const Teuchos::RCP<Thyra::LinearOpBase<Scalar>>& op) {
377
378 using Teuchos::RCP;
379 using Teuchos::rcp;
380 using Teuchos::rcp_const_cast;
381 using Teuchos::rcp_dynamic_cast;
382
383#ifdef HAVE_XPETRA_TPETRA
384 if(isTpetra(op)) {
385 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
386 typedef Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpetraOperator_t;
387 RCP<const TpetraOperator_t> TpetraOp = TOE::getConstTpetraOperator(op);
389 RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>> TpetraRowMat =
390 rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>>(TpetraOp, true);
391 RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>> TpetraCrsMat =
392 rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>>(TpetraRowMat, true);
393
394 RCP<Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>> xTpetraCrsMat =
395 rcp(new Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(
396 rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>>(TpetraCrsMat)
397 ));
398 TEUCHOS_TEST_FOR_EXCEPT(is_null(xTpetraCrsMat));
399 RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> xpCrsMat =
400 rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(xTpetraCrsMat, true);
401 RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> xpCrsWrap =
402 rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
403 RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> xpMat =
404 rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(xpCrsWrap, true);
405 return xpMat;
406 }
407#endif
408
409#ifdef HAVE_XPETRA_EPETRA
410 if(isEpetra(op)) {
411 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
412 }
413#endif
414 return Teuchos::null;
415 }
416
417 static Teuchos::RCP<const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
418 toXpetraOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
419
420#ifdef HAVE_XPETRA_TPETRA
421 if(isTpetra(op)) {
422 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
423 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
424
425 Teuchos::RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraOp =
426 Teuchos::rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraOp));
428
429 Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpOp =
430 Teuchos::rcp_dynamic_cast<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraOp, true);
431 return xpOp;
432 }
433#endif
434
435#ifdef HAVE_XPETRA_EPETRA
436 if(isEpetra(op)) {
437 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
438 }
439#endif
440 return Teuchos::null;
441 }
442
443 static Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
444 toXpetraOperator(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
445
446#ifdef HAVE_XPETRA_TPETRA
447 if(isTpetra(op)) {
448 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
449 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
450
451 Teuchos::RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraOp =
452 Teuchos::rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraOp));
454
455 Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpOp =
456 Teuchos::rcp_dynamic_cast<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraOp, true);
457 return xpOp;
458 }
459#endif
460
461#ifdef HAVE_XPETRA_EPETRA
462 if(isEpetra(op)) {
463 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
464 }
465#endif
466 return Teuchos::null;
467 }
468
469 static Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
470 toXpetra(const Teuchos::RCP<Thyra::DiagonalLinearOpBase<Scalar> >& op) {
471 using Teuchos::rcp_dynamic_cast;
472 using Teuchos::rcp_const_cast;
473
474 RCP<const Thyra::VectorBase<Scalar> > diag = op->getDiag();
475
476 RCP<const Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xpDiag;
477#ifdef HAVE_XPETRA_TPETRA
478 using thyTpV = Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
479 using tV = Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
480 if (!rcp_dynamic_cast<const thyTpV>(diag).is_null()) {
481 RCP<const tV> tDiag = Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(diag);
482 if (!tDiag.is_null())
483 xpDiag = Xpetra::toXpetra(tDiag);
484 }
485#endif
486 TEUCHOS_ASSERT(!xpDiag.is_null());
487 RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > M = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(xpDiag);
488 return M;
489 }
490
491 static Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
492 toXpetra(const Teuchos::RCP<const Thyra::DiagonalLinearOpBase<Scalar> >& op) {
493 return toXpetra(Teuchos::rcp_const_cast<Thyra::DiagonalLinearOpBase<Scalar> >(op));
494 }
495
496 static Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
497 toThyra(Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map) {
498 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyraMap = Teuchos::null;
499
500 // check whether map is of type BlockedMap
501 RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
502 if(bmap.is_null() == false) {
503
504 Teuchos::Array<Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > > vecSpaces(bmap->getNumMaps());
505 for(size_t i = 0; i < bmap->getNumMaps(); i++) {
506 // we need Thyra GIDs for all the submaps
507 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > vs =
508 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(bmap->getMap(i,true));
509 vecSpaces[i] = vs;
510 }
511
512 thyraMap = Thyra::productVectorSpace<Scalar>(vecSpaces());
513 return thyraMap;
514 }
515
516 // standard case
517#ifdef HAVE_XPETRA_TPETRA
518 if(map->lib() == Xpetra::UseTpetra) {
519 Teuchos::RCP<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> > tpetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> >(map);
520 if (tpetraMap == Teuchos::null)
521 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::TpetraMap failed");
522 RCP<Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > thyraTpetraMap = Thyra::tpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, Node>(tpetraMap->getTpetra_Map());
523 thyraMap = thyraTpetraMap;
524 }
525#endif
526
527#ifdef HAVE_XPETRA_EPETRA
528 if(map->lib() == Xpetra::UseEpetra) {
529 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
530 }
531#endif
532
533 return thyraMap;
534 }
535
536 static Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> >
537 toThyraMultiVector(Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > vec) {
538
539 // create Thyra MultiVector
540#ifdef HAVE_XPETRA_TPETRA
541 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
542 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
543 RCP<Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpMV = Teuchos::rcp_dynamic_cast<const TpetraMultiVector>(vec)->getTpetra_MultiVector();
544 auto thyDomMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(vec->getNumVectors(), vec->getMap()->getComm()));
545 auto thyMV = rcp(new Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
546 thyMV->initialize(thyTpMap, thyDomMap, tpMV);
547 return thyMV;
548 }
549#endif
550
551#ifdef HAVE_XPETRA_EPETRA
552 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
553 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
554 }
555#endif
556
557 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "MultiVector cannot be converted to Thyra.");
558 }
559
560 static Teuchos::RCP<const Thyra::VectorBase<Scalar> >
561 toThyraVector(Teuchos::RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > vec) {
562
563 // create Thyra Vector
564#ifdef HAVE_XPETRA_TPETRA
565 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
566 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
567 RCP<Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpVec = Teuchos::rcp_dynamic_cast<const TpetraVector>(vec)->getTpetra_Vector();
568 auto thyVec = rcp(new Thyra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
569 thyVec->initialize(thyTpMap, tpVec);
570 return thyVec;
571 }
572#endif
573
574#ifdef HAVE_XPETRA_EPETRA
575 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
576 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
577 }
578#endif
579
580 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Vector cannot be converted to Thyra.");
581 }
582
583 // update Thyra multi vector with data from Xpetra multi vector
584 // In case of a Thyra::ProductMultiVector the Xpetra::MultiVector is splitted into its subparts using a provided MapExtractor
585 static void
586 updateThyra(Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > source, Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal,Node> > mapExtractor, const Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > & target) {
587 using Teuchos::RCP;
588 using Teuchos::rcp_dynamic_cast;
589 using Teuchos::as;
590 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
591 typedef Thyra::SpmdVectorSpaceBase<Scalar> ThySpmdVecSpaceBase;
592 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
593 //typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
594 //typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
595 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
596
597
598 // copy data from tY_inout to Y_inout
599 RCP<ThyProdMultVecBase> prodTarget = rcp_dynamic_cast<ThyProdMultVecBase>(target);
600 if(prodTarget != Teuchos::null) {
601 RCP<const BlockedMultiVector> bSourceVec = rcp_dynamic_cast<const BlockedMultiVector>(source);
602 if(bSourceVec.is_null() == true) {
603 // SPECIAL CASE: target vector is product vector:
604 // update Thyra product multi vector with data from a merged Xpetra multi vector
605
606 TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor == Teuchos::null, std::logic_error, "Found a Thyra product vector, but user did not provide an Xpetra::MapExtractor.");
607 TEUCHOS_TEST_FOR_EXCEPTION(prodTarget->productSpace()->numBlocks() != as<int>(mapExtractor->NumMaps()), std::logic_error, "Inconsistent numbers of sub maps in Thyra::ProductVectorSpace and Xpetra::MapExtractor.");
608
609 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
610 // access Xpetra data
611 RCP<MultiVector> xpSubBlock = mapExtractor->ExtractVector(source, bbb, false); // use Xpetra ordering (doesn't really matter)
612
613 // access Thyra data
614 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
615 RCP<const ThyVecSpaceBase> vs = thySubBlock->range();
616 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(vs);
617 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
618 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : vs->dim() );
619 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
620 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*thySubBlock,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
621
622 // loop over all vectors in multivector
623 for(size_t j = 0; j < xpSubBlock->getNumVectors(); ++j) {
624 Teuchos::ArrayRCP< const Scalar > xpData = xpSubBlock->getData(j); // access const data from Xpetra object
625
626 // loop over all local rows
627 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
628 (*thyData)(i,j) = xpData[i];
629 }
630 }
631 }
632 } else {
633 // source vector is a blocked multivector
634 // TODO test me
635 TEUCHOS_TEST_FOR_EXCEPTION(prodTarget->productSpace()->numBlocks() != as<int>(bSourceVec->getBlockedMap()->getNumMaps()), std::logic_error, "Inconsistent numbers of sub maps in Thyra::ProductVectorSpace and Xpetra::BlockedMultiVector.");
636
637 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
638 // access Thyra data
639 RCP<MultiVector> xpSubBlock = bSourceVec->getMultiVector(bbb, true); // use Thyra ordering
640
641 Teuchos::RCP<const ThyMultVecBase> thyXpSubBlock = toThyraMultiVector(xpSubBlock);
642
643 // access Thyra data
644 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
645 Thyra::assign(thySubBlock.ptr(), *thyXpSubBlock);
646 }
647
648 }
649 } else {
650 // STANDARD case:
651 // update Thyra::MultiVector with data from an Xpetra::MultiVector
652
653 // access Thyra data
654 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(target->range());
655 TEUCHOS_TEST_FOR_EXCEPTION(mpi_vs == Teuchos::null, std::logic_error, "Failed to cast Thyra::VectorSpaceBase to Thyra::SpmdVectorSpaceBase.");
656 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
657 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : target->range()->dim() );
658 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
659 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*target,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
660
661 // loop over all vectors in multivector
662 for(size_t j = 0; j < source->getNumVectors(); ++j) {
663 Teuchos::ArrayRCP< const Scalar > xpData = source->getData(j); // access const data from Xpetra object
664 // loop over all local rows
665 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
666 (*thyData)(i,j) = xpData[i];
667 }
668 }
669 }
670 }
671
672 static Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
673 toThyra(const Teuchos::RCP<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
674 // create a Thyra operator from Xpetra::CrsMatrix
675 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
676
677 //bool bIsTpetra = false;
678
679#ifdef HAVE_XPETRA_TPETRA
680 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
681 if(tpetraMat!=Teuchos::null) {
682 //bIsTpetra = true;
683 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat, true);
684 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrix();
686
687 Teuchos::RCP<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat, true);
688 Teuchos::RCP<const Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<const Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat, true);
689
690 thyraOp = Thyra::createConstLinearOp(tpOperator);
692 } else {
693#ifdef HAVE_XPETRA_EPETRA
694 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to Tpetra::CrsMatrix failed. Assume matrix should be Epetra then. Epetra needs SC=double, LO=int, and GO=int or GO=long long");
695#else
696 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to Tpetra::CrsMatrix failed. Assume matrix should be Epetra then. No Epetra available");
697#endif
698 }
699 return thyraOp;
700#else
701 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
702 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
703#endif
704 }
705
706 static Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
707 toThyra(const Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
708 // create a Thyra operator from Xpetra::CrsMatrix
709 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
710
711 //bool bIsTpetra = false;
712
713#ifdef HAVE_XPETRA_TPETRA
714 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
715 if(tpetraMat!=Teuchos::null) {
716 //bIsTpetra = true;
717 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat, true);
718 Teuchos::RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrixNonConst();
720
721 Teuchos::RCP<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat, true);
722 Teuchos::RCP<Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat, true);
723
724 thyraOp = Thyra::createLinearOp(tpOperator);
726 } else {
727 // cast to TpetraCrsMatrix failed
728#ifdef HAVE_XPETRA_EPETRA
729 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to TpetraCrsMatrix failed. Assuming matrix supposed to be Epetra. Epetra needs SC=double, LO=int, and GO=int or GO=long long");
730#else
731 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to TpetraCrsMatrix failed. Guess, matrix should be Epetra then, but no Epetra available.");
732#endif
733 }
734 return thyraOp;
735#else
736 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
737 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
738#endif
739 }
740
741 static Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
742 toThyra(const Teuchos::RCP<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
743
744 int nRows = mat->Rows();
745 int nCols = mat->Cols();
746
747 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Ablock = mat->getInnermostCrsMatrix();
748 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Ablock_wrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(Ablock);
749 TEUCHOS_TEST_FOR_EXCEPT(Ablock_wrap.is_null() == true);
750
751#ifdef HAVE_XPETRA_TPETRA
752 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(Ablock_wrap->getCrsMatrix());
753 if(tpetraMat!=Teuchos::null) {
754
755 // create new Thyra blocked operator
756 Teuchos::RCP<Thyra::PhysicallyBlockedLinearOpBase<Scalar> > blockMat =
757 Thyra::defaultBlockedLinearOp<Scalar>();
758
759 blockMat->beginBlockFill(nRows,nCols);
760
761 for (int r=0; r<nRows; ++r) {
762 for (int c=0; c<nCols; ++c) {
763 Teuchos::RCP<Matrix> xpmat = mat->getMatrix(r,c);
764
765 if(xpmat == Teuchos::null) continue; // shortcut for empty blocks
766
767 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thBlock = Teuchos::null;
768
769 // check whether the subblock is again a blocked operator
770 Teuchos::RCP<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpblock =
771 Teuchos::rcp_dynamic_cast<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpmat);
772 if(xpblock != Teuchos::null) {
773 if(xpblock->Rows() == 1 && xpblock->Cols() == 1) {
774 // If it is a single block operator, unwrap it
775 Teuchos::RCP<CrsMatrixWrap> xpwrap = Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(xpblock->getCrsMatrix());
776 TEUCHOS_TEST_FOR_EXCEPT(xpwrap.is_null() == true);
777 thBlock = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpwrap->getCrsMatrix());
778 } else {
779 // recursive call for general blocked operators
780 thBlock = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpblock);
781 }
782 } else {
783 // check whether it is a CRSMatrix object
784 Teuchos::RCP<CrsMatrixWrap> xpwrap = Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(xpmat);
785 TEUCHOS_TEST_FOR_EXCEPT(xpwrap.is_null() == true);
786 thBlock = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpwrap->getCrsMatrix());
787 }
788
789 blockMat->setBlock(r,c,thBlock);
790 }
791 }
792
793 blockMat->endBlockFill();
794
795 return blockMat;
796 } else {
797 // tpetraMat == Teuchos::null
798#ifdef HAVE_XPETRA_EPETRA
799 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to TpetraCrsMatrix failed. Assuming matrix supposed to be Epetra. Epetra needs SC=double, LO=int, and GO=int or GO=long long");
800#else
801 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to TpetraCrsMatrix failed. Guess, matrix should be Epetra then, but no Epetra available.");
802#endif
803 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
804 }
805#endif // endif HAVE_XPETRA_TPETRA
806
807//4-Aug-2017 JJH Added 2nd condition to avoid "warning: dynamic initialization in unreachable code"
808// If HAVE_XPETRA_TPETRA is defined, then this method will always return or throw in the if-then-else above.
809#if defined(HAVE_XPETRA_EPETRA) && !defined(HAVE_XPETRA_TPETRA)
810 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
811 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
812#endif // endif HAVE_XPETRA_EPETRA
813 }
814
815}; // end Utils class
816
817
818// full specialization for Epetra support
819// Note, that Thyra only has support for Epetra (not for Epetra64)
820#ifdef HAVE_XPETRA_EPETRA
821
822#ifndef XPETRA_EPETRA_NO_32BIT_GLOBAL_INDICES
823template <>
824class ThyraUtils<double, int, int, EpetraNode> {
825public:
826 typedef double Scalar;
827 typedef int LocalOrdinal;
828 typedef int GlobalOrdinal;
829 typedef EpetraNode Node;
830
831private:
832#undef XPETRA_THYRAUTILS_SHORT
834
835public:
836
837 static Teuchos::RCP<Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> >
838 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm, std::vector<size_t>& stridingInfo, LocalOrdinal stridedBlockId = -1, GlobalOrdinal offset = 0) {
839
840 Teuchos::RCP<Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map = ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toXpetra(vectorSpace,comm);
841
842 if(stridedBlockId == -1) {
843 TEUCHOS_TEST_FOR_EXCEPT(map->getLocalNumElements() % stridingInfo.size() != 0);
844 }
845 else {
846 TEUCHOS_TEST_FOR_EXCEPT(map->getLocalNumElements() % stridingInfo[stridedBlockId] != 0);
847 }
848
849 Teuchos::RCP<Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> > ret = Xpetra::StridedMapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(map, stridingInfo, stridedBlockId, offset);
850 return ret;
851 }
852
853 static Teuchos::RCP<Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
854 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
855 using Teuchos::RCP;
856 using Teuchos::rcp_dynamic_cast;
857 using Teuchos::as;
858 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
859 typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
860 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyUtils;
861
862 RCP<Map> resultMap = Teuchos::null;
863
864 RCP<const ThyProdVecSpaceBase > prodVectorSpace = rcp_dynamic_cast<const ThyProdVecSpaceBase >(vectorSpace);
865 if(prodVectorSpace != Teuchos::null) {
866 // SPECIAL CASE: product Vector space
867 // collect all submaps to store them in a hierarchical BlockedMap object
868 TEUCHOS_TEST_FOR_EXCEPTION(prodVectorSpace->numBlocks()==0, std::logic_error, "Found a product vector space with zero blocks.");
869 std::vector<RCP<const Map> > mapsThyra(prodVectorSpace->numBlocks(), Teuchos::null);
870 std::vector<RCP<const Map> > mapsXpetra(prodVectorSpace->numBlocks(), Teuchos::null);
871 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
872 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
873 // can be of type Map or BlockedMap (containing Thyra GIDs)
874 mapsThyra[b] = ThyUtils::toXpetra(bv, comm); // recursive call
875 }
876
877 // get offsets for submap GIDs
878 // we need that for the full map (Xpetra GIDs)
879 std::vector<GlobalOrdinal> gidOffsets(prodVectorSpace->numBlocks(),0);
880 for(int i = 1; i < prodVectorSpace->numBlocks(); ++i) {
881 gidOffsets[i] = mapsThyra[i-1]->getMaxAllGlobalIndex() + gidOffsets[i-1] + 1;
882 }
883
884 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
885 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
886 // map can be of type Map or BlockedMap (containing Xpetra style GIDs)
887 mapsXpetra[b] = MapUtils::transformThyra2XpetraGIDs(*mapsThyra[b], gidOffsets[b]);
888 }
889
890 resultMap = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node>(mapsXpetra, mapsThyra));
891 } else {
892 // STANDARD CASE: no product map
893 // Epetra/Tpetra specific code to access the underlying map data
894
895 // check whether we have a Tpetra based Thyra operator
896 bool bIsTpetra = false;
897#ifdef HAVE_XPETRA_TPETRA
898#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
899 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
900 Teuchos::RCP<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_vsc = Teuchos::rcp_dynamic_cast<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(vectorSpace);
901 bIsTpetra = Teuchos::is_null(tpetra_vsc) ? false : true;
902#endif
903#endif
904
905 // check whether we have an Epetra based Thyra operator
906 bool bIsEpetra = !bIsTpetra; // note: this is a little bit fragile!
907
908#ifdef HAVE_XPETRA_TPETRA
909 if(bIsTpetra) {
910#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
911 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
912 typedef Thyra::VectorBase<Scalar> ThyVecBase;
913 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
914 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
915 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
916 RCP<ThyVecBase> rgVec = Thyra::createMember<Scalar>(vectorSpace, std::string("label"));
918 RCP<const TpVector> rgTpetraVec = TOE::getTpetraVector(rgVec);
920 RCP<const TpMap> rgTpetraMap = rgTpetraVec->getMap();
922
923 resultMap = Xpetra::toXpetraNonConst(rgTpetraMap);
924#else
925 throw Xpetra::Exceptions::RuntimeError("Problem AAA. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
926#endif
927 }
928#endif
929
930#ifdef HAVE_XPETRA_EPETRA
931 if(bIsEpetra) {
932 //RCP<const Epetra_Map> epMap = Teuchos::null;
933 RCP<const Epetra_Map>
934 epetra_map = Teuchos::get_extra_data<RCP<const Epetra_Map> >(vectorSpace,"epetra_map");
935 if(!Teuchos::is_null(epetra_map)) {
936 resultMap = Teuchos::rcp(new Xpetra::EpetraMapT<GlobalOrdinal,Node>(epetra_map));
938 } else {
939 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "No Epetra_Map data found in Thyra::VectorSpace.");
940 }
941 }
942#endif
943 } // end standard case (no product map)
945 return resultMap;
946 }
947
948 // const version
949 static Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
950 toXpetra(Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
951 using Teuchos::RCP;
952 using Teuchos::rcp_dynamic_cast;
953 using Teuchos::as;
954
955 using ThyProdMultVecBase = Thyra::ProductMultiVectorBase<Scalar>;
956 using ThyMultVecBase = Thyra::MultiVectorBase<Scalar>;
957 using ThyUtils = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
958
959 // return value
960 RCP<MultiVector> xpMultVec = Teuchos::null;
961
962 // check whether v is a product multi vector
963 Teuchos::RCP<const ThyProdMultVecBase> thyProdVec = rcp_dynamic_cast<const ThyProdMultVecBase >(v);
964 if(thyProdVec != Teuchos::null) {
965 // SPECIAL CASE: create a nested BlockedMultiVector
966 // generate nested BlockedMap (containing Thyra and Xpetra GIDs)
967 RCP<Map> fullMap = ThyUtils::toXpetra(v->range(), comm);
968 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(Teuchos::rcp_dynamic_cast<BlockedMap>(fullMap)));
969
970 // create new Xpetra::BlockedMultiVector
971 xpMultVec = MultiVectorFactory::Build(fullMap, as<size_t>(thyProdVec->domain()->dim()));
972
973 RCP<BlockedMultiVector> xpBlockedMultVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xpMultVec, true);
974
975 // loop over all blocks, transform Thyra MultiVectors to Xpetra MultiVectors recursively
976 for (int b = 0; b < thyProdVec->productSpace()->numBlocks(); ++b){
977 RCP<const ThyMultVecBase> thyBlockMV = thyProdVec->getMultiVectorBlock(b);
978 // xpBlockMV can be of type MultiVector or BlockedMultiVector
979 RCP<const MultiVector> xpBlockMV = ThyUtils::toXpetra(thyBlockMV, comm); //recursive call
980 xpBlockedMultVec->setMultiVector(b, xpBlockMV, true /* Thyra mode */);
981 }
982
984 return xpMultVec;
985 } else {
986 // STANDARD CASE: no product vector
987 // Epetra/Tpetra specific code to access the underlying map data
988 bool bIsTpetra = false;
989#ifdef HAVE_XPETRA_TPETRA
990#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
991 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
992
993 //typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
994 //typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
995 typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
996 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> ConverterT;
997 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpMultVec;
998 typedef Xpetra::TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpTpMultVec;
999 typedef Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyTpMultVec;
1000
1001 RCP<const ThySpmdMultVecBase> thyraSpmdMultiVector = rcp_dynamic_cast<const ThySpmdMultVecBase>(v);
1002 RCP<const ThyTpMultVec> thyraTpetraMultiVector = rcp_dynamic_cast<const ThyTpMultVec>(thyraSpmdMultiVector);
1003 if(thyraTpetraMultiVector != Teuchos::null) {
1004 bIsTpetra = true;
1005 const RCP<const TpMultVec> tpMultVec = ConverterT::getConstTpetraMultiVector(v);
1007 RCP<TpMultVec> tpNonConstMultVec = Teuchos::rcp_const_cast<TpMultVec>(tpMultVec);
1008 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpNonConstMultVec));
1009 xpMultVec = rcp(new XpTpMultVec(tpNonConstMultVec));
1010 }
1011#endif
1012#endif
1013
1014#ifdef HAVE_XPETRA_EPETRA
1015 if(bIsTpetra == false) {
1016 // no product vector
1017 Teuchos::RCP<Map> map = ThyUtils::toXpetra(v->range(), comm);
1019 RCP<Xpetra::EpetraMapT<GlobalOrdinal,Node> > xeMap = rcp_dynamic_cast<Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map, true);
1020 RCP<const Epetra_Map> eMap = xeMap->getEpetra_MapRCP();
1022 Teuchos::RCP<const Epetra_MultiVector> epMultVec = Thyra::get_Epetra_MultiVector(*eMap, v);
1024 RCP<Epetra_MultiVector> epNonConstMultVec = Teuchos::rcp_const_cast<Epetra_MultiVector>(epMultVec);
1025 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epNonConstMultVec));
1026 xpMultVec = Teuchos::rcp(new Xpetra::EpetraMultiVectorT<GlobalOrdinal,Node>(epNonConstMultVec));
1027 }
1028#endif
1030 return xpMultVec;
1031 } // end standard case
1032 }
1033
1034 // non-const version
1035 static Teuchos::RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
1036 toXpetra(Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1037 Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > cv =
1038 Teuchos::rcp_const_cast<const Thyra::MultiVectorBase<Scalar> >(v);
1039 Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > r =
1040 toXpetra(cv,comm);
1041 return Teuchos::rcp_const_cast<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(r);
1042 }
1043
1044 static bool isTpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1045 // check whether we have a Tpetra based Thyra operator
1046 bool bIsTpetra = false;
1047#ifdef HAVE_XPETRA_TPETRA
1048#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1049 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1050
1051 Teuchos::RCP<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_op = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(op);
1052 bIsTpetra = Teuchos::is_null(tpetra_op) ? false : true;
1053
1054 // for debugging purposes: find out why dynamic cast failed
1055 if(!bIsTpetra &&
1056#ifdef HAVE_XPETRA_EPETRA
1057 Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op) == Teuchos::null &&
1058#endif
1059 Teuchos::rcp_dynamic_cast<const Thyra::DefaultBlockedLinearOp<Scalar> >(op) == Teuchos::null) {
1060 // If op is not blocked and not an Epetra object, it should be in fact an Tpetra object
1061 typedef Thyra::TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> TpetraLinearOp_t;
1062 if(Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op) == Teuchos::null) {
1063 std::cout << "ATTENTION: The dynamic cast to the TpetraLinearOp failed even though it should be a TpetraLinearOp." << std::endl;
1064 std::cout << " If you are using Panzer or Stratimikos you might check that the template parameters are " << std::endl;
1065 std::cout << " properly set!" << std::endl;
1066 std::cout << Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op, true) << std::endl;
1067 }
1068 }
1069#endif
1070#endif
1071
1072#if 0
1073 // Check whether it is a blocked operator.
1074 // If yes, grab the (0,0) block and check the underlying linear algebra
1075 // Note: we expect that the (0,0) block exists!
1076 if(bIsTpetra == false) {
1077 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
1078 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1079 if(ThyBlockedOp != Teuchos::null) {
1080 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1081 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > b00 =
1082 ThyBlockedOp->getBlock(0,0);
1084 bIsTpetra = isTpetra(b00);
1085 }
1086 }
1087#endif
1088
1089 return bIsTpetra;
1090 }
1091
1092 static bool isEpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1093 // check whether we have an Epetra based Thyra operator
1094 bool bIsEpetra = false;
1095
1096#ifdef HAVE_XPETRA_EPETRA
1097 Teuchos::RCP<const Thyra::EpetraLinearOp> epetra_op = Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op,false);
1098 bIsEpetra = Teuchos::is_null(epetra_op) ? false : true;
1099#endif
1100
1101#if 0
1102 // Check whether it is a blocked operator.
1103 // If yes, grab the (0,0) block and check the underlying linear algebra
1104 // Note: we expect that the (0,0) block exists!
1105 if(bIsEpetra == false) {
1106 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
1107 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op,false);
1108 if(ThyBlockedOp != Teuchos::null) {
1109 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1110 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > b00 =
1111 ThyBlockedOp->getBlock(0,0);
1113 bIsEpetra = isEpetra(b00);
1114 }
1115 }
1116#endif
1117
1118 return bIsEpetra;
1119 }
1120
1121 static bool isBlockedOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1122 // Check whether it is a blocked operator.
1123 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
1124 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1125 if(ThyBlockedOp != Teuchos::null) {
1126 return true;
1127 }
1128 return false;
1129 }
1130
1131 static Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1132 toXpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
1133
1134#ifdef HAVE_XPETRA_TPETRA
1135 if(isTpetra(op)) {
1136#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1137 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1138
1139 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1140 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
1141 // we should also add support for the const versions!
1142 //getConstTpetraOperator(const RCP<const LinearOpBase<Scalar> > &op);
1144 Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
1146 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat, true);
1147 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraNcnstCrsMat = Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraCrsMat);
1148 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(TpetraNcnstCrsMat));
1149
1150 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraCrsMat =
1151 Teuchos::rcp(new Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraNcnstCrsMat));
1153 Teuchos::RCP<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > ret =
1154 Teuchos::rcp_dynamic_cast<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat);
1155 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
1156 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat, true);
1157 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
1158 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
1159 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
1160 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
1161 return xpMat;
1162#else
1163 throw Xpetra::Exceptions::RuntimeError("Problem BBB. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1164#endif
1165 }
1166#endif
1167
1168#ifdef HAVE_XPETRA_EPETRA
1169 if(isEpetra(op)) {
1170 Teuchos::RCP<const Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1172 Teuchos::RCP<const Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(epetra_op, true);
1173 Teuchos::RCP<const Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(epetra_rowmat, true);
1174 Teuchos::RCP<Epetra_CrsMatrix> epetra_ncnstcrsmat = Teuchos::rcp_const_cast<Epetra_CrsMatrix>(epetra_crsmat);
1175 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epetra_ncnstcrsmat));
1176
1177 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpetraCrsMat =
1178 Teuchos::rcp(new Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> (epetra_ncnstcrsmat));
1180
1181 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
1182 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xEpetraCrsMat, true);
1183 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
1184 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
1185 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
1186 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
1187 return xpMat;
1188 }
1189#endif
1190 return Teuchos::null;
1191 }
1192
1193 static Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1194 toXpetra(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
1195
1196#ifdef HAVE_XPETRA_TPETRA
1197 if(isTpetra(op)) {
1198#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1199 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1200
1201 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1202 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
1204 Teuchos::RCP<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp, true);
1205 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat, true);
1206
1207 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraCrsMat =
1208 Teuchos::rcp(new Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraCrsMat));
1210 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
1211 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat, true);
1212 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
1213 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
1214 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
1215 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
1216 return xpMat;
1217#else
1218 throw Xpetra::Exceptions::RuntimeError("Problem CCC. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1219#endif
1220 }
1221#endif
1222
1223#ifdef HAVE_XPETRA_EPETRA
1224 if(isEpetra(op)) {
1225 Teuchos::RCP<Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1227 Teuchos::RCP<Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(epetra_op, true);
1228 Teuchos::RCP<Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(epetra_rowmat, true);
1229
1230 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpetraCrsMat =
1231 Teuchos::rcp(new Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> (epetra_crsmat));
1233 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
1234 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xEpetraCrsMat, true);
1235 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
1236 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
1237 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
1238 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
1239 return xpMat;
1240 }
1241#endif
1242 return Teuchos::null;
1243 }
1244
1245
1246 static Teuchos::RCP<const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1247 toXpetraOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
1248
1249 return toXpetraOperator(Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(op));
1250
1251// #ifdef HAVE_XPETRA_TPETRA
1252// if(isTpetra(op)) {
1253// typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1254// Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
1255
1256// Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > nonConstTpetraOp =
1257// Teuchos::rcp_const_cast<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
1258
1259// Teuchos::RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraOp =
1260// Teuchos::rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node>(nonConstTpetraOp));
1261// TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xTpetraOp));
1262
1263// Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpOp =
1264// Teuchos::rcp_dynamic_cast<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraOp, true);
1265// return xpOp;
1266// }
1267// #endif
1268
1269// #ifdef HAVE_XPETRA_EPETRA
1270// if(isEpetra(op)) {
1271// TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
1272// }
1273// #endif
1274// return Teuchos::null;
1275 }
1276
1277 static Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1278 toXpetraOperator(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
1279
1280#ifdef HAVE_XPETRA_TPETRA
1281 if(isTpetra(op)) {
1282 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1283 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
1284
1285 Teuchos::RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraOp =
1286 Teuchos::rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraOp));
1288
1289 Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpOp =
1290 Teuchos::rcp_dynamic_cast<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraOp, true);
1291 return xpOp;
1292 }
1293#endif
1294
1295#ifdef HAVE_XPETRA_EPETRA
1296 if(isEpetra(op)) {
1297 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
1298 }
1299#endif
1300 return Teuchos::null;
1301 }
1302
1303 static Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1304 toXpetra(const Teuchos::RCP<Thyra::DiagonalLinearOpBase<Scalar> >& op) {
1305 using Teuchos::rcp_dynamic_cast;
1306 using Teuchos::rcp_const_cast;
1307
1308 RCP<const Thyra::VectorBase<Scalar> > diag = op->getDiag();
1309
1310 RCP<const Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xpDiag;
1311#ifdef HAVE_XPETRA_TPETRA
1312 using thyTpV = Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
1313 using tV = Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
1314 if (!rcp_dynamic_cast<const thyTpV>(diag).is_null()) {
1315 RCP<const tV> tDiag = Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(diag);
1316 if (!tDiag.is_null())
1317 xpDiag = Xpetra::toXpetra(tDiag);
1318 }
1319#endif
1320#ifdef HAVE_XPETRA_EPETRA
1321 using ThyVSBase = Thyra::SpmdVectorSpaceBase<Scalar>;
1322 if (xpDiag.is_null()) {
1323 RCP<const Epetra_Comm> comm = Thyra::get_Epetra_Comm(*rcp_dynamic_cast<const ThyVSBase>(op->range())->getComm());
1324 RCP<const Epetra_Map> map = Thyra::get_Epetra_Map(*(op->range()), comm);
1325 if (!map.is_null()) {
1326 RCP<const Epetra_Vector> eDiag = Thyra::get_Epetra_Vector(*map, diag);
1327 RCP<Epetra_Vector> nceDiag = rcp_const_cast<Epetra_Vector>(eDiag);
1328 RCP<Xpetra::EpetraVectorT<int,Node> > xpEpDiag = rcp(new Xpetra::EpetraVectorT<int,Node>(nceDiag));
1329 xpDiag = rcp_dynamic_cast<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(xpEpDiag, true);
1330 }
1331 }
1332#endif
1333 TEUCHOS_ASSERT(!xpDiag.is_null());
1334 RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > M = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(xpDiag);
1335 return M;
1336 }
1337
1338 static Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1339 toXpetra(const Teuchos::RCP<const Thyra::DiagonalLinearOpBase<Scalar> >& op) {
1340 return toXpetra(Teuchos::rcp_const_cast<Thyra::DiagonalLinearOpBase<Scalar> >(op));
1341 }
1342
1343 static Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
1344 toThyra(Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map) {
1345 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyraMap = Teuchos::null;
1346
1347 // check whether map is of type BlockedMap
1348 RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
1349 if(bmap.is_null() == false) {
1350
1351 Teuchos::Array<Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > > vecSpaces(bmap->getNumMaps());
1352 for(size_t i = 0; i < bmap->getNumMaps(); i++) {
1353 // we need Thyra GIDs for all the submaps
1354 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > vs =
1355 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(bmap->getMap(i,true));
1356 vecSpaces[i] = vs;
1357 }
1358
1359 thyraMap = Thyra::productVectorSpace<Scalar>(vecSpaces());
1360 return thyraMap;
1361 }
1362
1363 // standard case
1364#ifdef HAVE_XPETRA_TPETRA
1365 if(map->lib() == Xpetra::UseTpetra) {
1366#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1367 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1368 Teuchos::RCP<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> > tpetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> >(map);
1369 if (tpetraMap == Teuchos::null)
1370 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::TpetraMap failed");
1371 RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > tpMap = tpetraMap->getTpetra_Map();
1372 RCP<Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > thyraTpetraMap = Thyra::tpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, Node>(tpMap);
1373 thyraMap = thyraTpetraMap;
1374#else
1375 throw Xpetra::Exceptions::RuntimeError("Problem DDD. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1376#endif
1377 }
1378#endif
1379
1380#ifdef HAVE_XPETRA_EPETRA
1381 if(map->lib() == Xpetra::UseEpetra) {
1382 Teuchos::RCP<const Xpetra::EpetraMapT<GlobalOrdinal,Node> > epetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map);
1383 if (epetraMap == Teuchos::null)
1384 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::EpetraMap failed");
1385 RCP<const Thyra::VectorSpaceBase<Scalar> > thyraEpetraMap = Thyra::create_VectorSpace(epetraMap->getEpetra_MapRCP());
1386 thyraMap = thyraEpetraMap;
1387 }
1388#endif
1389
1390 return thyraMap;
1391 }
1392
1393 static Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> >
1394 toThyraMultiVector(Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > vec) {
1395
1396 // create Thyra MultiVector
1397#ifdef HAVE_XPETRA_TPETRA
1398 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
1399 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
1400 RCP<Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpMV = Teuchos::rcp_dynamic_cast<const TpetraMultiVector>(vec)->getTpetra_MultiVector();
1401 auto thyDomMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(vec->getNumVectors(), vec->getMap()->getComm()));
1402 auto thyMV = rcp(new Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
1403 thyMV->initialize(thyTpMap, thyDomMap, tpMV);
1404 return thyMV;
1405 }
1406#endif
1407
1408#ifdef HAVE_XPETRA_EPETRA
1409 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
1410 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
1411 auto epMV = Teuchos::rcp_dynamic_cast<const EpetraMultiVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_MultiVector();
1412 auto thyMV = Thyra::create_MultiVector(epMV, thyEpMap);
1413 return thyMV;
1414 }
1415#endif
1416
1417 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "MultiVector cannot be converted to Thyra.");
1418
1419 }
1420
1421 static Teuchos::RCP<const Thyra::VectorBase<Scalar> >
1422 toThyraVector(Teuchos::RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > vec) {
1423
1424 // create Thyra Vector
1425#ifdef HAVE_XPETRA_TPETRA
1426 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
1427 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
1428 RCP<Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpVec = Teuchos::rcp_dynamic_cast<const TpetraVector>(vec)->getTpetra_Vector();
1429 auto thyVec = rcp(new Thyra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
1430 thyVec->initialize(thyTpMap, tpVec);
1431 return thyVec;
1432 }
1433#endif
1434
1435#ifdef HAVE_XPETRA_EPETRA
1436 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
1437 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
1438 auto epVec = rcp(Teuchos::rcp_dynamic_cast<const EpetraVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_Vector(), false);
1439 auto thyVec = Thyra::create_Vector(epVec, thyEpMap);
1440 return thyVec;
1441 }
1442#endif
1443
1444 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Vector cannot be converted to Thyra.");
1445 }
1446
1447 static void updateThyra(Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > source, Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal,Node> > mapExtractor, const Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > & target) {
1448 using Teuchos::RCP;
1449 using Teuchos::rcp_dynamic_cast;
1450 using Teuchos::as;
1451 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
1452 typedef Thyra::SpmdVectorSpaceBase<Scalar> ThySpmdVecSpaceBase;
1453 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
1454 //typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
1455 //typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
1456 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
1457
1458 // copy data from tY_inout to Y_inout
1459 RCP<ThyProdMultVecBase> prodTarget = rcp_dynamic_cast<ThyProdMultVecBase>(target);
1460 if(prodTarget != Teuchos::null) {
1461
1462 RCP<const BlockedMultiVector> bSourceVec = rcp_dynamic_cast<const BlockedMultiVector>(source);
1463 if(bSourceVec.is_null() == true) {
1464 // SPECIAL CASE: target vector is product vector:
1465 // update Thyra product multi vector with data from a merged Xpetra multi vector
1466
1467 TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor == Teuchos::null, std::logic_error, "Found a Thyra product vector, but user did not provide an Xpetra::MapExtractor.");
1468 TEUCHOS_TEST_FOR_EXCEPTION(prodTarget->productSpace()->numBlocks() != as<int>(mapExtractor->NumMaps()), std::logic_error, "Inconsistent numbers of sub maps in Thyra::ProductVectorSpace and Xpetra::MapExtractor.");
1469
1470 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
1471 // access Xpetra data
1472 RCP<MultiVector> xpSubBlock = mapExtractor->ExtractVector(source, bbb, false); // use Xpetra ordering (doesn't really matter)
1473
1474 // access Thyra data
1475 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
1476 RCP<const ThyVecSpaceBase> vs = thySubBlock->range();
1477 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(vs);
1478 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
1479 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : vs->dim() );
1480 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
1481 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*thySubBlock,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
1482
1483 // loop over all vectors in multivector
1484 for(size_t j = 0; j < xpSubBlock->getNumVectors(); ++j) {
1485 Teuchos::ArrayRCP< const Scalar > xpData = xpSubBlock->getData(j); // access const data from Xpetra object
1486
1487 // loop over all local rows
1488 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
1489 (*thyData)(i,j) = xpData[i];
1490 }
1491 }
1492 }
1493 } else {
1494 // source vector is a blocked multivector
1495 // TODO test me
1496 TEUCHOS_TEST_FOR_EXCEPTION(prodTarget->productSpace()->numBlocks() != as<int>(bSourceVec->getBlockedMap()->getNumMaps()), std::logic_error, "Inconsistent numbers of sub maps in Thyra::ProductVectorSpace and Xpetra::BlockedMultiVector.");
1497
1498 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
1499 // access Thyra data
1500 RCP<MultiVector> xpSubBlock = bSourceVec->getMultiVector(bbb, true); // use Thyra ordering
1501
1502 Teuchos::RCP<const ThyMultVecBase> thyXpSubBlock = toThyraMultiVector(xpSubBlock);
1503
1504 // access Thyra data
1505 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
1506 Thyra::assign(thySubBlock.ptr(), *thyXpSubBlock);
1507 }
1508
1509 }
1510 } else {
1511 // STANDARD case:
1512 // update Thyra::MultiVector with data from an Xpetra::MultiVector
1513
1514 // access Thyra data
1515 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(target->range());
1516 TEUCHOS_TEST_FOR_EXCEPTION(mpi_vs == Teuchos::null, std::logic_error, "Failed to cast Thyra::VectorSpaceBase to Thyra::SpmdVectorSpaceBase.");
1517 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
1518 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : target->range()->dim() );
1519 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
1520 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*target,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
1521
1522 // loop over all vectors in multivector
1523 for(size_t j = 0; j < source->getNumVectors(); ++j) {
1524 Teuchos::ArrayRCP< const Scalar > xpData = source->getData(j); // access const data from Xpetra object
1525 // loop over all local rows
1526 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
1527 (*thyData)(i,j) = xpData[i];
1528 }
1529 }
1530 }
1531 }
1532
1533 static Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
1534 toThyra(const Teuchos::RCP<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
1535 // create a Thyra operator from Xpetra::CrsMatrix
1536 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
1537
1538#ifdef HAVE_XPETRA_TPETRA
1539 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
1540 if(tpetraMat!=Teuchos::null) {
1541#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1542 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1543
1544 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat, true);
1545 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrix();
1547
1548 Teuchos::RCP<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat, true);
1549 Teuchos::RCP<const Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<const Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat, true);
1550
1551 thyraOp = Thyra::createConstLinearOp(tpOperator);
1553#else
1554 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1555#endif
1556 }
1557#endif
1558
1559#ifdef HAVE_XPETRA_EPETRA
1560 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1561 if(epetraMat!=Teuchos::null) {
1562 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1564 Teuchos::RCP<const Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrix();
1566
1567 Teuchos::RCP<const Thyra::EpetraLinearOp> thyraEpOp = Thyra::epetraLinearOp(epCrsMat,"op");
1569 thyraOp = thyraEpOp;
1570 }
1571#endif
1572 return thyraOp;
1573 }
1574
1575 static Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
1576 toThyra(const Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
1577 // create a Thyra operator from Xpetra::CrsMatrix
1578 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
1579
1580#ifdef HAVE_XPETRA_TPETRA
1581 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
1582 if(tpetraMat!=Teuchos::null) {
1583#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1584 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1585
1586 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat, true);
1587 Teuchos::RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrixNonConst();
1589
1590 Teuchos::RCP<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat, true);
1591 Teuchos::RCP<Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat, true);
1592
1593 thyraOp = Thyra::createLinearOp(tpOperator);
1595#else
1596 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1597#endif
1598 }
1599#endif
1600
1601#ifdef HAVE_XPETRA_EPETRA
1602 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1603 if(epetraMat!=Teuchos::null) {
1604 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat, true);
1605 Teuchos::RCP<Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrixNonConst();
1607
1608 Teuchos::RCP<Thyra::EpetraLinearOp> thyraEpOp = Thyra::nonconstEpetraLinearOp(epCrsMat,"op");
1610 thyraOp = thyraEpOp;
1611 }
1612#endif
1613 return thyraOp;
1614 }
1615
1616 static Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
1617 toThyra(const Teuchos::RCP<Xpetra::BlockedCrsMatrix<double, int, int, EpetraNode> >& mat);
1618
1619}; // specialization on SC=double, LO=GO=int and NO=EpetraNode
1620#endif // #ifndef XPETRA_EPETRA_NO_32BIT_GLOBAL_INDICES
1621
1622#ifndef XPETRA_EPETRA_NO_64BIT_GLOBAL_INDICES
1623template <>
1624class ThyraUtils<double, int, long long, EpetraNode> {
1625public:
1626 typedef double Scalar;
1627 typedef int LocalOrdinal;
1628 typedef long long GlobalOrdinal;
1629 typedef EpetraNode Node;
1630
1631private:
1632#undef XPETRA_THYRAUTILS_SHORT
1633#include "Xpetra_UseShortNames.hpp"
1634
1635public:
1636
1637 static Teuchos::RCP<Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> >
1638 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm, std::vector<size_t>& stridingInfo, LocalOrdinal stridedBlockId = -1, GlobalOrdinal offset = 0) {
1639
1640 Teuchos::RCP<Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map = ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toXpetra(vectorSpace,comm);
1641
1642 if(stridedBlockId == -1) {
1643 TEUCHOS_TEST_FOR_EXCEPT(map->getLocalNumElements() % stridingInfo.size() != 0);
1644 }
1645 else {
1646 TEUCHOS_TEST_FOR_EXCEPT(map->getLocalNumElements() % stridingInfo[stridedBlockId] != 0);
1647 }
1648
1649 Teuchos::RCP<Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> > ret = Xpetra::StridedMapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(map, stridingInfo, stridedBlockId, offset);
1650 return ret;
1651 }
1652
1653 static Teuchos::RCP<Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> >
1654 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1655 using Teuchos::RCP;
1656 using Teuchos::rcp_dynamic_cast;
1657 using Teuchos::as;
1658 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
1659 typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
1660 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyUtils;
1661
1662 RCP<const ThyProdVecSpaceBase > prodVectorSpace = rcp_dynamic_cast<const ThyProdVecSpaceBase >(vectorSpace);
1663 if(prodVectorSpace != Teuchos::null) {
1664 // SPECIAL CASE: product Vector space
1665 // collect all submaps to store them in a hierarchical BlockedMap object
1666 TEUCHOS_TEST_FOR_EXCEPTION(prodVectorSpace->numBlocks()==0, std::logic_error, "Found a product vector space with zero blocks.");
1667 std::vector<RCP<const Map> > mapsThyra(prodVectorSpace->numBlocks(), Teuchos::null);
1668 std::vector<RCP<const Map> > mapsXpetra(prodVectorSpace->numBlocks(), Teuchos::null);
1669 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
1670 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
1671 // can be of type Map or BlockedMap (containing Thyra GIDs)
1672 mapsThyra[b] = ThyUtils::toXpetra(bv, comm); // recursive call
1673 }
1674
1675 // get offsets for submap GIDs
1676 // we need that for the full map (Xpetra GIDs)
1677 std::vector<GlobalOrdinal> gidOffsets(prodVectorSpace->numBlocks(),0);
1678 for(int i = 1; i < prodVectorSpace->numBlocks(); ++i) {
1679 gidOffsets[i] = mapsThyra[i-1]->getMaxAllGlobalIndex() + gidOffsets[i-1] + 1;
1680 }
1681
1682 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
1683 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
1684 // map can be of type Map or BlockedMap (containing Xpetra style GIDs)
1685 mapsXpetra[b] = MapUtils::transformThyra2XpetraGIDs(*mapsThyra[b], gidOffsets[b]);
1686 }
1687
1688 Teuchos::RCP<Map> resultMap = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node>(mapsXpetra, mapsThyra));
1690 return resultMap;
1691 } else {
1692 // STANDARD CASE: no product map
1693 // Epetra/Tpetra specific code to access the underlying map data
1694
1695 // check whether we have a Tpetra based Thyra operator
1696 bool bIsTpetra = false;
1697#ifdef HAVE_XPETRA_TPETRA
1698#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1699 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1700 Teuchos::RCP<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_vsc = Teuchos::rcp_dynamic_cast<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(vectorSpace);
1701 bIsTpetra = Teuchos::is_null(tpetra_vsc) ? false : true;
1702#endif
1703#endif
1704
1705 // check whether we have an Epetra based Thyra operator
1706 bool bIsEpetra = !bIsTpetra; // note: this is a little bit fragile!
1707
1708#ifdef HAVE_XPETRA_TPETRA
1709 if(bIsTpetra) {
1710#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1711 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1712 typedef Thyra::VectorBase<Scalar> ThyVecBase;
1713 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
1714 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
1715 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1716 RCP<ThyVecBase> rgVec = Thyra::createMember<Scalar>(vectorSpace, std::string("label"));
1718 RCP<const TpVector> rgTpetraVec = TOE::getTpetraVector(rgVec);
1720 RCP<const TpMap> rgTpetraMap = rgTpetraVec->getMap();
1722
1723 RCP<Map> rgXpetraMap = Xpetra::toXpetraNonConst(rgTpetraMap);
1725 return rgXpetraMap;
1726#else
1727 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
1728#endif
1729 }
1730#endif
1731
1732#ifdef HAVE_XPETRA_EPETRA
1733 if(bIsEpetra) {
1734 //RCP<const Epetra_Map> epMap = Teuchos::null;
1735 RCP<const Epetra_Map>
1736 epetra_map = Teuchos::get_extra_data<RCP<const Epetra_Map> >(vectorSpace,"epetra_map");
1737 if(!Teuchos::is_null(epetra_map)) {
1738 Teuchos::RCP<Map> rgXpetraMap = Teuchos::rcp(new Xpetra::EpetraMapT<GlobalOrdinal,Node>(epetra_map));
1740 return rgXpetraMap;
1741 } else {
1742 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "No Epetra_Map data found in Thyra::VectorSpace.");
1743 }
1744 }
1745#endif
1746 } // end standard case (no product map)
1747 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "Cannot transform Thyra::VectorSpace to Xpetra::Map.");
1748 // return Teuchos::null; // unreachable
1749 }
1750
1751 // const version
1752 static Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
1753 toXpetra(Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1754 using Teuchos::RCP;
1755 using Teuchos::rcp_dynamic_cast;
1756 using Teuchos::as;
1757 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
1758 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
1759 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyUtils;
1760
1761 // return value
1762 RCP<MultiVector> xpMultVec = Teuchos::null;
1763
1764 // check whether v is a product multi vector
1765 Teuchos::RCP<const ThyProdMultVecBase> thyProdVec = rcp_dynamic_cast<const ThyProdMultVecBase >(v);
1766 if(thyProdVec != Teuchos::null) {
1767 // SPECIAL CASE: create a nested BlockedMultiVector
1768 // generate nested BlockedMap (containing Thyra and Xpetra GIDs)
1769 RCP<Map> fullMap = ThyUtils::toXpetra(v->range(), comm);
1770 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(Teuchos::rcp_dynamic_cast<BlockedMap>(fullMap)));
1771
1772 // create new Xpetra::BlockedMultiVector
1773 xpMultVec = MultiVectorFactory::Build(fullMap, as<size_t>(thyProdVec->domain()->dim()));
1774
1775 RCP<BlockedMultiVector> xpBlockedMultVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xpMultVec);
1776 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpBlockedMultVec));
1777
1778 // loop over all blocks, transform Thyra MultiVectors to Xpetra MultiVectors recursively
1779 for (int b = 0; b < thyProdVec->productSpace()->numBlocks(); ++b){
1780 RCP<const ThyMultVecBase> thyBlockMV = thyProdVec->getMultiVectorBlock(b);
1781 // xpBlockMV can be of type MultiVector or BlockedMultiVector
1782 RCP<const MultiVector> xpBlockMV = ThyUtils::toXpetra(thyBlockMV, comm); //recursive call
1783 xpBlockedMultVec->setMultiVector(b, xpBlockMV, true /* Thyra mode */);
1784 }
1785
1787 return xpMultVec;
1788 } else {
1789 // STANDARD CASE: no product vector
1790 // Epetra/Tpetra specific code to access the underlying map data
1791 bool bIsTpetra = false;
1792#ifdef HAVE_XPETRA_TPETRA
1793#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1794 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1795
1796 //typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
1797 //typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
1798 typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
1799 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> ConverterT;
1800 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpMultVec;
1801 typedef Xpetra::TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpTpMultVec;
1802 typedef Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyTpMultVec;
1803
1804 RCP<const ThySpmdMultVecBase> thyraSpmdMultiVector = rcp_dynamic_cast<const ThySpmdMultVecBase>(v);
1805 RCP<const ThyTpMultVec> thyraTpetraMultiVector = rcp_dynamic_cast<const ThyTpMultVec>(thyraSpmdMultiVector);
1806 if(thyraTpetraMultiVector != Teuchos::null) {
1807 bIsTpetra = true;
1808 const RCP<const TpMultVec> tpMultVec = ConverterT::getConstTpetraMultiVector(v);
1810 RCP<TpMultVec> tpNonConstMultVec = Teuchos::rcp_const_cast<TpMultVec>(tpMultVec);
1811 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpNonConstMultVec));
1812 xpMultVec = rcp(new XpTpMultVec(tpNonConstMultVec));
1814 return xpMultVec;
1815 }
1816#endif
1817#endif
1818
1819#ifdef HAVE_XPETRA_EPETRA
1820 if(bIsTpetra == false) {
1821 // no product vector
1822 Teuchos::RCP<Map> map = ThyUtils::toXpetra(v->range(), comm);
1824 RCP<Xpetra::EpetraMapT<GlobalOrdinal,Node> > xeMap = rcp_dynamic_cast<Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map, true);
1825 RCP<const Epetra_Map> eMap = xeMap->getEpetra_MapRCP();
1827 Teuchos::RCP<const Epetra_MultiVector> epMultVec = Thyra::get_Epetra_MultiVector(*eMap, v);
1829 RCP<Epetra_MultiVector> epNonConstMultVec = Teuchos::rcp_const_cast<Epetra_MultiVector>(epMultVec);
1830 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epNonConstMultVec));
1831 xpMultVec = Teuchos::rcp(new Xpetra::EpetraMultiVectorT<GlobalOrdinal,Node>(epNonConstMultVec));
1833 return xpMultVec;
1834 }
1835#endif
1836 } // end standard case
1837 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "Cannot transform Thyra::MultiVector to Xpetra::MultiVector.");
1838 // return Teuchos::null; // unreachable
1839 }
1840
1841 // non-const version
1842 static Teuchos::RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
1843 toXpetra(Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1844 Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > cv =
1845 Teuchos::rcp_const_cast<const Thyra::MultiVectorBase<Scalar> >(v);
1846 Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > r =
1847 toXpetra(cv,comm);
1848 return Teuchos::rcp_const_cast<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(r);
1849 }
1850
1851 static bool isTpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1852 // check whether we have a Tpetra based Thyra operator
1853 bool bIsTpetra = false;
1854#ifdef HAVE_XPETRA_TPETRA
1855#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1856 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1857
1858 Teuchos::RCP<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_op = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(op);
1859 bIsTpetra = Teuchos::is_null(tpetra_op) ? false : true;
1860
1861 // for debugging purposes: find out why dynamic cast failed
1862 if(!bIsTpetra &&
1863#ifdef HAVE_XPETRA_EPETRA
1864 Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op) == Teuchos::null &&
1865#endif
1866 Teuchos::rcp_dynamic_cast<const Thyra::DefaultBlockedLinearOp<Scalar> >(op) == Teuchos::null) {
1867 // If op is not blocked and not an Epetra object, it should be in fact an Tpetra object
1868 typedef Thyra::TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> TpetraLinearOp_t;
1869 if(Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op) == Teuchos::null) {
1870 std::cout << "ATTENTION: The dynamic cast to the TpetraLinearOp failed even though it should be a TpetraLinearOp." << std::endl;
1871 std::cout << " If you are using Panzer or Stratimikos you might check that the template parameters are " << std::endl;
1872 std::cout << " properly set!" << std::endl;
1873 std::cout << Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op, true) << std::endl;
1874 }
1875 }
1876#endif
1877#endif
1878
1879#if 0
1880 // Check whether it is a blocked operator.
1881 // If yes, grab the (0,0) block and check the underlying linear algebra
1882 // Note: we expect that the (0,0) block exists!
1883 if(bIsTpetra == false) {
1884 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
1885 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1886 if(ThyBlockedOp != Teuchos::null) {
1887 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1888 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > b00 =
1889 ThyBlockedOp->getBlock(0,0);
1891 bIsTpetra = isTpetra(b00);
1892 }
1893 }
1894#endif
1895
1896 return bIsTpetra;
1897 }
1898
1899 static bool isEpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1900 // check whether we have an Epetra based Thyra operator
1901 bool bIsEpetra = false;
1902
1903#ifdef HAVE_XPETRA_EPETRA
1904 Teuchos::RCP<const Thyra::EpetraLinearOp> epetra_op = Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op,false);
1905 bIsEpetra = Teuchos::is_null(epetra_op) ? false : true;
1906#endif
1907
1908#if 0
1909 // Check whether it is a blocked operator.
1910 // If yes, grab the (0,0) block and check the underlying linear algebra
1911 // Note: we expect that the (0,0) block exists!
1912 if(bIsEpetra == false) {
1913 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
1914 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op,false);
1915 if(ThyBlockedOp != Teuchos::null) {
1916 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1917 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > b00 =
1918 ThyBlockedOp->getBlock(0,0);
1920 bIsEpetra = isEpetra(b00);
1921 }
1922 }
1923#endif
1924
1925 return bIsEpetra;
1926 }
1927
1928 static bool isBlockedOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1929 // Check whether it is a blocked operator.
1930 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
1931 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1932 if(ThyBlockedOp != Teuchos::null) {
1933 return true;
1934 }
1935 return false;
1936 }
1937
1938 static Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1939 toXpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
1940
1941#ifdef HAVE_XPETRA_TPETRA
1942 if(isTpetra(op)) {
1943#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1944 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1945
1946 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1947 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
1948 // we should also add support for the const versions!
1949 //getConstTpetraOperator(const RCP<const LinearOpBase<Scalar> > &op);
1951 Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp, true);
1952 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat, true);
1953 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraNcnstCrsMat = Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraCrsMat);
1954 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(TpetraNcnstCrsMat));
1955
1956 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraCrsMat =
1957 Teuchos::rcp(new Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraNcnstCrsMat));
1959
1960 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
1961 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat, true);
1962 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
1963 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
1964 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
1965 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
1966 return xpMat;
1967#else
1968 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
1969#endif
1970 }
1971#endif
1972
1973#ifdef HAVE_XPETRA_EPETRA
1974 if(isEpetra(op)) {
1975 Teuchos::RCP<const Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1977 Teuchos::RCP<const Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(epetra_op, true);
1978 Teuchos::RCP<const Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(epetra_rowmat, true);
1979 Teuchos::RCP<Epetra_CrsMatrix> epetra_ncnstcrsmat = Teuchos::rcp_const_cast<Epetra_CrsMatrix>(epetra_crsmat);
1980 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epetra_ncnstcrsmat));
1981
1982 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpetraCrsMat =
1983 Teuchos::rcp(new Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> (epetra_ncnstcrsmat));
1985
1986 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
1987 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xEpetraCrsMat, true);
1988 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
1989 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
1990 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
1991 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
1992 return xpMat;
1993 }
1994#endif
1995 return Teuchos::null;
1996 }
1997
1998 static Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
1999 toXpetra(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
2000
2001#ifdef HAVE_XPETRA_TPETRA
2002 if(isTpetra(op)) {
2003#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
2004 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
2005
2006 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
2007 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
2009 Teuchos::RCP<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp, true);
2010 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat, true);
2011
2012 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraCrsMat =
2013 Teuchos::rcp(new Xpetra::TpetraCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraCrsMat));
2015
2016 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
2017 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat, true);
2018 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
2019 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
2020 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
2021 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
2022 return xpMat;
2023#else
2024 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
2025#endif
2026 }
2027#endif
2028
2029#ifdef HAVE_XPETRA_EPETRA
2030 if(isEpetra(op)) {
2031 Teuchos::RCP<Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
2033 Teuchos::RCP<Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(epetra_op, true);
2034 Teuchos::RCP<Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(epetra_rowmat, true);
2035
2036 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpetraCrsMat =
2037 Teuchos::rcp(new Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> (epetra_crsmat));
2039
2040 Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsMat =
2041 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xEpetraCrsMat, true);
2042 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpCrsWrap =
2043 Teuchos::rcp(new Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>(xpCrsMat));
2044 Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpMat =
2045 Teuchos::rcp_dynamic_cast<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpCrsWrap, true);
2046 return xpMat;
2047 }
2048#endif
2049 return Teuchos::null;
2050 }
2051
2052 static Teuchos::RCP<const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
2053 toXpetraOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
2054
2055#ifdef HAVE_XPETRA_TPETRA
2056 if(isTpetra(op)) {
2057 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
2058 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
2059
2060 Teuchos::RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraOp =
2061 Teuchos::rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraOp));
2063
2064 Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpOp =
2065 Teuchos::rcp_dynamic_cast<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraOp, true);
2066 return xpOp;
2067 }
2068#endif
2069
2070#ifdef HAVE_XPETRA_EPETRA
2071 if(isEpetra(op)) {
2072 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
2073 }
2074#endif
2075 return Teuchos::null;
2076 }
2077
2078 static Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
2079 toXpetraOperator(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
2080
2081#ifdef HAVE_XPETRA_TPETRA
2082 if(isTpetra(op)) {
2083 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
2084 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
2085
2086 Teuchos::RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xTpetraOp =
2087 Teuchos::rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node>(TpetraOp));
2089
2090 Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xpOp =
2091 Teuchos::rcp_dynamic_cast<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraOp, true);
2092 return xpOp;
2093 }
2094#endif
2095
2096#ifdef HAVE_XPETRA_EPETRA
2097 if(isEpetra(op)) {
2098 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
2099 }
2100#endif
2101 return Teuchos::null;
2102 }
2103
2104 static Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
2105 toXpetra(const Teuchos::RCP<Thyra::DiagonalLinearOpBase<Scalar> >& op) {
2106 using Teuchos::rcp_dynamic_cast;
2107 using Teuchos::rcp_const_cast;
2108 using ThyVSBase = Thyra::SpmdVectorSpaceBase<Scalar>;
2109 using thyTpV = Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
2110 using tV = Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2111
2112 RCP<const Thyra::VectorBase<Scalar> > diag = op->getDiag();
2113
2114 RCP<const Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > xpDiag;
2115#ifdef HAVE_XPETRA_TPETRA
2116 if (!rcp_dynamic_cast<const thyTpV>(diag).is_null()) {
2117 RCP<const tV> tDiag = Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(diag);
2118 if (!tDiag.is_null())
2119 xpDiag = Xpetra::toXpetra(tDiag);
2120 }
2121#endif
2122#ifdef HAVE_XPETRA_EPETRA
2123 if (xpDiag.is_null()) {
2124 RCP<const Epetra_Comm> comm = Thyra::get_Epetra_Comm(*rcp_dynamic_cast<const ThyVSBase>(op->range())->getComm());
2125 RCP<const Epetra_Map> map = Thyra::get_Epetra_Map(*(op->range()), comm);
2126 if (!map.is_null()) {
2127 RCP<const Epetra_Vector> eDiag = Thyra::get_Epetra_Vector(*map, diag);
2128 RCP<Epetra_Vector> nceDiag = rcp_const_cast<Epetra_Vector>(eDiag);
2129 RCP<Xpetra::EpetraVectorT<int,Node> > xpEpDiag = rcp(new Xpetra::EpetraVectorT<int,Node>(nceDiag));
2130 xpDiag = rcp_dynamic_cast<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(xpEpDiag, true);
2131 }
2132 }
2133#endif
2134 TEUCHOS_ASSERT(!xpDiag.is_null());
2135 RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > M = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(xpDiag);
2136 return M;
2137 }
2138
2139 static Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
2140 toXpetra(const Teuchos::RCP<const Thyra::DiagonalLinearOpBase<Scalar> >& op) {
2141 return toXpetra(Teuchos::rcp_const_cast<Thyra::DiagonalLinearOpBase<Scalar> >(op));
2142 }
2143
2144 static Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
2145 toThyra(Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > map) {
2146 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyraMap = Teuchos::null;
2147
2148 // check whether map is of type BlockedMap
2149 RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
2150 if(bmap.is_null() == false) {
2151
2152 Teuchos::Array<Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > > vecSpaces(bmap->getNumMaps());
2153 for(size_t i = 0; i < bmap->getNumMaps(); i++) {
2154 // we need Thyra GIDs for all the submaps
2155 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > vs =
2156 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(bmap->getMap(i,true));
2157 vecSpaces[i] = vs;
2158 }
2159
2160 thyraMap = Thyra::productVectorSpace<Scalar>(vecSpaces());
2161 return thyraMap;
2162 }
2163
2164 // standard case
2165#ifdef HAVE_XPETRA_TPETRA
2166 if(map->lib() == Xpetra::UseTpetra) {
2167#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
2168 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
2169 Teuchos::RCP<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> > tpetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> >(map);
2170 if (tpetraMap == Teuchos::null)
2171 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::TpetraMap failed");
2172 RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > tpMap = tpetraMap->getTpetra_Map();
2173 RCP<Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > thyraTpetraMap = Thyra::tpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, Node>(tpMap);
2174 thyraMap = thyraTpetraMap;
2175#else
2176 throw Xpetra::Exceptions::RuntimeError("Problem DDD. Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
2177#endif
2178 }
2179#endif
2180
2181#ifdef HAVE_XPETRA_EPETRA
2182 if(map->lib() == Xpetra::UseEpetra) {
2183 Teuchos::RCP<const Xpetra::EpetraMapT<GlobalOrdinal,Node> > epetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map);
2184 if (epetraMap == Teuchos::null)
2185 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::EpetraMap failed");
2186 RCP<const Thyra::VectorSpaceBase<Scalar> > thyraEpetraMap = Thyra::create_VectorSpace(epetraMap->getEpetra_MapRCP());
2187 thyraMap = thyraEpetraMap;
2188 }
2189#endif
2190
2191 return thyraMap;
2192 }
2193
2194 static Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> >
2195 toThyraMultiVector(Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > vec) {
2196
2197 // create Thyra MultiVector
2198#ifdef HAVE_XPETRA_TPETRA
2199 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
2200 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
2201 RCP<Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpMV = Teuchos::rcp_dynamic_cast<const TpetraMultiVector>(vec)->getTpetra_MultiVector();
2202 auto thyDomMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(vec->getNumVectors(), vec->getMap()->getComm()));
2203 auto thyMV = rcp(new Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
2204 thyMV->initialize(thyTpMap, thyDomMap, tpMV);
2205 return thyMV;
2206 }
2207#endif
2208
2209#ifdef HAVE_XPETRA_EPETRA
2210 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
2211 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
2212 auto epMV = Teuchos::rcp_dynamic_cast<const EpetraMultiVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_MultiVector();
2213 auto thyMV = Thyra::create_MultiVector(epMV, thyEpMap);
2214 return thyMV;
2215 }
2216#endif
2217
2218 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "MultiVector cannot be converted to Thyra.");
2219 }
2220
2221 static Teuchos::RCP<const Thyra::VectorBase<Scalar> >
2222 toThyraVector(Teuchos::RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > vec) {
2223
2224 // create Thyra Vector
2225#ifdef HAVE_XPETRA_TPETRA
2226 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
2227 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
2228 RCP<Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpVec = Teuchos::rcp_dynamic_cast<const TpetraVector>(vec)->getTpetra_Vector();
2229 auto thyVec = rcp(new Thyra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
2230 thyVec->initialize(thyTpMap, tpVec);
2231 return thyVec;
2232 }
2233#endif
2234
2235#ifdef HAVE_XPETRA_EPETRA
2236 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
2237 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
2238 auto epVec = rcp(Teuchos::rcp_dynamic_cast<const EpetraVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_Vector(), false);
2239 auto thyVec = Thyra::create_Vector(epVec, thyEpMap);
2240 return thyVec;
2241 }
2242#endif
2243
2244 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Vector cannot be converted to Thyra.");
2245 }
2246
2247 static void updateThyra(Teuchos::RCP<const Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > source, Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal,Node> > mapExtractor, const Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > & target) {
2248 using Teuchos::RCP;
2249 using Teuchos::rcp_dynamic_cast;
2250 using Teuchos::as;
2251 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
2252 typedef Thyra::SpmdVectorSpaceBase<Scalar> ThySpmdVecSpaceBase;
2253 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
2254 //typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
2255 //typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
2256 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
2257
2258 // copy data from tY_inout to Y_inout
2259 RCP<ThyProdMultVecBase> prodTarget = rcp_dynamic_cast<ThyProdMultVecBase>(target);
2260 if(prodTarget != Teuchos::null) {
2261 RCP<const BlockedMultiVector> bSourceVec = rcp_dynamic_cast<const BlockedMultiVector>(source);
2262 if(bSourceVec.is_null() == true) {
2263 // SPECIAL CASE: target vector is product vector:
2264 // update Thyra product multi vector with data from a merged Xpetra multi vector
2265
2266 TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor == Teuchos::null, std::logic_error, "Found a Thyra product vector, but user did not provide an Xpetra::MapExtractor.");
2267 TEUCHOS_TEST_FOR_EXCEPTION(prodTarget->productSpace()->numBlocks() != as<int>(mapExtractor->NumMaps()), std::logic_error, "Inconsistent numbers of sub maps in Thyra::ProductVectorSpace and Xpetra::MapExtractor.");
2268
2269 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
2270 // access Xpetra data
2271 RCP<MultiVector> xpSubBlock = mapExtractor->ExtractVector(source, bbb, false); // use Xpetra ordering (doesn't really matter)
2272
2273 // access Thyra data
2274 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
2275 RCP<const ThyVecSpaceBase> vs = thySubBlock->range();
2276 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(vs);
2277 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
2278 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : vs->dim() );
2279 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
2280 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*thySubBlock,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
2281
2282 // loop over all vectors in multivector
2283 for(size_t j = 0; j < xpSubBlock->getNumVectors(); ++j) {
2284 Teuchos::ArrayRCP< const Scalar > xpData = xpSubBlock->getData(j); // access const data from Xpetra object
2285
2286 // loop over all local rows
2287 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
2288 (*thyData)(i,j) = xpData[i];
2289 }
2290 }
2291 }
2292 } else {
2293 // source vector is a blocked multivector
2294 // TODO test me
2295 TEUCHOS_TEST_FOR_EXCEPTION(prodTarget->productSpace()->numBlocks() != as<int>(bSourceVec->getBlockedMap()->getNumMaps()), std::logic_error, "Inconsistent numbers of sub maps in Thyra::ProductVectorSpace and Xpetra::BlockedMultiVector.");
2296
2297 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
2298 // access Thyra data
2299 RCP<MultiVector> xpSubBlock = bSourceVec->getMultiVector(bbb, true); // use Thyra ordering
2300
2301 Teuchos::RCP<const ThyMultVecBase> thyXpSubBlock = toThyraMultiVector(xpSubBlock);
2302
2303 // access Thyra data
2304 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
2305 Thyra::assign(thySubBlock.ptr(), *thyXpSubBlock);
2306 }
2307
2308 }
2309 } else {
2310 // STANDARD case:
2311 // update Thyra::MultiVector with data from an Xpetra::MultiVector
2312
2313 // access Thyra data
2314 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(target->range());
2315 TEUCHOS_TEST_FOR_EXCEPTION(mpi_vs == Teuchos::null, std::logic_error, "Failed to cast Thyra::VectorSpaceBase to Thyra::SpmdVectorSpaceBase.");
2316 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
2317 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : target->range()->dim() );
2318 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
2319 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*target,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
2320
2321 // loop over all vectors in multivector
2322 for(size_t j = 0; j < source->getNumVectors(); ++j) {
2323 Teuchos::ArrayRCP< const Scalar > xpData = source->getData(j); // access const data from Xpetra object
2324 // loop over all local rows
2325 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
2326 (*thyData)(i,j) = xpData[i];
2327 }
2328 }
2329 }
2330 }
2331
2332 static Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
2333 toThyra(const Teuchos::RCP<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
2334 // create a Thyra operator from Xpetra::CrsMatrix
2335 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
2336
2337#ifdef HAVE_XPETRA_TPETRA
2338 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
2339 if(tpetraMat!=Teuchos::null) {
2340#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
2341 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
2342
2343 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat, true);
2344 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrix();
2346
2347 Teuchos::RCP<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat, true);
2348 Teuchos::RCP<const Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<const Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat, true);
2349
2350 thyraOp = Thyra::createConstLinearOp(tpOperator);
2352#else
2353 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
2354#endif
2355 }
2356#endif
2357
2358#ifdef HAVE_XPETRA_EPETRA
2359 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
2360 if(epetraMat!=Teuchos::null) {
2361 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat, true);
2362 Teuchos::RCP<const Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrix();
2364
2365 Teuchos::RCP<const Thyra::EpetraLinearOp> thyraEpOp = Thyra::epetraLinearOp(epCrsMat,"op");
2367 thyraOp = thyraEpOp;
2368 }
2369#endif
2370 return thyraOp;
2371 }
2372
2373 static Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
2374 toThyra(const Teuchos::RCP<Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& mat) {
2375 // create a Thyra operator from Xpetra::CrsMatrix
2376 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
2377
2378#ifdef HAVE_XPETRA_TPETRA
2379 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
2380 if(tpetraMat!=Teuchos::null) {
2381#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
2382 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
2383
2384 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat, true);
2385 Teuchos::RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrixNonConst();
2387
2388 Teuchos::RCP<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat, true);
2389 Teuchos::RCP<Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat, true);
2390
2391 thyraOp = Thyra::createLinearOp(tpOperator);
2393#else
2394 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
2395#endif
2396 }
2397#endif
2398
2399#ifdef HAVE_XPETRA_EPETRA
2400 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
2401 if(epetraMat!=Teuchos::null) {
2402 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat, true);
2403 Teuchos::RCP<Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrixNonConst();
2405
2406 Teuchos::RCP<Thyra::EpetraLinearOp> thyraEpOp = Thyra::nonconstEpetraLinearOp(epCrsMat,"op");
2408 thyraOp = thyraEpOp;
2409 }
2410#endif
2411 return thyraOp;
2412 }
2413
2414 static Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
2415 toThyra(const Teuchos::RCP<Xpetra::BlockedCrsMatrix<double, int, long long, EpetraNode> >& mat);
2416
2417}; // specialization on SC=double, LO=GO=int and NO=EpetraNode
2418#endif // XPETRA_EPETRA_NO_64BIT_GLOBAL_INDICES
2419
2420#endif // HAVE_XPETRA_EPETRA
2421
2422} // end namespace Xpetra
2423
2424#define XPETRA_THYRAUTILS_SHORT
2425#endif // HAVE_XPETRA_THYRA
2426
2427#endif // XPETRA_THYRAUTILS_HPP
bool is_null() const
Ptr< T > ptr() const
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
static RCP< Xpetra::StridedMap< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, std::vector< size_t > &stridingInfo, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, LocalOrdinal stridedBlockId=-1, GlobalOrdinal offset=0, LocalGlobal lg=Xpetra::GloballyDistributed)
Map constructor with Xpetra-defined contiguous uniform distribution.
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
bool is_null(const std::shared_ptr< T > &p)
TypeTo as(const TypeFrom &t)
#define TEUCHOS_UNREACHABLE_RETURN(dummyReturnVal)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Xpetra namespace
const RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > toXpetraNonConst(const RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &map)
Tpetra::KokkosCompat::KokkosSerialWrapperNode EpetraNode
RCP< const CrsGraph< int, GlobalOrdinal, Node > > toXpetra(const Epetra_CrsGraph &g)