10 #ifndef IFPACK2_ILUT_DEF_HPP
11 #define IFPACK2_ILUT_DEF_HPP
13 #include <type_traits>
14 #include "Kokkos_StaticCrsGraph.hpp"
16 #include "Teuchos_StandardParameterEntryValidators.hpp"
18 #include "Tpetra_CrsMatrix.hpp"
19 #include "KokkosSparse_par_ilut.hpp"
21 #include "Ifpack2_Heap.hpp"
22 #include "Ifpack2_LocalFilter.hpp"
23 #include "Ifpack2_LocalSparseTriangularSolver.hpp"
24 #include "Ifpack2_Parameters.hpp"
25 #include "Ifpack2_Details_getParamTryingTypes.hpp"
39 type_strs[0] =
"serial";
40 type_strs[1] =
"par_ilut";
42 type_enums[0] = Serial;
43 type_enums[1] = PAR_ILUT;
72 template<
class ScalarType>
74 ilutDefaultDropTolerance () {
76 typedef typename STS::magnitudeType magnitude_type;
80 const magnitude_type oneHalf = STM::one() / (STM::one() + STM::one());
85 return std::min (static_cast<magnitude_type> (1000) * STS::magnitude (STS::eps ()), oneHalf);
92 ilutDefaultDropTolerance<double> () {
99 template <
class MatrixType>
102 Athresh_ (Teuchos::ScalarTraits<magnitude_type>::zero ()),
103 Rthresh_ (Teuchos::ScalarTraits<magnitude_type>::one ()),
104 RelaxValue_ (Teuchos::ScalarTraits<magnitude_type>::zero ()),
106 DropTolerance_ (ilutDefaultDropTolerance<
scalar_type> ()),
107 par_ilut_options_{1, 0., -1, -1, 0.75,
false},
108 InitializeTime_ (0.0),
114 IsInitialized_ (
false),
116 useKokkosKernelsParILUT_(
false)
122 template<
class MatrixType>
123 void ILUT<MatrixType>::allocateSolvers ()
125 L_solver_ =
Teuchos::rcp (
new LocalSparseTriangularSolver<row_matrix_type> ());
126 L_solver_->setObjectLabel(
"lower");
127 U_solver_ =
Teuchos::rcp (
new LocalSparseTriangularSolver<row_matrix_type> ());
128 U_solver_->setObjectLabel(
"upper");
131 template <
class MatrixType>
134 using Ifpack2::Details::getParamTryingTypes;
135 const char prefix[] =
"Ifpack2::ILUT: ";
142 IlutImplType::Enum ilutimplType = IlutImplType::Serial;
144 static const char typeName[] =
"fact: type";
146 if ( ! params.
isType<std::string>(typeName))
break;
151 IlutImplType::loadPLTypeOption (ilutimplTypeStrs, ilutimplTypeEnums);
153 s2i(ilutimplTypeStrs (), ilutimplTypeEnums (), typeName,
false);
158 if (ilutimplType == IlutImplType::PAR_ILUT) {
159 this->useKokkosKernelsParILUT_ =
true;
162 this->useKokkosKernelsParILUT_ =
false;
168 double fillLevel = LevelOfFill_;
170 const std::string paramName (
"fact: ilut level-of-fill");
172 (params.
isParameter(paramName) && this->useKokkosKernelsParILUT_), std::runtime_error,
173 "Ifpack2::ILUT: Parameter " << paramName <<
" is meaningless for algorithm par_ilut.");
174 getParamTryingTypes<double, double, float>
175 (fillLevel, params, paramName, prefix);
177 (fillLevel < 1.0, std::runtime_error,
178 "Ifpack2::ILUT: The \"" << paramName <<
"\" parameter must be >= "
179 "1.0, but you set it to " << fillLevel <<
". For ILUT, the fill level "
180 "means something different than it does for ILU(k). ILU(0) produces "
181 "factors with the same sparsity structure as the input matrix A. For "
182 "ILUT, level-of-fill = 1.0 will produce factors with nonzeros matching "
183 "the sparsity structure of A. level-of-fill > 1.0 allows for additional "
187 magnitude_type absThresh = Athresh_;
189 const std::string paramName (
"fact: absolute threshold");
190 getParamTryingTypes<magnitude_type, magnitude_type, double>
191 (absThresh, params, paramName, prefix);
194 magnitude_type relThresh = Rthresh_;
196 const std::string paramName (
"fact: relative threshold");
197 getParamTryingTypes<magnitude_type, magnitude_type, double>
198 (relThresh, params, paramName, prefix);
201 magnitude_type relaxValue = RelaxValue_;
203 const std::string paramName (
"fact: relax value");
204 getParamTryingTypes<magnitude_type, magnitude_type, double>
205 (relaxValue, params, paramName, prefix);
208 magnitude_type dropTol = DropTolerance_;
210 const std::string paramName (
"fact: drop tolerance");
211 getParamTryingTypes<magnitude_type, magnitude_type, double>
212 (dropTol, params, paramName, prefix);
215 int par_ilut_max_iter=20;
216 magnitude_type par_ilut_residual_norm_delta_stop=1e-2;
217 int par_ilut_team_size=0;
218 int par_ilut_vector_size=0;
219 float par_ilut_fill_in_limit=0.75;
220 bool par_ilut_verbose=
false;
221 if (this->useKokkosKernelsParILUT_) {
222 par_ilut_max_iter = par_ilut_options_.max_iter;
223 par_ilut_residual_norm_delta_stop = par_ilut_options_.residual_norm_delta_stop;
224 par_ilut_team_size = par_ilut_options_.team_size;
225 par_ilut_vector_size = par_ilut_options_.vector_size;
226 par_ilut_fill_in_limit = par_ilut_options_.fill_in_limit;
227 par_ilut_verbose = par_ilut_options_.verbose;
229 std::string par_ilut_plist_name(
"parallel ILUT options");
230 if (params.
isSublist(par_ilut_plist_name)) {
233 std::string paramName(
"maximum iterations");
234 getParamTryingTypes<int, int>(par_ilut_max_iter, par_ilut_plist, paramName, prefix);
236 paramName =
"residual norm delta stop";
237 getParamTryingTypes<magnitude_type, magnitude_type, double>(par_ilut_residual_norm_delta_stop, par_ilut_plist, paramName, prefix);
239 paramName =
"team size";
240 getParamTryingTypes<int, int>(par_ilut_team_size, par_ilut_plist, paramName, prefix);
242 paramName =
"vector size";
243 getParamTryingTypes<int, int>(par_ilut_vector_size, par_ilut_plist, paramName, prefix);
245 paramName =
"fill in limit";
246 getParamTryingTypes<float, float, double>(par_ilut_fill_in_limit, par_ilut_plist, paramName, prefix);
248 paramName =
"verbose";
249 getParamTryingTypes<bool, bool>(par_ilut_verbose, par_ilut_plist, paramName, prefix);
253 par_ilut_options_.max_iter = par_ilut_max_iter;
254 par_ilut_options_.residual_norm_delta_stop = par_ilut_residual_norm_delta_stop;
255 par_ilut_options_.team_size = par_ilut_team_size;
256 par_ilut_options_.vector_size = par_ilut_vector_size;
257 par_ilut_options_.fill_in_limit = par_ilut_fill_in_limit;
258 par_ilut_options_.verbose = par_ilut_verbose;
263 L_solver_->setParameters(params);
264 U_solver_->setParameters(params);
266 LevelOfFill_ = fillLevel;
267 Athresh_ = absThresh;
268 Rthresh_ = relThresh;
269 RelaxValue_ = relaxValue;
270 DropTolerance_ = dropTol;
274 template <
class MatrixType>
278 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getComm: "
279 "The matrix is null. Please call setMatrix() with a nonnull input "
280 "before calling this method.");
281 return A_->getComm ();
285 template <
class MatrixType>
292 template <
class MatrixType>
297 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getDomainMap: "
298 "The matrix is null. Please call setMatrix() with a nonnull input "
299 "before calling this method.");
300 return A_->getDomainMap ();
304 template <
class MatrixType>
309 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getRangeMap: "
310 "The matrix is null. Please call setMatrix() with a nonnull input "
311 "before calling this method.");
312 return A_->getRangeMap ();
316 template <
class MatrixType>
322 template <
class MatrixType>
324 return NumInitialize_;
328 template <
class MatrixType>
334 template <
class MatrixType>
340 template <
class MatrixType>
342 return InitializeTime_;
346 template<
class MatrixType>
352 template<
class MatrixType>
358 template<
class MatrixType>
361 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getNodeSmootherComplexity: "
362 "The input matrix A is null. Please call setMatrix() with a nonnull "
363 "input matrix, then call compute(), before calling this method.");
365 return A_->getLocalNumEntries() + getLocalNumEntries();
369 template<
class MatrixType>
371 return L_->getGlobalNumEntries () + U_->getGlobalNumEntries ();
375 template<
class MatrixType>
377 return L_->getLocalNumEntries () + U_->getLocalNumEntries ();
381 template<
class MatrixType>
387 ! A.
is_null () && A->getComm ()->getSize () == 1 &&
388 A->getLocalNumRows () != A->getLocalNumCols (),
389 std::runtime_error,
"Ifpack2::ILUT::setMatrix: If A's communicator only "
390 "contains one process, then A must be square. Instead, you provided a "
391 "matrix A with " << A->getLocalNumRows () <<
" rows and "
392 << A->getLocalNumCols () <<
" columns.");
398 IsInitialized_ =
false;
400 A_local_ = Teuchos::null;
407 if (! L_solver_.is_null ()) {
408 L_solver_->setMatrix (Teuchos::null);
410 if (! U_solver_.is_null ()) {
411 U_solver_->setMatrix (Teuchos::null);
420 template <
class MatrixType>
426 using Teuchos::rcp_dynamic_cast;
427 using Teuchos::rcp_implicit_cast;
432 if (A->getRowMap ()->getComm ()->getSize () == 1 ||
433 A->getRowMap ()->isSameAs (* (A->getColMap ()))) {
440 RCP<const LocalFilter<row_matrix_type> > A_lf_r =
441 rcp_dynamic_cast<
const LocalFilter<row_matrix_type> > (A);
442 if (! A_lf_r.is_null ()) {
443 return rcp_implicit_cast<
const row_matrix_type> (A_lf_r);
449 return rcp (
new LocalFilter<row_matrix_type> (A));
454 template<
class MatrixType>
459 using Teuchos::rcp_const_cast;
461 double startTime = timer.
wallTime();
467 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::initialize: "
468 "The matrix to precondition is null. Please call setMatrix() with a "
469 "nonnull input before calling this method.");
472 IsInitialized_ =
false;
474 A_local_ = Teuchos::null;
478 A_local_ = makeLocalFilter(A_);
480 A_local_.is_null(), std::logic_error,
"Ifpack2::RILUT::initialize: "
481 "makeLocalFilter returned null; it failed to compute A_local. "
482 "Please report this bug to the Ifpack2 developers.");
484 if (this->useKokkosKernelsParILUT_) {
485 this->KernelHandle_ =
Teuchos::rcp(
new kk_handle_type());
486 KernelHandle_->create_par_ilut_handle();
487 auto par_ilut_handle = KernelHandle_->get_par_ilut_handle();
488 par_ilut_handle->set_residual_norm_delta_stop(par_ilut_options_.residual_norm_delta_stop);
489 par_ilut_handle->set_team_size(par_ilut_options_.team_size);
490 par_ilut_handle->set_vector_size(par_ilut_options_.vector_size);
491 par_ilut_handle->set_fill_in_limit(par_ilut_options_.fill_in_limit);
492 par_ilut_handle->set_verbose(par_ilut_options_.verbose);
493 par_ilut_handle->set_async_update(
false);
495 RCP<const crs_matrix_type> A_local_crs = Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(A_local_);
496 if (A_local_crs.is_null()) {
499 Array<size_t> entriesPerRow(numRows);
501 entriesPerRow[i] = A_local_->getNumEntriesInLocalRow(i);
503 RCP<crs_matrix_type> A_local_crs_nc =
505 A_local_->getColMap (),
508 nonconst_local_inds_host_view_type indices(
"indices",A_local_->getLocalMaxNumRowEntries());
509 nonconst_values_host_view_type values(
"values",A_local_->getLocalMaxNumRowEntries());
511 size_t numEntries = 0;
512 A_local_->getLocalRowCopy(i, indices, values, numEntries);
513 A_local_crs_nc->insertLocalValues(i, numEntries, reinterpret_cast<scalar_type*>(values.data()), indices.data());
515 A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
518 auto A_local_crs_device = A_local_crs->getLocalMatrixDevice();
521 typedef typename Kokkos::View<usize_type*, array_layout, device_type> ulno_row_view_t;
522 const int NumMyRows = A_local_crs->getRowMap()->getLocalNumElements();
523 L_rowmap_ = ulno_row_view_t(
"L_row_map", NumMyRows + 1);
524 U_rowmap_ = ulno_row_view_t(
"U_row_map", NumMyRows + 1);
525 L_rowmap_orig_ = ulno_row_view_t(
"L_row_map_orig", NumMyRows + 1);
526 U_rowmap_orig_ = ulno_row_view_t(
"U_row_map_orig", NumMyRows + 1);
528 KokkosSparse::Experimental::par_ilut_symbolic(KernelHandle_.getRawPtr(),
529 A_local_crs_device.graph.row_map, A_local_crs_device.graph.entries,
533 Kokkos::deep_copy(L_rowmap_orig_, L_rowmap_);
534 Kokkos::deep_copy(U_rowmap_orig_, U_rowmap_);
537 IsInitialized_ =
true;
540 InitializeTime_ += (timer.
wallTime() - startTime);
544 template<
typename ScalarType>
546 scalar_mag (
const ScalarType& s)
552 template<
class MatrixType>
560 using Teuchos::reduceAll;
562 using Teuchos::rcp_const_cast;
565 if (! isInitialized ()) {
570 double startTime = timer.
wallTime();
574 if (!this->useKokkosKernelsParILUT_)
607 #ifdef IFPACK2_WRITE_ILUT_FACTORS
608 std::ofstream ofsL(
"L.ifpack2_ilut.mtx", std::ios::out);
609 std::ofstream ofsU(
"U.ifpack2_ilut.mtx", std::ios::out);
614 double local_nnz =
static_cast<double> (A_local_->getLocalNumEntries ());
615 double fill = ((getLevelOfFill () - 1.0) * local_nnz) / (2 * myNumRows);
620 double fill_ceil=std::ceil(fill);
624 size_type fillL =
static_cast<size_type
>(fill_ceil);
625 size_type fillU =
static_cast<size_type
>(fill_ceil);
627 Array<scalar_type> InvDiagU (myNumRows, zero);
629 Array<Array<local_ordinal_type> > L_tmp_idx(myNumRows);
630 Array<Array<scalar_type> > L_tmpv(myNumRows);
631 Array<Array<local_ordinal_type> > U_tmp_idx(myNumRows);
632 Array<Array<scalar_type> > U_tmpv(myNumRows);
634 enum { UNUSED, ORIG, FILL };
637 Array<int> pattern(max_col, UNUSED);
638 Array<scalar_type> cur_row(max_col, zero);
639 Array<magnitude_type> unorm(max_col);
640 magnitude_type rownorm;
641 Array<local_ordinal_type> L_cols_heap;
642 Array<local_ordinal_type> U_cols;
643 Array<local_ordinal_type> L_vals_heap;
644 Array<local_ordinal_type> U_vals_heap;
649 greater_indirect<scalar_type,local_ordinal_type> vals_comp(cur_row);
654 nonconst_local_inds_host_view_type ColIndicesARCP;
655 nonconst_values_host_view_type ColValuesARCP;
656 if (! A_local_->supportsRowViews ()) {
657 const size_t maxnz = A_local_->getLocalMaxNumRowEntries ();
658 Kokkos::resize(ColIndicesARCP,maxnz);
659 Kokkos::resize(ColValuesARCP,maxnz);
663 local_inds_host_view_type ColIndicesA;
664 values_host_view_type ColValuesA;
667 if (A_local_->supportsRowViews ()) {
668 A_local_->getLocalRowView (row_i, ColIndicesA, ColValuesA);
669 RowNnz = ColIndicesA.size ();
672 A_local_->getLocalRowCopy (row_i, ColIndicesARCP, ColValuesARCP, RowNnz);
673 ColIndicesA = Kokkos::subview(ColIndicesARCP,std::make_pair((
size_t)0, RowNnz));
674 ColValuesA = Kokkos::subview(ColValuesARCP,std::make_pair((
size_t)0, RowNnz));
679 U_cols.push_back(row_i);
680 cur_row[row_i] = zero;
681 pattern[row_i] = ORIG;
683 size_type L_cols_heaplen = 0;
684 rownorm = STM::zero ();
685 for (
size_t i = 0; i < RowNnz; ++i) {
686 if (ColIndicesA[i] < myNumRows) {
687 if (ColIndicesA[i] < row_i) {
688 add_to_heap(ColIndicesA[i], L_cols_heap, L_cols_heaplen);
690 else if (ColIndicesA[i] > row_i) {
691 U_cols.push_back(ColIndicesA[i]);
694 cur_row[ColIndicesA[i]] = ColValuesA[i];
695 pattern[ColIndicesA[i]] = ORIG;
696 rownorm += scalar_mag(ColValuesA[i]);
703 const magnitude_type rthresh = getRelativeThreshold();
705 cur_row[row_i] = as<scalar_type> (getAbsoluteThreshold() * IFPACK2_SGN(v)) + rthresh*v;
707 size_type orig_U_len = U_cols.size();
708 RowNnz = L_cols_heap.size() + orig_U_len;
709 rownorm = getDropTolerance() * rownorm/RowNnz;
712 size_type L_vals_heaplen = 0;
713 while (L_cols_heaplen > 0) {
716 scalar_type multiplier = cur_row[row_k] * InvDiagU[row_k];
717 cur_row[row_k] = multiplier;
718 magnitude_type mag_mult = scalar_mag(multiplier);
719 if (mag_mult*unorm[row_k] < rownorm) {
720 pattern[row_k] = UNUSED;
724 if (pattern[row_k] != ORIG) {
725 if (L_vals_heaplen < fillL) {
726 add_to_heap(row_k, L_vals_heap, L_vals_heaplen, vals_comp);
728 else if (L_vals_heaplen==0 ||
729 mag_mult < scalar_mag(cur_row[L_vals_heap.front()])) {
730 pattern[row_k] = UNUSED;
735 pattern[L_vals_heap.front()] = UNUSED;
737 add_to_heap(row_k, L_vals_heap, L_vals_heaplen, vals_comp);
743 ArrayView<local_ordinal_type> ColIndicesU = U_tmp_idx[row_k]();
744 ArrayView<scalar_type> ColValuesU = U_tmpv[row_k]();
745 size_type ColNnzU = ColIndicesU.size();
747 for(size_type j=0; j<ColNnzU; ++j) {
748 if (ColIndicesU[j] > row_k) {
751 if (pattern[col_j] != UNUSED) {
752 cur_row[col_j] -= tmp;
754 else if (scalar_mag(tmp) > rownorm) {
755 cur_row[col_j] = -tmp;
756 pattern[col_j] = FILL;
758 U_cols.push_back(col_j);
774 for (size_type i = 0; i < (size_type)ColIndicesA.size (); ++i) {
775 if (ColIndicesA[i] < row_i) {
776 L_tmp_idx[row_i].push_back(ColIndicesA[i]);
777 L_tmpv[row_i].push_back(cur_row[ColIndicesA[i]]);
778 pattern[ColIndicesA[i]] = UNUSED;
783 for (size_type j = 0; j < L_vals_heaplen; ++j) {
784 L_tmp_idx[row_i].push_back(L_vals_heap[j]);
785 L_tmpv[row_i].push_back(cur_row[L_vals_heap[j]]);
786 pattern[L_vals_heap[j]] = UNUSED;
794 #ifdef IFPACK2_WRITE_ILUT_FACTORS
795 for (size_type ii = 0; ii < L_tmp_idx[row_i].size (); ++ii) {
796 ofsL << row_i <<
" " << L_tmp_idx[row_i][ii] <<
" "
797 << L_tmpv[row_i][ii] << std::endl;
803 if (cur_row[row_i] == zero) {
804 std::cerr <<
"Ifpack2::ILUT::Compute: zero pivot encountered! "
805 <<
"Replacing with rownorm and continuing..."
806 <<
"(You may need to set the parameter "
807 <<
"'fact: absolute threshold'.)" << std::endl;
808 cur_row[row_i] = rownorm;
810 InvDiagU[row_i] = one / cur_row[row_i];
813 U_tmp_idx[row_i].push_back(row_i);
814 U_tmpv[row_i].push_back(cur_row[row_i]);
815 unorm[row_i] = scalar_mag(cur_row[row_i]);
816 pattern[row_i] = UNUSED;
822 size_type U_vals_heaplen = 0;
823 for(size_type j=1; j<U_cols.size(); ++j) {
825 if (pattern[col] != ORIG) {
826 if (U_vals_heaplen < fillU) {
827 add_to_heap(col, U_vals_heap, U_vals_heaplen, vals_comp);
829 else if (U_vals_heaplen!=0 && scalar_mag(cur_row[col]) >
830 scalar_mag(cur_row[U_vals_heap.front()])) {
832 add_to_heap(col, U_vals_heap, U_vals_heaplen, vals_comp);
836 U_tmp_idx[row_i].push_back(col);
837 U_tmpv[row_i].push_back(cur_row[col]);
838 unorm[row_i] += scalar_mag(cur_row[col]);
840 pattern[col] = UNUSED;
843 for(size_type j=0; j<U_vals_heaplen; ++j) {
844 U_tmp_idx[row_i].push_back(U_vals_heap[j]);
845 U_tmpv[row_i].push_back(cur_row[U_vals_heap[j]]);
846 unorm[row_i] += scalar_mag(cur_row[U_vals_heap[j]]);
849 unorm[row_i] /= (orig_U_len + U_vals_heaplen);
851 #ifdef IFPACK2_WRITE_ILUT_FACTORS
852 for(
int ii=0; ii<U_tmp_idx[row_i].size(); ++ii) {
853 ofsU <<row_i<<
" " <<U_tmp_idx[row_i][ii]<<
" "
854 <<U_tmpv[row_i][ii]<< std::endl;
865 Array<size_t> nnzPerRow(myNumRows);
871 L_solver_->setMatrix(Teuchos::null);
872 U_solver_->setMatrix(Teuchos::null);
875 nnzPerRow[row_i] = L_tmp_idx[row_i].size();
882 L_->insertLocalValues (row_i, L_tmp_idx[row_i](), L_tmpv[row_i]());
888 nnzPerRow[row_i] = U_tmp_idx[row_i].size();
895 U_->insertLocalValues (row_i, U_tmp_idx[row_i](), U_tmpv[row_i]());
900 L_solver_->setMatrix(L_);
901 L_solver_->initialize ();
902 L_solver_->compute ();
904 U_solver_->setMatrix(U_);
905 U_solver_->initialize ();
906 U_solver_->compute ();
912 if (this->isComputed()) {
913 Kokkos::resize(L_rowmap_, L_rowmap_orig_.size());
914 Kokkos::resize(U_rowmap_, U_rowmap_orig_.size());
915 Kokkos::deep_copy(L_rowmap_, L_rowmap_orig_);
916 Kokkos::deep_copy(U_rowmap_, U_rowmap_orig_);
919 RCP<const crs_matrix_type> A_local_crs = Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(A_local_);
921 if(A_local_crs.is_null()) {
923 Array<size_t> entriesPerRow(numRows);
925 entriesPerRow[i] = A_local_->getNumEntriesInLocalRow(i);
927 RCP<crs_matrix_type> A_local_crs_nc =
929 A_local_->getColMap (),
932 nonconst_local_inds_host_view_type indices(
"indices",A_local_->getLocalMaxNumRowEntries());
933 nonconst_values_host_view_type values(
"values",A_local_->getLocalMaxNumRowEntries());
935 size_t numEntries = 0;
936 A_local_->getLocalRowCopy(i, indices, values, numEntries);
937 A_local_crs_nc->insertLocalValues(i, numEntries, reinterpret_cast<scalar_type*>(values.data()),indices.data());
939 A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
942 auto lclMtx = A_local_crs->getLocalMatrixDevice();
943 A_local_rowmap_ = lclMtx.graph.row_map;
944 A_local_entries_ = lclMtx.graph.entries;
945 A_local_values_ = lclMtx.values;
949 auto par_ilut_handle = KernelHandle_->get_par_ilut_handle();
950 auto nnzL = par_ilut_handle->get_nnzL();
951 static_graph_entries_t L_entries_ = static_graph_entries_t(
"L_entries", nnzL);
952 local_matrix_values_t L_values_ = local_matrix_values_t(
"L_values", nnzL);
954 auto nnzU = par_ilut_handle->get_nnzU();
955 static_graph_entries_t U_entries_ = static_graph_entries_t(
"U_entries", nnzU);
956 local_matrix_values_t U_values_ = local_matrix_values_t(
"U_values", nnzU);
958 KokkosSparse::Experimental::par_ilut_numeric(KernelHandle_.getRawPtr(),
959 A_local_rowmap_, A_local_entries_, A_local_values_,
960 L_rowmap_, L_entries_, L_values_, U_rowmap_, U_entries_, U_values_);
962 auto L_kokkosCrsGraph = local_graph_device_type(L_entries_, L_rowmap_);
963 auto U_kokkosCrsGraph = local_graph_device_type(U_entries_, U_rowmap_);
965 local_matrix_device_type L_localCrsMatrix_device;
966 L_localCrsMatrix_device = local_matrix_device_type(
"L_Factor_localmatrix",
967 A_local_->getLocalNumRows(),
972 A_local_crs->getRowMap(),
973 A_local_crs->getColMap(),
974 A_local_crs->getDomainMap(),
975 A_local_crs->getRangeMap(),
976 A_local_crs->getGraph()->getImporter(),
977 A_local_crs->getGraph()->getExporter()));
979 local_matrix_device_type U_localCrsMatrix_device;
980 U_localCrsMatrix_device = local_matrix_device_type(
"U_Factor_localmatrix",
981 A_local_->getLocalNumRows(),
986 A_local_crs->getRowMap(),
987 A_local_crs->getColMap(),
988 A_local_crs->getDomainMap(),
989 A_local_crs->getRangeMap(),
990 A_local_crs->getGraph()->getImporter(),
991 A_local_crs->getGraph()->getExporter()));
993 L_solver_->setMatrix (L_);
994 L_solver_->compute ();
995 U_solver_->setMatrix (U_);
996 U_solver_->compute ();
1000 ComputeTime_ += (timer.
wallTime() - startTime);
1006 template <
class MatrixType>
1008 apply (
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1009 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
1016 using Teuchos::rcpFromRef;
1019 ! isComputed (), std::runtime_error,
1020 "Ifpack2::ILUT::apply: You must call compute() to compute the incomplete "
1021 "factorization, before calling apply().");
1024 X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
1025 "Ifpack2::ILUT::apply: X and Y must have the same number of columns. "
1026 "X has " << X.getNumVectors () <<
" columns, but Y has "
1027 << Y.getNumVectors () <<
" columns.");
1033 double startTime = timer.
wallTime();
1037 if (alpha == one && beta == zero) {
1040 L_solver_->apply (X, Y, mode);
1043 U_solver_->apply (Y, Y, mode);
1048 U_solver_->apply (X, Y, mode);
1051 L_solver_->apply (Y, Y, mode);
1055 if (alpha == zero) {
1065 MV Y_tmp (Y.getMap (), Y.getNumVectors ());
1066 apply (X, Y_tmp, mode);
1067 Y.update (alpha, Y_tmp, beta);
1073 ApplyTime_ += (timer.
wallTime() - startTime);
1077 template <
class MatrixType>
1080 std::ostringstream os;
1085 os <<
"\"Ifpack2::ILUT\": {";
1086 os <<
"Initialized: " << (isInitialized () ?
"true" :
"false") <<
", "
1087 <<
"Computed: " << (isComputed () ?
"true" :
"false") <<
", ";
1089 os <<
"Level-of-fill: " << getLevelOfFill() <<
", "
1090 <<
"absolute threshold: " << getAbsoluteThreshold() <<
", "
1091 <<
"relative threshold: " << getRelativeThreshold() <<
", "
1092 <<
"relaxation value: " << getRelaxValue() <<
", ";
1095 os <<
"Matrix: null";
1098 os <<
"Global matrix dimensions: ["
1099 << A_->getGlobalNumRows () <<
", " << A_->getGlobalNumCols () <<
"]"
1100 <<
", Global nnz: " << A_->getGlobalNumEntries();
1108 template <
class MatrixType>
1131 out <<
"\"Ifpack2::ILUT\":" << endl;
1133 out <<
"MatrixType: " << TypeNameTraits<MatrixType>::name () << endl;
1134 if (this->getObjectLabel () !=
"") {
1135 out <<
"Label: \"" << this->getObjectLabel () <<
"\"" << endl;
1137 out <<
"Initialized: " << (isInitialized () ?
"true" :
"false")
1139 <<
"Computed: " << (isComputed () ?
"true" :
"false")
1141 <<
"Level of fill: " << getLevelOfFill () << endl
1142 <<
"Absolute threshold: " << getAbsoluteThreshold () << endl
1143 <<
"Relative threshold: " << getRelativeThreshold () << endl
1144 <<
"Relax value: " << getRelaxValue () << endl;
1147 const double fillFraction =
1148 (double) getGlobalNumEntries () / (double) A_->getGlobalNumEntries ();
1149 const double nnzToRows =
1150 (double) getGlobalNumEntries () / (double) U_->getGlobalNumRows ();
1152 out <<
"Dimensions of L: [" << L_->getGlobalNumRows () <<
", "
1153 << L_->getGlobalNumRows () <<
"]" << endl
1154 <<
"Dimensions of U: [" << U_->getGlobalNumRows () <<
", "
1155 << U_->getGlobalNumRows () <<
"]" << endl
1156 <<
"Number of nonzeros in factors: " << getGlobalNumEntries () << endl
1157 <<
"Fill fraction of factors over A: " << fillFraction << endl
1158 <<
"Ratio of nonzeros to rows: " << nnzToRows << endl;
1161 out <<
"Number of initialize calls: " << getNumInitialize () << endl
1162 <<
"Number of compute calls: " << getNumCompute () << endl
1163 <<
"Number of apply calls: " << getNumApply () << endl
1164 <<
"Total time in seconds for initialize: " << getInitializeTime () << endl
1165 <<
"Total time in seconds for compute: " << getComputeTime () << endl
1166 <<
"Total time in seconds for apply: " << getApplyTime () << endl;
1168 out <<
"Local matrix:" << endl;
1169 A_local_->describe (out, vl);
1181 #define IFPACK2_ILUT_INSTANT(S,LO,GO,N) \
1182 template class Ifpack2::ILUT< Tpetra::RowMatrix<S, LO, GO, N> >;
ILUT(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition: Ifpack2_ILUT_def.hpp:100
bool hasTransposeApply() const
Whether this object's apply() method can apply the transpose (or conjugate transpose, if applicable).
Definition: Ifpack2_ILUT_def.hpp:317
basic_OSTab< char > OSTab
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
global_size_t getGlobalNumEntries() const
Returns the number of nonzero entries in the global graph.
Definition: Ifpack2_ILUT_def.hpp:370
void initialize()
Clear any previously computed factors, and potentially compute sparsity patterns of factors...
Definition: Ifpack2_ILUT_def.hpp:455
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
Definition: Ifpack2_ILUT_def.hpp:1111
std::string description() const
Return a simple one-line description of this object.
Definition: Ifpack2_ILUT_def.hpp:1078
ILUT (incomplete LU factorization with threshold) of a Tpetra sparse matrix.
Definition: Ifpack2_ILUT_decl.hpp:60
void rm_heap_root(Teuchos::Array< Ordinal > &heap, SizeType &heap_len)
Definition: Ifpack2_Heap.hpp:59
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool isSublist(const std::string &name) const
Teuchos::RCP< const map_type > getRangeMap() const
Tpetra::Map representing the range of this operator.
Definition: Ifpack2_ILUT_def.hpp:306
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_ILUT_decl.hpp:75
void resize(size_type new_size, const value_type &x=value_type())
void compute()
Compute factors L and U using the specified diagonal perturbation thresholds and relaxation parameter...
Definition: Ifpack2_ILUT_def.hpp:553
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_ILUT_def.hpp:382
IntegralType getIntegralValue(const std::string &str, const std::string ¶mName="", const std::string &sublistName="") const
static magnitudeType magnitude(T a)
int getNumInitialize() const
Returns the number of calls to Initialize().
Definition: Ifpack2_ILUT_def.hpp:323
double getApplyTime() const
Returns the time spent in apply().
Definition: Ifpack2_ILUT_def.hpp:353
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Returns the input matrix's communicator.
Definition: Ifpack2_ILUT_def.hpp:276
Tpetra::CrsMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > crs_matrix_type
Type of the Tpetra::CrsMatrix specialization that this class uses for the L and U factors...
Definition: Ifpack2_ILUT_decl.hpp:103
TypeTo as(const TypeFrom &t)
Teuchos::RCP< const map_type > getDomainMap() const
Tpetra::Map representing the domain of this operator.
Definition: Ifpack2_ILUT_def.hpp:294
bool isType(const std::string &name) const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
void add_to_heap(const Ordinal &idx, Teuchos::Array< Ordinal > &heap, SizeType &heap_len)
Definition: Ifpack2_Heap.hpp:37
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition: Ifpack2_ILUT_def.hpp:359
double getInitializeTime() const
Returns the time spent in Initialize().
Definition: Ifpack2_ILUT_def.hpp:341
int getNumApply() const
Returns the number of calls to apply().
Definition: Ifpack2_ILUT_def.hpp:335
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 ILUT preconditioner to X, resulting in Y.
Definition: Ifpack2_ILUT_def.hpp:1008
size_t getLocalNumEntries() const
Returns the number of nonzero entries in the local graph.
Definition: Ifpack2_ILUT_def.hpp:376
double getComputeTime() const
Returns the time spent in Compute().
Definition: Ifpack2_ILUT_def.hpp:347
void setParameters(const Teuchos::ParameterList ¶ms)
Set preconditioner parameters.
Definition: Ifpack2_ILUT_def.hpp:132
int getNumCompute() const
Returns the number of calls to Compute().
Definition: Ifpack2_ILUT_def.hpp:329
std::string typeName(const T &t)
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_ILUT_decl.hpp:78
Teuchos::RCP< const row_matrix_type > getMatrix() const
Returns a reference to the matrix to be preconditioned.
Definition: Ifpack2_ILUT_def.hpp:287