Xpetra Version of the Day
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"
67#include "Xpetra_MapUtils.hpp"
68#include "Xpetra_StridedMap.hpp"
69#include "Xpetra_StridedMapFactory.hpp"
70#include "Xpetra_MapExtractor.hpp"
71#include "Xpetra_Matrix.hpp"
72#include "Xpetra_CrsMatrixWrap.hpp"
73#include "Xpetra_MultiVectorFactory.hpp"
74
75#include <Thyra_VectorSpaceBase.hpp>
76#include <Thyra_SpmdVectorSpaceBase.hpp>
77#include <Thyra_ProductVectorSpaceBase.hpp>
78#include <Thyra_ProductMultiVectorBase.hpp>
79#include <Thyra_VectorSpaceBase.hpp>
80#include <Thyra_DefaultProductVectorSpace.hpp>
81#include <Thyra_DefaultBlockedLinearOp.hpp>
82#include <Thyra_LinearOpBase.hpp>
83#include <Thyra_DetachedMultiVectorView.hpp>
84#include <Thyra_MultiVectorStdOps.hpp>
85
86#ifdef HAVE_XPETRA_TPETRA
87#include <Thyra_TpetraThyraWrappers.hpp>
88#include <Thyra_TpetraVector.hpp>
89#include <Thyra_TpetraMultiVector.hpp>
90#include <Thyra_TpetraVectorSpace.hpp>
91#include <Tpetra_Map.hpp>
92#include <Tpetra_Vector.hpp>
93#include <Tpetra_CrsMatrix.hpp>
94#include <Xpetra_TpetraMap.hpp>
95#include <Xpetra_TpetraCrsMatrix.hpp>
96#endif
97#ifdef HAVE_XPETRA_EPETRA
98#include <Thyra_EpetraLinearOp.hpp>
99#include <Thyra_EpetraThyraWrappers.hpp>
100#include <Thyra_SpmdVectorBase.hpp>
101#include <Thyra_get_Epetra_Operator.hpp>
102#include <Epetra_Map.h>
103#include <Epetra_Vector.h>
104#include <Epetra_CrsMatrix.h>
105#include <Xpetra_EpetraMap.hpp>
107#endif
108
109namespace Xpetra {
110
111template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node> class BlockedCrsMatrix;
112
113template <class Scalar,
114class LocalOrdinal = int,
115class GlobalOrdinal = LocalOrdinal,
117class ThyraUtils {
118
119private:
120#undef XPETRA_THYRAUTILS_SHORT
122
123public:
125 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) {
126
128
129 if(stridedBlockId == -1) {
130 TEUCHOS_TEST_FOR_EXCEPT(map->getNodeNumElements() % stridingInfo.size() != 0);
131 }
132 else {
133 TEUCHOS_TEST_FOR_EXCEPT(map->getNodeNumElements() % stridingInfo[stridedBlockId] != 0);
134 }
135
137 return ret;
138 }
139
141 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
142 using Teuchos::RCP;
143 using Teuchos::rcp_dynamic_cast;
144 using Teuchos::as;
145 using ThyVecSpaceBase = Thyra::VectorSpaceBase<Scalar>;
146 using ThyProdVecSpaceBase = Thyra::ProductVectorSpaceBase<Scalar>;
147 using ThyUtils = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
148
149
150 RCP<Map> resultMap = Teuchos::null;
151 RCP<const ThyProdVecSpaceBase > prodVectorSpace = rcp_dynamic_cast<const ThyProdVecSpaceBase >(vectorSpace);
152 if(prodVectorSpace != Teuchos::null) {
153 // SPECIAL CASE: product Vector space
154 // collect all submaps to store them in a hierarchical BlockedMap object
155 TEUCHOS_TEST_FOR_EXCEPTION(prodVectorSpace->numBlocks()==0, std::logic_error, "Found a product vector space with zero blocks.");
156 std::vector<RCP<const Map> > mapsThyra(prodVectorSpace->numBlocks(), Teuchos::null);
157 std::vector<RCP<const Map> > mapsXpetra(prodVectorSpace->numBlocks(), Teuchos::null);
158 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
159 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
160 // can be of type Map or BlockedMap (containing Thyra GIDs)
161 mapsThyra[b] = ThyUtils::toXpetra(bv, comm); // recursive call
162 }
163
164 // get offsets for submap GIDs
165 // we need that for the full map (Xpetra GIDs)
166 std::vector<GlobalOrdinal> gidOffsets(prodVectorSpace->numBlocks(),0);
167 for(int i = 1; i < prodVectorSpace->numBlocks(); ++i) {
168 gidOffsets[i] = mapsThyra[i-1]->getMaxAllGlobalIndex() + gidOffsets[i-1] + 1;
169 }
170
171 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
172 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
173 // map can be of type Map or BlockedMap (containing Xpetra style GIDs)
174 mapsXpetra[b] = MapUtils::transformThyra2XpetraGIDs(*mapsThyra[b], gidOffsets[b]);
175 }
176
177 resultMap = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node>(mapsXpetra, mapsThyra));
178 } else {
179#ifdef HAVE_XPETRA_TPETRA
180 // STANDARD CASE: no product map
181 // check whether we have a Tpetra based Thyra operator
182 Teuchos::RCP<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_vsc = Teuchos::rcp_dynamic_cast<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(vectorSpace);
183 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.");
184
185 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
186 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
187 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
188 typedef Thyra::VectorBase<Scalar> ThyVecBase;
189 RCP<ThyVecBase> rgVec = Thyra::createMember<Scalar>(vectorSpace, std::string("label"));
191 RCP<const TpVector> rgTpetraVec = TOE::getTpetraVector(rgVec);
193 RCP<const TpMap> rgTpetraMap = rgTpetraVec->getMap();
195 resultMap = Xpetra::toXpetraNonConst(rgTpetraMap);
196#else
197 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.");
198#endif
199 } // end standard case (no product map)
201 return resultMap;
202 }
203
204 // const version
206 toXpetra(Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
207 using Teuchos::RCP;
208 using Teuchos::rcp_dynamic_cast;
209 using Teuchos::as;
210
211 using ThyMultVecBase = Thyra::MultiVectorBase<Scalar>;
212 using ThyProdMultVecBase = Thyra::ProductMultiVectorBase<Scalar>;
213 using ThyUtils = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
214
215 // return value
216 RCP<MultiVector> xpMultVec = Teuchos::null;
217
218 // check whether v is a product multi vector
219 Teuchos::RCP<const ThyProdMultVecBase> thyProdVec = rcp_dynamic_cast<const ThyProdMultVecBase >(v);
220 if(thyProdVec != Teuchos::null) {
221 // SPECIAL CASE: create a nested BlockedMultiVector
222 // generate nested BlockedMap (containing Thyra and Xpetra GIDs)
223 RCP<Map> fullMap = ThyUtils::toXpetra(v->range(), comm);
224 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(Teuchos::rcp_dynamic_cast<BlockedMap>(fullMap)));
225
226 // create new Xpetra::BlockedMultiVector
227 xpMultVec = MultiVectorFactory::Build(fullMap, as<size_t>(thyProdVec->domain()->dim()));
228
229 RCP<BlockedMultiVector> xpBlockedMultVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xpMultVec);
230 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpBlockedMultVec));
231
232 // loop over all blocks, transform Thyra MultiVectors to Xpetra MultiVectors recursively
233 for (int b = 0; b < thyProdVec->productSpace()->numBlocks(); ++b){
234 RCP<const ThyMultVecBase> thyBlockMV = thyProdVec->getMultiVectorBlock(b);
235 // xpBlockMV can be of type MultiVector or BlockedMultiVector
236 RCP<const MultiVector> xpBlockMV = ThyUtils::toXpetra(thyBlockMV, comm); //recursive call
237 xpBlockedMultVec->setMultiVector(b, xpBlockMV, true /* Thyra mode */);
238 }
239 } else {
240 // STANDARD CASE: no product vector
241#ifdef HAVE_XPETRA_TPETRA
242 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> ConverterT;
243 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpMultVec;
245 typedef Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyTpMultVec;
246 typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
247
248 RCP<const ThySpmdMultVecBase> thyraSpmdMultiVector = rcp_dynamic_cast<const ThySpmdMultVecBase>(v);
249 RCP<const ThyTpMultVec> thyraTpetraMultiVector = rcp_dynamic_cast<const ThyTpMultVec>(thyraSpmdMultiVector);
250 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.");
251 const RCP<const TpMultVec> tpMultVec = ConverterT::getConstTpetraMultiVector(v);
253 RCP<TpMultVec> tpNonConstMultVec = Teuchos::rcp_const_cast<TpMultVec>(tpMultVec);
254 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpNonConstMultVec));
255 xpMultVec = rcp(new XpTpMultVec(tpNonConstMultVec));
256#else
257 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.");
258#endif
259 } // end standard case
261 return xpMultVec;
262 }
263
264 // non-const version
266 toXpetra(Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
268 Teuchos::rcp_const_cast<const Thyra::MultiVectorBase<Scalar> >(v);
270 toXpetra(cv,comm);
271 return Teuchos::rcp_const_cast<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(r);
272 }
273
274
275 static bool isTpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
277
278 // check whether we have a Tpetra based Thyra operator
279 bool bIsTpetra = false;
280#ifdef HAVE_XPETRA_TPETRA
281 Teuchos::RCP<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_op = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(op);
282 bIsTpetra = Teuchos::is_null(tpetra_op) ? false : true;
283
284 // for debugging purposes: find out why dynamic cast failed
285 if(!bIsTpetra &&
286#ifdef HAVE_XPETRA_EPETRA
287 Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op) == Teuchos::null &&
288#endif
289 Teuchos::rcp_dynamic_cast<const Thyra::DefaultBlockedLinearOp<Scalar> >(op) == Teuchos::null) {
290 // If op is not blocked and not an Epetra object, it should be in fact an Tpetra object
291 typedef Thyra::TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> TpetraLinearOp_t;
292 if(Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op) == Teuchos::null) {
293 std::cout << "ATTENTION: The dynamic cast to the TpetraLinearOp failed even though it should be a TpetraLinearOp." << std::endl;
294 std::cout << " If you are using Panzer or Stratimikos you might check that the template parameters are " << std::endl;
295 std::cout << " properly set!" << std::endl;
296 std::cout << Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op, true) << std::endl;
297 }
298 }
299#endif
300
301#if 0
302 // Check whether it is a blocked operator.
303 // If yes, grab the (0,0) block and check the underlying linear algebra
304 // Note: we expect that the (0,0) block exists!
305 if(bIsTpetra == false) {
307 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
308 if(ThyBlockedOp != Teuchos::null) {
309 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
311 ThyBlockedOp->getBlock(0,0);
313 bIsTpetra = isTpetra(b00);
314 }
315 }
316#endif
317
318 return bIsTpetra;
319 }
320
321 static bool isEpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
322 return false;
323 }
324
325 static bool isBlockedOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
326 // Check whether it is a blocked operator.
328 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
329 if(ThyBlockedOp != Teuchos::null) {
330 return true;
331 }
332 return false;
333 }
334
336 toXpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
337
338#ifdef HAVE_XPETRA_TPETRA
339 if(isTpetra(op)) {
340 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
341 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
342 // we should also add support for the const versions!
343 //getConstTpetraOperator(const RCP<const LinearOpBase<Scalar> > &op);
345 Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
347 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat);
349 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraNcnstCrsMat = Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraCrsMat);
350 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(TpetraNcnstCrsMat));
351
355
357 Teuchos::rcp_dynamic_cast<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat);
358 return ret;
359 }
360#endif
361
362#ifdef HAVE_XPETRA_EPETRA
363 if(isEpetra(op)) {
364 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
365 }
366#endif
367 return Teuchos::null;
368 }
369
371 toXpetra(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
372
373#ifdef HAVE_XPETRA_TPETRA
374 if(isTpetra(op)) {
375 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
376 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
378 Teuchos::RCP<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
380 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat);
382
386 return xTpetraCrsMat;
387 }
388#endif
389
390#ifdef HAVE_XPETRA_EPETRA
391 if(isEpetra(op)) {
392 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
393 }
394#endif
395 return Teuchos::null;
396 }
397
400 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyraMap = Teuchos::null;
401
402 // check whether map is of type BlockedMap
403 RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
404 if(bmap.is_null() == false) {
405
407 for(size_t i = 0; i < bmap->getNumMaps(); i++) {
408 // we need Thyra GIDs for all the submaps
410 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(bmap->getMap(i,true));
411 vecSpaces[i] = vs;
412 }
413
414 thyraMap = Thyra::productVectorSpace<Scalar>(vecSpaces());
415 return thyraMap;
416 }
417
418 // standard case
419#ifdef HAVE_XPETRA_TPETRA
420 if(map->lib() == Xpetra::UseTpetra) {
421 Teuchos::RCP<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> > tpetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> >(map);
422 if (tpetraMap == Teuchos::null)
423 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::TpetraMap failed");
424 RCP<Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > thyraTpetraMap = Thyra::tpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, Node>(tpetraMap->getTpetra_Map());
425 thyraMap = thyraTpetraMap;
426 }
427#endif
428
429#ifdef HAVE_XPETRA_EPETRA
430 if(map->lib() == Xpetra::UseEpetra) {
431 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
432 }
433#endif
434
435 return thyraMap;
436 }
437
440
441 // create Thyra MultiVector
442#ifdef HAVE_XPETRA_TPETRA
443 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
444 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
445 RCP<Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpMV = Teuchos::rcp_dynamic_cast<const TpetraMultiVector>(vec)->getTpetra_MultiVector();
446 auto thyDomMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(vec->getNumVectors(), vec->getMap()->getComm()));
447 auto thyMV = rcp(new Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
448 thyMV->initialize(thyTpMap, thyDomMap, tpMV);
449 return thyMV;
450 }
451#endif
452
453#ifdef HAVE_XPETRA_EPETRA
454 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
455 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
456 }
457#endif
458
459 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "MultiVector cannot be converted to Thyra.");
460 }
461
464
465 // create Thyra Vector
466#ifdef HAVE_XPETRA_TPETRA
467 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
468 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
469 RCP<Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpVec = Teuchos::rcp_dynamic_cast<const TpetraVector>(vec)->getTpetra_Vector();
470 auto thyVec = rcp(new Thyra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
471 thyVec->initialize(thyTpMap, tpVec);
472 return thyVec;
473 }
474#endif
475
476#ifdef HAVE_XPETRA_EPETRA
477 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
478 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
479 }
480#endif
481
482 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Vector cannot be converted to Thyra.");
483 }
484
485 // update Thyra multi vector with data from Xpetra multi vector
486 // In case of a Thyra::ProductMultiVector the Xpetra::MultiVector is splitted into its subparts using a provided MapExtractor
487 static void
488 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) {
489 using Teuchos::RCP;
490 using Teuchos::rcp_dynamic_cast;
491 using Teuchos::as;
492 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
493 typedef Thyra::SpmdVectorSpaceBase<Scalar> ThySpmdVecSpaceBase;
494 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
495 //typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
496 //typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
497 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
498
499
500 // copy data from tY_inout to Y_inout
501 RCP<ThyProdMultVecBase> prodTarget = rcp_dynamic_cast<ThyProdMultVecBase>(target);
502 if(prodTarget != Teuchos::null) {
503 RCP<const BlockedMultiVector> bSourceVec = rcp_dynamic_cast<const BlockedMultiVector>(source);
504 if(bSourceVec.is_null() == true) {
505 // SPECIAL CASE: target vector is product vector:
506 // update Thyra product multi vector with data from a merged Xpetra multi vector
507
508 TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor == Teuchos::null, std::logic_error, "Found a Thyra product vector, but user did not provide an Xpetra::MapExtractor.");
509 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.");
510
511 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
512 // access Xpetra data
513 RCP<MultiVector> xpSubBlock = mapExtractor->ExtractVector(source, bbb, false); // use Xpetra ordering (doesn't really matter)
514
515 // access Thyra data
516 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
517 RCP<const ThyVecSpaceBase> vs = thySubBlock->range();
518 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(vs);
519 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
520 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : vs->dim() );
521 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
522 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*thySubBlock,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
523
524 // loop over all vectors in multivector
525 for(size_t j = 0; j < xpSubBlock->getNumVectors(); ++j) {
526 Teuchos::ArrayRCP< const Scalar > xpData = xpSubBlock->getData(j); // access const data from Xpetra object
527
528 // loop over all local rows
529 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
530 (*thyData)(i,j) = xpData[i];
531 }
532 }
533 }
534 } else {
535 // source vector is a blocked multivector
536 // TODO test me
537 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.");
538
539 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
540 // access Thyra data
541 RCP<MultiVector> xpSubBlock = bSourceVec->getMultiVector(bbb, true); // use Thyra ordering
542
543 Teuchos::RCP<const ThyMultVecBase> thyXpSubBlock = toThyraMultiVector(xpSubBlock);
544
545 // access Thyra data
546 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
547 Thyra::assign(thySubBlock.ptr(), *thyXpSubBlock);
548 }
549
550 }
551 } else {
552 // STANDARD case:
553 // update Thyra::MultiVector with data from an Xpetra::MultiVector
554
555 // access Thyra data
556 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(target->range());
557 TEUCHOS_TEST_FOR_EXCEPTION(mpi_vs == Teuchos::null, std::logic_error, "Failed to cast Thyra::VectorSpaceBase to Thyra::SpmdVectorSpaceBase.");
558 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
559 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : target->range()->dim() );
560 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
561 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*target,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
562
563 // loop over all vectors in multivector
564 for(size_t j = 0; j < source->getNumVectors(); ++j) {
565 Teuchos::ArrayRCP< const Scalar > xpData = source->getData(j); // access const data from Xpetra object
566 // loop over all local rows
567 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
568 (*thyData)(i,j) = xpData[i];
569 }
570 }
571 }
572 }
573
576 // create a Thyra operator from Xpetra::CrsMatrix
577 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
578
579 //bool bIsTpetra = false;
580
581#ifdef HAVE_XPETRA_TPETRA
582 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
583 if(tpetraMat!=Teuchos::null) {
584 //bIsTpetra = true;
585 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
589
590 Teuchos::RCP<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat);
592 Teuchos::RCP<const Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<const Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat);
594
595 thyraOp = Thyra::createConstLinearOp(tpOperator);
597 } else {
598#ifdef HAVE_XPETRA_EPETRA
599 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");
600#else
601 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to Tpetra::CrsMatrix failed. Assume matrix should be Epetra then. No Epetra available");
602#endif
603 }
604 return thyraOp;
605#else
606 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
607 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
608#endif
609 }
610
613 // create a Thyra operator from Xpetra::CrsMatrix
614 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
615
616 //bool bIsTpetra = false;
617
618#ifdef HAVE_XPETRA_TPETRA
619 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
620 if(tpetraMat!=Teuchos::null) {
621 //bIsTpetra = true;
622 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
624 Teuchos::RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrixNonConst();
626
627 Teuchos::RCP<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat);
629 Teuchos::RCP<Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat);
631
632 thyraOp = Thyra::createLinearOp(tpOperator);
634 } else {
635 // cast to TpetraCrsMatrix failed
636#ifdef HAVE_XPETRA_EPETRA
637 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");
638#else
639 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to TpetraCrsMatrix failed. Guess, matrix should be Epetra then, but no Epetra available.");
640#endif
641 }
642 return thyraOp;
643#else
644 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
645 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
646#endif
647 }
648
651
652 int nRows = mat->Rows();
653 int nCols = mat->Cols();
654
656 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Ablock_wrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(Ablock);
657 TEUCHOS_TEST_FOR_EXCEPT(Ablock_wrap.is_null() == true);
658
659#ifdef HAVE_XPETRA_TPETRA
660 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(Ablock_wrap->getCrsMatrix());
661 if(tpetraMat!=Teuchos::null) {
662
663 // create new Thyra blocked operator
665 Thyra::defaultBlockedLinearOp<Scalar>();
666
667 blockMat->beginBlockFill(nRows,nCols);
668
669 for (int r=0; r<nRows; ++r) {
670 for (int c=0; c<nCols; ++c) {
671 Teuchos::RCP<Matrix> xpmat = mat->getMatrix(r,c);
672
673 if(xpmat == Teuchos::null) continue; // shortcut for empty blocks
674
675 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thBlock = Teuchos::null;
676
677 // check whether the subblock is again a blocked operator
679 Teuchos::rcp_dynamic_cast<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xpmat);
680 if(xpblock != Teuchos::null) {
681 if(xpblock->Rows() == 1 && xpblock->Cols() == 1) {
682 // If it is a single block operator, unwrap it
683 Teuchos::RCP<CrsMatrixWrap> xpwrap = Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(xpblock->getCrsMatrix());
684 TEUCHOS_TEST_FOR_EXCEPT(xpwrap.is_null() == true);
685 thBlock = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpwrap->getCrsMatrix());
686 } else {
687 // recursive call for general blocked operators
688 thBlock = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpblock);
689 }
690 } else {
691 // check whether it is a CRSMatrix object
692 Teuchos::RCP<CrsMatrixWrap> xpwrap = Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(xpmat);
693 TEUCHOS_TEST_FOR_EXCEPT(xpwrap.is_null() == true);
694 thBlock = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpwrap->getCrsMatrix());
695 }
696
697 blockMat->setBlock(r,c,thBlock);
698 }
699 }
700
701 blockMat->endBlockFill();
702
703 return blockMat;
704 } else {
705 // tpetraMat == Teuchos::null
706#ifdef HAVE_XPETRA_EPETRA
707 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");
708#else
709 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Cast to TpetraCrsMatrix failed. Guess, matrix should be Epetra then, but no Epetra available.");
710#endif
711 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
712 }
713#endif // endif HAVE_XPETRA_TPETRA
714
715//4-Aug-2017 JJH Added 2nd condition to avoid "warning: dynamic initialization in unreachable code"
716// If HAVE_XPETRA_TPETRA is defined, then this method will always return or throw in the if-then-else above.
717#if defined(HAVE_XPETRA_EPETRA) && !defined(HAVE_XPETRA_TPETRA)
718 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Epetra needs SC=double, LO=int, and GO=int or GO=long long");
719 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
720#endif // endif HAVE_XPETRA_EPETRA
721 }
722
723}; // end Utils class
724
725
726// full specialization for Epetra support
727// Note, that Thyra only has support for Epetra (not for Epetra64)
728#ifdef HAVE_XPETRA_EPETRA
729
730#ifndef XPETRA_EPETRA_NO_32BIT_GLOBAL_INDICES
731template <>
732class ThyraUtils<double, int, int, EpetraNode> {
733public:
734 typedef double Scalar;
735 typedef int LocalOrdinal;
736 typedef int GlobalOrdinal;
737 typedef EpetraNode Node;
738
739private:
740#undef XPETRA_THYRAUTILS_SHORT
742
743public:
744
746 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) {
747
749
750 if(stridedBlockId == -1) {
751 TEUCHOS_TEST_FOR_EXCEPT(map->getNodeNumElements() % stridingInfo.size() != 0);
752 }
753 else {
754 TEUCHOS_TEST_FOR_EXCEPT(map->getNodeNumElements() % stridingInfo[stridedBlockId] != 0);
755 }
756
758 return ret;
759 }
760
762 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
763 using Teuchos::RCP;
764 using Teuchos::rcp_dynamic_cast;
765 using Teuchos::as;
766 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
767 typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
768 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyUtils;
769
770 RCP<Map> resultMap = Teuchos::null;
771
772 RCP<const ThyProdVecSpaceBase > prodVectorSpace = rcp_dynamic_cast<const ThyProdVecSpaceBase >(vectorSpace);
773 if(prodVectorSpace != Teuchos::null) {
774 // SPECIAL CASE: product Vector space
775 // collect all submaps to store them in a hierarchical BlockedMap object
776 TEUCHOS_TEST_FOR_EXCEPTION(prodVectorSpace->numBlocks()==0, std::logic_error, "Found a product vector space with zero blocks.");
777 std::vector<RCP<const Map> > mapsThyra(prodVectorSpace->numBlocks(), Teuchos::null);
778 std::vector<RCP<const Map> > mapsXpetra(prodVectorSpace->numBlocks(), Teuchos::null);
779 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
780 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
781 // can be of type Map or BlockedMap (containing Thyra GIDs)
782 mapsThyra[b] = ThyUtils::toXpetra(bv, comm); // recursive call
783 }
784
785 // get offsets for submap GIDs
786 // we need that for the full map (Xpetra GIDs)
787 std::vector<GlobalOrdinal> gidOffsets(prodVectorSpace->numBlocks(),0);
788 for(int i = 1; i < prodVectorSpace->numBlocks(); ++i) {
789 gidOffsets[i] = mapsThyra[i-1]->getMaxAllGlobalIndex() + gidOffsets[i-1] + 1;
790 }
791
792 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
793 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
794 // map can be of type Map or BlockedMap (containing Xpetra style GIDs)
795 mapsXpetra[b] = MapUtils::transformThyra2XpetraGIDs(*mapsThyra[b], gidOffsets[b]);
796 }
797
798 resultMap = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node>(mapsXpetra, mapsThyra));
799 } else {
800 // STANDARD CASE: no product map
801 // Epetra/Tpetra specific code to access the underlying map data
802
803 // check whether we have a Tpetra based Thyra operator
804 bool bIsTpetra = false;
805#ifdef HAVE_XPETRA_TPETRA
806#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
807 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
808 Teuchos::RCP<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_vsc = Teuchos::rcp_dynamic_cast<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(vectorSpace);
809 bIsTpetra = Teuchos::is_null(tpetra_vsc) ? false : true;
810#endif
811#endif
812
813 // check whether we have an Epetra based Thyra operator
814 bool bIsEpetra = !bIsTpetra; // note: this is a little bit fragile!
815
816#ifdef HAVE_XPETRA_TPETRA
817 if(bIsTpetra) {
818#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
819 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
820 typedef Thyra::VectorBase<Scalar> ThyVecBase;
821 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
822 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
823 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
824 RCP<ThyVecBase> rgVec = Thyra::createMember<Scalar>(vectorSpace, std::string("label"));
826 RCP<const TpVector> rgTpetraVec = TOE::getTpetraVector(rgVec);
828 RCP<const TpMap> rgTpetraMap = rgTpetraVec->getMap();
830
831 resultMap = Xpetra::toXpetraNonConst(rgTpetraMap);
832#else
833 throw Xpetra::Exceptions::RuntimeError("Problem AAA. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
834#endif
835 }
836#endif
837
838#ifdef HAVE_XPETRA_EPETRA
839 if(bIsEpetra) {
840 //RCP<const Epetra_Map> epMap = Teuchos::null;
841 RCP<const Epetra_Map>
842 epetra_map = Teuchos::get_extra_data<RCP<const Epetra_Map> >(vectorSpace,"epetra_map");
843 if(!Teuchos::is_null(epetra_map)) {
844 resultMap = Teuchos::rcp(new Xpetra::EpetraMapT<GlobalOrdinal,Node>(epetra_map));
846 } else {
847 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "No Epetra_Map data found in Thyra::VectorSpace.");
848 }
849 }
850#endif
851 } // end standard case (no product map)
853 return resultMap;
854 }
855
856 // const version
858 toXpetra(Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
859 using Teuchos::RCP;
860 using Teuchos::rcp_dynamic_cast;
861 using Teuchos::as;
862
863 using ThyProdMultVecBase = Thyra::ProductMultiVectorBase<Scalar>;
864 using ThyMultVecBase = Thyra::MultiVectorBase<Scalar>;
865 using ThyUtils = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>;
866
867 // return value
868 RCP<MultiVector> xpMultVec = Teuchos::null;
869
870 // check whether v is a product multi vector
871 Teuchos::RCP<const ThyProdMultVecBase> thyProdVec = rcp_dynamic_cast<const ThyProdMultVecBase >(v);
872 if(thyProdVec != Teuchos::null) {
873 // SPECIAL CASE: create a nested BlockedMultiVector
874 // generate nested BlockedMap (containing Thyra and Xpetra GIDs)
875 RCP<Map> fullMap = ThyUtils::toXpetra(v->range(), comm);
876 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(Teuchos::rcp_dynamic_cast<BlockedMap>(fullMap)));
877
878 // create new Xpetra::BlockedMultiVector
879 xpMultVec = MultiVectorFactory::Build(fullMap, as<size_t>(thyProdVec->domain()->dim()));
880
881 RCP<BlockedMultiVector> xpBlockedMultVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xpMultVec);
882 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpBlockedMultVec));
883
884 // loop over all blocks, transform Thyra MultiVectors to Xpetra MultiVectors recursively
885 for (int b = 0; b < thyProdVec->productSpace()->numBlocks(); ++b){
886 RCP<const ThyMultVecBase> thyBlockMV = thyProdVec->getMultiVectorBlock(b);
887 // xpBlockMV can be of type MultiVector or BlockedMultiVector
888 RCP<const MultiVector> xpBlockMV = ThyUtils::toXpetra(thyBlockMV, comm); //recursive call
889 xpBlockedMultVec->setMultiVector(b, xpBlockMV, true /* Thyra mode */);
890 }
891
893 return xpMultVec;
894 } else {
895 // STANDARD CASE: no product vector
896 // Epetra/Tpetra specific code to access the underlying map data
897 bool bIsTpetra = false;
898#ifdef HAVE_XPETRA_TPETRA
899#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
900 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
901
902 //typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
903 //typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
904 typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
905 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> ConverterT;
906 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpMultVec;
908 typedef Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyTpMultVec;
909
910 RCP<const ThySpmdMultVecBase> thyraSpmdMultiVector = rcp_dynamic_cast<const ThySpmdMultVecBase>(v);
911 RCP<const ThyTpMultVec> thyraTpetraMultiVector = rcp_dynamic_cast<const ThyTpMultVec>(thyraSpmdMultiVector);
912 if(thyraTpetraMultiVector != Teuchos::null) {
913 bIsTpetra = true;
914 const RCP<const TpMultVec> tpMultVec = ConverterT::getConstTpetraMultiVector(v);
916 RCP<TpMultVec> tpNonConstMultVec = Teuchos::rcp_const_cast<TpMultVec>(tpMultVec);
917 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpNonConstMultVec));
918 xpMultVec = rcp(new XpTpMultVec(tpNonConstMultVec));
919 }
920#endif
921#endif
922
923#ifdef HAVE_XPETRA_EPETRA
924 if(bIsTpetra == false) {
925 // no product vector
926 Teuchos::RCP<Map> map = ThyUtils::toXpetra(v->range(), comm);
928 RCP<Xpetra::EpetraMapT<GlobalOrdinal,Node> > xeMap = rcp_dynamic_cast<Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map);
930 RCP<const Epetra_Map> eMap = xeMap->getEpetra_MapRCP();
932 Teuchos::RCP<const Epetra_MultiVector> epMultVec = Thyra::get_Epetra_MultiVector(*eMap, v);
934 RCP<Epetra_MultiVector> epNonConstMultVec = Teuchos::rcp_const_cast<Epetra_MultiVector>(epMultVec);
935 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epNonConstMultVec));
936 xpMultVec = Teuchos::rcp(new Xpetra::EpetraMultiVectorT<GlobalOrdinal,Node>(epNonConstMultVec));
937 }
938#endif
940 return xpMultVec;
941 } // end standard case
942 }
943
944 // non-const version
946 toXpetra(Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
948 Teuchos::rcp_const_cast<const Thyra::MultiVectorBase<Scalar> >(v);
950 toXpetra(cv,comm);
951 return Teuchos::rcp_const_cast<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(r);
952 }
953
954 static bool isTpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
955 // check whether we have a Tpetra based Thyra operator
956 bool bIsTpetra = false;
957#ifdef HAVE_XPETRA_TPETRA
958#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
959 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
960
961 Teuchos::RCP<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_op = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(op);
962 bIsTpetra = Teuchos::is_null(tpetra_op) ? false : true;
963
964 // for debugging purposes: find out why dynamic cast failed
965 if(!bIsTpetra &&
966#ifdef HAVE_XPETRA_EPETRA
967 Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op) == Teuchos::null &&
968#endif
969 Teuchos::rcp_dynamic_cast<const Thyra::DefaultBlockedLinearOp<Scalar> >(op) == Teuchos::null) {
970 // If op is not blocked and not an Epetra object, it should be in fact an Tpetra object
971 typedef Thyra::TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> TpetraLinearOp_t;
972 if(Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op) == Teuchos::null) {
973 std::cout << "ATTENTION: The dynamic cast to the TpetraLinearOp failed even though it should be a TpetraLinearOp." << std::endl;
974 std::cout << " If you are using Panzer or Stratimikos you might check that the template parameters are " << std::endl;
975 std::cout << " properly set!" << std::endl;
976 std::cout << Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op, true) << std::endl;
977 }
978 }
979#endif
980#endif
981
982#if 0
983 // Check whether it is a blocked operator.
984 // If yes, grab the (0,0) block and check the underlying linear algebra
985 // Note: we expect that the (0,0) block exists!
986 if(bIsTpetra == false) {
988 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
989 if(ThyBlockedOp != Teuchos::null) {
990 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
992 ThyBlockedOp->getBlock(0,0);
994 bIsTpetra = isTpetra(b00);
995 }
996 }
997#endif
998
999 return bIsTpetra;
1000 }
1001
1002 static bool isEpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1003 // check whether we have an Epetra based Thyra operator
1004 bool bIsEpetra = false;
1005
1006#ifdef HAVE_XPETRA_EPETRA
1007 Teuchos::RCP<const Thyra::EpetraLinearOp> epetra_op = Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op,false);
1008 bIsEpetra = Teuchos::is_null(epetra_op) ? false : true;
1009#endif
1010
1011#if 0
1012 // Check whether it is a blocked operator.
1013 // If yes, grab the (0,0) block and check the underlying linear algebra
1014 // Note: we expect that the (0,0) block exists!
1015 if(bIsEpetra == false) {
1017 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op,false);
1018 if(ThyBlockedOp != Teuchos::null) {
1019 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1021 ThyBlockedOp->getBlock(0,0);
1023 bIsEpetra = isEpetra(b00);
1024 }
1025 }
1026#endif
1027
1028 return bIsEpetra;
1029 }
1030
1031 static bool isBlockedOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1032 // Check whether it is a blocked operator.
1034 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1035 if(ThyBlockedOp != Teuchos::null) {
1036 return true;
1037 }
1038 return false;
1039 }
1040
1042 toXpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
1043
1044#ifdef HAVE_XPETRA_TPETRA
1045 if(isTpetra(op)) {
1046#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1047 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1048
1049 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1050 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
1051 // we should also add support for the const versions!
1052 //getConstTpetraOperator(const RCP<const LinearOpBase<Scalar> > &op);
1054 Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
1056 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat);
1058 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraNcnstCrsMat = Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraCrsMat);
1059 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(TpetraNcnstCrsMat));
1060
1065 Teuchos::rcp_dynamic_cast<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat);
1067 return ret;
1068#else
1069 throw Xpetra::Exceptions::RuntimeError("Problem BBB. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1070#endif
1071 }
1072#endif
1073
1074#ifdef HAVE_XPETRA_EPETRA
1075 if(isEpetra(op)) {
1076 Teuchos::RCP<const Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1078 Teuchos::RCP<const Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(epetra_op);
1080 Teuchos::RCP<const Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(epetra_rowmat);
1082 Teuchos::RCP<Epetra_CrsMatrix> epetra_ncnstcrsmat = Teuchos::rcp_const_cast<Epetra_CrsMatrix>(epetra_crsmat);
1083 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epetra_ncnstcrsmat));
1084
1088
1090 Teuchos::rcp_dynamic_cast<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xEpetraCrsMat);
1092 return ret;
1093 }
1094#endif
1095 return Teuchos::null;
1096 }
1097
1099 toXpetra(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
1100
1101#ifdef HAVE_XPETRA_TPETRA
1102 if(isTpetra(op)) {
1103#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1104 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1105
1106 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1107 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
1109 Teuchos::RCP<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
1111 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat);
1113
1117 return xTpetraCrsMat;
1118#else
1119 throw Xpetra::Exceptions::RuntimeError("Problem CCC. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1120#endif
1121 }
1122#endif
1123
1124#ifdef HAVE_XPETRA_EPETRA
1125 if(isEpetra(op)) {
1126 Teuchos::RCP<Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1128 Teuchos::RCP<Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(epetra_op);
1130 Teuchos::RCP<Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(epetra_rowmat);
1132
1136 return xEpetraCrsMat;
1137 }
1138#endif
1139 return Teuchos::null;
1140 }
1141
1144 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyraMap = Teuchos::null;
1145
1146 // check whether map is of type BlockedMap
1147 RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
1148 if(bmap.is_null() == false) {
1149
1151 for(size_t i = 0; i < bmap->getNumMaps(); i++) {
1152 // we need Thyra GIDs for all the submaps
1154 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(bmap->getMap(i,true));
1155 vecSpaces[i] = vs;
1156 }
1157
1158 thyraMap = Thyra::productVectorSpace<Scalar>(vecSpaces());
1159 return thyraMap;
1160 }
1161
1162 // standard case
1163#ifdef HAVE_XPETRA_TPETRA
1164 if(map->lib() == Xpetra::UseTpetra) {
1165#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1166 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1167 Teuchos::RCP<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> > tpetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> >(map);
1168 if (tpetraMap == Teuchos::null)
1169 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::TpetraMap failed");
1170 RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > tpMap = tpetraMap->getTpetra_Map();
1171 RCP<Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > thyraTpetraMap = Thyra::tpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, Node>(tpMap);
1172 thyraMap = thyraTpetraMap;
1173#else
1174 throw Xpetra::Exceptions::RuntimeError("Problem DDD. Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1175#endif
1176 }
1177#endif
1178
1179#ifdef HAVE_XPETRA_EPETRA
1180 if(map->lib() == Xpetra::UseEpetra) {
1181 Teuchos::RCP<const Xpetra::EpetraMapT<GlobalOrdinal,Node> > epetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map);
1182 if (epetraMap == Teuchos::null)
1183 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::EpetraMap failed");
1184 RCP<const Thyra::VectorSpaceBase<Scalar> > thyraEpetraMap = Thyra::create_VectorSpace(epetraMap->getEpetra_MapRCP());
1185 thyraMap = thyraEpetraMap;
1186 }
1187#endif
1188
1189 return thyraMap;
1190 }
1191
1194
1195 // create Thyra MultiVector
1196#ifdef HAVE_XPETRA_TPETRA
1197 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
1198 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
1199 RCP<Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpMV = Teuchos::rcp_dynamic_cast<const TpetraMultiVector>(vec)->getTpetra_MultiVector();
1200 auto thyDomMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(vec->getNumVectors(), vec->getMap()->getComm()));
1201 auto thyMV = rcp(new Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
1202 thyMV->initialize(thyTpMap, thyDomMap, tpMV);
1203 return thyMV;
1204 }
1205#endif
1206
1207#ifdef HAVE_XPETRA_EPETRA
1208 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
1209 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
1210 auto epMV = Teuchos::rcp_dynamic_cast<const EpetraMultiVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_MultiVector();
1211 auto thyMV = Thyra::create_MultiVector(epMV, thyEpMap);
1212 return thyMV;
1213 }
1214#endif
1215
1216 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "MultiVector cannot be converted to Thyra.");
1217
1218 }
1219
1222
1223 // create Thyra Vector
1224#ifdef HAVE_XPETRA_TPETRA
1225 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
1226 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
1227 RCP<Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpVec = Teuchos::rcp_dynamic_cast<const TpetraVector>(vec)->getTpetra_Vector();
1228 auto thyVec = rcp(new Thyra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
1229 thyVec->initialize(thyTpMap, tpVec);
1230 return thyVec;
1231 }
1232#endif
1233
1234#ifdef HAVE_XPETRA_EPETRA
1235 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
1236 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
1237 auto epVec = rcp(Teuchos::rcp_dynamic_cast<const EpetraVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_Vector(), false);
1238 auto thyVec = Thyra::create_Vector(epVec, thyEpMap);
1239 return thyVec;
1240 }
1241#endif
1242
1243 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Vector cannot be converted to Thyra.");
1244 }
1245
1246 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) {
1247 using Teuchos::RCP;
1248 using Teuchos::rcp_dynamic_cast;
1249 using Teuchos::as;
1250 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
1251 typedef Thyra::SpmdVectorSpaceBase<Scalar> ThySpmdVecSpaceBase;
1252 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
1253 //typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
1254 //typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
1255 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
1256
1257 // copy data from tY_inout to Y_inout
1258 RCP<ThyProdMultVecBase> prodTarget = rcp_dynamic_cast<ThyProdMultVecBase>(target);
1259 if(prodTarget != Teuchos::null) {
1260
1261 RCP<const BlockedMultiVector> bSourceVec = rcp_dynamic_cast<const BlockedMultiVector>(source);
1262 if(bSourceVec.is_null() == true) {
1263 // SPECIAL CASE: target vector is product vector:
1264 // update Thyra product multi vector with data from a merged Xpetra multi vector
1265
1266 TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor == Teuchos::null, std::logic_error, "Found a Thyra product vector, but user did not provide an Xpetra::MapExtractor.");
1267 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.");
1268
1269 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
1270 // access Xpetra data
1271 RCP<MultiVector> xpSubBlock = mapExtractor->ExtractVector(source, bbb, false); // use Xpetra ordering (doesn't really matter)
1272
1273 // access Thyra data
1274 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
1275 RCP<const ThyVecSpaceBase> vs = thySubBlock->range();
1276 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(vs);
1277 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
1278 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : vs->dim() );
1279 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
1280 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*thySubBlock,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
1281
1282 // loop over all vectors in multivector
1283 for(size_t j = 0; j < xpSubBlock->getNumVectors(); ++j) {
1284 Teuchos::ArrayRCP< const Scalar > xpData = xpSubBlock->getData(j); // access const data from Xpetra object
1285
1286 // loop over all local rows
1287 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
1288 (*thyData)(i,j) = xpData[i];
1289 }
1290 }
1291 }
1292 } else {
1293 // source vector is a blocked multivector
1294 // TODO test me
1295 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.");
1296
1297 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
1298 // access Thyra data
1299 RCP<MultiVector> xpSubBlock = bSourceVec->getMultiVector(bbb, true); // use Thyra ordering
1300
1301 Teuchos::RCP<const ThyMultVecBase> thyXpSubBlock = toThyraMultiVector(xpSubBlock);
1302
1303 // access Thyra data
1304 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
1305 Thyra::assign(thySubBlock.ptr(), *thyXpSubBlock);
1306 }
1307
1308 }
1309 } else {
1310 // STANDARD case:
1311 // update Thyra::MultiVector with data from an Xpetra::MultiVector
1312
1313 // access Thyra data
1314 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(target->range());
1315 TEUCHOS_TEST_FOR_EXCEPTION(mpi_vs == Teuchos::null, std::logic_error, "Failed to cast Thyra::VectorSpaceBase to Thyra::SpmdVectorSpaceBase.");
1316 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
1317 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : target->range()->dim() );
1318 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
1319 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*target,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
1320
1321 // loop over all vectors in multivector
1322 for(size_t j = 0; j < source->getNumVectors(); ++j) {
1323 Teuchos::ArrayRCP< const Scalar > xpData = source->getData(j); // access const data from Xpetra object
1324 // loop over all local rows
1325 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
1326 (*thyData)(i,j) = xpData[i];
1327 }
1328 }
1329 }
1330 }
1331
1334 // create a Thyra operator from Xpetra::CrsMatrix
1335 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
1336
1337#ifdef HAVE_XPETRA_TPETRA
1338 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
1339 if(tpetraMat!=Teuchos::null) {
1340#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1341 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1342
1343 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
1345 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrix();
1347
1348 Teuchos::RCP<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat);
1350 Teuchos::RCP<const Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<const Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat);
1352
1353 thyraOp = Thyra::createConstLinearOp(tpOperator);
1355#else
1356 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1357#endif
1358 }
1359#endif
1360
1361#ifdef HAVE_XPETRA_EPETRA
1362 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1363 if(epetraMat!=Teuchos::null) {
1364 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1366 Teuchos::RCP<const Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrix();
1368
1369 Teuchos::RCP<const Thyra::EpetraLinearOp> thyraEpOp = Thyra::epetraLinearOp(epCrsMat,"op");
1371 thyraOp = thyraEpOp;
1372 }
1373#endif
1374 return thyraOp;
1375 }
1376
1379 // create a Thyra operator from Xpetra::CrsMatrix
1380 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
1381
1382#ifdef HAVE_XPETRA_TPETRA
1383 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
1384 if(tpetraMat!=Teuchos::null) {
1385#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1386 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT) && defined(HAVE_TPETRA_INST_DOUBLE)))
1387
1388 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
1390 Teuchos::RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrixNonConst();
1392
1393 Teuchos::RCP<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat);
1395 Teuchos::RCP<Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat);
1397
1398 thyraOp = Thyra::createLinearOp(tpOperator);
1400#else
1401 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_INT:BOOL=ON in your configuration.");
1402#endif
1403 }
1404#endif
1405
1406#ifdef HAVE_XPETRA_EPETRA
1407 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1408 if(epetraMat!=Teuchos::null) {
1409 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
1411 Teuchos::RCP<Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrixNonConst();
1413
1414 Teuchos::RCP<Thyra::EpetraLinearOp> thyraEpOp = Thyra::nonconstEpetraLinearOp(epCrsMat,"op");
1416 thyraOp = thyraEpOp;
1417 }
1418#endif
1419 return thyraOp;
1420 }
1421
1424
1425}; // specialization on SC=double, LO=GO=int and NO=EpetraNode
1426#endif // #ifndef XPETRA_EPETRA_NO_32BIT_GLOBAL_INDICES
1427
1428#ifndef XPETRA_EPETRA_NO_64BIT_GLOBAL_INDICES
1429template <>
1430class ThyraUtils<double, int, long long, EpetraNode> {
1431public:
1432 typedef double Scalar;
1433 typedef int LocalOrdinal;
1434 typedef long long GlobalOrdinal;
1435 typedef EpetraNode Node;
1436
1437private:
1438#undef XPETRA_THYRAUTILS_SHORT
1439#include "Xpetra_UseShortNames.hpp"
1440
1441public:
1442
1444 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) {
1445
1447
1448 if(stridedBlockId == -1) {
1449 TEUCHOS_TEST_FOR_EXCEPT(map->getNodeNumElements() % stridingInfo.size() != 0);
1450 }
1451 else {
1452 TEUCHOS_TEST_FOR_EXCEPT(map->getNodeNumElements() % stridingInfo[stridedBlockId] != 0);
1453 }
1454
1456 return ret;
1457 }
1458
1460 toXpetra(const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >& vectorSpace, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1461 using Teuchos::RCP;
1462 using Teuchos::rcp_dynamic_cast;
1463 using Teuchos::as;
1464 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
1465 typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
1466 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyUtils;
1467
1468 RCP<const ThyProdVecSpaceBase > prodVectorSpace = rcp_dynamic_cast<const ThyProdVecSpaceBase >(vectorSpace);
1469 if(prodVectorSpace != Teuchos::null) {
1470 // SPECIAL CASE: product Vector space
1471 // collect all submaps to store them in a hierarchical BlockedMap object
1472 TEUCHOS_TEST_FOR_EXCEPTION(prodVectorSpace->numBlocks()==0, std::logic_error, "Found a product vector space with zero blocks.");
1473 std::vector<RCP<const Map> > mapsThyra(prodVectorSpace->numBlocks(), Teuchos::null);
1474 std::vector<RCP<const Map> > mapsXpetra(prodVectorSpace->numBlocks(), Teuchos::null);
1475 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
1476 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
1477 // can be of type Map or BlockedMap (containing Thyra GIDs)
1478 mapsThyra[b] = ThyUtils::toXpetra(bv, comm); // recursive call
1479 }
1480
1481 // get offsets for submap GIDs
1482 // we need that for the full map (Xpetra GIDs)
1483 std::vector<GlobalOrdinal> gidOffsets(prodVectorSpace->numBlocks(),0);
1484 for(int i = 1; i < prodVectorSpace->numBlocks(); ++i) {
1485 gidOffsets[i] = mapsThyra[i-1]->getMaxAllGlobalIndex() + gidOffsets[i-1] + 1;
1486 }
1487
1488 for (int b = 0; b < prodVectorSpace->numBlocks(); ++b){
1489 RCP<const ThyVecSpaceBase > bv = prodVectorSpace->getBlock(b);
1490 // map can be of type Map or BlockedMap (containing Xpetra style GIDs)
1491 mapsXpetra[b] = MapUtils::transformThyra2XpetraGIDs(*mapsThyra[b], gidOffsets[b]);
1492 }
1493
1496 return resultMap;
1497 } else {
1498 // STANDARD CASE: no product map
1499 // Epetra/Tpetra specific code to access the underlying map data
1500
1501 // check whether we have a Tpetra based Thyra operator
1502 bool bIsTpetra = false;
1503#ifdef HAVE_XPETRA_TPETRA
1504#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1505 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1506 Teuchos::RCP<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_vsc = Teuchos::rcp_dynamic_cast<const Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(vectorSpace);
1507 bIsTpetra = Teuchos::is_null(tpetra_vsc) ? false : true;
1508#endif
1509#endif
1510
1511 // check whether we have an Epetra based Thyra operator
1512 bool bIsEpetra = !bIsTpetra; // note: this is a little bit fragile!
1513
1514#ifdef HAVE_XPETRA_TPETRA
1515 if(bIsTpetra) {
1516#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1517 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1518 typedef Thyra::VectorBase<Scalar> ThyVecBase;
1519 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
1520 typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
1521 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1522 RCP<ThyVecBase> rgVec = Thyra::createMember<Scalar>(vectorSpace, std::string("label"));
1524 RCP<const TpVector> rgTpetraVec = TOE::getTpetraVector(rgVec);
1526 RCP<const TpMap> rgTpetraMap = rgTpetraVec->getMap();
1528
1529 RCP<Map> rgXpetraMap = Xpetra::toXpetraNonConst(rgTpetraMap);
1531 return rgXpetraMap;
1532#else
1533 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
1534#endif
1535 }
1536#endif
1537
1538#ifdef HAVE_XPETRA_EPETRA
1539 if(bIsEpetra) {
1540 //RCP<const Epetra_Map> epMap = Teuchos::null;
1541 RCP<const Epetra_Map>
1542 epetra_map = Teuchos::get_extra_data<RCP<const Epetra_Map> >(vectorSpace,"epetra_map");
1543 if(!Teuchos::is_null(epetra_map)) {
1546 return rgXpetraMap;
1547 } else {
1548 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "No Epetra_Map data found in Thyra::VectorSpace.");
1549 }
1550 }
1551#endif
1552 } // end standard case (no product map)
1553 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "Cannot transform Thyra::VectorSpace to Xpetra::Map.");
1554 // return Teuchos::null; // unreachable
1555 }
1556
1557 // const version
1559 toXpetra(Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1560 using Teuchos::RCP;
1561 using Teuchos::rcp_dynamic_cast;
1562 using Teuchos::as;
1563 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
1564 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
1565 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyUtils;
1566
1567 // return value
1568 RCP<MultiVector> xpMultVec = Teuchos::null;
1569
1570 // check whether v is a product multi vector
1571 Teuchos::RCP<const ThyProdMultVecBase> thyProdVec = rcp_dynamic_cast<const ThyProdMultVecBase >(v);
1572 if(thyProdVec != Teuchos::null) {
1573 // SPECIAL CASE: create a nested BlockedMultiVector
1574 // generate nested BlockedMap (containing Thyra and Xpetra GIDs)
1575 RCP<Map> fullMap = ThyUtils::toXpetra(v->range(), comm);
1576 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(Teuchos::rcp_dynamic_cast<BlockedMap>(fullMap)));
1577
1578 // create new Xpetra::BlockedMultiVector
1579 xpMultVec = MultiVectorFactory::Build(fullMap, as<size_t>(thyProdVec->domain()->dim()));
1580
1581 RCP<BlockedMultiVector> xpBlockedMultVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xpMultVec);
1582 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpBlockedMultVec));
1583
1584 // loop over all blocks, transform Thyra MultiVectors to Xpetra MultiVectors recursively
1585 for (int b = 0; b < thyProdVec->productSpace()->numBlocks(); ++b){
1586 RCP<const ThyMultVecBase> thyBlockMV = thyProdVec->getMultiVectorBlock(b);
1587 // xpBlockMV can be of type MultiVector or BlockedMultiVector
1588 RCP<const MultiVector> xpBlockMV = ThyUtils::toXpetra(thyBlockMV, comm); //recursive call
1589 xpBlockedMultVec->setMultiVector(b, xpBlockMV, true /* Thyra mode */);
1590 }
1591
1593 return xpMultVec;
1594 } else {
1595 // STANDARD CASE: no product vector
1596 // Epetra/Tpetra specific code to access the underlying map data
1597 bool bIsTpetra = false;
1598#ifdef HAVE_XPETRA_TPETRA
1599#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1600 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1601
1602 //typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> TpMap;
1603 //typedef Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpVector;
1604 typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
1605 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> ConverterT;
1606 typedef Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpMultVec;
1608 typedef Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyTpMultVec;
1609
1610 RCP<const ThySpmdMultVecBase> thyraSpmdMultiVector = rcp_dynamic_cast<const ThySpmdMultVecBase>(v);
1611 RCP<const ThyTpMultVec> thyraTpetraMultiVector = rcp_dynamic_cast<const ThyTpMultVec>(thyraSpmdMultiVector);
1612 if(thyraTpetraMultiVector != Teuchos::null) {
1613 bIsTpetra = true;
1614 const RCP<const TpMultVec> tpMultVec = ConverterT::getConstTpetraMultiVector(v);
1616 RCP<TpMultVec> tpNonConstMultVec = Teuchos::rcp_const_cast<TpMultVec>(tpMultVec);
1617 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpNonConstMultVec));
1618 xpMultVec = rcp(new XpTpMultVec(tpNonConstMultVec));
1620 return xpMultVec;
1621 }
1622#endif
1623#endif
1624
1625#ifdef HAVE_XPETRA_EPETRA
1626 if(bIsTpetra == false) {
1627 // no product vector
1628 Teuchos::RCP<Map> map = ThyUtils::toXpetra(v->range(), comm);
1630 RCP<Xpetra::EpetraMapT<GlobalOrdinal,Node> > xeMap = rcp_dynamic_cast<Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map);
1632 RCP<const Epetra_Map> eMap = xeMap->getEpetra_MapRCP();
1634 Teuchos::RCP<const Epetra_MultiVector> epMultVec = Thyra::get_Epetra_MultiVector(*eMap, v);
1636 RCP<Epetra_MultiVector> epNonConstMultVec = Teuchos::rcp_const_cast<Epetra_MultiVector>(epMultVec);
1637 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epNonConstMultVec));
1638 xpMultVec = Teuchos::rcp(new Xpetra::EpetraMultiVectorT<GlobalOrdinal,Node>(epNonConstMultVec));
1640 return xpMultVec;
1641 }
1642#endif
1643 } // end standard case
1644 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error, "Cannot transform Thyra::MultiVector to Xpetra::MultiVector.");
1645 // return Teuchos::null; // unreachable
1646 }
1647
1648 // non-const version
1650 toXpetra(Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > v, const Teuchos::RCP<const Teuchos::Comm<int> >& comm) {
1652 Teuchos::rcp_const_cast<const Thyra::MultiVectorBase<Scalar> >(v);
1654 toXpetra(cv,comm);
1655 return Teuchos::rcp_const_cast<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(r);
1656 }
1657
1658 static bool isTpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1659 // check whether we have a Tpetra based Thyra operator
1660 bool bIsTpetra = false;
1661#ifdef HAVE_XPETRA_TPETRA
1662#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1663 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1664
1665 Teuchos::RCP<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpetra_op = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(op);
1666 bIsTpetra = Teuchos::is_null(tpetra_op) ? false : true;
1667
1668 // for debugging purposes: find out why dynamic cast failed
1669 if(!bIsTpetra &&
1670#ifdef HAVE_XPETRA_EPETRA
1671 Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op) == Teuchos::null &&
1672#endif
1673 Teuchos::rcp_dynamic_cast<const Thyra::DefaultBlockedLinearOp<Scalar> >(op) == Teuchos::null) {
1674 // If op is not blocked and not an Epetra object, it should be in fact an Tpetra object
1675 typedef Thyra::TpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> TpetraLinearOp_t;
1676 if(Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op) == Teuchos::null) {
1677 std::cout << "ATTENTION: The dynamic cast to the TpetraLinearOp failed even though it should be a TpetraLinearOp." << std::endl;
1678 std::cout << " If you are using Panzer or Stratimikos you might check that the template parameters are " << std::endl;
1679 std::cout << " properly set!" << std::endl;
1680 std::cout << Teuchos::rcp_dynamic_cast<const TpetraLinearOp_t>(op, true) << std::endl;
1681 }
1682 }
1683#endif
1684#endif
1685
1686#if 0
1687 // Check whether it is a blocked operator.
1688 // If yes, grab the (0,0) block and check the underlying linear algebra
1689 // Note: we expect that the (0,0) block exists!
1690 if(bIsTpetra == false) {
1692 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1693 if(ThyBlockedOp != Teuchos::null) {
1694 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1696 ThyBlockedOp->getBlock(0,0);
1698 bIsTpetra = isTpetra(b00);
1699 }
1700 }
1701#endif
1702
1703 return bIsTpetra;
1704 }
1705
1706 static bool isEpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1707 // check whether we have an Epetra based Thyra operator
1708 bool bIsEpetra = false;
1709
1710#ifdef HAVE_XPETRA_EPETRA
1711 Teuchos::RCP<const Thyra::EpetraLinearOp> epetra_op = Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(op,false);
1712 bIsEpetra = Teuchos::is_null(epetra_op) ? false : true;
1713#endif
1714
1715#if 0
1716 // Check whether it is a blocked operator.
1717 // If yes, grab the (0,0) block and check the underlying linear algebra
1718 // Note: we expect that the (0,0) block exists!
1719 if(bIsEpetra == false) {
1721 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op,false);
1722 if(ThyBlockedOp != Teuchos::null) {
1723 TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
1725 ThyBlockedOp->getBlock(0,0);
1727 bIsEpetra = isEpetra(b00);
1728 }
1729 }
1730#endif
1731
1732 return bIsEpetra;
1733 }
1734
1735 static bool isBlockedOperator(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > & op){
1736 // Check whether it is a blocked operator.
1738 Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(op);
1739 if(ThyBlockedOp != Teuchos::null) {
1740 return true;
1741 }
1742 return false;
1743 }
1744
1746 toXpetra(const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >& op) {
1747
1748#ifdef HAVE_XPETRA_TPETRA
1749 if(isTpetra(op)) {
1750#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1751 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1752
1753 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1754 Teuchos::RCP<const Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getConstTpetraOperator(op);
1755 // we should also add support for the const versions!
1756 //getConstTpetraOperator(const RCP<const LinearOpBase<Scalar> > &op);
1758 Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
1760 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat);
1762 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraNcnstCrsMat = Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraCrsMat);
1763 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(TpetraNcnstCrsMat));
1764
1769 Teuchos::rcp_dynamic_cast<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xTpetraCrsMat);
1771 return ret;
1772#else
1773 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
1774#endif
1775 }
1776#endif
1777
1778#ifdef HAVE_XPETRA_EPETRA
1779 if(isEpetra(op)) {
1780 Teuchos::RCP<const Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1782 Teuchos::RCP<const Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(epetra_op);
1784 Teuchos::RCP<const Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(epetra_rowmat);
1786 Teuchos::RCP<Epetra_CrsMatrix> epetra_ncnstcrsmat = Teuchos::rcp_const_cast<Epetra_CrsMatrix>(epetra_crsmat);
1787 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(epetra_ncnstcrsmat));
1788
1792
1794 Teuchos::rcp_dynamic_cast<const Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xEpetraCrsMat);
1796 return ret;
1797 }
1798#endif
1799 return Teuchos::null;
1800 }
1801
1803 toXpetra(const Teuchos::RCP<Thyra::LinearOpBase<Scalar> >& op) {
1804
1805#ifdef HAVE_XPETRA_TPETRA
1806 if(isTpetra(op)) {
1807#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1808 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1809
1810 typedef Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node> TOE;
1811 Teuchos::RCP<Tpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraOp = TOE::getTpetraOperator(op);
1813 Teuchos::RCP<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraOp);
1815 Teuchos::RCP<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > TpetraCrsMat = Teuchos::rcp_dynamic_cast<Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(TpetraRowMat);
1817
1821 return xTpetraCrsMat;
1822#else
1823 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
1824#endif
1825 }
1826#endif
1827
1828#ifdef HAVE_XPETRA_EPETRA
1829 if(isEpetra(op)) {
1830 Teuchos::RCP<Epetra_Operator> epetra_op = Thyra::get_Epetra_Operator( *op );
1832 Teuchos::RCP<Epetra_RowMatrix> epetra_rowmat = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(epetra_op);
1834 Teuchos::RCP<Epetra_CrsMatrix> epetra_crsmat = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(epetra_rowmat);
1836
1840 return xEpetraCrsMat;
1841 }
1842#endif
1843 return Teuchos::null;
1844 }
1845
1848 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyraMap = Teuchos::null;
1849
1850 // check whether map is of type BlockedMap
1851 RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
1852 if(bmap.is_null() == false) {
1853
1855 for(size_t i = 0; i < bmap->getNumMaps(); i++) {
1856 // we need Thyra GIDs for all the submaps
1858 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(bmap->getMap(i,true));
1859 vecSpaces[i] = vs;
1860 }
1861
1862 thyraMap = Thyra::productVectorSpace<Scalar>(vecSpaces());
1863 return thyraMap;
1864 }
1865
1866 // standard case
1867#ifdef HAVE_XPETRA_TPETRA
1868 if(map->lib() == Xpetra::UseTpetra) {
1869#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
1870 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
1871 Teuchos::RCP<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> > tpetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraMap<LocalOrdinal,GlobalOrdinal,Node> >(map);
1872 if (tpetraMap == Teuchos::null)
1873 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::TpetraMap failed");
1874 RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > tpMap = tpetraMap->getTpetra_Map();
1875 RCP<Thyra::TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> > thyraTpetraMap = Thyra::tpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, Node>(tpMap);
1876 thyraMap = thyraTpetraMap;
1877#else
1878 throw Xpetra::Exceptions::RuntimeError("Problem DDD. Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
1879#endif
1880 }
1881#endif
1882
1883#ifdef HAVE_XPETRA_EPETRA
1884 if(map->lib() == Xpetra::UseEpetra) {
1885 Teuchos::RCP<const Xpetra::EpetraMapT<GlobalOrdinal,Node> > epetraMap = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraMapT<GlobalOrdinal,Node> >(map);
1886 if (epetraMap == Teuchos::null)
1887 throw Exceptions::BadCast("Xpetra::ThyraUtils::toThyra: Cast from Xpetra::Map to Xpetra::EpetraMap failed");
1888 RCP<const Thyra::VectorSpaceBase<Scalar> > thyraEpetraMap = Thyra::create_VectorSpace(epetraMap->getEpetra_MapRCP());
1889 thyraMap = thyraEpetraMap;
1890 }
1891#endif
1892
1893 return thyraMap;
1894 }
1895
1898
1899 // create Thyra MultiVector
1900#ifdef HAVE_XPETRA_TPETRA
1901 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
1902 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
1903 RCP<Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpMV = Teuchos::rcp_dynamic_cast<const TpetraMultiVector>(vec)->getTpetra_MultiVector();
1904 auto thyDomMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(vec->getNumVectors(), vec->getMap()->getComm()));
1905 auto thyMV = rcp(new Thyra::TpetraMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
1906 thyMV->initialize(thyTpMap, thyDomMap, tpMV);
1907 return thyMV;
1908 }
1909#endif
1910
1911#ifdef HAVE_XPETRA_EPETRA
1912 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
1913 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
1914 auto epMV = Teuchos::rcp_dynamic_cast<const EpetraMultiVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_MultiVector();
1915 auto thyMV = Thyra::create_MultiVector(epMV, thyEpMap);
1916 return thyMV;
1917 }
1918#endif
1919
1920 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "MultiVector cannot be converted to Thyra.");
1921 }
1922
1925
1926 // create Thyra Vector
1927#ifdef HAVE_XPETRA_TPETRA
1928 if (vec->getMap()->lib() == Xpetra::UseTpetra) {
1929 auto thyTpMap = Thyra::tpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcp_dynamic_cast<const TpetraMap>(vec->getMap())->getTpetra_Map());
1930 RCP<Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> tpVec = Teuchos::rcp_dynamic_cast<const TpetraVector>(vec)->getTpetra_Vector();
1931 auto thyVec = rcp(new Thyra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>());
1932 thyVec->initialize(thyTpMap, tpVec);
1933 return thyVec;
1934 }
1935#endif
1936
1937#ifdef HAVE_XPETRA_EPETRA
1938 if (vec->getMap()->lib() == Xpetra::UseEpetra) {
1939 auto thyEpMap = Thyra::create_VectorSpace(Teuchos::rcp_dynamic_cast<const EpetraMapT<GlobalOrdinal, Node> >(vec->getMap())->getEpetra_MapRCP());
1940 auto epVec = rcp(Teuchos::rcp_dynamic_cast<const EpetraVectorT<GlobalOrdinal, Node> >(vec)->getEpetra_Vector(), false);
1941 auto thyVec = Thyra::create_Vector(epVec, thyEpMap);
1942 return thyVec;
1943 }
1944#endif
1945
1946 TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::RuntimeError, "Vector cannot be converted to Thyra.");
1947 }
1948
1949 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) {
1950 using Teuchos::RCP;
1951 using Teuchos::rcp_dynamic_cast;
1952 using Teuchos::as;
1953 typedef Thyra::VectorSpaceBase<Scalar> ThyVecSpaceBase;
1954 typedef Thyra::SpmdVectorSpaceBase<Scalar> ThySpmdVecSpaceBase;
1955 typedef Thyra::MultiVectorBase<Scalar> ThyMultVecBase;
1956 //typedef Thyra::SpmdMultiVectorBase<Scalar> ThySpmdMultVecBase;
1957 //typedef Thyra::ProductVectorSpaceBase<Scalar> ThyProdVecSpaceBase;
1958 typedef Thyra::ProductMultiVectorBase<Scalar> ThyProdMultVecBase;
1959
1960 // copy data from tY_inout to Y_inout
1961 RCP<ThyProdMultVecBase> prodTarget = rcp_dynamic_cast<ThyProdMultVecBase>(target);
1962 if(prodTarget != Teuchos::null) {
1963 RCP<const BlockedMultiVector> bSourceVec = rcp_dynamic_cast<const BlockedMultiVector>(source);
1964 if(bSourceVec.is_null() == true) {
1965 // SPECIAL CASE: target vector is product vector:
1966 // update Thyra product multi vector with data from a merged Xpetra multi vector
1967
1968 TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor == Teuchos::null, std::logic_error, "Found a Thyra product vector, but user did not provide an Xpetra::MapExtractor.");
1969 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.");
1970
1971 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
1972 // access Xpetra data
1973 RCP<MultiVector> xpSubBlock = mapExtractor->ExtractVector(source, bbb, false); // use Xpetra ordering (doesn't really matter)
1974
1975 // access Thyra data
1976 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
1977 RCP<const ThyVecSpaceBase> vs = thySubBlock->range();
1978 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(vs);
1979 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
1980 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : vs->dim() );
1981 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
1982 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*thySubBlock,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
1983
1984 // loop over all vectors in multivector
1985 for(size_t j = 0; j < xpSubBlock->getNumVectors(); ++j) {
1986 Teuchos::ArrayRCP< const Scalar > xpData = xpSubBlock->getData(j); // access const data from Xpetra object
1987
1988 // loop over all local rows
1989 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
1990 (*thyData)(i,j) = xpData[i];
1991 }
1992 }
1993 }
1994 } else {
1995 // source vector is a blocked multivector
1996 // TODO test me
1997 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.");
1998
1999 for(int bbb = 0; bbb < prodTarget->productSpace()->numBlocks(); ++bbb) {
2000 // access Thyra data
2001 RCP<MultiVector> xpSubBlock = bSourceVec->getMultiVector(bbb, true); // use Thyra ordering
2002
2003 Teuchos::RCP<const ThyMultVecBase> thyXpSubBlock = toThyraMultiVector(xpSubBlock);
2004
2005 // access Thyra data
2006 Teuchos::RCP<ThyMultVecBase> thySubBlock = prodTarget->getNonconstMultiVectorBlock(bbb);
2007 Thyra::assign(thySubBlock.ptr(), *thyXpSubBlock);
2008 }
2009
2010 }
2011 } else {
2012 // STANDARD case:
2013 // update Thyra::MultiVector with data from an Xpetra::MultiVector
2014
2015 // access Thyra data
2016 RCP<const ThySpmdVecSpaceBase> mpi_vs = rcp_dynamic_cast<const ThySpmdVecSpaceBase>(target->range());
2017 TEUCHOS_TEST_FOR_EXCEPTION(mpi_vs == Teuchos::null, std::logic_error, "Failed to cast Thyra::VectorSpaceBase to Thyra::SpmdVectorSpaceBase.");
2018 const LocalOrdinal localOffset = ( mpi_vs != Teuchos::null ? mpi_vs->localOffset() : 0 );
2019 const LocalOrdinal localSubDim = ( mpi_vs != Teuchos::null ? mpi_vs->localSubDim() : target->range()->dim() );
2020 RCP<Thyra::DetachedMultiVectorView<Scalar> > thyData =
2021 Teuchos::rcp(new Thyra::DetachedMultiVectorView<Scalar>(*target,Teuchos::Range1D(localOffset,localOffset+localSubDim-1)));
2022
2023 // loop over all vectors in multivector
2024 for(size_t j = 0; j < source->getNumVectors(); ++j) {
2025 Teuchos::ArrayRCP< const Scalar > xpData = source->getData(j); // access const data from Xpetra object
2026 // loop over all local rows
2027 for(LocalOrdinal i = 0; i < localSubDim; ++i) {
2028 (*thyData)(i,j) = xpData[i];
2029 }
2030 }
2031 }
2032 }
2033
2036 // create a Thyra operator from Xpetra::CrsMatrix
2037 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
2038
2039#ifdef HAVE_XPETRA_TPETRA
2040 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
2041 if(tpetraMat!=Teuchos::null) {
2042#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
2043 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
2044
2045 Teuchos::RCP<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
2047 Teuchos::RCP<const Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrix();
2049
2050 Teuchos::RCP<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<const Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat);
2052 Teuchos::RCP<const Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<const Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat);
2054
2055 thyraOp = Thyra::createConstLinearOp(tpOperator);
2057#else
2058 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
2059#endif
2060 }
2061#endif
2062
2063#ifdef HAVE_XPETRA_EPETRA
2064 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
2065 if(epetraMat!=Teuchos::null) {
2066 Teuchos::RCP<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
2068 Teuchos::RCP<const Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrix();
2070
2071 Teuchos::RCP<const Thyra::EpetraLinearOp> thyraEpOp = Thyra::epetraLinearOp(epCrsMat,"op");
2073 thyraOp = thyraEpOp;
2074 }
2075#endif
2076 return thyraOp;
2077 }
2078
2081 // create a Thyra operator from Xpetra::CrsMatrix
2082 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thyraOp = Teuchos::null;
2083
2084#ifdef HAVE_XPETRA_TPETRA
2085 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpetraMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
2086 if(tpetraMat!=Teuchos::null) {
2087#if ((defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)) || \
2088 (!defined(EPETRA_HAVE_OMP) && defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_LONG_LONG) && defined(HAVE_TPETRA_INST_DOUBLE)))
2089
2090 Teuchos::RCP<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > xTpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(mat);
2092 Teuchos::RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpCrsMat = xTpCrsMat->getTpetra_CrsMatrixNonConst();
2094
2095 Teuchos::RCP<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpRowMat = Teuchos::rcp_dynamic_cast<Tpetra::RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpCrsMat);
2097 Teuchos::RCP<Tpetra::Operator <Scalar, LocalOrdinal, GlobalOrdinal, Node> > tpOperator = Teuchos::rcp_dynamic_cast<Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tpRowMat);
2099
2100 thyraOp = Thyra::createLinearOp(tpOperator);
2102#else
2103 throw Xpetra::Exceptions::RuntimeError("Add TPETRA_INST_INT_LONG_LONG:BOOL=ON in your configuration.");
2104#endif
2105 }
2106#endif
2107
2108#ifdef HAVE_XPETRA_EPETRA
2109 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > epetraMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
2110 if(epetraMat!=Teuchos::null) {
2111 Teuchos::RCP<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> > xEpCrsMat = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> >(mat);
2113 Teuchos::RCP<Epetra_CrsMatrix> epCrsMat = xEpCrsMat->getEpetra_CrsMatrixNonConst();
2115
2116 Teuchos::RCP<Thyra::EpetraLinearOp> thyraEpOp = Thyra::nonconstEpetraLinearOp(epCrsMat,"op");
2118 thyraOp = thyraEpOp;
2119 }
2120#endif
2121 return thyraOp;
2122 }
2123
2126
2127}; // specialization on SC=double, LO=GO=int and NO=EpetraNode
2128#endif // XPETRA_EPETRA_NO_64BIT_GLOBAL_INDICES
2129
2130#endif // HAVE_XPETRA_EPETRA
2131
2132} // end namespace Xpetra
2133
2134#define XPETRA_THYRAUTILS_SHORT
2135#endif // HAVE_XPETRA_THYRA
2136
2137#endif // XPETRA_THYRAUTILS_HPP
bool is_null() const
Ptr< T > ptr() const
Exception throws to report errors in the internal logical of the program.
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > transformThyra2XpetraGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlReferenceInput)
replace set of global ids by new global ids
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &map, size_t NumVectors, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
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_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)
RCP< const CrsGraph< int, GlobalOrdinal, Node > > toXpetra(const Epetra_CrsGraph &g)