43 #ifndef IFPACK2_LOCALSPARSETRIANGULARSOLVER_DEF_HPP 44 #define IFPACK2_LOCALSPARSETRIANGULARSOLVER_DEF_HPP 46 #include "Tpetra_CrsMatrix.hpp" 47 #include "Tpetra_DefaultPlatform.hpp" 48 #include "Teuchos_StandardParameterEntryValidators.hpp" 50 #ifdef HAVE_IFPACK2_SHYLUHTS 51 # include "shylu_hts.hpp" 57 struct TrisolverType {
63 static void loadPLTypeOption (Teuchos::Array<std::string>& type_strs, Teuchos::Array<Enum>& type_enums) {
65 type_strs[0] =
"Internal";
68 type_enums[0] = Internal;
74 template<
class MatrixType>
75 class LocalSparseTriangularSolver<MatrixType>::HtsImpl {
77 typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> crs_matrix_type;
80 #ifdef HAVE_IFPACK2_SHYLUHTS 81 Timpl_ = Teuchos::null;
82 levelset_block_size_ = 1;
86 void setParameters (
const Teuchos::ParameterList& pl) {
87 #ifdef HAVE_IFPACK2_SHYLUHTS 88 const char* block_size_s =
"trisolver: block size";
89 if (pl.isParameter(block_size_s)) {
90 TEUCHOS_TEST_FOR_EXCEPT_MSG( ! pl.isType<
int>(block_size_s),
91 "The parameter \"" << block_size_s <<
"\" must be of type int.");
92 levelset_block_size_ = pl.get<
int>(block_size_s);
94 if (levelset_block_size_ < 1)
95 levelset_block_size_ = 1;
103 void initialize (
const crs_matrix_type& ) {
104 #ifdef HAVE_IFPACK2_SHYLUHTS 106 transpose_ = conjugate_ =
false;
110 void compute (
const crs_matrix_type& T_in,
const Teuchos::RCP<Teuchos::FancyOStream>& out) {
111 #ifdef HAVE_IFPACK2_SHYLUHTS 112 using Teuchos::ArrayRCP;
114 Teuchos::ArrayRCP<const size_t> rowptr;
115 Teuchos::ArrayRCP<const local_ordinal_type> colidx;
116 Teuchos::ArrayRCP<const scalar_type> val;
117 T_in.getAllValues(rowptr, colidx, val);
119 Teuchos::RCP<HtsCrsMatrix> T_hts = Teuchos::rcpWithDealloc(
120 HTST::make_CrsMatrix(rowptr.size() - 1,
121 rowptr.getRawPtr(), colidx.getRawPtr(), val.getRawPtr(),
122 transpose_, conjugate_),
123 HtsCrsMatrixDeleter());
125 if (Teuchos::nonnull(Timpl_)) {
127 HTST::reprocess_numeric(Timpl_.get(), T_hts.get());
130 if (T_in.getCrsGraph().is_null()) {
131 if (Teuchos::nonnull(out))
132 *out <<
"HTS compute failed because T_in.getCrsGraph().is_null().\n";
135 if ( ! T_in.getCrsGraph()->isSorted()) {
136 if (Teuchos::nonnull(out))
137 *out <<
"HTS compute failed because ! T_in.getCrsGraph().isSorted().\n";
140 if ( ! T_in.isStorageOptimized()) {
141 if (Teuchos::nonnull(out))
142 *out <<
"HTS compute failed because ! T_in.isStorageOptimized().\n";
146 typename HTST::PreprocessArgs args;
147 args.T = T_hts.get();
149 args.nthreads = omp_get_max_threads();
150 args.save_for_reprocess =
true;
151 typename HTST::Options opts;
152 opts.levelset_block_size = levelset_block_size_;
153 args.options = &opts;
156 Timpl_ = Teuchos::rcpWithDealloc(HTST::preprocess(args), TImplDeleter());
157 }
catch (
const std::exception& e) {
158 if (Teuchos::nonnull(out))
159 *out <<
"HTS preprocess threw: " << e.what() <<
"\n";
168 #ifdef HAVE_IFPACK2_SHYLUHTS 169 return Teuchos::nonnull(Timpl_);
176 void localApply (
const MV& X, MV& Y,
177 const Teuchos::ETransp mode,
178 const scalar_type& alpha,
const scalar_type& beta)
const {
179 #ifdef HAVE_IFPACK2_SHYLUHTS 180 const auto& X_view = X.template getLocalView<Kokkos::HostSpace>();
181 const auto& Y_view = Y.template getLocalView<Kokkos::HostSpace>();
183 HTST::reset_max_nrhs(Timpl_.get(), X_view.dimension_1());
185 HTST::solve_omp(Timpl_.get(), X_view.data(), X_view.dimension_1(), Y_view.data(), beta, alpha);
190 #ifdef HAVE_IFPACK2_SHYLUHTS 191 typedef ::Experimental::HTS<local_ordinal_type, size_t, scalar_type> HTST;
192 typedef typename HTST::Impl TImpl;
193 typedef typename HTST::CrsMatrix HtsCrsMatrix;
195 struct TImplDeleter {
196 void free (TImpl* impl) {
197 HTST::delete_Impl(impl);
201 struct HtsCrsMatrixDeleter {
202 void free (HtsCrsMatrix* T) {
203 HTST::delete_CrsMatrix(T);
207 Teuchos::RCP<TImpl> Timpl_;
208 bool transpose_, conjugate_;
209 int levelset_block_size_;
213 template<
class MatrixType>
221 if (! A.is_null ()) {
222 Teuchos::RCP<const crs_matrix_type> A_crs =
223 Teuchos::rcp_dynamic_cast<
const crs_matrix_type> (A);
224 TEUCHOS_TEST_FOR_EXCEPTION
225 (A_crs.is_null (), std::invalid_argument,
226 "Ifpack2::LocalSparseTriangularSolver constructor: " 227 "The input matrix A is not a Tpetra::CrsMatrix.");
232 template<
class MatrixType>
235 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
240 if (! out_.is_null ()) {
241 *out_ <<
">>> DEBUG Ifpack2::LocalSparseTriangularSolver constructor" 246 if (! A.is_null ()) {
247 Teuchos::RCP<const crs_matrix_type> A_crs =
248 Teuchos::rcp_dynamic_cast<
const crs_matrix_type> (A);
249 TEUCHOS_TEST_FOR_EXCEPTION
250 (A_crs.is_null (), std::invalid_argument,
251 "Ifpack2::LocalSparseTriangularSolver constructor: " 252 "The input matrix A is not a Tpetra::CrsMatrix.");
257 template<
class MatrixType>
264 template<
class MatrixType>
270 if (! out_.is_null ()) {
271 *out_ <<
">>> DEBUG Ifpack2::LocalSparseTriangularSolver constructor" 276 template<
class MatrixType>
279 isInitialized_ =
false;
284 initializeTime_ = 0.0;
289 template<
class MatrixType>
294 template<
class MatrixType>
300 using Teuchos::ParameterList;
301 using Teuchos::Array;
303 Details::TrisolverType::Enum trisolverType = Details::TrisolverType::Internal;
305 static const char typeName[] =
"trisolver: type";
307 if ( ! pl.isType<std::string>(typeName))
break;
310 Array<std::string> trisolverTypeStrs;
311 Array<Details::TrisolverType::Enum> trisolverTypeEnums;
312 Details::TrisolverType::loadPLTypeOption (trisolverTypeStrs, trisolverTypeEnums);
313 Teuchos::StringToIntegralParameterEntryValidator<Details::TrisolverType::Enum>
314 s2i(trisolverTypeStrs (), trisolverTypeEnums (), typeName,
false);
316 trisolverType = s2i.getIntegralValue(pl.get<std::string>(typeName));
319 if (trisolverType == Details::TrisolverType::HTS) {
320 htsImpl_ = Teuchos::rcp (
new HtsImpl ());
321 htsImpl_->setParameters (pl);
325 template<
class MatrixType>
330 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::initialize: ";
331 if (! out_.is_null ()) {
332 *out_ <<
">>> DEBUG " << prefix << std::endl;
335 TEUCHOS_TEST_FOR_EXCEPTION
336 (A_.is_null (), std::runtime_error, prefix <<
"You must call " 337 "setMatrix() with a nonnull input matrix before you may call " 338 "initialize() or compute().");
339 if (A_crs_.is_null ()) {
342 Teuchos::RCP<const crs_matrix_type> A_crs =
343 Teuchos::rcp_dynamic_cast<
const crs_matrix_type> (A_);
344 TEUCHOS_TEST_FOR_EXCEPTION
345 (A_crs.is_null (), std::invalid_argument, prefix <<
346 "The input matrix A is not a Tpetra::CrsMatrix.");
349 auto G = A_->getGraph ();
350 TEUCHOS_TEST_FOR_EXCEPTION
351 (G.is_null (), std::logic_error, prefix <<
"A_ and A_crs_ are nonnull, " 352 "but A_'s RowGraph G is null. " 353 "Please report this bug to the Ifpack2 developers.");
357 TEUCHOS_TEST_FOR_EXCEPTION
358 (! G->isFillComplete (), std::runtime_error,
"If you call this method, " 359 "the matrix's graph must be fill complete. It is not.");
361 if (Teuchos::nonnull (htsImpl_))
362 htsImpl_->initialize (*A_crs_);
364 isInitialized_ =
true;
368 template<
class MatrixType>
373 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::compute: ";
374 if (! out_.is_null ()) {
375 *out_ <<
">>> DEBUG " << prefix << std::endl;
378 TEUCHOS_TEST_FOR_EXCEPTION
379 (A_.is_null (), std::runtime_error, prefix <<
"You must call " 380 "setMatrix() with a nonnull input matrix before you may call " 381 "initialize() or compute().");
382 TEUCHOS_TEST_FOR_EXCEPTION
383 (A_crs_.is_null (), std::logic_error, prefix <<
"A_ is nonnull, but " 384 "A_crs_ is null. Please report this bug to the Ifpack2 developers.");
386 TEUCHOS_TEST_FOR_EXCEPTION
387 (! A_crs_->isFillComplete (), std::runtime_error,
"If you call this " 388 "method, the matrix must be fill complete. It is not.");
390 if (! isInitialized_) {
393 TEUCHOS_TEST_FOR_EXCEPTION
394 (! isInitialized_, std::logic_error, prefix <<
"initialize() should have " 395 "been called by this point, but isInitialized_ is false. " 396 "Please report this bug to the Ifpack2 developers.");
398 if (Teuchos::nonnull (htsImpl_))
399 htsImpl_->compute (*A_crs_, out_);
405 template<
class MatrixType>
411 Teuchos::ETransp mode,
417 using Teuchos::rcpFromRef;
419 typedef Teuchos::ScalarTraits<ST> STS;
420 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::apply: ";
421 if (! out_.is_null ()) {
422 *out_ <<
">>> DEBUG " << prefix;
423 if (A_crs_.is_null ()) {
424 *out_ <<
"A_crs_ is null!" << std::endl;
427 const std::string uplo = A_crs_->isUpperTriangular () ?
"U" :
428 (A_crs_->isLowerTriangular () ?
"L" :
"N");
429 const std::string trans = (mode == Teuchos::CONJ_TRANS) ?
"C" :
430 (mode == Teuchos::TRANS ?
"T" :
"N");
431 const std::string diag =
432 (A_crs_->getNodeNumDiags () < A_crs_->getNodeNumRows ()) ?
"U" :
"N";
433 *out_ <<
"uplo=\"" << uplo
434 <<
"\", trans=\"" << trans
435 <<
"\", diag=\"" << diag <<
"\"" << std::endl;
439 TEUCHOS_TEST_FOR_EXCEPTION
440 (!
isComputed (), std::runtime_error, prefix <<
"If compute() has not yet " 441 "been called, or if you have changed the matrix via setMatrix(), you must " 442 "call compute() before you may call this method.");
445 TEUCHOS_TEST_FOR_EXCEPTION
446 (A_.is_null (), std::logic_error, prefix <<
"A_ is null. " 447 "Please report this bug to the Ifpack2 developers.");
448 TEUCHOS_TEST_FOR_EXCEPTION
449 (A_crs_.is_null (), std::logic_error, prefix <<
"A_crs_ is null. " 450 "Please report this bug to the Ifpack2 developers.");
453 TEUCHOS_TEST_FOR_EXCEPTION
454 (! A_crs_->isFillComplete (), std::runtime_error,
"If you call this " 455 "method, the matrix must be fill complete. It is not. This means that " 456 " you must have called resumeFill() on the matrix before calling apply(). " 457 "This is NOT allowed. Note that this class may use the matrix's data in " 458 "place without copying it. Thus, you cannot change the matrix and expect " 459 "the solver to stay the same. If you have changed the matrix, first call " 460 "fillComplete() on it, then call compute() on this object, before you call" 461 " apply(). You do NOT need to call setMatrix, as long as the matrix " 462 "itself (that is, its address in memory) is the same.");
464 auto G = A_->getGraph ();
465 TEUCHOS_TEST_FOR_EXCEPTION
466 (G.is_null (), std::logic_error, prefix <<
"A_ and A_crs_ are nonnull, " 467 "but A_'s RowGraph G is null. " 468 "Please report this bug to the Ifpack2 developers.");
469 auto importer = G->getImporter ();
470 auto exporter = G->getExporter ();
472 if (! importer.is_null ()) {
473 if (X_colMap_.is_null () || X_colMap_->getNumVectors () != X.getNumVectors ()) {
474 X_colMap_ = rcp (
new MV (importer->getTargetMap (), X.getNumVectors ()));
477 X_colMap_->putScalar (STS::zero ());
482 X_colMap_->doImport (X, *importer, Tpetra::ZERO);
484 RCP<const MV> X_cur = importer.is_null () ? rcpFromRef (X) :
485 Teuchos::rcp_const_cast<
const MV> (X_colMap_);
487 if (! exporter.is_null ()) {
488 if (Y_rowMap_.is_null () || Y_rowMap_->getNumVectors () != Y.getNumVectors ()) {
489 Y_rowMap_ = rcp (
new MV (exporter->getSourceMap (), Y.getNumVectors ()));
492 Y_rowMap_->putScalar (STS::zero ());
494 Y_rowMap_->doExport (Y, *importer, Tpetra::ADD);
496 RCP<MV> Y_cur = exporter.is_null () ? rcpFromRef (Y) : Y_rowMap_;
498 localApply (*X_cur, *Y_cur, mode, alpha, beta);
500 if (! exporter.is_null ()) {
501 Y.putScalar (STS::zero ());
502 Y.doExport (*Y_cur, *exporter, Tpetra::ADD);
508 template<
class MatrixType>
513 const Teuchos::ETransp mode,
517 if (mode == Teuchos::NO_TRANS && Teuchos::nonnull (htsImpl_) &&
518 htsImpl_->isComputed ()) {
519 htsImpl_->localApply (X, Y, mode, alpha, beta);
525 typedef Teuchos::ScalarTraits<ST> STS;
527 if (beta == STS::zero ()) {
528 if (alpha == STS::zero ()) {
529 Y.putScalar (STS::zero ());
532 A_crs_->template localSolve<ST, ST> (X, Y, mode);
533 if (alpha != STS::one ()) {
539 if (alpha == STS::zero ()) {
543 MV Y_tmp (Y, Teuchos::Copy);
544 A_crs_->template localSolve<ST, ST> (X, Y_tmp, mode);
545 Y.update (alpha, Y_tmp, beta);
551 template <
class MatrixType>
555 return numInitialize_;
558 template <
class MatrixType>
565 template <
class MatrixType>
572 template <
class MatrixType>
576 return initializeTime_;
579 template<
class MatrixType>
586 template<
class MatrixType>
593 template <
class MatrixType>
598 std::ostringstream os;
603 os <<
"\"Ifpack2::LocalSparseTriangularSolver\": {";
604 if (this->getObjectLabel () !=
"") {
605 os <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
607 os <<
"Initialized: " << (
isInitialized () ?
"true" :
"false") <<
", " 608 <<
"Computed: " << (
isComputed () ?
"true" :
"false") <<
", ";
611 os <<
"Matrix: null";
614 os <<
"Matrix: not null" 615 <<
", Global matrix dimensions: [" 616 << A_->getGlobalNumRows () <<
", " 617 << A_->getGlobalNumCols () <<
"]";
620 if (Teuchos::nonnull (htsImpl_))
621 os <<
", HTS computed: " << (htsImpl_->isComputed () ?
"true" :
"false");
627 template <
class MatrixType>
630 const Teuchos::EVerbosityLevel verbLevel)
const 635 const Teuchos::EVerbosityLevel vl
636 = (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
638 if (vl != Teuchos::VERB_NONE) {
643 auto comm = A_.is_null () ?
644 Tpetra::DefaultPlatform::getDefaultPlatform ().getComm () :
649 if (! comm.is_null () && comm->getRank () == 0) {
651 Teuchos::OSTab tab0 (out);
654 out <<
"\"Ifpack2::LocalSparseTriangularSolver\":" << endl;
655 Teuchos::OSTab tab1 (out);
656 out <<
"Scalar: " << Teuchos::TypeNameTraits<scalar_type>::name () << endl
657 <<
"LocalOrdinal: " << Teuchos::TypeNameTraits<local_ordinal_type>::name () << endl
658 <<
"GlobalOrdinal: " << Teuchos::TypeNameTraits<global_ordinal_type>::name () << endl
659 <<
"Node: " << Teuchos::TypeNameTraits<node_type>::name () << endl;
664 template <
class MatrixType>
665 Teuchos::RCP<const typename LocalSparseTriangularSolver<MatrixType>::map_type>
669 TEUCHOS_TEST_FOR_EXCEPTION
670 (A_.is_null (), std::runtime_error,
671 "Ifpack2::LocalSparseTriangularSolver::getDomainMap: " 672 "The matrix is null. Please call setMatrix() with a nonnull input " 673 "before calling this method.");
674 return A_->getDomainMap ();
677 template <
class MatrixType>
678 Teuchos::RCP<const typename LocalSparseTriangularSolver<MatrixType>::map_type>
682 TEUCHOS_TEST_FOR_EXCEPTION
683 (A_.is_null (), std::runtime_error,
684 "Ifpack2::LocalSparseTriangularSolver::getRangeMap: " 685 "The matrix is null. Please call setMatrix() with a nonnull input " 686 "before calling this method.");
687 return A_->getRangeMap ();
690 template<
class MatrixType>
692 setMatrix (
const Teuchos::RCP<const row_matrix_type>& A)
694 const char prefix[] =
"Ifpack2::LocalSparseTriangularSolver::setMatrix: ";
700 if (A.getRawPtr () != A_.getRawPtr ()) {
702 TEUCHOS_TEST_FOR_EXCEPTION
703 (! A.is_null () && A->getComm ()->getSize () == 1 &&
704 A->getNodeNumRows () != A->getNodeNumCols (),
705 std::runtime_error, prefix <<
"If A's communicator only contains one " 706 "process, then A must be square. Instead, you provided a matrix A with " 707 << A->getNodeNumRows () <<
" rows and " << A->getNodeNumCols ()
713 isInitialized_ =
false;
719 A_crs_ = Teuchos::null;
723 Teuchos::RCP<const crs_matrix_type> A_crs =
724 Teuchos::rcp_dynamic_cast<
const crs_matrix_type> (A);
725 TEUCHOS_TEST_FOR_EXCEPTION
726 (A_crs.is_null (), std::invalid_argument, prefix <<
727 "The input matrix A is not a Tpetra::CrsMatrix.");
732 if (Teuchos::nonnull (htsImpl_))
739 #define IFPACK2_LOCALSPARSETRIANGULARSOLVER_INSTANT(S,LO,GO,N) \ 740 template class Ifpack2::LocalSparseTriangularSolver< Tpetra::RowMatrix<S, LO, GO, N> >; 742 #endif // IFPACK2_LOCALSPARSETRIANGULARSOLVER_DEF_HPP 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:407
bool isInitialized() const
Return true if the preconditioner has been successfully initialized.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:198
int getNumInitialize() const
Return the number of calls to initialize().
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:554
Teuchos::RCP< const map_type > getDomainMap() const
The domain of this operator.
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:667
Teuchos::RCP< const map_type > getRangeMap() const
The range of this operator.
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:680
int getNumCompute() const
Return the number of calls to compute().
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:561
double getApplyTime() const
Return the time spent in apply().
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:589
void compute()
"Numeric" phase of setup
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:371
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:629
MatrixType::global_ordinal_type global_ordinal_type
Type of the global indices of the input matrix.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:99
Ifpack2 implementation details.
MatrixType::node_type node_type
Node type of the input matrix.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:101
bool isComputed() const
Return true if compute() has been called.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:209
double getComputeTime() const
Return the time spent in compute().
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:582
int getNumApply() const
Return the number of calls to apply().
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:568
"Preconditioner" that solves local sparse triangular systems.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:83
void initialize()
"Symbolic" phase of setup
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:328
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Set this preconditioner's matrix.
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:692
double getInitializeTime() const
Return the time spent in initialize().
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:575
MatrixType::local_ordinal_type local_ordinal_type
Type of the local indices of the input matrix.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:97
void setParameters(const Teuchos::ParameterList ¶ms)
Set this object's parameters.
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:297
MatrixType::scalar_type scalar_type
Type of the entries of the input matrix.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:95
std::string description() const
A one-line description of this object.
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:596
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:72
virtual ~LocalSparseTriangularSolver()
Destructor (virtual for memory safety).
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:291
LocalSparseTriangularSolver()
Constructor that takes no input matrix.
Definition: Ifpack2_LocalSparseTriangularSolver_def.hpp:259