16 #ifndef IFPACK2_ILUK_GRAPH_HPP
17 #define IFPACK2_ILUK_GRAPH_HPP
22 #include "KokkosSparse_spiluk.hpp"
24 #include <Ifpack2_ConfigDefs.hpp>
26 #include <Teuchos_CommHelpers.hpp>
27 #include <Tpetra_CrsGraph.hpp>
28 #include <Tpetra_Details_WrappedDualView.hpp>
29 #include <Tpetra_Import.hpp>
30 #include <Ifpack2_CreateOverlapGraph.hpp>
31 #include <Ifpack2_Parameters.hpp>
66 template<
class GraphType,
class KKHandleType>
69 typedef typename GraphType::local_ordinal_type local_ordinal_type;
70 typedef typename GraphType::global_ordinal_type global_ordinal_type;
71 typedef typename GraphType::node_type node_type;
74 typedef Tpetra::RowGraph<local_ordinal_type,
78 typedef Tpetra::CrsGraph<local_ordinal_type,
84 typedef typename crs_graph_type::nonconst_global_inds_host_view_type nonconst_global_inds_host_view_type;
85 typedef typename crs_graph_type::nonconst_local_inds_host_view_type nonconst_local_inds_host_view_type;
86 typedef typename crs_graph_type::global_inds_host_view_type global_inds_host_view_type;
87 typedef typename crs_graph_type::local_inds_host_view_type local_inds_host_view_type;
102 const int levelOverlap,
103 const double overalloc = 2.);
152 return OverlapGraph_;
159 typedef typename GraphType::map_type map_type;
182 void constructOverlapGraph();
188 const double Overalloc_;
191 size_t NumMyDiagonals_;
192 size_t NumGlobalDiagonals_;
196 template<
class GraphType,
class KKHandleType>
200 const int levelOverlap,
201 const double overalloc)
203 LevelFill_ (levelFill),
204 LevelOverlap_ (levelOverlap),
205 Overalloc_ (overalloc),
207 NumGlobalDiagonals_ (0)
210 "Ifpack2::IlukGraph: FATAL: overalloc must be greater than 1.")
214 template<
class GraphType,
class KKHandleType>
219 template<
class GraphType,
class KKHandleType>
223 getParameter (parameterlist,
"iluk level-of-fill", LevelFill_);
224 getParameter (parameterlist,
"iluk level-of-overlap", LevelOverlap_);
228 template<
class GraphType,
class KKHandleType>
233 if (OverlapGraph_ == Teuchos::null) {
234 OverlapGraph_ = createOverlapGraph<GraphType> (Graph_, LevelOverlap_);
239 template<
class GraphType,
class KKHandleType>
247 using Teuchos::reduceAll;
249 size_t NumIn, NumL, NumU;
252 constructOverlapGraph();
255 const int MaxNumIndices = OverlapGraph_->getLocalMaxNumRowEntries ();
259 const int NumMyRows = OverlapGraph_->getRowMap ()->getLocalNumElements ();
261 using device_type =
typename node_type::device_type;
262 using execution_space =
typename device_type::execution_space;
263 using dual_view_type = Kokkos::DualView<size_t*,device_type>;
264 dual_view_type numEntPerRow_dv(
"numEntPerRow",NumMyRows);
265 Tpetra::Details::WrappedDualView<dual_view_type> numEntPerRow(numEntPerRow_dv);
267 const auto overalloc = Overalloc_;
268 const auto levelfill = LevelFill_;
271 auto numEntPerRow_d = numEntPerRow.getDeviceView(Tpetra::Access::OverwriteAll);
272 auto localOverlapGraph = OverlapGraph_->getLocalGraphDevice();
273 Kokkos::parallel_for(
"CountOverlapGraphRowEntries",
274 Kokkos::RangePolicy<execution_space>(0, NumMyRows),
275 KOKKOS_LAMBDA(
const int i)
278 int RowMaxNumIndices = localOverlapGraph.rowConst(i).length;
279 numEntPerRow_d(i) = (levelfill == 0) ? RowMaxNumIndices
280 : Kokkos::ceil(static_cast<double>(RowMaxNumIndices)
281 * Kokkos::pow(overalloc, levelfill));
291 OverlapGraph_->getRowMap (),
294 OverlapGraph_->getRowMap (),
297 Array<local_ordinal_type> L (MaxNumIndices);
298 Array<local_ordinal_type> U (MaxNumIndices);
304 for (
int i = 0; i< NumMyRows; ++i) {
305 local_inds_host_view_type my_indices;
306 OverlapGraph_->getLocalRowView (i, my_indices);
313 NumIn = my_indices.size();
315 for (
size_t j = 0; j < NumIn; ++j) {
316 const local_ordinal_type k = my_indices[j];
340 L_Graph_->insertLocalIndices (i, NumL, L.data());
343 U_Graph_->insertLocalIndices (i, NumU, U.data());
347 if (LevelFill_ > 0) {
349 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
350 RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
351 RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
352 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
353 RCP<Teuchos::ParameterList> params = Teuchos::parameterList ();
354 params->set (
"Optimize Storage",
false);
355 L_Graph_->fillComplete (L_DomainMap, L_RangeMap, params);
356 U_Graph_->fillComplete (U_DomainMap, U_RangeMap, params);
357 L_Graph_->resumeFill ();
358 U_Graph_->resumeFill ();
364 int MaxRC = NumMyRows;
365 std::vector<std::vector<int> > Levels(MaxRC);
366 std::vector<int> LinkList(MaxRC);
367 std::vector<int> CurrentLevel(MaxRC);
368 Array<local_ordinal_type> CurrentRow (MaxRC + 1);
369 std::vector<int> LevelsRowU(MaxRC);
372 for (
int i = 0; i < NumMyRows; ++i) {
377 size_t LenL = L_Graph_->getNumEntriesInLocalRow(i);
378 size_t LenU = U_Graph_->getNumEntriesInLocalRow(i);
379 size_t Len = LenL + LenU + 1;
380 CurrentRow.resize(Len);
381 nonconst_local_inds_host_view_type CurrentRow_view(CurrentRow.data(),CurrentRow.size());
382 L_Graph_->getLocalRowCopy(i, CurrentRow_view, LenL);
383 CurrentRow[LenL] = i;
385 ArrayView<local_ordinal_type> URowView = CurrentRow.
view (LenL+1,LenU);
386 nonconst_local_inds_host_view_type URowView_v(URowView.data(),URowView.size());
389 U_Graph_->getLocalRowCopy (i, URowView_v, LenU);
394 for (
size_t j=0; j<Len-1; j++) {
395 LinkList[CurrentRow[j]] = CurrentRow[j+1];
396 CurrentLevel[CurrentRow[j]] = 0;
399 LinkList[CurrentRow[Len-1]] = NumMyRows;
400 CurrentLevel[CurrentRow[Len-1]] = 0;
404 First = CurrentRow[0];
407 int PrevInList = Next;
408 int NextInList = LinkList[Next];
411 local_inds_host_view_type IndicesU;
412 U_Graph_->getLocalRowView (RowU, IndicesU);
414 int LengthRowU = IndicesU.size ();
420 for (ii = 0; ii < LengthRowU; ) {
421 int CurInList = IndicesU[ii];
422 if (CurInList < NextInList) {
424 int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
425 if (NewLevel <= LevelFill_) {
426 LinkList[PrevInList] = CurInList;
427 LinkList[CurInList] = NextInList;
428 PrevInList = CurInList;
429 CurrentLevel[CurInList] = NewLevel;
433 else if (CurInList == NextInList) {
434 PrevInList = NextInList;
435 NextInList = LinkList[PrevInList];
436 int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
437 CurrentLevel[CurInList] = std::min (CurrentLevel[CurInList],
442 PrevInList = NextInList;
443 NextInList = LinkList[PrevInList];
446 Next = LinkList[Next];
450 CurrentRow.resize(0);
456 CurrentRow.push_back(Next);
457 Next = LinkList[Next];
463 L_Graph_->removeLocalIndices (i);
464 if (CurrentRow.size() > 0) {
465 L_Graph_->insertLocalIndices (i, CurrentRow.size(),CurrentRow.data());
471 Next != i, std::runtime_error,
472 "Ifpack2::IlukGraph::initialize: FATAL: U has zero diagonal")
474 LevelsRowU[0] = CurrentLevel[Next];
475 Next = LinkList[Next];
478 CurrentRow.resize(0);
481 while (Next < NumMyRows) {
482 LevelsRowU[LenU+1] = CurrentLevel[Next];
483 CurrentRow.push_back (Next);
485 Next = LinkList[Next];
492 U_Graph_->removeLocalIndices (i);
494 U_Graph_->insertLocalIndices (i, CurrentRow.size(),CurrentRow.data());
498 Levels[i] = std::vector<int> (LenU+1);
499 for (
size_t jj=0; jj<LenU+1; jj++) {
500 Levels[i][jj] = LevelsRowU[jj];
504 catch (std::runtime_error &e) {
506 auto numEntPerRow_d = numEntPerRow.getDeviceView(Tpetra::Access::OverwriteAll);
507 Kokkos::parallel_for(
"CountOverlapGraphRowEntries",
508 Kokkos::RangePolicy<execution_space>(0, NumMyRows),
509 KOKKOS_LAMBDA(
const int i)
511 const auto numRowEnt = numEntPerRow_d(i);
512 numEntPerRow_d(i) = ceil(static_cast<double>((numRowEnt != 0 ? numRowEnt : 1)) * overalloc);
515 const int localInsertError = insertError ? 1 : 0;
516 int globalInsertError = 0;
517 reduceAll (* (OverlapGraph_->getRowMap ()->getComm ()), REDUCE_SUM, 1,
518 &localInsertError, &globalInsertError);
519 insertError = globalInsertError > 0;
521 }
while (insertError);
524 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
525 RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
526 RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
527 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
528 L_Graph_->fillComplete (L_DomainMap, L_RangeMap);
529 U_Graph_->fillComplete (U_DomainMap, U_RangeMap);
531 reduceAll<int, size_t> (* (L_DomainMap->getComm ()), REDUCE_SUM, 1,
532 &NumMyDiagonals_, &NumGlobalDiagonals_);
536 template<
class GraphType,
class KKHandleType>
544 using Teuchos::reduceAll;
546 typedef typename crs_graph_type::local_graph_device_type local_graph_device_type;
547 typedef typename local_graph_device_type::size_type size_type;
548 typedef typename local_graph_device_type::data_type data_type;
549 typedef typename local_graph_device_type::array_layout array_layout;
550 typedef typename local_graph_device_type::device_type device_type;
552 typedef typename Kokkos::View<size_type*, array_layout, device_type> lno_row_view_t;
553 typedef typename Kokkos::View<data_type*, array_layout, device_type> lno_nonzero_view_t;
555 constructOverlapGraph();
559 const int NumMyRows = OverlapGraph_->getRowMap()->getLocalNumElements();
560 auto localOverlapGraph = OverlapGraph_->getLocalGraphDevice();
562 if (KernelHandle->get_spiluk_handle()->get_nrows() <
static_cast<size_type
>(NumMyRows)) {
563 KernelHandle->get_spiluk_handle()->reset_handle(NumMyRows,
564 KernelHandle->get_spiluk_handle()->get_nnzL(),
565 KernelHandle->get_spiluk_handle()->get_nnzU());
568 lno_row_view_t L_row_map(
"L_row_map", NumMyRows + 1);
569 lno_nonzero_view_t L_entries(
"L_entries", KernelHandle->get_spiluk_handle()->get_nnzL());
570 lno_row_view_t U_row_map(
"U_row_map", NumMyRows + 1);
571 lno_nonzero_view_t U_entries(
"U_entries", KernelHandle->get_spiluk_handle()->get_nnzU());
575 symbolicError =
false;
577 KokkosSparse::Experimental::spiluk_symbolic( KernelHandle.
getRawPtr(), LevelFill_,
578 localOverlapGraph.row_map, localOverlapGraph.entries,
579 L_row_map, L_entries, U_row_map, U_entries );
581 catch (std::runtime_error &e) {
582 symbolicError =
true;
583 data_type nnzL =
static_cast<data_type
>(Overalloc_)*L_entries.extent(0);
584 data_type nnzU =
static_cast<data_type
>(Overalloc_)*U_entries.extent(0);
585 KernelHandle->get_spiluk_handle()->reset_handle(NumMyRows, nnzL, nnzU);
586 Kokkos::resize(L_entries, KernelHandle->get_spiluk_handle()->get_nnzL());
587 Kokkos::resize(U_entries, KernelHandle->get_spiluk_handle()->get_nnzU());
589 const int localSymbolicError = symbolicError ? 1 : 0;
590 int globalSymbolicError = 0;
591 reduceAll (* (OverlapGraph_->getRowMap ()->getComm ()), REDUCE_SUM, 1,
592 &localSymbolicError, &globalSymbolicError);
593 symbolicError = globalSymbolicError > 0;
594 }
while (symbolicError);
596 Kokkos::resize(L_entries, KernelHandle->get_spiluk_handle()->get_nnzL());
597 Kokkos::resize(U_entries, KernelHandle->get_spiluk_handle()->get_nnzU());
599 RCP<Teuchos::ParameterList> params = Teuchos::parameterList ();
600 params->set (
"Optimize Storage",
false);
602 L_Graph_ =
rcp (
new crs_graph_type (OverlapGraph_->getRowMap (),
603 OverlapGraph_->getRowMap (),
604 L_row_map, L_entries));
605 U_Graph_ =
rcp (
new crs_graph_type (OverlapGraph_->getRowMap (),
606 OverlapGraph_->getRowMap (),
607 U_row_map, U_entries));
609 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
610 RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
611 RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
612 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
613 L_Graph_->fillComplete (L_DomainMap, L_RangeMap, params);
614 U_Graph_->fillComplete (U_DomainMap, U_RangeMap, params);
IlukGraph(const Teuchos::RCP< const GraphType > &G, const int levelFill, const int levelOverlap, const double overalloc=2.)
Constructor.
Definition: Ifpack2_IlukGraph.hpp:198
Teuchos::RCP< const GraphType > getA_Graph() const
Returns the original graph given.
Definition: Ifpack2_IlukGraph.hpp:136
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void getParameter(const Teuchos::ParameterList ¶ms, const std::string &name, T &value)
Set a value from a ParameterList if a parameter with the specified name exists.
Definition: Ifpack2_Parameters.hpp:26
size_t getNumGlobalDiagonals() const
Returns the global number of diagonals in the ILU(k) graph.
Definition: Ifpack2_IlukGraph.hpp:156
virtual ~IlukGraph()
IlukGraph Destructor.
Definition: Ifpack2_IlukGraph.hpp:215
Tpetra::CrsGraph< local_ordinal_type, global_ordinal_type, node_type > crs_graph_type
Tpetra::CrsGraph specialization used by this class.
Definition: Ifpack2_IlukGraph.hpp:80
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< const crs_graph_type > getOverlapGraph() const
Returns the the overlapped graph.
Definition: Ifpack2_IlukGraph.hpp:151
Construct a level filled graph for use in computing an ILU(k) incomplete factorization.
Definition: Ifpack2_IlukGraph.hpp:67
Teuchos::RCP< crs_graph_type > getU_Graph() const
Returns the graph of upper triangle of the ILU(k) graph as a Tpetra::CrsGraph.
Definition: Ifpack2_IlukGraph.hpp:146
Teuchos::RCP< crs_graph_type > getL_Graph() const
Returns the graph of lower triangle of the ILU(k) graph as a Tpetra::CrsGraph.
Definition: Ifpack2_IlukGraph.hpp:141
void initialize()
Set up the graph structure of the L and U factors.
Definition: Ifpack2_IlukGraph.hpp:240
int getLevelFill() const
The level of fill used to construct this graph.
Definition: Ifpack2_IlukGraph.hpp:130
ArrayView< T > view(size_type offset, size_type size) const
int getLevelOverlap() const
The level of overlap used to construct this graph.
Definition: Ifpack2_IlukGraph.hpp:133
Tpetra::RowGraph< local_ordinal_type, global_ordinal_type, node_type > row_graph_type
Tpetra::RowGraph specialization used by this class.
Definition: Ifpack2_IlukGraph.hpp:76
void setParameters(const Teuchos::ParameterList ¶meterlist)
Set parameters.
Definition: Ifpack2_IlukGraph.hpp:221