Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_IlukGraph.hpp
Go to the documentation of this file.
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41  */
42 
48 
49 #ifndef IFPACK2_ILUK_GRAPH_HPP
50 #define IFPACK2_ILUK_GRAPH_HPP
51 
52 #include <algorithm>
53 #include <vector>
54 
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>
62 
63 namespace Ifpack2 {
64 
96 template<class GraphType>
98 public:
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;
102 
104  typedef Tpetra::RowGraph<local_ordinal_type,
105  global_ordinal_type,
106  node_type> row_graph_type;
108  typedef Tpetra::CrsGraph<local_ordinal_type,
109  global_ordinal_type,
110  node_type> crs_graph_type;
111 
123  const int levelFill,
124  const int levelOverlap);
125 
127  virtual ~IlukGraph ();
128 
134  void setParameters (const Teuchos::ParameterList& parameterlist);
135 
147  void initialize ();
148 
150  int getLevelFill () const { return LevelFill_; }
151 
153  int getLevelOverlap () const { return LevelOverlap_; }
154 
157  return L_Graph_;
158  }
159 
162  return U_Graph_;
163  }
164 
167  return OverlapGraph_;
168  }
169 
171  size_t getNumGlobalDiagonals() const { return NumGlobalDiagonals_; }
172 
173 private:
174  typedef typename GraphType::map_type map_type;
175 
185 
194  IlukGraph& operator= (const IlukGraph<GraphType>&);
195 
197  void constructOverlapGraph();
198 
201  int LevelFill_;
202  int LevelOverlap_;
205  size_t NumMyDiagonals_;
206  size_t NumGlobalDiagonals_;
207 };
208 
209 
210 template<class GraphType>
213  const int levelFill,
214  const int levelOverlap)
215  : Graph_ (G),
216  LevelFill_ (levelFill),
217  LevelOverlap_ (levelOverlap),
218  NumMyDiagonals_ (0),
219  NumGlobalDiagonals_ (0)
220 {}
221 
222 
223 template<class GraphType>
225 {}
226 
227 
228 template<class GraphType>
230 setParameters (const Teuchos::ParameterList& parameterlist)
231 {
232  getParameter (parameterlist, "iluk level-of-fill", LevelFill_);
233  getParameter (parameterlist, "iluk level-of-overlap", LevelOverlap_);
234 }
235 
236 
237 template<class GraphType>
239  // FIXME (mfh 22 Dec 2013) This won't do if we want
240  // RILUK::initialize() to do the right thing (that is,
241  // unconditionally recompute the "symbolic factorization").
242  if (OverlapGraph_ == Teuchos::null) {
243  OverlapGraph_ = createOverlapGraph<GraphType> (Graph_, LevelOverlap_);
244  }
245 }
246 
247 
248 template<class GraphType>
250 {
251  using Teuchos::Array;
252  using Teuchos::ArrayView;
253  using Teuchos::RCP;
254  using Teuchos::rcp;
255  using Teuchos::REDUCE_SUM;
256  using Teuchos::reduceAll;
257 
258  size_t NumIn, NumL, NumU;
259  bool DiagFound;
260 
261  constructOverlapGraph();
262 
263  // Get Maximum Row length
264  const int MaxNumIndices = OverlapGraph_->getNodeMaxNumRowEntries ();
265 
266  // FIXME (mfh 23 Dec 2013) Use size_t or whatever
267  // getNodeNumElements() returns, instead of ptrdiff_t.
268  const int NumMyRows = OverlapGraph_->getRowMap ()->getNodeNumElements ();
269 
270  // Heuristic to get the maximum number of entries per row.
271  const int MaxNumEntriesPerRow = (LevelFill_ == 0)
272  ? MaxNumIndices
273  : MaxNumIndices + 5*LevelFill_;
274  L_Graph_ = rcp (new crs_graph_type (OverlapGraph_->getRowMap (),
275  OverlapGraph_->getRowMap (), MaxNumEntriesPerRow));
276  U_Graph_ = rcp (new crs_graph_type (OverlapGraph_->getRowMap (),
277  OverlapGraph_->getRowMap (), MaxNumEntriesPerRow));
278 
279  Array<local_ordinal_type> L (MaxNumIndices);
280  Array<local_ordinal_type> U (MaxNumIndices);
281 
282  // First we copy the user's graph into L and U, regardless of fill level
283 
284  NumMyDiagonals_ = 0;
285 
286  for (int i = 0; i< NumMyRows; ++i) {
287  ArrayView<const local_ordinal_type> my_indices;
288  OverlapGraph_->getLocalRowView (i, my_indices);
289 
290  // Split into L and U (we don't assume that indices are ordered).
291 
292  NumL = 0;
293  NumU = 0;
294  DiagFound = false;
295  NumIn = my_indices.size();
296 
297  for (size_t j = 0; j < NumIn; ++j) {
298  const local_ordinal_type k = my_indices[j];
299 
300  if (k<NumMyRows) { // Ignore column elements that are not in the square matrix
301 
302  if (k==i) {
303  DiagFound = true;
304  }
305  else if (k < i) {
306  L[NumL] = k;
307  NumL++;
308  }
309  else {
310  U[NumU] = k;
311  NumU++;
312  }
313  }
314  }
315 
316  // Check in things for this row of L and U
317 
318  if (DiagFound) {
319  ++NumMyDiagonals_;
320  }
321  if (NumL) {
322  ArrayView<const local_ordinal_type> L_view = L.view (0, NumL);
323  L_Graph_->insertLocalIndices (i, L_view);
324  }
325  if (NumU) {
326  ArrayView<const local_ordinal_type> U_view = U.view (0, NumU);
327  U_Graph_->insertLocalIndices (i, U_view);
328  }
329  }
330 
331  if (LevelFill_ > 0) {
332  // Complete Fill steps
333  RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
334  RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
335  RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
336  RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
337  RCP<Teuchos::ParameterList> params = Teuchos::parameterList ();
338  params->set ("Optimize Storage",false);
339  L_Graph_->fillComplete (L_DomainMap, L_RangeMap, params);
340  U_Graph_->fillComplete (U_DomainMap, U_RangeMap, params);
341  L_Graph_->resumeFill ();
342  U_Graph_->resumeFill ();
343 
344  // At this point L_Graph and U_Graph are filled with the pattern of input graph,
345  // sorted and have redundant indices (if any) removed. Indices are zero based.
346  // LevelFill is greater than zero, so continue...
347 
348  int MaxRC = NumMyRows;
349  std::vector<std::vector<int> > Levels(MaxRC);
350  std::vector<int> LinkList(MaxRC);
351  std::vector<int> CurrentLevel(MaxRC);
352  Array<local_ordinal_type> CurrentRow (MaxRC + 1);
353  std::vector<int> LevelsRowU(MaxRC);
354 
355  for (int i = 0; i < NumMyRows; ++i) {
356  int First, Next;
357 
358  // copy column indices of row into workspace and sort them
359 
360  size_t LenL = L_Graph_->getNumEntriesInLocalRow(i);
361  size_t LenU = U_Graph_->getNumEntriesInLocalRow(i);
362  size_t Len = LenL + LenU + 1;
363 
364  CurrentRow.resize(Len);
365 
366  L_Graph_->getLocalRowCopy(i, CurrentRow(), LenL); // Get L Indices
367  CurrentRow[LenL] = i; // Put in Diagonal
368  if (LenU > 0) {
369  ArrayView<local_ordinal_type> URowView = CurrentRow.view (LenL+1, LenU);
370  // Get U Indices
371  U_Graph_->getLocalRowCopy (i, URowView, LenU);
372  }
373 
374  // Construct linked list for current row
375 
376  for (size_t j=0; j<Len-1; j++) {
377  LinkList[CurrentRow[j]] = CurrentRow[j+1];
378  CurrentLevel[CurrentRow[j]] = 0;
379  }
380 
381  LinkList[CurrentRow[Len-1]] = NumMyRows;
382  CurrentLevel[CurrentRow[Len-1]] = 0;
383 
384  // Merge List with rows in U
385 
386  First = CurrentRow[0];
387  Next = First;
388  while (Next < i) {
389  int PrevInList = Next;
390  int NextInList = LinkList[Next];
391  int RowU = Next;
392  // Get Indices for this row of U
393  ArrayView<const local_ordinal_type> IndicesU;
394  U_Graph_->getLocalRowView (RowU, IndicesU);
395  // FIXME (mfh 23 Dec 2013) size() returns ptrdiff_t, not int.
396  int LengthRowU = IndicesU.size ();
397 
398  int ii;
399 
400  // Scan RowU
401 
402  for (ii = 0; ii < LengthRowU; /*nop*/) {
403  int CurInList = IndicesU[ii];
404  if (CurInList < NextInList) {
405  // new fill-in
406  int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
407  if (NewLevel <= LevelFill_) {
408  LinkList[PrevInList] = CurInList;
409  LinkList[CurInList] = NextInList;
410  PrevInList = CurInList;
411  CurrentLevel[CurInList] = NewLevel;
412  }
413  ii++;
414  }
415  else if (CurInList == NextInList) {
416  PrevInList = NextInList;
417  NextInList = LinkList[PrevInList];
418  int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
419  CurrentLevel[CurInList] = std::min (CurrentLevel[CurInList], NewLevel);
420  ii++;
421  }
422  else { // (CurInList > NextInList)
423  PrevInList = NextInList;
424  NextInList = LinkList[PrevInList];
425  }
426  }
427  Next = LinkList[Next];
428  }
429 
430  // Put pattern into L and U
431 
432  CurrentRow.resize (0);
433 
434  Next = First;
435 
436  // Lower
437 
438  while (Next < i) {
439  CurrentRow.push_back (Next);
440  Next = LinkList[Next];
441  }
442 
443  // FIXME (mfh 23 Dec 2013) It's not clear to me that
444  // removeLocalIndices works like people expect it to work. In
445  // particular, it does not actually change the column Map.
446  L_Graph_->removeLocalIndices (i); // Delete current set of Indices
447  if (CurrentRow.size() > 0) {
448  L_Graph_->insertLocalIndices (i, CurrentRow ());
449  }
450 
451  // Diagonal
452 
454  Next != i, std::runtime_error,
455  "Ifpack2::IlukGraph::initialize: FATAL: U has zero diagonal")
456 
457  LevelsRowU[0] = CurrentLevel[Next];
458  Next = LinkList[Next];
459 
460  // Upper
461 
462  CurrentRow.resize (0);
463  LenU = 0;
464 
465  while (Next < NumMyRows) {
466  LevelsRowU[LenU+1] = CurrentLevel[Next];
467  CurrentRow.push_back (Next);
468  ++LenU;
469  Next = LinkList[Next];
470  }
471 
472  // FIXME (mfh 23 Dec 2013) It's not clear to me that
473  // removeLocalIndices works like people expect it to work. In
474  // particular, it does not actually change the column Map.
475 
476  U_Graph_->removeLocalIndices (i); // Delete current set of Indices
477  if (LenU > 0) {
478  U_Graph_->insertLocalIndices (i, CurrentRow ());
479  }
480 
481  // Allocate and fill Level info for this row
482  Levels[i] = std::vector<int> (LenU+1);
483  for (size_t jj=0; jj<LenU+1; jj++) {
484  Levels[i][jj] = LevelsRowU[jj];
485  }
486  }
487  }
488 
489  // Complete Fill steps
490  RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
491  RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
492  RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
493  RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
494  L_Graph_->fillComplete (L_DomainMap, L_RangeMap);//DoOptimizeStorage is default here...
495  U_Graph_->fillComplete (U_DomainMap, U_RangeMap);//DoOptimizeStorage is default here...
496 
497  reduceAll<int, size_t> (* (L_DomainMap->getComm ()), REDUCE_SUM, 1,
498  &NumMyDiagonals_, &NumGlobalDiagonals_);
499 }
500 
501 } // namespace Ifpack2
502 
503 #endif /* IFPACK2_ILUK_GRAPH_HPP */
void initialize()
Set up the graph structure of the L and U factors.
Definition: Ifpack2_IlukGraph.hpp:249
void setParameters(const Teuchos::ParameterList &parameterlist)
Set parameters.
Definition: Ifpack2_IlukGraph.hpp:230
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 &params, 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:224
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:156
IlukGraph(const Teuchos::RCP< const GraphType > &G, const int levelFill, const int levelOverlap)
Constructor.
Definition: Ifpack2_IlukGraph.hpp:212
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
int getLevelFill() const
The level of fill used to construct this graph.
Definition: Ifpack2_IlukGraph.hpp:150
int getLevelOverlap() const
The level of overlap used to construct this graph.
Definition: Ifpack2_IlukGraph.hpp:153
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:171
Teuchos::RCP< const crs_graph_type > getOverlapGraph() const
Returns the the overlapped graph.
Definition: Ifpack2_IlukGraph.hpp:166
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:161