Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Util.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Amesos2: Templated Direct Sparse Solver Package
4 //
5 // Copyright 2011 NTESS and the Amesos2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
18 #ifndef AMESOS2_UTIL_HPP
19 #define AMESOS2_UTIL_HPP
20 
21 #include <cstdio>
22 #include <fstream>
23 #include <iostream>
24 
25 #include "Amesos2_config.h"
26 
27 #include "Teuchos_RCP.hpp"
28 #include "Teuchos_BLAS_types.hpp"
29 #include "Teuchos_Array.hpp"
30 #include "Teuchos_ArrayView.hpp"
31 #include "Teuchos_FancyOStream.hpp"
32 
33 #include <Tpetra_Map.hpp>
34 #include <Tpetra_DistObject_decl.hpp>
35 #include <Tpetra_ComputeGatherMap.hpp> // added for gather map... where is the best place??
36 
37 #include "Amesos2_TypeDecl.hpp"
38 #include "Amesos2_Meta.hpp"
40 
41 #ifdef HAVE_AMESOS2_EPETRA
42 #include <Epetra_Map.h>
43 #endif
44 
45 #ifdef HAVE_AMESOS2_METIS
46 #include "metis.h" // to discuss, remove from header?
47 #endif
48 
49 namespace Amesos2 {
50 
51  namespace Util {
52 
59  using Teuchos::RCP;
60  using Teuchos::ArrayView;
61 
78  template <typename LO, typename GO, typename GS, typename Node>
79  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
80  getGatherMap( const Teuchos::RCP< const Tpetra::Map<LO,GO,Node> > &map );
81 
82 
83  template <typename LO, typename GO, typename GS, typename Node>
84  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
85  getDistributionMap(EDistribution distribution,
86  GS num_global_elements,
87  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
88  GO indexBase = 0,
89  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >& map = Teuchos::null);
90 
91 
92 #ifdef HAVE_AMESOS2_EPETRA
93 
99  template <typename LO, typename GO, typename GS, typename Node>
100  RCP<Tpetra::Map<LO,GO,Node> >
101  epetra_map_to_tpetra_map(const Epetra_BlockMap& map);
102 
108  template <typename LO, typename GO, typename GS, typename Node>
109  RCP<Epetra_Map>
110  tpetra_map_to_epetra_map(const Tpetra::Map<LO,GO,Node>& map);
111 
117  const RCP<const Teuchos::Comm<int> > to_teuchos_comm(RCP<const Epetra_Comm> c);
118 
124  const RCP<const Epetra_Comm> to_epetra_comm(RCP<const Teuchos::Comm<int> > c);
125 #endif // HAVE_AMESOS2_EPETRA
126 
132  template <typename Scalar,
133  typename GlobalOrdinal,
134  typename GlobalSizeT>
135  void transpose(ArrayView<Scalar> vals,
136  ArrayView<GlobalOrdinal> indices,
137  ArrayView<GlobalSizeT> ptr,
138  ArrayView<Scalar> trans_vals,
139  ArrayView<GlobalOrdinal> trans_indices,
140  ArrayView<GlobalSizeT> trans_ptr);
141 
155  template <typename Scalar1, typename Scalar2>
156  void scale(ArrayView<Scalar1> vals, size_t l,
157  size_t ld, ArrayView<Scalar2> s);
158 
177  template <typename Scalar1, typename Scalar2, class BinaryOp>
178  void scale(ArrayView<Scalar1> vals, size_t l,
179  size_t ld, ArrayView<Scalar2> s, BinaryOp binary_op);
180 
181 
183  void printLine( Teuchos::FancyOStream &out );
184 
185  // Helper function used to convert Kokkos::complex pointer
186  // to std::complex pointer; needed for optimized code path
187  // when retrieving the CRS raw pointers
188  template < class T0, class T1 >
189  struct getStdCplxType
190  {
191  using common_type = typename std::common_type<T0,T1>::type;
192  using type = common_type;
193  };
194 
195  template < class T0, class T1 >
196  struct getStdCplxType< T0, T1* >
197  {
198  using common_type = typename std::common_type<T0,T1>::type;
199  using type = common_type;
200  };
201 
202 #if defined(HAVE_TEUCHOS_COMPLEX) && defined(HAVE_AMESOS2_KOKKOS)
203  template < class T0 >
204  struct getStdCplxType< T0, Kokkos::complex<T0>* >
205  {
206  using type = std::complex<T0>;
207  };
208 
209  template < class T0 , class T1 >
210  struct getStdCplxType< T0, Kokkos::complex<T1>* >
211  {
212  using common_type = typename std::common_type<T0,T1>::type;
213  using type = std::complex<common_type>;
214  };
215 #endif
216 
218  // Matrix/MultiVector Utilities //
220 
221 
222 
236  template<class M, typename KV_S, typename KV_GO, typename KV_GS, class Op>
238  {
239  static void do_get(const Teuchos::Ptr<const M> mat,
240  KV_S& nzvals,
241  KV_GO& indices,
242  KV_GS& pointers,
243  typename KV_GS::value_type& nnz,
244  const Teuchos::Ptr<
245  const Tpetra::Map<typename M::local_ordinal_t,
246  typename M::global_ordinal_t,
247  typename M::node_t> > map,
248  EDistribution distribution,
249  EStorage_Ordering ordering)
250  {
251  Op::template apply_kokkos_view<KV_S, KV_GO, KV_GS>(mat, nzvals,
252  indices, pointers, nnz, map, distribution, ordering);
253  }
254  };
255 
256  template<class M, typename KV_S, typename KV_GO, typename KV_GS, class Op>
257  struct diff_gs_helper_kokkos_view
258  {
259  static void do_get(const Teuchos::Ptr<const M> mat,
260  KV_S& nzvals,
261  KV_GO& indices,
262  KV_GS& pointers,
263  typename KV_GS::value_type& nnz,
264  const Teuchos::Ptr<
265  const Tpetra::Map<typename M::local_ordinal_t,
266  typename M::global_ordinal_t,
267  typename M::node_t> > map,
268  EDistribution distribution,
269  EStorage_Ordering ordering)
270  {
271  typedef typename M::global_size_t mat_gs_t;
272  typedef typename Kokkos::View<mat_gs_t*, Kokkos::HostSpace> KV_TMP;
273  size_t i, size = (pointers.extent(0) > 0 ? pointers.extent(0) : 1); // making sure it is at least 1, even for empty local matrix
274  KV_TMP pointers_tmp(Kokkos::ViewAllocateWithoutInitializing("pointers_tmp"), size);
275 
276  mat_gs_t nnz_tmp = 0;
277  Op::template apply_kokkos_view<KV_S, KV_GO, KV_TMP>(mat, nzvals,
278  indices, pointers_tmp, nnz_tmp, Teuchos::ptrInArg(*map), distribution, ordering);
279  nnz = Teuchos::as<typename KV_GS::value_type>(nnz_tmp);
280 
281  typedef typename KV_GS::value_type view_gs_t;
282  for (i = 0; i < pointers.extent(0); ++i){
283  pointers(i) = Teuchos::as<view_gs_t>(pointers_tmp(i));
284  }
285  nnz = Teuchos::as<view_gs_t>(nnz_tmp);
286  }
287  };
288 
289  template<class M, typename KV_S, typename KV_GO, typename KV_GS, class Op>
290  struct same_go_helper_kokkos_view
291  {
292  static void do_get(const Teuchos::Ptr<const M> mat,
293  KV_S& nzvals,
294  KV_GO& indices,
295  KV_GS& pointers,
296  typename KV_GS::value_type& nnz,
297  const Teuchos::Ptr<
298  const Tpetra::Map<typename M::local_ordinal_t,
299  typename M::global_ordinal_t,
300  typename M::node_t> > map,
301  EDistribution distribution,
302  EStorage_Ordering ordering)
303  {
304  typedef typename M::global_size_t mat_gs_t;
305  typedef typename KV_GS::value_type view_gs_t;
306  std::conditional_t<std::is_same_v<view_gs_t,mat_gs_t>,
307  same_gs_helper_kokkos_view<M, KV_S, KV_GO, KV_GS, Op>,
308  diff_gs_helper_kokkos_view<M, KV_S, KV_GO, KV_GS, Op> >::do_get(mat, nzvals, indices,
309  pointers, nnz, map,
310  distribution, ordering);
311  }
312  };
313 
314  template<class M, typename KV_S, typename KV_GO, typename KV_GS, class Op>
315  struct diff_go_helper_kokkos_view
316  {
317  static void do_get(const Teuchos::Ptr<const M> mat,
318  KV_S& nzvals,
319  KV_GO& indices,
320  KV_GS& pointers,
321  typename KV_GS::value_type& nnz,
322  const Teuchos::Ptr<
323  const Tpetra::Map<typename M::local_ordinal_t,
324  typename M::global_ordinal_t,
325  typename M::node_t> > map,
326  EDistribution distribution,
327  EStorage_Ordering ordering)
328  {
329  typedef typename M::global_ordinal_t mat_go_t;
330  typedef typename M::global_size_t mat_gs_t;
331  typedef typename Kokkos::View<mat_go_t*, Kokkos::HostSpace> KV_TMP;
332  size_t i, size = indices.extent(0);
333  KV_TMP indices_tmp(Kokkos::ViewAllocateWithoutInitializing("indices_tmp"), size);
334 
335  typedef typename KV_GO::value_type view_go_t;
336  typedef typename KV_GS::value_type view_gs_t;
337  std::conditional_t<std::is_same_v<view_gs_t,mat_gs_t>,
338  same_gs_helper_kokkos_view<M, KV_S, KV_TMP, KV_GS, Op>,
339  diff_gs_helper_kokkos_view<M, KV_S, KV_TMP, KV_GS, Op> >::do_get(mat, nzvals, indices_tmp,
340  pointers, nnz, map,
341  distribution, ordering);
342  for (i = 0; i < size; ++i){
343  indices(i) = Teuchos::as<view_go_t>(indices_tmp(i));
344  }
345  }
346  };
347 
348  template<class M, typename KV_S, typename KV_GO, typename KV_GS, class Op>
349  struct same_scalar_helper_kokkos_view
350  {
351  static void do_get(const Teuchos::Ptr<const M> mat,
352  KV_S& nzvals,
353  KV_GO& indices,
354  KV_GS& pointers,
355  typename KV_GS::value_type& nnz,
356  const Teuchos::Ptr<
357  const Tpetra::Map<typename M::local_ordinal_t,
358  typename M::global_ordinal_t,
359  typename M::node_t> > map,
360  EDistribution distribution,
361  EStorage_Ordering ordering)
362  {
363  typedef typename M::global_ordinal_t mat_go_t;
364  typedef typename KV_GO::value_type view_go_t;
365  std::conditional_t<std::is_same_v<view_go_t, mat_go_t>,
366  same_go_helper_kokkos_view<M, KV_S, KV_GO, KV_GS, Op>,
367  diff_go_helper_kokkos_view<M, KV_S, KV_GO, KV_GS, Op> >::do_get(mat, nzvals, indices,
368  pointers, nnz, map,
369  distribution, ordering);
370  }
371  };
372 
373  template<class M, typename KV_S, typename KV_GO, typename KV_GS, class Op>
374  struct diff_scalar_helper_kokkos_view
375  {
376  static void do_get(const Teuchos::Ptr<const M> mat,
377  KV_S& nzvals,
378  KV_GO& indices,
379  KV_GS& pointers,
380  typename KV_GS::value_type& nnz,
381  const Teuchos::Ptr<
382  const Tpetra::Map<typename M::local_ordinal_t,
383  typename M::global_ordinal_t,
384  typename M::node_t> > map,
385  EDistribution distribution,
386  EStorage_Ordering ordering)
387  {
388  typedef typename M::global_ordinal_t mat_go_t;
389  typedef typename Kokkos::ArithTraits<typename M::scalar_t>::val_type mat_scalar_t;
390  typedef typename Kokkos::View<mat_scalar_t*, Kokkos::HostSpace> KV_TMP;
391  size_t i, size = nzvals.extent(0);
392  KV_TMP nzvals_tmp(Kokkos::ViewAllocateWithoutInitializing("nzvals_tmp"), size);
393 
394  typedef typename KV_S::value_type view_scalar_t;
395  typedef typename KV_GO::value_type view_go_t;
396  std::conditional_t<std::is_same_v<view_go_t, mat_go_t>,
397  same_go_helper_kokkos_view<M, KV_TMP, KV_GO, KV_GS, Op>,
398  diff_go_helper_kokkos_view<M, KV_TMP, KV_GO, KV_GS, Op> >::do_get(mat, nzvals_tmp, indices,
399  pointers, nnz, map,
400  distribution, ordering);
401 
402  for (i = 0; i < size; ++i){
403  nzvals(i) = Teuchos::as<view_scalar_t>(nzvals_tmp(i));
404  }
405  }
406  };
407 
408 
409  template<class Matrix, typename KV_S, typename KV_GO, typename KV_GS, class Op>
410  struct get_cxs_helper_kokkos_view
411  {
412  static void do_get(const Teuchos::Ptr<const Matrix> mat,
413  KV_S& nzvals,
414  KV_GO& indices,
415  KV_GS& pointers,
416  typename KV_GS::value_type& nnz,
417  EDistribution distribution,
418  EStorage_Ordering ordering=ARBITRARY,
419  typename KV_GO::value_type indexBase = 0)
420  {
421  typedef typename Matrix::local_ordinal_t lo_t;
422  typedef typename Matrix::global_ordinal_t go_t;
423  typedef typename Matrix::global_size_t gs_t;
424  typedef typename Matrix::node_t node_t;
425 
426  const Teuchos::RCP<const Tpetra::Map<lo_t,go_t,node_t> > map
427  = getDistributionMap<lo_t,go_t,gs_t,node_t>(distribution,
428  Op::get_dimension(mat),
429  mat->getComm(),
430  indexBase,
431  Op::getMapFromMatrix(mat) //getMap must be the map returned, NOT rowmap or colmap
432  );
433  do_get(mat, nzvals, indices, pointers, nnz, Teuchos::ptrInArg(*map), distribution, ordering);
434  }
435 
440  static void do_get(const Teuchos::Ptr<const Matrix> mat,
441  KV_S& nzvals,
442  KV_GO& indices,
443  KV_GS& pointers,
444  typename KV_GS::value_type& nnz,
445  EDistribution distribution, // Does this one need a distribution argument??
446  EStorage_Ordering ordering=ARBITRARY)
447  {
448  const Teuchos::RCP<const Tpetra::Map<typename Matrix::local_ordinal_t,
449  typename Matrix::global_ordinal_t,
450  typename Matrix::node_t> > map
451  = Op::getMap(mat);
452  do_get(mat, nzvals, indices, pointers, nnz, Teuchos::ptrInArg(*map), distribution, ordering);
453  }
454 
459  static void do_get(const Teuchos::Ptr<const Matrix> mat,
460  KV_S& nzvals,
461  KV_GO& indices,
462  KV_GS& pointers,
463  typename KV_GS::value_type& nnz,
464  const Teuchos::Ptr<
465  const Tpetra::Map<typename Matrix::local_ordinal_t,
466  typename Matrix::global_ordinal_t,
467  typename Matrix::node_t> > map,
468  EDistribution distribution,
469  EStorage_Ordering ordering=ARBITRARY)
470  {
471  typedef typename Matrix::scalar_t mat_scalar;
472  typedef typename KV_S::value_type view_scalar_t;
473 
474  std::conditional_t<std::is_same_v<mat_scalar,view_scalar_t>,
475  same_scalar_helper_kokkos_view<Matrix,KV_S,KV_GO,KV_GS,Op>,
476  diff_scalar_helper_kokkos_view<Matrix,KV_S,KV_GO,KV_GS,Op> >::do_get(mat,
477  nzvals, indices,
478  pointers, nnz,
479  map,
480  distribution, ordering);
481  }
482  };
483 
484 #ifndef DOXYGEN_SHOULD_SKIP_THIS
485  /*
486  * These two function-like classes are meant to be used as the \c
487  * Op template parameter for the \c get_cxs_helper template class.
488  */
489  template<class Matrix>
490  struct get_ccs_func
491  {
492  template<typename KV_S, typename KV_GO, typename KV_GS>
493  static void apply_kokkos_view(const Teuchos::Ptr<const Matrix> mat,
494  KV_S& nzvals,
495  KV_GO& rowind,
496  KV_GS& colptr,
497  typename Matrix::global_size_t& nnz,
498  const Teuchos::Ptr<
499  const Tpetra::Map<typename Matrix::local_ordinal_t,
500  typename Matrix::global_ordinal_t,
501  typename Matrix::node_t> > map,
502  EDistribution distribution,
503  EStorage_Ordering ordering)
504  {
505  mat->getCcs_kokkos_view(nzvals, rowind, colptr, nnz, map, ordering, distribution);
506  }
507 
508  static
509  const Teuchos::RCP<const Tpetra::Map<typename Matrix::local_ordinal_t,
510  typename Matrix::global_ordinal_t,
511  typename Matrix::node_t> >
512  getMapFromMatrix(const Teuchos::Ptr<const Matrix> mat)
513  {
514  return mat->getMap(); // returns Teuchos::null if mat is Epetra_CrsMatrix
515  }
516 
517  static
518  const Teuchos::RCP<const Tpetra::Map<typename Matrix::local_ordinal_t,
519  typename Matrix::global_ordinal_t,
520  typename Matrix::node_t> >
521  getMap(const Teuchos::Ptr<const Matrix> mat)
522  {
523  return mat->getColMap();
524  }
525 
526  static
527  typename Matrix::global_size_t
528  get_dimension(const Teuchos::Ptr<const Matrix> mat)
529  {
530  return mat->getGlobalNumCols();
531  }
532  };
533 
534  template<class Matrix>
535  struct get_crs_func
536  {
537  template<typename KV_S, typename KV_GO, typename KV_GS>
538  static void apply_kokkos_view(const Teuchos::Ptr<const Matrix> mat,
539  KV_S& nzvals,
540  KV_GO& colind,
541  KV_GS& rowptr,
542  typename Matrix::global_size_t& nnz,
543  const Teuchos::Ptr<
544  const Tpetra::Map<typename Matrix::local_ordinal_t,
545  typename Matrix::global_ordinal_t,
546  typename Matrix::node_t> > map,
547  EDistribution distribution,
548  EStorage_Ordering ordering)
549  {
550  mat->getCrs_kokkos_view(nzvals, colind, rowptr, nnz, map, ordering, distribution);
551  }
552 
553  static
554  const Teuchos::RCP<const Tpetra::Map<typename Matrix::local_ordinal_t,
555  typename Matrix::global_ordinal_t,
556  typename Matrix::node_t> >
557  getMapFromMatrix(const Teuchos::Ptr<const Matrix> mat)
558  {
559  return mat->getMap(); // returns Teuchos::null if mat is Epetra_CrsMatrix
560  }
561 
562  static
563  const Teuchos::RCP<const Tpetra::Map<typename Matrix::local_ordinal_t,
564  typename Matrix::global_ordinal_t,
565  typename Matrix::node_t> >
566  getMap(const Teuchos::Ptr<const Matrix> mat)
567  {
568  return mat->getRowMap();
569  }
570 
571  static
572  typename Matrix::global_size_t
573  get_dimension(const Teuchos::Ptr<const Matrix> mat)
574  {
575  return mat->getGlobalNumRows();
576  }
577  };
578 #endif // DOXYGEN_SHOULD_SKIP_THIS
579 
617  template<class Matrix, typename KV_S, typename KV_GO, typename KV_GS>
618  struct get_ccs_helper_kokkos_view : get_cxs_helper_kokkos_view<Matrix,KV_S,KV_GO,KV_GS,get_ccs_func<Matrix> >
619  {};
620 
628  template<class Matrix, typename KV_S, typename KV_GO, typename KV_GS>
629  struct get_crs_helper_kokkos_view : get_cxs_helper_kokkos_view<Matrix,KV_S,KV_GO,KV_GS,get_crs_func<Matrix> >
630  {};
631  /* End Matrix/MultiVector Utilities */
632 
633 
635  // Definitions //
637 
638 
639  template <typename LO, typename GO, typename GS, typename Node>
640  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
641  getGatherMap( const Teuchos::RCP< const Tpetra::Map<LO,GO,Node> > &map )
642  {
643  //RCP<Teuchos::FancyOStream> fos = Teuchos::fancyOStream( Teuchos::null ); // may need to pass an osstream to computeGatherMap for debugging cases...
644  Teuchos::RCP< const Tpetra::Map<LO,GO,Node> > gather_map = Tpetra::Details::computeGatherMap(map, Teuchos::null);
645  return gather_map;
646  }
647 
648 
649  template <typename LO, typename GO, typename GS, typename Node>
650  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
651  getDistributionMap(EDistribution distribution,
652  GS num_global_elements,
653  const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
654  GO indexBase,
655  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >& map)
656  {
657  // TODO: Need to add indexBase to cases other than ROOTED
658  // We do not support these maps in any solver now.
659  switch( distribution ){
660  case DISTRIBUTED:
661  case DISTRIBUTED_NO_OVERLAP:
662  return Tpetra::createUniformContigMapWithNode<LO,GO, Node>(num_global_elements, comm);
663  case GLOBALLY_REPLICATED:
664  return Tpetra::createLocalMapWithNode<LO,GO, Node>(num_global_elements, comm);
665  case ROOTED:
666  {
667  int rank = Teuchos::rank(*comm);
668  size_t my_num_elems = Teuchos::OrdinalTraits<size_t>::zero();
669  if( rank == 0 ) { my_num_elems = num_global_elements; }
670 
671  return rcp(new Tpetra::Map<LO,GO, Node>(num_global_elements,
672  my_num_elems, indexBase, comm));
673  }
674  case CONTIGUOUS_AND_ROOTED:
675  {
676  const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> > gathermap
677  = getGatherMap<LO,GO,GS,Node>( map ); //getMap must be the map returned, NOT rowmap or colmap
678  return gathermap;
679  }
680  default:
681  TEUCHOS_TEST_FOR_EXCEPTION( true,
682  std::logic_error,
683  "Control should never reach this point. "
684  "Please contact the Amesos2 developers." );
685  }
686  }
687 
688 
689 #ifdef HAVE_AMESOS2_EPETRA
690 
691  //#pragma message "include 3"
692  //#include <Epetra_Map.h>
693 
694  template <typename LO, typename GO, typename GS, typename Node>
695  Teuchos::RCP<Tpetra::Map<LO,GO,Node> >
696  epetra_map_to_tpetra_map(const Epetra_BlockMap& map)
697  {
698  using Teuchos::as;
699  using Teuchos::rcp;
700 
701  int num_my_elements = map.NumMyElements();
702  Teuchos::Array<int> my_global_elements(num_my_elements);
703  map.MyGlobalElements(my_global_elements.getRawPtr());
704 
705  Teuchos::Array<GO> my_gbl_inds_buf;
706  Teuchos::ArrayView<GO> my_gbl_inds;
707  if (! std::is_same<int, GO>::value) {
708  my_gbl_inds_buf.resize (num_my_elements);
709  my_gbl_inds = my_gbl_inds_buf ();
710  for (int k = 0; k < num_my_elements; ++k) {
711  my_gbl_inds[k] = static_cast<GO> (my_global_elements[k]);
712  }
713  }
714  else {
715  using Teuchos::av_reinterpret_cast;
716  my_gbl_inds = av_reinterpret_cast<GO> (my_global_elements ());
717  }
718 
719  typedef Tpetra::Map<LO,GO,Node> map_t;
720  RCP<map_t> tmap = rcp(new map_t(Teuchos::OrdinalTraits<GS>::invalid(),
721  my_gbl_inds(),
722  as<GO>(map.IndexBase()),
723  to_teuchos_comm(Teuchos::rcpFromRef(map.Comm()))));
724  return tmap;
725  }
726 
727  template <typename LO, typename GO, typename GS, typename Node>
728  Teuchos::RCP<Epetra_Map>
729  tpetra_map_to_epetra_map(const Tpetra::Map<LO,GO,Node>& map)
730  {
731  using Teuchos::as;
732 
733  Teuchos::Array<GO> elements_tmp;
734  elements_tmp = map.getLocalElementList();
735  int num_my_elements = elements_tmp.size();
736  Teuchos::Array<int> my_global_elements(num_my_elements);
737  for (int i = 0; i < num_my_elements; ++i){
738  my_global_elements[i] = as<int>(elements_tmp[i]);
739  }
740 
741  using Teuchos::rcp;
742  RCP<Epetra_Map> emap = rcp(new Epetra_Map(-1,
743  num_my_elements,
744  my_global_elements.getRawPtr(),
745  as<GO>(map.getIndexBase()),
746  *to_epetra_comm(map.getComm())));
747  return emap;
748  }
749 #endif // HAVE_AMESOS2_EPETRA
750 
751  template <typename Scalar,
752  typename GlobalOrdinal,
753  typename GlobalSizeT>
754  void transpose(Teuchos::ArrayView<Scalar> vals,
755  Teuchos::ArrayView<GlobalOrdinal> indices,
756  Teuchos::ArrayView<GlobalSizeT> ptr,
757  Teuchos::ArrayView<Scalar> trans_vals,
758  Teuchos::ArrayView<GlobalOrdinal> trans_indices,
759  Teuchos::ArrayView<GlobalSizeT> trans_ptr)
760  {
761  /* We have a compressed-row storage format of this matrix. We
762  * transform this into a compressed-column format using a
763  * distribution-counting sort algorithm, which is described by
764  * D.E. Knuth in TAOCP Vol 3, 2nd ed pg 78.
765  */
766 
767 #ifdef HAVE_AMESOS2_DEBUG
768  typename Teuchos::ArrayView<GlobalOrdinal>::iterator ind_it, ind_begin, ind_end;
769  ind_begin = indices.begin();
770  ind_end = indices.end();
771  size_t min_trans_ptr_size = *std::max_element(ind_begin, ind_end) + 1;
772  TEUCHOS_TEST_FOR_EXCEPTION( Teuchos::as<size_t>(trans_ptr.size()) < min_trans_ptr_size,
773  std::invalid_argument,
774  "Transpose pointer size not large enough." );
775  TEUCHOS_TEST_FOR_EXCEPTION( trans_vals.size() < vals.size(),
776  std::invalid_argument,
777  "Transpose values array not large enough." );
778  TEUCHOS_TEST_FOR_EXCEPTION( trans_indices.size() < indices.size(),
779  std::invalid_argument,
780  "Transpose indices array not large enough." );
781 #else
782  typename Teuchos::ArrayView<GlobalOrdinal>::iterator ind_it, ind_end;
783 #endif
784  // Count the number of entries in each column
785  Teuchos::Array<GlobalSizeT> count(trans_ptr.size(), 0);
786  ind_end = indices.end();
787  for( ind_it = indices.begin(); ind_it != ind_end; ++ind_it ){
788  ++(count[(*ind_it) + 1]);
789  }
790  // Accumulate
791  typename Teuchos::Array<GlobalSizeT>::iterator cnt_it, cnt_end;
792  cnt_end = count.end();
793  for( cnt_it = count.begin() + 1; cnt_it != cnt_end; ++cnt_it ){
794  *cnt_it = *cnt_it + *(cnt_it - 1);
795  }
796  // This becomes the array of column pointers
797  trans_ptr.assign(count);
798 
799  /* Move the nonzero values into their final place in nzval, based on the
800  * counts found previously.
801  *
802  * This sequence deviates from Knuth's algorithm a bit, following more
803  * closely the description presented in Gustavson, Fred G. "Two Fast
804  * Algorithms for Sparse Matrices: Multiplication and Permuted
805  * Transposition" ACM Trans. Math. Softw. volume 4, number 3, 1978, pages
806  * 250--269, http://doi.acm.org/10.1145/355791.355796.
807  *
808  * The output indices end up in sorted order
809  */
810 
811  GlobalSizeT size = ptr.size();
812  for( GlobalSizeT i = 0; i < size - 1; ++i ){
813  GlobalOrdinal u = ptr[i];
814  GlobalOrdinal v = ptr[i + 1];
815  for( GlobalOrdinal j = u; j < v; ++j ){
816  GlobalOrdinal k = count[indices[j]];
817  trans_vals[k] = vals[j];
818  trans_indices[k] = i;
819  ++(count[indices[j]]);
820  }
821  }
822  }
823 
824 
825  template <typename Scalar1, typename Scalar2>
826  void
827  scale(Teuchos::ArrayView<Scalar1> vals, size_t l,
828  size_t ld, Teuchos::ArrayView<Scalar2> s)
829  {
830  size_t vals_size = vals.size();
831 #ifdef HAVE_AMESOS2_DEBUG
832  size_t s_size = s.size();
833  TEUCHOS_TEST_FOR_EXCEPTION( s_size < l,
834  std::invalid_argument,
835  "Scale vector must have length at least that of the vector" );
836 #endif
837  size_t i, s_i;
838  for( i = 0, s_i = 0; i < vals_size; ++i, ++s_i ){
839  if( s_i == l ){
840  // bring i to the next multiple of ld
841  i += ld - s_i;
842  s_i = 0;
843  }
844  vals[i] *= s[s_i];
845  }
846  }
847 
848  template <typename Scalar1, typename Scalar2, class BinaryOp>
849  void
850  scale(Teuchos::ArrayView<Scalar1> vals, size_t l,
851  size_t ld, Teuchos::ArrayView<Scalar2> s,
852  BinaryOp binary_op)
853  {
854  size_t vals_size = vals.size();
855 #ifdef HAVE_AMESOS2_DEBUG
856  size_t s_size = s.size();
857  TEUCHOS_TEST_FOR_EXCEPTION( s_size < l,
858  std::invalid_argument,
859  "Scale vector must have length at least that of the vector" );
860 #endif
861  size_t i, s_i;
862  for( i = 0, s_i = 0; i < vals_size; ++i, ++s_i ){
863  if( s_i == l ){
864  // bring i to the next multiple of ld
865  i += ld - s_i;
866  s_i = 0;
867  }
868  vals[i] = binary_op(vals[i], s[s_i]);
869  }
870  }
871 
872  template<class row_ptr_view_t, class cols_view_t, class per_view_t>
873  void
874  reorder(row_ptr_view_t & row_ptr, cols_view_t & cols,
875  per_view_t & perm, per_view_t & peri, size_t & nnz,
876  bool permute_matrix)
877  {
878  #ifndef HAVE_AMESOS2_METIS
879  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
880  "Cannot reorder for cuSolver because no METIS is available.");
881  #else
882  typedef typename cols_view_t::value_type ordinal_type;
883  typedef typename row_ptr_view_t::value_type size_type;
884 
885  // begin on host where we'll run metis reorder
886  auto host_row_ptr = Kokkos::create_mirror_view(row_ptr);
887  auto host_cols = Kokkos::create_mirror_view(cols);
888  Kokkos::deep_copy(host_row_ptr, row_ptr);
889  Kokkos::deep_copy(host_cols, cols);
890 
891  // strip out the diagonals - metis will just crash with them included.
892  // make space for the stripped version
893  typedef Kokkos::View<idx_t*, Kokkos::HostSpace> host_metis_array;
894  const ordinal_type size = row_ptr.size() - 1;
895  size_type max_nnz = host_row_ptr(size);
896  host_metis_array host_strip_diag_row_ptr(
897  Kokkos::ViewAllocateWithoutInitializing("host_strip_diag_row_ptr"),
898  size+1);
899  host_metis_array host_strip_diag_cols(
900  Kokkos::ViewAllocateWithoutInitializing("host_strip_diag_cols"),
901  max_nnz);
902 
903  size_type new_nnz = 0;
904  for(ordinal_type i = 0; i < size; ++i) {
905  host_strip_diag_row_ptr(i) = new_nnz;
906  for(size_type j = host_row_ptr(i); j < host_row_ptr(i+1); ++j) {
907  if (i != host_cols(j)) {
908  host_strip_diag_cols(new_nnz++) = host_cols(j);
909  }
910  }
911  }
912  host_strip_diag_row_ptr(size) = new_nnz;
913 
914  // we'll get original permutations on host
915  host_metis_array host_perm(
916  Kokkos::ViewAllocateWithoutInitializing("host_perm"), size);
917  host_metis_array host_peri(
918  Kokkos::ViewAllocateWithoutInitializing("host_peri"), size);
919 
920  // If we want to remove metis.h included in this header we can move this
921  // to the cpp, but we need to decide how to handle the idx_t declaration.
922  idx_t metis_size = size;
923  int err = METIS_NodeND(&metis_size, host_strip_diag_row_ptr.data(), host_strip_diag_cols.data(),
924  NULL, NULL, host_perm.data(), host_peri.data());
925 
926  TEUCHOS_TEST_FOR_EXCEPTION(err != METIS_OK, std::runtime_error,
927  "METIS_NodeND failed to sort matrix.");
928 
929  // put the permutations on our saved device ptrs
930  // these will be used to permute x and b when we solve
931  typedef typename cols_view_t::execution_space exec_space_t;
932  auto device_perm = Kokkos::create_mirror_view(exec_space_t(), host_perm);
933  auto device_peri = Kokkos::create_mirror_view(exec_space_t(), host_peri);
934  deep_copy(device_perm, host_perm);
935  deep_copy(device_peri, host_peri);
936 
937  // also set the permutation which may need to convert the type from
938  // metis to the native ordinal_type
939  deep_copy_or_assign_view(perm, device_perm);
940  deep_copy_or_assign_view(peri, device_peri);
941 
942  if (permute_matrix) {
943  // we'll permute matrix on device to a new set of arrays
944  row_ptr_view_t new_row_ptr(
945  Kokkos::ViewAllocateWithoutInitializing("new_row_ptr"), row_ptr.size());
946  cols_view_t new_cols(
947  Kokkos::ViewAllocateWithoutInitializing("new_cols"), cols.size() - new_nnz/2);
948 
949  // permute row indices
950  Kokkos::RangePolicy<exec_space_t> policy_row(0, row_ptr.size());
951  Kokkos::parallel_scan(policy_row, KOKKOS_LAMBDA(
952  ordinal_type i, size_type & update, const bool &final) {
953  if(final) {
954  new_row_ptr(i) = update;
955  }
956  if(i < size) {
957  ordinal_type count = 0;
958  const ordinal_type row = device_perm(i);
959  for(ordinal_type k = row_ptr(row); k < row_ptr(row + 1); ++k) {
960  const ordinal_type j = device_peri(cols(k));
961  count += (i >= j);
962  }
963  update += count;
964  }
965  });
966 
967  // permute col indices
968  Kokkos::RangePolicy<exec_space_t> policy_col(0, size);
969  Kokkos::parallel_for(policy_col, KOKKOS_LAMBDA(ordinal_type i) {
970  const ordinal_type kbeg = new_row_ptr(i);
971  const ordinal_type row = device_perm(i);
972  const ordinal_type col_beg = row_ptr(row);
973  const ordinal_type col_end = row_ptr(row + 1);
974  const ordinal_type nk = col_end - col_beg;
975  for(ordinal_type k = 0, t = 0; k < nk; ++k) {
976  const ordinal_type tk = kbeg + t;
977  const ordinal_type sk = col_beg + k;
978  const ordinal_type j = device_peri(cols(sk));
979  if(i >= j) {
980  new_cols(tk) = j;
981  ++t;
982  }
983  }
984  });
985 
986  // finally set the inputs to the new sorted arrays
987  row_ptr = new_row_ptr;
988  cols = new_cols;
989  }
990 
991  nnz = new_nnz;
992  #endif // HAVE_AMESOS2_METIS
993  }
994 
995  template<class values_view_t, class row_ptr_view_t,
996  class cols_view_t, class per_view_t>
997  void
998  reorder_values(values_view_t & values, const row_ptr_view_t & orig_row_ptr,
999  const row_ptr_view_t & new_row_ptr,
1000  const cols_view_t & orig_cols, const per_view_t & perm, const per_view_t & peri,
1001  size_t nnz)
1002  {
1003  typedef typename cols_view_t::value_type ordinal_type;
1004  typedef typename cols_view_t::execution_space exec_space_t;
1005 
1006  auto device_perm = Kokkos::create_mirror_view(exec_space_t(), perm);
1007  auto device_peri = Kokkos::create_mirror_view(exec_space_t(), peri);
1008  deep_copy(device_perm, perm);
1009  deep_copy(device_peri, peri);
1010 
1011  const ordinal_type size = orig_row_ptr.size() - 1;
1012 
1013  auto host_orig_row_ptr = Kokkos::create_mirror_view(orig_row_ptr);
1014  auto new_nnz = host_orig_row_ptr(size); // TODO: Maybe optimize this by caching
1015 
1016  values_view_t new_values(
1017  Kokkos::ViewAllocateWithoutInitializing("new_values"), values.size() - new_nnz/2);
1018 
1019  // permute col indices
1020  Kokkos::RangePolicy<exec_space_t> policy_col(0, size);
1021  Kokkos::parallel_for(policy_col, KOKKOS_LAMBDA(ordinal_type i) {
1022  const ordinal_type kbeg = new_row_ptr(i);
1023  const ordinal_type row = device_perm(i);
1024  const ordinal_type col_beg = orig_row_ptr(row);
1025  const ordinal_type col_end = orig_row_ptr(row + 1);
1026  const ordinal_type nk = col_end - col_beg;
1027  for(ordinal_type k = 0, t = 0; k < nk; ++k) {
1028  const ordinal_type tk = kbeg + t;
1029  const ordinal_type sk = col_beg + k;
1030  const ordinal_type j = device_peri(orig_cols(sk));
1031  if(i >= j) {
1032  new_values(tk) = values(sk);
1033  ++t;
1034  }
1035  }
1036  });
1037 
1038  values = new_values;
1039  }
1040 
1041  template<class array_view_t, class per_view_t>
1042  void
1043  apply_reorder_permutation(const array_view_t & array,
1044  array_view_t & permuted_array, const per_view_t & permutation) {
1045  if(permuted_array.extent(0) != array.extent(0) || permuted_array.extent(1) != array.extent(1)) {
1046  permuted_array = array_view_t(
1047  Kokkos::ViewAllocateWithoutInitializing("permuted_array"),
1048  array.extent(0), array.extent(1));
1049  }
1050  typedef typename array_view_t::execution_space exec_space_t;
1051  Kokkos::RangePolicy<exec_space_t> policy(0, array.extent(0));
1052  Kokkos::parallel_for(policy, KOKKOS_LAMBDA(size_t i) {
1053  for(size_t j = 0; j < array.extent(1); ++j) {
1054  permuted_array(i, j) = array(permutation(i), j);
1055  }
1056  });
1057  }
1058 
1059 
1060  // used to read matrix with gapped GIDs for test/example
1061  template <typename GO, typename Scalar>
1062  bool
1063  readEntryFromFile (GO& gblRowInd, GO& gblColInd, Scalar& val, const std::string& s)
1064  {
1065  if (s.size () == 0 || s.find ("%") != std::string::npos) {
1066  return false; // empty line or comment line
1067  }
1068  std::istringstream in (s);
1069 
1070  if (! in) {
1071  return false;
1072  }
1073  in >> gblRowInd;
1074  if (! in) {
1075  return false;
1076  }
1077  in >> gblColInd;
1078  if (! in) {
1079  return false;
1080  }
1081  in >> val;
1082  return true;
1083  }
1084 
1085 #ifdef HAVE_AMESOS2_EPETRA
1086  template<class map_type, class MAT>
1087  Teuchos::RCP<MAT>
1088  readEpetraCrsMatrixFromFile (const std::string& matrixFilename,
1089  Teuchos::RCP<Teuchos::FancyOStream> & fos,
1090  const Teuchos::RCP<const map_type>& rowMap,
1091  const Teuchos::RCP<const map_type>& domainMap,
1092  const Teuchos::RCP<const map_type>& rangeMap,
1093  const bool convert_to_zero_base,
1094  const int header_size)
1095  {
1096  using Scalar = double;
1097  using GO = int;
1098 
1099  using counter_type = std::map<GO, size_t>;
1100  using pair_type = std::pair<const GO, size_t>;
1101  using Teuchos::RCP;
1102 
1103  const int myRank = rowMap->Comm().MyPID();
1104 
1105  std::ifstream inFile;
1106  int opened = 0;
1107  if (myRank == 0)
1108  {
1109  try {
1110  inFile.open (matrixFilename);
1111  if (inFile) {
1112  opened = 1;
1113  }
1114  }
1115  catch (...) {
1116  opened = 0;
1117  }
1118  }
1119  rowMap->Comm().Broadcast(&opened, 1, 0);
1120  TEUCHOS_TEST_FOR_EXCEPTION
1121  (opened == 0, std::runtime_error, "readCrsMatrixFromFile: "
1122  "Failed to open file \"" << matrixFilename << "\" on Process 0.");
1123 
1124  RCP<MAT> A;
1125  if (myRank == 0)
1126  {
1127  std::string line;
1128 
1129  // Skip the first N lines. This is a hack, specific to the input file in question.
1130  //*fos << " Reading matrix market file. Skip " << header_size << " header lines" << std::endl;
1131  for ( int i = 0; i < header_size; ++i ) {
1132  std::getline (inFile, line);
1133  }
1134 
1135  counter_type counts;
1136  Teuchos::Array<Scalar> vals;
1137  Teuchos::Array<GO> gblRowInds;
1138  Teuchos::Array<GO> gblColInds;
1139  while (inFile) {
1140  std::getline (inFile, line);
1141  GO gblRowInd {};
1142  GO gblColInd {};
1143  Scalar val {};
1144  const bool gotLine = readEntryFromFile (gblRowInd, gblColInd, val, line);
1145  if (gotLine) {
1146  if ( convert_to_zero_base ) {
1147  gblRowInd -= 1 ;
1148  gblColInd -= 1 ;
1149  }
1150  counts[gblRowInd]++;
1151  vals.push_back(val);
1152  gblRowInds.push_back(gblRowInd);
1153  gblColInds.push_back(gblColInd);
1154  }
1155  }
1156 
1157  // Max number of entries in any row
1158  auto pr = std::max_element(
1159  std::begin(counts),
1160  std::end(counts),
1161  [] (pair_type const& p1, pair_type const& p2){ return p1.second < p2.second; }
1162  );
1163  size_t maxCount = (counts.empty()) ? size_t(0) : pr->second;
1164  A = Teuchos::rcp(new MAT(Epetra_DataAccess::Copy, *rowMap, maxCount));
1165  for (typename Teuchos::Array<GO>::size_type i=0; i<gblRowInds.size(); i++) {
1166  A->InsertGlobalValues (gblRowInds[i], 1, &vals[i], &gblColInds[i]);
1167  }
1168  } else {
1169  A = Teuchos::rcp(new MAT(Epetra_DataAccess::Copy, *rowMap, 0));
1170  }
1171 
1172  A->FillComplete (*domainMap, *rangeMap);
1173  return A;
1174  }
1175 #endif
1176 
1177  template<class map_type, class MAT>
1178  Teuchos::RCP<MAT>
1179  readCrsMatrixFromFile (const std::string& matrixFilename,
1180  Teuchos::RCP<Teuchos::FancyOStream> & fos,
1181  const Teuchos::RCP<const map_type>& rowMap,
1182  const Teuchos::RCP<const map_type>& domainMap,
1183  const Teuchos::RCP<const map_type>& rangeMap,
1184  const bool convert_to_zero_base,
1185  const int header_size)
1186  {
1187  using Scalar = typename MAT::scalar_type;
1188  using GO = typename MAT::global_ordinal_type;
1189 
1190  using counter_type = std::map<GO, size_t>;
1191  using pair_type = std::pair<const GO, size_t>;
1192  using Teuchos::RCP;
1193 
1194  auto comm = rowMap->getComm ();
1195  const int myRank = comm->getRank ();
1196 
1197  std::ifstream inFile;
1198  int opened = 0;
1199  if (myRank == 0)
1200  {
1201  try {
1202  inFile.open (matrixFilename);
1203  if (inFile) {
1204  opened = 1;
1205  }
1206  }
1207  catch (...) {
1208  opened = 0;
1209  }
1210  }
1211  Teuchos::broadcast<int, int> (*comm, 0, Teuchos::outArg (opened));
1212  TEUCHOS_TEST_FOR_EXCEPTION
1213  (opened == 0, std::runtime_error, "readCrsMatrixFromFile: "
1214  "Failed to open file \"" << matrixFilename << "\" on Process 0.");
1215 
1216  RCP<MAT> A;
1217  if (myRank == 0)
1218  {
1219  std::string line;
1220 
1221  // Skip the first N lines. This is a hack, specific to the input file in question.
1222  //*fos << " Reading matrix market file. Skip " << header_size << " header lines" << std::endl;
1223  for ( int i = 0; i < header_size; ++i ) {
1224  std::getline (inFile, line);
1225  }
1226 
1227  counter_type counts;
1228  Teuchos::Array<Scalar> vals;
1229  Teuchos::Array<GO> gblRowInds;
1230  Teuchos::Array<GO> gblColInds;
1231  while (inFile) {
1232  std::getline (inFile, line);
1233  GO gblRowInd {};
1234  GO gblColInd {};
1235  Scalar val {};
1236  const bool gotLine = readEntryFromFile (gblRowInd, gblColInd, val, line);
1237  if (gotLine) {
1238  //*fos << " read mtx rank: " << myRank << " | gblRowInd = " << gblRowInd << " gblColInd = " << gblColInd << std::endl;
1239  if ( convert_to_zero_base ) {
1240  gblRowInd -= 1 ;
1241  gblColInd -= 1 ;
1242  }
1243  counts[gblRowInd]++;
1244  vals.push_back(val);
1245  gblRowInds.push_back(gblRowInd);
1246  gblColInds.push_back(gblColInd);
1247  }
1248  }
1249 
1250  // Max number of entries in any row
1251  auto pr = std::max_element(
1252  std::begin(counts),
1253  std::end(counts),
1254  [] (pair_type const& p1, pair_type const& p2){ return p1.second < p2.second; }
1255  );
1256  size_t maxCount = (counts.empty()) ? size_t(0) : pr->second;
1257  A = Teuchos::rcp(new MAT(rowMap, maxCount));
1258  for (typename Teuchos::Array<GO>::size_type i=0; i<gblRowInds.size(); i++) {
1259  A->insertGlobalValues (gblRowInds[i], gblColInds(i,1), vals(i,1));
1260  }
1261  } else {
1262  A = Teuchos::rcp(new MAT(rowMap, 0));
1263  }
1264 
1265  A->fillComplete (domainMap, rangeMap);
1266  return A;
1267  }
1270  } // end namespace Util
1271 
1272 } // end namespace Amesos2
1273 
1274 #endif // #ifndef AMESOS2_UTIL_HPP
A generic helper class for getting a CCS representation of a Matrix.
Definition: Amesos2_Util.hpp:618
const int size
Definition: klu2_simple.cpp:50
void scale(ArrayView< Scalar1 > vals, size_t l, size_t ld, ArrayView< Scalar2 > s)
Scales a 1-D representation of a multivector.
A generic base class for the CRS and CCS helpers.
Definition: Amesos2_Util.hpp:237
Provides some simple meta-programming utilities for Amesos2.
EStorage_Ordering
Definition: Amesos2_TypeDecl.hpp:107
void transpose(ArrayView< Scalar > vals, ArrayView< GlobalOrdinal > indices, ArrayView< GlobalSizeT > ptr, ArrayView< Scalar > trans_vals, ArrayView< GlobalOrdinal > trans_indices, ArrayView< GlobalSizeT > trans_ptr)
Copy or assign views based on memory spaces.
const RCP< const Teuchos::Comm< int > > to_teuchos_comm(RCP< const Epetra_Comm > c)
Transform an Epetra_Comm object into a Teuchos::Comm object.
void printLine(Teuchos::FancyOStream &out)
Prints a line of 70 &quot;-&quot;s on std::cout.
Definition: Amesos2_Util.cpp:85
const RCP< const Epetra_Comm > to_epetra_comm(RCP< const Teuchos::Comm< int > > c)
Transfrom a Teuchos::Comm object into an Epetra_Comm object.
const Teuchos::RCP< const Tpetra::Map< LO, GO, Node > > getGatherMap(const Teuchos::RCP< const Tpetra::Map< LO, GO, Node > > &map)
Gets a Tpetra::Map described by the EDistribution.
Definition: Amesos2_Util.hpp:641
Similar to get_ccs_helper , but used to get a CRS representation of the given matrix.
Definition: Amesos2_Util.hpp:629
RCP< Epetra_Map > tpetra_map_to_epetra_map(const Tpetra::Map< LO, GO, Node > &map)
Transform a Tpetra::Map object into an Epetra_Map.
Definition: Amesos2_Util.hpp:729
Enum and other types declarations for Amesos2.
RCP< Tpetra::Map< LO, GO, Node > > epetra_map_to_tpetra_map(const Epetra_BlockMap &map)
Transform an Epetra_Map object into a Tpetra::Map.
Definition: Amesos2_Util.hpp:696
EDistribution
Definition: Amesos2_TypeDecl.hpp:89