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