10#ifndef IFPACK2_LOCALSPARSETRIANGULARSOLVER_DEF_HPP
11#define IFPACK2_LOCALSPARSETRIANGULARSOLVER_DEF_HPP
13#include "Kokkos_Macros.hpp"
17#include "Ifpack2_LocalSparseTriangularSolver_decl.hpp"
18#include "Tpetra_CrsMatrix.hpp"
19#include "Tpetra_Core.hpp"
20#include "Teuchos_StandardParameterEntryValidators.hpp"
21#include "Tpetra_Details_determineLocalTriangularStructure.hpp"
22#include "KokkosSparse_sptrsv.hpp"
23#include "KokkosSparse_trsv.hpp"
25#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
26#include "shylu_hts.hpp"
33#if defined(KOKKOSKERNELS_ENABLE_TPL_CUSPARSE) && defined(KOKKOS_ENABLE_CUDA)
35inline void cusparse_error_throw(cusparseStatus_t cusparseStatus,
const char* name,
36 const char* file,
const int line) {
37 std::ostringstream out;
38#if defined(CUSPARSE_VERSION) && (10300 <= CUSPARSE_VERSION)
39 out << name <<
" error( " << cusparseGetErrorName(cusparseStatus) <<
"): " << cusparseGetErrorString(cusparseStatus);
41 out << name <<
" error( ";
42 switch (cusparseStatus) {
43 case CUSPARSE_STATUS_NOT_INITIALIZED:
44 out <<
"CUSPARSE_STATUS_NOT_INITIALIZED): cusparse handle was not "
47 case CUSPARSE_STATUS_ALLOC_FAILED:
48 out <<
"CUSPARSE_STATUS_ALLOC_FAILED): you might tried to allocate too "
51 case CUSPARSE_STATUS_INVALID_VALUE: out <<
"CUSPARSE_STATUS_INVALID_VALUE)";
break;
52 case CUSPARSE_STATUS_ARCH_MISMATCH: out <<
"CUSPARSE_STATUS_ARCH_MISMATCH)";
break;
53 case CUSPARSE_STATUS_MAPPING_ERROR: out <<
"CUSPARSE_STATUS_MAPPING_ERROR)";
break;
54 case CUSPARSE_STATUS_EXECUTION_FAILED: out <<
"CUSPARSE_STATUS_EXECUTION_FAILED)";
break;
55 case CUSPARSE_STATUS_INTERNAL_ERROR: out <<
"CUSPARSE_STATUS_INTERNAL_ERROR)";
break;
56 case CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED: out <<
"CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED)";
break;
57 case CUSPARSE_STATUS_ZERO_PIVOT: out <<
"CUSPARSE_STATUS_ZERO_PIVOT)";
break;
58 default: out <<
"unrecognized error code): this is bad!";
break;
62 out <<
" " << file <<
":" << line;
64 throw std::runtime_error(out.str());
67inline void cusparse_safe_call(cusparseStatus_t cusparseStatus,
const char* name,
const char* file =
nullptr,
69 if (CUSPARSE_STATUS_SUCCESS != cusparseStatus) {
70 cusparse_error_throw(cusparseStatus, name, file, line);
74#define IFPACK2_DETAILS_CUSPARSE_SAFE_CALL(call) \
75 Ifpack2::Details::cusparse_safe_call(call, #call, __FILE__, __LINE__)
86 static void loadPLTypeOption(Teuchos::Array<std::string>& type_strs, Teuchos::Array<Enum>& type_enums) {
88 type_strs[0] =
"Internal";
90 type_strs[2] =
"KSPTRSV";
92 type_enums[0] = Internal;
94 type_enums[2] = KSPTRSV;
99template <
class MatrixType>
100class LocalSparseTriangularSolver<MatrixType>::HtsImpl {
102 typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type>
crs_matrix_type;
105#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
106 Timpl_ = Teuchos::null;
107 levelset_block_size_ = 1;
113#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
114 const char* block_size_s =
"trisolver: block size";
115 if (pl.isParameter(block_size_s)) {
116 TEUCHOS_TEST_FOR_EXCEPT_MSG(!pl.isType<
int>(block_size_s),
117 "The parameter \"" << block_size_s <<
"\" must be of type int.");
118 levelset_block_size_ = pl.get<
int>(block_size_s);
120 if (levelset_block_size_ < 1)
121 levelset_block_size_ = 1;
130#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
132 transpose_ = conjugate_ =
false;
139#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
140 using Teuchos::ArrayRCP;
142 auto rowptr = T_in.getLocalRowPtrsHost();
143 auto colidx = T_in.getLocalIndicesHost();
144 auto val = T_in.getLocalValuesHost(Tpetra::Access::ReadOnly);
147 Teuchos::RCP<HtsCrsMatrix> T_hts = Teuchos::rcpWithDealloc(
148 HTST::make_CrsMatrix(rowptr.size() - 1,
149 rowptr.data(), colidx.data(),
152 transpose_, conjugate_),
153 HtsCrsMatrixDeleter());
155 if (Teuchos::nonnull(Timpl_)) {
157 HTST::reprocess_numeric(Timpl_.get(), T_hts.get());
160 if (T_in.getCrsGraph().is_null()) {
161 if (Teuchos::nonnull(out))
162 *out <<
"HTS compute failed because T_in.getCrsGraph().is_null().\n";
165 if (!T_in.getCrsGraph()->isSorted()) {
166 if (Teuchos::nonnull(out))
167 *out <<
"HTS compute failed because ! T_in.getCrsGraph().isSorted().\n";
170 if (!T_in.isStorageOptimized()) {
171 if (Teuchos::nonnull(out))
172 *out <<
"HTS compute failed because ! T_in.isStorageOptimized().\n";
176 typename HTST::PreprocessArgs args;
177 args.T = T_hts.get();
180 args.nthreads = omp_get_max_threads();
184 args.save_for_reprocess =
true;
185 typename HTST::Options opts;
186 opts.levelset_block_size = levelset_block_size_;
187 args.options = &opts;
190 Timpl_ = Teuchos::rcpWithDealloc(HTST::preprocess(args), TImplDeleter());
191 }
catch (
const std::exception& e) {
192 if (Teuchos::nonnull(out))
193 *out <<
"HTS preprocess threw: " << e.what() <<
"\n";
202#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
203 return Teuchos::nonnull(Timpl_);
210 void localApply(
const MV& X, MV& Y,
211 const Teuchos::ETransp ,
217#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
218 const auto& X_view = X.getLocalViewHost(Tpetra::Access::ReadOnly);
219 const auto& Y_view = Y.getLocalViewHost(Tpetra::Access::ReadWrite);
222 HTST::reset_max_nrhs(Timpl_.get(), X_view.extent(1));
224 HTST::solve_omp(Timpl_.get(),
226 reinterpret_cast<const scalar_type*
>(X_view.data()),
235#ifdef HAVE_IFPACK2_SHYLU_NODEHTS
236 typedef ::Experimental::HTS<local_ordinal_type, size_t, scalar_type> HTST;
237 typedef typename HTST::Impl TImpl;
238 typedef typename HTST::CrsMatrix HtsCrsMatrix;
240 struct TImplDeleter {
241 void free(TImpl* impl) {
242 HTST::delete_Impl(impl);
246 struct HtsCrsMatrixDeleter {
247 void free(HtsCrsMatrix* T) {
248 HTST::delete_CrsMatrix(T);
252 Teuchos::RCP<TImpl> Timpl_;
253 bool transpose_, conjugate_;
254 int levelset_block_size_;
258template <
class MatrixType>
265 Teuchos::RCP<const crs_matrix_type> A_crs =
266 Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A);
267 TEUCHOS_TEST_FOR_EXCEPTION(A_crs.is_null(), std::invalid_argument,
268 "Ifpack2::LocalSparseTriangularSolver constructor: "
269 "The input matrix A is not a Tpetra::CrsMatrix.");
274template <
class MatrixType>
277 const Teuchos::RCP<Teuchos::FancyOStream>& out)
281 if (!out_.is_null()) {
282 *out_ <<
">>> DEBUG Ifpack2::LocalSparseTriangularSolver constructor"
287 Teuchos::RCP<const crs_matrix_type> A_crs =
288 Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A);
289 TEUCHOS_TEST_FOR_EXCEPTION(A_crs.is_null(), std::invalid_argument,
290 "Ifpack2::LocalSparseTriangularSolver constructor: "
291 "The input matrix A is not a Tpetra::CrsMatrix.");
296template <
class MatrixType>
302template <
class MatrixType>
307 if (!out_.is_null()) {
308 *out_ <<
">>> DEBUG Ifpack2::LocalSparseTriangularSolver constructor"
313template <
class MatrixType>
315 isInitialized_ =
false;
317 reverseStorage_ =
false;
318 isInternallyChanged_ =
false;
322 initializeTime_ = 0.0;
325 isKokkosKernelsSptrsv_ =
false;
326 isKokkosKernelsStream_ =
false;
332template <
class MatrixType>
335 if (!isKokkosKernelsStream_) {
336 if (Teuchos::nonnull(kh_)) {
337 kh_->destroy_sptrsv_handle();
340 for (
size_t i = 0; i < kh_v_.size(); i++) {
341 if (Teuchos::nonnull(kh_v_[i])) {
342 kh_v_[i]->destroy_sptrsv_handle();
349template <
typename MatrixType>
350constexpr bool is_host_type() {
351 using node_type =
typename MatrixType::node_type;
352 return std::is_same_v<typename node_type::execution_space, Kokkos::Serial>
353#ifdef KOKKOS_ENABLE_THREADS
354 || std::is_same_v<typename node_type::execution_space, Kokkos::Threads>
356#ifdef KOKKOS_ENABLE_OPENMP
357 || std::is_same_v<typename node_type::execution_space, Kokkos::OpenMP>
363template <
class MatrixType>
366 using Teuchos::Array;
367 using Teuchos::ParameterList;
370 Details::TrisolverType::Enum trisolverType = is_host_type<MatrixType>() ? Details::TrisolverType::Internal : Details::TrisolverType::KSPTRSV;
372 static const char typeName[] =
"trisolver: type";
374 if (!pl.isType<std::string>(typeName))
break;
377 Array<std::string> trisolverTypeStrs;
378 Array<Details::TrisolverType::Enum> trisolverTypeEnums;
379 Details::TrisolverType::loadPLTypeOption(trisolverTypeStrs, trisolverTypeEnums);
380 Teuchos::StringToIntegralParameterEntryValidator<Details::TrisolverType::Enum>
381 s2i(trisolverTypeStrs(), trisolverTypeEnums(), typeName,
false);
383 trisolverType = s2i.getIntegralValue(pl.get<std::string>(typeName));
386 if (trisolverType == Details::TrisolverType::HTS) {
387 htsImpl_ = Teuchos::rcp(
new HtsImpl());
388 htsImpl_->setParameters(pl);
391 if (trisolverType == Details::TrisolverType::KSPTRSV) {
392 this->isKokkosKernelsSptrsv_ =
true;
394 this->isKokkosKernelsSptrsv_ =
false;
397 if (pl.isParameter(
"trisolver: reverse U"))
398 reverseStorage_ = pl.get<
bool>(
"trisolver: reverse U");
400 TEUCHOS_TEST_FOR_EXCEPTION(reverseStorage_ && (trisolverType == Details::TrisolverType::HTS || trisolverType == Details::TrisolverType::KSPTRSV),
402 "Ifpack2::LocalSparseTriangularSolver::setParameters: "
403 "You are not allowed to enable both HTS or KSPTRSV and the \"trisolver: reverse U\" "
404 "options. See GitHub issue #2647.");
407template <
class MatrixType>
410 using Tpetra::Details::determineLocalTriangularStructure;
412 using local_matrix_type =
typename crs_matrix_type::local_matrix_device_type;
415 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::initialize: ";
416 if (!out_.is_null()) {
417 *out_ <<
">>> DEBUG " << prefix << std::endl;
420 if (!isKokkosKernelsStream_) {
421 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error, prefix <<
"You must call "
422 "setMatrix() with a nonnull input matrix before you may call "
423 "initialize() or compute().");
424 if (A_crs_.is_null()) {
425 auto A_crs = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_);
426 TEUCHOS_TEST_FOR_EXCEPTION(A_crs.get() ==
nullptr, std::invalid_argument,
427 prefix <<
"The input matrix A is not a Tpetra::CrsMatrix.");
430 auto G = A_crs_->getGraph();
431 TEUCHOS_TEST_FOR_EXCEPTION(G.is_null(), std::logic_error, prefix <<
"A_ and A_crs_ are nonnull, "
432 "but A_crs_'s RowGraph G is null. "
433 "Please report this bug to the Ifpack2 developers.");
437 TEUCHOS_TEST_FOR_EXCEPTION(!G->isFillComplete(), std::runtime_error,
438 "If you call this method, "
439 "the matrix's graph must be fill complete. It is not.");
442 constexpr bool ignoreMapsForTriStructure =
true;
443 auto lclTriStructure = [&] {
444 auto lclMatrix = A_crs_->getLocalMatrixDevice();
445 auto lclRowMap = A_crs_->getRowMap()->getLocalMap();
446 auto lclColMap = A_crs_->getColMap()->getLocalMap();
448 determineLocalTriangularStructure(lclMatrix.graph,
451 ignoreMapsForTriStructure);
452 const LO lclNumRows = lclRowMap.getLocalNumElements();
453 this->diag_ = (lclTriStruct.diagCount < lclNumRows) ?
"U" :
"N";
454 this->uplo_ = lclTriStruct.couldBeLowerTriangular ?
"L" : (lclTriStruct.couldBeUpperTriangular ?
"U" :
"N");
458 if (reverseStorage_ && lclTriStructure.couldBeUpperTriangular &&
459 htsImpl_.is_null()) {
461 auto Alocal = A_crs_->getLocalMatrixDevice();
462 auto ptr = Alocal.graph.row_map;
463 auto ind = Alocal.graph.entries;
464 auto val = Alocal.values;
466 auto numRows = Alocal.numRows();
467 auto numCols = Alocal.numCols();
468 auto numNnz = Alocal.nnz();
470 typename decltype(ptr)::non_const_type newptr(
"ptr", ptr.extent(0));
471 typename decltype(ind)::non_const_type newind(
"ind", ind.extent(0));
472 decltype(val) newval(
"val", val.extent(0));
475 typename crs_matrix_type::execution_space().fence();
478 auto A_r = Alocal.row(numRows - 1 - row);
480 auto numEnt = A_r.length;
482 newind(rowStart + k) = numCols - 1 - A_r.colidx(numEnt - 1 - k);
483 newval(rowStart + k) = A_r.value(numEnt - 1 - k);
486 newptr(row + 1) = rowStart;
488 typename crs_matrix_type::execution_space().fence();
491 Teuchos::RCP<map_type> newRowMap, newColMap;
494 auto rowMap = A_->getRowMap();
495 auto numElems = rowMap->getLocalNumElements();
496 auto rowElems = rowMap->getLocalElementList();
498 Teuchos::Array<global_ordinal_type> newRowElems(rowElems.size());
499 for (
size_t i = 0; i < numElems; i++)
500 newRowElems[i] = rowElems[numElems - 1 - i];
502 newRowMap = Teuchos::rcp(
new map_type(rowMap->getGlobalNumElements(), newRowElems, rowMap->getIndexBase(), rowMap->getComm()));
506 auto colMap = A_->getColMap();
507 auto numElems = colMap->getLocalNumElements();
508 auto colElems = colMap->getLocalElementList();
510 Teuchos::Array<global_ordinal_type> newColElems(colElems.size());
511 for (
size_t i = 0; i < numElems; i++)
512 newColElems[i] = colElems[numElems - 1 - i];
514 newColMap = Teuchos::rcp(
new map_type(colMap->getGlobalNumElements(), newColElems, colMap->getIndexBase(), colMap->getComm()));
518 local_matrix_type newLocalMatrix(
"Upermuted", numRows, numCols, numNnz, newval, newptr, newind);
520 A_crs_ = Teuchos::rcp(
new crs_matrix_type(newLocalMatrix, newRowMap, newColMap, A_crs_->getDomainMap(), A_crs_->getRangeMap()));
522 isInternallyChanged_ =
true;
527 auto newLclTriStructure =
528 determineLocalTriangularStructure(newLocalMatrix.graph,
529 newRowMap->getLocalMap(),
530 newColMap->getLocalMap(),
531 ignoreMapsForTriStructure);
532 const LO newLclNumRows = newRowMap->getLocalNumElements();
533 this->diag_ = (newLclTriStructure.diagCount < newLclNumRows) ?
"U" :
"N";
534 this->uplo_ = newLclTriStructure.couldBeLowerTriangular ?
"L" : (newLclTriStructure.couldBeUpperTriangular ?
"U" :
"N");
537 bool prev_ambiguous =
false;
538 bool all_ambiguous =
true;
539 for (
int i = 0; i < num_streams_; i++) {
540 TEUCHOS_TEST_FOR_EXCEPTION(A_crs_v_[i].is_null(), std::runtime_error, prefix <<
"You must call "
541 "setMatrix() with a nonnull input matrix before you may call "
542 "initialize() or compute().");
543 auto G = A_crs_v_[i]->getGraph();
544 TEUCHOS_TEST_FOR_EXCEPTION(G.is_null(), std::logic_error, prefix <<
"A_crs_ are nonnull, "
545 "but A_crs_'s RowGraph G is null. "
546 "Please report this bug to the Ifpack2 developers.");
550 TEUCHOS_TEST_FOR_EXCEPTION(!G->isFillComplete(), std::runtime_error,
551 "If you call this method, "
552 "the matrix's graph must be fill complete. It is not.");
555 constexpr bool ignoreMapsForTriStructure =
true;
556 std::string prev_uplo = this->uplo_;
557 std::string prev_diag = this->diag_;
558 auto lclMatrix = A_crs_v_[i]->getLocalMatrixDevice();
559 auto lclRowMap = A_crs_v_[i]->getRowMap()->getLocalMap();
560 auto lclColMap = A_crs_v_[i]->getColMap()->getLocalMap();
562 determineLocalTriangularStructure(lclMatrix.graph,
565 ignoreMapsForTriStructure);
566 const LO lclNumRows = lclRowMap.getLocalNumElements();
567 this->diag_ = (lclTriStruct.diagCount < lclNumRows) ?
"U" :
"N";
568 const bool could_be_lower = lclTriStruct.couldBeLowerTriangular;
569 const bool could_be_upper = lclTriStruct.couldBeUpperTriangular;
570 if (could_be_lower && could_be_upper) {
572 this->uplo_ = prev_uplo;
573 prev_ambiguous =
true;
575 this->uplo_ = could_be_lower ?
"L" : (could_be_upper ?
"U" :
"N");
576 if (this->uplo_ !=
"N" && prev_uplo ==
"N" && prev_ambiguous) {
577 prev_uplo = this->uplo_;
579 prev_ambiguous =
false;
581 all_ambiguous &= prev_ambiguous;
583 TEUCHOS_TEST_FOR_EXCEPTION((this->diag_ != prev_diag) || (this->uplo_ != prev_uplo),
584 std::logic_error, prefix <<
"A_crs_'s structures in streams "
585 "are different. Please report this bug to the Ifpack2 developers.");
594 if (Teuchos::nonnull(htsImpl_)) {
595 htsImpl_->initialize(*A_crs_);
596 isInternallyChanged_ =
true;
599 const bool ksptrsv_valid_uplo = (this->uplo_ !=
"N");
600 kh_v_nonnull_ =
false;
601 if (this->isKokkosKernelsSptrsv_ && ksptrsv_valid_uplo && this->diag_ !=
"U") {
602 if (!isKokkosKernelsStream_) {
603 kh_ = Teuchos::rcp(
new k_handle());
604 const bool is_lower_tri = (this->uplo_ ==
"L") ?
true :
false;
606 auto A_crs = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_,
true);
607 auto Alocal = A_crs->getLocalMatrixDevice();
608 auto ptr = Alocal.graph.row_map;
609 auto ind = Alocal.graph.entries;
610 auto val = Alocal.values;
612 auto numRows = Alocal.numRows();
613 kh_->create_sptrsv_handle(kokkosKernelsAlgorithm(), numRows, is_lower_tri);
614 KokkosSparse::sptrsv_symbolic(kh_.getRawPtr(), ptr, ind, val);
616 kh_v_ = std::vector<Teuchos::RCP<k_handle>>(num_streams_);
617 for (
int i = 0; i < num_streams_; i++) {
618 kh_v_[i] = Teuchos::rcp(
new k_handle());
619 auto A_crs_i = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_crs_v_[i],
true);
620 auto Alocal_i = A_crs_i->getLocalMatrixDevice();
621 auto ptr_i = Alocal_i.graph.row_map;
622 auto ind_i = Alocal_i.graph.entries;
623 auto val_i = Alocal_i.values;
625 auto numRows_i = Alocal_i.numRows();
627 const bool is_lower_tri = (this->uplo_ ==
"L") ?
true :
false;
628 kh_v_[i]->create_sptrsv_handle(kokkosKernelsAlgorithm(), numRows_i, is_lower_tri);
629 KokkosSparse::sptrsv_symbolic(kh_v_[i].getRawPtr(), ptr_i, ind_i, val_i);
631 kh_v_nonnull_ =
true;
635 isInitialized_ =
true;
639template <
class MatrixType>
640KokkosSparse::Experimental::SPTRSVAlgorithm
642#if defined(KOKKOSKERNELS_ENABLE_TPL_CUSPARSE) && defined(KOKKOS_ENABLE_CUDA)
645 if constexpr (std::is_same<Kokkos::Cuda, HandleExecSpace>::value &&
646 std::is_same<int, local_ordinal_type>::value &&
647 (std::is_same<scalar_type, float>::value ||
648 std::is_same<scalar_type, double>::value ||
649 std::is_same<impl_scalar_type, Kokkos::complex<float>>::value ||
650 std::is_same<impl_scalar_type, Kokkos::complex<double>>::value)) {
651 return KokkosSparse::Experimental::SPTRSVAlgorithm::SPTRSV_CUSPARSE;
654 return KokkosSparse::Experimental::SPTRSVAlgorithm::SEQLVLSCHD_TP1;
657template <
class MatrixType>
660 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::compute: ";
661 if (!out_.is_null()) {
662 *out_ <<
">>> DEBUG " << prefix << std::endl;
665 if (!isKokkosKernelsStream_) {
666 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error, prefix <<
"You must call "
667 "setMatrix() with a nonnull input matrix before you may call "
668 "initialize() or compute().");
669 TEUCHOS_TEST_FOR_EXCEPTION(A_crs_.is_null(), std::logic_error, prefix <<
"A_ is nonnull, but "
670 "A_crs_ is null. Please report this bug to the Ifpack2 developers.");
672 TEUCHOS_TEST_FOR_EXCEPTION(!A_crs_->isFillComplete(), std::runtime_error,
674 "method, the matrix must be fill complete. It is not.");
676 for (
int i = 0; i < num_streams_; i++) {
677 TEUCHOS_TEST_FOR_EXCEPTION(A_crs_v_[i].is_null(), std::runtime_error, prefix <<
"You must call "
678 "setMatrices() with a nonnull input matrix before you may call "
679 "initialize() or compute().");
681 TEUCHOS_TEST_FOR_EXCEPTION(!A_crs_v_[i]->isFillComplete(), std::runtime_error,
683 "method, the matrix must be fill complete. It is not.");
687 if (!isInitialized_) {
690 TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error, prefix <<
"initialize() should have "
691 "been called by this point, but isInitialized_ is false. "
692 "Please report this bug to the Ifpack2 developers.");
701#if defined(KOKKOS_ENABLE_CUDA) && defined(KOKKOSKERNELS_ENABLE_TPL_CUSPARSE) && (CUDA_VERSION >= 11030)
702 if constexpr (std::is_same_v<typename crs_matrix_type::execution_space, Kokkos::Cuda>) {
703 if (this->isKokkosKernelsSptrsv_) {
704 if (Teuchos::nonnull(kh_) && !isKokkosKernelsStream_) {
705 auto A_crs = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_crs_,
true);
706 auto Alocal = A_crs->getLocalMatrixDevice();
707 auto val = Alocal.values;
708 auto ptr = Alocal.graph.row_map;
709 auto ind = Alocal.graph.entries;
710 KokkosSparse::sptrsv_symbolic(kh_.getRawPtr(), ptr, ind, val);
711 }
else if (kh_v_nonnull_) {
712 for (
int i = 0; i < num_streams_; i++) {
713 auto A_crs_i = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_crs_v_[i],
true);
714 auto Alocal_i = A_crs_i->getLocalMatrixDevice();
715 auto val_i = Alocal_i.values;
716 auto ptr_i = Alocal_i.graph.row_map;
717 auto ind_i = Alocal_i.graph.entries;
718 KokkosSparse::sptrsv_symbolic(exec_space_instances_[i], kh_v_[i].getRawPtr(), ptr_i, ind_i, val_i);
726 if (Teuchos::nonnull(htsImpl_))
727 htsImpl_->compute(*A_crs_, out_);
734template <
class MatrixType>
740 Teuchos::ETransp mode,
745 using Teuchos::rcpFromRef;
747 typedef Teuchos::ScalarTraits<ST> STS;
748 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::apply: ";
750 if (!out_.is_null()) {
751 *out_ <<
">>> DEBUG " << prefix;
752 if (!isKokkosKernelsStream_) {
753 if (A_crs_.is_null()) {
754 *out_ <<
"A_crs_ is null!" << std::endl;
756 Teuchos::RCP<const crs_matrix_type> A_crs =
757 Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_);
758 const std::string uplo = this->uplo_;
759 const std::string trans = (mode == Teuchos::CONJ_TRANS) ?
"C" : (mode == Teuchos::TRANS ?
"T" :
"N");
760 const std::string diag = this->diag_;
761 *out_ <<
"uplo=\"" << uplo
762 <<
"\", trans=\"" << trans
763 <<
"\", diag=\"" << diag <<
"\"" << std::endl;
766 for (
int i = 0; i < num_streams_; i++) {
767 if (A_crs_v_[i].is_null()) {
768 *out_ <<
"A_crs_v_[" << i <<
"]"
769 <<
" is null!" << std::endl;
771 const std::string uplo = this->uplo_;
772 const std::string trans = (mode == Teuchos::CONJ_TRANS) ?
"C" : (mode == Teuchos::TRANS ?
"T" :
"N");
773 const std::string diag = this->diag_;
774 *out_ <<
"A_crs_v_[" << i <<
"]: "
776 <<
"\", trans=\"" << trans
777 <<
"\", diag=\"" << diag <<
"\"" << std::endl;
783 TEUCHOS_TEST_FOR_EXCEPTION(!isComputed(), std::runtime_error, prefix <<
"If compute() has not yet "
784 "been called, or if you have changed the matrix via setMatrix(), you must "
785 "call compute() before you may call this method.");
788 if (!isKokkosKernelsStream_) {
789 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::logic_error, prefix <<
"A_ is null. "
790 "Please report this bug to the Ifpack2 developers.");
791 TEUCHOS_TEST_FOR_EXCEPTION(A_crs_.is_null(), std::logic_error, prefix <<
"A_crs_ is null. "
792 "Please report this bug to the Ifpack2 developers.");
795 TEUCHOS_TEST_FOR_EXCEPTION(!A_crs_->isFillComplete(), std::runtime_error,
797 "method, the matrix must be fill complete. It is not. This means that "
798 " you must have called resumeFill() on the matrix before calling apply(). "
799 "This is NOT allowed. Note that this class may use the matrix's data in "
800 "place without copying it. Thus, you cannot change the matrix and expect "
801 "the solver to stay the same. If you have changed the matrix, first call "
802 "fillComplete() on it, then call compute() on this object, before you call"
803 " apply(). You do NOT need to call setMatrix, as long as the matrix "
804 "itself (that is, its address in memory) is the same.");
806 for (
int i = 0; i < num_streams_; i++) {
807 TEUCHOS_TEST_FOR_EXCEPTION(A_crs_v_[i].is_null(), std::logic_error, prefix <<
"A_crs_ is null. "
808 "Please report this bug to the Ifpack2 developers.");
811 TEUCHOS_TEST_FOR_EXCEPTION(!A_crs_v_[i]->isFillComplete(), std::runtime_error,
813 "method, the matrix must be fill complete. It is not. This means that "
814 " you must have called resumeFill() on the matrix before calling apply(). "
815 "This is NOT allowed. Note that this class may use the matrix's data in "
816 "place without copying it. Thus, you cannot change the matrix and expect "
817 "the solver to stay the same. If you have changed the matrix, first call "
818 "fillComplete() on it, then call compute() on this object, before you call"
819 " apply(). You do NOT need to call setMatrix, as long as the matrix "
820 "itself (that is, its address in memory) is the same.");
827 if (!isKokkosKernelsStream_) {
828 auto G = A_crs_->getGraph();
829 TEUCHOS_TEST_FOR_EXCEPTION(G.is_null(), std::logic_error, prefix <<
"A_ and A_crs_ are nonnull, "
830 "but A_crs_'s RowGraph G is null. "
831 "Please report this bug to the Ifpack2 developers.");
832 auto importer = G->getImporter();
833 auto exporter = G->getExporter();
835 if (!importer.is_null()) {
836 if (X_colMap_.is_null() || X_colMap_->getNumVectors() != X.getNumVectors()) {
837 X_colMap_ = rcp(
new MV(importer->getTargetMap(), X.getNumVectors()));
839 X_colMap_->putScalar(STS::zero());
844 X_colMap_->doImport(X, *importer, Tpetra::ZERO);
846 X_cur = importer.is_null() ? rcpFromRef(X) : Teuchos::rcp_const_cast<const MV>(X_colMap_);
848 if (!exporter.is_null()) {
849 if (Y_rowMap_.is_null() || Y_rowMap_->getNumVectors() != Y.getNumVectors()) {
850 Y_rowMap_ = rcp(
new MV(exporter->getSourceMap(), Y.getNumVectors()));
852 Y_rowMap_->putScalar(STS::zero());
854 Y_rowMap_->doExport(Y, *importer, Tpetra::ADD);
856 Y_cur = exporter.is_null() ? rcpFromRef(Y) : Y_rowMap_;
860 X_cur = rcpFromRef(X);
861 Y_cur = rcpFromRef(Y);
864 localApply(*X_cur, *Y_cur, mode, alpha, beta);
866 if (!isKokkosKernelsStream_) {
867 auto G = A_crs_->getGraph();
868 auto exporter = G->getExporter();
869 if (!exporter.is_null()) {
870 Y.putScalar(STS::zero());
871 Y.doExport(*Y_cur, *exporter, Tpetra::ADD);
877template <
class MatrixType>
881 const Teuchos::ETransp mode)
const {
882 using Teuchos::CONJ_TRANS;
883 using Teuchos::NO_TRANS;
884 using Teuchos::TRANS;
885 const char tfecfFuncName[] =
"localTriangularSolve: ";
887 if (!isKokkosKernelsStream_) {
888 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!A_crs_->isFillComplete(), std::runtime_error,
889 "The matrix is not fill complete.");
890 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(A_crs_->getLocalNumRows() > 0 && this->uplo_ ==
"N", std::runtime_error,
891 "The matrix is neither upper triangular or lower triangular. "
892 "You may only call this method if the matrix is triangular. "
893 "Remember that this is a local (per MPI process) property, and that "
894 "Tpetra only knows how to do a local (per process) triangular solve.");
896 for (
int i = 0; i < num_streams_; i++) {
897 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!A_crs_v_[i]->isFillComplete(), std::runtime_error,
898 "The matrix is not fill complete.");
899 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(A_crs_v_[i]->getLocalNumRows() > 0 && this->uplo_ ==
"N", std::runtime_error,
900 "The matrix is neither upper triangular or lower triangular. "
901 "You may only call this method if the matrix is triangular. "
902 "Remember that this is a local (per MPI process) property, and that "
903 "Tpetra only knows how to do a local (per process) triangular solve.");
906 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!X.isConstantStride() || !Y.isConstantStride(), std::invalid_argument,
907 "X and Y must be constant stride.");
908 using STS = Teuchos::ScalarTraits<scalar_type>;
909 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(STS::isComplex && mode == TRANS, std::logic_error,
911 "not currently support non-conjugated transposed solve (mode == "
912 "Teuchos::TRANS) for complex scalar types.");
914 const std::string uplo = this->uplo_;
915 const std::string trans = (mode == Teuchos::CONJ_TRANS) ?
"C" : (mode == Teuchos::
TRANS ?
"T" :
"N");
916 const size_t numVecs = std::min(X.getNumVectors(), Y.getNumVectors());
918 if (Teuchos::nonnull(kh_) && this->isKokkosKernelsSptrsv_ && trans ==
"N") {
919 auto A_crs = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(this->A_);
920 auto A_lclk = A_crs->getLocalMatrixDevice();
921 auto ptr = A_lclk.graph.row_map;
922 auto ind = A_lclk.graph.entries;
923 auto val = A_lclk.values;
925 for (
size_t j = 0; j < numVecs; ++j) {
926 auto X_j = X.getVectorNonConst(j);
927 auto Y_j = Y.getVector(j);
928 auto X_lcl = X_j->getLocalViewDevice(Tpetra::Access::ReadWrite);
929 auto Y_lcl = Y_j->getLocalViewDevice(Tpetra::Access::ReadOnly);
930 auto X_lcl_1d = Kokkos::subview(X_lcl, Kokkos::ALL(), 0);
931 auto Y_lcl_1d = Kokkos::subview(Y_lcl, Kokkos::ALL(), 0);
932 KokkosSparse::sptrsv_solve(kh_.getRawPtr(), ptr, ind, val, Y_lcl_1d, X_lcl_1d);
934 typename k_handle::HandleExecSpace().fence();
937 else if (kh_v_nonnull_ && this->isKokkosKernelsSptrsv_ && trans ==
"N") {
938 std::vector<lno_row_view_t> ptr_v(num_streams_);
939 std::vector<lno_nonzero_view_t> ind_v(num_streams_);
940 std::vector<scalar_nonzero_view_t> val_v(num_streams_);
941 std::vector<k_handle*> KernelHandle_rawptr_v_(num_streams_);
942 for (
size_t j = 0; j < numVecs; ++j) {
943 auto X_j = X.getVectorNonConst(j);
944 auto Y_j = Y.getVector(j);
945 auto X_lcl = X_j->getLocalViewDevice(Tpetra::Access::ReadWrite);
946 auto Y_lcl = Y_j->getLocalViewDevice(Tpetra::Access::ReadOnly);
947 auto X_lcl_1d = Kokkos::subview(X_lcl, Kokkos::ALL(), 0);
948 auto Y_lcl_1d = Kokkos::subview(Y_lcl, Kokkos::ALL(), 0);
949 std::vector<
decltype(X_lcl_1d)> x_v(num_streams_);
950 std::vector<
decltype(Y_lcl_1d)> y_v(num_streams_);
951 local_ordinal_type stream_begin = 0;
952 local_ordinal_type stream_end;
953 for (
int i = 0; i < num_streams_; i++) {
954 auto A_crs_i = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_crs_v_[i]);
955 auto Alocal_i = A_crs_i->getLocalMatrixDevice();
956 ptr_v[i] = Alocal_i.graph.row_map;
957 ind_v[i] = Alocal_i.graph.entries;
958 val_v[i] = Alocal_i.values;
959 stream_end = stream_begin + Alocal_i.numRows();
960 x_v[i] = Kokkos::subview(X_lcl, Kokkos::make_pair(stream_begin, stream_end), 0);
961 y_v[i] = Kokkos::subview(Y_lcl, Kokkos::make_pair(stream_begin, stream_end), 0);
962 KernelHandle_rawptr_v_[i] = kh_v_[i].getRawPtr();
963 stream_begin = stream_end;
966 KokkosSparse::Experimental::sptrsv_solve_streams(exec_space_instances_, KernelHandle_rawptr_v_,
967 ptr_v, ind_v, val_v, y_v, x_v);
968 for (
int i = 0; i < num_streams_; i++) exec_space_instances_[i].fence();
973 const std::string diag = this->diag_;
978 auto A_lcl = this->A_crs_->getLocalMatrixHost();
980 if (X.isConstantStride() && Y.isConstantStride()) {
981 auto X_lcl = X.getLocalViewHost(Tpetra::Access::ReadWrite);
982 auto Y_lcl = Y.getLocalViewHost(Tpetra::Access::ReadOnly);
983 KokkosSparse::trsv(uplo.c_str(), trans.c_str(), diag.c_str(),
984 A_lcl, Y_lcl, X_lcl);
986 for (
size_t j = 0; j < numVecs; ++j) {
987 auto X_j = X.getVectorNonConst(j);
988 auto Y_j = Y.getVector(j);
989 auto X_lcl = X_j->getLocalViewHost(Tpetra::Access::ReadWrite);
990 auto Y_lcl = Y_j->getLocalViewHost(Tpetra::Access::ReadOnly);
991 KokkosSparse::trsv(uplo.c_str(), trans.c_str(),
992 diag.c_str(), A_lcl, Y_lcl, X_lcl);
998template <
class MatrixType>
999void LocalSparseTriangularSolver<MatrixType>::
1000 localApply(
const MV& X,
1002 const Teuchos::ETransp mode,
1003 const scalar_type& alpha,
1004 const scalar_type& beta)
const {
1005 if (mode == Teuchos::NO_TRANS && Teuchos::nonnull(htsImpl_) &&
1006 htsImpl_->isComputed()) {
1007 htsImpl_->localApply(X, Y, mode, alpha, beta);
1012 typedef scalar_type ST;
1013 typedef Teuchos::ScalarTraits<ST> STS;
1015 if (beta == STS::zero()) {
1016 if (alpha == STS::zero()) {
1017 Y.putScalar(STS::zero());
1019 this->localTriangularSolve(X, Y, mode);
1020 if (alpha != STS::one()) {
1025 if (alpha == STS::zero()) {
1028 MV Y_tmp(Y, Teuchos::Copy);
1029 this->localTriangularSolve(X, Y_tmp, mode);
1030 Y.update(alpha, Y_tmp, beta);
1035template <
class MatrixType>
1038 return numInitialize_;
1041template <
class MatrixType>
1047template <
class MatrixType>
1053template <
class MatrixType>
1057 return initializeTime_;
1060template <
class MatrixType>
1064 return computeTime_;
1067template <
class MatrixType>
1074template <
class MatrixType>
1078 std::ostringstream os;
1083 os <<
"\"Ifpack2::LocalSparseTriangularSolver\": {";
1084 if (this->getObjectLabel() !=
"") {
1085 os <<
"Label: \"" << this->getObjectLabel() <<
"\", ";
1087 os <<
"Initialized: " << (isInitialized() ?
"true" :
"false") <<
", "
1088 <<
"Computed: " << (isComputed() ?
"true" :
"false") <<
", ";
1090 if (isKokkosKernelsSptrsv_) os <<
"KK-SPTRSV, ";
1091 if (isKokkosKernelsStream_) os <<
"KK-SolveStream, ";
1094 os <<
"Matrix: null";
1096 os <<
"Matrix dimensions: ["
1097 << A_->getGlobalNumRows() <<
", "
1098 << A_->getGlobalNumCols() <<
"]"
1099 <<
", Number of nonzeros: " << A_->getGlobalNumEntries();
1102 if (Teuchos::nonnull(htsImpl_))
1103 os <<
", HTS computed: " << (htsImpl_->isComputed() ?
"true" :
"false");
1108template <
class MatrixType>
1110 describe(Teuchos::FancyOStream& out,
1111 const Teuchos::EVerbosityLevel verbLevel)
const {
1115 const Teuchos::EVerbosityLevel vl = (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
1117 if (vl != Teuchos::VERB_NONE) {
1122 auto comm = A_.is_null() ? Tpetra::getDefaultComm() : A_->getComm();
1126 if (!comm.is_null() && comm->getRank() == 0) {
1128 Teuchos::OSTab tab0(out);
1131 out <<
"\"Ifpack2::LocalSparseTriangularSolver\":" << endl;
1132 Teuchos::OSTab tab1(out);
1133 out <<
"Scalar: " << Teuchos::TypeNameTraits<scalar_type>::name() << endl
1134 <<
"LocalOrdinal: " << Teuchos::TypeNameTraits<local_ordinal_type>::name() << endl
1135 <<
"GlobalOrdinal: " << Teuchos::TypeNameTraits<global_ordinal_type>::name() << endl
1136 <<
"Node: " << Teuchos::TypeNameTraits<node_type>::name() << endl;
1141template <
class MatrixType>
1142Teuchos::RCP<const typename LocalSparseTriangularSolver<MatrixType>::map_type>
1145 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error,
1146 "Ifpack2::LocalSparseTriangularSolver::getDomainMap: "
1147 "The matrix is null. Please call setMatrix() with a nonnull input "
1148 "before calling this method.");
1149 return A_->getDomainMap();
1152template <
class MatrixType>
1153Teuchos::RCP<const typename LocalSparseTriangularSolver<MatrixType>::map_type>
1156 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error,
1157 "Ifpack2::LocalSparseTriangularSolver::getRangeMap: "
1158 "The matrix is null. Please call setMatrix() with a nonnull input "
1159 "before calling this method.");
1160 return A_->getRangeMap();
1163template <
class MatrixType>
1165 setMatrix(
const Teuchos::RCP<const row_matrix_type>& A) {
1166 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::setMatrix: ";
1172 if (A.getRawPtr() != A_.getRawPtr() || isInternallyChanged_) {
1174 TEUCHOS_TEST_FOR_EXCEPTION(!A.is_null() && A->getComm()->getSize() == 1 &&
1175 A->getLocalNumRows() != A->getLocalNumCols(),
1176 std::runtime_error, prefix <<
"If A's communicator only contains one "
1177 "process, then A must be square. Instead, you provided a matrix A with "
1178 << A->getLocalNumRows() <<
" rows and " << A->getLocalNumCols() <<
" columns.");
1183 isInitialized_ =
false;
1184 isComputed_ =
false;
1187 A_crs_ = Teuchos::null;
1190 Teuchos::RCP<const crs_matrix_type> A_crs =
1191 Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A);
1192 TEUCHOS_TEST_FOR_EXCEPTION(A_crs.is_null(), std::invalid_argument, prefix <<
"The input matrix A is not a Tpetra::CrsMatrix.");
1197 if (Teuchos::nonnull(htsImpl_))
1202template <
class MatrixType>
1204 setStreamInfo(
const bool& isKokkosKernelsStream,
const int& num_streams,
1205 const std::vector<HandleExecSpace>& exec_space_instances) {
1206 isKokkosKernelsStream_ = isKokkosKernelsStream;
1207 num_streams_ = num_streams;
1208 exec_space_instances_ = exec_space_instances;
1209 A_crs_v_ = std::vector<Teuchos::RCP<crs_matrix_type>>(num_streams_);
1212template <
class MatrixType>
1214 setMatrices(
const std::vector<Teuchos::RCP<crs_matrix_type>>& A_crs_v) {
1215 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::setMatrixWithStreams: ";
1217 for (
int i = 0; i < num_streams_; i++) {
1222 if (A_crs_v[i].getRawPtr() != A_crs_v_[i].getRawPtr() || isInternallyChanged_) {
1224 TEUCHOS_TEST_FOR_EXCEPTION(!A_crs_v[i].is_null() && A_crs_v[i]->getComm()->getSize() == 1 &&
1225 A_crs_v[i]->getLocalNumRows() != A_crs_v[i]->getLocalNumCols(),
1226 std::runtime_error, prefix <<
"If A's communicator only contains one "
1227 "process, then A must be square. Instead, you provided a matrix A with "
1228 << A_crs_v[i]->getLocalNumRows() <<
" rows and " << A_crs_v[i]->getLocalNumCols() <<
" columns.");
1233 isInitialized_ =
false;
1234 isComputed_ =
false;
1236 if (A_crs_v[i].is_null()) {
1237 A_crs_v_[i] = Teuchos::null;
1239 Teuchos::RCP<crs_matrix_type> A_crs =
1240 Teuchos::rcp_dynamic_cast<crs_matrix_type>(A_crs_v[i]);
1241 TEUCHOS_TEST_FOR_EXCEPTION(A_crs.is_null(), std::invalid_argument, prefix <<
"The input matrix A is not a Tpetra::CrsMatrix.");
1242 A_crs_v_[i] = A_crs;
1250#define IFPACK2_LOCALSPARSETRIANGULARSOLVER_INSTANT(S, LO, GO, N) \
1251 template class Ifpack2::LocalSparseTriangularSolver<Tpetra::RowMatrix<S, LO, GO, N>>;
"Preconditioner" that solves local sparse triangular systems.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:54
bool isComputed() const
Return true if compute() has been called.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:192
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print this object with given verbosity to the given output stream.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1110
std::string description() const
A one-line description of this object.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1077
Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > map_type
Specialization of Tpetra::Map used by this class.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:70
LocalSparseTriangularSolver()
Constructor that takes no input matrix.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:298
MatrixType::local_ordinal_type local_ordinal_type
Type of the local indices of the input matrix.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:61
void setParameters(const Teuchos::ParameterList ¶ms)
Set this object's parameters.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:365
double getComputeTime() const
Return the time spent in compute().
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1063
void initialize()
"Symbolic" phase of setup
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:409
MatrixType::global_ordinal_type global_ordinal_type
Type of the global indices of the input matrix.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:63
int getNumCompute() const
Return the number of calls to compute().
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1043
double getInitializeTime() const
Return the time spent in initialize().
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1056
Teuchos::RCP< const map_type > getDomainMap() const
The domain of this operator.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1144
MatrixType::scalar_type scalar_type
Scalar type of the entries of the input matrix.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:57
MatrixType::node_type node_type
Node type of the input matrix.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:65
int getNumInitialize() const
Return the number of calls to initialize().
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1037
void setStreamInfo(const bool &isKokkosKernelsStream, const int &num_streams, const std::vector< HandleExecSpace > &exec_space_instances)
Set this triangular solver's stream information.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1204
Tpetra::CrsMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > crs_matrix_type
Specialization of Tpetra::CrsMatrix used by this class.
Definition Ifpack2_LocalSparseTriangularSolver_decl.hpp:78
Teuchos::RCP< const map_type > getRangeMap() const
The range of this operator.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1155
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Set this preconditioner's matrix.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1165
void setMatrices(const std::vector< Teuchos::RCP< crs_matrix_type > > &A_crs_v)
Set this preconditioner's matrices (used by stream interface of triangular solve).
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1214
virtual ~LocalSparseTriangularSolver()
Destructor (virtual for memory safety).
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:334
double getApplyTime() const
Return the time spent in apply().
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1070
void apply(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, scalar_type alpha=Teuchos::ScalarTraits< scalar_type >::one(), scalar_type beta=Teuchos::ScalarTraits< scalar_type >::zero()) const
Apply the preconditioner to X, and put the result in Y.
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:736
int getNumApply() const
Return the number of calls to apply().
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:1049
void compute()
"Numeric" phase of setup
Definition Ifpack2_LocalSparseTriangularSolver_def.hpp:659
Ifpack2 implementation details.
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:40