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