49 #ifndef IFPACK2_ILUK_GRAPH_HPP
50 #define IFPACK2_ILUK_GRAPH_HPP
55 #include <Ifpack2_ConfigDefs.hpp>
57 #include <Teuchos_CommHelpers.hpp>
58 #include <Tpetra_CrsGraph.hpp>
59 #include <Tpetra_Import.hpp>
60 #include <Ifpack2_CreateOverlapGraph.hpp>
61 #include <Ifpack2_Parameters.hpp>
96 template<
class GraphType>
99 typedef typename GraphType::local_ordinal_type local_ordinal_type;
100 typedef typename GraphType::global_ordinal_type global_ordinal_type;
101 typedef typename GraphType::node_type node_type;
104 typedef Tpetra::RowGraph<local_ordinal_type,
108 typedef Tpetra::CrsGraph<local_ordinal_type,
125 const int levelOverlap,
126 const double overalloc = 2.);
169 return OverlapGraph_;
176 typedef typename GraphType::map_type map_type;
199 void constructOverlapGraph();
205 const double Overalloc_;
208 size_t NumMyDiagonals_;
209 size_t NumGlobalDiagonals_;
213 template<
class GraphType>
217 const int levelOverlap,
218 const double overalloc)
220 LevelFill_ (levelFill),
221 LevelOverlap_ (levelOverlap),
222 Overalloc_ (overalloc),
224 NumGlobalDiagonals_ (0)
227 "Ifpack2::IlukGraph: FATAL: overalloc must be greater than 1.")
231 template<
class GraphType>
236 template<
class GraphType>
240 getParameter (parameterlist,
"iluk level-of-fill", LevelFill_);
241 getParameter (parameterlist,
"iluk level-of-overlap", LevelOverlap_);
245 template<
class GraphType>
250 if (OverlapGraph_ == Teuchos::null) {
251 OverlapGraph_ = createOverlapGraph<GraphType> (Graph_, LevelOverlap_);
256 template<
class GraphType>
264 using Teuchos::reduceAll;
266 size_t NumIn, NumL, NumU;
269 constructOverlapGraph();
272 const int MaxNumIndices = OverlapGraph_->getNodeMaxNumRowEntries ();
276 const int NumMyRows = OverlapGraph_->getRowMap ()->getNodeNumElements ();
279 using device_type =
typename node_type::device_type;
280 using execution_space =
typename device_type::execution_space;
281 Kokkos::DualView<size_t*, device_type> numEntPerRow(
"numEntPerRow", NumMyRows);
282 auto numEntPerRow_d = numEntPerRow.template view<device_type>();
283 auto localOverlapGraph = OverlapGraph_->getLocalGraph();
285 const auto overalloc = Overalloc_;
286 const auto levelfill = LevelFill_;
287 numEntPerRow.sync_device();
288 numEntPerRow.modify_device();
289 Kokkos::parallel_for(
"CountOverlapGraphRowEntries",
290 Kokkos::RangePolicy<execution_space>(0, NumMyRows),
291 KOKKOS_LAMBDA(
const int i)
294 int RowMaxNumIndices = localOverlapGraph.rowConst(i).length;
295 numEntPerRow_d(i) = (levelfill == 0) ? RowMaxNumIndices
296 : ceil(static_cast<double>(RowMaxNumIndices)
297 * pow(overalloc, levelfill));
304 OverlapGraph_->getRowMap (),
307 OverlapGraph_->getRowMap (),
310 Array<local_ordinal_type> L (MaxNumIndices);
311 Array<local_ordinal_type> U (MaxNumIndices);
317 for (
int i = 0; i< NumMyRows; ++i) {
318 ArrayView<const local_ordinal_type> my_indices;
319 OverlapGraph_->getLocalRowView (i, my_indices);
326 NumIn = my_indices.size();
328 for (
size_t j = 0; j < NumIn; ++j) {
329 const local_ordinal_type k = my_indices[j];
353 ArrayView<const local_ordinal_type> L_view = L.view (0, NumL);
354 L_Graph_->insertLocalIndices (i, L_view);
357 ArrayView<const local_ordinal_type> U_view = U.view (0, NumU);
358 U_Graph_->insertLocalIndices (i, U_view);
362 if (LevelFill_ > 0) {
364 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
365 RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
366 RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
367 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
368 RCP<Teuchos::ParameterList> params = Teuchos::parameterList ();
369 params->set (
"Optimize Storage",
false);
370 L_Graph_->fillComplete (L_DomainMap, L_RangeMap, params);
371 U_Graph_->fillComplete (U_DomainMap, U_RangeMap, params);
372 L_Graph_->resumeFill ();
373 U_Graph_->resumeFill ();
379 int MaxRC = NumMyRows;
380 std::vector<std::vector<int> > Levels(MaxRC);
381 std::vector<int> LinkList(MaxRC);
382 std::vector<int> CurrentLevel(MaxRC);
383 Array<local_ordinal_type> CurrentRow (MaxRC + 1);
384 std::vector<int> LevelsRowU(MaxRC);
387 for (
int i = 0; i < NumMyRows; ++i) {
392 size_t LenL = L_Graph_->getNumEntriesInLocalRow(i);
393 size_t LenU = U_Graph_->getNumEntriesInLocalRow(i);
394 size_t Len = LenL + LenU + 1;
396 CurrentRow.resize(Len);
398 L_Graph_->getLocalRowCopy(i, CurrentRow(), LenL);
399 CurrentRow[LenL] = i;
401 ArrayView<local_ordinal_type> URowView = CurrentRow.view (LenL+1,
404 U_Graph_->getLocalRowCopy (i, URowView, LenU);
409 for (
size_t j=0; j<Len-1; j++) {
410 LinkList[CurrentRow[j]] = CurrentRow[j+1];
411 CurrentLevel[CurrentRow[j]] = 0;
414 LinkList[CurrentRow[Len-1]] = NumMyRows;
415 CurrentLevel[CurrentRow[Len-1]] = 0;
419 First = CurrentRow[0];
422 int PrevInList = Next;
423 int NextInList = LinkList[Next];
426 ArrayView<const local_ordinal_type> IndicesU;
427 U_Graph_->getLocalRowView (RowU, IndicesU);
429 int LengthRowU = IndicesU.size ();
435 for (ii = 0; ii < LengthRowU; ) {
436 int CurInList = IndicesU[ii];
437 if (CurInList < NextInList) {
439 int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
440 if (NewLevel <= LevelFill_) {
441 LinkList[PrevInList] = CurInList;
442 LinkList[CurInList] = NextInList;
443 PrevInList = CurInList;
444 CurrentLevel[CurInList] = NewLevel;
448 else if (CurInList == NextInList) {
449 PrevInList = NextInList;
450 NextInList = LinkList[PrevInList];
451 int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
452 CurrentLevel[CurInList] = std::min (CurrentLevel[CurInList],
457 PrevInList = NextInList;
458 NextInList = LinkList[PrevInList];
461 Next = LinkList[Next];
466 CurrentRow.resize (0);
473 CurrentRow.push_back (Next);
474 Next = LinkList[Next];
480 L_Graph_->removeLocalIndices (i);
481 if (CurrentRow.size() > 0) {
482 L_Graph_->insertLocalIndices (i, CurrentRow ());
488 Next != i, std::runtime_error,
489 "Ifpack2::IlukGraph::initialize: FATAL: U has zero diagonal")
491 LevelsRowU[0] = CurrentLevel[Next];
492 Next = LinkList[Next];
496 CurrentRow.resize (0);
499 while (Next < NumMyRows) {
500 LevelsRowU[LenU+1] = CurrentLevel[Next];
501 CurrentRow.push_back (Next);
503 Next = LinkList[Next];
510 U_Graph_->removeLocalIndices (i);
512 U_Graph_->insertLocalIndices (i, CurrentRow ());
516 Levels[i] = std::vector<int> (LenU+1);
517 for (
size_t jj=0; jj<LenU+1; jj++) {
518 Levels[i][jj] = LevelsRowU[jj];
522 catch (std::runtime_error &e) {
524 numEntPerRow.sync_device();
525 numEntPerRow.modify_device();
526 Kokkos::parallel_for(
"CountOverlapGraphRowEntries",
527 Kokkos::RangePolicy<execution_space>(0, NumMyRows),
528 KOKKOS_LAMBDA(
const int i)
530 const auto numRowEnt = numEntPerRow_d(i);
531 numEntPerRow_d(i) = ceil(static_cast<double>((numRowEnt != 0 ? numRowEnt : 1)) * overalloc);
534 const int localInsertError = insertError ? 1 : 0;
535 int globalInsertError = 0;
536 reduceAll (* (OverlapGraph_->getRowMap ()->getComm ()), REDUCE_SUM, 1,
537 &localInsertError, &globalInsertError);
538 insertError = globalInsertError > 0;
540 }
while (insertError);
543 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
544 RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
545 RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
546 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
547 L_Graph_->fillComplete (L_DomainMap, L_RangeMap);
548 U_Graph_->fillComplete (U_DomainMap, U_RangeMap);
550 reduceAll<int, size_t> (* (L_DomainMap->getComm ()), REDUCE_SUM, 1,
551 &NumMyDiagonals_, &NumGlobalDiagonals_);
void initialize()
Set up the graph structure of the L and U factors.
Definition: Ifpack2_IlukGraph.hpp:257
void setParameters(const Teuchos::ParameterList ¶meterlist)
Set parameters.
Definition: Ifpack2_IlukGraph.hpp:238
Tpetra::CrsGraph< local_ordinal_type, global_ordinal_type, node_type > crs_graph_type
Tpetra::CrsGraph specialization used by this class.
Definition: Ifpack2_IlukGraph.hpp:110
#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:59
Tpetra::RowGraph< local_ordinal_type, global_ordinal_type, node_type > row_graph_type
Tpetra::RowGraph specialization used by this class.
Definition: Ifpack2_IlukGraph.hpp:106
virtual ~IlukGraph()
IlukGraph Destructor.
Definition: Ifpack2_IlukGraph.hpp:232
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
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:158
int getLevelFill() const
The level of fill used to construct this graph.
Definition: Ifpack2_IlukGraph.hpp:152
int getLevelOverlap() const
The level of overlap used to construct this graph.
Definition: Ifpack2_IlukGraph.hpp:155
Construct a level filled graph for use in computing an ILU(k) incomplete factorization.
Definition: Ifpack2_IlukGraph.hpp:97
size_t getNumGlobalDiagonals() const
Returns the global number of diagonals in the ILU(k) graph.
Definition: Ifpack2_IlukGraph.hpp:173
Teuchos::RCP< const crs_graph_type > getOverlapGraph() const
Returns the the overlapped graph.
Definition: Ifpack2_IlukGraph.hpp:168
IlukGraph(const Teuchos::RCP< const GraphType > &G, const int levelFill, const int levelOverlap, const double overalloc=2.)
Constructor.
Definition: Ifpack2_IlukGraph.hpp:215
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:163