Zoltan2
Loading...
Searching...
No Matches
Zoltan2_XpetraTraits.hpp
Go to the documentation of this file.
1// @HEADER
2//
3// ***********************************************************************
4//
5// Zoltan2: A package of combinatorial algorithms for scientific computing
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 Karen Devine (kddevin@sandia.gov)
39// Erik Boman (egboman@sandia.gov)
40// Siva Rajamanickam (srajama@sandia.gov)
41//
42// ***********************************************************************
43//
44// @HEADER
45
50#ifndef _ZOLTAN2_XPETRATRAITS_HPP_
51#define _ZOLTAN2_XPETRATRAITS_HPP_
52
54#include <Zoltan2_Standards.hpp>
55
56#include <Xpetra_TpetraCrsGraph.hpp>
57#include <Xpetra_TpetraCrsMatrix.hpp>
58#include <Xpetra_TpetraVector.hpp>
59#include <Tpetra_Vector.hpp>
60
61#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
62#include <Xpetra_EpetraCrsMatrix.hpp>
63#include <Xpetra_EpetraVector.hpp>
64#include <Xpetra_EpetraUtils.hpp>
65#endif
66
67namespace Zoltan2 {
68
70// Extra traits needed only for Xpetra matrices and graphs
71
94template <typename User>
96{
99 static inline RCP<User> convertToXpetra(const RCP<User> &a)
100 {
101 return a;
102 }
103
107
111
117 static RCP<User> doMigration(const User &from,
118 size_t numLocalRows, const gno_t *myNewRows)
119 {
120 return Teuchos::null;
121 }
122};
123
124#ifndef DOXYGEN_SHOULD_SKIP_THIS
125
127// Tpetra::CrsMatrix
128template <typename scalar_t,
129 typename lno_t,
130 typename gno_t,
131 typename node_t>
132struct XpetraTraits<Tpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> >
133{
134 typedef typename Xpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> xmatrix_t;
135 typedef typename Xpetra::TpetraCrsMatrix<scalar_t,lno_t,gno_t,node_t> xtmatrix_t;
136 typedef typename Tpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> tmatrix_t;
137
138 static inline RCP<xmatrix_t> convertToXpetra(const RCP<tmatrix_t> &a)
139 {
140 return rcp(new xtmatrix_t(a));
141 }
142
143 static RCP<tmatrix_t> doMigration(const tmatrix_t &from,
144 size_t numLocalRows, const gno_t *myNewRows)
145 {
146 typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
147
148 // source map
149 const RCP<const map_t> &smap = from.getRowMap();
150 gno_t numGlobalRows = smap->getGlobalNumElements();
151 gno_t base = smap->getMinAllGlobalIndex();
152
153 // target map
154 ArrayView<const gno_t> rowList(myNewRows, numLocalRows);
155 const RCP<const Teuchos::Comm<int> > &comm = from.getComm();
156 RCP<const map_t> tmap = rcp(new map_t(numGlobalRows, rowList, base, comm));
157
158 // importer
159 Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
160
161 // target matrix
162 // Chris Siefert proposed using the following to make migration
163 // more efficient.
164 // By default, the Domain and Range maps are the same as in "from".
165 // As in the original code, we instead set them both to tmap.
166 // The assumption is a square matrix.
167 // TODO: what about rectangular matrices?
168 // TODO: Should choice of domain/range maps be an option to this function?
169
170 // KDD 3/7/16: disabling Chris' new code to avoid dashboard failures;
171 // KDD 3/7/16: can re-enable when issue #114 is fixed.
172 // KDD 3/7/16: when re-enable CSIEFERT code, can comment out
173 // KDD 3/7/16: "Original way" code.
174 // KDD 1/27/17: Re-enabling Chris' code, as this issue is resolved.
175 RCP<tmatrix_t> M;
176 from.importAndFillComplete(M, importer, tmap, tmap);
177
180 //int oldNumElts = smap->getLocalNumElements();
181 //int newNumElts = numLocalRows;
182
184 //typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> vector_t;
185 //vector_t numOld(smap); // TODO These vectors should have scalar=size_t,
186 //vector_t numNew(tmap); // but ETI does not yet support that.
187 //for (int lid=0; lid < oldNumElts; lid++){
188 //numOld.replaceGlobalValue(smap->getGlobalElement(lid),
189 //scalar_t(from.getNumEntriesInLocalRow(lid)));
190 //}
191 //numNew.doImport(numOld, importer, Tpetra::INSERT);
192
193 // TODO Could skip this copy if could declare vector with scalar=size_t.
194 //ArrayRCP<size_t> nnz(newNumElts);
195 //if (newNumElts > 0){
196 //ArrayRCP<scalar_t> ptr = numNew.getDataNonConst(0);
197 //for (int lid=0; lid < newNumElts; lid++){
198 //nnz[lid] = static_cast<size_t>(ptr[lid]);
199 //}
200 //}
201
202 //RCP<tmatrix_t> M = rcp(new tmatrix_t(tmap, nnz, Tpetra::StaticProfile));
203 //M->doImport(from, importer, Tpetra::INSERT);
204 //M->fillComplete();
205
206 // End of original way we did it.
207 return M;
208 }
209};
210
212#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
213// Epetra_CrsMatrix
214template <>
215struct XpetraTraits<Epetra_CrsMatrix>
216{
221
222 static inline RCP<Xpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> >
223 convertToXpetra(const RCP<Epetra_CrsMatrix> &a)
224 {
225 RCP<Xpetra::EpetraCrsMatrixT<gno_t, node_t> > xa;
226 try {
227 xa = rcp(new Xpetra::EpetraCrsMatrixT<gno_t, node_t>(a));
228 }
229 catch (std::exception &e) {
230 if (std::is_same<node_t, Xpetra::EpetraNode>::value)
231 throw std::runtime_error(std::string("Cannot convert from "
232 "Epetra_CrsMatrix to "
233 "Xpetra::EpetraCrsMatrixT\n")
234 + e.what());
235 else
236 throw std::runtime_error(std::string("Cannot convert from "
237 "Epetra_CrsMatrix to "
238 "Xpetra::EpetraCrsMatrixT\n"
239 "Use node_t that is supported by "
240 "Xpetra with Epetra classes\n")
241 + e.what());
242 }
243 return xa;
244 }
245
246
247 static RCP<Epetra_CrsMatrix> doMigration(const Epetra_CrsMatrix &from,
248 size_t numLocalRows, const gno_t *myNewRows)
249 {
250 // source map
251 const Epetra_Map &smap = from.RowMap();
252 gno_t numGlobalRows = smap.NumGlobalElements();
253 int base = smap.MinAllGID();
254
255 // target map
256 const Epetra_Comm &comm = from.Comm();
257 Epetra_Map tmap(numGlobalRows, numLocalRows, myNewRows, base, comm);
258
259 // importer
260 Epetra_Import importer(tmap, smap);
261
262
263 // target matrix
264 // Chris Siefert proposed using the following to make migration
265 // more efficient.
266 // By default, the Domain and Range maps are the same as in "from".
267 // As in the original code, we instead set them both to tmap.
268 // The assumption is a square matrix.
269 // TODO: what about rectangular matrices?
270 // TODO: Should choice of domain/range maps be an option to this function?
271
272 RCP<Epetra_CrsMatrix> M = rcp(new Epetra_CrsMatrix(from, importer,
273 &tmap, &tmap));
274
275 // Original way we did it:
276 //
277 // int oldNumElts = smap.NumMyElements();
278 //
279 // // number of non zeros in my new rows
280 // Epetra_Vector numOld(smap);
281 // Epetra_Vector numNew(tmap);
282 //
283 // for (int lid=0; lid < oldNumElts; lid++){
284 // numOld[lid] = from.NumMyEntries(lid);
285 // }
286 // numNew.Import(numOld, importer, Insert);
287 //
288 // int newNumElts = numLocalRows;
289 // Array<int> nnz(newNumElts);
290 // for (int lid=0; lid < newNumElts; lid++){
291 // nnz[lid] = static_cast<int>(numNew[lid]);
292 // }
293 //
294 // RCP<Epetra_CrsMatrix> M =
295 // rcp(new Epetra_CrsMatrix(::Copy, tmap, nnz.getRawPtr(), true));
296 // M->Import(from, importer, Insert);
297 // M->FillComplete();
298
299 return M;
300 }
301};
302#endif
303
305// Xpetra::CrsMatrix
306// KDDKDD: Do we need specializations for Xpetra::EpetraCrsMatrix and
307// KDDKDD: Xpetra::TpetraCrsMatrix
308template <typename scalar_t,
309 typename lno_t,
310 typename gno_t,
311 typename node_t>
312struct XpetraTraits<Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> >
313{
314 typedef Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> x_matrix_t;
315 typedef Xpetra::TpetraCrsMatrix<scalar_t, lno_t, gno_t, node_t> xt_matrix_t;
316 typedef Tpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> t_matrix_t;
317
318 static inline RCP<x_matrix_t> convertToXpetra(const RCP<x_matrix_t > &a)
319 {
320 return a;
321 }
322
323 static RCP<x_matrix_t> doMigration(const x_matrix_t &from,
324 size_t numLocalRows, const gno_t *myNewRows)
325 {
326 Xpetra::UnderlyingLib lib = from.getRowMap()->lib();
327
328 if (lib == Xpetra::UseEpetra){
329 throw std::logic_error("compiler should have used specialization");
330 } else{
331 // Do the import with the Tpetra::CrsMatrix traits object
332 const xt_matrix_t *xtm = dynamic_cast<const xt_matrix_t *>(&from);
333 RCP<const t_matrix_t> tm = xtm->getTpetra_CrsMatrix();
334
335 RCP<t_matrix_t> tmnew = XpetraTraits<t_matrix_t>::doMigration(
336 *tm, numLocalRows, myNewRows);
337
338 RCP<x_matrix_t> xmnew = XpetraTraits<t_matrix_t>::convertToXpetra(tmnew);
339
340 return xmnew;
341 }
342 }
343};
344
346// Xpetra::CrsMatrix specialization
347
348template <typename node_t>
349struct XpetraTraits<Xpetra::CrsMatrix<double, int, int, node_t> >
350{
351 typedef double scalar_t;
352 typedef int lno_t;
353 typedef int gno_t;
354 typedef Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> x_matrix_t;
355 typedef Xpetra::TpetraCrsMatrix<scalar_t, lno_t, gno_t, node_t> xt_matrix_t;
356 typedef Tpetra::CrsMatrix<scalar_t,lno_t,gno_t,node_t> t_matrix_t;
357
358 static inline RCP<x_matrix_t> convertToXpetra(const RCP<x_matrix_t > &a)
359 {
360 return a;
361 }
362
363 static RCP<x_matrix_t> doMigration(const x_matrix_t &from,
364 size_t numLocalRows, const gno_t *myNewRows)
365 {
366 Xpetra::UnderlyingLib lib = from.getRowMap()->lib();
367
368 if (lib == Xpetra::UseEpetra){
369#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
370 typedef Epetra_CrsMatrix e_matrix_t;
371 typedef Xpetra::EpetraCrsMatrixT<gno_t,node_t> xe_matrix_t;
372 // Do the import with the Epetra_CrsMatrix traits object
373 const xe_matrix_t *xem = dynamic_cast<const xe_matrix_t *>(&from);
374 RCP<const e_matrix_t> em = xem->getEpetra_CrsMatrix();
375
376 RCP<e_matrix_t> emnew = XpetraTraits<e_matrix_t>::doMigration(
377 *em, numLocalRows, myNewRows);
378
379 RCP<x_matrix_t> xmnew = XpetraTraits<e_matrix_t>::convertToXpetra(emnew);
380
381 return xmnew;
382#else
383 throw std::runtime_error("Xpetra with Epetra requested, but "
384 "Trilinos is not built with Epetra");
385#endif
386 } else{
387 // Do the import with the Tpetra::CrsMatrix traits object
388 const xt_matrix_t *xtm = dynamic_cast<const xt_matrix_t *>(&from);
389 RCP<const t_matrix_t> tm = xtm->getTpetra_CrsMatrix();
390
391 RCP<t_matrix_t> tmnew = XpetraTraits<t_matrix_t>::doMigration(
392 *tm, numLocalRows, myNewRows);
393
394 RCP<x_matrix_t> xmnew = XpetraTraits<t_matrix_t>::convertToXpetra(tmnew);
395
396 return xmnew;
397 }
398 }
399};
400
401
403// Tpetra::CrsGraph
404template <typename lno_t,
405 typename gno_t,
406 typename node_t>
407struct XpetraTraits<Tpetra::CrsGraph<lno_t, gno_t, node_t> >
408{
409 typedef typename Xpetra::CrsGraph<lno_t, gno_t, node_t> xgraph_t;
410 typedef typename Xpetra::TpetraCrsGraph<lno_t, gno_t, node_t> xtgraph_t;
411 typedef typename Tpetra::CrsGraph<lno_t, gno_t, node_t> tgraph_t;
412
413 static inline RCP<xgraph_t> convertToXpetra(const RCP<tgraph_t> &a)
414 {
415 return rcp(new xtgraph_t(a));
416 }
417
418 static RCP<tgraph_t> doMigration(const tgraph_t &from,
419 size_t numLocalRows, const gno_t *myNewRows)
420 {
421 typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
422
423 // source map
424 const RCP<const map_t> &smap = from.getRowMap();
425 int oldNumElts = smap->getLocalNumElements();
426 gno_t numGlobalRows = smap->getGlobalNumElements();
427 gno_t base = smap->getMinAllGlobalIndex();
428
429 // target map
430 ArrayView<const gno_t> rowList(myNewRows, numLocalRows);
431 const RCP<const Teuchos::Comm<int> > &comm = from.getComm();
432 RCP<const map_t> tmap = rcp(new map_t(numGlobalRows, rowList, base, comm));
433
434 // importer
435 Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
436
437 // number of entries in my new rows
438 typedef Tpetra::Vector<gno_t, lno_t, gno_t, node_t> vector_t;
439 vector_t numOld(smap);
440 vector_t numNew(tmap);
441 for (int lid=0; lid < oldNumElts; lid++){
442 numOld.replaceGlobalValue(smap->getGlobalElement(lid),
443 from.getNumEntriesInLocalRow(lid));
444 }
445 numNew.doImport(numOld, importer, Tpetra::INSERT);
446
447 size_t numElts = tmap->getLocalNumElements();
448 ArrayRCP<const gno_t> nnz;
449 if (numElts > 0)
450 nnz = numNew.getData(0); // hangs if vector len == 0
451
452 ArrayRCP<const size_t> nnz_size_t;
453
454 if (numElts && sizeof(gno_t) != sizeof(size_t)){
455 size_t *vals = new size_t [numElts];
456 nnz_size_t = arcp(vals, 0, numElts, true);
457 for (size_t i=0; i < numElts; i++){
458 vals[i] = static_cast<size_t>(nnz[i]);
459 }
460 }
461 else{
462 nnz_size_t = arcp_reinterpret_cast<const size_t>(nnz);
463 }
464
465 // target graph
466 RCP<tgraph_t> G = rcp(new tgraph_t(tmap, nnz_size_t()));
467
468 G->doImport(from, importer, Tpetra::INSERT);
469 G->fillComplete();
470
471 return G;
472 }
473
474};
475
477#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
478// Epetra_CrsGraph
479template < >
480struct XpetraTraits<Epetra_CrsGraph>
481{
485 static inline RCP<Xpetra::CrsGraph<lno_t,gno_t,node_t> >
486 convertToXpetra(const RCP<Epetra_CrsGraph> &a)
487 {
488 RCP<Xpetra::EpetraCrsGraphT<gno_t, node_t> > xa;
489 try {
490 xa = rcp(new Xpetra::EpetraCrsGraphT<gno_t, node_t>(a));
491 }
492 catch (std::exception &e) {
493 if (std::is_same<node_t, Xpetra::EpetraNode>::value)
494 throw std::runtime_error(std::string("Cannot convert from "
495 "Epetra_CrsGraph to "
496 "Xpetra::EpetraCrsGraphT\n")
497 + e.what());
498 else
499 throw std::runtime_error(std::string("Cannot convert from "
500 "Epetra_CrsGraph to "
501 "Xpetra::EpetraCrsGraphT\n"
502 "Use node_t that is supported by "
503 "Xpetra with Epetra classes\n")
504 + e.what());
505 }
506 return xa;
507 }
508
509 static RCP<Epetra_CrsGraph> doMigration(const Epetra_CrsGraph &from,
510 size_t numLocalRows, const gno_t *myNewRows)
511 {
512 // source map
513 const Epetra_BlockMap &smap = from.RowMap();
514 gno_t numGlobalRows = smap.NumGlobalElements();
515 lno_t oldNumElts = smap.NumMyElements();
516 int base = smap.MinAllGID();
517
518 // target map
519 const Epetra_Comm &comm = from.Comm();
520 Epetra_BlockMap tmap(numGlobalRows, numLocalRows, myNewRows, 1, base, comm);
521 lno_t newNumElts = tmap.NumMyElements();
522
523 // importer
524 Epetra_Import importer(tmap, smap);
525
526 // number of non zeros in my new rows
527 Epetra_Vector numOld(smap);
528 Epetra_Vector numNew(tmap);
529
530 for (int lid=0; lid < oldNumElts; lid++){
531 numOld[lid] = from.NumMyIndices(lid);
532 }
533 numNew.Import(numOld, importer, Insert);
534
535 Array<int> nnz(newNumElts);
536 for (int lid=0; lid < newNumElts; lid++){
537 nnz[lid] = static_cast<int>(numNew[lid]);
538 }
539
540 // target graph
541 RCP<Epetra_CrsGraph> G = rcp(new Epetra_CrsGraph(::Copy, tmap, nnz.getRawPtr(), true));
542 G->Import(from, importer, Insert);
543 G->FillComplete();
544
545 return G;
546 }
547
548};
549#endif
550
552// Xpetra::CrsGraph
553// KDDKDD Do we need specializations for Xpetra::TpetraCrsGraph and
554// KDDKDD Xpetra::EpetraCrsGraph?
555template <typename lno_t,
556 typename gno_t,
557 typename node_t>
558struct XpetraTraits<Xpetra::CrsGraph<lno_t, gno_t, node_t> >
559{
560 typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> x_graph_t;
561 typedef Xpetra::TpetraCrsGraph<lno_t, gno_t, node_t> xt_graph_t;
562 typedef Tpetra::CrsGraph<lno_t,gno_t,node_t> t_graph_t;
563
564 static inline RCP<x_graph_t> convertToXpetra(const RCP<x_graph_t> &a)
565 {
566 return a;
567 }
568
569 static RCP<x_graph_t> doMigration(const x_graph_t &from,
570 size_t numLocalRows, const gno_t *myNewRows)
571 {
572 Xpetra::UnderlyingLib lib = from.getRowMap()->lib();
573
574 if (lib == Xpetra::UseEpetra){
575 throw std::logic_error("compiler should have used specialization");
576 } else{
577 // Do the import with the Tpetra::CrsGraph traits object
578 const xt_graph_t *xtg = dynamic_cast<const xt_graph_t *>(&from);
579 RCP<const t_graph_t> tg = xtg->getTpetra_CrsGraph();
580
581 RCP<t_graph_t> tgnew = XpetraTraits<t_graph_t>::doMigration(
582 *tg, numLocalRows, myNewRows);
583
584 RCP<x_graph_t> xgnew = XpetraTraits<t_graph_t>::convertToXpetra(tgnew);
585 return xgnew;
586 }
587 }
588};
589
590
592// Xpetra::CrsGraph specialization
593template < typename node_t>
594struct XpetraTraits<Xpetra::CrsGraph<int, int, node_t> >
595{
596 typedef int lno_t;
597 typedef int gno_t;
598 typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> x_graph_t;
599 typedef Xpetra::TpetraCrsGraph<lno_t, gno_t, node_t> xt_graph_t;
600 typedef Tpetra::CrsGraph<lno_t,gno_t,node_t> t_graph_t;
601
602 static inline RCP<x_graph_t> convertToXpetra(const RCP<x_graph_t> &a)
603 {
604 return a;
605 }
606
607 static RCP<x_graph_t> doMigration(const x_graph_t &from,
608 size_t numLocalRows, const gno_t *myNewRows)
609 {
610 Xpetra::UnderlyingLib lib = from.getRowMap()->lib();
611
612 if (lib == Xpetra::UseEpetra){
613#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
614 typedef Xpetra::EpetraCrsGraphT<gno_t,node_t> xe_graph_t;
615 typedef Epetra_CrsGraph e_graph_t;
616 // Do the import with the Epetra_CrsGraph traits object
617 const xe_graph_t *xeg = dynamic_cast<const xe_graph_t *>(&from);
618 RCP<const e_graph_t> eg = xeg->getEpetra_CrsGraph();
619
620 RCP<e_graph_t> egnew = XpetraTraits<e_graph_t>::doMigration(
621 *eg, numLocalRows, myNewRows);
622
623 RCP<x_graph_t> xgnew = XpetraTraits<e_graph_t>::convertToXpetra(egnew);
624
625 return xgnew;
626#else
627 throw std::runtime_error("Xpetra with Epetra requested, but "
628 "Trilinos is not built with Epetra");
629#endif
630 } else{
631 // Do the import with the Tpetra::CrsGraph traits object
632 const xt_graph_t *xtg = dynamic_cast<const xt_graph_t *>(&from);
633 RCP<const t_graph_t> tg = xtg->getTpetra_CrsGraph();
634
635 RCP<t_graph_t> tgnew = XpetraTraits<t_graph_t>::doMigration(
636 *tg, numLocalRows, myNewRows);
637
638 RCP<x_graph_t> xgnew = XpetraTraits<t_graph_t>::convertToXpetra(tgnew);
639
640 return xgnew;
641 }
642 }
643};
644
646// Tpetra::Vector
647template <typename scalar_t,
648 typename lno_t,
649 typename gno_t,
650 typename node_t>
651struct XpetraTraits<Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> >
652{
653 typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
654 typedef Xpetra::TpetraVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
655 typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
656
657 static inline RCP<x_vector_t> convertToXpetra(const RCP<t_vector_t> &a)
658 {
659 return rcp(new xt_vector_t(a));
660 }
661
662 static RCP<t_vector_t> doMigration(const t_vector_t &from,
663 size_t numLocalElts, const gno_t *myNewElts)
664 {
665 typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
666
667 // source map
668 const RCP<const map_t> &smap = from.getMap();
669 gno_t numGlobalElts = smap->getGlobalNumElements();
670 gno_t base = smap->getMinAllGlobalIndex();
671
672 // target map
673 ArrayView<const gno_t> eltList(myNewElts, numLocalElts);
674 const RCP<const Teuchos::Comm<int> > comm = from.getMap()->getComm();
675 RCP<const map_t> tmap = rcp(new map_t(numGlobalElts, eltList, base, comm));
676
677 // importer
678 Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
679
680 // target vector
681 RCP<t_vector_t> V =
682 Tpetra::createVector<scalar_t,lno_t,gno_t,node_t>(tmap);
683 V->doImport(from, importer, Tpetra::INSERT);
684
685 return V;
686 }
687};
688
690#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
691// Epetra_Vector
692template < >
693struct XpetraTraits<Epetra_Vector>
694{
699
700 typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
701
702 static inline RCP<x_vector_t> convertToXpetra(const RCP<Epetra_Vector> &a)
703 {
704 RCP<Xpetra::EpetraVectorT<gno_t, node_t> > xev;
705 try {
706 xev = rcp(new Xpetra::EpetraVectorT<gno_t,node_t>(a));
707 }
708 catch (std::exception &e) {
709 if (std::is_same<node_t, Xpetra::EpetraNode>::value)
710 throw std::runtime_error(std::string("Cannot convert from "
711 "Epetra_Vector to "
712 "Xpetra::EpetraVectorT\n")
713 + e.what());
714 else
715 throw std::runtime_error(std::string("Cannot convert from "
716 "Epetra_Vector to "
717 "Xpetra::EpetraVectorT\n"
718 "Use node_t that is supported by "
719 "Xpetra with Epetra classes\n")
720 + e.what());
721 }
722 return rcp_implicit_cast<x_vector_t>(xev);
723 }
724
725 static RCP<Epetra_Vector> doMigration(const Epetra_Vector &from,
726 size_t numLocalElts, const gno_t *myNewElts)
727 {
728 // source map
729 const Epetra_BlockMap &smap = from.Map();
730 gno_t numGlobalElts = smap.NumGlobalElements();
731 int base = smap.MinAllGID();
732
733 // target map
734 const Epetra_Comm &comm = from.Comm();
735 const Epetra_BlockMap tmap(numGlobalElts, numLocalElts, myNewElts,
736 1, base, comm);
737
738 // importer
739 Epetra_Import importer(tmap, smap);
740
741 // target vector
742 RCP<Epetra_Vector> V = rcp(new Epetra_Vector(tmap, true));
743 Epetra_CombineMode c = Insert;
744 V->Import(from, importer, c);
745
746 return V;
747 }
748};
749#endif
750
752// Xpetra::Vector
753template <typename scalar_t,
754 typename lno_t,
755 typename gno_t,
756 typename node_t>
757struct XpetraTraits<Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> >
758{
759 typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
760 typedef Xpetra::TpetraVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
761 typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
762
763 static inline RCP<x_vector_t> convertToXpetra(const RCP<x_vector_t> &a)
764 {
765 return a;
766 }
767
768 static RCP<x_vector_t> doMigration(const x_vector_t &from,
769 size_t numLocalRows, const gno_t *myNewRows)
770 {
771 Xpetra::UnderlyingLib lib = from.getMap()->lib();
772
773 if (lib == Xpetra::UseEpetra){
774 throw std::logic_error("compiler should have used specialization");
775 } else{
776 // Do the import with the Tpetra::Vector traits object
777 const xt_vector_t *xtv = dynamic_cast<const xt_vector_t *>(&from);
778 RCP<const t_vector_t> tv = xtv->getTpetra_Vector();
779
780 RCP<t_vector_t> tvnew = XpetraTraits<t_vector_t>::doMigration(
781 *tv, numLocalRows, myNewRows);
782
783 RCP<x_vector_t> xvnew = XpetraTraits<t_vector_t>::convertToXpetra(tvnew);
784
785 return xvnew;
786 }
787 }
788};
789
791// Xpetra::Vector specialization
792template <typename node_t>
793struct XpetraTraits<Xpetra::Vector<double, int, int, node_t> >
794{
795 typedef double scalar_t;
796 typedef int lno_t;
797 typedef int gno_t;
798 typedef Xpetra::Vector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
799 typedef Xpetra::TpetraVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
800 typedef Tpetra::Vector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
801
802 static inline RCP<x_vector_t> convertToXpetra(const RCP<x_vector_t> &a)
803 {
804 return a;
805 }
806
807 static RCP<x_vector_t> doMigration(const x_vector_t &from,
808 size_t numLocalRows, const gno_t *myNewRows)
809 {
810 Xpetra::UnderlyingLib lib = from.getMap()->lib();
811
812 if (lib == Xpetra::UseEpetra){
813#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
814 typedef Epetra_Vector e_vector_t;
815 typedef Xpetra::EpetraVectorT<gno_t,node_t> xe_vector_t;
816 // Do the import with the Epetra_Vector traits object
817 const xe_vector_t *xev = dynamic_cast<const xe_vector_t *>(&from);
818 RCP<const e_vector_t> ev = rcp(xev->getEpetra_Vector());
819
820 RCP<e_vector_t> evnew = XpetraTraits<e_vector_t>::doMigration(
821 *ev, numLocalRows, myNewRows);
822
823 RCP<x_vector_t> xvnew = XpetraTraits<e_vector_t>::convertToXpetra(evnew);
824
825 return xvnew;
826#else
827 throw std::runtime_error("Xpetra with Epetra requested, but "
828 "Trilinos is not built with Epetra");
829#endif
830 } else{
831 // Do the import with the Tpetra::Vector traits object
832 const xt_vector_t *xtv = dynamic_cast<const xt_vector_t *>(&from);
833 RCP<t_vector_t> tv = xtv->getTpetra_Vector();
834
835 RCP<t_vector_t> tvnew = XpetraTraits<t_vector_t>::doMigration(
836 *tv, numLocalRows, myNewRows);
837
838 RCP<x_vector_t> xvnew = XpetraTraits<t_vector_t>::convertToXpetra(tvnew);
839
840 return xvnew;
841 }
842 }
843};
844
846// Tpetra::MultiVector
847template <typename scalar_t,
848 typename lno_t,
849 typename gno_t,
850 typename node_t>
851struct XpetraTraits<Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >
852{
853 typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> t_vector_t;
854 typedef Xpetra::TpetraMultiVector<scalar_t, lno_t, gno_t, node_t> xt_vector_t;
855 typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_vector_t;
856
857 static inline RCP<x_vector_t> convertToXpetra(const RCP<t_vector_t> &a)
858 {
859 return rcp(new xt_vector_t(a));
860 }
861
862 static RCP<t_vector_t> doMigration(const t_vector_t &from,
863 size_t numLocalElts, const gno_t *myNewElts)
864 {
865 typedef Tpetra::Map<lno_t, gno_t, node_t> map_t;
866
867 // source map
868 const RCP<const map_t> &smap = from.getMap();
869 gno_t numGlobalElts = smap->getGlobalNumElements();
870 gno_t base = smap->getMinAllGlobalIndex();
871
872 // target map
873 ArrayView<const gno_t> eltList(myNewElts, numLocalElts);
874 const RCP<const Teuchos::Comm<int> > comm = from.getMap()->getComm();
875 RCP<const map_t> tmap = rcp(new map_t(numGlobalElts, eltList, base, comm));
876
877 // importer
878 Tpetra::Import<lno_t, gno_t, node_t> importer(smap, tmap);
879
880 // target vector
881 RCP<t_vector_t> MV = rcp(
882 new t_vector_t(tmap, from.getNumVectors(), true));
883 MV->doImport(from, importer, Tpetra::INSERT);
884
885 return MV;
886 }
887};
888
890#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
891// Epetra_MultiVector
892template < >
893struct XpetraTraits<Epetra_MultiVector>
894{
899 typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
900
901 static inline RCP<x_mvector_t> convertToXpetra(
902 const RCP<Epetra_MultiVector> &a)
903 {
904 RCP<Xpetra::EpetraMultiVectorT<gno_t, node_t> > xemv;
905 try {
906 xemv = rcp(new Xpetra::EpetraMultiVectorT<gno_t,node_t>(a));
907 }
908 catch (std::exception &e) {
909 if (std::is_same<node_t, Xpetra::EpetraNode>::value)
910 throw std::runtime_error(std::string("Cannot convert from "
911 "Epetra_MultiVector to "
912 "Xpetra::EpetraMultiVectorT\n")
913 + e.what());
914 else
915 throw std::runtime_error(std::string("Cannot convert from "
916 "Epetra_MultiVector to "
917 "Xpetra::EpetraMultiVectorT\n"
918 "Use node_t that is supported by "
919 "Xpetra with Epetra classes\n")
920 + e.what());
921 }
922 return rcp_implicit_cast<x_mvector_t>(xemv);
923 }
924
925 static RCP<Epetra_MultiVector> doMigration(const Epetra_MultiVector &from,
926 size_t numLocalElts, const gno_t *myNewElts)
927 {
928 // source map
929 const Epetra_BlockMap &smap = from.Map();
930 gno_t numGlobalElts = smap.NumGlobalElements();
931 int base = smap.MinAllGID();
932
933 // target map
934 const Epetra_Comm &comm = from.Comm();
935 const Epetra_BlockMap tmap(numGlobalElts, numLocalElts, myNewElts,
936 1, base, comm);
937
938 // importer
939 Epetra_Import importer(tmap, smap);
940
941 // target vector
942 RCP<Epetra_MultiVector> MV = rcp(
943 new Epetra_MultiVector(tmap, from.NumVectors(), true));
944 Epetra_CombineMode c = Insert;
945 MV->Import(from, importer, c);
946
947 return MV;
948 }
949};
950#endif
951
953// Xpetra::MultiVector
954template <typename scalar_t,
955 typename lno_t,
956 typename gno_t,
957 typename node_t>
958struct XpetraTraits<Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >
959{
960 typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
961 typedef Xpetra::TpetraMultiVector<scalar_t, lno_t, gno_t, node_t> xt_mvector_t;
962 typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> t_mvector_t;
963
964 static inline RCP<x_mvector_t> convertToXpetra(const RCP<x_mvector_t> &a)
965 {
966 return a;
967 }
968
969 static RCP<x_mvector_t> doMigration(const x_mvector_t &from,
970 size_t numLocalRows, const gno_t *myNewRows)
971 {
972 Xpetra::UnderlyingLib lib = from.getMap()->lib();
973
974 if (lib == Xpetra::UseEpetra){
975 throw std::logic_error("compiler should have used specialization");
976 } else{
977 // Do the import with the Tpetra::MultiVector traits object
978 const xt_mvector_t *xtv = dynamic_cast<const xt_mvector_t *>(&from);
979 RCP<t_mvector_t> tv = xtv->getTpetra_MultiVector();
980
981 RCP<t_mvector_t> tvnew = XpetraTraits<t_mvector_t>::doMigration(
982 *tv, numLocalRows, myNewRows);
983
984 RCP<x_mvector_t> xvnew = XpetraTraits<t_mvector_t>::convertToXpetra(tvnew);
985
986 return xvnew;
987 }
988 }
989};
990
992// Xpetra::MultiVector specialization
993template <typename node_t>
994struct XpetraTraits<Xpetra::MultiVector<double, int, int, node_t> >
995{
996 typedef double scalar_t;
997 typedef int lno_t;
998 typedef int gno_t;
999 typedef Xpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> x_mvector_t;
1000 typedef Xpetra::TpetraMultiVector<scalar_t, lno_t, gno_t, node_t> xt_mvector_t;
1001 typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> t_mvector_t;
1002
1003 static inline RCP<x_mvector_t> convertToXpetra(const RCP<x_mvector_t> &a)
1004 {
1005 return a;
1006 }
1007
1008 static RCP<x_mvector_t> doMigration(const x_mvector_t &from,
1009 size_t numLocalRows, const gno_t *myNewRows)
1010 {
1011 Xpetra::UnderlyingLib lib = from.getMap()->lib();
1012
1013 if (lib == Xpetra::UseEpetra){
1014#if defined(HAVE_ZOLTAN2_EPETRA) && defined(HAVE_XPETRA_EPETRA)
1015 typedef Epetra_MultiVector e_mvector_t;
1016 typedef Xpetra::EpetraMultiVectorT<gno_t,node_t> xe_mvector_t;
1017 // Do the import with the Epetra_MultiVector traits object
1018 const xe_mvector_t *xev = dynamic_cast<const xe_mvector_t *>(&from);
1019 RCP<e_mvector_t> ev = xev->getEpetra_MultiVector();
1020
1021 RCP<e_mvector_t> evnew = XpetraTraits<e_mvector_t>::doMigration(
1022 *ev, numLocalRows, myNewRows);
1023
1024 RCP<x_mvector_t> xvnew = XpetraTraits<e_mvector_t>::convertToXpetra(evnew);
1025
1026 return xvnew;
1027#else
1028 throw std::runtime_error("Xpetra with Epetra requested, but "
1029 "Trilinos is not built with Epetra");
1030#endif
1031 } else{
1032 // Do the import with the Tpetra::MultiVector traits object
1033 const xt_mvector_t *xtv = dynamic_cast<const xt_mvector_t *>(&from);
1034 RCP<t_mvector_t> tv = xtv->getTpetra_MultiVector();
1035
1036 RCP<t_mvector_t> tvnew = XpetraTraits<t_mvector_t>::doMigration(
1037 *tv, numLocalRows, myNewRows);
1038
1039 RCP<x_mvector_t> xvnew = XpetraTraits<t_mvector_t>::convertToXpetra(tvnew);
1040
1041 return xvnew;
1042 }
1043 }
1044};
1045
1046#endif // DOXYGEN_SHOULD_SKIP_THIS
1047
1048} //namespace Zoltan2
1049
1050#endif // _ZOLTAN2_XPETRATRAITS_HPP_
Tpetra::CrsGraph< zlno_t, zgno_t, znode_t > tgraph_t
Xpetra::CrsGraph< zlno_t, zgno_t, znode_t > xgraph_t
Xpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t, znode_t > xmatrix_t
Tpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t, znode_t > tmatrix_t
Traits for application input objects.
Gathering definitions used in software development.
Tpetra::Vector< z2TestScalar, z2TestLO, z2TestGO > Vector
Definition coloring1.cpp:80
map_t::local_ordinal_type lno_t
map_t::global_ordinal_type gno_t
Tpetra::Map map_t
Created by mbenlioglu on Aug 31, 2020.
::Tpetra::Details::DefaultTypes::local_ordinal_type default_lno_t
::Tpetra::Details::DefaultTypes::global_ordinal_type default_gno_t
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices.
default_scalar_t scalar_t
The data type for weights and coordinates.
Defines the traits required for Tpetra, Eptra and Xpetra objects.
static RCP< User > doMigration(const User &from, size_t numLocalRows, const gno_t *myNewRows)
Migrate the object Given a user object and a new row distribution, create and return a new user objec...
static RCP< User > convertToXpetra(const RCP< User > &a)
Convert the object to its Xpetra wrapped version.
default_gno_t gno_t
The objects global ordinal data type.
default_lno_t lno_t
The objects local ordinal data type.