Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_ILUT_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
4 //
5 // Copyright 2009 NTESS and the Ifpack2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef IFPACK2_ILUT_DEF_HPP
11 #define IFPACK2_ILUT_DEF_HPP
12 
13 #include <type_traits>
15 #include "Teuchos_StandardParameterEntryValidators.hpp"
16 #include "Teuchos_Time.hpp"
17 #include "Tpetra_CrsMatrix.hpp"
18 #include "KokkosSparse_par_ilut.hpp"
19 
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"
25 
26 namespace Ifpack2 {
27 
28  namespace {
29 
30  struct IlutImplType {
31  enum Enum {
32  Serial,
33  PAR_ILUT
34  };
35 
36  static void loadPLTypeOption (Teuchos::Array<std::string>& type_strs, Teuchos::Array<Enum>& type_enums) {
37  type_strs.resize(2);
38  type_strs[0] = "serial";
39  type_strs[1] = "par_ilut";
40  type_enums.resize(2);
41  type_enums[0] = Serial;
42  type_enums[1] = PAR_ILUT;
43  }
44  };
45 
46 
71  template<class ScalarType>
73  ilutDefaultDropTolerance () {
75  typedef typename STS::magnitudeType magnitude_type;
77 
78  // 1/2. Hopefully this can be represented in magnitude_type.
79  const magnitude_type oneHalf = STM::one() / (STM::one() + STM::one());
80 
81  // The min ensures that in case magnitude_type has very low
82  // precision, we'll at least get some value strictly less than
83  // one.
84  return std::min (static_cast<magnitude_type> (1000) * STS::magnitude (STS::eps ()), oneHalf);
85  }
86 
87  // Full specialization for ScalarType = double.
88  // This specialization preserves ILUT's previous default behavior.
89  template<>
91  ilutDefaultDropTolerance<double> () {
92  return 1e-12;
93  }
94 
95  } // namespace (anonymous)
96 
97 
98 template <class MatrixType>
100  A_ (A),
101  Athresh_ (Teuchos::ScalarTraits<magnitude_type>::zero ()),
102  Rthresh_ (Teuchos::ScalarTraits<magnitude_type>::one ()),
103  RelaxValue_ (Teuchos::ScalarTraits<magnitude_type>::zero ()),
104  LevelOfFill_ (1.0),
105  DropTolerance_ (ilutDefaultDropTolerance<scalar_type> ()),
106  par_ilut_options_{1, 0., -1, -1, 0.75, false},
107  InitializeTime_ (0.0),
108  ComputeTime_ (0.0),
109  ApplyTime_ (0.0),
110  NumInitialize_ (0),
111  NumCompute_ (0),
112  NumApply_ (0),
113  IsInitialized_ (false),
114  IsComputed_ (false),
115  useKokkosKernelsParILUT_(false)
116 
117 {
118  allocateSolvers();
119 }
120 
121 template<class MatrixType>
122 void ILUT<MatrixType>::allocateSolvers ()
123 {
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");
128 }
129 
130 template <class MatrixType>
132 {
133  using Ifpack2::Details::getParamTryingTypes;
134  const char prefix[] = "Ifpack2::ILUT: ";
135 
136  // Don't actually change the instance variables until we've checked
137  // all parameters. This ensures that setParameters satisfies the
138  // strong exception guarantee (i.e., is transactional).
139 
140  // Parsing implementation type
141  IlutImplType::Enum ilutimplType = IlutImplType::Serial;
142  do {
143  static const char typeName[] = "fact: type";
144 
145  if ( ! params.isType<std::string>(typeName)) break;
146 
147  // Map std::string <-> IlutImplType::Enum.
148  Teuchos::Array<std::string> ilutimplTypeStrs;
149  Teuchos::Array<IlutImplType::Enum> ilutimplTypeEnums;
150  IlutImplType::loadPLTypeOption (ilutimplTypeStrs, ilutimplTypeEnums);
152  s2i(ilutimplTypeStrs (), ilutimplTypeEnums (), typeName, false);
153 
154  ilutimplType = s2i.getIntegralValue(params.get<std::string>(typeName));
155  } while (0);
156 
157  if (ilutimplType == IlutImplType::PAR_ILUT) {
158  this->useKokkosKernelsParILUT_ = true;
159  }
160  else {
161  this->useKokkosKernelsParILUT_ = false;
162  }
163 
164  // Fill level in ILUT is a double, not a magnitude_type, because it
165  // depends on LO and GO, not on Scalar. Also, you can't cast
166  // arbitrary magnitude_type (e.g., Sacado::MP::Vector) to double.
167  double fillLevel = LevelOfFill_;
168  {
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 "
183  "fill-in.");
184  }
185 
186  magnitude_type absThresh = Athresh_;
187  {
188  const std::string paramName ("fact: absolute threshold");
189  getParamTryingTypes<magnitude_type, magnitude_type, double>
190  (absThresh, params, paramName, prefix);
191  }
192 
193  magnitude_type relThresh = Rthresh_;
194  {
195  const std::string paramName ("fact: relative threshold");
196  getParamTryingTypes<magnitude_type, magnitude_type, double>
197  (relThresh, params, paramName, prefix);
198  }
199 
200  magnitude_type relaxValue = RelaxValue_;
201  {
202  const std::string paramName ("fact: relax value");
203  getParamTryingTypes<magnitude_type, magnitude_type, double>
204  (relaxValue, params, paramName, prefix);
205  }
206 
207  magnitude_type dropTol = DropTolerance_;
208  {
209  const std::string paramName ("fact: drop tolerance");
210  getParamTryingTypes<magnitude_type, magnitude_type, double>
211  (dropTol, params, paramName, prefix);
212  }
213 
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;
227 
228  std::string par_ilut_plist_name("parallel ILUT options");
229  if (params.isSublist(par_ilut_plist_name)) {
230  Teuchos::ParameterList const &par_ilut_plist = params.sublist(par_ilut_plist_name);
231 
232  std::string paramName("maximum iterations");
233  getParamTryingTypes<int, int>(par_ilut_max_iter, par_ilut_plist, paramName, prefix);
234 
235  paramName = "residual norm delta stop";
236  getParamTryingTypes<magnitude_type, magnitude_type, double>(par_ilut_residual_norm_delta_stop, par_ilut_plist, paramName, prefix);
237 
238  paramName = "team size";
239  getParamTryingTypes<int, int>(par_ilut_team_size, par_ilut_plist, paramName, prefix);
240 
241  paramName = "vector size";
242  getParamTryingTypes<int, int>(par_ilut_vector_size, par_ilut_plist, paramName, prefix);
243 
244  paramName = "fill in limit";
245  getParamTryingTypes<float, float, double>(par_ilut_fill_in_limit, par_ilut_plist, paramName, prefix);
246 
247  paramName = "verbose";
248  getParamTryingTypes<bool, bool>(par_ilut_verbose, par_ilut_plist, paramName, prefix);
249 
250  } // if (params.isSublist(par_ilut_plist_name))
251 
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;
258 
259  } //if (this->useKokkosKernelsParILUT_)
260 
261  // Forward to trisolvers.
262  L_solver_->setParameters(params);
263  U_solver_->setParameters(params);
264 
265  LevelOfFill_ = fillLevel;
266  Athresh_ = absThresh;
267  Rthresh_ = relThresh;
268  RelaxValue_ = relaxValue;
269  DropTolerance_ = dropTol;
270 }
271 
272 
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 ();
281 }
282 
283 
284 template <class MatrixType>
287  return A_;
288 }
289 
290 
291 template <class MatrixType>
294 {
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 ();
300 }
301 
302 
303 template <class MatrixType>
306 {
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 ();
312 }
313 
314 
315 template <class MatrixType>
317  return true;
318 }
319 
320 
321 template <class MatrixType>
323  return NumInitialize_;
324 }
325 
326 
327 template <class MatrixType>
329  return NumCompute_;
330 }
331 
332 
333 template <class MatrixType>
335  return NumApply_;
336 }
337 
338 
339 template <class MatrixType>
341  return InitializeTime_;
342 }
343 
344 
345 template<class MatrixType>
347  return ComputeTime_;
348 }
349 
350 
351 template<class MatrixType>
353  return ApplyTime_;
354 }
355 
356 
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.");
363  // ILUT methods cost roughly one apply + the nnz in the upper+lower triangles
364  return A_->getLocalNumEntries() + getLocalNumEntries();
365 }
366 
367 
368 template<class MatrixType>
370  return L_->getGlobalNumEntries () + U_->getGlobalNumEntries ();
371 }
372 
373 
374 template<class MatrixType>
376  return L_->getLocalNumEntries () + U_->getLocalNumEntries ();
377 }
378 
379 
380 template<class MatrixType>
382 {
383  if (A.getRawPtr () != A_.getRawPtr ()) {
384  // Check in serial or one-process mode if the matrix is square.
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.");
392 
393  // It's legal for A to be null; in that case, you may not call
394  // initialize() until calling setMatrix() with a nonnull input.
395  // Regardless, setting the matrix invalidates any previous
396  // factorization.
397  IsInitialized_ = false;
398  IsComputed_ = false;
399  A_local_ = Teuchos::null;
400 
401  // The sparse triangular solvers get a triangular factor as their
402  // input matrix. The triangular factors L_ and U_ are getting
403  // reset, so we reset the solvers' matrices to null. Do that
404  // before setting L_ and U_ to null, so that latter step actually
405  // frees the factors.
406  if (! L_solver_.is_null ()) {
407  L_solver_->setMatrix (Teuchos::null);
408  }
409  if (! U_solver_.is_null ()) {
410  U_solver_->setMatrix (Teuchos::null);
411  }
412 
413  L_ = Teuchos::null;
414  U_ = Teuchos::null;
415  A_ = A;
416  }
417 }
418 
419 template <class MatrixType>
422 {
423  using Teuchos::RCP;
424  using Teuchos::rcp;
425  using Teuchos::rcp_dynamic_cast;
426  using Teuchos::rcp_implicit_cast;
427 
428  // If A_'s communicator only has one process, or if its column and
429  // row Maps are the same, then it is already local, so use it
430  // directly.
431  if (A->getRowMap ()->getComm ()->getSize () == 1 ||
432  A->getRowMap ()->isSameAs (* (A->getColMap ()))) {
433  return A;
434  }
435 
436  // If A_ is already a LocalFilter, then use it directly. This
437  // should be the case if RILUT is being used through
438  // AdditiveSchwarz, for example.
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);
443  }
444  else {
445  // A_'s communicator has more than one process, its row Map and
446  // its column Map differ, and A_ is not a LocalFilter. Thus, we
447  // have to wrap it in a LocalFilter.
448  return rcp (new LocalFilter<row_matrix_type> (A));
449  }
450 }
451 
452 
453 template<class MatrixType>
455 {
456  using Teuchos::RCP;
457  using Teuchos::Array;
458  using Teuchos::rcp_const_cast;
459  Teuchos::Time timer ("ILUT::initialize");
460  double startTime = timer.wallTime();
461  {
462  Teuchos::TimeMonitor timeMon (timer);
463 
464  // Check that the matrix is nonnull.
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.");
469 
470  // Clear any previous computations.
471  IsInitialized_ = false;
472  IsComputed_ = false;
473  A_local_ = Teuchos::null;
474  L_ = Teuchos::null;
475  U_ = Teuchos::null;
476 
477  A_local_ = makeLocalFilter(A_); // Compute the local filter.
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.");
482 
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);
493 
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()) {
496  // the result is a host-based matrix, which is the same as what happens in RILUK
497  local_ordinal_type numRows = A_local_->getLocalNumRows();
498  Array<size_t> entriesPerRow(numRows);
499  for(local_ordinal_type i = 0; i < numRows; i++) {
500  entriesPerRow[i] = A_local_->getNumEntriesInLocalRow(i);
501  }
502  RCP<crs_matrix_type> A_local_crs_nc =
503  rcp (new crs_matrix_type (A_local_->getRowMap (),
504  A_local_->getColMap (),
505  entriesPerRow()));
506  // copy entries into A_local_crs
507  nonconst_local_inds_host_view_type indices("indices",A_local_->getLocalMaxNumRowEntries());
508  nonconst_values_host_view_type values("values",A_local_->getLocalMaxNumRowEntries());
509  for(local_ordinal_type i = 0; i < numRows; i++) {
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());
513  }
514  A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
515  A_local_crs = rcp_const_cast<const crs_matrix_type> (A_local_crs_nc);
516  }
517  auto A_local_crs_device = A_local_crs->getLocalMatrixDevice();
518 
519  //KokkosKernels requires unsigned
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);
526 
527  KokkosSparse::Experimental::par_ilut_symbolic(KernelHandle_.getRawPtr(),
528  A_local_crs_device.graph.row_map, A_local_crs_device.graph.entries,
529  L_rowmap_,
530  U_rowmap_);
531 
532  Kokkos::deep_copy(L_rowmap_orig_, L_rowmap_);
533  Kokkos::deep_copy(U_rowmap_orig_, U_rowmap_);
534  }
535 
536  IsInitialized_ = true;
537  ++NumInitialize_;
538  } //timer scope
539  InitializeTime_ += (timer.wallTime() - startTime);
540 }
541 
542 
543 template<typename ScalarType>
545 scalar_mag (const ScalarType& s)
546 {
548 }
549 
550 
551 template<class MatrixType>
553 {
554  using Teuchos::Array;
555  using Teuchos::ArrayRCP;
556  using Teuchos::ArrayView;
557  using Teuchos::as;
558  using Teuchos::rcp;
559  using Teuchos::reduceAll;
560  using Teuchos::RCP;
561  using Teuchos::rcp_const_cast;
562 
563  // Don't count initialization in the compute() time.
564  if (! isInitialized ()) {
565  initialize ();
566  }
567 
568  Teuchos::Time timer ("ILUT::compute");
569  double startTime = timer.wallTime();
570  { // Timer scope for timing compute()
571  Teuchos::TimeMonitor timeMon (timer, true);
572 
573  if (!this->useKokkosKernelsParILUT_)
574  {
575  //--------------------------------------------------------------------------
576  // Ifpack2::ILUT's serial version is a translation of the Aztec ILUT
577  // implementation. The Aztec ILUT implementation was written by Ray Tuminaro.
578  //
579  // This isn't an exact translation of the Aztec ILUT algorithm, for the
580  // following reasons:
581  // 1. Minor differences result from the fact that Aztec factors a MSR format
582  // matrix in place, while the code below factors an input CrsMatrix which
583  // remains untouched and stores the resulting factors in separate L and U
584  // CrsMatrix objects.
585  // Also, the Aztec code begins by shifting the matrix pointers back
586  // by one, and the pointer contents back by one, and then using 1-based
587  // Fortran-style indexing in the algorithm. This Ifpack2 code uses C-style
588  // 0-based indexing throughout.
589  // 2. Aztec stores the inverse of the diagonal of U. This Ifpack2 code
590  // stores the non-inverted diagonal in U.
591  // The triangular solves (in Ifpack2::ILUT::apply()) are performed by
592  // calling the Tpetra::CrsMatrix::solve method on the L and U objects, and
593  // this requires U to contain the non-inverted diagonal.
594  //
595  // ABW.
596  //--------------------------------------------------------------------------
597 
598  const scalar_type zero = STS::zero ();
599  const scalar_type one = STS::one ();
600 
601  const local_ordinal_type myNumRows = A_local_->getLocalNumRows ();
602 
603  // If this macro is defined, files containing the L and U factors
604  // will be written. DON'T CHECK IN THE CODE WITH THIS MACRO ENABLED!!!
605  // #define IFPACK2_WRITE_ILUT_FACTORS
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);
609 #endif
610 
611  // Calculate how much fill will be allowed in addition to the
612  // space that corresponds to the input matrix entries.
613  double local_nnz = static_cast<double> (A_local_->getLocalNumEntries ());
614  double fill = ((getLevelOfFill () - 1.0) * local_nnz) / (2 * myNumRows);
615 
616  // std::ceil gives the smallest integer larger than the argument.
617  // this may give a slightly different result than Aztec's fill value in
618  // some cases.
619  double fill_ceil=std::ceil(fill);
620 
621  // Similarly to Aztec, we will allow the same amount of fill for each
622  // row, half in L and half in U.
623  size_type fillL = static_cast<size_type>(fill_ceil);
624  size_type fillU = static_cast<size_type>(fill_ceil);
625 
626  Array<scalar_type> InvDiagU (myNumRows, zero);
627 
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);
632 
633  enum { UNUSED, ORIG, FILL };
634  local_ordinal_type max_col = myNumRows;
635 
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;
644 
645  // A comparison object which will be used to create 'heaps' of indices
646  // that are ordered according to the corresponding values in the
647  // 'cur_row' array.
648  greater_indirect<scalar_type,local_ordinal_type> vals_comp(cur_row);
649 
650  // =================== //
651  // start factorization //
652  // =================== //
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);
659  }
660 
661  for (local_ordinal_type row_i = 0 ; row_i < myNumRows ; ++row_i) {
662  local_inds_host_view_type ColIndicesA;
663  values_host_view_type ColValuesA;
664  size_t RowNnz;
665 
666  if (A_local_->supportsRowViews ()) {
667  A_local_->getLocalRowView (row_i, ColIndicesA, ColValuesA);
668  RowNnz = ColIndicesA.size ();
669  }
670  else {
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));
674  }
675 
676  // Always include the diagonal in the U factor. The value should get
677  // set in the next loop below.
678  U_cols.push_back(row_i);
679  cur_row[row_i] = zero;
680  pattern[row_i] = ORIG;
681 
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);
688  }
689  else if (ColIndicesA[i] > row_i) {
690  U_cols.push_back(ColIndicesA[i]);
691  }
692 
693  cur_row[ColIndicesA[i]] = ColValuesA[i];
694  pattern[ColIndicesA[i]] = ORIG;
695  rownorm += scalar_mag(ColValuesA[i]);
696  }
697  }
698 
699  // Alter the diagonal according to the absolute-threshold and
700  // relative-threshold values. If not set, those values default
701  // to zero and one respectively.
702  const magnitude_type rthresh = getRelativeThreshold();
703  const scalar_type& v = cur_row[row_i];
704  cur_row[row_i] = as<scalar_type> (getAbsoluteThreshold() * IFPACK2_SGN(v)) + rthresh*v;
705 
706  size_type orig_U_len = U_cols.size();
707  RowNnz = L_cols_heap.size() + orig_U_len;
708  rownorm = getDropTolerance() * rownorm/RowNnz;
709 
710  // The following while loop corresponds to the 'L30' goto's in Aztec.
711  size_type L_vals_heaplen = 0;
712  while (L_cols_heaplen > 0) {
713  local_ordinal_type row_k = L_cols_heap.front();
714 
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;
720  rm_heap_root(L_cols_heap, L_cols_heaplen);
721  continue;
722  }
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);
726  }
727  else if (L_vals_heaplen==0 ||
728  mag_mult < scalar_mag(cur_row[L_vals_heap.front()])) {
729  pattern[row_k] = UNUSED;
730  rm_heap_root(L_cols_heap, L_cols_heaplen);
731  continue;
732  }
733  else {
734  pattern[L_vals_heap.front()] = UNUSED;
735  rm_heap_root(L_vals_heap, L_vals_heaplen, vals_comp);
736  add_to_heap(row_k, L_vals_heap, L_vals_heaplen, vals_comp);
737  }
738  }
739 
740  /* Reduce current row */
741 
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();
745 
746  for(size_type j=0; j<ColNnzU; ++j) {
747  if (ColIndicesU[j] > row_k) {
748  scalar_type tmp = multiplier * ColValuesU[j];
749  local_ordinal_type col_j = ColIndicesU[j];
750  if (pattern[col_j] != UNUSED) {
751  cur_row[col_j] -= tmp;
752  }
753  else if (scalar_mag(tmp) > rownorm) {
754  cur_row[col_j] = -tmp;
755  pattern[col_j] = FILL;
756  if (col_j > row_i) {
757  U_cols.push_back(col_j);
758  }
759  else {
760  add_to_heap(col_j, L_cols_heap, L_cols_heaplen);
761  }
762  }
763  }
764  }
765 
766  rm_heap_root(L_cols_heap, L_cols_heaplen);
767  }//end of while(L_cols_heaplen) loop
768 
769 
770  // Put indices and values for L into arrays and then into the L_ matrix.
771 
772  // first, the original entries from the L section of A:
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;
778  }
779  }
780 
781  // next, the L entries resulting from fill:
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;
786  }
787 
788  // L has a one on the diagonal, but we don't explicitly store
789  // it. If we don't store it, then the kernel which performs the
790  // triangular solve can assume a unit diagonal, take a short-cut
791  // and perform faster.
792 
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;
797  }
798 #endif
799 
800 
801  // Pick out the diagonal element, store its reciprocal.
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;
808  }
809  InvDiagU[row_i] = one / cur_row[row_i];
810 
811  // Non-inverted diagonal is stored for U:
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;
816 
817  // Now put indices and values for U into arrays and then into the U_ matrix.
818  // The first entry in U_cols is the diagonal, which we just handled, so we'll
819  // start our loop at j=1.
820 
821  size_type U_vals_heaplen = 0;
822  for(size_type j=1; j<U_cols.size(); ++j) {
823  local_ordinal_type col = U_cols[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);
827  }
828  else if (U_vals_heaplen!=0 && scalar_mag(cur_row[col]) >
829  scalar_mag(cur_row[U_vals_heap.front()])) {
830  rm_heap_root(U_vals_heap, U_vals_heaplen, vals_comp);
831  add_to_heap(col, U_vals_heap, U_vals_heaplen, vals_comp);
832  }
833  }
834  else {
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]);
838  }
839  pattern[col] = UNUSED;
840  }
841 
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]]);
846  }
847 
848  unorm[row_i] /= (orig_U_len + U_vals_heaplen);
849 
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;
854  }
855 #endif
856 
857  L_cols_heap.clear();
858  U_cols.clear();
859  L_vals_heap.clear();
860  U_vals_heap.clear();
861  } // end of for(row_i) loop
862 
863  // Now allocate and fill the matrices
864  Array<size_t> nnzPerRow(myNumRows);
865 
866  // Make sure to release the old memory for L & U prior to recomputing to
867  // avoid bloating the high-water mark.
868  L_ = Teuchos::null;
869  U_ = Teuchos::null;
870  L_solver_->setMatrix(Teuchos::null);
871  U_solver_->setMatrix(Teuchos::null);
872 
873  for (local_ordinal_type row_i = 0 ; row_i < myNumRows ; ++row_i) {
874  nnzPerRow[row_i] = L_tmp_idx[row_i].size();
875  }
876 
877  L_ = rcp (new crs_matrix_type (A_local_->getRowMap(), A_local_->getColMap(),
878  nnzPerRow()));
879 
880  for (local_ordinal_type row_i = 0 ; row_i < myNumRows ; ++row_i) {
881  L_->insertLocalValues (row_i, L_tmp_idx[row_i](), L_tmpv[row_i]());
882  }
883 
884  L_->fillComplete();
885 
886  for (local_ordinal_type row_i = 0 ; row_i < myNumRows ; ++row_i) {
887  nnzPerRow[row_i] = U_tmp_idx[row_i].size();
888  }
889 
890  U_ = rcp (new crs_matrix_type (A_local_->getRowMap(), A_local_->getColMap(),
891  nnzPerRow()));
892 
893  for (local_ordinal_type row_i = 0 ; row_i < myNumRows ; ++row_i) {
894  U_->insertLocalValues (row_i, U_tmp_idx[row_i](), U_tmpv[row_i]());
895  }
896 
897  U_->fillComplete();
898 
899  L_solver_->setMatrix(L_);
900  L_solver_->initialize ();
901  L_solver_->compute ();
902 
903  U_solver_->setMatrix(U_);
904  U_solver_->initialize ();
905  U_solver_->compute ();
906 
907  } //if (!this->useKokkosKernelsParILUT_)
908  else {
909  // Set L, U rowmaps back to original state. Par_ilut can change them, which invalidates them
910  // if compute is called again.
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_);
916  }
917 
918  RCP<const crs_matrix_type> A_local_crs = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_local_);
919  {//Make sure values in A is picked up even in case of pattern reuse
920  if(A_local_crs.is_null()) {
921  local_ordinal_type numRows = A_local_->getLocalNumRows();
922  Array<size_t> entriesPerRow(numRows);
923  for(local_ordinal_type i = 0; i < numRows; i++) {
924  entriesPerRow[i] = A_local_->getNumEntriesInLocalRow(i);
925  }
926  RCP<crs_matrix_type> A_local_crs_nc =
927  rcp (new crs_matrix_type (A_local_->getRowMap (),
928  A_local_->getColMap (),
929  entriesPerRow()));
930  // copy entries into A_local_crs
931  nonconst_local_inds_host_view_type indices("indices",A_local_->getLocalMaxNumRowEntries());
932  nonconst_values_host_view_type values("values",A_local_->getLocalMaxNumRowEntries());
933  for(local_ordinal_type i = 0; i < numRows; i++) {
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());
937  }
938  A_local_crs_nc->fillComplete (A_local_->getDomainMap (), A_local_->getRangeMap ());
939  A_local_crs = rcp_const_cast<const crs_matrix_type> (A_local_crs_nc);
940  }
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;
945  }
946 
947  //JHU TODO Should allocation of L & U's column (aka entry) and value arrays occur here or in init()?
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);
952 
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);
956 
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_);
960 
961  auto L_kokkosCrsGraph = local_graph_device_type(L_entries_, L_rowmap_);
962  auto U_kokkosCrsGraph = local_graph_device_type(U_entries_, U_rowmap_);
963 
964  local_matrix_device_type L_localCrsMatrix_device;
965  L_localCrsMatrix_device = local_matrix_device_type("L_Factor_localmatrix",
966  A_local_->getLocalNumRows(),
967  L_values_,
968  L_kokkosCrsGraph);
969 
970  L_ = rcp (new crs_matrix_type (L_localCrsMatrix_device,
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()));
977 
978  local_matrix_device_type U_localCrsMatrix_device;
979  U_localCrsMatrix_device = local_matrix_device_type("U_Factor_localmatrix",
980  A_local_->getLocalNumRows(),
981  U_values_,
982  U_kokkosCrsGraph);
983 
984  U_ = rcp (new crs_matrix_type (U_localCrsMatrix_device,
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()));
991 
992  L_solver_->setMatrix (L_);
993  L_solver_->compute ();//NOTE: Only do compute if the pointer changed. Otherwise, do nothing
994  U_solver_->setMatrix (U_);
995  U_solver_->compute ();//NOTE: Only do compute if the pointer changed. Otherwise, do nothing
996  } //if (!this->useKokkosKernelsParILUT_) ... else ...
997 
998  } // Timer scope for timing compute()
999  ComputeTime_ += (timer.wallTime() - startTime);
1000  IsComputed_ = true;
1001  ++NumCompute_;
1002 } //compute()
1003 
1004 
1005 template <class MatrixType>
1006 void ILUT<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,
1009  Teuchos::ETransp mode,
1010  scalar_type alpha,
1011  scalar_type beta) const
1012 {
1013  using Teuchos::RCP;
1014  using Teuchos::rcp;
1015  using Teuchos::rcpFromRef;
1016 
1018  ! isComputed (), std::runtime_error,
1019  "Ifpack2::ILUT::apply: You must call compute() to compute the incomplete "
1020  "factorization, before calling apply().");
1021 
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.");
1027 
1028  const scalar_type one = STS::one ();
1029  const scalar_type zero = STS::zero ();
1030 
1031  Teuchos::Time timer ("ILUT::apply");
1032  double startTime = timer.wallTime();
1033  { // Start timing
1034  Teuchos::TimeMonitor timeMon (timer, true);
1035 
1036  if (alpha == one && beta == zero) {
1037  if (mode == Teuchos::NO_TRANS) { // Solve L (U Y) = X for Y.
1038  // Start by solving L Y = X for Y.
1039  L_solver_->apply (X, Y, mode);
1040 
1041  // Solve U Y = Y.
1042  U_solver_->apply (Y, Y, mode);
1043  }
1044  else { // Solve U^P (L^P Y)) = X for Y (where P is * or T).
1045 
1046  // Start by solving U^P Y = X for Y.
1047  U_solver_->apply (X, Y, mode);
1048 
1049  // Solve L^P Y = Y.
1050  L_solver_->apply (Y, Y, mode);
1051  }
1052  }
1053  else { // alpha != 1 or beta != 0
1054  if (alpha == zero) {
1055  // The special case for beta == 0 ensures that if Y contains Inf
1056  // or NaN values, we replace them with 0 (following BLAS
1057  // convention), rather than multiplying them by 0 to get NaN.
1058  if (beta == zero) {
1059  Y.putScalar (zero);
1060  } else {
1061  Y.scale (beta);
1062  }
1063  } else { // alpha != zero
1064  MV Y_tmp (Y.getMap (), Y.getNumVectors ());
1065  apply (X, Y_tmp, mode);
1066  Y.update (alpha, Y_tmp, beta);
1067  }
1068  }
1069  }//end timing
1070 
1071  ++NumApply_;
1072  ApplyTime_ += (timer.wallTime() - startTime);
1073 } //apply()
1074 
1075 
1076 template <class MatrixType>
1077 std::string ILUT<MatrixType>::description () const
1078 {
1079  std::ostringstream os;
1080 
1081  // Output is a valid YAML dictionary in flow style. If you don't
1082  // like everything on a single line, you should call describe()
1083  // instead.
1084  os << "\"Ifpack2::ILUT\": {";
1085  os << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
1086  << "Computed: " << (isComputed () ? "true" : "false") << ", ";
1087 
1088  os << "Level-of-fill: " << getLevelOfFill() << ", "
1089  << "absolute threshold: " << getAbsoluteThreshold() << ", "
1090  << "relative threshold: " << getRelativeThreshold() << ", "
1091  << "relaxation value: " << getRelaxValue() << ", ";
1092 
1093  if (A_.is_null ()) {
1094  os << "Matrix: null";
1095  }
1096  else {
1097  os << "Global matrix dimensions: ["
1098  << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]"
1099  << ", Global nnz: " << A_->getGlobalNumEntries();
1100  }
1101 
1102  os << "}";
1103  return os.str ();
1104 }
1105 
1106 
1107 template <class MatrixType>
1108 void
1111  const Teuchos::EVerbosityLevel verbLevel) const
1112 {
1113  using Teuchos::Comm;
1114  using Teuchos::OSTab;
1115  using Teuchos::RCP;
1117  using std::endl;
1118  using Teuchos::VERB_DEFAULT;
1119  using Teuchos::VERB_NONE;
1120  using Teuchos::VERB_LOW;
1121  using Teuchos::VERB_MEDIUM;
1122  using Teuchos::VERB_HIGH;
1123  using Teuchos::VERB_EXTREME;
1124 
1125  const Teuchos::EVerbosityLevel vl =
1126  (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
1127  OSTab tab0 (out);
1128 
1129  if (vl > VERB_NONE) {
1130  out << "\"Ifpack2::ILUT\":" << endl;
1131  OSTab tab1 (out);
1132  out << "MatrixType: " << TypeNameTraits<MatrixType>::name () << endl;
1133  if (this->getObjectLabel () != "") {
1134  out << "Label: \"" << this->getObjectLabel () << "\"" << endl;
1135  }
1136  out << "Initialized: " << (isInitialized () ? "true" : "false")
1137  << endl
1138  << "Computed: " << (isComputed () ? "true" : "false")
1139  << endl
1140  << "Level of fill: " << getLevelOfFill () << endl
1141  << "Absolute threshold: " << getAbsoluteThreshold () << endl
1142  << "Relative threshold: " << getRelativeThreshold () << endl
1143  << "Relax value: " << getRelaxValue () << endl;
1144 
1145  if (isComputed () && vl >= VERB_HIGH) {
1146  const double fillFraction =
1147  (double) getGlobalNumEntries () / (double) A_->getGlobalNumEntries ();
1148  const double nnzToRows =
1149  (double) getGlobalNumEntries () / (double) U_->getGlobalNumRows ();
1150 
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;
1158  }
1159 
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;
1166 
1167  out << "Local matrix:" << endl;
1168  A_local_->describe (out, vl);
1169  }
1170 }
1171 
1172 }//namespace Ifpack2
1173 
1174 
1175 // FIXME (mfh 16 Sep 2014) We should really only use RowMatrix here!
1176 // There's no need to instantiate for CrsMatrix too. All Ifpack2
1177 // preconditioners can and should do dynamic casts if they need a type
1178 // more specific than RowMatrix.
1179 
1180 #define IFPACK2_ILUT_INSTANT(S,LO,GO,N) \
1181  template class Ifpack2::ILUT< Tpetra::RowMatrix<S, LO, GO, N> >;
1182 
1183 #endif /* IFPACK2_ILUT_DEF_HPP */
ILUT(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition: Ifpack2_ILUT_def.hpp:99
bool hasTransposeApply() const
Whether this object&#39;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
T * getRawPtr() 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 &paramName="", 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&#39;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
static double wallTime()
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 &params)
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
bool is_null() const
Teuchos::RCP< const row_matrix_type > getMatrix() const
Returns a reference to the matrix to be preconditioned.
Definition: Ifpack2_ILUT_def.hpp:286