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
49namespace 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:
676 return Tpetra::createUniformContigMapWithNode<LO,GO, Node>(num_global_elements, comm);
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 }
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
Copy or assign views based on memory spaces.
Provides some simple meta-programming utilities for Amesos2.
Enum and other types declarations for Amesos2.
EDistribution
Definition Amesos2_TypeDecl.hpp:89
@ DISTRIBUTED
Definition Amesos2_TypeDecl.hpp:90
@ GLOBALLY_REPLICATED
Definition Amesos2_TypeDecl.hpp:92
@ DISTRIBUTED_NO_OVERLAP
Definition Amesos2_TypeDecl.hpp:91
@ ROOTED
Definition Amesos2_TypeDecl.hpp:93
@ CONTIGUOUS_AND_ROOTED
Definition Amesos2_TypeDecl.hpp:94
EStorage_Ordering
Definition Amesos2_TypeDecl.hpp:107
void printLine(Teuchos::FancyOStream &out)
Prints a line of 70 "-"s on std::cout.
Definition Amesos2_Util.cpp:85
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
void scale(ArrayView< Scalar1 > vals, size_t l, size_t ld, ArrayView< Scalar2 > s)
Scales a 1-D representation of a multivector.
void transpose(ArrayView< Scalar > vals, ArrayView< GlobalOrdinal > indices, ArrayView< GlobalSizeT > ptr, ArrayView< Scalar > trans_vals, ArrayView< GlobalOrdinal > trans_indices, ArrayView< GlobalSizeT > trans_ptr)
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 RCP< const Teuchos::Comm< int > > to_teuchos_comm(RCP< const Epetra_Comm > c)
Transform an Epetra_Comm object into a Teuchos::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
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
const int size
Definition klu2_simple.cpp:50
A generic helper class for getting a CCS representation of a Matrix.
Definition Amesos2_Util.hpp:633
Similar to get_ccs_helper , but used to get a CRS representation of the given matrix.
Definition Amesos2_Util.hpp:644
A generic base class for the CRS and CCS helpers.
Definition Amesos2_Util.hpp:238