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