Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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_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 
67 namespace Zoltan2 {
68 
70 // Extra traits needed only for Xpetra matrices and graphs
71 
94 template <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
128 template <typename scalar_t,
129  typename lno_t,
130  typename gno_t,
131  typename node_t>
132 struct 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
214 template <>
215 struct XpetraTraits<Epetra_CrsMatrix>
216 {
217  typedef InputTraits<Epetra_CrsMatrix>::scalar_t scalar_t;
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
308 template <typename scalar_t,
309  typename lno_t,
310  typename gno_t,
311  typename node_t>
312 struct 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 
348 template <typename node_t>
349 struct 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
404 template <typename lno_t,
405  typename gno_t,
406  typename node_t>
407 struct 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
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  // 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?
555 template <typename lno_t,
556  typename gno_t,
557  typename node_t>
558 struct 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
593 template < typename node_t>
594 struct 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
647 template <typename scalar_t,
648  typename lno_t,
649  typename gno_t,
650  typename node_t>
651 struct 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
692 template < >
693 struct XpetraTraits<Epetra_Vector>
694 {
698  typedef InputTraits<Epetra_Vector>::scalar_t scalar_t;
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
753 template <typename scalar_t,
754  typename lno_t,
755  typename gno_t,
756  typename node_t>
757 struct 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
792 template <typename node_t>
793 struct 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
847 template <typename scalar_t,
848  typename lno_t,
849  typename gno_t,
850  typename node_t>
851 struct 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
892 template < >
893 struct XpetraTraits<Epetra_MultiVector>
894 {
898  typedef InputTraits<Epetra_MultiVector>::scalar_t scalar_t;
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
954 template <typename scalar_t,
955  typename lno_t,
956  typename gno_t,
957  typename node_t>
958 struct 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
993 template <typename node_t>
994 struct 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_
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
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:18
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...
typename Zoltan2::InputTraits< ztcrsmatrix_t >::node_t node_t
Xpetra::CrsGraph< zlno_t, zgno_t, znode_t > xgraph_t
::Tpetra::Details::DefaultTypes::global_ordinal_type default_gno_t
::Tpetra::Details::DefaultTypes::local_ordinal_type default_lno_t
Tpetra::Vector< z2TestScalar, z2TestLO, z2TestGO > Vector
Definition: coloring1.cpp:80
static RCP< User > convertToXpetra(const RCP< User > &a)
Convert the object to its Xpetra wrapped version.
Tpetra::Map map_t
Definition: mapRemotes.cpp:16
Traits for application input objects.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:17
default_lno_t lno_t
The objects local ordinal data type.
Gathering definitions used in software development.
Tpetra::CrsGraph< zlno_t, zgno_t, znode_t > tgraph_t