Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_LinePartitioner_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
4 //
5 // Copyright 2009 NTESS and the Ifpack2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef IFPACK2_LINE_PARTITIONER_DEF_HPP
11 #define IFPACK2_LINE_PARTITIONER_DEF_HPP
12 
13 #include "Tpetra_CrsGraph.hpp"
14 #include "Tpetra_Util.hpp"
15 
16 namespace Ifpack2 {
17 
18 template <class T>
19 inline typename Teuchos::ScalarTraits<T>::magnitudeType square(T x) {
21 }
22 
23 //==============================================================================
24 // Constructor
25 template <class GraphType, class Scalar>
28  : OverlappingPartitioner<GraphType>(graph)
29  , NumEqns_(1)
30  , threshold_(0.0) {}
31 
32 template <class GraphType, class Scalar>
34 
35 template <class GraphType, class Scalar>
38  threshold_ = List.get("partitioner: line detection threshold", threshold_);
39  TEUCHOS_TEST_FOR_EXCEPTION(threshold_ < 0.0 || threshold_ > 1.0,
40  std::runtime_error, "Ifpack2::LinePartitioner: threshold not valid");
41 
42  NumEqns_ = List.get("partitioner: PDE equations", NumEqns_);
43  TEUCHOS_TEST_FOR_EXCEPTION(NumEqns_ < 1, std::runtime_error, "Ifpack2::LinePartitioner: NumEqns not valid");
44 
45  coord_ = List.get("partitioner: coordinates", coord_);
46  TEUCHOS_TEST_FOR_EXCEPTION(coord_.is_null(), std::runtime_error, "Ifpack2::LinePartitioner: coordinates not defined");
47 }
48 
49 template <class GraphType, class Scalar>
51  const local_ordinal_type invalid = Teuchos::OrdinalTraits<local_ordinal_type>::invalid();
52 
53  // Sanity Checks
54  TEUCHOS_TEST_FOR_EXCEPTION(coord_.is_null(), std::runtime_error, "Ifpack2::LinePartitioner: coordinates not defined");
55  TEUCHOS_TEST_FOR_EXCEPTION((size_t)this->Partition_.size() != this->Graph_->getLocalNumRows(), std::runtime_error, "Ifpack2::LinePartitioner: partition size error");
56 
57  // Short circuit
58  if (this->Partition_.size() == 0) {
59  this->NumLocalParts_ = 0;
60  return;
61  }
62 
63  // Set partitions to invalid to initialize algorithm
64  for (size_t i = 0; i < this->Graph_->getLocalNumRows(); i++)
65  this->Partition_[i] = invalid;
66 
67  // Use the auto partitioner
68  this->NumLocalParts_ = this->Compute_Blocks_AutoLine(this->Partition_());
69 
70  // Resize Parts_
71  this->Parts_.resize(this->NumLocalParts_);
72 }
73 
74 // ============================================================================
75 template <class GraphType, class Scalar>
77  typedef local_ordinal_type LO;
78  typedef magnitude_type MT;
79  const LO invalid = Teuchos::OrdinalTraits<LO>::invalid();
80  const MT zero = Teuchos::ScalarTraits<MT>::zero();
81 
82  Teuchos::ArrayRCP<const MT> xvalsRCP, yvalsRCP, zvalsRCP;
83  Teuchos::ArrayView<const MT> xvals, yvals, zvals;
84  xvalsRCP = coord_->getData(0);
85  xvals = xvalsRCP();
86  if (coord_->getNumVectors() > 1) {
87  yvalsRCP = coord_->getData(1);
88  yvals = yvalsRCP();
89  }
90  if (coord_->getNumVectors() > 2) {
91  zvalsRCP = coord_->getData(2);
92  zvals = zvalsRCP();
93  }
94 
95  double tol = threshold_;
96  size_t N = this->Graph_->getLocalNumRows();
97  size_t allocated_space = this->Graph_->getLocalMaxNumRowEntries();
98 
99  nonconst_local_inds_host_view_type cols("cols", allocated_space);
100  Teuchos::Array<LO> indices(allocated_space);
101  Teuchos::Array<MT> dist(allocated_space);
102 
103  Teuchos::Array<LO> itemp(2 * allocated_space);
104  Teuchos::Array<MT> dtemp(allocated_space);
105 
106  LO num_lines = 0;
107 
108  for (LO i = 0; i < (LO)N; i += NumEqns_) {
109  size_t nz = 0;
110  // Short circuit if I've already been blocked
111  if (blockIndices[i] != invalid) continue;
112 
113  // Get neighbors and sort by distance
114  this->Graph_->getLocalRowCopy(i, cols, nz);
115  MT x0 = (!xvals.is_null()) ? xvals[i / NumEqns_] : zero;
116  MT y0 = (!yvals.is_null()) ? yvals[i / NumEqns_] : zero;
117  MT z0 = (!zvals.is_null()) ? zvals[i / NumEqns_] : zero;
118 
119  LO neighbor_len = 0;
120  for (size_t j = 0; j < nz; j += NumEqns_) {
121  MT mydist = zero;
122  LO nn = cols[j] / NumEqns_;
123  if (cols[j] >= (LO)N) continue; // Check for off-proc entries
124  if (!xvals.is_null()) mydist += square<MT>(x0 - xvals[nn]);
125  if (!yvals.is_null()) mydist += square<MT>(y0 - yvals[nn]);
126  if (!zvals.is_null()) mydist += square<MT>(z0 - zvals[nn]);
127  dist[neighbor_len] = Teuchos::ScalarTraits<MT>::squareroot(mydist);
128  indices[neighbor_len] = cols[j];
129  neighbor_len++;
130  }
131 
132  Teuchos::ArrayView<MT> dist_view = dist(0, neighbor_len);
133  Tpetra::sort2(dist_view.begin(), dist_view.end(), indices.begin());
134 
135  // Number myself
136  for (LO k = 0; k < NumEqns_; k++)
137  blockIndices[i + k] = num_lines;
138 
139  // Fire off a neighbor line search (nearest neighbor)
140  if (neighbor_len > 2 && dist[1] / dist[neighbor_len - 1] < tol) {
141  local_automatic_line_search(NumEqns_, blockIndices, i, indices[1], num_lines, tol, itemp, dtemp);
142  }
143  // Fire off a neighbor line search (second nearest neighbor)
144  if (neighbor_len > 3 && dist[2] / dist[neighbor_len - 1] < tol) {
145  local_automatic_line_search(NumEqns_, blockIndices, i, indices[2], num_lines, tol, itemp, dtemp);
146  }
147 
148  num_lines++;
149  }
150  return num_lines;
151 }
152 // ============================================================================
153 template <class GraphType, class Scalar>
154 void LinePartitioner<GraphType, Scalar>::local_automatic_line_search(int NumEqns, Teuchos::ArrayView<local_ordinal_type> blockIndices, local_ordinal_type last, local_ordinal_type next, local_ordinal_type LineID, double tol, Teuchos::Array<local_ordinal_type> itemp, Teuchos::Array<magnitude_type> dtemp) const {
155  typedef local_ordinal_type LO;
156  typedef magnitude_type MT;
157  const LO invalid = Teuchos::OrdinalTraits<LO>::invalid();
158  const MT zero = Teuchos::ScalarTraits<MT>::zero();
159 
160  Teuchos::ArrayRCP<const MT> xvalsRCP, yvalsRCP, zvalsRCP;
161  Teuchos::ArrayView<const MT> xvals, yvals, zvals;
162  xvalsRCP = coord_->getData(0);
163  xvals = xvalsRCP();
164  if (coord_->getNumVectors() > 1) {
165  yvalsRCP = coord_->getData(1);
166  yvals = yvalsRCP();
167  }
168  if (coord_->getNumVectors() > 2) {
169  zvalsRCP = coord_->getData(2);
170  zvals = zvalsRCP();
171  }
172 
173  size_t N = this->Graph_->getLocalNumRows();
174  size_t allocated_space = this->Graph_->getLocalMaxNumRowEntries();
175 
176  nonconst_local_inds_host_view_type cols(itemp.data(), allocated_space);
177  Teuchos::ArrayView<LO> indices = itemp.view(allocated_space, allocated_space);
178  Teuchos::ArrayView<MT> dist = dtemp();
179 
180  while (blockIndices[next] == invalid) {
181  // Get the next row
182  size_t nz = 0;
183  LO neighbors_in_line = 0;
184 
185  this->Graph_->getLocalRowCopy(next, cols, nz);
186  MT x0 = (!xvals.is_null()) ? xvals[next / NumEqns_] : zero;
187  MT y0 = (!yvals.is_null()) ? yvals[next / NumEqns_] : zero;
188  MT z0 = (!zvals.is_null()) ? zvals[next / NumEqns_] : zero;
189 
190  // Calculate neighbor distances & sort
191  LO neighbor_len = 0;
192  for (size_t i = 0; i < nz; i += NumEqns) {
193  MT mydist = zero;
194  if (cols[i] >= (LO)N) continue; // Check for off-proc entries
195  LO nn = cols[i] / NumEqns;
196  if (blockIndices[nn] == LineID) neighbors_in_line++;
197  if (!xvals.is_null()) mydist += square<MT>(x0 - xvals[nn]);
198  if (!yvals.is_null()) mydist += square<MT>(y0 - yvals[nn]);
199  if (!zvals.is_null()) mydist += square<MT>(z0 - zvals[nn]);
200  dist[neighbor_len] = Teuchos::ScalarTraits<MT>::squareroot(mydist);
201  indices[neighbor_len] = cols[i];
202  neighbor_len++;
203  }
204  // If more than one of my neighbors is already in this line. I
205  // can't be because I'd create a cycle
206  if (neighbors_in_line > 1) break;
207 
208  // Otherwise add me to the line
209  for (LO k = 0; k < NumEqns; k++)
210  blockIndices[next + k] = LineID;
211 
212  // Try to find the next guy in the line (only check the closest two that aren't element 0 (diagonal))
213  Teuchos::ArrayView<MT> dist_view = dist(0, neighbor_len);
214  Tpetra::sort2(dist_view.begin(), dist_view.end(), indices.begin());
215 
216  if (neighbor_len > 2 && indices[1] != last && blockIndices[indices[1]] == -1 && dist[1] / dist[neighbor_len - 1] < tol) {
217  last = next;
218  next = indices[1];
219  } else if (neighbor_len > 3 && indices[2] != last && blockIndices[indices[2]] == -1 && dist[2] / dist[neighbor_len - 1] < tol) {
220  last = next;
221  next = indices[2];
222  } else {
223  // I have no further neighbors in this line
224  break;
225  }
226  }
227 }
228 
229 } // namespace Ifpack2
230 
231 #define IFPACK2_LINEPARTITIONER_INSTANT(S, LO, GO, N) \
232  template class Ifpack2::LinePartitioner<Tpetra::CrsGraph<LO, GO, N>, S>; \
233  template class Ifpack2::LinePartitioner<Tpetra::RowGraph<LO, GO, N>, S>;
234 
235 #endif // IFPACK2_LINEPARTITIONER_DEF_HPP
bool is_null() const
iterator begin() const
LinePartitioner(const Teuchos::RCP< const row_graph_type > &graph)
Constructor.
Definition: Ifpack2_LinePartitioner_def.hpp:27
T & get(const std::string &name, T def_value)
ArrayView< T > view(size_type offset, size_type size)
static T squareroot(T x)
void computePartitions()
Compute the partitions.
Definition: Ifpack2_LinePartitioner_def.hpp:50
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual ~LinePartitioner()
Destructor.
Definition: Ifpack2_LinePartitioner_def.hpp:33
static magnitudeType magnitude(T a)
iterator end() const
Create overlapping partitions of a local graph.
Definition: Ifpack2_OverlappingPartitioner_decl.hpp:45
void setPartitionParameters(Teuchos::ParameterList &List)
Set the partitioner&#39;s parameters (none for linear partitioning).
Definition: Ifpack2_LinePartitioner_def.hpp:37
Ifpack2::LinePartitioner: A class to define partitions into a set of lines.
Definition: Ifpack2_LinePartitioner_decl.hpp:45