18 #ifndef AMESOS2_UTIL_HPP
19 #define AMESOS2_UTIL_HPP
25 #include "Amesos2_config.h"
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"
33 #include <Tpetra_Map.hpp>
34 #include <Tpetra_DistObject_decl.hpp>
35 #include <Tpetra_ComputeGatherMap.hpp>
41 #ifdef HAVE_AMESOS2_EPETRA
42 #include <Epetra_Map.h>
45 #ifdef HAVE_AMESOS2_METIS
60 using Teuchos::ArrayView;
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 );
83 template <
typename LO,
typename GO,
typename GS,
typename Node>
84 const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
86 GS num_global_elements,
87 const Teuchos::RCP<
const Teuchos::Comm<int> >& comm,
89 const Teuchos::RCP<
const Tpetra::Map<LO,GO,Node> >& map = Teuchos::null);
92 #ifdef HAVE_AMESOS2_EPETRA
99 template <
typename LO,
typename GO,
typename GS,
typename Node>
100 RCP<Tpetra::Map<LO,GO,Node> >
108 template <
typename LO,
typename GO,
typename GS,
typename Node>
117 const RCP<const Teuchos::Comm<int> >
to_teuchos_comm(RCP<const Epetra_Comm> c);
124 const RCP<const Epetra_Comm>
to_epetra_comm(RCP<
const Teuchos::Comm<int> > c);
125 #endif // HAVE_AMESOS2_EPETRA
132 template <
typename Scalar,
133 typename GlobalOrdinal,
134 typename GlobalSizeT>
136 ArrayView<GlobalOrdinal> indices,
137 ArrayView<GlobalSizeT> ptr,
138 ArrayView<Scalar> trans_vals,
139 ArrayView<GlobalOrdinal> trans_indices,
140 ArrayView<GlobalSizeT> trans_ptr);
155 template <
typename Scalar1,
typename Scalar2>
156 void scale(ArrayView<Scalar1> vals,
size_t l,
157 size_t ld, ArrayView<Scalar2> s);
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);
183 void printLine( Teuchos::FancyOStream &out );
188 template <
class T0,
class T1 >
189 struct getStdCplxType
191 using common_type =
typename std::common_type<T0,T1>::type;
192 using type = common_type;
195 template <
class T0,
class T1 >
196 struct getStdCplxType< T0, T1* >
198 using common_type =
typename std::common_type<T0,T1>::type;
199 using type = common_type;
202 #if defined(HAVE_TEUCHOS_COMPLEX) && defined(HAVE_AMESOS2_KOKKOS)
203 template <
class T0 >
204 struct getStdCplxType< T0, Kokkos::complex<T0>* >
206 using type = std::complex<T0>;
209 template <
class T0 ,
class T1 >
210 struct getStdCplxType< T0, Kokkos::complex<T1>* >
212 using common_type =
typename std::common_type<T0,T1>::type;
213 using type = std::complex<common_type>;
236 template<
class M,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
239 static void do_get(
const Teuchos::Ptr<const M> mat,
243 typename KV_GS::value_type& nnz,
245 const Tpetra::Map<
typename M::local_ordinal_t,
246 typename M::global_ordinal_t,
247 typename M::node_t> > map,
251 Op::template apply_kokkos_view<KV_S, KV_GO, KV_GS>(mat, nzvals,
252 indices, pointers, nnz, map, distribution, ordering);
256 template<
class M,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
257 struct diff_gs_helper_kokkos_view
259 static void do_get(
const Teuchos::Ptr<const M> mat,
263 typename KV_GS::value_type& nnz,
265 const Tpetra::Map<
typename M::local_ordinal_t,
266 typename M::global_ordinal_t,
267 typename M::node_t> > map,
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);
274 KV_TMP pointers_tmp(Kokkos::ViewAllocateWithoutInitializing(
"pointers_tmp"), size);
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);
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));
285 nnz = Teuchos::as<view_gs_t>(nnz_tmp);
289 template<
class M,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
290 struct same_go_helper_kokkos_view
292 static void do_get(
const Teuchos::Ptr<const M> mat,
296 typename KV_GS::value_type& nnz,
298 const Tpetra::Map<
typename M::local_ordinal_t,
299 typename M::global_ordinal_t,
300 typename M::node_t> > map,
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,
310 distribution, ordering);
314 template<
class M,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
315 struct diff_go_helper_kokkos_view
317 static void do_get(
const Teuchos::Ptr<const M> mat,
321 typename KV_GS::value_type& nnz,
323 const Tpetra::Map<
typename M::local_ordinal_t,
324 typename M::global_ordinal_t,
325 typename M::node_t> > map,
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);
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,
341 distribution, ordering);
342 for (i = 0; i <
size; ++i){
343 indices(i) = Teuchos::as<view_go_t>(indices_tmp(i));
348 template<
class M,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
349 struct same_scalar_helper_kokkos_view
351 static void do_get(
const Teuchos::Ptr<const M> mat,
355 typename KV_GS::value_type& nnz,
357 const Tpetra::Map<
typename M::local_ordinal_t,
358 typename M::global_ordinal_t,
359 typename M::node_t> > map,
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,
369 distribution, ordering);
373 template<
class M,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
374 struct diff_scalar_helper_kokkos_view
376 static void do_get(
const Teuchos::Ptr<const M> mat,
380 typename KV_GS::value_type& nnz,
382 const Tpetra::Map<
typename M::local_ordinal_t,
383 typename M::global_ordinal_t,
384 typename M::node_t> > map,
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);
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,
400 distribution, ordering);
402 for (i = 0; i <
size; ++i){
403 nzvals(i) = Teuchos::as<view_scalar_t>(nzvals_tmp(i));
409 template<
class Matrix,
typename KV_S,
typename KV_GO,
typename KV_GS,
class Op>
410 struct get_cxs_helper_kokkos_view
412 static void do_get(
const Teuchos::Ptr<const Matrix> mat,
416 typename KV_GS::value_type& nnz,
419 typename KV_GO::value_type indexBase = 0)
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;
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),
431 Op::getMapFromMatrix(mat)
433 do_get(mat, nzvals, indices, pointers, nnz, Teuchos::ptrInArg(*map), distribution, ordering);
440 static void do_get(
const Teuchos::Ptr<const Matrix> mat,
444 typename KV_GS::value_type& nnz,
448 const Teuchos::RCP<
const Tpetra::Map<
typename Matrix::local_ordinal_t,
449 typename Matrix::global_ordinal_t,
450 typename Matrix::node_t> > map
452 do_get(mat, nzvals, indices, pointers, nnz, Teuchos::ptrInArg(*map), distribution, ordering);
459 static void do_get(
const Teuchos::Ptr<const Matrix> mat,
463 typename KV_GS::value_type& nnz,
465 const Tpetra::Map<
typename Matrix::local_ordinal_t,
466 typename Matrix::global_ordinal_t,
467 typename Matrix::node_t> > map,
471 typedef typename Matrix::scalar_t mat_scalar;
472 typedef typename KV_S::value_type view_scalar_t;
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,
480 distribution, ordering);
484 #ifndef DOXYGEN_SHOULD_SKIP_THIS
489 template<
class Matrix>
492 template<
typename KV_S,
typename KV_GO,
typename KV_GS>
493 static void apply_kokkos_view(
const Teuchos::Ptr<const Matrix> mat,
497 typename Matrix::global_size_t& nnz,
499 const Tpetra::Map<
typename Matrix::local_ordinal_t,
500 typename Matrix::global_ordinal_t,
501 typename Matrix::node_t> > map,
505 mat->getCcs_kokkos_view(nzvals, rowind, colptr, nnz, map, ordering, distribution);
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)
514 return mat->getMap();
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)
523 return mat->getColMap();
527 typename Matrix::global_size_t
528 get_dimension(
const Teuchos::Ptr<const Matrix> mat)
530 return mat->getGlobalNumCols();
534 template<
class Matrix>
537 template<
typename KV_S,
typename KV_GO,
typename KV_GS>
538 static void apply_kokkos_view(
const Teuchos::Ptr<const Matrix> mat,
542 typename Matrix::global_size_t& nnz,
544 const Tpetra::Map<
typename Matrix::local_ordinal_t,
545 typename Matrix::global_ordinal_t,
546 typename Matrix::node_t> > map,
550 mat->getCrs_kokkos_view(nzvals, colind, rowptr, nnz, map, ordering, distribution);
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)
559 return mat->getMap();
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)
568 return mat->getRowMap();
572 typename Matrix::global_size_t
573 get_dimension(
const Teuchos::Ptr<const Matrix> mat)
575 return mat->getGlobalNumRows();
578 #endif // DOXYGEN_SHOULD_SKIP_THIS
617 template<
class Matrix,
typename KV_S,
typename KV_GO,
typename KV_GS>
628 template<
class Matrix,
typename KV_S,
typename KV_GO,
typename KV_GS>
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 )
644 Teuchos::RCP< const Tpetra::Map<LO,GO,Node> > gather_map = Tpetra::Details::computeGatherMap(map, Teuchos::null);
649 template <
typename LO,
typename GO,
typename GS,
typename Node>
650 const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
652 GS num_global_elements,
653 const Teuchos::RCP<
const Teuchos::Comm<int> >& comm,
655 const Teuchos::RCP<
const Tpetra::Map<LO,GO,Node> >& map)
659 switch( distribution ){
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);
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; }
671 return rcp(
new Tpetra::Map<LO,GO, Node>(num_global_elements,
672 my_num_elems, indexBase, comm));
674 case CONTIGUOUS_AND_ROOTED:
676 const Teuchos::RCP<const Tpetra::Map<LO,GO,Node> > gathermap
677 = getGatherMap<LO,GO,GS,Node>( map );
681 TEUCHOS_TEST_FOR_EXCEPTION(
true,
683 "Control should never reach this point. "
684 "Please contact the Amesos2 developers." );
689 #ifdef HAVE_AMESOS2_EPETRA
694 template <
typename LO,
typename GO,
typename GS,
typename Node>
695 Teuchos::RCP<Tpetra::Map<LO,GO,Node> >
701 int num_my_elements = map.NumMyElements();
702 Teuchos::Array<int> my_global_elements(num_my_elements);
703 map.MyGlobalElements(my_global_elements.getRawPtr());
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]);
715 using Teuchos::av_reinterpret_cast;
716 my_gbl_inds = av_reinterpret_cast<GO> (my_global_elements ());
719 typedef Tpetra::Map<LO,GO,Node> map_t;
720 RCP<map_t> tmap = rcp(
new map_t(Teuchos::OrdinalTraits<GS>::invalid(),
722 as<GO>(map.IndexBase()),
727 template <
typename LO,
typename GO,
typename GS,
typename Node>
728 Teuchos::RCP<Epetra_Map>
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]);
742 RCP<Epetra_Map> emap = rcp(
new Epetra_Map(-1,
744 my_global_elements.getRawPtr(),
745 as<GO>(map.getIndexBase()),
749 #endif // HAVE_AMESOS2_EPETRA
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)
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." );
782 typename Teuchos::ArrayView<GlobalOrdinal>::iterator ind_it, ind_end;
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]);
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);
797 trans_ptr.assign(count);
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]]);
825 template <
typename Scalar1,
typename Scalar2>
827 scale(Teuchos::ArrayView<Scalar1> vals,
size_t l,
828 size_t ld, Teuchos::ArrayView<Scalar2> s)
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" );
838 for( i = 0, s_i = 0; i < vals_size; ++i, ++s_i ){
848 template <
typename Scalar1,
typename Scalar2,
class BinaryOp>
850 scale(Teuchos::ArrayView<Scalar1> vals,
size_t l,
851 size_t ld, Teuchos::ArrayView<Scalar2> s,
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" );
862 for( i = 0, s_i = 0; i < vals_size; ++i, ++s_i ){
868 vals[i] = binary_op(vals[i], s[s_i]);
872 template<
class row_ptr_view_t,
class cols_view_t,
class per_view_t>
874 reorder(row_ptr_view_t & row_ptr, cols_view_t & cols,
875 per_view_t & perm, per_view_t & peri,
size_t & nnz,
878 #ifndef HAVE_AMESOS2_METIS
879 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
880 "Cannot reorder for cuSolver because no METIS is available.");
882 typedef typename cols_view_t::value_type ordinal_type;
883 typedef typename row_ptr_view_t::value_type size_type;
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);
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"),
899 host_metis_array host_strip_diag_cols(
900 Kokkos::ViewAllocateWithoutInitializing(
"host_strip_diag_cols"),
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);
912 host_strip_diag_row_ptr(size) = new_nnz;
915 host_metis_array host_perm(
916 Kokkos::ViewAllocateWithoutInitializing(
"host_perm"), size);
917 host_metis_array host_peri(
918 Kokkos::ViewAllocateWithoutInitializing(
"host_peri"), size);
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());
926 TEUCHOS_TEST_FOR_EXCEPTION(err != METIS_OK, std::runtime_error,
927 "METIS_NodeND failed to sort matrix.");
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);
939 deep_copy_or_assign_view(perm, device_perm);
940 deep_copy_or_assign_view(peri, device_peri);
942 if (permute_matrix) {
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);
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) {
954 new_row_ptr(i) = update;
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));
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));
987 row_ptr = new_row_ptr;
992 #endif // HAVE_AMESOS2_METIS
995 template<
class values_view_t,
class row_ptr_view_t,
996 class cols_view_t,
class per_view_t>
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,
1003 typedef typename cols_view_t::value_type ordinal_type;
1004 typedef typename cols_view_t::execution_space exec_space_t;
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);
1011 const ordinal_type size = orig_row_ptr.size() - 1;
1013 auto host_orig_row_ptr = Kokkos::create_mirror_view(orig_row_ptr);
1014 auto new_nnz = host_orig_row_ptr(size);
1016 values_view_t new_values(
1017 Kokkos::ViewAllocateWithoutInitializing(
"new_values"), values.size() - new_nnz/2);
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));
1032 new_values(tk) = values(sk);
1038 values = new_values;
1041 template<
class array_view_t,
class per_view_t>
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));
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);
1061 template <
typename GO,
typename Scalar>
1063 readEntryFromFile (GO& gblRowInd, GO& gblColInd, Scalar& val,
const std::string& s)
1065 if (s.size () == 0 || s.find (
"%") != std::string::npos) {
1068 std::istringstream in (s);
1085 #ifdef HAVE_AMESOS2_EPETRA
1086 template<
class map_type,
class 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)
1096 using Scalar = double;
1099 using counter_type = std::map<GO, size_t>;
1100 using pair_type = std::pair<const GO, size_t>;
1103 const int myRank = rowMap->Comm().MyPID();
1105 std::ifstream inFile;
1110 inFile.open (matrixFilename);
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.");
1131 for (
int i = 0; i < header_size; ++i ) {
1132 std::getline (inFile, line);
1135 counter_type counts;
1136 Teuchos::Array<Scalar> vals;
1137 Teuchos::Array<GO> gblRowInds;
1138 Teuchos::Array<GO> gblColInds;
1140 std::getline (inFile, line);
1144 const bool gotLine = readEntryFromFile (gblRowInd, gblColInd, val, line);
1146 if ( convert_to_zero_base ) {
1150 counts[gblRowInd]++;
1151 vals.push_back(val);
1152 gblRowInds.push_back(gblRowInd);
1153 gblColInds.push_back(gblColInd);
1158 auto pr = std::max_element(
1161 [] (pair_type
const& p1, pair_type
const& p2){
return p1.second < p2.second; }
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]);
1169 A = Teuchos::rcp(
new MAT(Epetra_DataAccess::Copy, *rowMap, 0));
1172 A->FillComplete (*domainMap, *rangeMap);
1177 template<
class map_type,
class 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)
1187 using Scalar =
typename MAT::scalar_type;
1188 using GO =
typename MAT::global_ordinal_type;
1190 using counter_type = std::map<GO, size_t>;
1191 using pair_type = std::pair<const GO, size_t>;
1194 auto comm = rowMap->getComm ();
1195 const int myRank = comm->getRank ();
1197 std::ifstream inFile;
1202 inFile.open (matrixFilename);
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.");
1223 for (
int i = 0; i < header_size; ++i ) {
1224 std::getline (inFile, line);
1227 counter_type counts;
1228 Teuchos::Array<Scalar> vals;
1229 Teuchos::Array<GO> gblRowInds;
1230 Teuchos::Array<GO> gblColInds;
1232 std::getline (inFile, line);
1236 const bool gotLine = readEntryFromFile (gblRowInd, gblColInd, val, line);
1239 if ( convert_to_zero_base ) {
1243 counts[gblRowInd]++;
1244 vals.push_back(val);
1245 gblRowInds.push_back(gblRowInd);
1246 gblColInds.push_back(gblColInd);
1251 auto pr = std::max_element(
1254 [] (pair_type
const& p1, pair_type
const& p2){
return p1.second < p2.second; }
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));
1262 A = Teuchos::rcp(
new MAT(rowMap, 0));
1265 A->fillComplete (domainMap, rangeMap);
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
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 "-"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