43 #ifndef IFPACK2_CRSRILUK_DEF_HPP 44 #define IFPACK2_CRSRILUK_DEF_HPP 46 #include "Ifpack2_LocalFilter.hpp" 47 #include "Tpetra_CrsMatrix.hpp" 48 #include "Ifpack2_LocalSparseTriangularSolver.hpp" 50 #ifdef IFPACK2_ILUK_EXPERIMENTAL 51 #include <shylubasker_def.hpp> 52 #include <Kokkos_CrsMatrix.hpp> 53 # ifdef IFPACK2_HTS_EXPERIMENTAL 54 # include <shylu_hts.hpp> 60 template<
class MatrixType>
65 isInitialized_ (false),
67 isExperimental_ (false),
71 initializeTime_ (0.0),
82 template<
class MatrixType>
87 isInitialized_ (false),
89 isExperimental_ (false),
93 initializeTime_ (0.0),
104 template<
class MatrixType>
107 template<
class MatrixType>
114 template<
class MatrixType>
122 if (A.getRawPtr () != A_.getRawPtr ()) {
123 isAllocated_ =
false;
124 isInitialized_ =
false;
126 A_local_ = Teuchos::null;
127 Graph_ = Teuchos::null;
134 if (! L_solver_.is_null ()) {
137 if (! U_solver_.is_null ()) {
138 U_solver_->setMatrix (Teuchos::null);
150 template<
class MatrixType>
154 TEUCHOS_TEST_FOR_EXCEPTION(
155 L_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getL: The L factor " 156 "is null. Please call initialize() (and preferably also compute()) " 157 "before calling this method. If the input matrix has not yet been set, " 158 "you must first call setMatrix() with a nonnull input matrix before you " 159 "may call initialize() or compute().");
164 template<
class MatrixType>
165 const Tpetra::Vector<typename RILUK<MatrixType>::scalar_type,
171 TEUCHOS_TEST_FOR_EXCEPTION(
172 D_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getD: The D factor " 173 "(of diagonal entries) is null. Please call initialize() (and " 174 "preferably also compute()) before calling this method. If the input " 175 "matrix has not yet been set, you must first call setMatrix() with a " 176 "nonnull input matrix before you may call initialize() or compute().");
181 template<
class MatrixType>
185 TEUCHOS_TEST_FOR_EXCEPTION(
186 U_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getU: The U factor " 187 "is null. Please call initialize() (and preferably also compute()) " 188 "before calling this method. If the input matrix has not yet been set, " 189 "you must first call setMatrix() with a nonnull input matrix before you " 190 "may call initialize() or compute().");
195 template<
class MatrixType>
196 Teuchos::RCP<const Tpetra::Map<typename RILUK<MatrixType>::local_ordinal_type,
197 typename RILUK<MatrixType>::global_ordinal_type,
200 TEUCHOS_TEST_FOR_EXCEPTION(
201 A_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getDomainMap: " 202 "The matrix is null. Please call setMatrix() with a nonnull input " 203 "before calling this method.");
206 TEUCHOS_TEST_FOR_EXCEPTION(
207 Graph_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getDomainMap: " 208 "The computed graph is null. Please call initialize() before calling " 214 template<
class MatrixType>
215 Teuchos::RCP<const Tpetra::Map<typename RILUK<MatrixType>::local_ordinal_type,
216 typename RILUK<MatrixType>::global_ordinal_type,
219 TEUCHOS_TEST_FOR_EXCEPTION(
220 A_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getRangeMap: " 221 "The matrix is null. Please call setMatrix() with a nonnull input " 222 "before calling this method.");
225 TEUCHOS_TEST_FOR_EXCEPTION(
226 Graph_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getRangeMap: " 227 "The computed graph is null. Please call initialize() before calling " 233 template<
class MatrixType>
239 if (! isAllocated_) {
250 L_->setAllToScalar (STS::zero ());
251 U_->setAllToScalar (STS::zero ());
256 D_ = rcp (
new vec_type (Graph_->getL_Graph ()->getRowMap ()));
262 template<
class MatrixType>
268 using Teuchos::Exceptions::InvalidParameterName;
269 using Teuchos::Exceptions::InvalidParameterType;
285 bool gotFillLevel =
false;
287 fillLevel = params.get<
int> (
"fact: iluk level-of-fill");
290 catch (InvalidParameterType&) {
295 catch (InvalidParameterName&) {
299 if (! gotFillLevel) {
305 catch (InvalidParameterType&) {
311 if (! gotFillLevel) {
315 fillLevel = as<int> (params.get<
magnitude_type> (
"fact: iluk level-of-fill"));
318 catch (InvalidParameterType&) {
324 if (! gotFillLevel) {
328 fillLevel = as<int> (params.get<
double> (
"fact: iluk level-of-fill"));
331 catch (InvalidParameterType& e) {
341 TEUCHOS_TEST_FOR_EXCEPTION(
344 "Ifpack2::RILUK::setParameters: We should never get here! " 345 "The method should either have read the \"fact: iluk level-of-fill\" " 346 "parameter by this point, or have thrown an exception. " 347 "Please let the Ifpack2 developers know about this bug.");
355 absThresh = params.get<
magnitude_type> (
"fact: absolute threshold");
357 catch (InvalidParameterType&) {
360 absThresh = as<magnitude_type> (params.get<
double> (
"fact: absolute threshold"));
362 catch (InvalidParameterName&) {
367 relThresh = params.get<
magnitude_type> (
"fact: relative threshold");
369 catch (InvalidParameterType&) {
372 relThresh = as<magnitude_type> (params.get<
double> (
"fact: relative threshold"));
374 catch (InvalidParameterName&) {
381 catch (InvalidParameterType&) {
384 relaxValue = as<magnitude_type> (params.get<
double> (
"fact: relax value"));
386 catch (InvalidParameterName&) {
391 L_solver_->setParameters(params);
392 U_solver_->setParameters(params);
397 #ifdef IFPACK2_ILUK_EXPERIMENTAL 399 isExperimental_ = params.get<
bool> (
"fact: iluk experimental basker");
401 catch (InvalidParameterType&) {
404 catch (InvalidParameterName&) {
409 basker_threads = params.get<
int> (
"fact: iluk experimental basker threads");
411 catch (InvalidParameterType&) {
414 catch (InvalidParameterName&) {
419 basker_user_fill = (
scalar_type) params.get<
double>(
"fact: iluk experimental basker user_fill");
421 catch (InvalidParameterType&) {
424 catch (InvalidParameterName&) {
428 # ifdef IFPACK2_HTS_EXPERIMENTAL 430 hts_nthreads_ = basker_threads;
432 const std::string name(
"fact: iluk experimental HTS");
433 if (params.isType<
bool> (name))
434 use_hts_ = params.get<
bool> (name);
437 const std::string name(
"fact: iluk experimental HTS threads");
438 if (params.isType<
int> (name))
439 hts_nthreads_ = params.get<
int> (name);
448 LevelOfFill_ = fillLevel;
455 if (absThresh != -STM::one ()) {
456 Athresh_ = absThresh;
458 if (relThresh != -STM::one ()) {
459 Rthresh_ = relThresh;
461 if (relaxValue != -STM::one ()) {
462 RelaxValue_ = relaxValue;
467 template<
class MatrixType>
468 Teuchos::RCP<const typename RILUK<MatrixType>::row_matrix_type>
474 template<
class MatrixType>
475 Teuchos::RCP<const typename RILUK<MatrixType>::crs_matrix_type>
481 template<
class MatrixType>
482 Teuchos::RCP<const typename RILUK<MatrixType>::row_matrix_type>
487 using Teuchos::rcp_dynamic_cast;
488 using Teuchos::rcp_implicit_cast;
493 if (A->getRowMap ()->getComm ()->getSize () == 1 ||
494 A->getRowMap ()->isSameAs (* (A->getColMap ()))) {
501 RCP<const LocalFilter<row_matrix_type> > A_lf_r =
503 if (! A_lf_r.is_null ()) {
515 template<
class MatrixType>
520 using Teuchos::rcp_const_cast;
521 using Teuchos::rcp_dynamic_cast;
522 using Teuchos::rcp_implicit_cast;
526 const char prefix[] =
"Ifpack2::RILUK::initialize: ";
528 TEUCHOS_TEST_FOR_EXCEPTION
529 (A_.is_null (), std::runtime_error, prefix <<
"The matrix is null. Please " 530 "call setMatrix() with a nonnull input before calling this method.");
531 TEUCHOS_TEST_FOR_EXCEPTION
532 (! A_->isFillComplete (), std::runtime_error, prefix <<
"The matrix is not " 533 "fill complete. You may not invoke initialize() or compute() with this " 534 "matrix until the matrix is fill complete. If your matrix is a " 535 "Tpetra::CrsMatrix, please call fillComplete on it (with the domain and " 536 "range Maps, if appropriate) before calling this method.");
538 Teuchos::Time timer (
"RILUK::initialize");
540 Teuchos::TimeMonitor timeMon (timer);
549 isInitialized_ =
false;
550 isAllocated_ =
false;
552 Graph_ = Teuchos::null;
554 A_local_ = makeLocalFilter (A_);
555 TEUCHOS_TEST_FOR_EXCEPTION(
556 A_local_.is_null (), std::logic_error,
"Ifpack2::RILUK::initialize: " 557 "makeLocalFilter returned null; it failed to compute A_local. " 558 "Please report this bug to the Ifpack2 developers.");
566 RCP<const crs_matrix_type> A_local_crs =
568 if (A_local_crs.is_null ()) {
573 RCP<crs_matrix_type> A_local_crs_nc =
575 A_local_->getColMap (), 0));
582 typedef Tpetra::Import<local_ordinal_type, global_ordinal_type,
584 import_type
import (A_local_->getRowMap (), A_local_->getRowMap ());
585 A_local_crs_nc->doImport (*A_local_,
import, Tpetra::REPLACE);
586 A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
591 #ifdef IFPACK2_ILUK_EXPERIMENTAL 592 if (isExperimental_) A_local_crs_ = A_local_crs;
598 Graph_->initialize ();
600 checkOrderingConsistency (*A_local_);
601 L_solver_->setMatrix (L_);
602 L_solver_->initialize ();
603 U_solver_->setMatrix( U_);
604 U_solver_->initialize ();
611 #ifdef IFPACK2_ILUK_EXPERIMENTAL 612 typedef typename node_type::device_type kokkos_device;
613 typedef typename kokkos_device::execution_space kokkos_exe;
614 typedef typename crs_matrix_type::local_matrix_type kokkos_csr_matrix;
616 static_assert( std::is_same< kokkos_exe,
617 Kokkos::OpenMP>::value,
618 "Kokkos node type not supported by experimental thread basker RILUK");
621 myBasker = rcp(
new BaskerNS::Basker<local_ordinal_type, scalar_type, Kokkos::OpenMP>);
622 myBasker->Options.no_pivot =
true;
623 myBasker->Options.transpose =
true;
624 myBasker->Options.symmetric =
false;
625 myBasker->Options.realloc =
true;
626 myBasker->Options.btf =
false;
627 myBasker->Options.incomplete =
true;
628 myBasker->Options.inc_lvl = LevelOfFill_;
629 myBasker->Options.user_fill = basker_user_fill;
630 myBasker->Options.same_pattern =
false;
631 myBasker->SetThreads(basker_threads);
632 basker_reuse =
false;
634 kokkos_csr_matrix kcsr = A_local_crs_->getLocalMatrix();
636 local_ordinal_type* r_ptr;
637 r_ptr =
new local_ordinal_type[(local_ordinal_type)A_local_crs_->getNodeNumRows()+1];
641 for(local_ordinal_type bi = 0;
642 bi < A_local_crs_->getNodeNumRows()+1; bi++)
644 r_ptr[bi] = (local_ordinal_type)kcsr.graph.row_map(bi);
649 ((local_ordinal_type)A_local_crs_->getNodeNumRows()),
650 ((local_ordinal_type)A_local_crs_->getNodeNumCols()),
651 ((local_ordinal_type)A_local_crs_->getNodeNumEntries()),
653 &(kcsr.graph.entries(0)),
656 TEUCHOS_TEST_FOR_EXCEPTION(
657 basker_error != 0, std::logic_error,
"Ifpack2::RILUK::initialize:" 658 "Error in basker Symbolic");
662 TEUCHOS_TEST_FOR_EXCEPTION(
663 0==0, std::logic_error,
"Ifpack2::RILUK::initialize: " 664 "Using experimental ILUK without compiling experimental " 665 "Try again with -DIFPACK2_ILUK_EXPERIMENAL.");
671 isInitialized_ =
true;
673 initializeTime_ += timer.totalElapsedTime ();
676 #ifdef IFPACK2_ILUK_EXPERIMENTAL 678 template<
class MatrixType>
685 using Teuchos::rcp_dynamic_cast;
686 using Teuchos::rcp_implicit_cast;
687 using Teuchos::rcp_const_cast;
689 RCP<crs_matrix_type> A_local_crs_nc = rcp_const_cast<
crs_matrix_type> (A_local_crs_);
691 if (A_local_crs_.is_null ()) {
692 Teuchos::Array<local_ordinal_type> lclColInds;
693 Teuchos::Array<scalar_type> vals;
694 A_local_crs_nc->resumeFill();
695 for (
size_t i = 0; i < A_local_crs_nc->getNodeNumRows(); ++i) {
697 const auto nc = A_local_->getNumEntriesInLocalRow(i);
698 if (static_cast<size_t>(lclColInds.size()) < nc) {
699 lclColInds.resize(nc);
702 A_local_->getLocalRowCopy(i, lclColInds(), vals(), numEnt);
703 A_local_crs_nc->replaceLocalValues(i, lclColInds.view(0, numEnt), vals.view(0, numEnt));
705 A_local_crs_nc->fillComplete();
711 template<
class MatrixType>
719 Teuchos::ArrayView<const global_ordinal_type> rowGIDs = A.getRowMap()->getNodeElementList();
720 Teuchos::ArrayView<const global_ordinal_type> colGIDs = A.getColMap()->getNodeElementList();
721 bool gidsAreConsistentlyOrdered=
true;
724 if (rowGIDs[i] != colGIDs[i]) {
725 gidsAreConsistentlyOrdered=
false;
726 indexOfInconsistentGID=i;
730 TEUCHOS_TEST_FOR_EXCEPTION(gidsAreConsistentlyOrdered==
false, std::runtime_error,
731 "The ordering of the local GIDs in the row and column maps is not the same" 732 << std::endl <<
"at index " << indexOfInconsistentGID
733 <<
". Consistency is required, as all calculations are done with" 734 << std::endl <<
"local indexing.");
737 template<
class MatrixType>
742 using Teuchos::ArrayRCP;
746 using Teuchos::REDUCE_SUM;
747 using Teuchos::reduceAll;
748 typedef Tpetra::Map<local_ordinal_type,global_ordinal_type,node_type> map_type;
750 size_t NumIn = 0, NumL = 0, NumU = 0;
751 bool DiagFound =
false;
752 size_t NumNonzeroDiags = 0;
753 size_t MaxNumEntries = A.getGlobalMaxNumRowEntries();
757 Teuchos::Array<local_ordinal_type> InI(MaxNumEntries);
758 Teuchos::Array<local_ordinal_type> LI(MaxNumEntries);
759 Teuchos::Array<local_ordinal_type> UI(MaxNumEntries);
760 Teuchos::Array<scalar_type> InV(MaxNumEntries);
761 Teuchos::Array<scalar_type> LV(MaxNumEntries);
762 Teuchos::Array<scalar_type> UV(MaxNumEntries);
765 const bool ReplaceValues = L_->isStaticGraph () || L_->isLocallyIndexed ();
770 L_->setAllToScalar (STS::zero ());
771 U_->setAllToScalar (STS::zero ());
774 D_->putScalar (STS::zero ());
775 ArrayRCP<scalar_type> DV = D_->get1dViewNonConst ();
777 RCP<const map_type> rowMap = L_->getRowMap ();
787 Teuchos::ArrayView<const global_ordinal_type> nodeGIDs = rowMap->getNodeElementList();
788 for (
size_t myRow=0; myRow<A.getNodeNumRows(); ++myRow) {
793 A.getLocalRowCopy (local_row, InI(), InV(), NumIn);
801 for (
size_t j = 0; j < NumIn; ++j) {
804 if (k == local_row) {
807 DV[local_row] += Rthresh_ * InV[j] + IFPACK2_SGN(InV[j]) * Athresh_;
810 TEUCHOS_TEST_FOR_EXCEPTION(
811 true, std::runtime_error,
"Ifpack2::RILUK::initAllValues: current " 812 "GID k = " << k <<
" < 0. I'm not sure why this is an error; it is " 813 "probably an artifact of the undocumented assumptions of the " 814 "original implementation (likely copied and pasted from Ifpack). " 815 "Nevertheless, the code I found here insisted on this being an error " 816 "state, so I will throw an exception here.");
818 else if (k < local_row) {
823 else if (Teuchos::as<size_t>(k) <= rowMap->getNodeNumElements()) {
835 DV[local_row] = Athresh_;
840 L_->replaceLocalValues(local_row, LI(0, NumL), LV(0,NumL));
844 L_->insertLocalValues(local_row, LI(0,NumL), LV(0,NumL));
850 U_->replaceLocalValues(local_row, UI(0,NumU), UV(0,NumU));
854 U_->insertLocalValues(local_row, UI(0,NumU), UV(0,NumU));
862 isInitialized_ =
true;
866 template<
class MatrixType>
870 const char prefix[] =
"Ifpack2::RILUK::compute: ";
875 TEUCHOS_TEST_FOR_EXCEPTION
876 (A_.is_null (), std::runtime_error, prefix <<
"The matrix is null. Please " 877 "call setMatrix() with a nonnull input before calling this method.");
878 TEUCHOS_TEST_FOR_EXCEPTION
879 (! A_->isFillComplete (), std::runtime_error, prefix <<
"The matrix is not " 880 "fill complete. You may not invoke initialize() or compute() with this " 881 "matrix until the matrix is fill complete. If your matrix is a " 882 "Tpetra::CrsMatrix, please call fillComplete on it (with the domain and " 883 "range Maps, if appropriate) before calling this method.");
885 if (! isInitialized ()) {
889 Teuchos::Time timer (
"RILUK::compute");
890 if ( ! isExperimental_) {
892 Teuchos::TimeMonitor timeMon (timer);
898 initAllValues (*A_local_);
904 const scalar_type MaxDiagonalValue = STS::one () / MinDiagonalValue;
906 size_t NumIn, NumL, NumU;
909 const size_t MaxNumEntries =
910 L_->getNodeMaxNumRowEntries () + U_->getNodeMaxNumRowEntries () + 1;
912 Teuchos::Array<local_ordinal_type> InI(MaxNumEntries);
913 Teuchos::Array<scalar_type> InV(MaxNumEntries);
914 size_t num_cols = U_->getColMap()->getNodeNumElements();
915 Teuchos::Array<int> colflag(num_cols);
917 Teuchos::ArrayRCP<scalar_type> DV = D_->get1dViewNonConst();
923 Teuchos::ArrayView<const local_ordinal_type> UUI;
924 Teuchos::ArrayView<const scalar_type> UUV;
925 for (
size_t j = 0; j < num_cols; ++j) {
929 for (
size_t i = 0; i < L_->getNodeNumRows (); ++i) {
934 NumIn = MaxNumEntries;
935 L_->getLocalRowCopy (local_row, InI (), InV (), NumL);
938 InI[NumL] = local_row;
940 U_->getLocalRowCopy (local_row, InI (NumL+1, MaxNumEntries-NumL-1),
941 InV (NumL+1, MaxNumEntries-NumL-1), NumU);
945 for (
size_t j = 0; j < NumIn; ++j) {
951 for (
size_t jj = 0; jj < NumL; ++jj) {
957 U_->getLocalRowView(j, UUI, UUV);
960 if (RelaxValue_ == STM::zero ()) {
961 for (
size_t k = 0; k < NumUU; ++k) {
962 const int kk = colflag[UUI[k]];
967 InV[kk] -= multiplier * UUV[k];
972 for (
size_t k = 0; k < NumUU; ++k) {
976 const int kk = colflag[UUI[k]];
978 InV[kk] -= multiplier*UUV[k];
981 diagmod -= multiplier*UUV[k];
988 L_->replaceLocalValues (local_row, InI (0, NumL), InV (0, NumL));
993 if (RelaxValue_ != STM::zero ()) {
994 DV[i] += RelaxValue_*diagmod;
997 if (STS::magnitude (DV[i]) > STS::magnitude (MaxDiagonalValue)) {
998 if (STS::real (DV[i]) < STM::zero ()) {
999 DV[i] = -MinDiagonalValue;
1002 DV[i] = MinDiagonalValue;
1006 DV[i] = STS::one () / DV[i];
1009 for (
size_t j = 0; j < NumU; ++j) {
1010 InV[NumL+1+j] *= DV[i];
1015 U_->replaceLocalValues (local_row, InI (NumL+1, NumU), InV (NumL+1, NumU));
1019 for (
size_t j = 0; j < NumIn; ++j) {
1020 colflag[InI[j]] = -1;
1031 L_->fillComplete (L_->getColMap (), A_local_->getRangeMap ());
1032 U_->fillComplete (A_local_->getDomainMap (), U_->getRowMap ());
1037 TEUCHOS_TEST_FOR_EXCEPTION(
1038 0 < L_->getNodeNumRows() &&
1039 ! L_->isLowerTriangular (), std::runtime_error,
1040 "Ifpack2::RILUK::compute: L isn't lower triangular.");
1041 TEUCHOS_TEST_FOR_EXCEPTION(
1042 0 < U_->getNodeNumRows() &&
1043 ! U_->isUpperTriangular (), std::runtime_error,
1044 "Ifpack2::RILUK::compute: U isn't lower triangular.");
1046 L_solver_->compute ();
1047 U_solver_->compute ();
1050 #ifdef IFPACK2_ILUK_EXPERIMENTAL 1051 Teuchos::Time timerbasker (
"RILUK::basercompute");
1054 Teuchos::TimeMonitor timeMon (timer);
1056 if(basker_reuse ==
false)
1061 myBasker->Factor_Inc(0);
1062 basker_reuse =
true;
1068 myBasker->Options.same_pattern =
true;
1070 typedef typename crs_matrix_type::local_matrix_type kokkos_csr_matrix;
1071 kokkos_csr_matrix kcsr = A_local_crs_->getLocalMatrix();
1089 &(kcsr.graph.entries(0)),
1094 TEUCHOS_TEST_FOR_EXCEPTION(
1095 basker_error != 0, std::logic_error,
"Ifpack2::RILUK::initialize:" 1096 "Error in basker compute");
1101 # ifdef IFPACK2_HTS_EXPERIMENTAL 1104 Teuchos::Time basker_getL(
"basker_getL");
1105 Teuchos::Time hts_buildL (
"hts_buildL");
1106 Teuchos::Time basker_getU(
"basker_getU");
1107 Teuchos::Time hts_buildU (
"hts_buildU");
1109 hts_mgr_ = Teuchos::rcp(
new HTSManager());
1113 myBasker->GetPerm(&p, &q);
1116 myBasker->GetL(d.n, nnz, &d.ir, &d.jc, &d.v);
1118 typename HTST::CrsMatrix* T = HTST::make_CrsMatrix(d.n, d.ir, d.jc, d.v,
true);
1119 hts_mgr_->Limpl = HTST::preprocess(T, 1, hts_nthreads_,
true, p, 0);
1120 HTST::delete_CrsMatrix(T);
1125 myBasker->GetU(d.n, nnz, &d.ir, &d.jc, &d.v);
1127 typename HTST::CrsMatrix* T = HTST::make_CrsMatrix(d.n, d.ir, d.jc, d.v,
true);
1128 hts_mgr_->Uimpl = HTST::preprocess(T, 1, hts_nthreads_,
true, 0, q);
1129 HTST::delete_CrsMatrix(T);
1136 TEUCHOS_TEST_FOR_EXCEPTION(
1137 false, std::runtime_error,
1138 "Ifpack2::RILUK::compute: experimental not enabled");
1144 computeTime_ += timer.totalElapsedTime ();
1148 template<
class MatrixType>
1151 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1152 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
1153 Teuchos::ETransp mode,
1158 using Teuchos::rcpFromRef;
1160 TEUCHOS_TEST_FOR_EXCEPTION(
1161 A_.is_null (), std::runtime_error,
"Ifpack2::RILUK::apply: The matrix is " 1162 "null. Please call setMatrix() with a nonnull input, then initialize() " 1163 "and compute(), before calling this method.");
1164 TEUCHOS_TEST_FOR_EXCEPTION(
1165 ! isComputed (), std::runtime_error,
1166 "Ifpack2::RILUK::apply: If you have not yet called compute(), " 1167 "you must call compute() before calling this method.");
1168 TEUCHOS_TEST_FOR_EXCEPTION(
1169 X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
1170 "Ifpack2::RILUK::apply: X and Y do not have the same number of columns. " 1171 "X.getNumVectors() = " << X.getNumVectors ()
1172 <<
" != Y.getNumVectors() = " << Y.getNumVectors () <<
".");
1173 TEUCHOS_TEST_FOR_EXCEPTION(
1174 STS::isComplex && mode == Teuchos::CONJ_TRANS, std::logic_error,
1175 "Ifpack2::RILUK::apply: mode = Teuchos::CONJ_TRANS is not implemented for " 1176 "complex Scalar type. Please talk to the Ifpack2 developers to get this " 1177 "fixed. There is a FIXME in this file about this very issue.");
1178 #ifdef HAVE_IFPACK2_DEBUG 1181 TEUCHOS_TEST_FOR_EXCEPTION( STM::isnaninf (D_nrm1), std::runtime_error,
"Ifpack2::RILUK::apply: The 1-norm of the stored diagonal is NaN or Inf.");
1182 Teuchos::Array<magnitude_type> norms (X.getNumVectors ());
1185 for (
size_t j = 0; j < X.getNumVectors (); ++j) {
1186 if (STM::isnaninf (norms[j])) {
1191 TEUCHOS_TEST_FOR_EXCEPTION( ! good, std::runtime_error,
"Ifpack2::RILUK::apply: The 1-norm of the input X is NaN or Inf.");
1193 #endif // HAVE_IFPACK2_DEBUG 1198 Teuchos::Time timer (
"RILUK::apply");
1200 if(!isExperimental_){
1201 Teuchos::TimeMonitor timeMon (timer);
1202 if (alpha == one && beta == zero) {
1203 if (mode == Teuchos::NO_TRANS) {
1205 L_solver_->apply (X, Y, mode);
1209 Y.elementWiseMultiply (one, *D_, Y, zero);
1211 U_solver_->apply (Y, Y, mode);
1216 U_solver_->apply (X, Y, mode);
1223 Y.elementWiseMultiply (one, *D_, Y, zero);
1225 L_solver_->apply (Y, Y, mode);
1229 if (alpha == zero) {
1237 Y.update (alpha, Y, beta);
1243 #ifdef IFPACK2_ILUK_EXPERIMENTAL 1244 Teuchos::ArrayRCP<const scalar_type> XX;
1245 Teuchos::ArrayRCP<const scalar_type> YY;
1249 # ifdef IFPACK2_HTS_EXPERIMENTAL 1251 HTST::solve_omp(hts_mgr_->Limpl, const_cast<scalar_type*>(XX.getRawPtr()),
1252 X.getNumVectors(),
const_cast<scalar_type*
>(YY.getRawPtr()));
1253 HTST::solve_omp(hts_mgr_->Uimpl, const_cast<scalar_type*>(YY.getRawPtr()),
1259 (const_cast<scalar_type *>(XX.getRawPtr())),
1263 TEUCHOS_TEST_FOR_EXCEPTION(
1264 0==1, std::runtime_error,
1265 "Ifpack2::RILUK::apply: Experimental no enabled");
1270 #ifdef HAVE_IFPACK2_DEBUG 1272 Teuchos::Array<magnitude_type> norms (Y.getNumVectors ());
1275 for (
size_t j = 0; j < Y.getNumVectors (); ++j) {
1276 if (STM::isnaninf (norms[j])) {
1281 TEUCHOS_TEST_FOR_EXCEPTION( ! good, std::runtime_error,
"Ifpack2::RILUK::apply: The 1-norm of the output Y is NaN or Inf.");
1283 #endif // HAVE_IFPACK2_DEBUG 1286 applyTime_ = timer.totalElapsedTime ();
1290 template<
class MatrixType>
1292 multiply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1293 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
1294 const Teuchos::ETransp mode)
const 1299 if (mode != Teuchos::NO_TRANS) {
1300 U_->apply (X, Y, mode);
1301 Y.update (one, X, one);
1306 Y.elementWiseMultiply (one, *D_, Y, zero);
1308 MV Y_tmp (Y, Teuchos::Copy);
1309 L_->apply (Y_tmp, Y, mode);
1310 Y.update (one, Y_tmp, one);
1313 L_->apply (X, Y, mode);
1314 Y.update (one, X, one);
1315 Y.elementWiseMultiply (one, *D_, Y, zero);
1316 MV Y_tmp (Y, Teuchos::Copy);
1317 U_->apply (Y_tmp, Y, mode);
1318 Y.update (one, Y_tmp, one);
1323 template<
class MatrixType>
1326 std::ostringstream os;
1331 os <<
"\"Ifpack2::RILUK\": {";
1332 os <<
"Initialized: " << (isInitialized () ?
"true" :
"false") <<
", " 1333 <<
"Computed: " << (isComputed () ?
"true" :
"false") <<
", ";
1335 os <<
"Level-of-fill: " << getLevelOfFill() <<
", ";
1337 if (A_.is_null ()) {
1338 os <<
"Matrix: null";
1341 os <<
"Global matrix dimensions: [" 1342 << A_->getGlobalNumRows () <<
", " << A_->getGlobalNumCols () <<
"]" 1346 if (! L_solver_.is_null ()) os <<
", " << L_solver_->description ();
1347 if (! U_solver_.is_null ()) os <<
", " << U_solver_->description ();
1353 #if defined IFPACK2_ILUK_EXPERIMENTAL && defined IFPACK2_HTS_EXPERIMENTAL 1354 template<
class MatrixType>
1356 : Limpl(0), Uimpl(0)
1359 template<
class MatrixType>
1362 HTST::delete_Impl(Limpl);
1363 HTST::delete_Impl(Uimpl);
1366 template<
class MatrixType>
1368 : jc(0), ir(0), v(0)
1371 template<
class MatrixType>
1374 free_CrsMatrix_data();
1377 template<
class MatrixType>
1380 if (jc)
delete[] jc;
1381 if (ir)
delete[] ir;
1387 template<
class MatrixType>
1390 if ( ! ir || ! jc)
return;
1391 std::vector<Entry> es;
1393 es.resize(ir[i+1] - ir[i]);
1399 std::sort(es.begin(), es.end());
1410 #define IFPACK2_RILUK_INSTANT(S,LO,GO,N) \ 1411 template class Ifpack2::RILUK< Tpetra::RowMatrix<S, LO, GO, N> >; Ifpack2::Preconditioner< Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > ::scalar_type, Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > ::local_ordinal_type, Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > ::global_ordinal_type, Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > ::node_type >::magnitude_type Teuchos::ScalarTraits< Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > ::scalar_type >::magnitudeType magnitude_type
The type of the magnitude (absolute value) of a matrix entry.
Definition: Ifpack2_Preconditioner.hpp:111
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_RILUK_decl.hpp:272
Tpetra::RowMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > row_matrix_type
Tpetra::RowMatrix specialization used by this class.
Definition: Ifpack2_RILUK_decl.hpp:284
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_RILUK_def.hpp:116
ILU(k) factorization of a given Tpetra::RowMatrix.
Definition: Ifpack2_RILUK_decl.hpp:254
Tpetra::CrsMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > crs_matrix_type
Tpetra::CrsMatrix specialization used by this class for representing L and U.
Definition: Ifpack2_RILUK_decl.hpp:287
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_RILUK_decl.hpp:275
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_RILUK_decl.hpp:269
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getDomainMap() const
Returns the Tpetra::Map object associated with the domain of this operator.
Definition: Ifpack2_RILUK_def.hpp:199
"Preconditioner" that solves local sparse triangular systems.
Definition: Ifpack2_LocalSparseTriangularSolver_decl.hpp:83
Construct a level filled graph for use in computing an ILU(k) incomplete factorization.
Definition: Ifpack2_IlukGraph.hpp:97
Tpetra::global_size_t getGlobalNumEntries() const
Returns the number of nonzero entries in the global graph.
Definition: Ifpack2_RILUK_decl.hpp:524
Definition: Ifpack2_Container.hpp:761
Access only local rows and columns of a sparse matrix.
Definition: Ifpack2_LocalFilter_decl.hpp:160
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:72
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
Returns the Tpetra::Map object associated with the range of this operator.
Definition: Ifpack2_RILUK_def.hpp:218
Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > ::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_RILUK_decl.hpp:266