10 #ifndef IFPACK2_ILUT_DEF_HPP
11 #define IFPACK2_ILUT_DEF_HPP
13 #include <type_traits>
15 #include "Teuchos_StandardParameterEntryValidators.hpp"
17 #include "Tpetra_CrsMatrix.hpp"
18 #include "KokkosSparse_par_ilut.hpp"
20 #include "Ifpack2_Heap.hpp"
21 #include "Ifpack2_LocalFilter.hpp"
22 #include "Ifpack2_LocalSparseTriangularSolver.hpp"
23 #include "Ifpack2_Parameters.hpp"
24 #include "Ifpack2_Details_getParamTryingTypes.hpp"
38 type_strs[0] =
"serial";
39 type_strs[1] =
"par_ilut";
41 type_enums[0] = Serial;
42 type_enums[1] = PAR_ILUT;
71 template<
class ScalarType>
73 ilutDefaultDropTolerance () {
75 typedef typename STS::magnitudeType magnitude_type;
79 const magnitude_type oneHalf = STM::one() / (STM::one() + STM::one());
84 return std::min (static_cast<magnitude_type> (1000) * STS::magnitude (STS::eps ()), oneHalf);
91 ilutDefaultDropTolerance<double> () {
98 template <
class MatrixType>
101 Athresh_ (Teuchos::ScalarTraits<magnitude_type>::zero ()),
102 Rthresh_ (Teuchos::ScalarTraits<magnitude_type>::one ()),
103 RelaxValue_ (Teuchos::ScalarTraits<magnitude_type>::zero ()),
105 DropTolerance_ (ilutDefaultDropTolerance<
scalar_type> ()),
106 par_ilut_options_{1, 0., -1, -1, 0.75,
false},
107 InitializeTime_ (0.0),
113 IsInitialized_ (
false),
115 useKokkosKernelsParILUT_(
false)
121 template<
class MatrixType>
122 void ILUT<MatrixType>::allocateSolvers ()
124 L_solver_ =
Teuchos::rcp (
new LocalSparseTriangularSolver<row_matrix_type> ());
125 L_solver_->setObjectLabel(
"lower");
126 U_solver_ =
Teuchos::rcp (
new LocalSparseTriangularSolver<row_matrix_type> ());
127 U_solver_->setObjectLabel(
"upper");
130 template <
class MatrixType>
133 using Ifpack2::Details::getParamTryingTypes;
134 const char prefix[] =
"Ifpack2::ILUT: ";
141 IlutImplType::Enum ilutimplType = IlutImplType::Serial;
143 static const char typeName[] =
"fact: type";
145 if ( ! params.
isType<std::string>(typeName))
break;
150 IlutImplType::loadPLTypeOption (ilutimplTypeStrs, ilutimplTypeEnums);
152 s2i(ilutimplTypeStrs (), ilutimplTypeEnums (), typeName,
false);
157 if (ilutimplType == IlutImplType::PAR_ILUT) {
158 this->useKokkosKernelsParILUT_ =
true;
161 this->useKokkosKernelsParILUT_ =
false;
167 double fillLevel = LevelOfFill_;
169 const std::string paramName (
"fact: ilut level-of-fill");
171 (params.
isParameter(paramName) && this->useKokkosKernelsParILUT_), std::runtime_error,
172 "Ifpack2::ILUT: Parameter " << paramName <<
" is meaningless for algorithm par_ilut.");
173 getParamTryingTypes<double, double, float>
174 (fillLevel, params, paramName, prefix);
176 (fillLevel < 1.0, std::runtime_error,
177 "Ifpack2::ILUT: The \"" << paramName <<
"\" parameter must be >= "
178 "1.0, but you set it to " << fillLevel <<
". For ILUT, the fill level "
179 "means something different than it does for ILU(k). ILU(0) produces "
180 "factors with the same sparsity structure as the input matrix A. For "
181 "ILUT, level-of-fill = 1.0 will produce factors with nonzeros matching "
182 "the sparsity structure of A. level-of-fill > 1.0 allows for additional "
186 magnitude_type absThresh = Athresh_;
188 const std::string paramName (
"fact: absolute threshold");
189 getParamTryingTypes<magnitude_type, magnitude_type, double>
190 (absThresh, params, paramName, prefix);
193 magnitude_type relThresh = Rthresh_;
195 const std::string paramName (
"fact: relative threshold");
196 getParamTryingTypes<magnitude_type, magnitude_type, double>
197 (relThresh, params, paramName, prefix);
200 magnitude_type relaxValue = RelaxValue_;
202 const std::string paramName (
"fact: relax value");
203 getParamTryingTypes<magnitude_type, magnitude_type, double>
204 (relaxValue, params, paramName, prefix);
207 magnitude_type dropTol = DropTolerance_;
209 const std::string paramName (
"fact: drop tolerance");
210 getParamTryingTypes<magnitude_type, magnitude_type, double>
211 (dropTol, params, paramName, prefix);
214 int par_ilut_max_iter=20;
215 magnitude_type par_ilut_residual_norm_delta_stop=1e-2;
216 int par_ilut_team_size=0;
217 int par_ilut_vector_size=0;
218 float par_ilut_fill_in_limit=0.75;
219 bool par_ilut_verbose=
false;
220 if (this->useKokkosKernelsParILUT_) {
221 par_ilut_max_iter = par_ilut_options_.max_iter;
222 par_ilut_residual_norm_delta_stop = par_ilut_options_.residual_norm_delta_stop;
223 par_ilut_team_size = par_ilut_options_.team_size;
224 par_ilut_vector_size = par_ilut_options_.vector_size;
225 par_ilut_fill_in_limit = par_ilut_options_.fill_in_limit;
226 par_ilut_verbose = par_ilut_options_.verbose;
228 std::string par_ilut_plist_name(
"parallel ILUT options");
229 if (params.
isSublist(par_ilut_plist_name)) {
232 std::string paramName(
"maximum iterations");
233 getParamTryingTypes<int, int>(par_ilut_max_iter, par_ilut_plist, paramName, prefix);
235 paramName =
"residual norm delta stop";
236 getParamTryingTypes<magnitude_type, magnitude_type, double>(par_ilut_residual_norm_delta_stop, par_ilut_plist, paramName, prefix);
238 paramName =
"team size";
239 getParamTryingTypes<int, int>(par_ilut_team_size, par_ilut_plist, paramName, prefix);
241 paramName =
"vector size";
242 getParamTryingTypes<int, int>(par_ilut_vector_size, par_ilut_plist, paramName, prefix);
244 paramName =
"fill in limit";
245 getParamTryingTypes<float, float, double>(par_ilut_fill_in_limit, par_ilut_plist, paramName, prefix);
247 paramName =
"verbose";
248 getParamTryingTypes<bool, bool>(par_ilut_verbose, par_ilut_plist, paramName, prefix);
252 par_ilut_options_.max_iter = par_ilut_max_iter;
253 par_ilut_options_.residual_norm_delta_stop = par_ilut_residual_norm_delta_stop;
254 par_ilut_options_.team_size = par_ilut_team_size;
255 par_ilut_options_.vector_size = par_ilut_vector_size;
256 par_ilut_options_.fill_in_limit = par_ilut_fill_in_limit;
257 par_ilut_options_.verbose = par_ilut_verbose;
262 L_solver_->setParameters(params);
263 U_solver_->setParameters(params);
265 LevelOfFill_ = fillLevel;
266 Athresh_ = absThresh;
267 Rthresh_ = relThresh;
268 RelaxValue_ = relaxValue;
269 DropTolerance_ = dropTol;
273 template <
class MatrixType>
277 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getComm: "
278 "The matrix is null. Please call setMatrix() with a nonnull input "
279 "before calling this method.");
280 return A_->getComm ();
284 template <
class MatrixType>
291 template <
class MatrixType>
296 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getDomainMap: "
297 "The matrix is null. Please call setMatrix() with a nonnull input "
298 "before calling this method.");
299 return A_->getDomainMap ();
303 template <
class MatrixType>
308 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getRangeMap: "
309 "The matrix is null. Please call setMatrix() with a nonnull input "
310 "before calling this method.");
311 return A_->getRangeMap ();
315 template <
class MatrixType>
321 template <
class MatrixType>
323 return NumInitialize_;
327 template <
class MatrixType>
333 template <
class MatrixType>
339 template <
class MatrixType>
341 return InitializeTime_;
345 template<
class MatrixType>
351 template<
class MatrixType>
357 template<
class MatrixType>
360 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::getNodeSmootherComplexity: "
361 "The input matrix A is null. Please call setMatrix() with a nonnull "
362 "input matrix, then call compute(), before calling this method.");
364 return A_->getLocalNumEntries() + getLocalNumEntries();
368 template<
class MatrixType>
370 return L_->getGlobalNumEntries () + U_->getGlobalNumEntries ();
374 template<
class MatrixType>
376 return L_->getLocalNumEntries () + U_->getLocalNumEntries ();
380 template<
class MatrixType>
386 ! A.
is_null () && A->getComm ()->getSize () == 1 &&
387 A->getLocalNumRows () != A->getLocalNumCols (),
388 std::runtime_error,
"Ifpack2::ILUT::setMatrix: If A's communicator only "
389 "contains one process, then A must be square. Instead, you provided a "
390 "matrix A with " << A->getLocalNumRows () <<
" rows and "
391 << A->getLocalNumCols () <<
" columns.");
397 IsInitialized_ =
false;
399 A_local_ = Teuchos::null;
406 if (! L_solver_.is_null ()) {
407 L_solver_->setMatrix (Teuchos::null);
409 if (! U_solver_.is_null ()) {
410 U_solver_->setMatrix (Teuchos::null);
419 template <
class MatrixType>
425 using Teuchos::rcp_dynamic_cast;
426 using Teuchos::rcp_implicit_cast;
431 if (A->getRowMap ()->getComm ()->getSize () == 1 ||
432 A->getRowMap ()->isSameAs (* (A->getColMap ()))) {
439 RCP<const LocalFilter<row_matrix_type> > A_lf_r =
440 rcp_dynamic_cast<
const LocalFilter<row_matrix_type> > (A);
441 if (! A_lf_r.is_null ()) {
442 return rcp_implicit_cast<
const row_matrix_type> (A_lf_r);
448 return rcp (
new LocalFilter<row_matrix_type> (A));
453 template<
class MatrixType>
458 using Teuchos::rcp_const_cast;
460 double startTime = timer.
wallTime();
466 A_.
is_null (), std::runtime_error,
"Ifpack2::ILUT::initialize: "
467 "The matrix to precondition is null. Please call setMatrix() with a "
468 "nonnull input before calling this method.");
471 IsInitialized_ =
false;
473 A_local_ = Teuchos::null;
477 A_local_ = makeLocalFilter(A_);
479 A_local_.is_null(), std::logic_error,
"Ifpack2::RILUT::initialize: "
480 "makeLocalFilter returned null; it failed to compute A_local. "
481 "Please report this bug to the Ifpack2 developers.");
483 if (this->useKokkosKernelsParILUT_) {
484 this->KernelHandle_ =
Teuchos::rcp(
new kk_handle_type());
485 KernelHandle_->create_par_ilut_handle();
486 auto par_ilut_handle = KernelHandle_->get_par_ilut_handle();
487 par_ilut_handle->set_residual_norm_delta_stop(par_ilut_options_.residual_norm_delta_stop);
488 par_ilut_handle->set_team_size(par_ilut_options_.team_size);
489 par_ilut_handle->set_vector_size(par_ilut_options_.vector_size);
490 par_ilut_handle->set_fill_in_limit(par_ilut_options_.fill_in_limit);
491 par_ilut_handle->set_verbose(par_ilut_options_.verbose);
492 par_ilut_handle->set_async_update(
false);
494 RCP<const crs_matrix_type> A_local_crs = Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(A_local_);
495 if (A_local_crs.is_null()) {
498 Array<size_t> entriesPerRow(numRows);
500 entriesPerRow[i] = A_local_->getNumEntriesInLocalRow(i);
502 RCP<crs_matrix_type> A_local_crs_nc =
504 A_local_->getColMap (),
507 nonconst_local_inds_host_view_type indices(
"indices",A_local_->getLocalMaxNumRowEntries());
508 nonconst_values_host_view_type values(
"values",A_local_->getLocalMaxNumRowEntries());
510 size_t numEntries = 0;
511 A_local_->getLocalRowCopy(i, indices, values, numEntries);
512 A_local_crs_nc->insertLocalValues(i, numEntries, reinterpret_cast<scalar_type*>(values.data()), indices.data());
514 A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
517 auto A_local_crs_device = A_local_crs->getLocalMatrixDevice();
520 typedef typename Kokkos::View<usize_type*, array_layout, device_type> ulno_row_view_t;
521 const int NumMyRows = A_local_crs->getRowMap()->getLocalNumElements();
522 L_rowmap_ = ulno_row_view_t(
"L_row_map", NumMyRows + 1);
523 U_rowmap_ = ulno_row_view_t(
"U_row_map", NumMyRows + 1);
524 L_rowmap_orig_ = ulno_row_view_t(
"L_row_map_orig", NumMyRows + 1);
525 U_rowmap_orig_ = ulno_row_view_t(
"U_row_map_orig", NumMyRows + 1);
527 KokkosSparse::Experimental::par_ilut_symbolic(KernelHandle_.getRawPtr(),
528 A_local_crs_device.graph.row_map, A_local_crs_device.graph.entries,
532 Kokkos::deep_copy(L_rowmap_orig_, L_rowmap_);
533 Kokkos::deep_copy(U_rowmap_orig_, U_rowmap_);
536 IsInitialized_ =
true;
539 InitializeTime_ += (timer.
wallTime() - startTime);
543 template<
typename ScalarType>
545 scalar_mag (
const ScalarType& s)
551 template<
class MatrixType>
559 using Teuchos::reduceAll;
561 using Teuchos::rcp_const_cast;
564 if (! isInitialized ()) {
569 double startTime = timer.
wallTime();
573 if (!this->useKokkosKernelsParILUT_)
606 #ifdef IFPACK2_WRITE_ILUT_FACTORS
607 std::ofstream ofsL(
"L.ifpack2_ilut.mtx", std::ios::out);
608 std::ofstream ofsU(
"U.ifpack2_ilut.mtx", std::ios::out);
613 double local_nnz =
static_cast<double> (A_local_->getLocalNumEntries ());
614 double fill = ((getLevelOfFill () - 1.0) * local_nnz) / (2 * myNumRows);
619 double fill_ceil=std::ceil(fill);
623 size_type fillL =
static_cast<size_type
>(fill_ceil);
624 size_type fillU =
static_cast<size_type
>(fill_ceil);
626 Array<scalar_type> InvDiagU (myNumRows, zero);
628 Array<Array<local_ordinal_type> > L_tmp_idx(myNumRows);
629 Array<Array<scalar_type> > L_tmpv(myNumRows);
630 Array<Array<local_ordinal_type> > U_tmp_idx(myNumRows);
631 Array<Array<scalar_type> > U_tmpv(myNumRows);
633 enum { UNUSED, ORIG, FILL };
636 Array<int> pattern(max_col, UNUSED);
637 Array<scalar_type> cur_row(max_col, zero);
638 Array<magnitude_type> unorm(max_col);
639 magnitude_type rownorm;
640 Array<local_ordinal_type> L_cols_heap;
641 Array<local_ordinal_type> U_cols;
642 Array<local_ordinal_type> L_vals_heap;
643 Array<local_ordinal_type> U_vals_heap;
648 greater_indirect<scalar_type,local_ordinal_type> vals_comp(cur_row);
653 nonconst_local_inds_host_view_type ColIndicesARCP;
654 nonconst_values_host_view_type ColValuesARCP;
655 if (! A_local_->supportsRowViews ()) {
656 const size_t maxnz = A_local_->getLocalMaxNumRowEntries ();
657 Kokkos::resize(ColIndicesARCP,maxnz);
658 Kokkos::resize(ColValuesARCP,maxnz);
662 local_inds_host_view_type ColIndicesA;
663 values_host_view_type ColValuesA;
666 if (A_local_->supportsRowViews ()) {
667 A_local_->getLocalRowView (row_i, ColIndicesA, ColValuesA);
668 RowNnz = ColIndicesA.size ();
671 A_local_->getLocalRowCopy (row_i, ColIndicesARCP, ColValuesARCP, RowNnz);
672 ColIndicesA = Kokkos::subview(ColIndicesARCP,std::make_pair((
size_t)0, RowNnz));
673 ColValuesA = Kokkos::subview(ColValuesARCP,std::make_pair((
size_t)0, RowNnz));
678 U_cols.push_back(row_i);
679 cur_row[row_i] = zero;
680 pattern[row_i] = ORIG;
682 size_type L_cols_heaplen = 0;
683 rownorm = STM::zero ();
684 for (
size_t i = 0; i < RowNnz; ++i) {
685 if (ColIndicesA[i] < myNumRows) {
686 if (ColIndicesA[i] < row_i) {
687 add_to_heap(ColIndicesA[i], L_cols_heap, L_cols_heaplen);
689 else if (ColIndicesA[i] > row_i) {
690 U_cols.push_back(ColIndicesA[i]);
693 cur_row[ColIndicesA[i]] = ColValuesA[i];
694 pattern[ColIndicesA[i]] = ORIG;
695 rownorm += scalar_mag(ColValuesA[i]);
702 const magnitude_type rthresh = getRelativeThreshold();
704 cur_row[row_i] = as<scalar_type> (getAbsoluteThreshold() * IFPACK2_SGN(v)) + rthresh*v;
706 size_type orig_U_len = U_cols.size();
707 RowNnz = L_cols_heap.size() + orig_U_len;
708 rownorm = getDropTolerance() * rownorm/RowNnz;
711 size_type L_vals_heaplen = 0;
712 while (L_cols_heaplen > 0) {
715 scalar_type multiplier = cur_row[row_k] * InvDiagU[row_k];
716 cur_row[row_k] = multiplier;
717 magnitude_type mag_mult = scalar_mag(multiplier);
718 if (mag_mult*unorm[row_k] < rownorm) {
719 pattern[row_k] = UNUSED;
723 if (pattern[row_k] != ORIG) {
724 if (L_vals_heaplen < fillL) {
725 add_to_heap(row_k, L_vals_heap, L_vals_heaplen, vals_comp);
727 else if (L_vals_heaplen==0 ||
728 mag_mult < scalar_mag(cur_row[L_vals_heap.front()])) {
729 pattern[row_k] = UNUSED;
734 pattern[L_vals_heap.front()] = UNUSED;
736 add_to_heap(row_k, L_vals_heap, L_vals_heaplen, vals_comp);
742 ArrayView<local_ordinal_type> ColIndicesU = U_tmp_idx[row_k]();
743 ArrayView<scalar_type> ColValuesU = U_tmpv[row_k]();
744 size_type ColNnzU = ColIndicesU.size();
746 for(size_type j=0; j<ColNnzU; ++j) {
747 if (ColIndicesU[j] > row_k) {
750 if (pattern[col_j] != UNUSED) {
751 cur_row[col_j] -= tmp;
753 else if (scalar_mag(tmp) > rownorm) {
754 cur_row[col_j] = -tmp;
755 pattern[col_j] = FILL;
757 U_cols.push_back(col_j);
773 for (size_type i = 0; i < (size_type)ColIndicesA.size (); ++i) {
774 if (ColIndicesA[i] < row_i) {
775 L_tmp_idx[row_i].push_back(ColIndicesA[i]);
776 L_tmpv[row_i].push_back(cur_row[ColIndicesA[i]]);
777 pattern[ColIndicesA[i]] = UNUSED;
782 for (size_type j = 0; j < L_vals_heaplen; ++j) {
783 L_tmp_idx[row_i].push_back(L_vals_heap[j]);
784 L_tmpv[row_i].push_back(cur_row[L_vals_heap[j]]);
785 pattern[L_vals_heap[j]] = UNUSED;
793 #ifdef IFPACK2_WRITE_ILUT_FACTORS
794 for (size_type ii = 0; ii < L_tmp_idx[row_i].size (); ++ii) {
795 ofsL << row_i <<
" " << L_tmp_idx[row_i][ii] <<
" "
796 << L_tmpv[row_i][ii] << std::endl;
802 if (cur_row[row_i] == zero) {
803 std::cerr <<
"Ifpack2::ILUT::Compute: zero pivot encountered! "
804 <<
"Replacing with rownorm and continuing..."
805 <<
"(You may need to set the parameter "
806 <<
"'fact: absolute threshold'.)" << std::endl;
807 cur_row[row_i] = rownorm;
809 InvDiagU[row_i] = one / cur_row[row_i];
812 U_tmp_idx[row_i].push_back(row_i);
813 U_tmpv[row_i].push_back(cur_row[row_i]);
814 unorm[row_i] = scalar_mag(cur_row[row_i]);
815 pattern[row_i] = UNUSED;
821 size_type U_vals_heaplen = 0;
822 for(size_type j=1; j<U_cols.size(); ++j) {
824 if (pattern[col] != ORIG) {
825 if (U_vals_heaplen < fillU) {
826 add_to_heap(col, U_vals_heap, U_vals_heaplen, vals_comp);
828 else if (U_vals_heaplen!=0 && scalar_mag(cur_row[col]) >
829 scalar_mag(cur_row[U_vals_heap.front()])) {
831 add_to_heap(col, U_vals_heap, U_vals_heaplen, vals_comp);
835 U_tmp_idx[row_i].push_back(col);
836 U_tmpv[row_i].push_back(cur_row[col]);
837 unorm[row_i] += scalar_mag(cur_row[col]);
839 pattern[col] = UNUSED;
842 for(size_type j=0; j<U_vals_heaplen; ++j) {
843 U_tmp_idx[row_i].push_back(U_vals_heap[j]);
844 U_tmpv[row_i].push_back(cur_row[U_vals_heap[j]]);
845 unorm[row_i] += scalar_mag(cur_row[U_vals_heap[j]]);
848 unorm[row_i] /= (orig_U_len + U_vals_heaplen);
850 #ifdef IFPACK2_WRITE_ILUT_FACTORS
851 for(
int ii=0; ii<U_tmp_idx[row_i].size(); ++ii) {
852 ofsU <<row_i<<
" " <<U_tmp_idx[row_i][ii]<<
" "
853 <<U_tmpv[row_i][ii]<< std::endl;
864 Array<size_t> nnzPerRow(myNumRows);
870 L_solver_->setMatrix(Teuchos::null);
871 U_solver_->setMatrix(Teuchos::null);
874 nnzPerRow[row_i] = L_tmp_idx[row_i].size();
881 L_->insertLocalValues (row_i, L_tmp_idx[row_i](), L_tmpv[row_i]());
887 nnzPerRow[row_i] = U_tmp_idx[row_i].size();
894 U_->insertLocalValues (row_i, U_tmp_idx[row_i](), U_tmpv[row_i]());
899 L_solver_->setMatrix(L_);
900 L_solver_->initialize ();
901 L_solver_->compute ();
903 U_solver_->setMatrix(U_);
904 U_solver_->initialize ();
905 U_solver_->compute ();
911 if (this->isComputed()) {
912 Kokkos::resize(L_rowmap_, L_rowmap_orig_.size());
913 Kokkos::resize(U_rowmap_, U_rowmap_orig_.size());
914 Kokkos::deep_copy(L_rowmap_, L_rowmap_orig_);
915 Kokkos::deep_copy(U_rowmap_, U_rowmap_orig_);
918 RCP<const crs_matrix_type> A_local_crs = Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(A_local_);
920 if(A_local_crs.is_null()) {
922 Array<size_t> entriesPerRow(numRows);
924 entriesPerRow[i] = A_local_->getNumEntriesInLocalRow(i);
926 RCP<crs_matrix_type> A_local_crs_nc =
928 A_local_->getColMap (),
931 nonconst_local_inds_host_view_type indices(
"indices",A_local_->getLocalMaxNumRowEntries());
932 nonconst_values_host_view_type values(
"values",A_local_->getLocalMaxNumRowEntries());
934 size_t numEntries = 0;
935 A_local_->getLocalRowCopy(i, indices, values, numEntries);
936 A_local_crs_nc->insertLocalValues(i, numEntries, reinterpret_cast<scalar_type*>(values.data()),indices.data());
938 A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
941 auto lclMtx = A_local_crs->getLocalMatrixDevice();
942 A_local_rowmap_ = lclMtx.graph.row_map;
943 A_local_entries_ = lclMtx.graph.entries;
944 A_local_values_ = lclMtx.values;
948 auto par_ilut_handle = KernelHandle_->get_par_ilut_handle();
949 auto nnzL = par_ilut_handle->get_nnzL();
950 static_graph_entries_t L_entries_ = static_graph_entries_t(
"L_entries", nnzL);
951 local_matrix_values_t L_values_ = local_matrix_values_t(
"L_values", nnzL);
953 auto nnzU = par_ilut_handle->get_nnzU();
954 static_graph_entries_t U_entries_ = static_graph_entries_t(
"U_entries", nnzU);
955 local_matrix_values_t U_values_ = local_matrix_values_t(
"U_values", nnzU);
957 KokkosSparse::Experimental::par_ilut_numeric(KernelHandle_.getRawPtr(),
958 A_local_rowmap_, A_local_entries_, A_local_values_,
959 L_rowmap_, L_entries_, L_values_, U_rowmap_, U_entries_, U_values_);
961 auto L_kokkosCrsGraph = local_graph_device_type(L_entries_, L_rowmap_);
962 auto U_kokkosCrsGraph = local_graph_device_type(U_entries_, U_rowmap_);
964 local_matrix_device_type L_localCrsMatrix_device;
965 L_localCrsMatrix_device = local_matrix_device_type(
"L_Factor_localmatrix",
966 A_local_->getLocalNumRows(),
971 A_local_crs->getRowMap(),
972 A_local_crs->getColMap(),
973 A_local_crs->getDomainMap(),
974 A_local_crs->getRangeMap(),
975 A_local_crs->getGraph()->getImporter(),
976 A_local_crs->getGraph()->getExporter()));
978 local_matrix_device_type U_localCrsMatrix_device;
979 U_localCrsMatrix_device = local_matrix_device_type(
"U_Factor_localmatrix",
980 A_local_->getLocalNumRows(),
985 A_local_crs->getRowMap(),
986 A_local_crs->getColMap(),
987 A_local_crs->getDomainMap(),
988 A_local_crs->getRangeMap(),
989 A_local_crs->getGraph()->getImporter(),
990 A_local_crs->getGraph()->getExporter()));
992 L_solver_->setMatrix (L_);
993 L_solver_->compute ();
994 U_solver_->setMatrix (U_);
995 U_solver_->compute ();
999 ComputeTime_ += (timer.
wallTime() - startTime);
1005 template <
class MatrixType>
1007 apply (
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1008 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
1015 using Teuchos::rcpFromRef;
1018 ! isComputed (), std::runtime_error,
1019 "Ifpack2::ILUT::apply: You must call compute() to compute the incomplete "
1020 "factorization, before calling apply().");
1023 X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
1024 "Ifpack2::ILUT::apply: X and Y must have the same number of columns. "
1025 "X has " << X.getNumVectors () <<
" columns, but Y has "
1026 << Y.getNumVectors () <<
" columns.");
1032 double startTime = timer.
wallTime();
1036 if (alpha == one && beta == zero) {
1039 L_solver_->apply (X, Y, mode);
1042 U_solver_->apply (Y, Y, mode);
1047 U_solver_->apply (X, Y, mode);
1050 L_solver_->apply (Y, Y, mode);
1054 if (alpha == zero) {
1064 MV Y_tmp (Y.getMap (), Y.getNumVectors ());
1065 apply (X, Y_tmp, mode);
1066 Y.update (alpha, Y_tmp, beta);
1072 ApplyTime_ += (timer.
wallTime() - startTime);
1076 template <
class MatrixType>
1079 std::ostringstream os;
1084 os <<
"\"Ifpack2::ILUT\": {";
1085 os <<
"Initialized: " << (isInitialized () ?
"true" :
"false") <<
", "
1086 <<
"Computed: " << (isComputed () ?
"true" :
"false") <<
", ";
1088 os <<
"Level-of-fill: " << getLevelOfFill() <<
", "
1089 <<
"absolute threshold: " << getAbsoluteThreshold() <<
", "
1090 <<
"relative threshold: " << getRelativeThreshold() <<
", "
1091 <<
"relaxation value: " << getRelaxValue() <<
", ";
1094 os <<
"Matrix: null";
1097 os <<
"Global matrix dimensions: ["
1098 << A_->getGlobalNumRows () <<
", " << A_->getGlobalNumCols () <<
"]"
1099 <<
", Global nnz: " << A_->getGlobalNumEntries();
1107 template <
class MatrixType>
1130 out <<
"\"Ifpack2::ILUT\":" << endl;
1132 out <<
"MatrixType: " << TypeNameTraits<MatrixType>::name () << endl;
1133 if (this->getObjectLabel () !=
"") {
1134 out <<
"Label: \"" << this->getObjectLabel () <<
"\"" << endl;
1136 out <<
"Initialized: " << (isInitialized () ?
"true" :
"false")
1138 <<
"Computed: " << (isComputed () ?
"true" :
"false")
1140 <<
"Level of fill: " << getLevelOfFill () << endl
1141 <<
"Absolute threshold: " << getAbsoluteThreshold () << endl
1142 <<
"Relative threshold: " << getRelativeThreshold () << endl
1143 <<
"Relax value: " << getRelaxValue () << endl;
1146 const double fillFraction =
1147 (double) getGlobalNumEntries () / (double) A_->getGlobalNumEntries ();
1148 const double nnzToRows =
1149 (double) getGlobalNumEntries () / (double) U_->getGlobalNumRows ();
1151 out <<
"Dimensions of L: [" << L_->getGlobalNumRows () <<
", "
1152 << L_->getGlobalNumRows () <<
"]" << endl
1153 <<
"Dimensions of U: [" << U_->getGlobalNumRows () <<
", "
1154 << U_->getGlobalNumRows () <<
"]" << endl
1155 <<
"Number of nonzeros in factors: " << getGlobalNumEntries () << endl
1156 <<
"Fill fraction of factors over A: " << fillFraction << endl
1157 <<
"Ratio of nonzeros to rows: " << nnzToRows << endl;
1160 out <<
"Number of initialize calls: " << getNumInitialize () << endl
1161 <<
"Number of compute calls: " << getNumCompute () << endl
1162 <<
"Number of apply calls: " << getNumApply () << endl
1163 <<
"Total time in seconds for initialize: " << getInitializeTime () << endl
1164 <<
"Total time in seconds for compute: " << getComputeTime () << endl
1165 <<
"Total time in seconds for apply: " << getApplyTime () << endl;
1167 out <<
"Local matrix:" << endl;
1168 A_local_->describe (out, vl);
1180 #define IFPACK2_ILUT_INSTANT(S,LO,GO,N) \
1181 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:99
bool hasTransposeApply() const
Whether this object's apply() method can apply the transpose (or conjugate transpose, if applicable).
Definition: Ifpack2_ILUT_def.hpp:316
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:369
void initialize()
Clear any previously computed factors, and potentially compute sparsity patterns of factors...
Definition: Ifpack2_ILUT_def.hpp:454
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:1110
std::string description() const
Return a simple one-line description of this object.
Definition: Ifpack2_ILUT_def.hpp:1077
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:305
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:552
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_ILUT_def.hpp:381
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:322
double getApplyTime() const
Returns the time spent in apply().
Definition: Ifpack2_ILUT_def.hpp:352
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Returns the input matrix's communicator.
Definition: Ifpack2_ILUT_def.hpp:275
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:293
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:358
double getInitializeTime() const
Returns the time spent in Initialize().
Definition: Ifpack2_ILUT_def.hpp:340
int getNumApply() const
Returns the number of calls to apply().
Definition: Ifpack2_ILUT_def.hpp:334
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:1007
size_t getLocalNumEntries() const
Returns the number of nonzero entries in the local graph.
Definition: Ifpack2_ILUT_def.hpp:375
double getComputeTime() const
Returns the time spent in Compute().
Definition: Ifpack2_ILUT_def.hpp:346
void setParameters(const Teuchos::ParameterList ¶ms)
Set preconditioner parameters.
Definition: Ifpack2_ILUT_def.hpp:131
int getNumCompute() const
Returns the number of calls to Compute().
Definition: Ifpack2_ILUT_def.hpp:328
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:286