10#ifndef TPETRA_TRIPLEMATRIXMULTIPLY_DEF_HPP
11#define TPETRA_TRIPLEMATRIXMULTIPLY_DEF_HPP
14#include "TpetraExt_MatrixMatrix_ExtraKernels_decl.hpp"
15#include "Teuchos_VerboseObject.hpp"
16#include "Teuchos_Array.hpp"
18#include "Tpetra_ConfigDefs.hpp"
19#include "Tpetra_CrsMatrix.hpp"
21#include "Tpetra_RowMatrixTransposer.hpp"
22#include "Tpetra_ConfigDefs.hpp"
23#include "Tpetra_Map.hpp"
24#include "Tpetra_Export.hpp"
29#include "Teuchos_FancyOStream.hpp"
40#include "TpetraExt_MatrixMatrix_OpenMP.hpp"
41#include "TpetraExt_MatrixMatrix_Cuda.hpp"
42#include "TpetraExt_MatrixMatrix_HIP.hpp"
43#include "TpetraExt_MatrixMatrix_SYCL.hpp"
55template <
class Scalar,
67 bool call_FillComplete_on_result,
68 const std::string& label,
69 const Teuchos::RCP<Teuchos::ParameterList>& params) {
73 typedef LocalOrdinal LO;
74 typedef GlobalOrdinal GO;
83#ifdef HAVE_TPETRA_MMM_TIMINGS
84 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
85 using Teuchos::TimeMonitor;
86 RCP<Teuchos::TimeMonitor> MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP All Setup"))));
89 const std::string prefix =
"TpetraExt::TripleMatrixMultiply::MultiplyRAP(): ";
94 TEUCHOS_TEST_FOR_EXCEPTION(!R.
isFillComplete(), std::runtime_error, prefix <<
"Matrix R is not fill complete.");
95 TEUCHOS_TEST_FOR_EXCEPTION(!A.
isFillComplete(), std::runtime_error, prefix <<
"Matrix A is not fill complete.");
96 TEUCHOS_TEST_FOR_EXCEPTION(!P.
isFillComplete(), std::runtime_error, prefix <<
"Matrix P is not fill complete.");
101 RCP<const crs_matrix_type> Rprime = null;
105 RCP<const crs_matrix_type> Aprime = null;
109 RCP<const crs_matrix_type> Pprime = null;
119 const bool newFlag = !Ac.
getGraph()->isLocallyIndexed() && !Ac.
getGraph()->isGloballyIndexed();
121 using Teuchos::ParameterList;
122 RCP<ParameterList> transposeParams(
new ParameterList);
123 transposeParams->set(
"sort",
false);
125 if (transposeR && &R != &P) {
126 transposer_type transposer(rcpFromRef(R));
127 Rprime = transposer.createTranspose(transposeParams);
129 Rprime = rcpFromRef(R);
133 transposer_type transposer(rcpFromRef(A));
134 Aprime = transposer.createTranspose(transposeParams);
136 Aprime = rcpFromRef(A);
140 transposer_type transposer(rcpFromRef(P));
141 Pprime = transposer.createTranspose(transposeParams);
143 Pprime = rcpFromRef(P);
156 TEUCHOS_TEST_FOR_EXCEPTION(Rright != Aleft, std::runtime_error,
157 prefix <<
"ERROR, inner dimensions of op(R) and op(A) "
158 "must match for matrix-matrix product. op(R) is "
159 << Rleft <<
"x" << Rright <<
", op(A) is " << Aleft <<
"x" << Aright);
161 TEUCHOS_TEST_FOR_EXCEPTION(Aright != Pleft, std::runtime_error,
162 prefix <<
"ERROR, inner dimensions of op(A) and op(P) "
163 "must match for matrix-matrix product. op(A) is "
164 << Aleft <<
"x" << Aright <<
", op(P) is " << Pleft <<
"x" << Pright);
170 TEUCHOS_TEST_FOR_EXCEPTION(Rleft > Ac.
getGlobalNumRows(), std::runtime_error,
171 prefix <<
"ERROR, dimensions of result Ac must "
172 "match dimensions of op(R) * op(A) * op(P). Ac has "
174 <<
" rows, should have at least " << Rleft << std::endl);
186 int numProcs = P.
getComm()->getSize();
190 crs_matrix_struct_type Rview;
191 crs_matrix_struct_type Aview;
192 crs_matrix_struct_type Pview;
194 RCP<const map_type> targetMap_R = Rprime->getRowMap();
195 RCP<const map_type> targetMap_A = Aprime->getRowMap();
196 RCP<const map_type> targetMap_P = Pprime->getRowMap();
198#ifdef HAVE_TPETRA_MMM_TIMINGS
200 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP All I&X"))));
206 RCP<const import_type> dummyImporter;
208 if (!(transposeR && &R == &P))
209 MMdetails::import_and_extract_views(*Rprime, targetMap_R, Rview, dummyImporter,
true, label, params);
211 MMdetails::import_and_extract_views(*Aprime, targetMap_A, Aview, dummyImporter,
true, label, params);
216 targetMap_P = Aprime->getColMap();
219 MMdetails::import_and_extract_views(*Pprime, targetMap_P, Pview, Aprime->getGraph()->getImporter(),
false, label, params);
221 RCP<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Actemp;
223 bool needs_final_export = !Pprime->getGraph()->getImporter().is_null();
224 if (needs_final_export)
227 Actemp = rcp(&Ac,
false);
229#ifdef HAVE_TPETRA_MMM_TIMINGS
231 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP All Multiply"))));
235 if (call_FillComplete_on_result && newFlag) {
236 if (transposeR && &R == &P)
237 MMdetails::mult_PT_A_P_newmatrix(Aview, Pview, *Actemp, label, params);
239 MMdetails::mult_R_A_P_newmatrix(Rview, Aview, Pview, *Actemp, label, params);
240 }
else if (call_FillComplete_on_result) {
241 if (transposeR && &R == &P)
242 MMdetails::mult_PT_A_P_reuse(Aview, Pview, *Actemp, label, params);
244 MMdetails::mult_R_A_P_reuse(Rview, Aview, Pview, *Actemp, label, params);
267 if (transposeR && &R == &P)
268 MMdetails::mult_PT_A_P_newmatrix(Aview, Pview, *Actemp, label, params);
270 MMdetails::mult_R_A_P_newmatrix(Rview, Aview, Pview, *Actemp, label, params);
273 if (needs_final_export) {
274#ifdef HAVE_TPETRA_MMM_TIMINGS
276 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP exportAndFillComplete"))));
278 Teuchos::ParameterList labelList;
279 labelList.set(
"Timer Label", label);
280 Teuchos::ParameterList& labelList_subList = labelList.sublist(
"matrixmatrix: kernel params",
false);
281 labelList_subList.set(
"isMatrixMatrix_TransferAndFillComplete",
true,
282 "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.");
284 RCP<crs_matrix_type> Acprime = rcpFromRef(Ac);
285 if (!params.is_null()) {
286 labelList.setParameters(*params);
290 Actemp->exportAndFillComplete(Acprime,
293 Acprime->getRangeMap(),
294 rcp(&labelList,
false));
296#ifdef HAVE_TPETRA_MMM_STATISTICS
297 printMultiplicationStatistics(Actemp->getGraph()->getExporter(), label + std::string(
" RAP MMM"));
306template <
class Scalar,
310void mult_R_A_P_newmatrix(
311 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Rview,
312 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
313 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
314 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
315 const std::string& label,
316 const Teuchos::RCP<Teuchos::ParameterList>& params) {
317 using Teuchos::Array;
318 using Teuchos::ArrayRCP;
319 using Teuchos::ArrayView;
324 typedef LocalOrdinal LO;
325 typedef GlobalOrdinal GO;
328 typedef Import<LO, GO, NO> import_type;
329 typedef Map<LO, GO, NO> map_type;
332 typedef typename map_type::local_map_type local_map_type;
334 typedef typename KCRS::StaticCrsGraphType graph_t;
335 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
336 typedef typename NO::execution_space execution_space;
337 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
338 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
340#ifdef HAVE_TPETRA_MMM_TIMINGS
341 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
342 using Teuchos::TimeMonitor;
343 RCP<TimeMonitor> MM = rcp(
new TimeMonitor(*(TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP M5 Cmap")))));
345 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
348 RCP<const import_type> Cimport;
349 RCP<const map_type> Ccolmap;
350 RCP<const import_type> Pimport = Pview.origMatrix->getGraph()->getImporter();
351 RCP<const import_type> Iimport = Pview.importMatrix.is_null() ? Teuchos::null : Pview.importMatrix->getGraph()->getImporter();
352 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
353 local_map_type Prowmap_local = Pview.origMatrix->getRowMap()->getLocalMap();
354 local_map_type Irowmap_local;
355 if (!Pview.importMatrix.is_null()) Irowmap_local = Pview.importMatrix->getRowMap()->getLocalMap();
356 local_map_type Pcolmap_local = Pview.origMatrix->getColMap()->getLocalMap();
357 local_map_type Icolmap_local;
358 if (!Pview.importMatrix.is_null()) Icolmap_local = Pview.importMatrix->getColMap()->getLocalMap();
365 lo_view_t Pcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Pcol2Ccol"), Pview.colMap->getLocalNumElements()), Icol2Ccol;
367 if (Pview.importMatrix.is_null()) {
370 Ccolmap = Pview.colMap;
371 const LO colMapSize =
static_cast<LO
>(Pview.colMap->getLocalNumElements());
373 Kokkos::parallel_for(
374 "Tpetra::mult_R_A_P_newmatrix::Pcol2Ccol_fill",
375 Kokkos::RangePolicy<execution_space, LO>(0, colMapSize),
376 KOKKOS_LAMBDA(
const LO i) {
388 if (!Pimport.is_null() && !Iimport.is_null()) {
389 Cimport = Pimport->setUnion(*Iimport);
390 }
else if (!Pimport.is_null() && Iimport.is_null()) {
391 Cimport = Pimport->setUnion();
392 }
else if (Pimport.is_null() && !Iimport.is_null()) {
393 Cimport = Iimport->setUnion();
395 throw std::runtime_error(
"TpetraExt::RAP status of matrix importers is nonsensical");
397 Ccolmap = Cimport->getTargetMap();
402 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Pview.origMatrix->getDomainMap()),
403 std::runtime_error,
"Tpetra::RAP: Import setUnion messed with the DomainMap in an unfortunate way");
410 Kokkos::resize(Icol2Ccol, Pview.importMatrix->getColMap()->getLocalNumElements());
411 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
412 Kokkos::parallel_for(
413 "Tpetra::mult_R_A_P_newmatrix::Pcol2Ccol_getGlobalElement", range_type(0, Pview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
414 Pcol2Ccol(i) = Ccolmap_local.getLocalElement(Pcolmap_local.getGlobalElement(i));
416 Kokkos::parallel_for(
417 "Tpetra::mult_R_A_P_newmatrix::Icol2Ccol_getGlobalElement", range_type(0, Pview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
418 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
426 Ac.replaceColMap(Ccolmap);
444 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
445 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
446 Kokkos::parallel_for(
447 "Tpetra::mult_R_A_P_newmatrix::construct_tables", range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
448 GO aidx = Acolmap_local.getGlobalElement(i);
449 LO P_LID = Prowmap_local.getLocalElement(aidx);
450 if (P_LID != LO_INVALID) {
451 targetMapToOrigRow(i) = P_LID;
452 targetMapToImportRow(i) = LO_INVALID;
454 LO I_LID = Irowmap_local.getLocalElement(aidx);
455 targetMapToOrigRow(i) = LO_INVALID;
456 targetMapToImportRow(i) = I_LID;
462 KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::
463 mult_R_A_P_newmatrix_kernel_wrapper(Rview, Aview, Pview,
464 targetMapToOrigRow, targetMapToImportRow, Pcol2Ccol, Icol2Ccol,
465 Ac, Cimport, label, params);
469template <
class Scalar,
473void mult_R_A_P_reuse(
474 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Rview,
475 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
476 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
477 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
478 const std::string& label,
479 const Teuchos::RCP<Teuchos::ParameterList>& params) {
480 using Teuchos::Array;
481 using Teuchos::ArrayRCP;
482 using Teuchos::ArrayView;
487 typedef LocalOrdinal LO;
488 typedef GlobalOrdinal GO;
491 typedef Import<LO, GO, NO> import_type;
492 typedef Map<LO, GO, NO> map_type;
495 typedef typename map_type::local_map_type local_map_type;
497 typedef typename KCRS::StaticCrsGraphType graph_t;
498 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
499 typedef typename NO::execution_space execution_space;
500 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
501 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
503#ifdef HAVE_TPETRA_MMM_TIMINGS
504 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
505 using Teuchos::TimeMonitor;
506 RCP<TimeMonitor> MM = rcp(
new TimeMonitor(*(TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP M5 Cmap")))));
508 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
511 RCP<const import_type> Cimport = Ac.getGraph()->getImporter();
512 RCP<const map_type> Ccolmap = Ac.getColMap();
513 RCP<const import_type> Pimport = Pview.origMatrix->getGraph()->getImporter();
514 RCP<const import_type> Iimport = Pview.importMatrix.is_null() ? Teuchos::null : Pview.importMatrix->getGraph()->getImporter();
515 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
516 local_map_type Prowmap_local = Pview.origMatrix->getRowMap()->getLocalMap();
517 local_map_type Irowmap_local;
518 if (!Pview.importMatrix.is_null()) Irowmap_local = Pview.importMatrix->getRowMap()->getLocalMap();
519 local_map_type Pcolmap_local = Pview.origMatrix->getColMap()->getLocalMap();
520 local_map_type Icolmap_local;
521 if (!Pview.importMatrix.is_null()) Icolmap_local = Pview.importMatrix->getColMap()->getLocalMap();
522 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
525 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Pview.colMap->getLocalNumElements()), Icol2Ccol;
529 Kokkos::parallel_for(
530 range_type(0, Pview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
531 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Pcolmap_local.getGlobalElement(i));
534 if (!Pview.importMatrix.is_null()) {
535 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Pview.origMatrix->getDomainMap()),
536 std::runtime_error,
"Tpetra::MMM: Import setUnion messed with the DomainMap in an unfortunate way");
538 Kokkos::resize(Icol2Ccol, Pview.importMatrix->getColMap()->getLocalNumElements());
539 Kokkos::parallel_for(
540 range_type(0, Pview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
541 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
547 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
548 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
549 Kokkos::parallel_for(
550 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
551 GO aidx = Acolmap_local.getGlobalElement(i);
552 LO B_LID = Prowmap_local.getLocalElement(aidx);
553 if (B_LID != LO_INVALID) {
554 targetMapToOrigRow(i) = B_LID;
555 targetMapToImportRow(i) = LO_INVALID;
557 LO I_LID = Irowmap_local.getLocalElement(aidx);
558 targetMapToOrigRow(i) = LO_INVALID;
559 targetMapToImportRow(i) = I_LID;
565 KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::
566 mult_R_A_P_reuse_kernel_wrapper(Rview, Aview, Pview,
567 targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol,
568 Ac, Cimport, label, params);
572template <
class Scalar,
576void mult_PT_A_P_newmatrix(
577 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
578 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
579 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
580 const std::string& label,
581 const Teuchos::RCP<Teuchos::ParameterList>& params) {
582 using Teuchos::Array;
583 using Teuchos::ArrayRCP;
584 using Teuchos::ArrayView;
589 typedef LocalOrdinal LO;
590 typedef GlobalOrdinal GO;
593 typedef Import<LO, GO, NO> import_type;
594 typedef Map<LO, GO, NO> map_type;
597 typedef typename map_type::local_map_type local_map_type;
599 typedef typename KCRS::StaticCrsGraphType graph_t;
600 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
601 typedef typename NO::execution_space execution_space;
602 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
603 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
605#ifdef HAVE_TPETRA_MMM_TIMINGS
606 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
607 using Teuchos::TimeMonitor;
608 RCP<TimeMonitor> MM = rcp(
new TimeMonitor(*(TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP M5 Cmap")))));
610 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
613 RCP<const import_type> Cimport;
614 RCP<const map_type> Ccolmap;
615 RCP<const import_type> Pimport = Pview.origMatrix->getGraph()->getImporter();
616 RCP<const import_type> Iimport = Pview.importMatrix.is_null() ? Teuchos::null : Pview.importMatrix->getGraph()->getImporter();
617 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
618 local_map_type Prowmap_local = Pview.origMatrix->getRowMap()->getLocalMap();
619 local_map_type Irowmap_local;
620 if (!Pview.importMatrix.is_null()) Irowmap_local = Pview.importMatrix->getRowMap()->getLocalMap();
621 local_map_type Pcolmap_local = Pview.origMatrix->getColMap()->getLocalMap();
622 local_map_type Icolmap_local;
623 if (!Pview.importMatrix.is_null()) Icolmap_local = Pview.importMatrix->getColMap()->getLocalMap();
630 lo_view_t Pcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Pcol2Ccol"), Pview.colMap->getLocalNumElements()), Icol2Ccol;
632 if (Pview.importMatrix.is_null()) {
635 Ccolmap = Pview.colMap;
636 const LO colMapSize =
static_cast<LO
>(Pview.colMap->getLocalNumElements());
638 Kokkos::parallel_for(
639 "Tpetra::mult_R_A_P_newmatrix::Pcol2Ccol_fill",
640 Kokkos::RangePolicy<execution_space, LO>(0, colMapSize),
641 KOKKOS_LAMBDA(
const LO i) {
653 if (!Pimport.is_null() && !Iimport.is_null()) {
654 Cimport = Pimport->setUnion(*Iimport);
655 }
else if (!Pimport.is_null() && Iimport.is_null()) {
656 Cimport = Pimport->setUnion();
657 }
else if (Pimport.is_null() && !Iimport.is_null()) {
658 Cimport = Iimport->setUnion();
660 throw std::runtime_error(
"TpetraExt::RAP status of matrix importers is nonsensical");
662 Ccolmap = Cimport->getTargetMap();
667 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Pview.origMatrix->getDomainMap()),
668 std::runtime_error,
"Tpetra::RAP: Import setUnion messed with the DomainMap in an unfortunate way");
675 Kokkos::resize(Icol2Ccol, Pview.importMatrix->getColMap()->getLocalNumElements());
676 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
677 Kokkos::parallel_for(
678 "Tpetra::mult_R_A_P_newmatrix::Pcol2Ccol_getGlobalElement", range_type(0, Pview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
679 Pcol2Ccol(i) = Ccolmap_local.getLocalElement(Pcolmap_local.getGlobalElement(i));
681 Kokkos::parallel_for(
682 "Tpetra::mult_R_A_P_newmatrix::Icol2Ccol_getGlobalElement", range_type(0, Pview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
683 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
691 Ac.replaceColMap(Ccolmap);
709 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
710 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
712 Kokkos::parallel_for(
713 "Tpetra::mult_R_A_P_newmatrix::construct_tables", range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
714 GO aidx = Acolmap_local.getGlobalElement(i);
715 LO P_LID = Prowmap_local.getLocalElement(aidx);
716 if (P_LID != LO_INVALID) {
717 targetMapToOrigRow(i) = P_LID;
718 targetMapToImportRow(i) = LO_INVALID;
720 LO I_LID = Irowmap_local.getLocalElement(aidx);
721 targetMapToOrigRow(i) = LO_INVALID;
722 targetMapToImportRow(i) = I_LID;
728 KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::
729 mult_PT_A_P_newmatrix_kernel_wrapper(Aview, Pview,
730 targetMapToOrigRow, targetMapToImportRow, Pcol2Ccol, Icol2Ccol,
731 Ac, Cimport, label, params);
735template <
class Scalar,
739void mult_PT_A_P_reuse(
740 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
741 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
742 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
743 const std::string& label,
744 const Teuchos::RCP<Teuchos::ParameterList>& params) {
745 using Teuchos::Array;
746 using Teuchos::ArrayRCP;
747 using Teuchos::ArrayView;
752 typedef LocalOrdinal LO;
753 typedef GlobalOrdinal GO;
756 typedef Import<LO, GO, NO> import_type;
757 typedef Map<LO, GO, NO> map_type;
760 typedef typename map_type::local_map_type local_map_type;
762 typedef typename KCRS::StaticCrsGraphType graph_t;
763 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
764 typedef typename NO::execution_space execution_space;
765 typedef Kokkos::RangePolicy<execution_space, size_t> range_type;
766 typedef Kokkos::View<LO*, typename lno_view_t::array_layout, typename lno_view_t::device_type> lo_view_t;
768#ifdef HAVE_TPETRA_MMM_TIMINGS
769 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
770 using Teuchos::TimeMonitor;
771 RCP<TimeMonitor> MM = rcp(
new TimeMonitor(*(TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP M5 Cmap")))));
773 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
776 RCP<const import_type> Cimport = Ac.getGraph()->getImporter();
777 RCP<const map_type> Ccolmap = Ac.getColMap();
778 RCP<const import_type> Pimport = Pview.origMatrix->getGraph()->getImporter();
779 RCP<const import_type> Iimport = Pview.importMatrix.is_null() ? Teuchos::null : Pview.importMatrix->getGraph()->getImporter();
780 local_map_type Acolmap_local = Aview.colMap->getLocalMap();
781 local_map_type Prowmap_local = Pview.origMatrix->getRowMap()->getLocalMap();
782 local_map_type Irowmap_local;
783 if (!Pview.importMatrix.is_null()) Irowmap_local = Pview.importMatrix->getRowMap()->getLocalMap();
784 local_map_type Pcolmap_local = Pview.origMatrix->getColMap()->getLocalMap();
785 local_map_type Icolmap_local;
786 if (!Pview.importMatrix.is_null()) Icolmap_local = Pview.importMatrix->getColMap()->getLocalMap();
787 local_map_type Ccolmap_local = Ccolmap->getLocalMap();
790 lo_view_t Bcol2Ccol(Kokkos::ViewAllocateWithoutInitializing(
"Bcol2Ccol"), Pview.colMap->getLocalNumElements()), Icol2Ccol;
794 Kokkos::parallel_for(
795 range_type(0, Pview.origMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
796 Bcol2Ccol(i) = Ccolmap_local.getLocalElement(Pcolmap_local.getGlobalElement(i));
799 if (!Pview.importMatrix.is_null()) {
800 TEUCHOS_TEST_FOR_EXCEPTION(!Cimport->getSourceMap()->isSameAs(*Pview.origMatrix->getDomainMap()),
801 std::runtime_error,
"Tpetra::MMM: Import setUnion messed with the DomainMap in an unfortunate way");
803 Kokkos::resize(Icol2Ccol, Pview.importMatrix->getColMap()->getLocalNumElements());
804 Kokkos::parallel_for(
805 range_type(0, Pview.importMatrix->getColMap()->getLocalNumElements()), KOKKOS_LAMBDA(
const LO i) {
806 Icol2Ccol(i) = Ccolmap_local.getLocalElement(Icolmap_local.getGlobalElement(i));
812 lo_view_t targetMapToOrigRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToOrigRow"), Aview.colMap->getLocalNumElements());
813 lo_view_t targetMapToImportRow(Kokkos::ViewAllocateWithoutInitializing(
"targetMapToImportRow"), Aview.colMap->getLocalNumElements());
814 Kokkos::parallel_for(
815 range_type(Aview.colMap->getMinLocalIndex(), Aview.colMap->getMaxLocalIndex() + 1), KOKKOS_LAMBDA(
const LO i) {
816 GO aidx = Acolmap_local.getGlobalElement(i);
817 LO B_LID = Prowmap_local.getLocalElement(aidx);
818 if (B_LID != LO_INVALID) {
819 targetMapToOrigRow(i) = B_LID;
820 targetMapToImportRow(i) = LO_INVALID;
822 LO I_LID = Irowmap_local.getLocalElement(aidx);
823 targetMapToOrigRow(i) = LO_INVALID;
824 targetMapToImportRow(i) = I_LID;
830 KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, lo_view_t>::
831 mult_PT_A_P_reuse_kernel_wrapper(Aview, Pview,
832 targetMapToOrigRow, targetMapToImportRow, Bcol2Ccol, Icol2Ccol,
833 Ac, Cimport, label, params);
839template <
class Scalar,
843 class LocalOrdinalViewType>
844void KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_R_A_P_newmatrix_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Rview,
845 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
846 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
847 const LocalOrdinalViewType& Acol2Prow_dev,
848 const LocalOrdinalViewType& Acol2PIrow_dev,
849 const LocalOrdinalViewType& Pcol2Accol_dev,
850 const LocalOrdinalViewType& PIcol2Accol_dev,
851 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
852 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node> > Acimport,
853 const std::string& label,
854 const Teuchos::RCP<Teuchos::ParameterList>& params) {
855#ifdef HAVE_TPETRA_MMM_TIMINGS
856 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
857 using Teuchos::TimeMonitor;
858 Teuchos::RCP<Teuchos::TimeMonitor> MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Newmatrix SerialCore"))));
861 using Teuchos::Array;
862 using Teuchos::ArrayRCP;
863 using Teuchos::ArrayView;
869 typedef typename KCRS::StaticCrsGraphType graph_t;
870 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
871 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
872 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
873 typedef typename KCRS::values_type::non_const_type scalar_view_t;
876 typedef LocalOrdinal LO;
877 typedef GlobalOrdinal GO;
879 typedef Map<LO, GO, NO> map_type;
880 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
881 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
882 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
885 RCP<const map_type> Accolmap = Ac.getColMap();
886 size_t m = Rview.origMatrix->getLocalNumRows();
887 size_t n = Accolmap->getLocalNumElements();
888 size_t p_max_nnz_per_row = Pview.origMatrix->getLocalMaxNumRowEntries();
891 auto Acol2Prow = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
893 auto Acol2PIrow = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
895 auto Pcol2Accol = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
897 auto PIcol2Accol = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
901 const auto Amat = Aview.origMatrix->getLocalMatrixHost();
902 const auto Pmat = Pview.origMatrix->getLocalMatrixHost();
903 const auto Rmat = Rview.origMatrix->getLocalMatrixHost();
905 auto Arowptr = Amat.graph.row_map;
906 auto Prowptr = Pmat.graph.row_map;
907 auto Rrowptr = Rmat.graph.row_map;
908 const auto Acolind = Amat.graph.entries;
909 const auto Pcolind = Pmat.graph.entries;
910 const auto Rcolind = Rmat.graph.entries;
911 const auto Avals = Amat.values;
912 const auto Pvals = Pmat.values;
913 const auto Rvals = Rmat.values;
915 typename c_lno_view_t::host_mirror_type::const_type Irowptr;
916 typename lno_nnz_view_t::host_mirror_type Icolind;
917 typename scalar_view_t::host_mirror_type Ivals;
918 if (!Pview.importMatrix.is_null()) {
919 auto lclP = Pview.importMatrix->getLocalMatrixHost();
920 Irowptr = lclP.graph.row_map;
921 Icolind = lclP.graph.entries;
923 p_max_nnz_per_row = std::max(p_max_nnz_per_row, Pview.importMatrix->getLocalMaxNumRowEntries());
926#ifdef HAVE_TPETRA_MMM_TIMINGS
927 RCP<TimeMonitor> MM2 = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Newmatrix SerialCore - Compare"))));
937 size_t CSR_alloc = std::max(C_estimate_nnz(*Aview.origMatrix, *Pview.origMatrix), n);
938 typename lno_view_t::host_mirror_type Crowptr(Kokkos::ViewAllocateWithoutInitializing(
"Crowptr"), m + 1);
939 typename lno_nnz_view_t::host_mirror_type Ccolind(Kokkos::ViewAllocateWithoutInitializing(
"Ccolind"), CSR_alloc);
940 typename scalar_view_t::host_mirror_type Cvals(Kokkos::ViewAllocateWithoutInitializing(
"Cvals"), CSR_alloc);
950 const size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
951 Array<size_t> ac_status(n, ST_INVALID);
961 size_t nnz = 0, nnz_old = 0;
962 for (
size_t i = 0; i < m; i++) {
968 for (
size_t kk = Rrowptr[i]; kk < Rrowptr[i + 1]; kk++) {
970 const SC Rik = Rvals[kk];
974 for (
size_t ll = Arowptr[k]; ll < Arowptr[k + 1]; ll++) {
976 const SC Akl = Avals[ll];
980 if (Acol2Prow[l] != LO_INVALID) {
987 size_t Pl = Teuchos::as<size_t>(Acol2Prow[l]);
990 for (
size_t jj = Prowptr[Pl]; jj < Prowptr[Pl + 1]; jj++) {
992 LO Acj = Pcol2Accol[j];
995 if (ac_status[Acj] == INVALID || ac_status[Acj] < nnz_old) {
996#ifdef HAVE_TPETRA_DEBUG
998 TEUCHOS_TEST_FOR_EXCEPTION(nnz >= Teuchos::as<size_t>(Ccolind.size()),
1000 label <<
" ERROR, not enough memory allocated for matrix product. Allocated: " << Ccolind.extent(0) << std::endl);
1003 ac_status[Acj] = nnz;
1005 Cvals[nnz] = Rik * Akl * Plj;
1008 Cvals[ac_status[Acj]] += Rik * Akl * Plj;
1018 size_t Il = Teuchos::as<size_t>(Acol2PIrow[l]);
1019 for (
size_t jj = Irowptr[Il]; jj < Irowptr[Il + 1]; jj++) {
1021 LO Acj = PIcol2Accol[j];
1024 if (ac_status[Acj] == INVALID || ac_status[Acj] < nnz_old) {
1025#ifdef HAVE_TPETRA_DEBUG
1027 TEUCHOS_TEST_FOR_EXCEPTION(nnz >= Teuchos::as<size_t>(Ccolind.size()),
1029 label <<
" ERROR, not enough memory allocated for matrix product. Allocated: " << Ccolind.extent(0) << std::endl);
1032 ac_status[Acj] = nnz;
1034 Cvals[nnz] = Rik * Akl * Plj;
1037 Cvals[ac_status[Acj]] += Rik * Akl * Plj;
1044 if (nnz + n > CSR_alloc) {
1046 Kokkos::resize(Ccolind, CSR_alloc);
1047 Kokkos::resize(Cvals, CSR_alloc);
1055 Kokkos::resize(Ccolind, nnz);
1056 Kokkos::resize(Cvals, nnz);
1058#ifdef HAVE_TPETRA_MMM_TIMINGS
1060 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Newmatrix Final Sort"))));
1062 auto Crowptr_dev = Kokkos::create_mirror_view_and_copy(
1063 typename KCRS::device_type(), Crowptr);
1064 auto Ccolind_dev = Kokkos::create_mirror_view_and_copy(
1065 typename KCRS::device_type(), Ccolind);
1066 auto Cvals_dev = Kokkos::create_mirror_view_and_copy(
1067 typename KCRS::device_type(), Cvals);
1070 if (params.is_null() || params->get(
"sort entries",
true))
1071 Import_Util::sortCrsEntries(Crowptr_dev, Ccolind_dev, Cvals_dev);
1072 Ac.setAllValues(Crowptr_dev, Ccolind_dev, Cvals_dev);
1074#ifdef HAVE_TPETRA_MMM_TIMINGS
1076 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Newmatrix ESFC"))));
1087 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
1088 labelList->set(
"Timer Label", label);
1089 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
1090 RCP<const Export<LO, GO, NO> > dummyExport;
1091 Ac.expertStaticFillComplete(Pview.origMatrix->getDomainMap(),
1092 Rview.origMatrix->getRangeMap(),
1101template <
class Scalar,
1103 class GlobalOrdinal,
1105 class LocalOrdinalViewType>
1106void KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_R_A_P_reuse_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Rview,
1107 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1108 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
1109 const LocalOrdinalViewType& Acol2Prow_dev,
1110 const LocalOrdinalViewType& Acol2PIrow_dev,
1111 const LocalOrdinalViewType& Pcol2Accol_dev,
1112 const LocalOrdinalViewType& PIcol2Accol_dev,
1113 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
1114 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node> > Acimport,
1115 const std::string& label,
1116 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1117#ifdef HAVE_TPETRA_MMM_TIMINGS
1118 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
1119 using Teuchos::TimeMonitor;
1120 Teuchos::RCP<Teuchos::TimeMonitor> MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Reuse SerialCore"))));
1123 using Teuchos::Array;
1124 using Teuchos::ArrayRCP;
1125 using Teuchos::ArrayView;
1130 typedef typename Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_host_type KCRS;
1131 typedef typename KCRS::StaticCrsGraphType graph_t;
1132 typedef typename graph_t::row_map_type::const_type c_lno_view_t;
1133 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1134 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1137 typedef LocalOrdinal LO;
1138 typedef GlobalOrdinal GO;
1140 typedef Map<LO, GO, NO> map_type;
1141 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1142 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1143 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
1146 RCP<const map_type> Accolmap = Ac.getColMap();
1147 size_t m = Rview.origMatrix->getLocalNumRows();
1148 size_t n = Accolmap->getLocalNumElements();
1149 size_t p_max_nnz_per_row = Pview.origMatrix->getLocalMaxNumRowEntries();
1152 auto Acol2Prow = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1154 auto Acol2PIrow = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1156 auto Pcol2Accol = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1158 auto PIcol2Accol = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
1162 const KCRS Amat = Aview.origMatrix->getLocalMatrixHost();
1163 const KCRS Pmat = Pview.origMatrix->getLocalMatrixHost();
1164 const KCRS Rmat = Rview.origMatrix->getLocalMatrixHost();
1165 const KCRS Cmat = Ac.getLocalMatrixHost();
1167 c_lno_view_t Arowptr = Amat.graph.row_map, Prowptr = Pmat.graph.row_map, Rrowptr = Rmat.graph.row_map, Crowptr = Cmat.graph.row_map;
1168 const lno_nnz_view_t Acolind = Amat.graph.entries, Pcolind = Pmat.graph.entries, Rcolind = Rmat.graph.entries, Ccolind = Cmat.graph.entries;
1169 const scalar_view_t Avals = Amat.values, Pvals = Pmat.values, Rvals = Rmat.values;
1170 scalar_view_t Cvals = Cmat.values;
1172 c_lno_view_t Irowptr;
1173 lno_nnz_view_t Icolind;
1174 scalar_view_t Ivals;
1175 if (!Pview.importMatrix.is_null()) {
1176 auto lclP = Pview.importMatrix->getLocalMatrixHost();
1177 Irowptr = lclP.graph.row_map;
1178 Icolind = lclP.graph.entries;
1179 Ivals = lclP.values;
1180 p_max_nnz_per_row = std::max(p_max_nnz_per_row, Pview.importMatrix->getLocalMaxNumRowEntries());
1183#ifdef HAVE_TPETRA_MMM_TIMINGS
1184 RCP<TimeMonitor> MM2 = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Reuse SerialCore - Compare"))));
1195 Array<size_t> ac_status(n, ST_INVALID);
1209 size_t OLD_ip = 0, CSR_ip = 0;
1210 for (
size_t i = 0; i < m; i++) {
1213 OLD_ip = Crowptr[i];
1214 CSR_ip = Crowptr[i + 1];
1215 for (
size_t k = OLD_ip; k < CSR_ip; k++) {
1216 ac_status[Ccolind[k]] = k;
1223 for (
size_t kk = Rrowptr[i]; kk < Rrowptr[i + 1]; kk++) {
1225 const SC Rik = Rvals[kk];
1229 for (
size_t ll = Arowptr[k]; ll < Arowptr[k + 1]; ll++) {
1231 const SC Akl = Avals[ll];
1235 if (Acol2Prow[l] != LO_INVALID) {
1242 size_t Pl = Teuchos::as<size_t>(Acol2Prow[l]);
1245 for (
size_t jj = Prowptr[Pl]; jj < Prowptr[Pl + 1]; jj++) {
1247 LO Cij = Pcol2Accol[j];
1250 TEUCHOS_TEST_FOR_EXCEPTION(ac_status[Cij] < OLD_ip || ac_status[Cij] >= CSR_ip,
1251 std::runtime_error,
"Trying to insert a new entry (" << i <<
"," << Cij <<
") into a static graph "
1252 <<
"(c_status = " << ac_status[Cij] <<
" of [" << OLD_ip <<
"," << CSR_ip <<
"))");
1254 Cvals[ac_status[Cij]] += Rik * Akl * Plj;
1263 size_t Il = Teuchos::as<size_t>(Acol2PIrow[l]);
1264 for (
size_t jj = Irowptr[Il]; jj < Irowptr[Il + 1]; jj++) {
1266 LO Cij = PIcol2Accol[j];
1269 TEUCHOS_TEST_FOR_EXCEPTION(ac_status[Cij] < OLD_ip || ac_status[Cij] >= CSR_ip,
1270 std::runtime_error,
"Trying to insert a new entry (" << i <<
"," << Cij <<
") into a static graph "
1271 <<
"(c_status = " << ac_status[Cij] <<
" of [" << OLD_ip <<
"," << CSR_ip <<
"))");
1273 Cvals[ac_status[Cij]] += Rik * Akl * Plj;
1280#ifdef HAVE_TPETRA_MMM_TIMINGS
1281 auto MM3 = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"RAP Reuse ESFC"))));
1284 Ac.fillComplete(Ac.getDomainMap(), Ac.getRangeMap());
1290template <
class Scalar,
1292 class GlobalOrdinal,
1294 class LocalOrdinalViewType>
1295void KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_PT_A_P_newmatrix_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1296 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
1297 const LocalOrdinalViewType& Acol2Prow,
1298 const LocalOrdinalViewType& Acol2PIrow,
1299 const LocalOrdinalViewType& Pcol2Accol,
1300 const LocalOrdinalViewType& PIcol2Accol,
1301 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
1302 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node> > Acimport,
1303 const std::string& label,
1304 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1305#ifdef HAVE_TPETRA_MMM_TIMINGS
1306 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
1307 using Teuchos::TimeMonitor;
1308 Teuchos::TimeMonitor MM(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP local transpose")));
1312 typedef RowMatrixTransposer<Scalar, LocalOrdinal, GlobalOrdinal, Node> transposer_type;
1313 transposer_type transposer(Pview.origMatrix, label + std::string(
"XP: "));
1315 using Teuchos::ParameterList;
1317 RCP<ParameterList> transposeParams(
new ParameterList);
1318 transposeParams->set(
"sort",
false);
1320 if (!params.is_null()) {
1321 transposeParams->set(
"compute global constants",
1322 params->get(
"compute global constants: temporaries",
1325 RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Ptrans =
1326 transposer.createTransposeLocal(transposeParams);
1327 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node> Rview;
1328 Rview.origMatrix = Ptrans;
1330 mult_R_A_P_newmatrix_kernel_wrapper(Rview, Aview, Pview, Acol2Prow, Acol2PIrow, Pcol2Accol, PIcol2Accol, Ac, Acimport, label, params);
1336template <
class Scalar,
1338 class GlobalOrdinal,
1340 class LocalOrdinalViewType>
1341void KernelWrappers3<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalOrdinalViewType>::mult_PT_A_P_reuse_kernel_wrapper(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1342 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
1343 const LocalOrdinalViewType& Acol2Prow,
1344 const LocalOrdinalViewType& Acol2PIrow,
1345 const LocalOrdinalViewType& Pcol2Accol,
1346 const LocalOrdinalViewType& PIcol2Accol,
1347 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
1348 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node> > Acimport,
1349 const std::string& label,
1350 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1351#ifdef HAVE_TPETRA_MMM_TIMINGS
1352 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
1353 using Teuchos::TimeMonitor;
1354 Teuchos::TimeMonitor MM(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP local transpose")));
1358 typedef RowMatrixTransposer<Scalar, LocalOrdinal, GlobalOrdinal, Node> transposer_type;
1359 transposer_type transposer(Pview.origMatrix, label + std::string(
"XP: "));
1361 using Teuchos::ParameterList;
1363 RCP<ParameterList> transposeParams(
new ParameterList);
1364 transposeParams->set(
"sort",
false);
1366 if (!params.is_null()) {
1367 transposeParams->set(
"compute global constants",
1368 params->get(
"compute global constants: temporaries",
1371 RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Ptrans =
1372 transposer.createTransposeLocal(transposeParams);
1373 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node> Rview;
1374 Rview.origMatrix = Ptrans;
1376 mult_R_A_P_reuse_kernel_wrapper(Rview, Aview, Pview, Acol2Prow, Acol2PIrow, Pcol2Accol, PIcol2Accol, Ac, Acimport, label, params);
1384template <
class Scalar,
1386 class GlobalOrdinal,
1388void KernelWrappers3MMM<Scalar, LocalOrdinal, GlobalOrdinal, Node>::mult_PT_A_P_newmatrix_kernel_wrapper_2pass(CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Aview,
1389 CrsMatrixStruct<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Pview,
1390 const Teuchos::Array<LocalOrdinal>& Acol2PRow,
1391 const Teuchos::Array<LocalOrdinal>& Acol2PRowImport,
1392 const Teuchos::Array<LocalOrdinal>& Pcol2Accol,
1393 const Teuchos::Array<LocalOrdinal>& PIcol2Accol,
1394 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Ac,
1395 Teuchos::RCP<
const Import<LocalOrdinal, GlobalOrdinal, Node> > Acimport,
1396 const std::string& label,
1397 const Teuchos::RCP<Teuchos::ParameterList>& params) {
1398#ifdef HAVE_TPETRA_MMM_TIMINGS
1399 std::string prefix_mmm = std::string(
"TpetraExt ") + label + std::string(
": ");
1400 using Teuchos::TimeMonitor;
1401 Teuchos::RCP<Teuchos::TimeMonitor> MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP Newmatrix SerialCore"))));
1404 using Teuchos::Array;
1405 using Teuchos::ArrayRCP;
1406 using Teuchos::ArrayView;
1411 typedef LocalOrdinal LO;
1412 typedef GlobalOrdinal GO;
1414 typedef RowMatrixTransposer<SC, LO, GO, NO> transposer_type;
1415 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1416 const SC SC_ZERO = Teuchos::ScalarTraits<Scalar>::zero();
1421 size_t n = Ac.getRowMap()->getLocalNumElements();
1422 LO maxAccol = Ac.getColMap()->getMaxLocalIndex();
1425 ArrayRCP<size_t> Acrowptr_RCP;
1426 ArrayRCP<LO> Accolind_RCP;
1427 ArrayRCP<SC> Acvals_RCP;
1434 auto Arowptr = Aview.origMatrix->getLocalRowPtrsHost();
1435 auto Acolind = Aview.origMatrix->getLocalIndicesHost();
1436 auto Avals = Aview.origMatrix->getLocalValuesHost(
1437 Tpetra::Access::ReadOnly);
1438 auto Prowptr = Pview.origMatrix->getLocalRowPtrsHost();
1439 auto Pcolind = Pview.origMatrix->getLocalIndicesHost();
1440 auto Pvals = Pview.origMatrix->getLocalValuesHost(
1441 Tpetra::Access::ReadOnly);
1442 decltype(Prowptr) Irowptr;
1443 decltype(Pcolind) Icolind;
1444 decltype(Pvals) Ivals;
1446 if (!Pview.importMatrix.is_null()) {
1447 Irowptr = Pview.importMatrix->getLocalRowPtrsHost();
1448 Icolind = Pview.importMatrix->getLocalIndicesHost();
1449 Ivals = Pview.importMatrix->getLocalValuesHost(
1450 Tpetra::Access::ReadOnly);
1458 ArrayView<size_t> Acrowptr;
1459 ArrayView<LO> Accolind;
1460 ArrayView<SC> Acvals;
1471#ifdef HAVE_TPETRA_MMM_TIMINGS
1472 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP local transpose"))));
1479 transposer_type transposer(Pview.origMatrix, label + std::string(
"XP: "));
1481 using Teuchos::ParameterList;
1482 RCP<ParameterList> transposeParams(
new ParameterList);
1483 transposeParams->set(
"sort",
false);
1484 if (!params.is_null()) {
1485 transposeParams->set(
"compute global constants",
1486 params->get(
"compute global constants: temporaries",
1489 RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > Ptrans =
1490 transposer.createTransposeLocal(transposeParams);
1492 auto Rrowptr = Ptrans->getLocalRowPtrsHost();
1493 auto Rcolind = Ptrans->getLocalIndicesHost();
1494 auto Rvals = Ptrans->getLocalValuesHost(Tpetra::Access::ReadOnly);
1499#ifdef HAVE_TPETRA_MMM_TIMINGS
1500 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP graph"))));
1503 const size_t ST_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
1504 Array<size_t> ac_status(maxAccol + 1, ST_INVALID);
1506 size_t nnz_alloc = std::max(Ac_estimate_nnz(*Aview.origMatrix, *Pview.origMatrix), n);
1507 size_t nnzPerRowA = 100;
1508 if (Aview.origMatrix->getLocalNumEntries() > 0)
1509 nnzPerRowA = Aview.origMatrix->getLocalNumEntries() / Aview.origMatrix->getLocalNumRows();
1510 Acrowptr_RCP.resize(n + 1);
1511 Acrowptr = Acrowptr_RCP();
1512 Accolind_RCP.resize(nnz_alloc);
1513 Accolind = Accolind_RCP();
1515 size_t nnz = 0, nnz_old = 0;
1516 for (
size_t i = 0; i < n; i++) {
1522 for (
size_t kk = Rrowptr[i]; kk < Rrowptr[i + 1]; kk++) {
1525 for (
size_t ll = Arowptr[k]; ll < Arowptr[k + 1]; ll++) {
1528 if (Acol2PRow[l] != LO_INVALID) {
1535 size_t Pl = Teuchos::as<size_t>(Acol2PRow[l]);
1538 for (
size_t jj = Prowptr[Pl]; jj < Prowptr[Pl + 1]; jj++) {
1540 LO Acj = Pcol2Accol[j];
1542 if (ac_status[Acj] == ST_INVALID || ac_status[Acj] < nnz_old) {
1544 ac_status[Acj] = nnz;
1545 Accolind[nnz] = Acj;
1556 size_t Il = Teuchos::as<size_t>(Acol2PRowImport[l]);
1557 for (
size_t jj = Irowptr[Il]; jj < Irowptr[Il + 1]; jj++) {
1559 LO Acj = PIcol2Accol[j];
1561 if (ac_status[Acj] == ST_INVALID || ac_status[Acj] < nnz_old) {
1563 ac_status[Acj] = nnz;
1564 Accolind[nnz] = Acj;
1574 if (nnz + std::max(5 * nnzPerRowA, n) > nnz_alloc) {
1576 nnz_alloc = std::max(nnz_alloc, nnz + std::max(5 * nnzPerRowA, n));
1577 Accolind_RCP.resize(nnz_alloc);
1578 Accolind = Accolind_RCP();
1579 Acvals_RCP.resize(nnz_alloc);
1580 Acvals = Acvals_RCP();
1587 Accolind_RCP.resize(nnz);
1588 Accolind = Accolind_RCP();
1591 Acvals_RCP.resize(nnz, SC_ZERO);
1592 Acvals = Acvals_RCP();
1598#ifdef HAVE_TPETRA_MMM_TIMINGS
1599 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP Newmatrix Fill Matrix"))));
1602 for (
size_t k = 0; k < n; k++) {
1603 for (
size_t ii = Prowptr[k]; ii < Prowptr[k + 1]; ii++) {
1605 const SC Pki = Pvals[ii];
1606 for (
size_t ll = Arowptr[k]; ll < Arowptr[k + 1]; ll++) {
1608 const SC Akl = Avals[ll];
1611 if (Acol2PRow[l] != LO_INVALID) {
1618 size_t Pl = Teuchos::as<size_t>(Acol2PRow[l]);
1619 for (
size_t jj = Prowptr[Pl]; jj < Prowptr[Pl + 1]; jj++) {
1621 LO Acj = Pcol2Accol[j];
1623 for (pp = Acrowptr[i]; pp < Acrowptr[i + 1]; pp++)
1624 if (Accolind[pp] == Acj)
1628 Acvals[pp] += Pki * Akl * Pvals[jj];
1637 size_t Il = Teuchos::as<size_t>(Acol2PRowImport[l]);
1638 for (
size_t jj = Irowptr[Il]; jj < Irowptr[Il + 1]; jj++) {
1640 LO Acj = PIcol2Accol[j];
1642 for (pp = Acrowptr[i]; pp < Acrowptr[i + 1]; pp++)
1643 if (Accolind[pp] == Acj)
1647 Acvals[pp] += Pki * Akl * Ivals[jj];
1654#ifdef HAVE_TPETRA_MMM_TIMINGS
1655 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP sort"))));
1662 Import_Util::sortCrsEntries(Acrowptr_RCP(), Accolind_RCP(), Acvals_RCP());
1665 Ac.setAllValues(Acrowptr_RCP, Accolind_RCP, Acvals_RCP);
1667#ifdef HAVE_TPETRA_MMM_TIMINGS
1668 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix_mmm + std::string(
"PTAP Newmatrix ESFC"))));
1679 RCP<Teuchos::ParameterList> labelList = rcp(
new Teuchos::ParameterList);
1680 labelList->set(
"Timer Label", label);
1682 if (!params.is_null()) labelList->set(
"compute global constants", params->get(
"compute global constants",
true));
1683 RCP<const Export<LO, GO, NO> > dummyExport;
1684 Ac.expertStaticFillComplete(Pview.origMatrix->getDomainMap(),
1685 Pview.origMatrix->getDomainMap(),
1687 dummyExport, labelList);
1699#define TPETRA_TRIPLEMATRIXMULTIPLY_INSTANT(SCALAR, LO, GO, NODE) \
1701 template void TripleMatrixMultiply::MultiplyRAP( \
1702 const CrsMatrix<SCALAR, LO, GO, NODE>& R, \
1704 const CrsMatrix<SCALAR, LO, GO, NODE>& A, \
1706 const CrsMatrix<SCALAR, LO, GO, NODE>& P, \
1708 CrsMatrix<SCALAR, LO, GO, NODE>& Ac, \
1709 bool call_FillComplete_on_result, \
1710 const std::string& label, \
1711 const Teuchos::RCP<Teuchos::ParameterList>& params);
Utility functions for packing and unpacking sparse matrix entries.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects.
Stand-alone utility functions and macros.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries.
Teuchos::RCP< const map_type > getDomainMap() const override
The domain Map of this matrix.
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.
global_size_t getGlobalNumRows() const override
Number of global elements in the row map of this matrix.
Teuchos::RCP< const RowGraph< LocalOrdinal, GlobalOrdinal, Node > > getGraph() const override
This matrix's graph, as a RowGraph.
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...
bool isFillComplete() const override
Whether the matrix is fill complete.
Struct that holds views of the contents of a CrsMatrix.
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.
Construct and (optionally) redistribute the explicitly stored transpose of a CrsMatrix.
Distributed sparse triple matrix product.
void MultiplyRAP(const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &R, bool transposeR, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, bool transposeA, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &P, bool transposeP, CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Ac, bool call_FillComplete_on_result=true, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Sparse matrix-matrix multiply.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
size_t global_size_t
Global size_t object.