233 using Teuchos::Array;
234 using Teuchos::ArrayView;
237 using Teuchos::REDUCE_SUM;
238 using Teuchos::reduceAll;
240 size_t NumIn, NumL, NumU;
243 constructOverlapGraph();
246 const int MaxNumIndices = OverlapGraph_->getLocalMaxNumRowEntries();
250 const int NumMyRows = OverlapGraph_->getRowMap()->getLocalNumElements();
252 using device_type =
typename node_type::device_type;
253 using execution_space =
typename device_type::execution_space;
254 using dual_view_type = Kokkos::DualView<size_t*, device_type>;
255 dual_view_type numEntPerRow_dv(
"numEntPerRow", NumMyRows);
256 Tpetra::Details::WrappedDualView<dual_view_type> numEntPerRow(numEntPerRow_dv);
258 const auto overalloc = Overalloc_;
259 const auto levelfill = LevelFill_;
262 auto numEntPerRow_d = numEntPerRow.getDeviceView(Tpetra::Access::OverwriteAll);
263 auto localOverlapGraph = OverlapGraph_->getLocalGraphDevice();
264 Kokkos::parallel_for(
265 "CountOverlapGraphRowEntries",
266 Kokkos::RangePolicy<execution_space>(0, NumMyRows),
267 KOKKOS_LAMBDA(
const int i) {
269 int RowMaxNumIndices = localOverlapGraph.rowConst(i).length;
270 numEntPerRow_d(i) = (levelfill == 0) ? RowMaxNumIndices
271 : Kokkos::ceil(
static_cast<double>(RowMaxNumIndices) * Kokkos::pow(overalloc, levelfill));
278 Teuchos::ArrayView<const size_t> a_numEntPerRow(numEntPerRow.getHostView(Tpetra::Access::ReadOnly).data(), NumMyRows);
280 OverlapGraph_->getRowMap(),
283 OverlapGraph_->getRowMap(),
286 Array<local_ordinal_type> L(MaxNumIndices);
287 Array<local_ordinal_type> U(MaxNumIndices);
293 for (
int i = 0; i < NumMyRows; ++i) {
294 local_inds_host_view_type my_indices;
295 OverlapGraph_->getLocalRowView(i, my_indices);
302 NumIn = my_indices.size();
304 for (
size_t j = 0; j < NumIn; ++j) {
305 const local_ordinal_type k = my_indices[j];
327 L_Graph_->insertLocalIndices(i, NumL, L.data());
330 U_Graph_->insertLocalIndices(i, NumU, U.data());
334 if (LevelFill_ > 0) {
336 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap();
337 RCP<const map_type> L_RangeMap = Graph_->getRangeMap();
338 RCP<const map_type> U_DomainMap = Graph_->getDomainMap();
339 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap();
340 RCP<Teuchos::ParameterList> params = Teuchos::parameterList();
341 params->set(
"Optimize Storage",
false);
342 L_Graph_->fillComplete(L_DomainMap, L_RangeMap, params);
343 U_Graph_->fillComplete(U_DomainMap, U_RangeMap, params);
344 L_Graph_->resumeFill();
345 U_Graph_->resumeFill();
351 int MaxRC = NumMyRows;
352 std::vector<std::vector<int> > Levels(MaxRC);
353 std::vector<int> LinkList(MaxRC);
354 std::vector<int> CurrentLevel(MaxRC);
355 Array<local_ordinal_type> CurrentRow(MaxRC + 1);
356 std::vector<int> LevelsRowU(MaxRC);
359 for (
int i = 0; i < NumMyRows; ++i) {
364 size_t LenL = L_Graph_->getNumEntriesInLocalRow(i);
365 size_t LenU = U_Graph_->getNumEntriesInLocalRow(i);
366 size_t Len = LenL + LenU + 1;
367 CurrentRow.resize(Len);
368 nonconst_local_inds_host_view_type CurrentRow_view(CurrentRow.data(), CurrentRow.size());
369 L_Graph_->getLocalRowCopy(i, CurrentRow_view, LenL);
370 CurrentRow[LenL] = i;
372 ArrayView<local_ordinal_type> URowView = CurrentRow.view(LenL + 1, LenU);
373 nonconst_local_inds_host_view_type URowView_v(URowView.data(), URowView.size());
376 U_Graph_->getLocalRowCopy(i, URowView_v, LenU);
381 for (
size_t j = 0; j < Len - 1; j++) {
382 LinkList[CurrentRow[j]] = CurrentRow[j + 1];
383 CurrentLevel[CurrentRow[j]] = 0;
386 LinkList[CurrentRow[Len - 1]] = NumMyRows;
387 CurrentLevel[CurrentRow[Len - 1]] = 0;
391 First = CurrentRow[0];
394 int PrevInList = Next;
395 int NextInList = LinkList[Next];
398 local_inds_host_view_type IndicesU;
399 U_Graph_->getLocalRowView(RowU, IndicesU);
401 int LengthRowU = IndicesU.size();
407 for (ii = 0; ii < LengthRowU; ) {
408 int CurInList = IndicesU[ii];
409 if (CurInList < NextInList) {
411 int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii + 1] + 1;
412 if (NewLevel <= LevelFill_) {
413 LinkList[PrevInList] = CurInList;
414 LinkList[CurInList] = NextInList;
415 PrevInList = CurInList;
416 CurrentLevel[CurInList] = NewLevel;
419 }
else if (CurInList == NextInList) {
420 PrevInList = NextInList;
421 NextInList = LinkList[PrevInList];
422 int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii + 1] + 1;
423 CurrentLevel[CurInList] = std::min(CurrentLevel[CurInList],
427 PrevInList = NextInList;
428 NextInList = LinkList[PrevInList];
431 Next = LinkList[Next];
435 CurrentRow.resize(0);
441 CurrentRow.push_back(Next);
442 Next = LinkList[Next];
448 L_Graph_->removeLocalIndices(i);
449 if (CurrentRow.size() > 0) {
450 L_Graph_->insertLocalIndices(i, CurrentRow.size(), CurrentRow.data());
455 TEUCHOS_TEST_FOR_EXCEPTION(
456 Next != i, std::runtime_error,
457 "Ifpack2::IlukGraph::initialize: FATAL: U has zero diagonal")
459 LevelsRowU[0] = CurrentLevel[Next];
460 Next = LinkList[Next];
463 CurrentRow.resize(0);
466 while (Next < NumMyRows) {
467 LevelsRowU[LenU + 1] = CurrentLevel[Next];
468 CurrentRow.push_back(Next);
470 Next = LinkList[Next];
477 U_Graph_->removeLocalIndices(i);
479 U_Graph_->insertLocalIndices(i, CurrentRow.size(), CurrentRow.data());
483 Levels[i] = std::vector<int>(LenU + 1);
484 for (
size_t jj = 0; jj < LenU + 1; jj++) {
485 Levels[i][jj] = LevelsRowU[jj];
488 }
catch (std::runtime_error& e) {
490 auto numEntPerRow_d = numEntPerRow.getDeviceView(Tpetra::Access::OverwriteAll);
491 Kokkos::parallel_for(
492 "CountOverlapGraphRowEntries",
493 Kokkos::RangePolicy<execution_space>(0, NumMyRows),
494 KOKKOS_LAMBDA(
const int i) {
495 const auto numRowEnt = numEntPerRow_d(i);
496 numEntPerRow_d(i) = ceil(
static_cast<double>((numRowEnt != 0 ? numRowEnt : 1)) * overalloc);
499 const int localInsertError = insertError ? 1 : 0;
500 int globalInsertError = 0;
501 reduceAll(*(OverlapGraph_->getRowMap()->getComm()), REDUCE_SUM, 1,
502 &localInsertError, &globalInsertError);
503 insertError = globalInsertError > 0;
505 }
while (insertError);
508 RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap();
509 RCP<const map_type> L_RangeMap = Graph_->getRangeMap();
510 RCP<const map_type> U_DomainMap = Graph_->getDomainMap();
511 RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap();
512 L_Graph_->fillComplete(L_DomainMap, L_RangeMap);
513 U_Graph_->fillComplete(U_DomainMap, U_RangeMap);
515 reduceAll<int, size_t>(*(L_DomainMap->getComm()), REDUCE_SUM, 1,
516 &NumMyDiagonals_, &NumGlobalDiagonals_);