10#ifndef TPETRA_MATRIXMATRIX_DEF_HPP
11#define TPETRA_MATRIXMATRIX_DEF_HPP
13#include "KokkosSparse_Utils.hpp"
14#include "Tpetra_ConfigDefs.hpp"
16#include "Teuchos_VerboseObject.hpp"
17#include "Teuchos_Array.hpp"
19#include "Tpetra_CrsMatrix.hpp"
20#include "Tpetra_BlockCrsMatrix.hpp"
22#include "Tpetra_RowMatrixTransposer.hpp"
25#include "Tpetra_Details_makeColMap.hpp"
26#include "Tpetra_ConfigDefs.hpp"
27#include "Tpetra_Map.hpp"
28#include "Tpetra_Export.hpp"
35#include "Teuchos_FancyOStream.hpp"
37#include "TpetraExt_MatrixMatrix_ExtraKernels_def.hpp"
40#include "KokkosSparse_spgemm.hpp"
41#include "KokkosSparse_spadd.hpp"
42#include "Kokkos_Bitset.hpp"
44#include <MatrixMarket_Tpetra.hpp>
54#include "TpetraExt_MatrixMatrix_OpenMP.hpp"
55#include "TpetraExt_MatrixMatrix_Cuda.hpp"
56#include "TpetraExt_MatrixMatrix_HIP.hpp"
57#include "TpetraExt_MatrixMatrix_SYCL.hpp"
61namespace MatrixMatrix {
69template <
class Scalar,
80 const std::string& label,
81 const Teuchos::RCP<Teuchos::ParameterList>&
params) {
97 const std::string
prefix =
"TpetraExt::MatrixMatrix::Multiply(): ";
122 const bool newFlag = !
C.getGraph()->isLocallyIndexed() && !
C.getGraph()->isGloballyIndexed();
128#ifdef USE_OLD_TRANSPOSE
132 using Teuchos::ParameterList;
158 prefix <<
"ERROR, inner dimensions of op(A) and op(B) "
159 "must match for matrix-matrix product. op(A) is "
167 prefix <<
"ERROR, dimensions of result C must "
168 "match dimensions of op(A) * op(B). C has "
169 <<
C.getGlobalNumRows()
170 <<
" rows, should have at least " <<
Aouter << std::endl);
178 if (!
C.isFillActive())
C.resumeFill();
220 MMdetails::mult_AT_B_newmatrix(
A,
B,
C, label,
params);
246 C.fillComplete(
Bprime->getDomainMap(),
Aprime->getRangeMap());
264 const std::string& label) {
276 std::string
prefix = std::string(
"TpetraExt ") + label + std::string(
": ");
292 prefix <<
"ERROR, inner dimensions of op(A) and op(B) "
293 "must match for matrix-matrix product. op(A) is "
300 const LO blocksize =
A->getBlockSize();
302 prefix <<
"ERROR, Blocksizes do not match. A.blocksize = " << blocksize <<
", B.blocksize = " <<
B->getBlockSize());
322 MMdetails::import_and_extract_views(*
B,
targetMap_B,
Bview,
A->getGraph()->getImporter(),
323 A->getGraph()->getImporter().is_null());
333void Jacobi(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType
omega,
339 const std::string& label,
340 const Teuchos::RCP<Teuchos::ParameterList>&
params) {
354 const std::string
prefix =
"TpetraExt::MatrixMatrix::Jacobi(): ";
373 prefix <<
"ERROR, inner dimensions of op(A) and op(B) "
374 "must match for matrix-matrix product. op(A) is "
382 prefix <<
"ERROR, dimensions of result C must "
383 "match dimensions of op(A) * op(B). C has "
384 <<
C.getGlobalNumRows()
385 <<
" rows, should have at least " <<
Aouter << std::endl);
415 importParams->set(
"compute global constants",
params->get(
"compute global constants: temporaries",
false));
437 bool newFlag = !
C.getGraph()->isLocallyIndexed() && !
C.getGraph()->isGloballyIndexed();
452 typedef Teuchos::ScalarTraits<Scalar> STS;
453 typename STS::magnitudeType
threshold =
params->get(
"remove zeros threshold", STS::magnitude(STS::zero()));
469 using Teuchos::Array;
479 const std::string
prefix =
"TpetraExt::MatrixMatrix::Add(): ";
482 prefix <<
"ERROR, input matrix A.isFillComplete() is false; it is required to be true. "
483 "(Result matrix B is not required to be isFillComplete()).");
485 prefix <<
"ERROR, input matrix B must not be fill complete!");
487 prefix <<
"ERROR, input matrix B must not have static graph!");
489 prefix <<
"ERROR, input matrix B must not be locally indexed!");
491 using Teuchos::ParameterList;
504 typename crs_matrix_type::nonconst_global_inds_host_view_type
a_inds(
"a_inds",
A.getLocalMaxNumRowEntries());
505 typename crs_matrix_type::nonconst_values_host_view_type
a_vals(
"a_vals",
A.getLocalMaxNumRowEntries());
508 if (
scalarB != Teuchos::ScalarTraits<SC>::one())
512 if (
scalarA != Teuchos::ScalarTraits<SC>::zero()) {
514 row =
B.getRowMap()->getGlobalElement(
i);
517 if (
scalarA != Teuchos::ScalarTraits<SC>::one()) {
530Teuchos::RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
539 const Teuchos::RCP<Teuchos::ParameterList>&
params) {
540 using Teuchos::ParameterList;
543 using Teuchos::rcpFromRef;
547 params->isParameter(
"Call fillComplete") && !
params->get<
bool>(
"Call fillComplete"),
548 std::invalid_argument,
549 "Tpetra::MatrixMatrix::add(): this version of add() always calls fillComplete\n"
550 "on the result, but you explicitly set 'Call fillComplete' = false in the parameter list. Don't set this explicitly.");
551 params->set(
"Call fillComplete",
true);
562 "TpetraExt::MatrixMatrix::add(): A and B must both be fill complete.");
573template <
class LO,
class GO,
class LOView,
class GOView,
class LocalMap>
574struct ConvertGlobalToLocalFunctor {
580 KOKKOS_FUNCTION
void operator()(
const GO i)
const {
581 lids(i) = localColMap.getLocalElement(gids(i));
586 const LocalMap localColMap;
589template <
class Scalar,
602 const Teuchos::RCP<Teuchos::ParameterList>&
params) {
605 using Teuchos::rcp_dynamic_cast;
606 using Teuchos::rcp_implicit_cast;
607 using Teuchos::rcpFromRef;
608 using Teuchos::TimeMonitor;
619 using exec_space =
typename crs_graph_type::execution_space;
620 using AddKern = MMdetails::AddKernels<SC, LO, GO, NO>;
621 const char*
prefix_mmm =
"TpetraExt::MatrixMatrix::add: ";
622 constexpr bool debug =
false;
627 std::ostringstream
os;
628 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
629 <<
"TpetraExt::MatrixMatrix::add" << std::endl;
630 std::cerr <<
os.str();
634 prefix_mmm <<
"C must be a 'new' matrix (neither locally nor globally indexed).");
636 prefix_mmm <<
"A and B must both be fill complete.");
637#ifdef HAVE_TPETRA_DEBUG
639 if (
A.isFillComplete() &&
B.isFillComplete()) {
642 !
A.getDomainMap()->locallySameAs(*
B.getDomainMap())) ||
644 !
A.getDomainMap()->isSameAs(*
B.getRangeMap())) ||
646 !
A.getRangeMap()->isSameAs(*
B.getDomainMap()));
648 prefix_mmm <<
"The domain Maps of Op(A) and Op(B) are not the same.");
652 !
A.getRangeMap()->isSameAs(*
B.getRangeMap())) ||
654 !
A.getRangeMap()->isSameAs(*
B.getDomainMap())) ||
656 !
A.getDomainMap()->isSameAs(*
B.getRangeMap()));
658 prefix_mmm <<
"The range Maps of Op(A) and Op(B) are not the same.");
662 using Teuchos::ParameterList;
670#ifdef HAVE_TPETRA_DEBUG
673 "Please report this bug to the Tpetra developers.");
680 std::ostringstream
os;
681 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
682 <<
"Form explicit xpose of B" << std::endl;
683 std::cerr <<
os.str();
688#ifdef HAVE_TPETRA_DEBUG
690 prefix_mmm <<
"Failed to compute Op(B). Please report this bug to the Tpetra developers.");
692 !
Aprime->isFillComplete() || !
Bprime->isFillComplete(), std::invalid_argument,
693 prefix_mmm <<
"Aprime and Bprime must both be fill complete. "
694 "Please report this bug to the Tpetra developers.");
706 typedef typename AddKern::values_array values_array;
707 typedef typename AddKern::row_ptrs_array row_ptrs_array;
708 typedef typename AddKern::col_inds_array col_inds_array;
718 if (!(
Aprime->getRowMap()->isSameAs(*(
Bprime->getRowMap())))) {
720 auto import = rcp(new import_type(Aprime->getRowMap(), Bprime->getRowMap()));
732 if (Teuchos::nonnull(
params) &&
params->isParameter(
"Call fillComplete")) {
744 rowptrs = row_ptrs_array(
"C rowptrs", 0);
749 using global_col_inds_array =
typename AddKern::global_col_inds_array;
758 std::ostringstream
os;
759 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
760 <<
"Call AddKern::convertToGlobalAndAdd(...)" << std::endl;
761 std::cerr <<
os.str();
763 AddKern::convertToGlobalAndAdd(
767 std::ostringstream
os;
768 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
769 <<
"Finished AddKern::convertToGlobalAndAdd(...)" << std::endl;
770 std::cerr <<
os.str();
779 Kokkos::parallel_for(Kokkos::RangePolicy<exec_space>(0,
globalColinds.extent(0)),
781 col_inds_array, global_col_inds_array,
792 auto Arowptrs =
Alocal.graph.row_map;
793 auto Browptrs =
Blocal.graph.row_map;
794 auto Acolinds =
Alocal.graph.entries;
795 auto Bcolinds =
Blocal.graph.entries;
801 std::ostringstream
os;
802 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
803 <<
"Call AddKern::addSorted(...)" << std::endl;
804 std::cerr <<
os.str();
806 AddKern::addSorted(
Avals, Arowptrs, Acolinds,
alpha,
Bvals, Browptrs, Bcolinds,
beta,
Aprime->getGlobalNumCols(),
vals,
rowptrs,
colinds);
813 std::ostringstream
os;
814 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
815 <<
"Call AddKern::addUnsorted(...)" << std::endl;
816 std::cerr <<
os.str();
818 AddKern::addUnsorted(
Avals, Arowptrs, Acolinds,
alpha,
Bvals, Browptrs, Bcolinds,
beta,
Aprime->getGlobalNumCols(),
vals,
rowptrs,
colinds);
829 std::ostringstream
os;
830 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
831 <<
"Create Cimport" << std::endl;
832 std::cerr <<
os.str();
838 std::ostringstream
os;
839 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
840 <<
"Create Cexport" << std::endl;
841 std::cerr <<
os.str();
847 std::ostringstream
os;
848 os <<
"Proc " <<
A.getMap()->getComm()->getRank() <<
": "
849 <<
"Call C->expertStaticFillComplete(...)" << std::endl;
850 std::cerr <<
os.str();
872 using Teuchos::Array;
873 using Teuchos::ArrayRCP;
874 using Teuchos::ArrayView;
877 using Teuchos::rcp_dynamic_cast;
878 using Teuchos::rcpFromRef;
879 using Teuchos::tuple;
881 typedef Teuchos::ScalarTraits<Scalar> STS;
889 std::string
prefix =
"TpetraExt::MatrixMatrix::Add(): ";
892 !
A.isFillComplete() || !
B.isFillComplete(), std::invalid_argument,
893 prefix <<
"A and B must both be fill complete before calling this function.");
897 prefix <<
"C is null (must be allocated), but A.haveGlobalConstants() is false. "
898 "Please report this bug to the Tpetra developers.");
900 prefix <<
"C is null (must be allocated), but B.haveGlobalConstants() is false. "
901 "Please report this bug to the Tpetra developers.");
904#ifdef HAVE_TPETRA_DEBUG
911 prefix <<
"The domain Maps of Op(A) and Op(B) are not the same.");
918 prefix <<
"The range Maps of Op(A) and Op(B) are not the same.");
922 using Teuchos::ParameterList;
935#ifdef HAVE_TPETRA_DEBUG
937 prefix <<
"Failed to compute Op(A). Please report this bug to the Tpetra developers.");
949#ifdef HAVE_TPETRA_DEBUG
951 prefix <<
"Failed to compute Op(B). Please report this bug to the Tpetra developers.");
961 C->setAllToScalar(STS::zero());
971 if (
Aprime->getRowMap()->isSameAs(*
Bprime->getRowMap())) {
980 C =
rcp(
new crs_matrix_type(
Aprime->getRowMap(),
Aprime->getGlobalMaxNumRowEntries() +
Bprime->getGlobalMaxNumRowEntries()));
984#ifdef HAVE_TPETRA_DEBUG
986 prefix <<
"At this point, Aprime is null. Please report this bug to the Tpetra developers.");
988 prefix <<
"At this point, Bprime is null. Please report this bug to the Tpetra developers.");
990 prefix <<
"At this point, C is null. Please report this bug to the Tpetra developers.");
998 for (
int k = 0;
k < 2; ++
k) {
999 typename crs_matrix_type::nonconst_global_inds_host_view_type
Indices;
1000 typename crs_matrix_type::nonconst_values_host_view_type
Values;
1008#ifdef HAVE_TPETRA_DEBUG
1010 prefix <<
"At this point, curRowMap is null. Please report this bug to the Tpetra developers.");
1013#ifdef HAVE_TPETRA_DEBUG
1015 prefix <<
"At this point, curRowMap is null. Please report this bug to the Tpetra developers.");
1021 size_t numEntries =
Mat[
k]->getNumEntriesInGlobalRow(
globalRow);
1022 if (numEntries > 0) {
1023 if (numEntries >
Indices.extent(0)) {
1024 Kokkos::resize(
Indices, numEntries);
1025 Kokkos::resize(
Values, numEntries);
1029 if (
scalar[
k] != STS::one()) {
1030 for (
size_t j = 0;
j < numEntries; ++
j) {
1039 prefix <<
"sumIntoGlobalValues failed to add entries from A or B into C.");
1048 C->fillComplete(
C->getDomainMap(),
1067 std::string
prefix =
"TpetraExt::MatrixMatrix::Add(): ";
1070 prefix <<
"C must not be null");
1072 Teuchos::RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
C_ =
C;
1078namespace MMdetails {
1084struct CrsMatrixApplyHelperAccess {
1085 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1086 static auto get(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& matrix) {
1087 return matrix.getApplyHelper();
1091template <
class Scalar,
1093 class GlobalOrdinal,
1095 class LocalOrdinalViewType>
1096void kokkos_kernels_mult_A_B_newmatrix(
1097 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1098 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1099 const LocalOrdinalViewType& Acol2Brow,
1100 const LocalOrdinalViewType& Acol2Irow,
1101 const LocalOrdinalViewType& Bcol2Ccol,
1102 const LocalOrdinalViewType& Icol2Ccol,
1103 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1104 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1105 const std::string& label,
1106 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1107 using backend_type = KokkosKernelsSPGEMMBackend<Node>;
1112 using device_t =
typename KCRS::device_type;
1113 using graph_t =
typename KCRS::StaticCrsGraphType;
1114 using lno_view_t =
typename graph_t::row_map_type::non_const_type;
1115 using int_view_t = Kokkos::View<int*, typename lno_view_t::array_layout, typename lno_view_t::memory_space, typename lno_view_t::memory_traits>;
1116 using lno_nnz_view_t =
typename graph_t::entries_type::non_const_type;
1117 using scalar_view_t =
typename KCRS::values_type::non_const_type;
1118 using KernelHandle = KokkosKernels::Experimental::KokkosKernelsHandle<
1119 typename lno_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1120 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1121 using IntKernelHandle = KokkosKernels::Experimental::KokkosKernelsHandle<
1122 typename int_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1123 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1125 const std::string wrapperLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"Wrapper";
1126 RCP<Tpetra::Details::ProfilingRegion> MM =
1129 int team_work_size = 16;
1130 std::string myalg(
"SPGEMM_DEFAULT");
1131 if (!params.is_null()) {
1132 const std::string prefixedAlg = backend_type::parameter_prefix() +
": algorithm";
1133 const std::string prefixedTeam = backend_type::parameter_prefix() +
": team work size";
1134 if (params->isParameter(prefixedAlg))
1135 myalg = params->get(prefixedAlg, myalg);
1136 if (params->isParameter(prefixedTeam))
1137 team_work_size = params->get(prefixedTeam, team_work_size);
1140 const KCRS Amat = Aview.origMatrix->getLocalMatrixDevice();
1142 const std::string genericAlg = backend_type::algorithm_label() +
" algorithm";
1143 if (!params.is_null() && params->isParameter(genericAlg))
1144 myalg = params->get(genericAlg, myalg);
1145 KokkosSparse::SPGEMMAlgorithm alg_enum = KokkosSparse::StringToSPGEMMAlgorithm(myalg);
1147 KCRS Bmerged = Tpetra::MMdetails::merge_matrices(
1148 Aview, Bview, Acol2Brow, Acol2Irow, Bcol2Ccol, Icol2Ccol, C.getColMap()->getLocalNumElements());
1149 backend_type::pre_spgemm(Bmerged);
1151 const std::string coreLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"Core";
1155 typename KernelHandle::nnz_lno_t AnumRows = Amat.numRows();
1156 typename KernelHandle::nnz_lno_t BnumRows = Bmerged.numRows();
1157 typename KernelHandle::nnz_lno_t BnumCols = Bmerged.numCols();
1159 lno_view_t row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"non_const_lno_row"), AnumRows + 1);
1160 lno_nnz_view_t entriesC;
1161 scalar_view_t valuesC;
1164 const bool useIntRowptrs =
1165 irph.shouldUseIntRowptrs() &&
1166 CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->shouldUseIntRowptrs();
1168 if (useIntRowptrs) {
1170 kh.create_spgemm_handle(alg_enum);
1171 kh.set_team_work_size(team_work_size);
1173 int_view_t int_row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"non_const_int_row"), AnumRows + 1);
1175 auto Aint = CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->getIntRowptrMatrix(Amat);
1176 auto Bint = irph.getIntRowptrMatrix(Bmerged);
1180 KokkosSparse::spgemm_symbolic(
1181 &kh, AnumRows, BnumRows, BnumCols, Aint.graph.row_map, Aint.graph.entries,
false, Bint.graph.row_map, Bint.graph.entries,
false, int_row_mapC);
1185 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1187 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1188 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1190 KokkosSparse::spgemm_numeric(
1191 &kh, AnumRows, BnumRows, BnumCols, Aint.graph.row_map, Aint.graph.entries, Aint.values,
false,
1192 Bint.graph.row_map, Bint.graph.entries, Bint.values,
false, int_row_mapC, entriesC, valuesC);
1193 Kokkos::parallel_for(
1194 Kokkos::RangePolicy<typename device_t::execution_space>(0, int_row_mapC.size()),
1195 KOKKOS_LAMBDA(
const int i) { row_mapC(i) = int_row_mapC(i); });
1196 kh.destroy_spgemm_handle();
1200 kh.create_spgemm_handle(alg_enum);
1201 kh.set_team_work_size(team_work_size);
1205 KokkosSparse::spgemm_symbolic(
1206 &kh, AnumRows, BnumRows, BnumCols, Amat.graph.row_map, Amat.graph.entries,
false, Bmerged.graph.row_map, Bmerged.graph.entries,
false, row_mapC);
1210 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1212 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1213 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1215 KokkosSparse::spgemm_numeric(
1216 &kh, AnumRows, BnumRows, BnumCols, Amat.graph.row_map, Amat.graph.entries, Amat.values,
false,
1217 Bmerged.graph.row_map, Bmerged.graph.entries, Bmerged.values,
false, row_mapC, entriesC, valuesC);
1218 kh.destroy_spgemm_handle();
1221 const std::string sortLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"Sort";
1225 if (params.is_null() || params->get(
"sort entries",
true))
1226 Import_Util::sortCrsEntries(row_mapC, entriesC, valuesC);
1227 C.setAllValues(row_mapC, entriesC, valuesC);
1229 const std::string esfcLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"ESFC";
1233 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
1234 labelList->set(
"Timer Label", label);
1235 if (!params.is_null())
1236 labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
1237 RCP<const Export<LocalOrdinal, GlobalOrdinal, Node>> dummyExport;
1238 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
1241template <
class Scalar,
1243 class GlobalOrdinal,
1245 class LocalOrdinalViewType>
1246void host_mult_A_B_reuse(
1247 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1248 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1249 const LocalOrdinalViewType& targetMapToOrigRow_dev,
1250 const LocalOrdinalViewType& targetMapToImportRow_dev,
1251 const LocalOrdinalViewType& Bcol2Ccol_dev,
1252 const LocalOrdinalViewType& Icol2Ccol_dev,
1253 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1254 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1255 const std::string& label,
1256 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1264 bool throwOnInsert =
true;
1265 if (!params.is_null() && params->isType<
bool>(
"MM Throw For Non-Existent Entries"))
1266 throwOnInsert = params->get<
bool>(
"MM Throw For Non-Existent Entries");
1271 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
1272 typedef typename KCRS::StaticCrsGraphType graph_t;
1273 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
1274 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1275 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1278 typedef LocalOrdinal LO;
1279 typedef GlobalOrdinal GO;
1281 typedef Map<LO, GO, NO> map_type;
1282 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1283 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1284 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
1292 auto targetMapToOrigRow =
1293 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1294 targetMapToOrigRow_dev);
1295 auto targetMapToImportRow =
1296 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1297 targetMapToImportRow_dev);
1299 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1302 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1306 RCP<const map_type> Ccolmap = C.getColMap();
1307 size_t m = Aview.origMatrix->getLocalNumRows();
1308 size_t n = Ccolmap->getLocalNumElements();
1311 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
1312 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
1313 const KCRS Cmat = C.getLocalMatrixHost();
1315 c_lno_view_t Arowptr = Amat.graph.row_map,
1316 Browptr = Bmat.graph.row_map,
1317 Crowptr = Cmat.graph.row_map;
1318 const lno_nnz_view_t Acolind = Amat.graph.entries,
1319 Bcolind = Bmat.graph.entries,
1320 Ccolind = Cmat.graph.entries;
1321 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
1322 scalar_view_t Cvals = Cmat.values;
1324 c_lno_view_t Irowptr;
1325 lno_nnz_view_t Icolind;
1326 scalar_view_t Ivals;
1327 if (!Bview.importMatrix.is_null()) {
1328 auto lclB = Bview.importMatrix->getLocalMatrixHost();
1329 Irowptr = lclB.graph.row_map;
1330 Icolind = lclB.graph.entries;
1331 Ivals = lclB.values;
1343 std::vector<size_t> c_status(n, ST_INVALID);
1346 size_t CSR_ip = 0, OLD_ip = 0;
1347 for (
size_t i = 0; i < m; i++) {
1350 OLD_ip = Crowptr[i];
1351 CSR_ip = Crowptr[i + 1];
1352 for (
size_t k = OLD_ip; k < CSR_ip; k++) {
1353 c_status[Ccolind[k]] = k;
1359 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
1360 LO Aik = Acolind[k];
1361 const SC Aval = Avals[k];
1362 if (Aval == SC_ZERO)
1365 if (targetMapToOrigRow[Aik] != LO_INVALID) {
1367 size_t Bk = Teuchos::as<size_t>(targetMapToOrigRow[Aik]);
1369 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
1370 LO Bkj = Bcolind[j];
1371 LO Cij = Bcol2Ccol[Bkj];
1373 const bool badInsert = (Cij == LO_INVALID) || (c_status[Cij] < OLD_ip) || (c_status[Cij] >= CSR_ip);
1375 Cvals[c_status[Cij]] += Aval * Bvals[j];
1376 else if (throwOnInsert)
1377 TEUCHOS_TEST_FOR_EXCEPTION(badInsert,
1378 std::runtime_error,
"Trying to insert a new entry (" << i <<
"," << Cij <<
") into a static graph "
1379 <<
"(c_status = " << c_status[Cij] <<
" of [" << OLD_ip <<
"," << CSR_ip <<
"))");
1384 size_t Ik = Teuchos::as<size_t>(targetMapToImportRow[Aik]);
1385 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
1386 LO Ikj = Icolind[j];
1387 LO Cij = Icol2Ccol[Ikj];
1389 const bool badInsert = (Cij == LO_INVALID) || (c_status[Cij] < OLD_ip) || (c_status[Cij] >= CSR_ip);
1391 Cvals[c_status[Cij]] += Aval * Ivals[j];
1392 else if (throwOnInsert)
1393 TEUCHOS_TEST_FOR_EXCEPTION(badInsert,
1394 std::runtime_error,
"Trying to insert a new entry (" << i <<
"," << Cij <<
") into a static graph "
1395 <<
"(c_status = " << c_status[Cij] <<
" of [" << OLD_ip <<
"," << CSR_ip <<
"))");
1401 C.fillComplete(C.getDomainMap(), C.getRangeMap());
1404template <
class Scalar,
1406 class GlobalOrdinal,
1408 class LocalOrdinalViewType>
1409void kokkos_kernels_jacobi_A_B_newmatrix(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
1410 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
1411 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1412 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1413 const LocalOrdinalViewType& Acol2Brow,
1414 const LocalOrdinalViewType& Acol2Irow,
1415 const LocalOrdinalViewType& Bcol2Ccol,
1416 const LocalOrdinalViewType& Icol2Ccol,
1417 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1418 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1419 const std::string& label,
1420 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1421 using backend_type = KokkosKernelsSPGEMMBackend<Node>;
1425 auto rowMap = Aview.origMatrix->getRowMap();
1427 Aview.origMatrix->getLocalDiagCopy(diags);
1428 size_t diagLength = rowMap->getLocalNumElements();
1429 Teuchos::Array<Scalar> diagonal(diagLength);
1430 diags.get1dCopy(diagonal());
1432 for (
size_t i = 0; i < diagLength; ++i) {
1433 TEUCHOS_TEST_FOR_EXCEPTION(diagonal[i] == Teuchos::ScalarTraits<Scalar>::zero(),
1435 "Matrix A has a zero/missing diagonal: " << diagonal[i] << std::endl
1436 <<
"KokkosKernels Jacobi-fused SpGEMM requires nonzero diagonal entries in A" << std::endl);
1445 using device_t =
typename Node::device_type;
1447 using graph_t =
typename matrix_t::StaticCrsGraphType;
1448 using lno_view_t =
typename graph_t::row_map_type::non_const_type;
1449 using int_view_t = Kokkos::View<
int*,
1450 typename lno_view_t::array_layout,
1451 typename lno_view_t::memory_space,
1452 typename lno_view_t::memory_traits>;
1453 using lno_nnz_view_t =
typename graph_t::entries_type::non_const_type;
1454 using scalar_view_t =
typename matrix_t::values_type::non_const_type;
1457 using handle_t =
typename KokkosKernels::Experimental::KokkosKernelsHandle<
1458 typename lno_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1459 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1461 using int_handle_t =
typename KokkosKernels::Experimental::KokkosKernelsHandle<
1462 typename int_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1463 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1466 const matrix_t Bmerged = Tpetra::MMdetails::merge_matrices(Aview, Bview, Acol2Brow, Acol2Irow, Bcol2Ccol, Icol2Ccol, C.getColMap()->getLocalNumElements());
1469 const matrix_t Amat = Aview.origMatrix->getLocalMatrixDevice();
1470 const matrix_t Bmat = Bview.origMatrix->getLocalMatrixDevice();
1472 typename handle_t::nnz_lno_t AnumRows = Amat.numRows();
1473 typename handle_t::nnz_lno_t BnumRows = Bmerged.numRows();
1474 typename handle_t::nnz_lno_t BnumCols = Bmerged.numCols();
1477 lno_view_t row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"row_mapC"), AnumRows + 1);
1478 lno_nnz_view_t entriesC;
1479 scalar_view_t valuesC;
1482 int team_work_size = 16;
1483 std::string myalg(
"SPGEMM_DEFAULT");
1484 if (!params.is_null()) {
1485 const std::string prefixedAlg = backend_type::parameter_prefix() +
": algorithm";
1486 const std::string prefixedTeam = backend_type::parameter_prefix() +
": team work size";
1487 if (params->isParameter(prefixedAlg))
1488 myalg = params->get(prefixedAlg, myalg);
1489 if (params->isParameter(prefixedTeam))
1490 team_work_size = params->get(prefixedTeam, team_work_size);
1494 const std::string genericAlg = backend_type::algorithm_label() +
" algorithm";
1495 if (!params.is_null() && params->isParameter(genericAlg))
1496 myalg = params->get(genericAlg, myalg);
1497 KokkosSparse::SPGEMMAlgorithm alg_enum = KokkosSparse::StringToSPGEMMAlgorithm(myalg);
1501 const bool useIntRowptrs =
1502 irph.shouldUseIntRowptrs() &&
1503 CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->shouldUseIntRowptrs();
1505 const Scalar jacobiOmega = omega * Teuchos::ScalarTraits<Scalar>::one();
1507 if (useIntRowptrs) {
1509 kh.create_spgemm_handle(alg_enum);
1510 kh.set_team_work_size(team_work_size);
1512 int_view_t int_row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"int_row_mapC"), AnumRows + 1);
1514 auto Aint = CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->getIntRowptrMatrix(Amat);
1515 auto Bint = irph.getIntRowptrMatrix(Bmerged);
1519 KokkosSparse::spgemm_symbolic(&kh, AnumRows, BnumRows, BnumCols,
1520 Aint.graph.row_map, Aint.graph.entries,
false,
1521 Bint.graph.row_map, Bint.graph.entries,
false,
1525 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1527 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1528 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1535 KokkosSparse::Experimental::spgemm_jacobi(&kh, AnumRows, BnumRows, BnumCols,
1536 Aint.graph.row_map, Aint.graph.entries, Amat.values,
false,
1537 Bint.graph.row_map, Bint.graph.entries, Bint.values,
false,
1538 int_row_mapC, entriesC, valuesC,
1539 jacobiOmega, Dinv.getLocalViewDevice(Access::ReadOnly));
1542 Kokkos::parallel_for(
1543 Kokkos::RangePolicy<typename device_t::execution_space>(0, int_row_mapC.size()),
1544 KOKKOS_LAMBDA(
int i) { row_mapC(i) = int_row_mapC(i); });
1545 kh.destroy_spgemm_handle();
1548 kh.create_spgemm_handle(alg_enum);
1549 kh.set_team_work_size(team_work_size);
1553 KokkosSparse::spgemm_symbolic(&kh, AnumRows, BnumRows, BnumCols,
1554 Amat.graph.row_map, Amat.graph.entries,
false,
1555 Bmerged.graph.row_map, Bmerged.graph.entries,
false,
1559 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1561 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1562 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1567 KokkosSparse::Experimental::spgemm_jacobi(&kh, AnumRows, BnumRows, BnumCols,
1568 Amat.graph.row_map, Amat.graph.entries, Amat.values,
false,
1569 Bmerged.graph.row_map, Bmerged.graph.entries, Bmerged.values,
false,
1570 row_mapC, entriesC, valuesC,
1571 jacobiOmega, Dinv.getLocalViewDevice(Access::ReadOnly));
1573 kh.destroy_spgemm_handle();
1576 const std::string sortLabel =
"TpetraExt: Jacobi: Newmatrix " + backend_type::algorithm_label() +
"Sort";
1581 if (params.is_null() || params->get(
"sort entries",
true))
1582 Import_Util::sortCrsEntries(row_mapC, entriesC, valuesC);
1583 C.setAllValues(row_mapC, entriesC, valuesC);
1585 const std::string esfcLabel =
"TpetraExt: Jacobi: Newmatrix " + backend_type::algorithm_label() +
"ESFC";
1590 Teuchos::RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
1591 labelList->set(
"Timer Label", label);
1592 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
1593 Teuchos::RCP<const Export<LocalOrdinal, GlobalOrdinal, Node>> dummyExport;
1594 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
1597template <
class Scalar,
1599 class GlobalOrdinal,
1601 class LocalOrdinalViewType>
1602void host_jacobi_A_B_reuse(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
1603 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
1604 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1605 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1606 const LocalOrdinalViewType& targetMapToOrigRow_dev,
1607 const LocalOrdinalViewType& targetMapToImportRow_dev,
1608 const LocalOrdinalViewType& Bcol2Ccol_dev,
1609 const LocalOrdinalViewType& Icol2Ccol_dev,
1610 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1611 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1612 const std::string& label,
1613 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1620 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
1621 typedef typename KCRS::StaticCrsGraphType graph_t;
1622 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
1623 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1624 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1625 typedef typename scalar_view_t::memory_space scalar_memory_space;
1628 typedef LocalOrdinal LO;
1629 typedef GlobalOrdinal GO;
1631 typedef Map<LO, GO, NO> map_type;
1632 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1633 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1634 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
1642 auto targetMapToOrigRow =
1643 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1644 targetMapToOrigRow_dev);
1645 auto targetMapToImportRow =
1646 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1647 targetMapToImportRow_dev);
1649 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1652 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1656 RCP<const map_type> Ccolmap = C.getColMap();
1657 size_t m = Aview.origMatrix->getLocalNumRows();
1658 size_t n = Ccolmap->getLocalNumElements();
1661 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
1662 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
1663 const KCRS Cmat = C.getLocalMatrixHost();
1665 c_lno_view_t Arowptr = Amat.graph.row_map, Browptr = Bmat.graph.row_map, Crowptr = Cmat.graph.row_map;
1666 const lno_nnz_view_t Acolind = Amat.graph.entries, Bcolind = Bmat.graph.entries, Ccolind = Cmat.graph.entries;
1667 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
1668 scalar_view_t Cvals = Cmat.values;
1670 c_lno_view_t Irowptr;
1671 lno_nnz_view_t Icolind;
1672 scalar_view_t Ivals;
1673 if (!Bview.importMatrix.is_null()) {
1674 auto lclB = Bview.importMatrix->getLocalMatrixHost();
1675 Irowptr = lclB.graph.row_map;
1676 Icolind = lclB.graph.entries;
1677 Ivals = lclB.values;
1682 Dinv.template getLocalView<scalar_memory_space>(Access::ReadOnly);
1689 std::vector<size_t> c_status(n, ST_INVALID);
1692 size_t CSR_ip = 0, OLD_ip = 0;
1693 for (
size_t i = 0; i < m; i++) {
1696 OLD_ip = Crowptr[i];
1697 CSR_ip = Crowptr[i + 1];
1698 for (
size_t k = OLD_ip; k < CSR_ip; k++) {
1699 c_status[Ccolind[k]] = k;
1705 SC minusOmegaDval = -omega * Dvals(i, 0);
1708 for (
size_t j = Browptr[i]; j < Browptr[i + 1]; j++) {
1709 Scalar Bval = Bvals[j];
1710 if (Bval == SC_ZERO)
1712 LO Bij = Bcolind[j];
1713 LO Cij = Bcol2Ccol[Bij];
1715 TEUCHOS_TEST_FOR_EXCEPTION(c_status[Cij] < OLD_ip || c_status[Cij] >= CSR_ip,
1716 std::runtime_error,
"Trying to insert a new entry into a static graph");
1718 Cvals[c_status[Cij]] = Bvals[j];
1722 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
1723 LO Aik = Acolind[k];
1724 const SC Aval = Avals[k];
1725 if (Aval == SC_ZERO)
1728 if (targetMapToOrigRow[Aik] != LO_INVALID) {
1730 size_t Bk = Teuchos::as<size_t>(targetMapToOrigRow[Aik]);
1732 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
1733 LO Bkj = Bcolind[j];
1734 LO Cij = Bcol2Ccol[Bkj];
1736 TEUCHOS_TEST_FOR_EXCEPTION(c_status[Cij] < OLD_ip || c_status[Cij] >= CSR_ip,
1737 std::runtime_error,
"Trying to insert a new entry into a static graph");
1739 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Bvals[j];
1744 size_t Ik = Teuchos::as<size_t>(targetMapToImportRow[Aik]);
1745 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
1746 LO Ikj = Icolind[j];
1747 LO Cij = Icol2Ccol[Ikj];
1749 TEUCHOS_TEST_FOR_EXCEPTION(c_status[Cij] < OLD_ip || c_status[Cij] >= CSR_ip,
1750 std::runtime_error,
"Trying to insert a new entry into a static graph");
1752 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Ivals[j];
1761 C.fillComplete(C.getDomainMap(), C.getRangeMap());
1814template <
class Scalar,
1816 class GlobalOrdinal,
1818void mult_AT_B_newmatrix(
1819 const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
1820 const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& B,
1821 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1822 const std::string& label,
1823 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1827 typedef LocalOrdinal LO;
1828 typedef GlobalOrdinal GO;
1830 typedef CrsMatrixStruct<SC, LO, GO, NO> crs_matrix_struct_type;
1831 typedef RowMatrixTransposer<SC, LO, GO, NO> transposer_type;
1838 transposer_type transposer(rcpFromRef(A), label + std::string(
"XP: "));
1840 using Teuchos::ParameterList;
1841 RCP<ParameterList> transposeParams(
new ParameterList);
1842 transposeParams->set(
"sort",
true);
1843 if (!params.is_null()) {
1844 transposeParams->set(
"compute global constants",
1845 params->get(
"compute global constants: temporaries",
1848 RCP<Tpetra::CrsMatrix<SC, LO, GO, NO>> Atrans =
1849 transposer.createTransposeLocal(transposeParams);
1858 crs_matrix_struct_type Aview;
1859 crs_matrix_struct_type Bview;
1860 RCP<const Import<LO, GO, NO>> dummyImporter;
1863 RCP<Teuchos::ParameterList> importParams = Teuchos::rcp(
new ParameterList);
1864 importParams->set(
"compute global constants",
false);
1865 if (!params.is_null()) {
1866 importParams->setParameters(*params);
1867 if (params->isParameter(
"compute global constants: temporaries"))
1868 importParams->set(
"compute global constants",
1869 params->get<
bool>(
"compute global constants: temporaries"));
1871 MMdetails::import_and_extract_views(*Atrans, Atrans->getRowMap(),
1872 Aview, dummyImporter,
true,
1873 label, importParams);
1875 if (B.getRowMap()->isSameAs(*Atrans->getColMap())) {
1876 MMdetails::import_and_extract_views(B, B.getRowMap(), Bview, dummyImporter,
true, label, importParams);
1878 MMdetails::import_and_extract_views(B, Atrans->getColMap(), Bview, dummyImporter,
false, label, importParams);
1884 RCP<Tpetra::CrsMatrix<SC, LO, GO, NO>> Ctemp;
1887 bool needs_final_export = !Atrans->getGraph()->getExporter().is_null();
1888 if (needs_final_export) {
1891 Ctemp = rcp(&C,
false);
1894 RCP<Teuchos::ParameterList> multParams = Teuchos::rcp(
new ParameterList);
1895 if (!params.is_null()) {
1896 multParams->setParameters(*params);
1898 multParams->set(
"compute global constants", !needs_final_export);
1899 mult_A_B_newmatrix(Aview, Bview, *Ctemp, label, multParams);
1907 RCP<Tpetra::CrsMatrix<SC, LO, GO, NO>> Crcp(&C,
false);
1909 if (needs_final_export) {
1910 ParameterList labelList;
1911 labelList.set(
"Timer Label", label);
1912 if (!params.is_null()) {
1913 labelList.setParameters(*params);
1915 ParameterList& labelList_subList = labelList.sublist(
"matrixmatrix: kernel params",
false);
1916 labelList_subList.set(
"isMatrixMatrix_TransferAndFillComplete",
true,
1917 "This parameter should be set to true only for MatrixMatrix operations: the optimization in Epetra that was ported to Tpetra does _not_ take into account the possibility that for any given source PID, a particular GID may not exist on the target PID: i.e. a transfer operation. A fix for this general case is in development.");
1919 Ctemp->exportAndFillComplete(Crcp,
1920 *Ctemp->getGraph()->getExporter(),
1923 rcp(&labelList,
false));
1925#ifdef HAVE_TPETRA_MMM_STATISTICS
1926 printMultiplicationStatistics(Ctemp->getGraph()->getExporter(), label + std::string(
" AT_B MMM"));
1932template <
class Scalar,
1934 class GlobalOrdinal,
1937 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1938 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1939 CrsWrapper<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1940 const std::string& ,
1941 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1942 using Teuchos::Array;
1943 using Teuchos::ArrayRCP;
1944 using Teuchos::ArrayView;
1945 using Teuchos::null;
1946 using Teuchos::OrdinalTraits;
1948 bool skipExplicitZero =
true;
1949 if (params && params->isParameter(
"MM Skip Explicit Zeros")) {
1950 skipExplicitZero = params->get<
bool>(
"MM Skip Explicit Zeros");
1953 typedef Teuchos::ScalarTraits<Scalar> STS;
1955 LocalOrdinal C_firstCol = Bview.
colMap->getMinLocalIndex();
1956 LocalOrdinal C_lastCol = Bview.colMap->getMaxLocalIndex();
1958 LocalOrdinal C_firstCol_import = OrdinalTraits<LocalOrdinal>::zero();
1959 LocalOrdinal C_lastCol_import = OrdinalTraits<LocalOrdinal>::invalid();
1961 ArrayView<const GlobalOrdinal> bcols = Bview.colMap->getLocalElementList();
1962 ArrayView<const GlobalOrdinal> bcols_import = null;
1963 if (Bview.importColMap != null) {
1964 C_firstCol_import = Bview.importColMap->getMinLocalIndex();
1965 C_lastCol_import = Bview.importColMap->getMaxLocalIndex();
1967 bcols_import = Bview.importColMap->getLocalElementList();
1970 size_t C_numCols = C_lastCol - C_firstCol +
1971 OrdinalTraits<LocalOrdinal>::one();
1972 size_t C_numCols_import = C_lastCol_import - C_firstCol_import +
1973 OrdinalTraits<LocalOrdinal>::one();
1975 if (C_numCols_import > C_numCols)
1976 C_numCols = C_numCols_import;
1978 Array<Scalar> dwork = Array<Scalar>(C_numCols);
1979 Array<GlobalOrdinal> iwork = Array<GlobalOrdinal>(C_numCols);
1980 Array<size_t> iwork2 = Array<size_t>(C_numCols);
1982 Array<Scalar> C_row_i = dwork;
1983 Array<GlobalOrdinal> C_cols = iwork;
1984 Array<size_t> c_index = iwork2;
1985 Array<GlobalOrdinal> combined_index = Array<GlobalOrdinal>(2 * C_numCols);
1986 Array<Scalar> combined_values = Array<Scalar>(2 * C_numCols);
1988 size_t C_row_i_length, j, k, last_index;
1991 LocalOrdinal LO_INVALID = OrdinalTraits<LocalOrdinal>::invalid();
1992 Array<LocalOrdinal> Acol2Brow(Aview.colMap->getLocalNumElements(), LO_INVALID);
1993 Array<LocalOrdinal> Acol2Irow(Aview.colMap->getLocalNumElements(), LO_INVALID);
1994 if (Aview.colMap->isSameAs(*Bview.origMatrix->getRowMap())) {
1996 for (LocalOrdinal i = Aview.colMap->getMinLocalIndex(); i <=
1997 Aview.colMap->getMaxLocalIndex();
2002 for (LocalOrdinal i = Aview.colMap->getMinLocalIndex(); i <=
2003 Aview.colMap->getMaxLocalIndex();
2005 GlobalOrdinal GID = Aview.colMap->getGlobalElement(i);
2006 LocalOrdinal BLID = Bview.origMatrix->getRowMap()->getLocalElement(GID);
2007 if (BLID != LO_INVALID)
2008 Acol2Brow[i] = BLID;
2010 Acol2Irow[i] = Bview.importMatrix->getRowMap()->getLocalElement(GID);
2020 auto Arowptr = Aview.origMatrix->getLocalRowPtrsHost();
2021 auto Acolind = Aview.origMatrix->getLocalIndicesHost();
2022 auto Avals = Aview.origMatrix->getLocalValuesHost(Tpetra::Access::ReadOnly);
2023 auto Browptr = Bview.origMatrix->getLocalRowPtrsHost();
2024 auto Bcolind = Bview.origMatrix->getLocalIndicesHost();
2025 auto Bvals = Bview.origMatrix->getLocalValuesHost(Tpetra::Access::ReadOnly);
2026 decltype(Browptr) Irowptr;
2027 decltype(Bcolind) Icolind;
2028 decltype(Bvals) Ivals;
2029 if (!Bview.importMatrix.is_null()) {
2030 Irowptr = Bview.importMatrix->getLocalRowPtrsHost();
2031 Icolind = Bview.importMatrix->getLocalIndicesHost();
2032 Ivals = Bview.importMatrix->getLocalValuesHost(Tpetra::Access::ReadOnly);
2035 bool C_filled = C.isFillComplete();
2037 for (
size_t i = 0; i < C_numCols; i++)
2038 c_index[i] = OrdinalTraits<size_t>::invalid();
2041 size_t Arows = Aview.rowMap->getLocalNumElements();
2042 for (
size_t i = 0; i < Arows; ++i) {
2045 GlobalOrdinal global_row = Aview.rowMap->getGlobalElement(i);
2051 C_row_i_length = OrdinalTraits<size_t>::zero();
2053 for (k = Arowptr[i]; k < Arowptr[i + 1]; ++k) {
2054 LocalOrdinal Ak = Acol2Brow[Acolind[k]];
2055 const Scalar Aval = Avals[k];
2056 if (Aval == STS::zero() && skipExplicitZero)
2059 if (Ak == LO_INVALID)
2062 for (j = Browptr[Ak]; j < Browptr[Ak + 1]; ++j) {
2063 LocalOrdinal col = Bcolind[j];
2066 if (c_index[col] == OrdinalTraits<size_t>::invalid()) {
2069 C_row_i[C_row_i_length] = Aval * Bvals[j];
2070 C_cols[C_row_i_length] = col;
2071 c_index[col] = C_row_i_length;
2076 C_row_i[c_index[col]] += Aval *
static_cast<Scalar
>(Bvals[j]);
2081 for (
size_t ii = 0; ii < C_row_i_length; ii++) {
2082 c_index[C_cols[ii]] = OrdinalTraits<size_t>::invalid();
2083 C_cols[ii] = bcols[C_cols[ii]];
2084 combined_index[ii] = C_cols[ii];
2085 combined_values[ii] = C_row_i[ii];
2087 last_index = C_row_i_length;
2093 C_row_i_length = OrdinalTraits<size_t>::zero();
2095 for (k = Arowptr[i]; k < Arowptr[i + 1]; ++k) {
2096 LocalOrdinal Ak = Acol2Brow[Acolind[k]];
2097 const Scalar Aval = Avals[k];
2098 if (Aval == STS::zero() && skipExplicitZero)
2101 if (Ak != LO_INVALID)
continue;
2103 Ak = Acol2Irow[Acolind[k]];
2104 for (j = Irowptr[Ak]; j < Irowptr[Ak + 1]; ++j) {
2105 LocalOrdinal col = Icolind[j];
2108 if (c_index[col] == OrdinalTraits<size_t>::invalid()) {
2111 C_row_i[C_row_i_length] = Aval * Ivals[j];
2112 C_cols[C_row_i_length] = col;
2113 c_index[col] = C_row_i_length;
2119 C_row_i[c_index[col]] += Aval *
static_cast<Scalar
>(Ivals[j]);
2124 for (
size_t ii = 0; ii < C_row_i_length; ii++) {
2125 c_index[C_cols[ii]] = OrdinalTraits<size_t>::invalid();
2126 C_cols[ii] = bcols_import[C_cols[ii]];
2127 combined_index[last_index] = C_cols[ii];
2128 combined_values[last_index] = C_row_i[ii];
2134 C_filled ? C.sumIntoGlobalValues(
2136 combined_index.view(OrdinalTraits<size_t>::zero(), last_index),
2137 combined_values.view(OrdinalTraits<size_t>::zero(), last_index))
2138 : C.insertGlobalValues(
2140 combined_index.view(OrdinalTraits<size_t>::zero(), last_index),
2141 combined_values.view(OrdinalTraits<size_t>::zero(), last_index));
2146template <
class Scalar,
2148 class GlobalOrdinal,
2150void setMaxNumEntriesPerRow(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Mview) {
2151 typedef typename Teuchos::Array<Teuchos::ArrayView<const LocalOrdinal>>::size_type local_length_size;
2152 Mview.maxNumRowEntries = Teuchos::OrdinalTraits<local_length_size>::zero();
2154 if (Mview.indices.size() > Teuchos::OrdinalTraits<local_length_size>::zero()) {
2155 Mview.maxNumRowEntries = Mview.indices[0].size();
2157 for (local_length_size i = 1; i < Mview.indices.size(); ++i)
2158 if (Mview.indices[i].size() > Mview.maxNumRowEntries)
2159 Mview.maxNumRowEntries = Mview.indices[i].size();
2164template <
class CrsMatrixType>
2165size_t C_estimate_nnz(CrsMatrixType& A, CrsMatrixType& B) {
2167 size_t Aest = 100, Best = 100;
2168 if (A.getLocalNumEntries() >= A.getLocalNumRows())
2169 Aest = (A.getLocalNumRows() > 0) ? A.getLocalNumEntries() / A.getLocalNumRows() : 100;
2170 if (B.getLocalNumEntries() >= B.getLocalNumRows())
2171 Best = (B.getLocalNumRows() > 0) ? B.getLocalNumEntries() / B.getLocalNumRows() : 100;
2173 size_t nnzperrow = (size_t)(sqrt((
double)Aest) + sqrt((
double)Best) - 1);
2174 nnzperrow *= nnzperrow;
2176 return (
size_t)(A.getLocalNumRows() * nnzperrow * 0.75 + 100);
2185template <
class Scalar,
2187 class GlobalOrdinal,
2189void mult_A_B_newmatrix(
2190 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2191 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2192 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2193 const std::string& label,
2194 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2195 using Teuchos::Array;
2196 using Teuchos::ArrayRCP;
2197 using Teuchos::ArrayView;
2202 typedef LocalOrdinal LO;
2203 typedef GlobalOrdinal GO;
2205 typedef Import<LO, GO, NO> import_type;
2206 typedef Map<LO, GO, NO> map_type;
2209 typedef typename map_type::local_map_type local_map_type;
2211 typedef typename KCRS::StaticCrsGraphType graph_t;
2212 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2213 typedef typename NO::execution_space execution_space;
2214 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2215 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2219 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2222 RCP<const import_type> Cimport;
2223 RCP<const map_type> Ccolmap;
2224 RCP<const import_type> Bimport = Bview.origMatrix->getGraph()->getImporter();
2225 RCP<const import_type> Iimport = Bview.importMatrix.is_null() ? Teuchos::null : Bview.importMatrix->getGraph()->getImporter();
2226 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2227 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2228 local_map_type Irowmap_local;
2229 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2230 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2231 local_map_type Icolmap_local;
2232 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2239 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2241 if (Bview.importMatrix.is_null()) {
2244 Ccolmap = Bview.colMap;
2245 const LO colMapSize =
static_cast<LO
>(Bview.colMap->getLocalNumElements());
2247 Kokkos::parallel_for(
2248 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_fill",
2249 Kokkos::RangePolicy<execution_space, LO>(0, colMapSize),
2250 KOKKOS_LAMBDA(
const LO i) {
2262 if (!Bimport.is_null() && !Iimport.is_null()) {
2263 Cimport = Bimport->setUnion(*Iimport, params);
2264 }
else if (!Bimport.is_null() && Iimport.is_null()) {
2265 Cimport = Bimport->setUnion(params);
2266 }
else if (Bimport.is_null() && !Iimport.is_null()) {
2267 Cimport = Iimport->setUnion(params);
2269 throw std::runtime_error(
"TpetraExt::MMM status of matrix importers is nonsensical");
2271 Ccolmap = Cimport->getTargetMap();
2276 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
2277 std::runtime_error,
"Tpetra::MMM: Import setUnion messed with the DomainMap in an unfortunate way");
2284 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2285 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2286 Kokkos::parallel_for(
2287 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_getGlobalElement", range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2288 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2290 Kokkos::parallel_for(
2291 "Tpetra::mult_A_B_newmatrix::Icol2Ccol_getGlobalElement", range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2292 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2300 C.replaceColMap(Ccolmap);
2318 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
2319 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
2321 Kokkos::parallel_for(
2322 "Tpetra::mult_A_B_newmatrix::construct_tables", range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
2323 GO aidx = Acolmap_local.getGlobalElement(i);
2324 LO B_LID = Browmap_local.getLocalElement(aidx);
2325 if (B_LID != LO_INVALID) {
2326 targetMapToOrigRow(i) = B_LID;
2327 targetMapToImportRow(i) = LO_INVALID;
2329 LO I_LID = Irowmap_local.getLocalElement(aidx);
2330 targetMapToOrigRow(i) = LO_INVALID;
2331 targetMapToImportRow(i) = I_LID;
2337 KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::mult_A_B_newmatrix_kernel_wrapper(Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
2342template <
class Scalar,
2344 class GlobalOrdinal,
2346void mult_A_B_newmatrix(BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2347 BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2348 Teuchos::RCP<BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& C) {
2349 using Teuchos::Array;
2350 using Teuchos::ArrayRCP;
2351 using Teuchos::ArrayView;
2352 using Teuchos::null;
2357 typedef LocalOrdinal LO;
2358 typedef GlobalOrdinal GO;
2360 typedef Import<LO, GO, NO> import_type;
2361 typedef Map<LO, GO, NO> map_type;
2362 typedef BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> block_crs_matrix_type;
2363 typedef typename block_crs_matrix_type::crs_graph_type graph_t;
2366 typedef typename map_type::local_map_type local_map_type;
2367 typedef typename block_crs_matrix_type::local_matrix_device_type KBSR;
2368 typedef typename KBSR::device_type device_t;
2369 typedef typename KBSR::StaticCrsGraphType static_graph_t;
2370 typedef typename static_graph_t::row_map_type::non_const_type lno_view_t;
2371 typedef typename static_graph_t::entries_type::non_const_type lno_nnz_view_t;
2372 typedef typename KBSR::values_type::non_const_type scalar_view_t;
2373 typedef typename NO::execution_space execution_space;
2374 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2375 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2377 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2380 RCP<const import_type> Cimport;
2381 RCP<const map_type> Ccolmap;
2382 RCP<const import_type> Bimport = Bview.origMatrix->getGraph()->getImporter();
2383 RCP<const import_type> Iimport = Bview.importMatrix.is_null() ? Teuchos::null : Bview.importMatrix->getGraph()->getImporter();
2384 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2385 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2386 local_map_type Irowmap_local;
2387 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2388 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2389 local_map_type Icolmap_local;
2390 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2397 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2399 if (Bview.importMatrix.is_null()) {
2402 Ccolmap = Bview.colMap;
2403 const LO colMapSize =
static_cast<LO
>(Bview.colMap->getLocalNumElements());
2405 Kokkos::parallel_for(
2406 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_fill",
2407 Kokkos::RangePolicy<execution_space, LO>(0, colMapSize),
2408 KOKKOS_LAMBDA(
const LO i) {
2420 if (!Bimport.is_null() && !Iimport.is_null()) {
2421 Cimport = Bimport->setUnion(*Iimport);
2422 }
else if (!Bimport.is_null() && Iimport.is_null()) {
2423 Cimport = Bimport->setUnion();
2424 }
else if (Bimport.is_null() && !Iimport.is_null()) {
2425 Cimport = Iimport->setUnion();
2427 throw std::runtime_error(
"TpetraExt::MMM status of matrix importers is nonsensical");
2429 Ccolmap = Cimport->getTargetMap();
2436 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2437 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2438 Kokkos::parallel_for(
2439 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_getGlobalElement",
2440 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()),
2441 KOKKOS_LAMBDA(
const LO i) {
2442 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2444 Kokkos::parallel_for(
2445 "Tpetra::mult_A_B_newmatrix::Icol2Ccol_getGlobalElement",
2446 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()),
2447 KOKKOS_LAMBDA(
const LO i) {
2448 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2468 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"),
2469 Aview.colMap->getLocalNumElements());
2470 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"),
2471 Aview.colMap->getLocalNumElements());
2473 Kokkos::parallel_for(
2474 "Tpetra::mult_A_B_newmatrix::construct_tables",
2475 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1),
2476 KOKKOS_LAMBDA(
const LO i) {
2477 GO aidx = Acolmap_local.getGlobalElement(i);
2478 LO B_LID = Browmap_local.getLocalElement(aidx);
2479 if (B_LID != LO_INVALID) {
2480 targetMapToOrigRow(i) = B_LID;
2481 targetMapToImportRow(i) = LO_INVALID;
2483 LO I_LID = Irowmap_local.getLocalElement(aidx);
2484 targetMapToOrigRow(i) = LO_INVALID;
2485 targetMapToImportRow(i) = I_LID;
2490 using KernelHandle =
2491 KokkosKernels::Experimental::KokkosKernelsHandle<
typename lno_view_t::const_value_type,
2492 typename lno_nnz_view_t::const_value_type,
2493 typename scalar_view_t::const_value_type,
2494 typename device_t::execution_space,
2495 typename device_t::memory_space,
2496 typename device_t::memory_space>;
2497 int team_work_size = 16;
2498 std::string myalg(
"SPGEMM_DEFAULT");
2499 KokkosSparse::SPGEMMAlgorithm alg_enum = KokkosSparse::StringToSPGEMMAlgorithm(myalg);
2502 kh.create_spgemm_handle(alg_enum);
2503 kh.set_team_work_size(team_work_size);
2506 const KBSR Amat = Aview.origMatrix->getLocalMatrixDevice();
2507 const KBSR Bmerged = Tpetra::MMdetails::merge_matrices(Aview, Bview,
2508 targetMapToOrigRow, targetMapToImportRow,
2509 Bcol2Ccol, Icol2Ccol,
2510 Ccolmap.getConst()->getLocalNumElements());
2512 RCP<graph_t> graphC;
2513 typename KBSR::values_type values;
2518 KokkosSparse::block_spgemm_symbolic(kh, Amat,
false, Bmerged,
false, Cmat);
2519 KokkosSparse::block_spgemm_numeric(kh, Amat,
false, Bmerged,
false, Cmat);
2520 kh.destroy_spgemm_handle();
2523 graphC = rcp(
new graph_t(Cmat.graph, Aview.origMatrix->getRowMap(), Ccolmap.getConst()));
2524 values = Cmat.values;
2526 C = rcp(
new block_crs_matrix_type(*graphC, values, Aview.blocksize));
2531template <
class Scalar,
2533 class GlobalOrdinal,
2535 class LocalOrdinalViewType>
2536void KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_A_B_newmatrix_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2537 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2538 const LocalOrdinalViewType& targetMapToOrigRow,
2539 const LocalOrdinalViewType& targetMapToImportRow,
2540 const LocalOrdinalViewType& Bcol2Ccol,
2541 const LocalOrdinalViewType& Icol2Ccol,
2542 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2543 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
2544 const std::string& label,
2545 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2546 using Teuchos::Array;
2547 using Teuchos::ArrayRCP;
2548 using Teuchos::ArrayView;
2555 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
2556 typedef typename KCRS::StaticCrsGraphType graph_t;
2557 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
2558 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2559 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
2560 typedef typename KCRS::values_type::non_const_type scalar_view_t;
2563 typedef LocalOrdinal LO;
2564 typedef GlobalOrdinal GO;
2566 typedef Map<LO, GO, NO> map_type;
2567 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2568 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2569 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
2571 bool skipExplicitZero =
true;
2572 if (params && params->isParameter(
"MM Skip Explicit Zeros")) {
2573 skipExplicitZero = params->get<
bool>(
"MM Skip Explicit Zeros");
2577 RCP<const map_type> Ccolmap = C.getColMap();
2578 size_t m = Aview.origMatrix->getLocalNumRows();
2579 size_t n = Ccolmap->getLocalNumElements();
2580 size_t b_max_nnz_per_row = Bview.origMatrix->getLocalMaxNumRowEntries();
2583 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
2584 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
2586 c_lno_view_t Arowptr = Amat.graph.row_map, Browptr = Bmat.graph.row_map;
2587 const lno_nnz_view_t Acolind = Amat.graph.entries, Bcolind = Bmat.graph.entries;
2588 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
2590 c_lno_view_t Irowptr;
2591 lno_nnz_view_t Icolind;
2592 scalar_view_t Ivals;
2593 if (!Bview.importMatrix.is_null()) {
2594 auto lclB = Bview.importMatrix->getLocalMatrixHost();
2595 Irowptr = lclB.graph.row_map;
2596 Icolind = lclB.graph.entries;
2597 Ivals = lclB.values;
2598 b_max_nnz_per_row = std::max(b_max_nnz_per_row, Bview.importMatrix->getLocalMaxNumRowEntries());
2608 size_t CSR_alloc = std::max(C_estimate_nnz(*Aview.origMatrix, *Bview.origMatrix), n);
2609 lno_view_t Crowptr(Kokkos::ViewAllocateWithoutInitializing(
"Crowptr"), m + 1);
2610 lno_nnz_view_t Ccolind(Kokkos::ViewAllocateWithoutInitializing(
"Ccolind"), CSR_alloc);
2611 scalar_view_t Cvals(Kokkos::ViewAllocateWithoutInitializing(
"Cvals"), CSR_alloc);
2621 size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
2622 std::vector<size_t> c_status(n, ST_INVALID);
2632 size_t CSR_ip = 0, OLD_ip = 0;
2633 for (
size_t i = 0; i < m; i++) {
2636 Crowptr[i] = CSR_ip;
2639 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
2640 LO Aik = Acolind[k];
2641 const SC Aval = Avals[k];
2642 if (Aval == SC_ZERO && skipExplicitZero)
2645 if (targetMapToOrigRow[Aik] != LO_INVALID) {
2652 size_t Bk =
static_cast<size_t>(targetMapToOrigRow[Aik]);
2655 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
2656 LO Bkj = Bcolind[j];
2657 LO Cij = Bcol2Ccol[Bkj];
2659 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
2661 c_status[Cij] = CSR_ip;
2662 Ccolind[CSR_ip] = Cij;
2663 Cvals[CSR_ip] = Aval * Bvals[j];
2667 Cvals[c_status[Cij]] += Aval * Bvals[j];
2678 size_t Ik =
static_cast<size_t>(targetMapToImportRow[Aik]);
2679 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
2680 LO Ikj = Icolind[j];
2681 LO Cij = Icol2Ccol[Ikj];
2683 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
2685 c_status[Cij] = CSR_ip;
2686 Ccolind[CSR_ip] = Cij;
2687 Cvals[CSR_ip] = Aval * Ivals[j];
2690 Cvals[c_status[Cij]] += Aval * Ivals[j];
2697 if (i + 1 < m && CSR_ip + std::min(n, (Arowptr[i + 2] - Arowptr[i + 1]) * b_max_nnz_per_row) > CSR_alloc) {
2699 Kokkos::resize(Ccolind, CSR_alloc);
2700 Kokkos::resize(Cvals, CSR_alloc);
2705 Crowptr[m] = CSR_ip;
2708 Kokkos::resize(Ccolind, CSR_ip);
2709 Kokkos::resize(Cvals, CSR_ip);
2715 if (params.is_null() || params->get(
"sort entries",
true)) {
2717 Import_Util::sortCrsEntries(Crowptr, Ccolind, Cvals);
2719 C.setAllValues(Crowptr, Ccolind, Cvals);
2732 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
2733 labelList->set(
"Timer Label", label);
2734 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
2735 RCP<const Export<LO, GO, NO>> dummyExport;
2736 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
2741template <
class Scalar,
2743 class GlobalOrdinal,
2746 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2747 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2748 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2749 const std::string& label,
2750 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2751 using Teuchos::Array;
2752 using Teuchos::ArrayRCP;
2753 using Teuchos::ArrayView;
2758 typedef LocalOrdinal LO;
2759 typedef GlobalOrdinal GO;
2761 typedef Import<LO, GO, NO> import_type;
2762 typedef Map<LO, GO, NO> map_type;
2765 typedef typename map_type::local_map_type local_map_type;
2767 typedef typename KCRS::StaticCrsGraphType graph_t;
2768 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2769 typedef typename NO::execution_space execution_space;
2770 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2771 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2776 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2779 RCP<const import_type> Cimport = C.getGraph()->getImporter();
2780 RCP<const map_type> Ccolmap = C.getColMap();
2781 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2782 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2783 local_map_type Irowmap_local;
2784 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2785 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2786 local_map_type Icolmap_local;
2787 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2788 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2791 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2795 Kokkos::parallel_for(
2796 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2797 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2800 if (!Bview.importMatrix.is_null()) {
2801 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
2802 std::runtime_error,
"Tpetra::MMM: Import setUnion messed with the DomainMap in an unfortunate way");
2804 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2805 Kokkos::parallel_for(
2806 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2807 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2813 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
2814 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
2815 Kokkos::parallel_for(
2816 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
2817 GO aidx = Acolmap_local.getGlobalElement(i);
2818 LO B_LID = Browmap_local.getLocalElement(aidx);
2819 if (B_LID != LO_INVALID) {
2820 targetMapToOrigRow(i) = B_LID;
2821 targetMapToImportRow(i) = LO_INVALID;
2823 LO I_LID = Irowmap_local.getLocalElement(aidx);
2824 targetMapToOrigRow(i) = LO_INVALID;
2825 targetMapToImportRow(i) = I_LID;
2831 KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::mult_A_B_reuse_kernel_wrapper(Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
2835template <
class Scalar,
2837 class GlobalOrdinal,
2839 class LocalOrdinalViewType>
2840void KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_A_B_reuse_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2841 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2842 const LocalOrdinalViewType& targetMapToOrigRow,
2843 const LocalOrdinalViewType& targetMapToImportRow,
2844 const LocalOrdinalViewType& Bcol2Ccol,
2845 const LocalOrdinalViewType& Icol2Ccol,
2846 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2847 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
2848 const std::string& label,
2849 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2850 Tpetra::MMdetails::host_mult_A_B_reuse(
2851 Aview, Bview, targetMapToOrigRow, targetMapToImportRow,
2852 Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
2857template <
class Scalar,
2859 class GlobalOrdinal,
2861void jacobi_A_B_newmatrix(
2862 typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
2863 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
2864 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2865 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2866 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2867 const std::string& label,
2868 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2869 using Teuchos::Array;
2870 using Teuchos::ArrayRCP;
2871 using Teuchos::ArrayView;
2875 typedef LocalOrdinal LO;
2876 typedef GlobalOrdinal GO;
2879 typedef Import<LO, GO, NO> import_type;
2880 typedef Map<LO, GO, NO> map_type;
2881 typedef typename map_type::local_map_type local_map_type;
2885 typedef typename KCRS::StaticCrsGraphType graph_t;
2886 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2887 typedef typename NO::execution_space execution_space;
2888 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2889 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2893 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2896 RCP<const import_type> Cimport;
2897 RCP<const map_type> Ccolmap;
2898 RCP<const import_type> Bimport = Bview.origMatrix->getGraph()->getImporter();
2899 RCP<const import_type> Iimport = Bview.importMatrix.is_null() ? Teuchos::null : Bview.importMatrix->getGraph()->getImporter();
2900 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2901 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2902 local_map_type Irowmap_local;
2903 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2904 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2905 local_map_type Icolmap_local;
2906 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2913 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2915 if (Bview.importMatrix.is_null()) {
2918 Ccolmap = Bview.colMap;
2922 Kokkos::RangePolicy<execution_space, LO> range(0,
static_cast<LO
>(Bview.colMap->getLocalNumElements()));
2923 Kokkos::parallel_for(
2924 range, KOKKOS_LAMBDA(
const size_t i) {
2925 Bcol2Ccol(i) =
static_cast<LO
>(i);
2936 if (!Bimport.is_null() && !Iimport.is_null()) {
2937 Cimport = Bimport->setUnion(*Iimport, params);
2938 Ccolmap = Cimport->getTargetMap();
2940 }
else if (!Bimport.is_null() && Iimport.is_null()) {
2941 Cimport = Bimport->setUnion(params);
2943 }
else if (Bimport.is_null() && !Iimport.is_null()) {
2944 Cimport = Iimport->setUnion(params);
2947 throw std::runtime_error(
"TpetraExt::Jacobi status of matrix importers is nonsensical");
2949 Ccolmap = Cimport->getTargetMap();
2951 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
2952 std::runtime_error,
"Tpetra:Jacobi Import setUnion messed with the DomainMap in an unfortunate way");
2959 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2960 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2961 Kokkos::parallel_for(
2962 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2963 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2965 Kokkos::parallel_for(
2966 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2967 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2975 C.replaceColMap(Ccolmap);
2993 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
2994 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
2995 Kokkos::parallel_for(
2996 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
2997 GO aidx = Acolmap_local.getGlobalElement(i);
2998 LO B_LID = Browmap_local.getLocalElement(aidx);
2999 if (B_LID != LO_INVALID) {
3000 targetMapToOrigRow(i) = B_LID;
3001 targetMapToImportRow(i) = LO_INVALID;
3003 LO I_LID = Irowmap_local.getLocalElement(aidx);
3004 targetMapToOrigRow(i) = LO_INVALID;
3005 targetMapToImportRow(i) = I_LID;
3011 KernelWrappers2<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::jacobi_A_B_newmatrix_kernel_wrapper(omega, Dinv, Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
3018template <
class Scalar,
3020 class GlobalOrdinal,
3022 class LocalOrdinalViewType>
3023void KernelWrappers2<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::jacobi_A_B_newmatrix_kernel_wrapper(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
3024 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
3025 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3026 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3027 const LocalOrdinalViewType& targetMapToOrigRow,
3028 const LocalOrdinalViewType& targetMapToImportRow,
3029 const LocalOrdinalViewType& Bcol2Ccol,
3030 const LocalOrdinalViewType& Icol2Ccol,
3031 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
3032 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
3033 const std::string& label,
3034 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3037 using Teuchos::Array;
3038 using Teuchos::ArrayRCP;
3039 using Teuchos::ArrayView;
3044 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
3045 typedef typename KCRS::StaticCrsGraphType graph_t;
3046 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
3047 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3048 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
3049 typedef typename KCRS::values_type::non_const_type scalar_view_t;
3052 typedef typename scalar_view_t::memory_space scalar_memory_space;
3055 typedef LocalOrdinal LO;
3056 typedef GlobalOrdinal GO;
3059 typedef Map<LO, GO, NO> map_type;
3060 size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3061 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3064 RCP<const map_type> Ccolmap = C.getColMap();
3065 size_t m = Aview.origMatrix->getLocalNumRows();
3066 size_t n = Ccolmap->getLocalNumElements();
3067 size_t b_max_nnz_per_row = Bview.origMatrix->getLocalMaxNumRowEntries();
3070 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
3071 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
3073 c_lno_view_t Arowptr = Amat.graph.row_map, Browptr = Bmat.graph.row_map;
3074 const lno_nnz_view_t Acolind = Amat.graph.entries, Bcolind = Bmat.graph.entries;
3075 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
3077 c_lno_view_t Irowptr;
3078 lno_nnz_view_t Icolind;
3079 scalar_view_t Ivals;
3080 if (!Bview.importMatrix.is_null()) {
3081 auto lclB = Bview.importMatrix->getLocalMatrixHost();
3082 Irowptr = lclB.graph.row_map;
3083 Icolind = lclB.graph.entries;
3084 Ivals = lclB.values;
3085 b_max_nnz_per_row = std::max(b_max_nnz_per_row, Bview.importMatrix->getLocalMaxNumRowEntries());
3090 Dinv.template getLocalView<scalar_memory_space>(Access::ReadOnly);
3098 size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
3099 Array<size_t> c_status(n, ST_INVALID);
3108 size_t CSR_alloc = std::max(C_estimate_nnz(*Aview.origMatrix, *Bview.origMatrix), n);
3109 lno_view_t Crowptr(Kokkos::ViewAllocateWithoutInitializing(
"Crowptr"), m + 1);
3110 lno_nnz_view_t Ccolind(Kokkos::ViewAllocateWithoutInitializing(
"Ccolind"), CSR_alloc);
3111 scalar_view_t Cvals(Kokkos::ViewAllocateWithoutInitializing(
"Cvals"), CSR_alloc);
3112 size_t CSR_ip = 0, OLD_ip = 0;
3114 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
3128 for (
size_t i = 0; i < m; i++) {
3131 Crowptr[i] = CSR_ip;
3132 SC minusOmegaDval = -omega * Dvals(i, 0);
3135 for (
size_t j = Browptr[i]; j < Browptr[i + 1]; j++) {
3136 Scalar Bval = Bvals[j];
3137 if (Bval == SC_ZERO)
3139 LO Bij = Bcolind[j];
3140 LO Cij = Bcol2Ccol[Bij];
3143 c_status[Cij] = CSR_ip;
3144 Ccolind[CSR_ip] = Cij;
3145 Cvals[CSR_ip] = Bvals[j];
3150 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
3151 LO Aik = Acolind[k];
3152 const SC Aval = Avals[k];
3153 if (Aval == SC_ZERO)
3156 if (targetMapToOrigRow[Aik] != LO_INVALID) {
3158 size_t Bk =
static_cast<size_t>(targetMapToOrigRow[Aik]);
3160 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
3161 LO Bkj = Bcolind[j];
3162 LO Cij = Bcol2Ccol[Bkj];
3164 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
3166 c_status[Cij] = CSR_ip;
3167 Ccolind[CSR_ip] = Cij;
3168 Cvals[CSR_ip] = minusOmegaDval * Aval * Bvals[j];
3172 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Bvals[j];
3178 size_t Ik =
static_cast<size_t>(targetMapToImportRow[Aik]);
3179 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
3180 LO Ikj = Icolind[j];
3181 LO Cij = Icol2Ccol[Ikj];
3183 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
3185 c_status[Cij] = CSR_ip;
3186 Ccolind[CSR_ip] = Cij;
3187 Cvals[CSR_ip] = minusOmegaDval * Aval * Ivals[j];
3190 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Ivals[j];
3197 if (i + 1 < m && CSR_ip + std::min(n, (Arowptr[i + 2] - Arowptr[i + 1] + 1) * b_max_nnz_per_row) > CSR_alloc) {
3199 Kokkos::resize(Ccolind, CSR_alloc);
3200 Kokkos::resize(Cvals, CSR_alloc);
3204 Crowptr[m] = CSR_ip;
3207 Kokkos::resize(Ccolind, CSR_ip);
3208 Kokkos::resize(Cvals, CSR_ip);
3217 C.replaceColMap(Ccolmap);
3224 if (params.is_null() || params->get(
"sort entries",
true)) {
3226 Import_Util::sortCrsEntries(Crowptr, Ccolind, Cvals);
3228 C.setAllValues(Crowptr, Ccolind, Cvals);
3241 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
3242 labelList->set(
"Timer Label", label);
3243 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
3244 RCP<const Export<LO, GO, NO>> dummyExport;
3245 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
3251template <
class Scalar,
3253 class GlobalOrdinal,
3255void jacobi_A_B_reuse(
3256 typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
3257 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
3258 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3259 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3260 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
3261 const std::string& label,
3262 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3263 using Teuchos::Array;
3264 using Teuchos::ArrayRCP;
3265 using Teuchos::ArrayView;
3269 typedef LocalOrdinal LO;
3270 typedef GlobalOrdinal GO;
3273 typedef Import<LO, GO, NO> import_type;
3274 typedef Map<LO, GO, NO> map_type;
3277 typedef typename map_type::local_map_type local_map_type;
3279 typedef typename KCRS::StaticCrsGraphType graph_t;
3280 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3281 typedef typename NO::execution_space execution_space;
3282 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3283 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
3285 RCP<const import_type> Cimport = C.getGraph()->getImporter();
3286 lo_view_t Bcol2Ccol, Icol2Ccol;
3287 lo_view_t targetMapToOrigRow;
3288 lo_view_t targetMapToImportRow;
3292 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3295 RCP<const map_type> Ccolmap = C.getColMap();
3296 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
3297 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
3298 local_map_type Irowmap_local;
3299 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
3300 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
3301 local_map_type Icolmap_local;
3302 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
3303 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
3306 Bcol2Ccol = lo_view_t(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements());
3310 Kokkos::parallel_for(
3311 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
3312 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
3315 if (!Bview.importMatrix.is_null()) {
3316 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
3317 std::runtime_error,
"Tpetra::Jacobi: Import setUnion messed with the DomainMap in an unfortunate way");
3319 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
3320 Kokkos::parallel_for(
3321 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
3322 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
3328 targetMapToOrigRow = lo_view_t(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
3329 targetMapToImportRow = lo_view_t(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
3330 Kokkos::parallel_for(
3331 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
3332 GO aidx = Acolmap_local.getGlobalElement(i);
3333 LO B_LID = Browmap_local.getLocalElement(aidx);
3334 if (B_LID != LO_INVALID) {
3335 targetMapToOrigRow(i) = B_LID;
3336 targetMapToImportRow(i) = LO_INVALID;
3338 LO I_LID = Irowmap_local.getLocalElement(aidx);
3339 targetMapToOrigRow(i) = LO_INVALID;
3340 targetMapToImportRow(i) = I_LID;
3347 KernelWrappers2<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::jacobi_A_B_reuse_kernel_wrapper(omega, Dinv, Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
3351template <
class Scalar,
3353 class GlobalOrdinal,
3355 class LocalOrdinalViewType>
3356void KernelWrappers2<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::jacobi_A_B_reuse_kernel_wrapper(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
3357 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
3358 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3359 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3360 const LocalOrdinalViewType& targetMapToOrigRow,
3361 const LocalOrdinalViewType& targetMapToImportRow,
3362 const LocalOrdinalViewType& Bcol2Ccol,
3363 const LocalOrdinalViewType& Icol2Ccol,
3364 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
3365 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
3366 const std::string& label,
3367 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3368 host_jacobi_A_B_reuse(omega, Dinv, Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
3372template <
class Scalar,
3374 class GlobalOrdinal,
3376void import_and_extract_views(
3377 const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
3378 Teuchos::RCP<
const Map<LocalOrdinal, GlobalOrdinal, Node>> targetMap,
3379 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3380 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> prototypeImporter,
3381 bool userAssertsThereAreNoRemotes,
3382 const std::string& label,
3383 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3384 using Teuchos::Array;
3385 using Teuchos::ArrayView;
3386 using Teuchos::null;
3391 typedef LocalOrdinal LO;
3392 typedef GlobalOrdinal GO;
3395 typedef Map<LO, GO, NO> map_type;
3396 typedef Import<LO, GO, NO> import_type;
3397 typedef CrsMatrix<SC, LO, GO, NO> crs_matrix_type;
3407 Aview.deleteContents();
3409 Aview.origMatrix = rcp(&A,
false);
3411 Aview.origMatrix->getApplyHelper();
3412 Aview.origRowMap = A.getRowMap();
3413 Aview.rowMap = targetMap;
3414 Aview.colMap = A.getColMap();
3415 Aview.domainMap = A.getDomainMap();
3416 Aview.importColMap = null;
3417 RCP<const map_type> rowMap = A.getRowMap();
3418 const int numProcs = rowMap->getComm()->getSize();
3421 if (userAssertsThereAreNoRemotes || numProcs < 2)
3424 RCP<const import_type> importer;
3425 if (params != null && params->isParameter(
"importer")) {
3426 importer = params->get<RCP<const import_type>>(
"importer");
3434 RCP<const map_type> remoteRowMap;
3435 size_t numRemote = 0;
3437 if (!prototypeImporter.is_null() &&
3438 prototypeImporter->getSourceMap()->isSameAs(*rowMap) &&
3439 prototypeImporter->getTargetMap()->isSameAs(*targetMap)) {
3443 ArrayView<const LO> remoteLIDs = prototypeImporter->getRemoteLIDs();
3444 numRemote = prototypeImporter->getNumRemoteIDs();
3446 Array<GO> remoteRows(numRemote);
3447 for (
size_t i = 0; i < numRemote; i++)
3448 remoteRows[i] = targetMap->getGlobalElement(remoteLIDs[i]);
3450 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3451 rowMap->getIndexBase(), rowMap->getComm(), params));
3454 }
else if (prototypeImporter.is_null()) {
3458 ArrayView<const GO> rows = targetMap->getLocalElementList();
3459 size_t numRows = targetMap->getLocalNumElements();
3461 Array<GO> remoteRows(numRows);
3462 for (
size_t i = 0; i < numRows; ++i) {
3463 const LO mlid = rowMap->getLocalElement(rows[i]);
3465 if (mlid == Teuchos::OrdinalTraits<LO>::invalid())
3466 remoteRows[numRemote++] = rows[i];
3468 remoteRows.resize(numRemote);
3469 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3470 rowMap->getIndexBase(), rowMap->getComm(), params));
3479 TEUCHOS_TEST_FOR_EXCEPTION(numRemote > 0, std::runtime_error,
3480 "MatrixMatrix::import_and_extract_views ERROR, numProcs < 2 but attempting to import remote matrix rows.");
3488 if (!remoteRowMap.is_null() && (remoteRowMap->getGlobalNumElements() > 0)) {
3494 importer = prototypeImporter->createRemoteOnlyImport(remoteRowMap);
3496 importer = rcp(
new import_type(rowMap, remoteRowMap));
3498 throw std::runtime_error(
"prototypeImporter->SourceMap() does not match A.getRowMap()!");
3502 params->set(
"importer", importer);
3505 if (importer != null) {
3510 Teuchos::ParameterList labelList;
3511 labelList.set(
"Timer Label", label);
3513 labelList.set(
"compute global constants",
false);
3514 auto& labelList_subList = labelList.sublist(
"matrixmatrix: kernel params",
false);
3515 labelList_subList.set(
"isMatrixMatrix_TransferAndFillComplete",
true);
3517 if (!params.is_null()) {
3518 if (params->isParameter(
"compute global constants"))
3519 labelList.set(
"compute global constants", params->get<
bool>(
"compute global constants"));
3523 A.getDomainMap(), importer->getTargetMap(), rcpFromRef(labelList));
3525 Aview.importMatrix->getApplyHelper();
3531 sprintf(str,
"import_matrix.%d.dat",count);
3536#ifdef HAVE_TPETRA_MMM_STATISTICS
3537 printMultiplicationStatistics(importer, label + std::string(
" I&X MMM"));
3544 Aview.importColMap = Aview.importMatrix->getColMap();
3550template <
class Scalar,
3552 class GlobalOrdinal,
3554void import_and_extract_views(
3555 const BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& M,
3556 Teuchos::RCP<
const Map<LocalOrdinal, GlobalOrdinal, Node>> targetMap,
3557 BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Mview,
3558 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> prototypeImporter,
3559 bool userAssertsThereAreNoRemotes) {
3560 using Teuchos::Array;
3561 using Teuchos::ArrayView;
3562 using Teuchos::null;
3567 typedef LocalOrdinal LO;
3568 typedef GlobalOrdinal GO;
3571 typedef Map<LO, GO, NO> map_type;
3572 typedef Import<LO, GO, NO> import_type;
3573 typedef BlockCrsMatrix<SC, LO, GO, NO> blockcrs_matrix_type;
3581 Mview.deleteContents();
3585 Mview.origMatrix->getApplyHelper();
3586 Mview.origRowMap = M.getRowMap();
3587 Mview.rowMap = targetMap;
3588 Mview.colMap = M.getColMap();
3589 Mview.importColMap = null;
3590 RCP<const map_type> rowMap = M.getRowMap();
3591 const int numProcs = rowMap->getComm()->getSize();
3594 if (userAssertsThereAreNoRemotes || numProcs < 2)
return;
3598 RCP<const map_type> remoteRowMap;
3599 size_t numRemote = 0;
3601 if (!prototypeImporter.is_null() &&
3602 prototypeImporter->getSourceMap()->isSameAs(*rowMap) &&
3603 prototypeImporter->getTargetMap()->isSameAs(*targetMap)) {
3605 ArrayView<const LO> remoteLIDs = prototypeImporter->getRemoteLIDs();
3606 numRemote = prototypeImporter->getNumRemoteIDs();
3608 Array<GO> remoteRows(numRemote);
3609 for (
size_t i = 0; i < numRemote; i++)
3610 remoteRows[i] = targetMap->getGlobalElement(remoteLIDs[i]);
3612 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3613 rowMap->getIndexBase(), rowMap->getComm()));
3616 }
else if (prototypeImporter.is_null()) {
3618 ArrayView<const GO> rows = targetMap->getLocalElementList();
3619 size_t numRows = targetMap->getLocalNumElements();
3621 Array<GO> remoteRows(numRows);
3622 for (
size_t i = 0; i < numRows; ++i) {
3623 const LO mlid = rowMap->getLocalElement(rows[i]);
3625 if (mlid == Teuchos::OrdinalTraits<LO>::invalid())
3626 remoteRows[numRemote++] = rows[i];
3628 remoteRows.resize(numRemote);
3629 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3630 rowMap->getIndexBase(), rowMap->getComm()));
3639 TEUCHOS_TEST_FOR_EXCEPTION(numRemote > 0, std::runtime_error,
3640 "MatrixMatrix::import_and_extract_views ERROR, numProcs < 2 but attempting to import remote matrix rows.");
3647 RCP<const import_type> importer;
3649 if (!remoteRowMap.is_null() && (remoteRowMap->getGlobalNumElements() > 0)) {
3652 importer = prototypeImporter->createRemoteOnlyImport(remoteRowMap);
3654 importer = rcp(
new import_type(rowMap, remoteRowMap));
3656 throw std::runtime_error(
"prototypeImporter->SourceMap() does not match M.getRowMap()!");
3659 if (importer != null) {
3664 Mview.importMatrix->getApplyHelper();
3667 Mview.importColMap = Mview.importMatrix->getColMap();
3673template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class LocalOrdinalViewType>
3675merge_matrices(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3676 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3677 const LocalOrdinalViewType& Acol2Brow,
3678 const LocalOrdinalViewType& Acol2Irow,
3679 const LocalOrdinalViewType& Bcol2Ccol,
3680 const LocalOrdinalViewType& Icol2Ccol,
3681 const size_t mergedNodeNumCols) {
3684 typedef typename KCRS::StaticCrsGraphType graph_t;
3685 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3686 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
3687 typedef typename KCRS::values_type::non_const_type scalar_view_t;
3689 const KCRS Ak = Aview.
origMatrix->getLocalMatrixDevice();
3690 const KCRS Bk = Bview.origMatrix->getLocalMatrixDevice();
3693 if (!Bview.importMatrix.is_null() || (Bview.importMatrix.is_null() && (&*Aview.origMatrix->getGraph()->getColMap() != &*Bview.origMatrix->getGraph()->getRowMap()))) {
3699 if (!Bview.importMatrix.is_null()) Iks = Bview.importMatrix->getLocalMatrixDevice();
3701 size_t merge_numrows = Ak.numCols();
3704 lno_view_t Mrowptr(
"Mrowptr", merge_numrows + 1);
3706 const LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
3709 typedef typename Node::execution_space execution_space;
3710 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3711 Kokkos::parallel_scan(
3712 "Tpetra_MatrixMatrix_merge_matrices_buildRowptr", range_type(0, merge_numrows),
3713 KOKKOS_LAMBDA(
const size_t i,
size_t& update,
const bool final) {
3714 if (
final) Mrowptr(i) = update;
3717 if (Acol2Brow(i) != LO_INVALID)
3718 ct = Bk.graph.row_map(Acol2Brow(i) + 1) - Bk.graph.row_map(Acol2Brow(i));
3720 ct = Iks.graph.row_map(Acol2Irow(i) + 1) - Iks.graph.row_map(Acol2Irow(i));
3723 if (
final && i + 1 == merge_numrows)
3724 Mrowptr(i + 1) = update;
3728 size_t merge_nnz = ::Tpetra::Details::getEntryOnHost(Mrowptr, merge_numrows);
3729 lno_nnz_view_t Mcolind(Kokkos::ViewAllocateWithoutInitializing(
"Mcolind"), merge_nnz);
3730 scalar_view_t Mvalues(Kokkos::ViewAllocateWithoutInitializing(
"Mvals"), merge_nnz);
3733 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3734 Kokkos::parallel_for(
3735 "Tpetra_MatrixMatrix_merg_matrices_buildColindValues", range_type(0, merge_numrows), KOKKOS_LAMBDA(
const size_t i) {
3736 if (Acol2Brow(i) != LO_INVALID) {
3737 size_t row = Acol2Brow(i);
3738 size_t start = Bk.graph.row_map(row);
3739 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3740 Mvalues(j) = Bk.values(j - Mrowptr(i) + start);
3741 Mcolind(j) = Bcol2Ccol(Bk.graph.entries(j - Mrowptr(i) + start));
3744 size_t row = Acol2Irow(i);
3745 size_t start = Iks.graph.row_map(row);
3746 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3747 Mvalues(j) = Iks.values(j - Mrowptr(i) + start);
3748 Mcolind(j) = Icol2Ccol(Iks.graph.entries(j - Mrowptr(i) + start));
3753 KCRS newmat(
"CrsMatrix", merge_numrows, mergedNodeNumCols, merge_nnz, Mvalues, Mrowptr, Mcolind);
3763template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class LocalOrdinalViewType>
3764const typename Tpetra::BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_device_type
3765merge_matrices(BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3766 BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3767 const LocalOrdinalViewType& Acol2Brow,
3768 const LocalOrdinalViewType& Acol2Irow,
3769 const LocalOrdinalViewType& Bcol2Ccol,
3770 const LocalOrdinalViewType& Icol2Ccol,
3771 const size_t mergedNodeNumCols) {
3773 typedef typename Tpetra::BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_device_type KBCRS;
3774 typedef typename KBCRS::StaticCrsGraphType graph_t;
3775 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3776 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
3777 typedef typename KBCRS::values_type::non_const_type scalar_view_t;
3780 const KBCRS Ak = Aview.
origMatrix->getLocalMatrixDevice();
3781 const KBCRS Bk = Bview.origMatrix->getLocalMatrixDevice();
3784 if (!Bview.importMatrix.is_null() ||
3785 (Bview.importMatrix.is_null() &&
3786 (&*Aview.origMatrix->getGraph()->getColMap() != &*Bview.origMatrix->getGraph()->getRowMap()))) {
3791 if (!Bview.importMatrix.is_null()) Iks = Bview.importMatrix->getLocalMatrixDevice();
3792 size_t merge_numrows = Ak.numCols();
3795 lno_view_t Mrowptr(
"Mrowptr", merge_numrows + 1);
3797 const LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
3800 typedef typename Node::execution_space execution_space;
3801 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3802 Kokkos::parallel_scan(
3803 "Tpetra_MatrixMatrix_merge_matrices_buildRowptr", range_type(0, merge_numrows),
3804 KOKKOS_LAMBDA(
const size_t i,
size_t& update,
const bool final) {
3805 if (
final) Mrowptr(i) = update;
3808 if (Acol2Brow(i) != LO_INVALID)
3809 ct = Bk.graph.row_map(Acol2Brow(i) + 1) - Bk.graph.row_map(Acol2Brow(i));
3811 ct = Iks.graph.row_map(Acol2Irow(i) + 1) - Iks.graph.row_map(Acol2Irow(i));
3814 if (
final && i + 1 == merge_numrows)
3815 Mrowptr(i + 1) = update;
3819 size_t merge_nnz = ::Tpetra::Details::getEntryOnHost(Mrowptr, merge_numrows);
3820 const int blocksize = Ak.blockDim();
3821 lno_nnz_view_t Mcolind(Kokkos::ViewAllocateWithoutInitializing(
"Mcolind"), merge_nnz);
3822 scalar_view_t Mvalues(Kokkos::ViewAllocateWithoutInitializing(
"Mvals"), merge_nnz * blocksize * blocksize);
3825 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3826 Kokkos::parallel_for(
3827 "Tpetra_MatrixMatrix_merg_matrices_buildColindValues", range_type(0, merge_numrows), KOKKOS_LAMBDA(
const size_t i) {
3828 if (Acol2Brow(i) != LO_INVALID) {
3829 size_t row = Acol2Brow(i);
3830 size_t start = Bk.graph.row_map(row);
3831 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3832 Mcolind(j) = Bcol2Ccol(Bk.graph.entries(j - Mrowptr(i) + start));
3834 for (
int b = 0; b < blocksize * blocksize; ++b) {
3835 const int val_indx = j * blocksize * blocksize + b;
3836 const int b_val_indx = (j - Mrowptr(i) +
start) * blocksize * blocksize + b;
3837 Mvalues(val_indx) = Bk.values(b_val_indx);
3841 size_t row = Acol2Irow(i);
3842 size_t start = Iks.graph.row_map(row);
3843 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3844 Mcolind(j) = Icol2Ccol(Iks.graph.entries(j - Mrowptr(i) + start));
3846 for (
int b = 0; b < blocksize * blocksize; ++b) {
3847 const int val_indx = j * blocksize * blocksize + b;
3848 const int b_val_indx = (j - Mrowptr(i) +
start) * blocksize * blocksize + b;
3849 Mvalues(val_indx) = Iks.values(b_val_indx);
3856 KBCRS newmat(
"CrsMatrix", merge_numrows, mergedNodeNumCols, merge_nnz, Mvalues, Mrowptr, Mcolind, blocksize);
3865template <
typename SC,
typename LO,
typename GO,
typename NO>
3866void AddKernels<SC, LO, GO, NO>::
3868 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Avals,
3869 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Arowptrs,
3870 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Acolinds,
3871 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarA,
3872 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Bvals,
3873 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Browptrs,
3874 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Bcolinds,
3875 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarB,
3877 typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Cvals,
3878 typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array& Crowptrs,
3879 typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Ccolinds) {
3881 using Teuchos::TimeMonitor;
3882 using AddKern = MMdetails::AddKernels<SC, LO, GO, NO>;
3883 TEUCHOS_TEST_FOR_EXCEPTION(Arowptrs.extent(0) != Browptrs.extent(0), std::runtime_error,
"Can't add matrices with different numbers of rows.");
3884 auto nrows = Arowptrs.extent(0) - 1;
3885 Crowptrs = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"C row ptrs"), nrows + 1);
3886 typename AddKern::KKH handle;
3887 handle.create_spadd_handle(
true);
3888 auto addHandle = handle.get_spadd_handle();
3892 KokkosSparse::spadd_symbolic(&handle,
3893 nrows, numGlobalCols,
3894 Arowptrs, Acolinds, Browptrs, Bcolinds, Crowptrs);
3896 Cvals = values_array(
"C values", addHandle->get_c_nnz());
3897 Ccolinds = col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
3901 KokkosSparse::spadd_numeric(&handle,
3902 nrows, numGlobalCols,
3903 Arowptrs, Acolinds, Avals, scalarA,
3904 Browptrs, Bcolinds, Bvals, scalarB,
3905 Crowptrs, Ccolinds, Cvals);
3908template <
typename SC,
typename LO,
typename GO,
typename NO>
3909void AddKernels<SC, LO, GO, NO>::
3911 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Avals,
3912 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Arowptrs,
3913 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Acolinds,
3914 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarA,
3915 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Bvals,
3916 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Browptrs,
3917 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Bcolinds,
3918 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarB,
3920 typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Cvals,
3921 typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array& Crowptrs,
3922 typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Ccolinds) {
3924 using Teuchos::TimeMonitor;
3925 using AddKern = MMdetails::AddKernels<SC, LO, GO, NO>;
3926 TEUCHOS_TEST_FOR_EXCEPTION(Arowptrs.extent(0) != Browptrs.extent(0), std::runtime_error,
"Can't add matrices with different numbers of rows.");
3927 auto nrows = Arowptrs.extent(0) - 1;
3928 Crowptrs = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"C row ptrs"), nrows + 1);
3929 typedef MMdetails::AddKernels<SC, LO, GO, NO> AddKern;
3930 typename AddKern::KKH handle;
3931 handle.create_spadd_handle(
false);
3932 auto addHandle = handle.get_spadd_handle();
3935 KokkosSparse::spadd_symbolic(&handle,
3936 nrows, numGlobalCols,
3937 Arowptrs, Acolinds, Browptrs, Bcolinds, Crowptrs);
3939 Cvals = values_array(
"C values", addHandle->get_c_nnz());
3940 Ccolinds = col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
3943 KokkosSparse::spadd_numeric(&handle,
3944 nrows, numGlobalCols,
3945 Arowptrs, Acolinds, Avals, scalarA,
3946 Browptrs, Bcolinds, Bvals, scalarB,
3947 Crowptrs, Ccolinds, Cvals);
3950template <
typename GO,
3951 typename LocalIndicesType,
3952 typename GlobalIndicesType,
3953 typename ColMapType>
3954struct ConvertLocalToGlobalFunctor {
3955 ConvertLocalToGlobalFunctor(
3956 const LocalIndicesType& colindsOrig_,
3957 const GlobalIndicesType& colindsConverted_,
3958 const ColMapType& colmap_)
3959 : colindsOrig(colindsOrig_)
3960 , colindsConverted(colindsConverted_)
3961 , colmap(colmap_) {}
3962 KOKKOS_INLINE_FUNCTION
void
3963 operator()(
const GO i)
const {
3964 colindsConverted(i) = colmap.getGlobalElement(colindsOrig(i));
3966 LocalIndicesType colindsOrig;
3967 GlobalIndicesType colindsConverted;
3971template <
typename SC,
typename LO,
typename GO,
typename NO>
3972void MMdetails::AddKernels<SC, LO, GO, NO>::
3973 convertToGlobalAndAdd(
3974 const typename MMdetails::AddKernels<SC, LO, GO, NO>::KCRS A,
3975 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarA,
3976 const typename MMdetails::AddKernels<SC, LO, GO, NO>::KCRS B,
3977 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarB,
3978 const typename MMdetails::AddKernels<SC, LO, GO, NO>::local_map_type& AcolMap,
3979 const typename MMdetails::AddKernels<SC, LO, GO, NO>::local_map_type& BcolMap,
3980 typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Cvals,
3981 typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array& Crowptrs,
3982 typename MMdetails::AddKernels<SC, LO, GO, NO>::global_col_inds_array& Ccolinds) {
3984 using Teuchos::TimeMonitor;
3987 using KKH_GO = KokkosKernels::Experimental::KokkosKernelsHandle<size_t, GO, impl_scalar_type,
3988 typename NO::execution_space,
typename NO::memory_space,
typename NO::memory_space>;
3990 const values_array Avals = A.values;
3991 const values_array Bvals = B.values;
3992 const col_inds_array Acolinds = A.graph.entries;
3993 const col_inds_array Bcolinds = B.graph.entries;
3994 auto Arowptrs = A.graph.row_map;
3995 auto Browptrs = B.graph.row_map;
3996 global_col_inds_array AcolindsConverted(Kokkos::ViewAllocateWithoutInitializing(
"A colinds (converted)"), Acolinds.extent(0));
3997 global_col_inds_array BcolindsConverted(Kokkos::ViewAllocateWithoutInitializing(
"B colinds (converted)"), Bcolinds.extent(0));
4001 ConvertLocalToGlobalFunctor<GO, col_inds_array, global_col_inds_array, local_map_type> convertA(Acolinds, AcolindsConverted, AcolMap);
4002 Kokkos::parallel_for(
"Tpetra_MatrixMatrix_convertColIndsA", range_type(0, Acolinds.extent(0)), convertA);
4003 ConvertLocalToGlobalFunctor<GO, col_inds_array, global_col_inds_array, local_map_type> convertB(Bcolinds, BcolindsConverted, BcolMap);
4004 Kokkos::parallel_for(
"Tpetra_MatrixMatrix_convertColIndsB", range_type(0, Bcolinds.extent(0)), convertB);
4006 handle.create_spadd_handle(
false);
4007 auto addHandle = handle.get_spadd_handle();
4010 auto nrows = Arowptrs.extent(0) - 1;
4011 Crowptrs = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"C row ptrs"), nrows + 1);
4012 KokkosSparse::spadd_symbolic(&handle,
4014 Arowptrs, AcolindsConverted, Browptrs, BcolindsConverted, Crowptrs);
4015 Cvals = values_array(
"C values", addHandle->get_c_nnz());
4016 Ccolinds = global_col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
4020 KokkosSparse::spadd_numeric(&handle,
4022 Arowptrs, AcolindsConverted, Avals, scalarA,
4023 Browptrs, BcolindsConverted, Bvals, scalarB,
4024 Crowptrs, Ccolinds, Cvals);
4039#define TPETRA_MATRIXMATRIX_INSTANT(SCALAR, LO, GO, NODE) \
4040 template void MatrixMatrix::Multiply( \
4041 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4043 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4045 CrsMatrix<SCALAR, LO, GO, NODE>& C, \
4046 bool call_FillComplete_on_result, \
4047 const std::string& label, \
4048 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4050 template void MatrixMatrix::Multiply( \
4051 const Teuchos::RCP<const BlockCrsMatrix<SCALAR, LO, GO, NODE>>& A, \
4053 const Teuchos::RCP<const BlockCrsMatrix<SCALAR, LO, GO, NODE>>& B, \
4055 Teuchos::RCP<BlockCrsMatrix<SCALAR, LO, GO, NODE>>& C, \
4056 const std::string& label); \
4058 template void MatrixMatrix::Jacobi( \
4059 typename Teuchos::ScalarTraits<SCALAR>::magnitudeType omega, \
4060 const Vector<SCALAR, LO, GO, NODE>& Dinv, \
4061 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4062 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4063 CrsMatrix<SCALAR, LO, GO, NODE>& C, \
4064 bool call_FillComplete_on_result, \
4065 const std::string& label, \
4066 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4068 template void MatrixMatrix::Add( \
4069 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4072 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4075 Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE>>& C); \
4077 template void MatrixMatrix::Add( \
4078 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4081 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4084 const Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE>>& C); \
4086 template void MatrixMatrix::Add( \
4087 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4090 CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4093 template Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE>> \
4094 MatrixMatrix::add<SCALAR, LO, GO, NODE>(const SCALAR& alpha, \
4095 const bool transposeA, \
4096 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4097 const SCALAR& beta, \
4098 const bool transposeB, \
4099 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4100 const Teuchos::RCP<const Map<LO, GO, NODE>>& domainMap, \
4101 const Teuchos::RCP<const Map<LO, GO, NODE>>& rangeMap, \
4102 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4105 MatrixMatrix::add<SCALAR, LO, GO, NODE>(const SCALAR& alpha, \
4106 const bool transposeA, \
4107 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4108 const SCALAR& beta, \
4109 const bool transposeB, \
4110 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4111 CrsMatrix<SCALAR, LO, GO, NODE>& C, \
4112 const Teuchos::RCP<const Map<LO, GO, NODE>>& domainMap, \
4113 const Teuchos::RCP<const Map<LO, GO, NODE>>& rangeMap, \
4114 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4116 template struct MMdetails::AddKernels<SCALAR, LO, GO, NODE>; \
4118 template void MMdetails::import_and_extract_views<SCALAR, LO, GO, NODE>(const CrsMatrix<SCALAR, LO, GO, NODE>& M, \
4119 Teuchos::RCP<const Map<LO, GO, NODE>> targetMap, \
4120 CrsMatrixStruct<SCALAR, LO, GO, NODE>& Mview, \
4121 Teuchos::RCP<const Import<LO, GO, NODE>> prototypeImporter, \
4122 bool userAssertsThereAreNoRemotes, \
4123 const std::string& label, \
4124 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4126 template void MMdetails::import_and_extract_views<SCALAR, LO, GO, NODE>(const BlockCrsMatrix<SCALAR, LO, GO, NODE>& M, \
4127 Teuchos::RCP<const Map<LO, GO, NODE>> targetMap, \
4128 BlockCrsMatrixStruct<SCALAR, LO, GO, NODE>& Mview, \
4129 Teuchos::RCP<const Import<LO, GO, NODE>> prototypeImporter, \
4130 bool userAssertsThereAreNoRemotes);
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Declaration and definition of Tpetra::Details::getEntryOnHost.
Utility functions for packing and unpacking sparse matrix entries.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects.
Stand-alone utility functions and macros.
Forward declaration of some Tpetra Matrix Matrix objects.
KokkosSparse::CrsMatrix< impl_scalar_type, local_ordinal_type, device_type, void, typename local_graph_device_type::size_type > local_matrix_device_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
Struct that holds views of the contents of a CrsMatrix.
Teuchos::RCP< const map_type > colMap
Col map for the original version of the matrix.
Teuchos::RCP< const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > origMatrix
The original matrix.
static bool debug()
Whether Tpetra is in debug mode.
void start()
Start the deep_copy counter.
void Jacobi(typename Teuchos::ScalarTraits< Scalar >::magnitudeType omega, const Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Dinv, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &C, bool call_FillComplete_on_result=true, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Teuchos::RCP< CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > add(const Scalar &alpha, const bool transposeA, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta, const bool transposeB, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap=Teuchos::null, const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Compute the sparse matrix sum C = scalarA * Op(A) + scalarB * Op(B), where Op(X) is either X or its t...
void Multiply(const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, bool transposeA, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, bool transposeB, CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &C, bool call_FillComplete_on_result=true, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Sparse matrix-matrix multiply.
void Add(const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, bool transposeA, Scalar scalarA, CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, Scalar scalarB)
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void removeCrsMatrixZeros(CrsMatrixType &matrix, typename Teuchos::ScalarTraits< typename CrsMatrixType::scalar_type >::magnitudeType const &threshold=Teuchos::ScalarTraits< typename CrsMatrixType::scalar_type >::magnitude(Teuchos::ScalarTraits< typename CrsMatrixType::scalar_type >::zero()))
Remove zero entries from a matrix.