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"
69template <
class Scalar,
79 bool call_FillComplete_on_result,
80 const std::string& label,
81 const Teuchos::RCP<Teuchos::ParameterList>& params) {
86 typedef LocalOrdinal LO;
87 typedef GlobalOrdinal GO;
97 const std::string prefix =
"TpetraExt::MatrixMatrix::Multiply(): ";
102 TEUCHOS_TEST_FOR_EXCEPTION(!A.
isFillComplete(), std::runtime_error, prefix <<
"Matrix A is not fill complete.");
103 TEUCHOS_TEST_FOR_EXCEPTION(!B.
isFillComplete(), std::runtime_error, prefix <<
"Matrix B is not fill complete.");
108 RCP<const crs_matrix_type> Aprime = null;
112 RCP<const crs_matrix_type> Bprime = null;
122 const bool newFlag = !C.
getGraph()->isLocallyIndexed() && !C.
getGraph()->isGloballyIndexed();
124 bool use_optimized_ATB =
false;
125 if (transposeA && !transposeB && call_FillComplete_on_result && newFlag)
126 use_optimized_ATB =
true;
128#ifdef USE_OLD_TRANSPOSE
129 use_optimized_ATB =
false;
132 using Teuchos::ParameterList;
133 RCP<ParameterList> transposeParams(
new ParameterList);
134#if KOKKOSKERNELS_VERSION >= 50299
135 transposeParams->set(
"sort",
false);
137 transposeParams->set(
"sort",
true);
140 if (!use_optimized_ATB && transposeA) {
141 transposer_type transposer(rcpFromRef(A));
142 Aprime = transposer.createTranspose(transposeParams);
144 Aprime = rcpFromRef(A);
148 transposer_type transposer(rcpFromRef(B));
149 Bprime = transposer.createTranspose(transposeParams);
151 Bprime = rcpFromRef(B);
161 TEUCHOS_TEST_FOR_EXCEPTION(Ainner != Binner, std::runtime_error,
162 prefix <<
"ERROR, inner dimensions of op(A) and op(B) "
163 "must match for matrix-matrix product. op(A) is "
164 << Aouter <<
"x" << Ainner <<
", op(B) is " << Binner <<
"x" << Bouter);
170 TEUCHOS_TEST_FOR_EXCEPTION(Aouter > C.
getGlobalNumRows(), std::runtime_error,
171 prefix <<
"ERROR, dimensions of result C must "
172 "match dimensions of op(A) * op(B). C has "
174 <<
" rows, should have at least " << Aouter << std::endl);
186 int numProcs = A.
getComm()->getSize();
190 crs_matrix_struct_type Aview;
191 crs_matrix_struct_type Bview;
193 RCP<const map_type> targetMap_A = Aprime->getRowMap();
194 RCP<const map_type> targetMap_B = Bprime->getRowMap();
202 if (!use_optimized_ATB) {
203 RCP<const import_type> dummyImporter;
204 MMdetails::import_and_extract_views(*Aprime, targetMap_A, Aview, dummyImporter,
true, label, params);
210 targetMap_B = Aprime->getColMap();
213 if (!use_optimized_ATB)
214 MMdetails::import_and_extract_views(*Bprime, targetMap_B, Bview, Aprime->getGraph()->getImporter(), Aprime->getGraph()->getImporter().is_null(), label, params);
223 if (use_optimized_ATB) {
224 MMdetails::mult_AT_B_newmatrix(A, B, C, label, params);
226 }
else if (call_FillComplete_on_result && newFlag) {
227 MMdetails::mult_A_B_newmatrix(Aview, Bview, C, label, params);
229 }
else if (call_FillComplete_on_result) {
230 MMdetails::mult_A_B_reuse(Aview, Bview, C, label, params);
236 CrsWrapper_CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> crsmat(C);
238 MMdetails::mult_A_B(Aview, Bview, crsmat, label, params);
250 C.
fillComplete(Bprime->getDomainMap(), Aprime->getRangeMap());
258template <
class Scalar,
268 const std::string& label) {
273 typedef LocalOrdinal LO;
274 typedef GlobalOrdinal GO;
280 std::string prefix = std::string(
"TpetraExt ") + label + std::string(
": ");
282 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true, std::runtime_error, prefix <<
"Matrix A cannot be transposed.");
283 TEUCHOS_TEST_FOR_EXCEPTION(transposeB ==
true, std::runtime_error, prefix <<
"Matrix B cannot be transposed.");
295 TEUCHOS_TEST_FOR_EXCEPTION(Ainner != Binner, std::runtime_error,
296 prefix <<
"ERROR, inner dimensions of op(A) and op(B) "
297 "must match for matrix-matrix product. op(A) is "
298 << Aouter <<
"x" << Ainner <<
", op(B) is " << Binner <<
"x" << Bouter);
302 int numProcs = A->getComm()->getSize();
304 const LO blocksize = A->getBlockSize();
305 TEUCHOS_TEST_FOR_EXCEPTION(blocksize != B->getBlockSize(), std::runtime_error,
306 prefix <<
"ERROR, Blocksizes do not match. A.blocksize = " << blocksize <<
", B.blocksize = " << B->getBlockSize());
310 blockcrs_matrix_struct_type Aview(blocksize);
311 blockcrs_matrix_struct_type Bview(blocksize);
313 RCP<const map_type> targetMap_A = A->getRowMap();
314 RCP<const map_type> targetMap_B = B->getRowMap();
317 RCP<const import_type> dummyImporter;
318 MMdetails::import_and_extract_views(*A, targetMap_A, Aview, dummyImporter,
true);
323 targetMap_B = A->getColMap();
326 MMdetails::import_and_extract_views(*B, targetMap_B, Bview, A->getGraph()->getImporter(),
327 A->getGraph()->getImporter().is_null());
330 MMdetails::mult_A_B_newmatrix(Aview, Bview, C);
333template <
class Scalar,
337void Jacobi(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
342 bool call_FillComplete_on_result,
343 const std::string& label,
344 const Teuchos::RCP<Teuchos::ParameterList>& params) {
348 typedef LocalOrdinal LO;
349 typedef GlobalOrdinal GO;
358 const std::string prefix =
"TpetraExt::MatrixMatrix::Jacobi(): ";
363 TEUCHOS_TEST_FOR_EXCEPTION(!A.
isFillComplete(), std::runtime_error, prefix <<
"Matrix A is not fill complete.");
364 TEUCHOS_TEST_FOR_EXCEPTION(!B.
isFillComplete(), std::runtime_error, prefix <<
"Matrix B is not fill complete.");
366 RCP<const crs_matrix_type> Aprime = rcpFromRef(A);
367 RCP<const crs_matrix_type> Bprime = rcpFromRef(B);
376 TEUCHOS_TEST_FOR_EXCEPTION(Ainner != Binner, std::runtime_error,
377 prefix <<
"ERROR, inner dimensions of op(A) and op(B) "
378 "must match for matrix-matrix product. op(A) is "
379 << Aouter <<
"x" << Ainner <<
", op(B) is " << Binner <<
"x" << Bouter);
385 TEUCHOS_TEST_FOR_EXCEPTION(Aouter > C.
getGlobalNumRows(), std::runtime_error,
386 prefix <<
"ERROR, dimensions of result C must "
387 "match dimensions of op(A) * op(B). C has "
389 <<
" rows, should have at least " << Aouter << std::endl);
401 int numProcs = A.
getComm()->getSize();
405 crs_matrix_struct_type Aview;
406 crs_matrix_struct_type Bview;
408 RCP<const map_type> targetMap_A = Aprime->getRowMap();
409 RCP<const map_type> targetMap_B = Bprime->getRowMap();
415 RCP<Teuchos::ParameterList> importParams = Teuchos::rcp(
new Teuchos::ParameterList);
416 importParams->set(
"compute global constants",
false);
417 if (!params.is_null()) {
418 importParams->setParameters(*params);
419 importParams->set(
"compute global constants", params->get(
"compute global constants: temporaries",
false));
423 RCP<const import_type> dummyImporter;
424 MMdetails::import_and_extract_views(*Aprime, targetMap_A, Aview, dummyImporter,
true, label, importParams);
429 targetMap_B = Aprime->getColMap();
432 MMdetails::import_and_extract_views(*Bprime, targetMap_B, Bview, Aprime->getGraph()->getImporter(), Aprime->getGraph()->getImporter().is_null(), label, importParams);
438 CrsWrapper_CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> crsmat(C);
441 bool newFlag = !C.
getGraph()->isLocallyIndexed() && !C.
getGraph()->isGloballyIndexed();
443 if (call_FillComplete_on_result && newFlag) {
444 MMdetails::jacobi_A_B_newmatrix(omega, Dinv, Aview, Bview, C, label, params);
446 }
else if (call_FillComplete_on_result) {
447 MMdetails::jacobi_A_B_reuse(omega, Dinv, Aview, Bview, C, label, params);
450 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"jacobi_A_B_general not implemented");
453 if (!params.is_null()) {
454 bool removeZeroEntries = params->get(
"remove zeros",
false);
455 if (removeZeroEntries) {
456 typedef Teuchos::ScalarTraits<Scalar> STS;
457 typename STS::magnitudeType threshold = params->get(
"remove zeros threshold", STS::magnitude(STS::zero()));
463template <
class Scalar,
473 using Teuchos::Array;
477 typedef LocalOrdinal LO;
478 typedef GlobalOrdinal GO;
483 const std::string prefix =
"TpetraExt::MatrixMatrix::Add(): ";
485 TEUCHOS_TEST_FOR_EXCEPTION(!A.
isFillComplete(), std::runtime_error,
486 prefix <<
"ERROR, input matrix A.isFillComplete() is false; it is required to be true. "
487 "(Result matrix B is not required to be isFillComplete()).");
488 TEUCHOS_TEST_FOR_EXCEPTION(B.
isFillComplete(), std::runtime_error,
489 prefix <<
"ERROR, input matrix B must not be fill complete!");
490 TEUCHOS_TEST_FOR_EXCEPTION(B.
isStaticGraph(), std::runtime_error,
491 prefix <<
"ERROR, input matrix B must not have static graph!");
493 prefix <<
"ERROR, input matrix B must not be locally indexed!");
495 using Teuchos::ParameterList;
496 RCP<ParameterList> transposeParams(
new ParameterList);
497 transposeParams->set(
"sort",
false);
499 RCP<const crs_matrix_type> Aprime = null;
501 transposer_type transposer(rcpFromRef(A));
502 Aprime = transposer.createTranspose(transposeParams);
504 Aprime = rcpFromRef(A);
512 if (scalarB != Teuchos::ScalarTraits<SC>::one())
516 if (scalarA != Teuchos::ScalarTraits<SC>::zero()) {
517 for (LO i = 0; (size_t)i < numMyRows; ++i) {
518 row = B.
getRowMap()->getGlobalElement(i);
519 Aprime->getGlobalRowCopy(row, a_inds, a_vals, a_numEntries);
521 if (scalarA != Teuchos::ScalarTraits<SC>::one()) {
522 for (
size_t j = 0; j < a_numEntries; ++j)
523 a_vals[j] *= scalarA;
525 B.
insertGlobalValues(row, a_numEntries,
reinterpret_cast<Scalar*
>(a_vals.data()), a_inds.data());
530template <
class Scalar,
534Teuchos::RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
536 const bool transposeA,
539 const bool transposeB,
543 const Teuchos::RCP<Teuchos::ParameterList>& params) {
544 using Teuchos::ParameterList;
547 using Teuchos::rcpFromRef;
549 if (!params.is_null()) {
550 TEUCHOS_TEST_FOR_EXCEPTION(
551 params->isParameter(
"Call fillComplete") && !params->get<
bool>(
"Call fillComplete"),
552 std::invalid_argument,
553 "Tpetra::MatrixMatrix::add(): this version of add() always calls fillComplete\n"
554 "on the result, but you explicitly set 'Call fillComplete' = false in the parameter list. Don't set this explicitly.");
555 params->set(
"Call fillComplete",
true);
559 RCP<const crs_matrix_type> Brcp = rcpFromRef(B);
565 TEUCHOS_TEST_FOR_EXCEPTION(!A.
isFillComplete() || !Brcp->isFillComplete(), std::invalid_argument,
566 "TpetraExt::MatrixMatrix::add(): A and B must both be fill complete.");
567 RCP<crs_matrix_type> C = rcp(
new crs_matrix_type(Brcp->getRowMap(), 0));
569 add(alpha, transposeA, A, beta,
false, *Brcp, *C, domainMap, rangeMap, params);
577template <
class LO,
class GO,
class LOView,
class GOView,
class LocalMap>
578struct ConvertGlobalToLocalFunctor {
579 ConvertGlobalToLocalFunctor(LOView& lids_,
const GOView& gids_,
const LocalMap localColMap_)
582 , localColMap(localColMap_) {}
584 KOKKOS_FUNCTION
void operator()(
const GO i)
const {
585 lids(i) = localColMap.getLocalElement(gids(i));
590 const LocalMap localColMap;
593template <
class Scalar,
597void add(
const Scalar& alpha,
598 const bool transposeA,
601 const bool transposeB,
606 const Teuchos::RCP<Teuchos::ParameterList>& params) {
609 using Teuchos::rcp_dynamic_cast;
610 using Teuchos::rcp_implicit_cast;
611 using Teuchos::rcpFromRef;
612 using Teuchos::TimeMonitor;
614 using LO = LocalOrdinal;
615 using GO = GlobalOrdinal;
623 using exec_space =
typename crs_graph_type::execution_space;
624 using AddKern = MMdetails::AddKernels<SC, LO, GO, NO>;
625 const char* prefix_mmm =
"TpetraExt::MatrixMatrix::add: ";
626 constexpr bool debug =
false;
631 std::ostringstream os;
632 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
633 <<
"TpetraExt::MatrixMatrix::add" << std::endl;
634 std::cerr << os.str();
638 prefix_mmm <<
"C must be a 'new' matrix (neither locally nor globally indexed).");
640 prefix_mmm <<
"A and B must both be fill complete.");
641#ifdef HAVE_TPETRA_DEBUG
644 const bool domainMapsSame =
645 (!transposeA && !transposeB &&
647 (!transposeA && transposeB &&
649 (transposeA && !transposeB &&
651 TEUCHOS_TEST_FOR_EXCEPTION(domainMapsSame, std::invalid_argument,
652 prefix_mmm <<
"The domain Maps of Op(A) and Op(B) are not the same.");
654 const bool rangeMapsSame =
655 (!transposeA && !transposeB &&
657 (!transposeA && transposeB &&
659 (transposeA && !transposeB &&
661 TEUCHOS_TEST_FOR_EXCEPTION(rangeMapsSame, std::invalid_argument,
662 prefix_mmm <<
"The range Maps of Op(A) and Op(B) are not the same.");
666 using Teuchos::ParameterList;
668 RCP<const crs_matrix_type> Aprime = rcpFromRef(A);
670 transposer_type transposer(Aprime);
671 Aprime = transposer.createTranspose();
674#ifdef HAVE_TPETRA_DEBUG
675 TEUCHOS_TEST_FOR_EXCEPTION(Aprime.is_null(), std::logic_error,
676 prefix_mmm <<
"Failed to compute Op(A). "
677 "Please report this bug to the Tpetra developers.");
681 RCP<const crs_matrix_type> Bprime = rcpFromRef(B);
684 std::ostringstream os;
685 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
686 <<
"Form explicit xpose of B" << std::endl;
687 std::cerr << os.str();
689 transposer_type transposer(Bprime);
690 Bprime = transposer.createTranspose();
692#ifdef HAVE_TPETRA_DEBUG
693 TEUCHOS_TEST_FOR_EXCEPTION(Bprime.is_null(), std::logic_error,
694 prefix_mmm <<
"Failed to compute Op(B). Please report this bug to the Tpetra developers.");
695 TEUCHOS_TEST_FOR_EXCEPTION(
696 !Aprime->isFillComplete() || !Bprime->isFillComplete(), std::invalid_argument,
697 prefix_mmm <<
"Aprime and Bprime must both be fill complete. "
698 "Please report this bug to the Tpetra developers.");
700 RCP<const map_type> CDomainMap = domainMap;
701 RCP<const map_type> CRangeMap = rangeMap;
702 if (CDomainMap.is_null()) {
703 CDomainMap = Bprime->getDomainMap();
705 if (CRangeMap.is_null()) {
706 CRangeMap = Bprime->getRangeMap();
708 assert(!(CDomainMap.is_null()));
709 assert(!(CRangeMap.is_null()));
710 typedef typename AddKern::values_array values_array;
711 typedef typename AddKern::row_ptrs_array row_ptrs_array;
712 typedef typename AddKern::col_inds_array col_inds_array;
713 bool AGraphSorted = Aprime->getCrsGraph()->isSorted();
714 bool BGraphSorted = Bprime->getCrsGraph()->isSorted();
716 row_ptrs_array rowptrs;
717 col_inds_array colinds;
722 if (!(Aprime->getRowMap()->isSameAs(*(Bprime->getRowMap())))) {
724 auto import = rcp(new import_type(Aprime->getRowMap(), Bprime->getRowMap()));
731 bool matchingColMaps = Aprime->getColMap()->isSameAs(*(Bprime->getColMap()));
732 bool sorted = AGraphSorted && BGraphSorted;
733 RCP<const import_type> Cimport = Teuchos::null;
734 RCP<export_type> Cexport = Teuchos::null;
735 bool doFillComplete =
true;
736 if (Teuchos::nonnull(params) && params->isParameter(
"Call fillComplete")) {
737 doFillComplete = params->get<
bool>(
"Call fillComplete");
739 auto Alocal = Aprime->getLocalMatrixDevice();
740 auto Blocal = Bprime->getLocalMatrixDevice();
741 LO numLocalRows = Alocal.numRows();
742 if (numLocalRows == 0) {
748 rowptrs = row_ptrs_array(
"C rowptrs", 0);
750 auto Acolmap = Aprime->getColMap();
751 auto Bcolmap = Bprime->getColMap();
752 if (!matchingColMaps) {
753 using global_col_inds_array =
typename AddKern::global_col_inds_array;
758 auto AlocalColmap = Acolmap->getLocalMap();
759 auto BlocalColmap = Bcolmap->getLocalMap();
760 global_col_inds_array globalColinds;
762 std::ostringstream os;
763 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
764 <<
"Call AddKern::convertToGlobalAndAdd(...)" << std::endl;
765 std::cerr << os.str();
767 AddKern::convertToGlobalAndAdd(
768 Alocal, alpha, Blocal, beta, AlocalColmap, BlocalColmap,
769 vals, rowptrs, globalColinds);
771 std::ostringstream os;
772 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
773 <<
"Finished AddKern::convertToGlobalAndAdd(...)" << std::endl;
774 std::cerr << os.str();
779 RCP<const map_type> CcolMap;
782 col_inds_array localColinds(
"C colinds", globalColinds.extent(0));
783 Kokkos::parallel_for(Kokkos::RangePolicy<exec_space>(0, globalColinds.extent(0)),
784 ConvertGlobalToLocalFunctor<LocalOrdinal, GlobalOrdinal,
785 col_inds_array, global_col_inds_array,
786 typename map_type::local_map_type>(localColinds, globalColinds, CcolMap->getLocalMap()));
794 auto Avals = Alocal.values;
795 auto Bvals = Blocal.values;
796 auto Arowptrs = Alocal.graph.row_map;
797 auto Browptrs = Blocal.graph.row_map;
798 auto Acolinds = Alocal.graph.entries;
799 auto Bcolinds = Blocal.graph.entries;
805 std::ostringstream os;
806 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
807 <<
"Call AddKern::addSorted(...)" << std::endl;
808 std::cerr << os.str();
810 AddKern::addSorted(Avals, Arowptrs, Acolinds, alpha, Bvals, Browptrs, Bcolinds, beta, Aprime->getGlobalNumCols(), vals, rowptrs, colinds);
817 std::ostringstream os;
818 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
819 <<
"Call AddKern::addUnsorted(...)" << std::endl;
820 std::cerr << os.str();
822 AddKern::addUnsorted(Avals, Arowptrs, Acolinds, alpha, Bvals, Browptrs, Bcolinds, beta, Aprime->getGlobalNumCols(), vals, rowptrs, colinds);
825 RCP<const map_type> Ccolmap = Bcolmap;
828 if (doFillComplete) {
831 if (!CDomainMap->isSameAs(*Ccolmap)) {
833 std::ostringstream os;
834 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
835 <<
"Create Cimport" << std::endl;
836 std::cerr << os.str();
838 Cimport = rcp(
new import_type(CDomainMap, Ccolmap));
840 if (!C.
getRowMap()->isSameAs(*CRangeMap)) {
842 std::ostringstream os;
843 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
844 <<
"Create Cexport" << std::endl;
845 std::cerr << os.str();
851 std::ostringstream os;
852 os <<
"Proc " << A.
getMap()->getComm()->getRank() <<
": "
853 <<
"Call C->expertStaticFillComplete(...)" << std::endl;
854 std::cerr << os.str();
863template <
class Scalar,
876 using Teuchos::Array;
877 using Teuchos::ArrayRCP;
878 using Teuchos::ArrayView;
881 using Teuchos::rcp_dynamic_cast;
882 using Teuchos::rcpFromRef;
883 using Teuchos::tuple;
885 typedef Teuchos::ScalarTraits<Scalar> STS;
893 std::string prefix =
"TpetraExt::MatrixMatrix::Add(): ";
895 TEUCHOS_TEST_FOR_EXCEPTION(
897 prefix <<
"A and B must both be fill complete before calling this function.");
901 prefix <<
"C is null (must be allocated), but A.haveGlobalConstants() is false. "
902 "Please report this bug to the Tpetra developers.");
904 prefix <<
"C is null (must be allocated), but B.haveGlobalConstants() is false. "
905 "Please report this bug to the Tpetra developers.");
908#ifdef HAVE_TPETRA_DEBUG
910 const bool domainMapsSame =
914 TEUCHOS_TEST_FOR_EXCEPTION(domainMapsSame, std::invalid_argument,
915 prefix <<
"The domain Maps of Op(A) and Op(B) are not the same.");
917 const bool rangeMapsSame =
921 TEUCHOS_TEST_FOR_EXCEPTION(rangeMapsSame, std::invalid_argument,
922 prefix <<
"The range Maps of Op(A) and Op(B) are not the same.");
926 using Teuchos::ParameterList;
927 RCP<ParameterList> transposeParams(
new ParameterList);
928 transposeParams->set(
"sort",
false);
931 RCP<const crs_matrix_type> Aprime;
933 transposer_type theTransposer(rcpFromRef(A));
934 Aprime = theTransposer.createTranspose(transposeParams);
936 Aprime = rcpFromRef(A);
939#ifdef HAVE_TPETRA_DEBUG
940 TEUCHOS_TEST_FOR_EXCEPTION(Aprime.is_null(), std::logic_error,
941 prefix <<
"Failed to compute Op(A). Please report this bug to the Tpetra developers.");
945 RCP<const crs_matrix_type> Bprime;
947 transposer_type theTransposer(rcpFromRef(B));
948 Bprime = theTransposer.createTranspose(transposeParams);
950 Bprime = rcpFromRef(B);
953#ifdef HAVE_TPETRA_DEBUG
954 TEUCHOS_TEST_FOR_EXCEPTION(Bprime.is_null(), std::logic_error,
955 prefix <<
"Failed to compute Op(B). Please report this bug to the Tpetra developers.");
958 bool CwasFillComplete =
false;
962 CwasFillComplete = C->isFillComplete();
963 if (CwasFillComplete)
965 C->setAllToScalar(STS::zero());
975 if (Aprime->getRowMap()->isSameAs(*Bprime->getRowMap())) {
976 LocalOrdinal numLocalRows = Aprime->getLocalNumRows();
977 Array<size_t> CmaxEntriesPerRow(numLocalRows);
978 for (LocalOrdinal i = 0; i < numLocalRows; i++) {
979 CmaxEntriesPerRow[i] = Aprime->getNumEntriesInLocalRow(i) + Bprime->getNumEntriesInLocalRow(i);
981 C = rcp(
new crs_matrix_type(Aprime->getRowMap(), CmaxEntriesPerRow()));
984 C = rcp(
new crs_matrix_type(Aprime->getRowMap(), Aprime->getGlobalMaxNumRowEntries() + Bprime->getGlobalMaxNumRowEntries()));
988#ifdef HAVE_TPETRA_DEBUG
989 TEUCHOS_TEST_FOR_EXCEPTION(Aprime.is_null(), std::logic_error,
990 prefix <<
"At this point, Aprime is null. Please report this bug to the Tpetra developers.");
991 TEUCHOS_TEST_FOR_EXCEPTION(Bprime.is_null(), std::logic_error,
992 prefix <<
"At this point, Bprime is null. Please report this bug to the Tpetra developers.");
993 TEUCHOS_TEST_FOR_EXCEPTION(C.is_null(), std::logic_error,
994 prefix <<
"At this point, C is null. Please report this bug to the Tpetra developers.");
997 Array<RCP<const crs_matrix_type>> Mat =
998 tuple<RCP<const crs_matrix_type>>(Aprime, Bprime);
999 Array<Scalar> scalar = tuple<Scalar>(scalarA, scalarB);
1002 for (
int k = 0; k < 2; ++k) {
1003 typename crs_matrix_type::nonconst_global_inds_host_view_type Indices;
1004 typename crs_matrix_type::nonconst_values_host_view_type Values;
1012#ifdef HAVE_TPETRA_DEBUG
1013 TEUCHOS_TEST_FOR_EXCEPTION(Mat[k].is_null(), std::logic_error,
1014 prefix <<
"At this point, curRowMap is null. Please report this bug to the Tpetra developers.");
1016 RCP<const map_type> curRowMap = Mat[k]->getRowMap();
1017#ifdef HAVE_TPETRA_DEBUG
1018 TEUCHOS_TEST_FOR_EXCEPTION(curRowMap.is_null(), std::logic_error,
1019 prefix <<
"At this point, curRowMap is null. Please report this bug to the Tpetra developers.");
1022 const size_t localNumRows = Mat[k]->getLocalNumRows();
1023 for (
size_t i = 0; i < localNumRows; ++i) {
1024 const GlobalOrdinal globalRow = curRowMap->getGlobalElement(i);
1025 size_t numEntries = Mat[k]->getNumEntriesInGlobalRow(globalRow);
1026 if (numEntries > 0) {
1027 if (numEntries > Indices.extent(0)) {
1028 Kokkos::resize(Indices, numEntries);
1029 Kokkos::resize(Values, numEntries);
1031 Mat[k]->getGlobalRowCopy(globalRow, Indices, Values, numEntries);
1033 if (scalar[k] != STS::one()) {
1034 for (
size_t j = 0; j < numEntries; ++j) {
1035 Values[j] *= scalar[k];
1039 if (CwasFillComplete) {
1040 size_t result = C->sumIntoGlobalValues(globalRow, numEntries,
1041 reinterpret_cast<Scalar*
>(Values.data()), Indices.data());
1042 TEUCHOS_TEST_FOR_EXCEPTION(result != numEntries, std::logic_error,
1043 prefix <<
"sumIntoGlobalValues failed to add entries from A or B into C.");
1045 C->insertGlobalValues(globalRow, numEntries,
1046 reinterpret_cast<Scalar*
>(Values.data()), Indices.data());
1051 if (CwasFillComplete) {
1052 C->fillComplete(C->getDomainMap(),
1059template <
class Scalar,
1061 class GlobalOrdinal,
1071 std::string prefix =
"TpetraExt::MatrixMatrix::Add(): ";
1073 TEUCHOS_TEST_FOR_EXCEPTION(C.is_null(), std::invalid_argument,
1074 prefix <<
"C must not be null");
1076 Teuchos::RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> C_ = C;
1077 Add(A, transposeA, scalarA, B, transposeB, scalarB, C_);
1082namespace MMdetails {
1088struct CrsMatrixApplyHelperAccess {
1089 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1090 static auto get(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& matrix) {
1091 return matrix.getApplyHelper();
1095template <
class Scalar,
1097 class GlobalOrdinal,
1099 class LocalOrdinalViewType>
1100void kokkos_kernels_mult_A_B_newmatrix(
1101 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1102 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1103 const LocalOrdinalViewType& Acol2Brow,
1104 const LocalOrdinalViewType& Acol2Irow,
1105 const LocalOrdinalViewType& Bcol2Ccol,
1106 const LocalOrdinalViewType& Icol2Ccol,
1107 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1108 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1109 const std::string& label,
1110 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1111 using backend_type = KokkosKernelsSPGEMMBackend<Node>;
1116 using device_t =
typename KCRS::device_type;
1117 using graph_t =
typename KCRS::StaticCrsGraphType;
1118 using lno_view_t =
typename graph_t::row_map_type::non_const_type;
1119 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>;
1120 using lno_nnz_view_t =
typename graph_t::entries_type::non_const_type;
1121 using scalar_view_t =
typename KCRS::values_type::non_const_type;
1122 using KernelHandle = KokkosKernels::Experimental::KokkosKernelsHandle<
1123 typename lno_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1124 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1125 using IntKernelHandle = KokkosKernels::Experimental::KokkosKernelsHandle<
1126 typename int_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1127 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1130 const std::string wrapperLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"Wrapper";
1131 RCP<Tpetra::Details::ProfilingRegion> MM =
1132 rcp(
new Tpetra::Details::ProfilingRegion(wrapperLabel));
1134 bool spgemm_options_customized =
false;
1135 int team_work_size = 16;
1136 std::string myalg(
"SPGEMM_DEFAULT");
1137 if (!params.is_null()) {
1138 const std::string prefixedAlg = backend_type::parameter_prefix() +
": algorithm";
1139 const std::string prefixedTeam = backend_type::parameter_prefix() +
": team work size";
1140 if (params->isParameter(prefixedAlg))
1141 myalg = params->get(prefixedAlg, myalg);
1142 if (params->isParameter(prefixedTeam)) {
1143 team_work_size = params->get(prefixedTeam, team_work_size);
1144 spgemm_options_customized =
true;
1147#if KOKKOSKERNELS_VERSION < 50299
1148 (void)spgemm_options_customized;
1151 const KCRS Amat = Aview.origMatrix->getLocalMatrixDevice();
1153 const std::string genericAlg = backend_type::algorithm_label() +
" algorithm";
1154 if (!params.is_null() && params->isParameter(genericAlg))
1155 myalg = params->get(genericAlg, myalg);
1156 KokkosSparse::SPGEMMAlgorithm alg_enum = KokkosSparse::StringToSPGEMMAlgorithm(myalg);
1158 KCRS Bmerged = Tpetra::MMdetails::merge_matrices(
1159 Aview, Bview, Acol2Brow, Acol2Irow, Bcol2Ccol, Icol2Ccol, C.getColMap()->getLocalNumElements());
1163#if KOKKOSKERNELS_VERSION >= 50299
1169 const bool input_sorted =
1170 Aview.origMatrix->getCrsGraph()->isSorted() &&
1171 (Bview.importMatrix.is_null() && Bview.origMatrix->getCrsGraph()->isSorted());
1173 const bool result_sorted =
true;
1178 if (!spgemm_options_customized) {
1179 const std::string coreLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"Core";
1181 MM = rcp(
new Tpetra::Details::ProfilingRegion(coreLabel));
1183 Tpetra::Details::IntRowPtrHelper<
decltype(Bmerged)> irph(Bmerged.nnz(), Bmerged.graph.row_map);
1184 const bool useIntRowptrs =
1185 irph.shouldUseIntRowptrs() &&
1186 CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->shouldUseIntRowptrs();
1188 if (useIntRowptrs) {
1191 auto Aint = CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->getIntRowptrMatrix(Amat);
1192 auto Bint = irph.getIntRowptrMatrix(Bmerged);
1193 using int_matrix_t =
decltype(Bint);
1195 int_matrix_t Cint = KokkosSparse::spgemm<int_matrix_t>(
1196 alg_enum, Aint,
false, Bint,
false, input_sorted, result_sorted);
1198 auto int_row_mapC = Cint.graph.row_map;
1199 lno_view_t row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"non_const_lno_row"), int_row_mapC.extent(0));
1200 Kokkos::parallel_for(
1201 Kokkos::RangePolicy<typename device_t::execution_space>(0, int_row_mapC.extent(0)),
1202 KOKKOS_LAMBDA(
const int i) { row_mapC(i) = int_row_mapC(i); });
1203 Cmat = KCRS(
"C", Cint.numRows(), Cint.numCols(), Cint.nnz(), Cint.values, row_mapC, Cint.graph.entries);
1205 Cmat = KokkosSparse::spgemm<KCRS>(
1206 alg_enum, Amat,
false, Bmerged,
false, input_sorted, result_sorted);
1211 backend_type::pre_spgemm(*Aview.origMatrix);
1212 backend_type::pre_spgemm(Bmerged);
1214 const std::string coreLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"Core";
1216 MM = rcp(
new Tpetra::Details::ProfilingRegion(coreLabel));
1218 Tpetra::Details::IntRowPtrHelper<
decltype(Bmerged)> irph(Bmerged.nnz(), Bmerged.graph.row_map);
1219 const bool useIntRowptrs =
1220 irph.shouldUseIntRowptrs() &&
1221 CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->shouldUseIntRowptrs();
1223 if (useIntRowptrs) {
1224 typename KernelHandle::nnz_lno_t AnumRows = Amat.numRows();
1225 typename KernelHandle::nnz_lno_t BnumRows = Bmerged.numRows();
1226 typename KernelHandle::nnz_lno_t BnumCols = Bmerged.numCols();
1228 lno_view_t row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"non_const_lno_row"), AnumRows + 1);
1229 lno_nnz_view_t entriesC;
1230 scalar_view_t valuesC;
1233#if KOKKOSKERNELS_VERSION >= 50299
1234 kh.create_spgemm_handle(alg_enum, input_sorted, result_sorted);
1236 kh.create_spgemm_handle(alg_enum);
1238 kh.set_team_work_size(team_work_size);
1240 int_view_t int_row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"non_const_int_row"), AnumRows + 1);
1242 auto Aint = CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->getIntRowptrMatrix(Amat);
1243 auto Bint = irph.getIntRowptrMatrix(Bmerged);
1246 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: MMM: Newmatrix KokkosKernels symbolic int");
1247 KokkosSparse::spgemm_symbolic(
1248 &kh, AnumRows, BnumRows, BnumCols, Aint.graph.row_map, Aint.graph.entries,
false, Bint.graph.row_map, Bint.graph.entries,
false, int_row_mapC);
1251 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: MMM: Newmatrix KokkosKernels numeric int");
1252 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1254 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1255 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1257 KokkosSparse::spgemm_numeric(
1258 &kh, AnumRows, BnumRows, BnumCols, Aint.graph.row_map, Aint.graph.entries, Aint.values,
false,
1259 Bint.graph.row_map, Bint.graph.entries, Bint.values,
false, int_row_mapC, entriesC, valuesC);
1260 Kokkos::parallel_for(
1261 Kokkos::RangePolicy<typename device_t::execution_space>(0, int_row_mapC.size()),
1262 KOKKOS_LAMBDA(
const int i) { row_mapC(i) = int_row_mapC(i); });
1263 kh.destroy_spgemm_handle();
1264 Cmat = KCRS(
"C", AnumRows, BnumCols, c_nnz_size, valuesC, row_mapC, entriesC);
1267#if KOKKOSKERNELS_VERSION >= 50299
1268 kh.create_spgemm_handle(alg_enum, input_sorted, result_sorted);
1270 kh.create_spgemm_handle(alg_enum);
1272 kh.set_team_work_size(team_work_size);
1275 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: MMM: Newmatrix KokkosKernels symbolic non-int");
1276 KokkosSparse::spgemm_symbolic(kh, Amat,
false, Bmerged,
false, Cmat);
1279 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: MMM: Newmatrix KokkosKernels numeric non-int");
1280 KokkosSparse::spgemm_numeric(kh, Amat,
false, Bmerged,
false, Cmat);
1281 kh.destroy_spgemm_handle();
1285#if KOKKOSKERNELS_VERSION < 50299
1290 TEUCHOS_TEST_FOR_EXCEPTION(!KokkosSparse::Impl::isCrsGraphSorted(Cmat.graph.row_map, Cmat.graph.entries),
1292 "KokkosKernels spgemm_numeric did not produce sorted output as expected!");
1298 C.setAllValues(Cmat);
1300 const std::string esfcLabel =
"TpetraExt: MMM: Newmatrix " + backend_type::algorithm_label() +
"ESFC";
1302 MM = rcp(
new Tpetra::Details::ProfilingRegion(esfcLabel));
1304 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
1305 labelList->set(
"Timer Label", label);
1306 if (!params.is_null())
1307 labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
1308 RCP<const Export<LocalOrdinal, GlobalOrdinal, Node>> dummyExport;
1309 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
1310 TEUCHOS_TEST_FOR_EXCEPTION(!C.getCrsGraph()->isSorted(), std::runtime_error,
1311 "TpetraExt: kokkos_kernels_mult_A_B_newmatrix: result C does not have a sorted CrsGraph.");
1314template <
class Scalar,
1316 class GlobalOrdinal,
1318 class LocalOrdinalViewType>
1319void host_mult_A_B_reuse(
1320 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1321 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1322 const LocalOrdinalViewType& targetMapToOrigRow_dev,
1323 const LocalOrdinalViewType& targetMapToImportRow_dev,
1324 const LocalOrdinalViewType& Bcol2Ccol_dev,
1325 const LocalOrdinalViewType& Icol2Ccol_dev,
1326 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1327 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1328 const std::string& label,
1329 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1337 bool throwOnInsert =
true;
1338 if (!params.is_null() && params->isType<
bool>(
"MM Throw For Non-Existent Entries"))
1339 throwOnInsert = params->get<
bool>(
"MM Throw For Non-Existent Entries");
1341 RCP<Tpetra::Details::ProfilingRegion> MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM: Reuse SerialCore"));
1344 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
1345 typedef typename KCRS::StaticCrsGraphType graph_t;
1346 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
1347 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1348 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1351 typedef LocalOrdinal LO;
1352 typedef GlobalOrdinal GO;
1354 typedef Map<LO, GO, NO> map_type;
1355 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1356 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1357 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
1365 auto targetMapToOrigRow =
1366 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1367 targetMapToOrigRow_dev);
1368 auto targetMapToImportRow =
1369 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1370 targetMapToImportRow_dev);
1372 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1375 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1379 RCP<const map_type> Ccolmap = C.getColMap();
1380 size_t m = Aview.origMatrix->getLocalNumRows();
1381 size_t n = Ccolmap->getLocalNumElements();
1384 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
1385 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
1386 const KCRS Cmat = C.getLocalMatrixHost();
1388 c_lno_view_t Arowptr = Amat.graph.row_map,
1389 Browptr = Bmat.graph.row_map,
1390 Crowptr = Cmat.graph.row_map;
1391 const lno_nnz_view_t Acolind = Amat.graph.entries,
1392 Bcolind = Bmat.graph.entries,
1393 Ccolind = Cmat.graph.entries;
1394 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
1395 scalar_view_t Cvals = Cmat.values;
1397 c_lno_view_t Irowptr;
1398 lno_nnz_view_t Icolind;
1399 scalar_view_t Ivals;
1400 if (!Bview.importMatrix.is_null()) {
1401 auto lclB = Bview.importMatrix->getLocalMatrixHost();
1402 Irowptr = lclB.graph.row_map;
1403 Icolind = lclB.graph.entries;
1404 Ivals = lclB.values;
1416 std::vector<size_t> c_status(n, ST_INVALID);
1419 size_t CSR_ip = 0, OLD_ip = 0;
1420 for (
size_t i = 0; i < m; i++) {
1423 OLD_ip = Crowptr[i];
1424 CSR_ip = Crowptr[i + 1];
1425 for (
size_t k = OLD_ip; k < CSR_ip; k++) {
1426 c_status[Ccolind[k]] = k;
1432 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
1433 LO Aik = Acolind[k];
1434 const SC Aval = Avals[k];
1435 if (Aval == SC_ZERO)
1438 if (targetMapToOrigRow[Aik] != LO_INVALID) {
1440 size_t Bk = Teuchos::as<size_t>(targetMapToOrigRow[Aik]);
1442 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
1443 LO Bkj = Bcolind[j];
1444 LO Cij = Bcol2Ccol[Bkj];
1446 const bool badInsert = (Cij == LO_INVALID) || (c_status[Cij] < OLD_ip) || (c_status[Cij] >= CSR_ip);
1448 Cvals[c_status[Cij]] += Aval * Bvals[j];
1449 else if (throwOnInsert)
1450 TEUCHOS_TEST_FOR_EXCEPTION(badInsert,
1451 std::runtime_error,
"Trying to insert a new entry (" << i <<
"," << Cij <<
") into a static graph "
1452 <<
"(c_status = " << c_status[Cij] <<
" of [" << OLD_ip <<
"," << CSR_ip <<
"))");
1457 size_t Ik = Teuchos::as<size_t>(targetMapToImportRow[Aik]);
1458 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
1459 LO Ikj = Icolind[j];
1460 LO Cij = Icol2Ccol[Ikj];
1462 const bool badInsert = (Cij == LO_INVALID) || (c_status[Cij] < OLD_ip) || (c_status[Cij] >= CSR_ip);
1464 Cvals[c_status[Cij]] += Aval * Ivals[j];
1465 else if (throwOnInsert)
1466 TEUCHOS_TEST_FOR_EXCEPTION(badInsert,
1467 std::runtime_error,
"Trying to insert a new entry (" << i <<
"," << Cij <<
") into a static graph "
1468 <<
"(c_status = " << c_status[Cij] <<
" of [" << OLD_ip <<
"," << CSR_ip <<
"))");
1474 C.fillComplete(C.getDomainMap(), C.getRangeMap());
1477template <
class Scalar,
1479 class GlobalOrdinal,
1481 class LocalOrdinalViewType>
1482void kokkos_kernels_jacobi_A_B_newmatrix(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
1483 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
1484 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1485 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1486 const LocalOrdinalViewType& Acol2Brow,
1487 const LocalOrdinalViewType& Acol2Irow,
1488 const LocalOrdinalViewType& Bcol2Ccol,
1489 const LocalOrdinalViewType& Icol2Ccol,
1490 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1491 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1492 const std::string& label,
1493 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1494 using backend_type = KokkosKernelsSPGEMMBackend<Node>;
1498 auto rowMap = Aview.origMatrix->getRowMap();
1499 Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> diags(rowMap);
1500 Aview.origMatrix->getLocalDiagCopy(diags);
1501 size_t diagLength = rowMap->getLocalNumElements();
1502 Teuchos::Array<Scalar> diagonal(diagLength);
1503 diags.get1dCopy(diagonal());
1505 for (
size_t i = 0; i < diagLength; ++i) {
1506 TEUCHOS_TEST_FOR_EXCEPTION(diagonal[i] == Teuchos::ScalarTraits<Scalar>::zero(),
1508 "Matrix A has a zero/missing diagonal: " << diagonal[i] << std::endl
1509 <<
"KokkosKernels Jacobi-fused SpGEMM requires nonzero diagonal entries in A" << std::endl);
1515 RCP<Tpetra::Details::ProfilingRegion> MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: Jacobi: Newmatrix KokkosKernels"));
1518 using device_t =
typename Node::device_type;
1520 using graph_t =
typename matrix_t::StaticCrsGraphType;
1521 using lno_view_t =
typename graph_t::row_map_type::non_const_type;
1522 using int_view_t = Kokkos::View<
int*,
1523 typename lno_view_t::array_layout,
1524 typename lno_view_t::memory_space,
1525 typename lno_view_t::memory_traits>;
1526 using lno_nnz_view_t =
typename graph_t::entries_type::non_const_type;
1527 using scalar_view_t =
typename matrix_t::values_type::non_const_type;
1530 using handle_t =
typename KokkosKernels::Experimental::KokkosKernelsHandle<
1531 typename lno_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1532 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1534 using int_handle_t =
typename KokkosKernels::Experimental::KokkosKernelsHandle<
1535 typename int_view_t::const_value_type,
typename lno_nnz_view_t::const_value_type,
typename scalar_view_t::const_value_type,
1536 typename device_t::execution_space,
typename device_t::memory_space,
typename device_t::memory_space>;
1539 const matrix_t Bmerged = Tpetra::MMdetails::merge_matrices(Aview, Bview, Acol2Brow, Acol2Irow, Bcol2Ccol, Icol2Ccol, C.getColMap()->getLocalNumElements());
1542 const matrix_t Amat = Aview.origMatrix->getLocalMatrixDevice();
1543 const matrix_t Bmat = Bview.origMatrix->getLocalMatrixDevice();
1545 typename handle_t::nnz_lno_t AnumRows = Amat.numRows();
1546 typename handle_t::nnz_lno_t BnumRows = Bmerged.numRows();
1547 typename handle_t::nnz_lno_t BnumCols = Bmerged.numCols();
1550 lno_view_t row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"row_mapC"), AnumRows + 1);
1551 lno_nnz_view_t entriesC;
1552 scalar_view_t valuesC;
1555 int team_work_size = 16;
1556 std::string myalg(
"SPGEMM_DEFAULT");
1557 if (!params.is_null()) {
1558 const std::string prefixedAlg = backend_type::parameter_prefix() +
": algorithm";
1559 const std::string prefixedTeam = backend_type::parameter_prefix() +
": team work size";
1560 if (params->isParameter(prefixedAlg))
1561 myalg = params->get(prefixedAlg, myalg);
1562 if (params->isParameter(prefixedTeam))
1563 team_work_size = params->get(prefixedTeam, team_work_size);
1567 const std::string genericAlg = backend_type::algorithm_label() +
" algorithm";
1568 if (!params.is_null() && params->isParameter(genericAlg))
1569 myalg = params->get(genericAlg, myalg);
1570 KokkosSparse::SPGEMMAlgorithm alg_enum = KokkosSparse::StringToSPGEMMAlgorithm(myalg);
1575 Tpetra::Details::IntRowPtrHelper<
decltype(Bmerged)> irph(Bmerged.nnz(), Bmerged.graph.row_map);
1576#if KOKKOSKERNELS_VERSION >= 50299
1577 const bool useIntRowptrs =
1578 irph.shouldUseIntRowptrs() &&
1579 CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->shouldUseIntRowptrs();
1581 const bool useIntRowptrs =
1582 irph.shouldUseIntRowptrs() &&
1583 CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->shouldUseIntRowptrs() &&
1584 KokkosSparse::isCrsGraphSorted(Amat.graph.row_map, Amat.graph.entries) &&
1585 KokkosSparse::isCrsGraphSorted(Bmerged.graph.row_map, Bmerged.graph.entries);
1588 const Scalar jacobiOmega = omega * Teuchos::ScalarTraits<Scalar>::one();
1590#if KOKKOSKERNELS_VERSION >= 50299
1596 const bool input_sorted =
1597 Aview.origMatrix->getCrsGraph()->isSorted() &&
1598 (Bview.importMatrix.is_null() && Bview.origMatrix->getCrsGraph()->isSorted());
1600 const bool result_sorted =
true;
1603 if (useIntRowptrs) {
1605#if KOKKOSKERNELS_VERSION >= 50299
1606 kh.create_spgemm_handle(alg_enum, input_sorted, result_sorted);
1608 kh.create_spgemm_handle(alg_enum);
1610 kh.set_team_work_size(team_work_size);
1612 int_view_t int_row_mapC(Kokkos::ViewAllocateWithoutInitializing(
"int_row_mapC"), AnumRows + 1);
1614 auto Aint = CrsMatrixApplyHelperAccess::get(*Aview.origMatrix)->getIntRowptrMatrix(Amat);
1615 auto Bint = irph.getIntRowptrMatrix(Bmerged);
1618 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: Jacobi: KokkosKernels symbolic int");
1619 KokkosSparse::spgemm_symbolic(&kh, AnumRows, BnumRows, BnumCols,
1620 Aint.graph.row_map, Aint.graph.entries,
false,
1621 Bint.graph.row_map, Bint.graph.entries,
false,
1625 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1627 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1628 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1630 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: Jacobi: KokkosKernels numeric int");
1635 KokkosSparse::Experimental::spgemm_jacobi(&kh, AnumRows, BnumRows, BnumCols,
1636 Aint.graph.row_map, Aint.graph.entries, Amat.values,
false,
1637 Bint.graph.row_map, Bint.graph.entries, Bint.values,
false,
1638 int_row_mapC, entriesC, valuesC,
1639 jacobiOmega, Dinv.getLocalViewDevice(Access::ReadOnly));
1642 Kokkos::parallel_for(
1643 Kokkos::RangePolicy<typename device_t::execution_space>(0, int_row_mapC.size()),
1644 KOKKOS_LAMBDA(
int i) { row_mapC(i) = int_row_mapC(i); });
1645 kh.destroy_spgemm_handle();
1648#if KOKKOSKERNELS_VERSION >= 50299
1649 kh.create_spgemm_handle(alg_enum, input_sorted, result_sorted);
1651 kh.create_spgemm_handle(alg_enum);
1653 kh.set_team_work_size(team_work_size);
1656 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: Jacobi: KokkosKernels symbolic non-int");
1657 KokkosSparse::spgemm_symbolic(&kh, AnumRows, BnumRows, BnumCols,
1658 Amat.graph.row_map, Amat.graph.entries,
false,
1659 Bmerged.graph.row_map, Bmerged.graph.entries,
false,
1663 size_t c_nnz_size = kh.get_spgemm_handle()->get_c_nnz();
1665 entriesC = lno_nnz_view_t(Kokkos::ViewAllocateWithoutInitializing(
"entriesC"), c_nnz_size);
1666 valuesC = scalar_view_t(Kokkos::ViewAllocateWithoutInitializing(
"valuesC"), c_nnz_size);
1669 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: Jacobi: KokkosKernels numeric non-int");
1671 KokkosSparse::Experimental::spgemm_jacobi(&kh, AnumRows, BnumRows, BnumCols,
1672 Amat.graph.row_map, Amat.graph.entries, Amat.values,
false,
1673 Bmerged.graph.row_map, Bmerged.graph.entries, Bmerged.values,
false,
1674 row_mapC, entriesC, valuesC,
1675 jacobiOmega, Dinv.getLocalViewDevice(Access::ReadOnly));
1677 kh.destroy_spgemm_handle();
1680#if KOKKOSKERNELS_VERSION < 50299
1685 TEUCHOS_TEST_FOR_EXCEPTION(!KokkosSparse::Impl::isCrsGraphSorted(row_mapC, entriesC),
1687 "KokkosKernels spgemm_jacobi did not produce sorted output!");
1691 C.setAllValues(row_mapC, entriesC, valuesC);
1693 const std::string esfcLabel =
"TpetraExt: Jacobi: Newmatrix " + backend_type::algorithm_label() +
"ESFC";
1695 MM = rcp(
new Tpetra::Details::ProfilingRegion(esfcLabel));
1698 Teuchos::RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
1699 labelList->set(
"Timer Label", label);
1700 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
1701 Teuchos::RCP<const Export<LocalOrdinal, GlobalOrdinal, Node>> dummyExport;
1702 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
1703 TEUCHOS_TEST_FOR_EXCEPTION(!C.getCrsGraph()->isSorted(), std::runtime_error,
1704 "TpetraExt: kokkos_kernels_jacobi_A_B_newmatrix: result C does not have a sorted CrsGraph.");
1707template <
class Scalar,
1709 class GlobalOrdinal,
1711 class LocalOrdinalViewType>
1712void host_jacobi_A_B_reuse(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
1713 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
1714 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1715 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
1716 const LocalOrdinalViewType& targetMapToOrigRow_dev,
1717 const LocalOrdinalViewType& targetMapToImportRow_dev,
1718 const LocalOrdinalViewType& Bcol2Ccol_dev,
1719 const LocalOrdinalViewType& Icol2Ccol_dev,
1720 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1721 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
1722 const std::string& label,
1723 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1727 RCP<Tpetra::Details::ProfilingRegion> MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: Jacobi: Reuse CudaCore"));
1730 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
1731 typedef typename KCRS::StaticCrsGraphType graph_t;
1732 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
1733 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1734 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1735 typedef typename scalar_view_t::memory_space scalar_memory_space;
1738 typedef LocalOrdinal LO;
1739 typedef GlobalOrdinal GO;
1741 typedef Map<LO, GO, NO> map_type;
1742 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1743 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1744 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
1752 auto targetMapToOrigRow =
1753 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1754 targetMapToOrigRow_dev);
1755 auto targetMapToImportRow =
1756 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1757 targetMapToImportRow_dev);
1759 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1762 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1766 RCP<const map_type> Ccolmap = C.getColMap();
1767 size_t m = Aview.origMatrix->getLocalNumRows();
1768 size_t n = Ccolmap->getLocalNumElements();
1771 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
1772 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
1773 const KCRS Cmat = C.getLocalMatrixHost();
1775 c_lno_view_t Arowptr = Amat.graph.row_map, Browptr = Bmat.graph.row_map, Crowptr = Cmat.graph.row_map;
1776 const lno_nnz_view_t Acolind = Amat.graph.entries, Bcolind = Bmat.graph.entries, Ccolind = Cmat.graph.entries;
1777 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
1778 scalar_view_t Cvals = Cmat.values;
1780 c_lno_view_t Irowptr;
1781 lno_nnz_view_t Icolind;
1782 scalar_view_t Ivals;
1783 if (!Bview.importMatrix.is_null()) {
1784 auto lclB = Bview.importMatrix->getLocalMatrixHost();
1785 Irowptr = lclB.graph.row_map;
1786 Icolind = lclB.graph.entries;
1787 Ivals = lclB.values;
1792 Dinv.template getLocalView<scalar_memory_space>(Access::ReadOnly);
1799 std::vector<size_t> c_status(n, ST_INVALID);
1802 size_t CSR_ip = 0, OLD_ip = 0;
1803 for (
size_t i = 0; i < m; i++) {
1806 OLD_ip = Crowptr[i];
1807 CSR_ip = Crowptr[i + 1];
1808 for (
size_t k = OLD_ip; k < CSR_ip; k++) {
1809 c_status[Ccolind[k]] = k;
1815 SC minusOmegaDval = -omega * Dvals(i, 0);
1818 for (
size_t j = Browptr[i]; j < Browptr[i + 1]; j++) {
1819 Scalar Bval = Bvals[j];
1820 if (Bval == SC_ZERO)
1822 LO Bij = Bcolind[j];
1823 LO Cij = Bcol2Ccol[Bij];
1825 TEUCHOS_TEST_FOR_EXCEPTION(c_status[Cij] < OLD_ip || c_status[Cij] >= CSR_ip,
1826 std::runtime_error,
"Trying to insert a new entry into a static graph");
1828 Cvals[c_status[Cij]] = Bvals[j];
1832 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
1833 LO Aik = Acolind[k];
1834 const SC Aval = Avals[k];
1835 if (Aval == SC_ZERO)
1838 if (targetMapToOrigRow[Aik] != LO_INVALID) {
1840 size_t Bk = Teuchos::as<size_t>(targetMapToOrigRow[Aik]);
1842 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
1843 LO Bkj = Bcolind[j];
1844 LO Cij = Bcol2Ccol[Bkj];
1846 TEUCHOS_TEST_FOR_EXCEPTION(c_status[Cij] < OLD_ip || c_status[Cij] >= CSR_ip,
1847 std::runtime_error,
"Trying to insert a new entry into a static graph");
1849 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Bvals[j];
1854 size_t Ik = Teuchos::as<size_t>(targetMapToImportRow[Aik]);
1855 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
1856 LO Ikj = Icolind[j];
1857 LO Cij = Icol2Ccol[Ikj];
1859 TEUCHOS_TEST_FOR_EXCEPTION(c_status[Cij] < OLD_ip || c_status[Cij] >= CSR_ip,
1860 std::runtime_error,
"Trying to insert a new entry into a static graph");
1862 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Ivals[j];
1869 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: Jacobi: Reuse ESFC"));
1871 C.fillComplete(C.getDomainMap(), C.getRangeMap());
1924template <
class Scalar,
1926 class GlobalOrdinal,
1928void mult_AT_B_newmatrix(
1929 const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
1930 const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& B,
1931 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
1932 const std::string& label,
1933 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1937 typedef LocalOrdinal LO;
1938 typedef GlobalOrdinal GO;
1940 typedef CrsMatrixStruct<SC, LO, GO, NO> crs_matrix_struct_type;
1941 typedef RowMatrixTransposer<SC, LO, GO, NO> transposer_type;
1943 RCP<Tpetra::Details::ProfilingRegion> MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM-T: Transpose"));
1948 transposer_type transposer(rcpFromRef(A), label + std::string(
"XP: "));
1950 using Teuchos::ParameterList;
1951 RCP<ParameterList> transposeParams(
new ParameterList);
1952 transposeParams->set(
"sort",
true);
1953 if (!params.is_null()) {
1954 transposeParams->set(
"compute global constants",
1955 params->get(
"compute global constants: temporaries",
1958 RCP<Tpetra::CrsMatrix<SC, LO, GO, NO>> Atrans =
1959 transposer.createTransposeLocal(transposeParams);
1965 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM-T: I&X"));
1968 crs_matrix_struct_type Aview;
1969 crs_matrix_struct_type Bview;
1970 RCP<const Import<LO, GO, NO>> dummyImporter;
1973 RCP<Teuchos::ParameterList> importParams = Teuchos::rcp(
new ParameterList);
1974 importParams->set(
"compute global constants",
false);
1975 if (!params.is_null()) {
1976 importParams->setParameters(*params);
1977 if (params->isParameter(
"compute global constants: temporaries"))
1978 importParams->set(
"compute global constants",
1979 params->get<
bool>(
"compute global constants: temporaries"));
1981 MMdetails::import_and_extract_views(*Atrans, Atrans->getRowMap(),
1982 Aview, dummyImporter,
true,
1983 label, importParams);
1985 if (B.getRowMap()->isSameAs(*Atrans->getColMap())) {
1986 MMdetails::import_and_extract_views(B, B.getRowMap(), Bview, dummyImporter,
true, label, importParams);
1988 MMdetails::import_and_extract_views(B, Atrans->getColMap(), Bview, dummyImporter,
false, label, importParams);
1992 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM-T: AB-core"));
1994 RCP<Tpetra::CrsMatrix<SC, LO, GO, NO>> Ctemp;
1997 bool needs_final_export = !Atrans->getGraph()->getExporter().is_null();
1998 if (needs_final_export) {
1999 Ctemp = rcp(
new Tpetra::CrsMatrix<SC, LO, GO, NO>(Atrans->getRowMap(), 0));
2001 Ctemp = rcp(&C,
false);
2004 RCP<Teuchos::ParameterList> multParams = Teuchos::rcp(
new ParameterList);
2005 if (!params.is_null()) {
2006 multParams->setParameters(*params);
2008 multParams->set(
"compute global constants", !needs_final_export);
2009 mult_A_B_newmatrix(Aview, Bview, *Ctemp, label, multParams);
2015 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM-T: exportAndFillComplete"));
2017 RCP<Tpetra::CrsMatrix<SC, LO, GO, NO>> Crcp(&C,
false);
2019 if (needs_final_export) {
2020 ParameterList labelList;
2021 labelList.set(
"Timer Label", label);
2022 if (!params.is_null()) {
2023 labelList.setParameters(*params);
2025 ParameterList& labelList_subList = labelList.sublist(
"matrixmatrix: kernel params",
false);
2026 labelList_subList.set(
"isMatrixMatrix_TransferAndFillComplete",
true,
2027 "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.");
2029 Ctemp->exportAndFillComplete(Crcp,
2030 *Ctemp->getGraph()->getExporter(),
2033 rcp(&labelList,
false));
2035#ifdef HAVE_TPETRA_MMM_STATISTICS
2036 printMultiplicationStatistics(Ctemp->getGraph()->getExporter(), label + std::string(
" AT_B MMM"));
2042template <
class Scalar,
2044 class GlobalOrdinal,
2047 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2048 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2049 CrsWrapper<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2050 const std::string& ,
2051 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2052 using Teuchos::Array;
2053 using Teuchos::ArrayRCP;
2054 using Teuchos::ArrayView;
2055 using Teuchos::null;
2056 using Teuchos::OrdinalTraits;
2058 bool skipExplicitZero =
true;
2059 if (params && params->isParameter(
"MM Skip Explicit Zeros")) {
2060 skipExplicitZero = params->get<
bool>(
"MM Skip Explicit Zeros");
2063 typedef Teuchos::ScalarTraits<Scalar> STS;
2065 LocalOrdinal C_firstCol = Bview.colMap->getMinLocalIndex();
2066 LocalOrdinal C_lastCol = Bview.colMap->getMaxLocalIndex();
2068 LocalOrdinal C_firstCol_import = OrdinalTraits<LocalOrdinal>::zero();
2069 LocalOrdinal C_lastCol_import = OrdinalTraits<LocalOrdinal>::invalid();
2071 ArrayView<const GlobalOrdinal> bcols = Bview.colMap->getLocalElementList();
2072 ArrayView<const GlobalOrdinal> bcols_import = null;
2073 if (Bview.importColMap != null) {
2074 C_firstCol_import = Bview.importColMap->getMinLocalIndex();
2075 C_lastCol_import = Bview.importColMap->getMaxLocalIndex();
2077 bcols_import = Bview.importColMap->getLocalElementList();
2080 size_t C_numCols = C_lastCol - C_firstCol +
2081 OrdinalTraits<LocalOrdinal>::one();
2082 size_t C_numCols_import = C_lastCol_import - C_firstCol_import +
2083 OrdinalTraits<LocalOrdinal>::one();
2085 if (C_numCols_import > C_numCols)
2086 C_numCols = C_numCols_import;
2088 Array<Scalar> dwork = Array<Scalar>(C_numCols);
2089 Array<GlobalOrdinal> iwork = Array<GlobalOrdinal>(C_numCols);
2090 Array<size_t> iwork2 = Array<size_t>(C_numCols);
2092 Array<Scalar> C_row_i = dwork;
2093 Array<GlobalOrdinal> C_cols = iwork;
2094 Array<size_t> c_index = iwork2;
2095 Array<GlobalOrdinal> combined_index = Array<GlobalOrdinal>(2 * C_numCols);
2096 Array<Scalar> combined_values = Array<Scalar>(2 * C_numCols);
2098 size_t C_row_i_length, j, k, last_index;
2101 LocalOrdinal LO_INVALID = OrdinalTraits<LocalOrdinal>::invalid();
2102 Array<LocalOrdinal> Acol2Brow(Aview.colMap->getLocalNumElements(), LO_INVALID);
2103 Array<LocalOrdinal> Acol2Irow(Aview.colMap->getLocalNumElements(), LO_INVALID);
2104 if (Aview.colMap->isSameAs(*Bview.origMatrix->getRowMap())) {
2106 for (LocalOrdinal i = Aview.colMap->getMinLocalIndex(); i <=
2107 Aview.colMap->getMaxLocalIndex();
2112 for (LocalOrdinal i = Aview.colMap->getMinLocalIndex(); i <=
2113 Aview.colMap->getMaxLocalIndex();
2115 GlobalOrdinal GID = Aview.colMap->getGlobalElement(i);
2116 LocalOrdinal BLID = Bview.origMatrix->getRowMap()->getLocalElement(GID);
2117 if (BLID != LO_INVALID)
2118 Acol2Brow[i] = BLID;
2120 Acol2Irow[i] = Bview.importMatrix->getRowMap()->getLocalElement(GID);
2130 auto Arowptr = Aview.origMatrix->getLocalRowPtrsHost();
2131 auto Acolind = Aview.origMatrix->getLocalIndicesHost();
2132 auto Avals = Aview.origMatrix->getLocalValuesHost(Tpetra::Access::ReadOnly);
2133 auto Browptr = Bview.origMatrix->getLocalRowPtrsHost();
2134 auto Bcolind = Bview.origMatrix->getLocalIndicesHost();
2135 auto Bvals = Bview.origMatrix->getLocalValuesHost(Tpetra::Access::ReadOnly);
2136 decltype(Browptr) Irowptr;
2137 decltype(Bcolind) Icolind;
2138 decltype(Bvals) Ivals;
2139 if (!Bview.importMatrix.is_null()) {
2140 Irowptr = Bview.importMatrix->getLocalRowPtrsHost();
2141 Icolind = Bview.importMatrix->getLocalIndicesHost();
2142 Ivals = Bview.importMatrix->getLocalValuesHost(Tpetra::Access::ReadOnly);
2145 bool C_filled = C.isFillComplete();
2147 for (
size_t i = 0; i < C_numCols; i++)
2148 c_index[i] = OrdinalTraits<size_t>::invalid();
2151 size_t Arows = Aview.rowMap->getLocalNumElements();
2152 for (
size_t i = 0; i < Arows; ++i) {
2155 GlobalOrdinal global_row = Aview.rowMap->getGlobalElement(i);
2161 C_row_i_length = OrdinalTraits<size_t>::zero();
2163 for (k = Arowptr[i]; k < Arowptr[i + 1]; ++k) {
2164 LocalOrdinal Ak = Acol2Brow[Acolind[k]];
2165 const Scalar Aval = Avals[k];
2166 if (Aval == STS::zero() && skipExplicitZero)
2169 if (Ak == LO_INVALID)
2172 for (j = Browptr[Ak]; j < Browptr[Ak + 1]; ++j) {
2173 LocalOrdinal col = Bcolind[j];
2176 if (c_index[col] == OrdinalTraits<size_t>::invalid()) {
2179 C_row_i[C_row_i_length] = Aval * Bvals[j];
2180 C_cols[C_row_i_length] = col;
2181 c_index[col] = C_row_i_length;
2186 C_row_i[c_index[col]] += Aval *
static_cast<Scalar
>(Bvals[j]);
2191 for (
size_t ii = 0; ii < C_row_i_length; ii++) {
2192 c_index[C_cols[ii]] = OrdinalTraits<size_t>::invalid();
2193 C_cols[ii] = bcols[C_cols[ii]];
2194 combined_index[ii] = C_cols[ii];
2195 combined_values[ii] = C_row_i[ii];
2197 last_index = C_row_i_length;
2203 C_row_i_length = OrdinalTraits<size_t>::zero();
2205 for (k = Arowptr[i]; k < Arowptr[i + 1]; ++k) {
2206 LocalOrdinal Ak = Acol2Brow[Acolind[k]];
2207 const Scalar Aval = Avals[k];
2208 if (Aval == STS::zero() && skipExplicitZero)
2211 if (Ak != LO_INVALID)
continue;
2213 Ak = Acol2Irow[Acolind[k]];
2214 for (j = Irowptr[Ak]; j < Irowptr[Ak + 1]; ++j) {
2215 LocalOrdinal col = Icolind[j];
2218 if (c_index[col] == OrdinalTraits<size_t>::invalid()) {
2221 C_row_i[C_row_i_length] = Aval * Ivals[j];
2222 C_cols[C_row_i_length] = col;
2223 c_index[col] = C_row_i_length;
2229 C_row_i[c_index[col]] += Aval *
static_cast<Scalar
>(Ivals[j]);
2234 for (
size_t ii = 0; ii < C_row_i_length; ii++) {
2235 c_index[C_cols[ii]] = OrdinalTraits<size_t>::invalid();
2236 C_cols[ii] = bcols_import[C_cols[ii]];
2237 combined_index[last_index] = C_cols[ii];
2238 combined_values[last_index] = C_row_i[ii];
2244 C_filled ? C.sumIntoGlobalValues(
2246 combined_index.view(OrdinalTraits<size_t>::zero(), last_index),
2247 combined_values.view(OrdinalTraits<size_t>::zero(), last_index))
2248 : C.insertGlobalValues(
2250 combined_index.view(OrdinalTraits<size_t>::zero(), last_index),
2251 combined_values.view(OrdinalTraits<size_t>::zero(), last_index));
2256template <
class Scalar,
2258 class GlobalOrdinal,
2260void setMaxNumEntriesPerRow(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Mview) {
2261 typedef typename Teuchos::Array<Teuchos::ArrayView<const LocalOrdinal>>::size_type local_length_size;
2262 Mview.maxNumRowEntries = Teuchos::OrdinalTraits<local_length_size>::zero();
2264 if (Mview.indices.size() > Teuchos::OrdinalTraits<local_length_size>::zero()) {
2265 Mview.maxNumRowEntries = Mview.indices[0].size();
2267 for (local_length_size i = 1; i < Mview.indices.size(); ++i)
2268 if (Mview.indices[i].size() > Mview.maxNumRowEntries)
2269 Mview.maxNumRowEntries = Mview.indices[i].size();
2274template <
class CrsMatrixType>
2275size_t C_estimate_nnz(CrsMatrixType& A, CrsMatrixType& B) {
2277 size_t Aest = 100, Best = 100;
2278 if (A.getLocalNumEntries() >= A.getLocalNumRows())
2279 Aest = (A.getLocalNumRows() > 0) ? A.getLocalNumEntries() / A.getLocalNumRows() : 100;
2280 if (B.getLocalNumEntries() >= B.getLocalNumRows())
2281 Best = (B.getLocalNumRows() > 0) ? B.getLocalNumEntries() / B.getLocalNumRows() : 100;
2283 size_t nnzperrow = (size_t)(sqrt((
double)Aest) + sqrt((
double)Best) - 1);
2284 nnzperrow *= nnzperrow;
2286 return (
size_t)(A.getLocalNumRows() * nnzperrow * 0.75 + 100);
2295template <
class Scalar,
2297 class GlobalOrdinal,
2299void mult_A_B_newmatrix(
2300 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2301 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2302 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2303 const std::string& label,
2304 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2305 using Teuchos::Array;
2306 using Teuchos::ArrayRCP;
2307 using Teuchos::ArrayView;
2312 typedef LocalOrdinal LO;
2313 typedef GlobalOrdinal GO;
2315 typedef Import<LO, GO, NO> import_type;
2316 typedef Map<LO, GO, NO> map_type;
2319 typedef typename map_type::local_map_type local_map_type;
2321 typedef typename KCRS::StaticCrsGraphType graph_t;
2322 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2323 typedef typename NO::execution_space execution_space;
2324 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2325 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2327 Tpetra::Details::ProfilingRegion MM(
"TpetraExt: MMM: M5 Cmap");
2329 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2332 RCP<const import_type> Cimport;
2333 RCP<const map_type> Ccolmap;
2334 RCP<const import_type> Bimport = Bview.origMatrix->getGraph()->getImporter();
2335 RCP<const import_type> Iimport = Bview.importMatrix.is_null() ? Teuchos::null : Bview.importMatrix->getGraph()->getImporter();
2336 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2337 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2338 local_map_type Irowmap_local;
2339 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2340 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2341 local_map_type Icolmap_local;
2342 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2349 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2351 if (Bview.importMatrix.is_null()) {
2354 Ccolmap = Bview.colMap;
2355 const LO colMapSize =
static_cast<LO
>(Bview.colMap->getLocalNumElements());
2357 Kokkos::parallel_for(
2358 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_fill",
2359 Kokkos::RangePolicy<execution_space, LO>(0, colMapSize),
2360 KOKKOS_LAMBDA(
const LO i) {
2372 if (!Bimport.is_null() && !Iimport.is_null()) {
2373 Cimport = Bimport->setUnion(*Iimport, params);
2374 }
else if (!Bimport.is_null() && Iimport.is_null()) {
2375 Cimport = Bimport->setUnion(params);
2376 }
else if (Bimport.is_null() && !Iimport.is_null()) {
2377 Cimport = Iimport->setUnion(params);
2379 throw std::runtime_error(
"TpetraExt::MMM status of matrix importers is nonsensical");
2381 Ccolmap = Cimport->getTargetMap();
2386 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
2387 std::runtime_error,
"Tpetra::MMM: Import setUnion messed with the DomainMap in an unfortunate way");
2394 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2395 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2396 Kokkos::parallel_for(
2397 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_getGlobalElement", range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2398 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2400 Kokkos::parallel_for(
2401 "Tpetra::mult_A_B_newmatrix::Icol2Ccol_getGlobalElement", range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2402 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2410 C.replaceColMap(Ccolmap);
2428 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
2429 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
2431 Kokkos::parallel_for(
2432 "Tpetra::mult_A_B_newmatrix::construct_tables", range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
2433 GO aidx = Acolmap_local.getGlobalElement(i);
2434 LO B_LID = Browmap_local.getLocalElement(aidx);
2435 if (B_LID != LO_INVALID) {
2436 targetMapToOrigRow(i) = B_LID;
2437 targetMapToImportRow(i) = LO_INVALID;
2439 LO I_LID = Irowmap_local.getLocalElement(aidx);
2440 targetMapToOrigRow(i) = LO_INVALID;
2441 targetMapToImportRow(i) = I_LID;
2447 KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::mult_A_B_newmatrix_kernel_wrapper(Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
2452template <
class Scalar,
2454 class GlobalOrdinal,
2456void mult_A_B_newmatrix(BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2457 BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2458 Teuchos::RCP<BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& C) {
2459 using Teuchos::Array;
2460 using Teuchos::ArrayRCP;
2461 using Teuchos::ArrayView;
2462 using Teuchos::null;
2467 typedef LocalOrdinal LO;
2468 typedef GlobalOrdinal GO;
2470 typedef Import<LO, GO, NO> import_type;
2471 typedef Map<LO, GO, NO> map_type;
2472 typedef BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> block_crs_matrix_type;
2473 typedef typename block_crs_matrix_type::crs_graph_type graph_t;
2476 typedef typename map_type::local_map_type local_map_type;
2477 typedef typename block_crs_matrix_type::local_matrix_device_type KBSR;
2478 typedef typename KBSR::device_type device_t;
2479 typedef typename KBSR::StaticCrsGraphType static_graph_t;
2480 typedef typename static_graph_t::row_map_type::non_const_type lno_view_t;
2481 typedef typename static_graph_t::entries_type::non_const_type lno_nnz_view_t;
2482 typedef typename KBSR::values_type::non_const_type scalar_view_t;
2483 typedef typename NO::execution_space execution_space;
2484 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2485 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2487 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2490 RCP<const import_type> Cimport;
2491 RCP<const map_type> Ccolmap;
2492 RCP<const import_type> Bimport = Bview.origMatrix->getGraph()->getImporter();
2493 RCP<const import_type> Iimport = Bview.importMatrix.is_null() ? Teuchos::null : Bview.importMatrix->getGraph()->getImporter();
2494 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2495 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2496 local_map_type Irowmap_local;
2497 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2498 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2499 local_map_type Icolmap_local;
2500 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2507 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2509 if (Bview.importMatrix.is_null()) {
2512 Ccolmap = Bview.colMap;
2513 const LO colMapSize =
static_cast<LO
>(Bview.colMap->getLocalNumElements());
2515 Kokkos::parallel_for(
2516 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_fill",
2517 Kokkos::RangePolicy<execution_space, LO>(0, colMapSize),
2518 KOKKOS_LAMBDA(
const LO i) {
2530 if (!Bimport.is_null() && !Iimport.is_null()) {
2531 Cimport = Bimport->setUnion(*Iimport);
2532 }
else if (!Bimport.is_null() && Iimport.is_null()) {
2533 Cimport = Bimport->setUnion();
2534 }
else if (Bimport.is_null() && !Iimport.is_null()) {
2535 Cimport = Iimport->setUnion();
2537 throw std::runtime_error(
"TpetraExt::MMM status of matrix importers is nonsensical");
2539 Ccolmap = Cimport->getTargetMap();
2546 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2547 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2548 Kokkos::parallel_for(
2549 "Tpetra::mult_A_B_newmatrix::Bcol2Ccol_getGlobalElement",
2550 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()),
2551 KOKKOS_LAMBDA(
const LO i) {
2552 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2554 Kokkos::parallel_for(
2555 "Tpetra::mult_A_B_newmatrix::Icol2Ccol_getGlobalElement",
2556 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()),
2557 KOKKOS_LAMBDA(
const LO i) {
2558 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2578 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"),
2579 Aview.colMap->getLocalNumElements());
2580 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"),
2581 Aview.colMap->getLocalNumElements());
2583 Kokkos::parallel_for(
2584 "Tpetra::mult_A_B_newmatrix::construct_tables",
2585 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1),
2586 KOKKOS_LAMBDA(
const LO i) {
2587 GO aidx = Acolmap_local.getGlobalElement(i);
2588 LO B_LID = Browmap_local.getLocalElement(aidx);
2589 if (B_LID != LO_INVALID) {
2590 targetMapToOrigRow(i) = B_LID;
2591 targetMapToImportRow(i) = LO_INVALID;
2593 LO I_LID = Irowmap_local.getLocalElement(aidx);
2594 targetMapToOrigRow(i) = LO_INVALID;
2595 targetMapToImportRow(i) = I_LID;
2600 using KernelHandle =
2601 KokkosKernels::Experimental::KokkosKernelsHandle<
typename lno_view_t::const_value_type,
2602 typename lno_nnz_view_t::const_value_type,
2603 typename scalar_view_t::const_value_type,
2604 typename device_t::execution_space,
2605 typename device_t::memory_space,
2606 typename device_t::memory_space>;
2607 int team_work_size = 16;
2608 std::string myalg(
"SPGEMM_DEFAULT");
2609 KokkosSparse::SPGEMMAlgorithm alg_enum = KokkosSparse::StringToSPGEMMAlgorithm(myalg);
2612 kh.create_spgemm_handle(alg_enum);
2613 kh.set_team_work_size(team_work_size);
2616 const KBSR Amat = Aview.origMatrix->getLocalMatrixDevice();
2617 const KBSR Bmerged = Tpetra::MMdetails::merge_matrices(Aview, Bview,
2618 targetMapToOrigRow, targetMapToImportRow,
2619 Bcol2Ccol, Icol2Ccol,
2620 Ccolmap.getConst()->getLocalNumElements());
2622 RCP<graph_t> graphC;
2623 typename KBSR::values_type values;
2628 KokkosSparse::block_spgemm_symbolic(kh, Amat,
false, Bmerged,
false, Cmat);
2629 KokkosSparse::block_spgemm_numeric(kh, Amat,
false, Bmerged,
false, Cmat);
2630 kh.destroy_spgemm_handle();
2633 graphC = rcp(
new graph_t(Cmat.graph, Aview.origMatrix->getRowMap(), Ccolmap.getConst()));
2634 values = Cmat.values;
2636 C = rcp(
new block_crs_matrix_type(*graphC, values, Aview.blocksize));
2641template <
class Scalar,
2643 class GlobalOrdinal,
2645 class LocalOrdinalViewType>
2646void KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_A_B_newmatrix_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2647 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2648 const LocalOrdinalViewType& targetMapToOrigRow,
2649 const LocalOrdinalViewType& targetMapToImportRow,
2650 const LocalOrdinalViewType& Bcol2Ccol,
2651 const LocalOrdinalViewType& Icol2Ccol,
2652 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2653 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
2654 const std::string& label,
2655 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2656 using Teuchos::Array;
2657 using Teuchos::ArrayRCP;
2658 using Teuchos::ArrayView;
2662 Tpetra::Details::ProfilingRegion MM(
"TpetraExt: MMM: Newmatrix SerialCore");
2665 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
2666 typedef typename KCRS::StaticCrsGraphType graph_t;
2667 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
2668 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2669 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
2670 typedef typename KCRS::values_type::non_const_type scalar_view_t;
2673 typedef LocalOrdinal LO;
2674 typedef GlobalOrdinal GO;
2676 typedef Map<LO, GO, NO> map_type;
2677 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2678 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2679 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
2681 bool skipExplicitZero =
true;
2682 if (params && params->isParameter(
"MM Skip Explicit Zeros")) {
2683 skipExplicitZero = params->get<
bool>(
"MM Skip Explicit Zeros");
2687 RCP<const map_type> Ccolmap = C.getColMap();
2688 size_t m = Aview.origMatrix->getLocalNumRows();
2689 size_t n = Ccolmap->getLocalNumElements();
2690 size_t b_max_nnz_per_row = Bview.origMatrix->getLocalMaxNumRowEntries();
2693 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
2694 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
2696 c_lno_view_t Arowptr = Amat.graph.row_map, Browptr = Bmat.graph.row_map;
2697 const lno_nnz_view_t Acolind = Amat.graph.entries, Bcolind = Bmat.graph.entries;
2698 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
2700 c_lno_view_t Irowptr;
2701 lno_nnz_view_t Icolind;
2702 scalar_view_t Ivals;
2703 if (!Bview.importMatrix.is_null()) {
2704 auto lclB = Bview.importMatrix->getLocalMatrixHost();
2705 Irowptr = lclB.graph.row_map;
2706 Icolind = lclB.graph.entries;
2707 Ivals = lclB.values;
2708 b_max_nnz_per_row = std::max(b_max_nnz_per_row, Bview.importMatrix->getLocalMaxNumRowEntries());
2718 size_t CSR_alloc = std::max(C_estimate_nnz(*Aview.origMatrix, *Bview.origMatrix), n);
2719 lno_view_t Crowptr(Kokkos::ViewAllocateWithoutInitializing(
"Crowptr"), m + 1);
2720 lno_nnz_view_t Ccolind(Kokkos::ViewAllocateWithoutInitializing(
"Ccolind"), CSR_alloc);
2721 scalar_view_t Cvals(Kokkos::ViewAllocateWithoutInitializing(
"Cvals"), CSR_alloc);
2731 size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
2732 std::vector<size_t> c_status(n, ST_INVALID);
2742 size_t CSR_ip = 0, OLD_ip = 0;
2743 for (
size_t i = 0; i < m; i++) {
2746 Crowptr[i] = CSR_ip;
2749 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
2750 LO Aik = Acolind[k];
2751 const SC Aval = Avals[k];
2752 if (Aval == SC_ZERO && skipExplicitZero)
2755 if (targetMapToOrigRow[Aik] != LO_INVALID) {
2762 size_t Bk =
static_cast<size_t>(targetMapToOrigRow[Aik]);
2765 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
2766 LO Bkj = Bcolind[j];
2767 LO Cij = Bcol2Ccol[Bkj];
2769 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
2771 c_status[Cij] = CSR_ip;
2772 Ccolind[CSR_ip] = Cij;
2773 Cvals[CSR_ip] = Aval * Bvals[j];
2777 Cvals[c_status[Cij]] += Aval * Bvals[j];
2788 size_t Ik =
static_cast<size_t>(targetMapToImportRow[Aik]);
2789 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
2790 LO Ikj = Icolind[j];
2791 LO Cij = Icol2Ccol[Ikj];
2793 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
2795 c_status[Cij] = CSR_ip;
2796 Ccolind[CSR_ip] = Cij;
2797 Cvals[CSR_ip] = Aval * Ivals[j];
2800 Cvals[c_status[Cij]] += Aval * Ivals[j];
2807 if (i + 1 < m && CSR_ip + std::min(n, (Arowptr[i + 2] - Arowptr[i + 1]) * b_max_nnz_per_row) > CSR_alloc) {
2809 Kokkos::resize(Ccolind, CSR_alloc);
2810 Kokkos::resize(Cvals, CSR_alloc);
2815 Crowptr[m] = CSR_ip;
2818 Kokkos::resize(Ccolind, CSR_ip);
2819 Kokkos::resize(Cvals, CSR_ip);
2822 Tpetra::Details::ProfilingRegion MM3(
"TpetraExt: MMM: Newmatrix Final Sort");
2825 if (params.is_null() || params->get(
"sort entries",
true)) {
2827 Import_Util::sortCrsEntries(Crowptr, Ccolind, Cvals);
2829 C.setAllValues(Crowptr, Ccolind, Cvals);
2832 Tpetra::Details::ProfilingRegion MM4(
"TpetraExt: MMM: Newmatrix ESCC");
2842 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
2843 labelList->set(
"Timer Label", label);
2844 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
2845 RCP<const Export<LO, GO, NO>> dummyExport;
2846 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
2851template <
class Scalar,
2853 class GlobalOrdinal,
2856 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2857 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2858 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2859 const std::string& label,
2860 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2861 using Teuchos::Array;
2862 using Teuchos::ArrayRCP;
2863 using Teuchos::ArrayView;
2868 typedef LocalOrdinal LO;
2869 typedef GlobalOrdinal GO;
2871 typedef Import<LO, GO, NO> import_type;
2872 typedef Map<LO, GO, NO> map_type;
2875 typedef typename map_type::local_map_type local_map_type;
2877 typedef typename KCRS::StaticCrsGraphType graph_t;
2878 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2879 typedef typename NO::execution_space execution_space;
2880 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2881 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
2883 Tpetra::Details::ProfilingRegion MM(
"TpetraExt: MMM: Reuse Cmap");
2886 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
2889 RCP<const import_type> Cimport = C.getGraph()->getImporter();
2890 RCP<const map_type> Ccolmap = C.getColMap();
2891 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
2892 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
2893 local_map_type Irowmap_local;
2894 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
2895 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
2896 local_map_type Icolmap_local;
2897 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
2898 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
2901 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
2905 Kokkos::parallel_for(
2906 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2907 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
2910 if (!Bview.importMatrix.is_null()) {
2911 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
2912 std::runtime_error,
"Tpetra::MMM: Import setUnion messed with the DomainMap in an unfortunate way");
2914 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
2915 Kokkos::parallel_for(
2916 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
2917 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
2923 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
2924 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
2925 Kokkos::parallel_for(
2926 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
2927 GO aidx = Acolmap_local.getGlobalElement(i);
2928 LO B_LID = Browmap_local.getLocalElement(aidx);
2929 if (B_LID != LO_INVALID) {
2930 targetMapToOrigRow(i) = B_LID;
2931 targetMapToImportRow(i) = LO_INVALID;
2933 LO I_LID = Irowmap_local.getLocalElement(aidx);
2934 targetMapToOrigRow(i) = LO_INVALID;
2935 targetMapToImportRow(i) = I_LID;
2941 KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::mult_A_B_reuse_kernel_wrapper(Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
2945template <
class Scalar,
2947 class GlobalOrdinal,
2949 class LocalOrdinalViewType>
2950void KernelWrappers<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_A_B_reuse_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2951 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2952 const LocalOrdinalViewType& targetMapToOrigRow,
2953 const LocalOrdinalViewType& targetMapToImportRow,
2954 const LocalOrdinalViewType& Bcol2Ccol,
2955 const LocalOrdinalViewType& Icol2Ccol,
2956 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2957 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
2958 const std::string& label,
2959 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2960 Tpetra::MMdetails::host_mult_A_B_reuse(
2961 Aview, Bview, targetMapToOrigRow, targetMapToImportRow,
2962 Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
2967template <
class Scalar,
2969 class GlobalOrdinal,
2971void jacobi_A_B_newmatrix(
2972 typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
2973 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
2974 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
2975 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
2976 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
2977 const std::string& label,
2978 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2979 using Teuchos::Array;
2980 using Teuchos::ArrayRCP;
2981 using Teuchos::ArrayView;
2985 typedef LocalOrdinal LO;
2986 typedef GlobalOrdinal GO;
2989 typedef Import<LO, GO, NO> import_type;
2990 typedef Map<LO, GO, NO> map_type;
2991 typedef typename map_type::local_map_type local_map_type;
2995 typedef typename KCRS::StaticCrsGraphType graph_t;
2996 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
2997 typedef typename NO::execution_space execution_space;
2998 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
2999 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
3001 Tpetra::Details::ProfilingRegion MM3(
"TpetraExt: Jacobi: M5 Cmap");
3003 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3006 RCP<const import_type> Cimport;
3007 RCP<const map_type> Ccolmap;
3008 RCP<const import_type> Bimport = Bview.origMatrix->getGraph()->getImporter();
3009 RCP<const import_type> Iimport = Bview.importMatrix.is_null() ? Teuchos::null : Bview.importMatrix->getGraph()->getImporter();
3010 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
3011 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
3012 local_map_type Irowmap_local;
3013 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
3014 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
3015 local_map_type Icolmap_local;
3016 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
3023 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements()), Icol2Ccol;
3025 if (Bview.importMatrix.is_null()) {
3028 Ccolmap = Bview.colMap;
3032 Kokkos::RangePolicy<execution_space, LO> range(0,
static_cast<LO
>(Bview.colMap->getLocalNumElements()));
3033 Kokkos::parallel_for(
3034 range, KOKKOS_LAMBDA(
const size_t i) {
3035 Bcol2Ccol(i) =
static_cast<LO
>(i);
3046 if (!Bimport.is_null() && !Iimport.is_null()) {
3047 Cimport = Bimport->setUnion(*Iimport, params);
3048 Ccolmap = Cimport->getTargetMap();
3050 }
else if (!Bimport.is_null() && Iimport.is_null()) {
3051 Cimport = Bimport->setUnion(params);
3053 }
else if (Bimport.is_null() && !Iimport.is_null()) {
3054 Cimport = Iimport->setUnion(params);
3057 throw std::runtime_error(
"TpetraExt::Jacobi status of matrix importers is nonsensical");
3059 Ccolmap = Cimport->getTargetMap();
3061 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
3062 std::runtime_error,
"Tpetra:Jacobi Import setUnion messed with the DomainMap in an unfortunate way");
3069 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
3070 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
3071 Kokkos::parallel_for(
3072 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
3073 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
3075 Kokkos::parallel_for(
3076 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
3077 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
3085 C.replaceColMap(Ccolmap);
3103 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
3104 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
3105 Kokkos::parallel_for(
3106 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
3107 GO aidx = Acolmap_local.getGlobalElement(i);
3108 LO B_LID = Browmap_local.getLocalElement(aidx);
3109 if (B_LID != LO_INVALID) {
3110 targetMapToOrigRow(i) = B_LID;
3111 targetMapToImportRow(i) = LO_INVALID;
3113 LO I_LID = Irowmap_local.getLocalElement(aidx);
3114 targetMapToOrigRow(i) = LO_INVALID;
3115 targetMapToImportRow(i) = I_LID;
3121 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);
3128template <
class Scalar,
3130 class GlobalOrdinal,
3132 class LocalOrdinalViewType>
3133void KernelWrappers2<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::jacobi_A_B_newmatrix_kernel_wrapper(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
3134 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
3135 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3136 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3137 const LocalOrdinalViewType& targetMapToOrigRow,
3138 const LocalOrdinalViewType& targetMapToImportRow,
3139 const LocalOrdinalViewType& Bcol2Ccol,
3140 const LocalOrdinalViewType& Icol2Ccol,
3141 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
3142 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
3143 const std::string& label,
3144 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3145 Tpetra::Details::ProfilingRegion MM(
"TpetraExt: Jacobi: Newmatrix SerialCore");
3147 using Teuchos::Array;
3148 using Teuchos::ArrayRCP;
3149 using Teuchos::ArrayView;
3154 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
3155 typedef typename KCRS::StaticCrsGraphType graph_t;
3156 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
3157 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3158 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
3159 typedef typename KCRS::values_type::non_const_type scalar_view_t;
3162 typedef typename scalar_view_t::memory_space scalar_memory_space;
3165 typedef LocalOrdinal LO;
3166 typedef GlobalOrdinal GO;
3169 typedef Map<LO, GO, NO> map_type;
3170 size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3171 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3174 RCP<const map_type> Ccolmap = C.getColMap();
3175 size_t m = Aview.origMatrix->getLocalNumRows();
3176 size_t n = Ccolmap->getLocalNumElements();
3177 size_t b_max_nnz_per_row = Bview.origMatrix->getLocalMaxNumRowEntries();
3180 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
3181 const KCRS Bmat = Bview.origMatrix->getLocalMatrixHost();
3183 c_lno_view_t Arowptr = Amat.graph.row_map, Browptr = Bmat.graph.row_map;
3184 const lno_nnz_view_t Acolind = Amat.graph.entries, Bcolind = Bmat.graph.entries;
3185 const scalar_view_t Avals = Amat.values, Bvals = Bmat.values;
3187 c_lno_view_t Irowptr;
3188 lno_nnz_view_t Icolind;
3189 scalar_view_t Ivals;
3190 if (!Bview.importMatrix.is_null()) {
3191 auto lclB = Bview.importMatrix->getLocalMatrixHost();
3192 Irowptr = lclB.graph.row_map;
3193 Icolind = lclB.graph.entries;
3194 Ivals = lclB.values;
3195 b_max_nnz_per_row = std::max(b_max_nnz_per_row, Bview.importMatrix->getLocalMaxNumRowEntries());
3200 Dinv.template getLocalView<scalar_memory_space>(Access::ReadOnly);
3208 size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
3209 Array<size_t> c_status(n, ST_INVALID);
3218 size_t CSR_alloc = std::max(C_estimate_nnz(*Aview.origMatrix, *Bview.origMatrix), n);
3219 lno_view_t Crowptr(Kokkos::ViewAllocateWithoutInitializing(
"Crowptr"), m + 1);
3220 lno_nnz_view_t Ccolind(Kokkos::ViewAllocateWithoutInitializing(
"Ccolind"), CSR_alloc);
3221 scalar_view_t Cvals(Kokkos::ViewAllocateWithoutInitializing(
"Cvals"), CSR_alloc);
3222 size_t CSR_ip = 0, OLD_ip = 0;
3224 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
3238 for (
size_t i = 0; i < m; i++) {
3241 Crowptr[i] = CSR_ip;
3242 SC minusOmegaDval = -omega * Dvals(i, 0);
3245 for (
size_t j = Browptr[i]; j < Browptr[i + 1]; j++) {
3246 Scalar Bval = Bvals[j];
3247 if (Bval == SC_ZERO)
3249 LO Bij = Bcolind[j];
3250 LO Cij = Bcol2Ccol[Bij];
3253 c_status[Cij] = CSR_ip;
3254 Ccolind[CSR_ip] = Cij;
3255 Cvals[CSR_ip] = Bvals[j];
3260 for (
size_t k = Arowptr[i]; k < Arowptr[i + 1]; k++) {
3261 LO Aik = Acolind[k];
3262 const SC Aval = Avals[k];
3263 if (Aval == SC_ZERO)
3266 if (targetMapToOrigRow[Aik] != LO_INVALID) {
3268 size_t Bk =
static_cast<size_t>(targetMapToOrigRow[Aik]);
3270 for (
size_t j = Browptr[Bk]; j < Browptr[Bk + 1]; ++j) {
3271 LO Bkj = Bcolind[j];
3272 LO Cij = Bcol2Ccol[Bkj];
3274 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
3276 c_status[Cij] = CSR_ip;
3277 Ccolind[CSR_ip] = Cij;
3278 Cvals[CSR_ip] = minusOmegaDval * Aval * Bvals[j];
3282 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Bvals[j];
3288 size_t Ik =
static_cast<size_t>(targetMapToImportRow[Aik]);
3289 for (
size_t j = Irowptr[Ik]; j < Irowptr[Ik + 1]; ++j) {
3290 LO Ikj = Icolind[j];
3291 LO Cij = Icol2Ccol[Ikj];
3293 if (c_status[Cij] == INVALID || c_status[Cij] < OLD_ip) {
3295 c_status[Cij] = CSR_ip;
3296 Ccolind[CSR_ip] = Cij;
3297 Cvals[CSR_ip] = minusOmegaDval * Aval * Ivals[j];
3300 Cvals[c_status[Cij]] += minusOmegaDval * Aval * Ivals[j];
3307 if (i + 1 < m && CSR_ip + std::min(n, (Arowptr[i + 2] - Arowptr[i + 1] + 1) * b_max_nnz_per_row) > CSR_alloc) {
3309 Kokkos::resize(Ccolind, CSR_alloc);
3310 Kokkos::resize(Cvals, CSR_alloc);
3314 Crowptr[m] = CSR_ip;
3317 Kokkos::resize(Ccolind, CSR_ip);
3318 Kokkos::resize(Cvals, CSR_ip);
3321 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: Jacobi: Newmatrix Final Sort");
3327 C.replaceColMap(Ccolmap);
3334 if (params.is_null() || params->get(
"sort entries",
true)) {
3336 Import_Util::sortCrsEntries(Crowptr, Ccolind, Cvals);
3338 C.setAllValues(Crowptr, Ccolind, Cvals);
3341 Tpetra::Details::ProfilingRegion MM3(
"TpetraExt: Jacobi: Newmatrix ESFC");
3351 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
3352 labelList->set(
"Timer Label", label);
3353 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
3354 RCP<const Export<LO, GO, NO>> dummyExport;
3355 C.expertStaticFillComplete(Bview.origMatrix->getDomainMap(), Aview.origMatrix->getRangeMap(), Cimport, dummyExport, labelList);
3361template <
class Scalar,
3363 class GlobalOrdinal,
3365void jacobi_A_B_reuse(
3366 typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
3367 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
3368 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3369 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3370 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
3371 const std::string& label,
3372 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3373 using Teuchos::Array;
3374 using Teuchos::ArrayRCP;
3375 using Teuchos::ArrayView;
3379 typedef LocalOrdinal LO;
3380 typedef GlobalOrdinal GO;
3383 typedef Import<LO, GO, NO> import_type;
3384 typedef Map<LO, GO, NO> map_type;
3387 typedef typename map_type::local_map_type local_map_type;
3389 typedef typename KCRS::StaticCrsGraphType graph_t;
3390 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3391 typedef typename NO::execution_space execution_space;
3392 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3393 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
3395 RCP<const import_type> Cimport = C.getGraph()->getImporter();
3396 lo_view_t Bcol2Ccol, Icol2Ccol;
3397 lo_view_t targetMapToOrigRow;
3398 lo_view_t targetMapToImportRow;
3400 Tpetra::Details::ProfilingRegion MM(
"TpetraExt: Jacobi: Reuse Cmap");
3402 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3405 RCP<const map_type> Ccolmap = C.getColMap();
3406 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
3407 local_map_type Browmap_local = Bview.origMatrix->getRowMap()->getLocalMap();
3408 local_map_type Irowmap_local;
3409 if (!Bview.importMatrix.is_null()) Irowmap_local = Bview.importMatrix->getRowMap()->getLocalMap();
3410 local_map_type Bcolmap_local = Bview.origMatrix->getColMap()->getLocalMap();
3411 local_map_type Icolmap_local;
3412 if (!Bview.importMatrix.is_null()) Icolmap_local = Bview.importMatrix->getColMap()->getLocalMap();
3413 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
3416 Bcol2Ccol = lo_view_t(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Bview.colMap->getLocalNumElements());
3420 Kokkos::parallel_for(
3421 range_type(0, Bview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
3422 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Bcolmap_local.getGlobalElement(i));
3425 if (!Bview.importMatrix.is_null()) {
3426 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Bview.origMatrix->getDomainMap()),
3427 std::runtime_error,
"Tpetra::Jacobi: Import setUnion messed with the DomainMap in an unfortunate way");
3429 Kokkos::resize(Icol2Ccol, Bview.importMatrix->getColMap()->getLocalNumElements());
3430 Kokkos::parallel_for(
3431 range_type(0, Bview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
3432 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
3438 targetMapToOrigRow = lo_view_t(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
3439 targetMapToImportRow = lo_view_t(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
3440 Kokkos::parallel_for(
3441 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
3442 GO aidx = Acolmap_local.getGlobalElement(i);
3443 LO B_LID = Browmap_local.getLocalElement(aidx);
3444 if (B_LID != LO_INVALID) {
3445 targetMapToOrigRow(i) = B_LID;
3446 targetMapToImportRow(i) = LO_INVALID;
3448 LO I_LID = Irowmap_local.getLocalElement(aidx);
3449 targetMapToOrigRow(i) = LO_INVALID;
3450 targetMapToImportRow(i) = I_LID;
3457 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);
3461template <
class Scalar,
3463 class GlobalOrdinal,
3465 class LocalOrdinalViewType>
3466void KernelWrappers2<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::jacobi_A_B_reuse_kernel_wrapper(
typename Teuchos::ScalarTraits<Scalar>::magnitudeType omega,
3467 const Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Dinv,
3468 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3469 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3470 const LocalOrdinalViewType& targetMapToOrigRow,
3471 const LocalOrdinalViewType& targetMapToImportRow,
3472 const LocalOrdinalViewType& Bcol2Ccol,
3473 const LocalOrdinalViewType& Icol2Ccol,
3474 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& C,
3475 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> Cimport,
3476 const std::string& label,
3477 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3478 host_jacobi_A_B_reuse(omega, Dinv, Aview, Bview, targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol, C, Cimport, label, params);
3482template <
class Scalar,
3484 class GlobalOrdinal,
3486void import_and_extract_views(
3487 const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
3488 Teuchos::RCP<
const Map<LocalOrdinal, GlobalOrdinal, Node>> targetMap,
3489 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3490 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> prototypeImporter,
3491 bool userAssertsThereAreNoRemotes,
3492 const std::string& label,
3493 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3494 using Teuchos::Array;
3495 using Teuchos::ArrayView;
3496 using Teuchos::null;
3501 typedef LocalOrdinal LO;
3502 typedef GlobalOrdinal GO;
3505 typedef Map<LO, GO, NO> map_type;
3506 typedef Import<LO, GO, NO> import_type;
3507 typedef CrsMatrix<SC, LO, GO, NO> crs_matrix_type;
3509 RCP<Tpetra::Details::ProfilingRegion> MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM: I&X Alloc"));
3517 Aview.deleteContents();
3519 Aview.origMatrix = rcp(&A,
false);
3521 Aview.origMatrix->getApplyHelper();
3522 Aview.origRowMap = A.getRowMap();
3523 Aview.rowMap = targetMap;
3524 Aview.colMap = A.getColMap();
3525 Aview.domainMap = A.getDomainMap();
3526 Aview.importColMap = null;
3527 RCP<const map_type> rowMap = A.getRowMap();
3528 const int numProcs = rowMap->getComm()->getSize();
3531 if (userAssertsThereAreNoRemotes || numProcs < 2)
3534 RCP<const import_type> importer;
3535 if (params != null && params->isParameter(
"importer")) {
3536 importer = params->get<RCP<const import_type>>(
"importer");
3540 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM: I&X RemoteMap"));
3544 RCP<const map_type> remoteRowMap;
3545 size_t numRemote = 0;
3547 if (!prototypeImporter.is_null() &&
3548 prototypeImporter->getSourceMap()->isSameAs(*rowMap) &&
3549 prototypeImporter->getTargetMap()->isSameAs(*targetMap)) {
3551 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: MMM: I&X RemoteMap: Mode1");
3553 ArrayView<const LO> remoteLIDs = prototypeImporter->getRemoteLIDs();
3554 numRemote = prototypeImporter->getNumRemoteIDs();
3556 Array<GO> remoteRows(numRemote);
3557 for (
size_t i = 0; i < numRemote; i++)
3558 remoteRows[i] = targetMap->getGlobalElement(remoteLIDs[i]);
3560 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3561 rowMap->getIndexBase(), rowMap->getComm(), params));
3564 }
else if (prototypeImporter.is_null()) {
3566 Tpetra::Details::ProfilingRegion MM2(
"TpetraExt: MMM: I&X RemoteMap: Mode2");
3568 ArrayView<const GO> rows = targetMap->getLocalElementList();
3569 size_t numRows = targetMap->getLocalNumElements();
3571 Array<GO> remoteRows(numRows);
3572 for (
size_t i = 0; i < numRows; ++i) {
3573 const LO mlid = rowMap->getLocalElement(rows[i]);
3575 if (mlid == Teuchos::OrdinalTraits<LO>::invalid())
3576 remoteRows[numRemote++] = rows[i];
3578 remoteRows.resize(numRemote);
3579 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3580 rowMap->getIndexBase(), rowMap->getComm(), params));
3589 TEUCHOS_TEST_FOR_EXCEPTION(numRemote > 0, std::runtime_error,
3590 "MatrixMatrix::import_and_extract_views ERROR, numProcs < 2 but attempting to import remote matrix rows.");
3598 if (!remoteRowMap.is_null() && (remoteRowMap->getGlobalNumElements() > 0)) {
3600 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM: I&X Import-2"));
3604 importer = prototypeImporter->createRemoteOnlyImport(remoteRowMap);
3606 importer = rcp(
new import_type(rowMap, remoteRowMap));
3608 throw std::runtime_error(
"prototypeImporter->SourceMap() does not match A.getRowMap()!");
3612 params->set(
"importer", importer);
3615 if (importer != null) {
3617 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM: I&X Import-3"));
3620 Teuchos::ParameterList labelList;
3621 labelList.set(
"Timer Label", label);
3623 labelList.set(
"compute global constants",
false);
3624 auto& labelList_subList = labelList.sublist(
"matrixmatrix: kernel params",
false);
3625 labelList_subList.set(
"isMatrixMatrix_TransferAndFillComplete",
true);
3627 if (!params.is_null()) {
3628 if (params->isParameter(
"compute global constants"))
3629 labelList.set(
"compute global constants", params->get<
bool>(
"compute global constants"));
3633 A.getDomainMap(), importer->getTargetMap(), rcpFromRef(labelList));
3635 Aview.importMatrix->getApplyHelper();
3641 sprintf(str,
"import_matrix.%d.dat",count);
3646#ifdef HAVE_TPETRA_MMM_STATISTICS
3647 printMultiplicationStatistics(importer, label + std::string(
" I&X MMM"));
3651 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: MMM: I&X Import-4"));
3654 Aview.importColMap = Aview.importMatrix->getColMap();
3660template <
class Scalar,
3662 class GlobalOrdinal,
3664void import_and_extract_views(
3665 const BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& M,
3666 Teuchos::RCP<
const Map<LocalOrdinal, GlobalOrdinal, Node>> targetMap,
3667 BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Mview,
3668 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node>> prototypeImporter,
3669 bool userAssertsThereAreNoRemotes) {
3670 using Teuchos::Array;
3671 using Teuchos::ArrayView;
3672 using Teuchos::null;
3677 typedef LocalOrdinal LO;
3678 typedef GlobalOrdinal GO;
3681 typedef Map<LO, GO, NO> map_type;
3682 typedef Import<LO, GO, NO> import_type;
3683 typedef BlockCrsMatrix<SC, LO, GO, NO> blockcrs_matrix_type;
3691 Mview.deleteContents();
3693 Mview.origMatrix = rcp(&M,
false);
3695 Mview.origMatrix->getApplyHelper();
3696 Mview.origRowMap = M.getRowMap();
3697 Mview.rowMap = targetMap;
3698 Mview.colMap = M.getColMap();
3699 Mview.importColMap = null;
3700 RCP<const map_type> rowMap = M.getRowMap();
3701 const int numProcs = rowMap->getComm()->getSize();
3704 if (userAssertsThereAreNoRemotes || numProcs < 2)
return;
3708 RCP<const map_type> remoteRowMap;
3709 size_t numRemote = 0;
3711 if (!prototypeImporter.is_null() &&
3712 prototypeImporter->getSourceMap()->isSameAs(*rowMap) &&
3713 prototypeImporter->getTargetMap()->isSameAs(*targetMap)) {
3715 ArrayView<const LO> remoteLIDs = prototypeImporter->getRemoteLIDs();
3716 numRemote = prototypeImporter->getNumRemoteIDs();
3718 Array<GO> remoteRows(numRemote);
3719 for (
size_t i = 0; i < numRemote; i++)
3720 remoteRows[i] = targetMap->getGlobalElement(remoteLIDs[i]);
3722 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3723 rowMap->getIndexBase(), rowMap->getComm()));
3726 }
else if (prototypeImporter.is_null()) {
3728 ArrayView<const GO> rows = targetMap->getLocalElementList();
3729 size_t numRows = targetMap->getLocalNumElements();
3731 Array<GO> remoteRows(numRows);
3732 for (
size_t i = 0; i < numRows; ++i) {
3733 const LO mlid = rowMap->getLocalElement(rows[i]);
3735 if (mlid == Teuchos::OrdinalTraits<LO>::invalid())
3736 remoteRows[numRemote++] = rows[i];
3738 remoteRows.resize(numRemote);
3739 remoteRowMap = rcp(
new map_type(Teuchos::OrdinalTraits<global_size_t>::invalid(), remoteRows(),
3740 rowMap->getIndexBase(), rowMap->getComm()));
3749 TEUCHOS_TEST_FOR_EXCEPTION(numRemote > 0, std::runtime_error,
3750 "MatrixMatrix::import_and_extract_views ERROR, numProcs < 2 but attempting to import remote matrix rows.");
3757 RCP<const import_type> importer;
3759 if (!remoteRowMap.is_null() && (remoteRowMap->getGlobalNumElements() > 0)) {
3762 importer = prototypeImporter->createRemoteOnlyImport(remoteRowMap);
3764 importer = rcp(
new import_type(rowMap, remoteRowMap));
3766 throw std::runtime_error(
"prototypeImporter->SourceMap() does not match M.getRowMap()!");
3769 if (importer != null) {
3772 Mview.importMatrix = Tpetra::importAndFillCompleteBlockCrsMatrix<blockcrs_matrix_type>(rcpFromRef(M), *importer);
3774 Mview.importMatrix->getApplyHelper();
3777 Mview.importColMap = Mview.importMatrix->getColMap();
3783template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class LocalOrdinalViewType>
3785merge_matrices(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3786 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3787 const LocalOrdinalViewType& Acol2Brow,
3788 const LocalOrdinalViewType& Acol2Irow,
3789 const LocalOrdinalViewType& Bcol2Ccol,
3790 const LocalOrdinalViewType& Icol2Ccol,
3791 const size_t mergedNodeNumCols) {
3794 typedef typename KCRS::StaticCrsGraphType graph_t;
3795 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3796 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
3797 typedef typename KCRS::values_type::non_const_type scalar_view_t;
3799 const KCRS Ak = Aview.origMatrix->getLocalMatrixDevice();
3800 const KCRS Bk = Bview.origMatrix->getLocalMatrixDevice();
3803 if (!Bview.importMatrix.is_null() || (Bview.importMatrix.is_null() && (&*Aview.origMatrix->getGraph()->getColMap() != &*Bview.origMatrix->getGraph()->getRowMap()))) {
3809 if (!Bview.importMatrix.is_null()) Iks = Bview.importMatrix->getLocalMatrixDevice();
3811 size_t merge_numrows = Ak.numCols();
3814 lno_view_t Mrowptr(
"Mrowptr", merge_numrows + 1);
3816 const LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
3819 typedef typename Node::execution_space execution_space;
3820 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3821 Kokkos::parallel_scan(
3822 "Tpetra_MatrixMatrix_merge_matrices_buildRowptr", range_type(0, merge_numrows),
3823 KOKKOS_LAMBDA(
const size_t i,
size_t& update,
const bool final) {
3824 if (
final) Mrowptr(i) = update;
3827 if (Acol2Brow(i) != LO_INVALID)
3828 ct = Bk.graph.row_map(Acol2Brow(i) + 1) - Bk.graph.row_map(Acol2Brow(i));
3830 ct = Iks.graph.row_map(Acol2Irow(i) + 1) - Iks.graph.row_map(Acol2Irow(i));
3833 if (
final && i + 1 == merge_numrows)
3834 Mrowptr(i + 1) = update;
3838 size_t merge_nnz = ::Tpetra::Details::getEntryOnHost(Mrowptr, merge_numrows);
3839 lno_nnz_view_t Mcolind(Kokkos::ViewAllocateWithoutInitializing(
"Mcolind"), merge_nnz);
3840 scalar_view_t Mvalues(Kokkos::ViewAllocateWithoutInitializing(
"Mvals"), merge_nnz);
3843 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3844 Kokkos::parallel_for(
3845 "Tpetra_MatrixMatrix_merg_matrices_buildColindValues", range_type(0, merge_numrows), KOKKOS_LAMBDA(
const size_t i) {
3846 if (Acol2Brow(i) != LO_INVALID) {
3847 size_t row = Acol2Brow(i);
3848 size_t start = Bk.graph.row_map(row);
3849 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3850 Mvalues(j) = Bk.values(j - Mrowptr(i) + start);
3851 Mcolind(j) = Bcol2Ccol(Bk.graph.entries(j - Mrowptr(i) + start));
3854 size_t row = Acol2Irow(i);
3855 size_t start = Iks.graph.row_map(row);
3856 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3857 Mvalues(j) = Iks.values(j - Mrowptr(i) + start);
3858 Mcolind(j) = Icol2Ccol(Iks.graph.entries(j - Mrowptr(i) + start));
3863 KCRS newmat(
"CrsMatrix", merge_numrows, mergedNodeNumCols, merge_nnz, Mvalues, Mrowptr, Mcolind);
3873template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class LocalOrdinalViewType>
3874const typename Tpetra::BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_device_type
3875merge_matrices(BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
3876 BlockCrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Bview,
3877 const LocalOrdinalViewType& Acol2Brow,
3878 const LocalOrdinalViewType& Acol2Irow,
3879 const LocalOrdinalViewType& Bcol2Ccol,
3880 const LocalOrdinalViewType& Icol2Ccol,
3881 const size_t mergedNodeNumCols) {
3883 typedef typename Tpetra::BlockCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_device_type KBCRS;
3884 typedef typename KBCRS::StaticCrsGraphType graph_t;
3885 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
3886 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
3887 typedef typename KBCRS::values_type::non_const_type scalar_view_t;
3890 const KBCRS Ak = Aview.origMatrix->getLocalMatrixDevice();
3891 const KBCRS Bk = Bview.origMatrix->getLocalMatrixDevice();
3894 if (!Bview.importMatrix.is_null() ||
3895 (Bview.importMatrix.is_null() &&
3896 (&*Aview.origMatrix->getGraph()->getColMap() != &*Bview.origMatrix->getGraph()->getRowMap()))) {
3901 if (!Bview.importMatrix.is_null()) Iks = Bview.importMatrix->getLocalMatrixDevice();
3902 size_t merge_numrows = Ak.numCols();
3905 lno_view_t Mrowptr(
"Mrowptr", merge_numrows + 1);
3907 const LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
3910 typedef typename Node::execution_space execution_space;
3911 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3912 Kokkos::parallel_scan(
3913 "Tpetra_MatrixMatrix_merge_matrices_buildRowptr", range_type(0, merge_numrows),
3914 KOKKOS_LAMBDA(
const size_t i,
size_t& update,
const bool final) {
3915 if (
final) Mrowptr(i) = update;
3918 if (Acol2Brow(i) != LO_INVALID)
3919 ct = Bk.graph.row_map(Acol2Brow(i) + 1) - Bk.graph.row_map(Acol2Brow(i));
3921 ct = Iks.graph.row_map(Acol2Irow(i) + 1) - Iks.graph.row_map(Acol2Irow(i));
3924 if (
final && i + 1 == merge_numrows)
3925 Mrowptr(i + 1) = update;
3929 size_t merge_nnz = ::Tpetra::Details::getEntryOnHost(Mrowptr, merge_numrows);
3930 const int blocksize = Ak.blockDim();
3931 lno_nnz_view_t Mcolind(Kokkos::ViewAllocateWithoutInitializing(
"Mcolind"), merge_nnz);
3932 scalar_view_t Mvalues(Kokkos::ViewAllocateWithoutInitializing(
"Mvals"), merge_nnz * blocksize * blocksize);
3935 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
3936 Kokkos::parallel_for(
3937 "Tpetra_MatrixMatrix_merg_matrices_buildColindValues", range_type(0, merge_numrows), KOKKOS_LAMBDA(
const size_t i) {
3938 if (Acol2Brow(i) != LO_INVALID) {
3939 size_t row = Acol2Brow(i);
3940 size_t start = Bk.graph.row_map(row);
3941 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3942 Mcolind(j) = Bcol2Ccol(Bk.graph.entries(j - Mrowptr(i) + start));
3944 for (
int b = 0; b < blocksize * blocksize; ++b) {
3945 const int val_indx = j * blocksize * blocksize + b;
3946 const int b_val_indx = (j - Mrowptr(i) +
start) * blocksize * blocksize + b;
3947 Mvalues(val_indx) = Bk.values(b_val_indx);
3951 size_t row = Acol2Irow(i);
3952 size_t start = Iks.graph.row_map(row);
3953 for (
size_t j = Mrowptr(i); j < Mrowptr(i + 1); j++) {
3954 Mcolind(j) = Icol2Ccol(Iks.graph.entries(j - Mrowptr(i) + start));
3956 for (
int b = 0; b < blocksize * blocksize; ++b) {
3957 const int val_indx = j * blocksize * blocksize + b;
3958 const int b_val_indx = (j - Mrowptr(i) +
start) * blocksize * blocksize + b;
3959 Mvalues(val_indx) = Iks.values(b_val_indx);
3966 KBCRS newmat(
"CrsMatrix", merge_numrows, mergedNodeNumCols, merge_nnz, Mvalues, Mrowptr, Mcolind, blocksize);
3975template <
typename SC,
typename LO,
typename GO,
typename NO>
3976void AddKernels<SC, LO, GO, NO>::
3978 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Avals,
3979 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Arowptrs,
3980 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Acolinds,
3981 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarA,
3982 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Bvals,
3983 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Browptrs,
3984 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Bcolinds,
3985 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarB,
3987 typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Cvals,
3988 typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array& Crowptrs,
3989 typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Ccolinds) {
3991 using Teuchos::TimeMonitor;
3992 using AddKern = MMdetails::AddKernels<SC, LO, GO, NO>;
3993 TEUCHOS_TEST_FOR_EXCEPTION(Arowptrs.extent(0) != Browptrs.extent(0), std::runtime_error,
"Can't add matrices with different numbers of rows.");
3994 auto nrows = Arowptrs.extent(0) - 1;
3995 Crowptrs = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"C row ptrs"), nrows + 1);
3996 typename AddKern::KKH handle;
3997 handle.create_spadd_handle(
true);
3998 auto addHandle = handle.get_spadd_handle();
4000 auto MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: sorted symbolic"));
4002 KokkosSparse::spadd_symbolic(&handle,
4003 nrows, numGlobalCols,
4004 Arowptrs, Acolinds, Browptrs, Bcolinds, Crowptrs);
4006 Cvals = values_array(
"C values", addHandle->get_c_nnz());
4007 Ccolinds = col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
4010 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: sorted numeric"));
4011 KokkosSparse::spadd_numeric(&handle,
4012 nrows, numGlobalCols,
4013 Arowptrs, Acolinds, Avals, scalarA,
4014 Browptrs, Bcolinds, Bvals, scalarB,
4015 Crowptrs, Ccolinds, Cvals);
4018template <
typename SC,
typename LO,
typename GO,
typename NO>
4019void AddKernels<SC, LO, GO, NO>::
4021 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Avals,
4022 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Arowptrs,
4023 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Acolinds,
4024 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarA,
4025 const typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Bvals,
4026 const typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array_const& Browptrs,
4027 const typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Bcolinds,
4028 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarB,
4030 typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Cvals,
4031 typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array& Crowptrs,
4032 typename MMdetails::AddKernels<SC, LO, GO, NO>::col_inds_array& Ccolinds) {
4034 using Teuchos::TimeMonitor;
4035 using AddKern = MMdetails::AddKernels<SC, LO, GO, NO>;
4036 TEUCHOS_TEST_FOR_EXCEPTION(Arowptrs.extent(0) != Browptrs.extent(0), std::runtime_error,
"Can't add matrices with different numbers of rows.");
4037 auto nrows = Arowptrs.extent(0) - 1;
4038 Crowptrs = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"C row ptrs"), nrows + 1);
4039 typedef MMdetails::AddKernels<SC, LO, GO, NO> AddKern;
4040 typename AddKern::KKH handle;
4041 handle.create_spadd_handle(
false);
4042 auto addHandle = handle.get_spadd_handle();
4043 auto MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: unsorted symbolic"));
4045 KokkosSparse::spadd_symbolic(&handle,
4046 nrows, numGlobalCols,
4047 Arowptrs, Acolinds, Browptrs, Bcolinds, Crowptrs);
4049 Cvals = values_array(
"C values", addHandle->get_c_nnz());
4050 Ccolinds = col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
4052 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: unsorted numeric"));
4053 KokkosSparse::spadd_numeric(&handle,
4054 nrows, numGlobalCols,
4055 Arowptrs, Acolinds, Avals, scalarA,
4056 Browptrs, Bcolinds, Bvals, scalarB,
4057 Crowptrs, Ccolinds, Cvals);
4060template <
typename GO,
4061 typename LocalIndicesType,
4062 typename GlobalIndicesType,
4063 typename ColMapType>
4064struct ConvertLocalToGlobalFunctor {
4065 ConvertLocalToGlobalFunctor(
4066 const LocalIndicesType& colindsOrig_,
4067 const GlobalIndicesType& colindsConverted_,
4068 const ColMapType& colmap_)
4069 : colindsOrig(colindsOrig_)
4070 , colindsConverted(colindsConverted_)
4071 , colmap(colmap_) {}
4072 KOKKOS_INLINE_FUNCTION
void
4073 operator()(
const GO i)
const {
4074 colindsConverted(i) = colmap.getGlobalElement(colindsOrig(i));
4076 LocalIndicesType colindsOrig;
4077 GlobalIndicesType colindsConverted;
4081template <
typename SC,
typename LO,
typename GO,
typename NO>
4082void MMdetails::AddKernels<SC, LO, GO, NO>::
4083 convertToGlobalAndAdd(
4084 const typename MMdetails::AddKernels<SC, LO, GO, NO>::KCRS A,
4085 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarA,
4086 const typename MMdetails::AddKernels<SC, LO, GO, NO>::KCRS B,
4087 const typename MMdetails::AddKernels<SC, LO, GO, NO>::impl_scalar_type scalarB,
4088 const typename MMdetails::AddKernels<SC, LO, GO, NO>::local_map_type& AcolMap,
4089 const typename MMdetails::AddKernels<SC, LO, GO, NO>::local_map_type& BcolMap,
4090 typename MMdetails::AddKernels<SC, LO, GO, NO>::values_array& Cvals,
4091 typename MMdetails::AddKernels<SC, LO, GO, NO>::row_ptrs_array& Crowptrs,
4092 typename MMdetails::AddKernels<SC, LO, GO, NO>::global_col_inds_array& Ccolinds) {
4094 using Teuchos::TimeMonitor;
4097 using KKH_GO = KokkosKernels::Experimental::KokkosKernelsHandle<size_t, GO, impl_scalar_type,
4098 typename NO::execution_space,
typename NO::memory_space,
typename NO::memory_space>;
4100 const values_array Avals = A.values;
4101 const values_array Bvals = B.values;
4102 const col_inds_array Acolinds = A.graph.entries;
4103 const col_inds_array Bcolinds = B.graph.entries;
4104 auto Arowptrs = A.graph.row_map;
4105 auto Browptrs = B.graph.row_map;
4106 global_col_inds_array AcolindsConverted(Kokkos::ViewAllocateWithoutInitializing(
"A colinds (converted)"), Acolinds.extent(0));
4107 global_col_inds_array BcolindsConverted(Kokkos::ViewAllocateWithoutInitializing(
"B colinds (converted)"), Bcolinds.extent(0));
4109 auto MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: diff col map kernel: column map conversion"));
4111 ConvertLocalToGlobalFunctor<GO, col_inds_array, global_col_inds_array, local_map_type> convertA(Acolinds, AcolindsConverted, AcolMap);
4112 Kokkos::parallel_for(
"Tpetra_MatrixMatrix_convertColIndsA", range_type(0, Acolinds.extent(0)), convertA);
4113 ConvertLocalToGlobalFunctor<GO, col_inds_array, global_col_inds_array, local_map_type> convertB(Bcolinds, BcolindsConverted, BcolMap);
4114 Kokkos::parallel_for(
"Tpetra_MatrixMatrix_convertColIndsB", range_type(0, Bcolinds.extent(0)), convertB);
4116 handle.create_spadd_handle(
false);
4117 auto addHandle = handle.get_spadd_handle();
4119 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: diff col map kernel: unsorted symbolic"));
4120 auto nrows = Arowptrs.extent(0) - 1;
4121 Crowptrs = row_ptrs_array(Kokkos::ViewAllocateWithoutInitializing(
"C row ptrs"), nrows + 1);
4122 KokkosSparse::spadd_symbolic(&handle,
4124 Arowptrs, AcolindsConverted, Browptrs, BcolindsConverted, Crowptrs);
4125 Cvals = values_array(
"C values", addHandle->get_c_nnz());
4126 Ccolinds = global_col_inds_array(Kokkos::ViewAllocateWithoutInitializing(
"C colinds"), addHandle->get_c_nnz());
4129 MM = rcp(
new Tpetra::Details::ProfilingRegion(
"TpetraExt: add: diff col map kernel: unsorted numeric"));
4130 KokkosSparse::spadd_numeric(&handle,
4132 Arowptrs, AcolindsConverted, Avals, scalarA,
4133 Browptrs, BcolindsConverted, Bvals, scalarB,
4134 Crowptrs, Ccolinds, Cvals);
4149#define TPETRA_MATRIXMATRIX_INSTANT(SCALAR, LO, GO, NODE) \
4150 template void MatrixMatrix::Multiply( \
4151 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4153 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4155 CrsMatrix<SCALAR, LO, GO, NODE>& C, \
4156 bool call_FillComplete_on_result, \
4157 const std::string& label, \
4158 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4160 template void MatrixMatrix::Multiply( \
4161 const Teuchos::RCP<const BlockCrsMatrix<SCALAR, LO, GO, NODE>>& A, \
4163 const Teuchos::RCP<const BlockCrsMatrix<SCALAR, LO, GO, NODE>>& B, \
4165 Teuchos::RCP<BlockCrsMatrix<SCALAR, LO, GO, NODE>>& C, \
4166 const std::string& label); \
4168 template void MatrixMatrix::Jacobi( \
4169 typename Teuchos::ScalarTraits<SCALAR>::magnitudeType omega, \
4170 const Vector<SCALAR, LO, GO, NODE>& Dinv, \
4171 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4172 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4173 CrsMatrix<SCALAR, LO, GO, NODE>& C, \
4174 bool call_FillComplete_on_result, \
4175 const std::string& label, \
4176 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4178 template void MatrixMatrix::Add( \
4179 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4182 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4185 Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE>>& C); \
4187 template void MatrixMatrix::Add( \
4188 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4191 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4194 const Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE>>& C); \
4196 template void MatrixMatrix::Add( \
4197 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4200 CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4203 template Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE>> \
4204 MatrixMatrix::add<SCALAR, LO, GO, NODE>(const SCALAR& alpha, \
4205 const bool transposeA, \
4206 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4207 const SCALAR& beta, \
4208 const bool transposeB, \
4209 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4210 const Teuchos::RCP<const Map<LO, GO, NODE>>& domainMap, \
4211 const Teuchos::RCP<const Map<LO, GO, NODE>>& rangeMap, \
4212 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4215 MatrixMatrix::add<SCALAR, LO, GO, NODE>(const SCALAR& alpha, \
4216 const bool transposeA, \
4217 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
4218 const SCALAR& beta, \
4219 const bool transposeB, \
4220 const CrsMatrix<SCALAR, LO, GO, NODE>& B, \
4221 CrsMatrix<SCALAR, LO, GO, NODE>& C, \
4222 const Teuchos::RCP<const Map<LO, GO, NODE>>& domainMap, \
4223 const Teuchos::RCP<const Map<LO, GO, NODE>>& rangeMap, \
4224 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4226 template struct MMdetails::AddKernels<SCALAR, LO, GO, NODE>; \
4228 template void MMdetails::import_and_extract_views<SCALAR, LO, GO, NODE>(const CrsMatrix<SCALAR, LO, GO, NODE>& M, \
4229 Teuchos::RCP<const Map<LO, GO, NODE>> targetMap, \
4230 CrsMatrixStruct<SCALAR, LO, GO, NODE>& Mview, \
4231 Teuchos::RCP<const Import<LO, GO, NODE>> prototypeImporter, \
4232 bool userAssertsThereAreNoRemotes, \
4233 const std::string& label, \
4234 const Teuchos::RCP<Teuchos::ParameterList>& params); \
4236 template void MMdetails::import_and_extract_views<SCALAR, LO, GO, NODE>(const BlockCrsMatrix<SCALAR, LO, GO, NODE>& M, \
4237 Teuchos::RCP<const Map<LO, GO, NODE>> targetMap, \
4238 BlockCrsMatrixStruct<SCALAR, LO, GO, NODE>& Mview, \
4239 Teuchos::RCP<const Import<LO, GO, NODE>> prototypeImporter, \
4240 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.
void sortCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort the entries of the (raw CSR) matrix by column index within each row.
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.
Sparse matrix whose entries are small dense square blocks, all of the same dimensions.
Struct that holds views of the contents of a BlockCrsMatrix.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries.
bool isGloballyIndexed() const override
Whether the matrix is globally indexed on the calling process.
bool haveGlobalConstants() const
Returns true if globalConstants have been computed; false otherwise.
void scale(const Scalar &alpha)
Scale the matrix's values: this := alpha*this.
Teuchos::RCP< const map_type > getDomainMap() const override
The domain Map of this matrix.
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Perform a fillComplete on a matrix that already has data.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
The communicator over which the matrix is distributed.
bool isFillActive() const
Whether the matrix is not fill complete.
Teuchos::RCP< const map_type > getRangeMap() const override
The range Map of this matrix.
size_t getLocalMaxNumRowEntries() const override
Maximum number of entries in any row of the matrix, on this process.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the matrix's column Map with the given Map.
global_size_t getGlobalNumRows() const override
Number of global elements in the row map of this matrix.
void insertGlobalValues(const GlobalOrdinal globalRow, const Teuchos::ArrayView< const GlobalOrdinal > &cols, const Teuchos::ArrayView< const Scalar > &vals)
Insert one or more entries into the matrix, using global column indices.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Tell the matrix that you are done changing its structure or values, and that you are ready to do comp...
void setAllValues(const typename local_graph_device_type::row_map_type &ptr, const typename local_graph_device_type::entries_type::non_const_type &ind, const typename local_matrix_device_type::values_type &val)
Set the local matrix using three (compressed sparse row) arrays.
Teuchos::RCP< const RowGraph< LocalOrdinal, GlobalOrdinal, Node > > getGraph() const override
This matrix's graph, as a RowGraph.
bool isStaticGraph() const
Indicates that the graph is static, so that new entries cannot be added to this matrix.
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...
size_t getLocalNumRows() const override
The number of matrix rows owned by the calling process.
bool isFillComplete() const override
Whether the matrix is fill complete.
Teuchos::RCP< const map_type > getRowMap() const override
The Map that describes the row distribution in this matrix.
bool isLocallyIndexed() const override
Whether the matrix is locally indexed on the calling process.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume operations that may change the values or structure of the matrix.
Struct that holds views of the contents of a CrsMatrix.
static bool debug()
Whether Tpetra is in debug mode.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
A parallel distribution of indices over processes.
static void writeSparseFile(const std::string &filename, const sparse_matrix_type &matrix, const std::string &matrixName, const std::string &matrixDescription, const bool debug=false)
Construct and (optionally) redistribute the explicitly stored transpose of a CrsMatrix.
Teuchos::RCP< crs_matrix_type > createTranspose(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Compute and return the transpose of the matrix given to the constructor.
A distributed dense vector.
void start()
Start the deep_copy counter.
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &colMap, Teuchos::Array< int > &remotePIDs, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &domMap, const CrsGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
Distributed sparse matrix-matrix multiply and add.
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.
size_t global_size_t
Global size_t object.
Teuchos::RCP< CrsMatrixType > importAndFillCompleteCrsMatrix(const Teuchos::RCP< const CrsMatrixType > &sourceMatrix, const Import< typename CrsMatrixType::local_ordinal_type, typename CrsMatrixType::global_ordinal_type, typename CrsMatrixType::node_type > &importer, const Teuchos::RCP< const Map< typename CrsMatrixType::local_ordinal_type, typename CrsMatrixType::global_ordinal_type, typename CrsMatrixType::node_type > > &domainMap=Teuchos::null, const Teuchos::RCP< const Map< typename CrsMatrixType::local_ordinal_type, typename CrsMatrixType::global_ordinal_type, typename CrsMatrixType::node_type > > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Nonmember CrsMatrix constructor that fuses Import and fillComplete().