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  L_Graph_ = rcp (new crs_graph_type (OverlapGraph_->getRowMap (),
264  OverlapGraph_->getRowMap (), 0));
265  U_Graph_ = rcp (new crs_graph_type (OverlapGraph_->getRowMap (),
266  OverlapGraph_->getRowMap (), 0));
267 
268  // Get Maximum Row length
269  const int MaxNumIndices = OverlapGraph_->getNodeMaxNumRowEntries ();
270 
271  Array<local_ordinal_type> L (MaxNumIndices);
272  Array<local_ordinal_type> U (MaxNumIndices);
273 
274  // First we copy the user's graph into L and U, regardless of fill level
275 
276  // FIXME (mfh 23 Dec 2013) Use size_t or whatever
277  // getNodeNumElements() returns, instead of ptrdiff_t.
278  const int NumMyRows = OverlapGraph_->getRowMap ()->getNodeNumElements ();
279  NumMyDiagonals_ = 0;
280 
281  for (int i = 0; i< NumMyRows; ++i) {
282  ArrayView<const local_ordinal_type> my_indices;
283  OverlapGraph_->getLocalRowView (i, my_indices);
284 
285  // Split into L and U (we don't assume that indices are ordered).
286 
287  NumL = 0;
288  NumU = 0;
289  DiagFound = false;
290  NumIn = my_indices.size();
291 
292  for (size_t j = 0; j < NumIn; ++j) {
293  const local_ordinal_type k = my_indices[j];
294 
295  if (k<NumMyRows) { // Ignore column elements that are not in the square matrix
296 
297  if (k==i) {
298  DiagFound = true;
299  }
300  else if (k < i) {
301  L[NumL] = k;
302  NumL++;
303  }
304  else {
305  U[NumU] = k;
306  NumU++;
307  }
308  }
309  }
310 
311  // Check in things for this row of L and U
312 
313  if (DiagFound) {
314  ++NumMyDiagonals_;
315  }
316  if (NumL) {
317  ArrayView<const local_ordinal_type> L_view = L.view (0, NumL);
318  L_Graph_->insertLocalIndices (i, L_view);
319  }
320  if (NumU) {
321  ArrayView<const local_ordinal_type> U_view = U.view (0, NumU);
322  U_Graph_->insertLocalIndices (i, U_view);
323  }
324  }
325 
326  if (LevelFill_ > 0) {
327  // Complete Fill steps
328  RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
329  RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
330  RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
331  RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
332  RCP<Teuchos::ParameterList> params = Teuchos::parameterList ();
333  params->set ("Optimize Storage",false);
334  L_Graph_->fillComplete (L_DomainMap, L_RangeMap, params);
335  U_Graph_->fillComplete (U_DomainMap, U_RangeMap, params);
336  L_Graph_->resumeFill ();
337  U_Graph_->resumeFill ();
338 
339  // At this point L_Graph and U_Graph are filled with the pattern of input graph,
340  // sorted and have redundant indices (if any) removed. Indices are zero based.
341  // LevelFill is greater than zero, so continue...
342 
343  int MaxRC = NumMyRows;
344  std::vector<std::vector<int> > Levels(MaxRC);
345  std::vector<int> LinkList(MaxRC);
346  std::vector<int> CurrentLevel(MaxRC);
347  Array<local_ordinal_type> CurrentRow (MaxRC + 1);
348  std::vector<int> LevelsRowU(MaxRC);
349 
350  for (int i = 0; i < NumMyRows; ++i) {
351  int First, Next;
352 
353  // copy column indices of row into workspace and sort them
354 
355  size_t LenL = L_Graph_->getNumEntriesInLocalRow(i);
356  size_t LenU = U_Graph_->getNumEntriesInLocalRow(i);
357  size_t Len = LenL + LenU + 1;
358 
359  CurrentRow.resize(Len);
360 
361  L_Graph_->getLocalRowCopy(i, CurrentRow(), LenL); // Get L Indices
362  CurrentRow[LenL] = i; // Put in Diagonal
363  if (LenU > 0) {
364  ArrayView<local_ordinal_type> URowView = CurrentRow.view (LenL+1, LenU);
365  // Get U Indices
366  U_Graph_->getLocalRowCopy (i, URowView, LenU);
367  }
368 
369  // Construct linked list for current row
370 
371  for (size_t j=0; j<Len-1; j++) {
372  LinkList[CurrentRow[j]] = CurrentRow[j+1];
373  CurrentLevel[CurrentRow[j]] = 0;
374  }
375 
376  LinkList[CurrentRow[Len-1]] = NumMyRows;
377  CurrentLevel[CurrentRow[Len-1]] = 0;
378 
379  // Merge List with rows in U
380 
381  First = CurrentRow[0];
382  Next = First;
383  while (Next < i) {
384  int PrevInList = Next;
385  int NextInList = LinkList[Next];
386  int RowU = Next;
387  // Get Indices for this row of U
388  ArrayView<const local_ordinal_type> IndicesU;
389  U_Graph_->getLocalRowView (RowU, IndicesU);
390  // FIXME (mfh 23 Dec 2013) size() returns ptrdiff_t, not int.
391  int LengthRowU = IndicesU.size ();
392 
393  int ii;
394 
395  // Scan RowU
396 
397  for (ii = 0; ii < LengthRowU; /*nop*/) {
398  int CurInList = IndicesU[ii];
399  if (CurInList < NextInList) {
400  // new fill-in
401  int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
402  if (NewLevel <= LevelFill_) {
403  LinkList[PrevInList] = CurInList;
404  LinkList[CurInList] = NextInList;
405  PrevInList = CurInList;
406  CurrentLevel[CurInList] = NewLevel;
407  }
408  ii++;
409  }
410  else if (CurInList == NextInList) {
411  PrevInList = NextInList;
412  NextInList = LinkList[PrevInList];
413  int NewLevel = CurrentLevel[RowU] + Levels[RowU][ii+1] + 1;
414  CurrentLevel[CurInList] = std::min (CurrentLevel[CurInList], NewLevel);
415  ii++;
416  }
417  else { // (CurInList > NextInList)
418  PrevInList = NextInList;
419  NextInList = LinkList[PrevInList];
420  }
421  }
422  Next = LinkList[Next];
423  }
424 
425  // Put pattern into L and U
426 
427  CurrentRow.resize (0);
428 
429  Next = First;
430 
431  // Lower
432 
433  while (Next < i) {
434  CurrentRow.push_back (Next);
435  Next = LinkList[Next];
436  }
437 
438  // FIXME (mfh 23 Dec 2013) It's not clear to me that
439  // removeLocalIndices works like people expect it to work. In
440  // particular, it does not actually change the column Map.
441  L_Graph_->removeLocalIndices (i); // Delete current set of Indices
442  if (CurrentRow.size() > 0) {
443  L_Graph_->insertLocalIndices (i, CurrentRow ());
444  }
445 
446  // Diagonal
447 
449  Next != i, std::runtime_error,
450  "Ifpack2::IlukGraph::initialize: FATAL: U has zero diagonal")
451 
452  LevelsRowU[0] = CurrentLevel[Next];
453  Next = LinkList[Next];
454 
455  // Upper
456 
457  CurrentRow.resize (0);
458  LenU = 0;
459 
460  while (Next < NumMyRows) {
461  LevelsRowU[LenU+1] = CurrentLevel[Next];
462  CurrentRow.push_back (Next);
463  ++LenU;
464  Next = LinkList[Next];
465  }
466 
467  // FIXME (mfh 23 Dec 2013) It's not clear to me that
468  // removeLocalIndices works like people expect it to work. In
469  // particular, it does not actually change the column Map.
470 
471  U_Graph_->removeLocalIndices (i); // Delete current set of Indices
472  if (LenU > 0) {
473  U_Graph_->insertLocalIndices (i, CurrentRow ());
474  }
475 
476  // Allocate and fill Level info for this row
477  Levels[i] = std::vector<int> (LenU+1);
478  for (size_t jj=0; jj<LenU+1; jj++) {
479  Levels[i][jj] = LevelsRowU[jj];
480  }
481  }
482  }
483 
484  // Complete Fill steps
485  RCP<const map_type> L_DomainMap = OverlapGraph_->getRowMap ();
486  RCP<const map_type> L_RangeMap = Graph_->getRangeMap ();
487  RCP<const map_type> U_DomainMap = Graph_->getDomainMap ();
488  RCP<const map_type> U_RangeMap = OverlapGraph_->getRowMap ();
489  L_Graph_->fillComplete (L_DomainMap, L_RangeMap);//DoOptimizeStorage is default here...
490  U_Graph_->fillComplete (U_DomainMap, U_RangeMap);//DoOptimizeStorage is default here...
491 
492  reduceAll<int, size_t> (* (L_DomainMap->getComm ()), REDUCE_SUM, 1,
493  &NumMyDiagonals_, &NumGlobalDiagonals_);
494 }
495 
496 } // namespace Ifpack2
497 
498 #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