Ifpack2 Templated Preconditioning Package Version 1.0
Loading...
Searching...
No Matches
Ifpack2_OverlappingPartitioner_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_OVERLAPPINGPARTITIONER_DEF_HPP
11#define IFPACK2_OVERLAPPINGPARTITIONER_DEF_HPP
12#include <vector>
13#include <string>
14#include <algorithm>
15#include "Ifpack2_ConfigDefs.hpp"
16#include "Ifpack2_OverlappingPartitioner_decl.hpp"
17#include "Teuchos_Array.hpp"
18#include "Teuchos_ArrayRCP.hpp"
19#include "Tpetra_Util.hpp"
20
21namespace Ifpack2 {
22
23template <class GraphType>
25 OverlappingPartitioner(const Teuchos::RCP<const row_graph_type>& graph)
26 : NumLocalParts_(1)
27 , Graph_(graph)
28 , OverlappingLevel_(0)
29 , IsComputed_(false)
30 , verbose_(false)
31 , maintainSparsity_(false) {}
32
33template <class GraphType>
35
36template <class GraphType>
38 return NumLocalParts_;
39}
40
41template <class GraphType>
43 return OverlappingLevel_;
44}
45
46template <class GraphType>
47typename GraphType::local_ordinal_type
49operator()(const local_ordinal_type MyRow) const {
50 TEUCHOS_TEST_FOR_EXCEPTION(
51 MyRow < 0 || Teuchos::as<size_t>(MyRow) > Graph_->getLocalNumRows(),
52 std::runtime_error,
53 "Ifpack2::OverlappingPartitioner::operator(): "
54 "Invalid local row index "
55 << MyRow << ".");
56
57 return Partition_[MyRow];
58}
59
60//==============================================================================
61template <class GraphType>
62typename GraphType::local_ordinal_type
64operator()(const local_ordinal_type i, const local_ordinal_type j) const {
65 TEUCHOS_TEST_FOR_EXCEPTION(
66 i < 0 || i > Teuchos::as<local_ordinal_type>(NumLocalParts_),
67 std::runtime_error,
68 "Ifpack2::OverlappingPartitioner::operator(): "
69 "Invalid local row index i="
70 << i << ".");
71 TEUCHOS_TEST_FOR_EXCEPTION(
72 j < 0 || j > Teuchos::as<local_ordinal_type>(Parts_[i].size()),
73 std::runtime_error,
74 "Ifpack2::OverlappingPartitioner::operator(): "
75 "Invalid node index j="
76 << j << ".");
77 return Parts_[i][j];
78}
79
80//==============================================================================
81template <class GraphType>
82size_t
84 numRowsInPart(const local_ordinal_type Part) const {
85 TEUCHOS_TEST_FOR_EXCEPTION(
86 Part < 0 || Part > Teuchos::as<local_ordinal_type>(NumLocalParts_),
87 std::runtime_error,
88 "Ifpack2::OverlappingPartitioner::numRowsInPart: "
89 "Invalid partition index Part="
90 << Part << ".");
91 return Parts_[Part].size();
92}
93
94//==============================================================================
95template <class GraphType>
97 rowsInPart(const local_ordinal_type Part,
98 Teuchos::ArrayRCP<local_ordinal_type>& List) const {
99 // Let numRowsInPart do the sanity checking...
100 const size_t numRows = numRowsInPart(Part);
101 for (size_t i = 0; i < numRows; ++i) {
102 List[i] = Parts_[Part][i];
103 }
104}
105
106//==============================================================================
107template <class GraphType>
108Teuchos::ArrayView<const typename GraphType::local_ordinal_type>
110 return Partition_.view(0, Graph_->getLocalNumRows());
111}
112
113//==============================================================================
114template <class GraphType>
116 setParameters(Teuchos::ParameterList& List) {
117 NumLocalParts_ = List.get("partitioner: local parts", NumLocalParts_);
118 OverlappingLevel_ = List.get("partitioner: overlap", OverlappingLevel_);
119 verbose_ = List.get("partitioner: print level", verbose_);
120 maintainSparsity_ = List.get("partitioner: maintain sparsity", false);
121 typedef Teuchos::RCP<Tpetra::Map<typename GraphType::local_ordinal_type, typename GraphType::global_ordinal_type, typename GraphType::node_type> const> map_type;
122 typedef Teuchos::RCP<Tpetra::Import<typename GraphType::local_ordinal_type, typename GraphType::global_ordinal_type, typename GraphType::node_type> const> import_type;
123
124 // when using overlapping schwarz wth combineMode ADD, we need import and
125 // overlap row map to adjust weights for ith dof. Specifically, we sum
126 // all blocks (including off processor ones) that contain i.
127 import_type theImport = Graph_->getImporter();
128 if (theImport != Teuchos::null) List.set<import_type>("theImport", theImport);
129 List.set<map_type>("OverlapRowMap", Graph_->getRowMap());
130
131 if (NumLocalParts_ < 0) {
132 NumLocalParts_ = Graph_->getLocalNumRows() / (-NumLocalParts_);
133 }
134 if (NumLocalParts_ == 0) {
135 NumLocalParts_ = 1;
136 }
137
138 // Sanity checking
139 TEUCHOS_TEST_FOR_EXCEPTION(
140 NumLocalParts_ < 0 ||
141 Teuchos::as<size_t>(NumLocalParts_) > Graph_->getLocalNumRows(),
142 std::runtime_error,
143 "Ifpack2::OverlappingPartitioner::setParameters: "
144 "Invalid NumLocalParts_ = "
145 << NumLocalParts_ << ".");
146 TEUCHOS_TEST_FOR_EXCEPTION(
147 OverlappingLevel_ < 0, std::runtime_error,
148 "Ifpack2::OverlappingPartitioner::setParameters: "
149 "Invalid OverlappingLevel_ = "
150 << OverlappingLevel_ << ".");
151
152 setPartitionParameters(List);
153}
154
155//==============================================================================
156template <class GraphType>
158 using std::cout;
159 using std::endl;
160
161 TEUCHOS_TEST_FOR_EXCEPTION(
162 NumLocalParts_ < 1 || OverlappingLevel_ < 0,
163 std::runtime_error,
164 "Ifpack2::OverlappingPartitioner::compute: "
165 "Invalid NumLocalParts_ or OverlappingLevel_.");
166
167 // std::string's constructor has some overhead, so it's better to
168 // use const char[] for local constant strings.
169 const char printMsg[] = "OverlappingPartitioner: ";
170
171 if (verbose_ && (Graph_->getComm()->getRank() == 0)) {
172 cout << printMsg << "Number of local parts = "
173 << NumLocalParts_ << endl;
174 cout << printMsg << "Approx. Number of global parts = "
175 << NumLocalParts_ * Graph_->getComm()->getSize() << endl;
176 cout << printMsg << "Amount of overlap = "
177 << OverlappingLevel_ << endl;
178 }
179
180 // 1.- allocate memory
181 Partition_.resize(Graph_->getLocalNumRows());
182 // Parts_ is allocated in computeOverlappingPartitions_, where it is used
183
184 // 2.- sanity checks on input graph
185 TEUCHOS_TEST_FOR_EXCEPTION(
186 !Graph_->isFillComplete(), std::runtime_error,
187 "Ifpack2::OverlappingPartitioner::compute: "
188 "The input graph must be fill complete.");
189
190 TEUCHOS_TEST_FOR_EXCEPTION(
191 Graph_->getGlobalNumRows() != Graph_->getGlobalNumCols(),
192 std::runtime_error,
193 "Ifpack2::OverlappingPartitioner::compute: "
194 "The input graph must be (globally) square.");
195
196 // 3.- perform non-overlapping partition
197 computePartitions();
198
199 // 4.- compute the partitions with overlapping
200 computeOverlappingPartitions();
201
202 // 5.- mark as computed
203 IsComputed_ = true;
204}
205
206//==============================================================================
207template <class GraphType>
209 // If user has explicitly specified parts, then Partition_ size has been set to 0.
210 // In this case, there is no need to compute Parts_.
211 if (Partition_.size() == 0)
212 return;
213
214 const local_ordinal_type invalid =
215 Teuchos::OrdinalTraits<local_ordinal_type>::invalid();
216
217 // Old FIXME from Ifpack: the first part of this function should be elsewhere
218
219 // start defining the subgraphs for no overlap
220
221 std::vector<size_t> sizes;
222 sizes.resize(NumLocalParts_);
223
224 // 1.- compute how many rows are in each subgraph
225 for (int i = 0; i < NumLocalParts_; ++i) {
226 sizes[i] = 0;
227 }
228
229 for (size_t i = 0; i < Graph_->getLocalNumRows(); ++i) {
230 TEUCHOS_TEST_FOR_EXCEPTION(
231 Partition_[i] >= NumLocalParts_, std::runtime_error,
232 "Ifpack2::OverlappingPartitioner::computeOverlappingPartitions: "
233 "Partition_[i] > NumLocalParts_.");
234 // invalid indicates that this unknown is not in a nonoverlapping
235 // partition
236 if (Partition_[i] != invalid) {
237 sizes[Partition_[i]]++;
238 }
239 }
240
241 // 2.- allocate space for each subgraph
242 Parts_.resize(NumLocalParts_);
243 for (int i = 0; i < NumLocalParts_; ++i) {
244 Parts_[i].resize(sizes[i]);
245 }
246
247 // 3.- cycle over all rows and populate the vectors
248 for (int i = 0; i < NumLocalParts_; ++i) {
249 sizes[i] = 0;
250 }
251
252 for (size_t i = 0; i < Graph_->getLocalNumRows(); ++i) {
253 const local_ordinal_type part = Partition_[i];
254 if (part != invalid) {
255 const size_t count = sizes[part];
256 Parts_[part][count] = i;
257 sizes[part]++;
258 }
259 }
260
261 // If there is no overlap, we're done, so return
262 if (OverlappingLevel_ == 0) {
263 return;
264 }
265
266 // wider overlap requires further computations
267 for (int level = 1; level <= OverlappingLevel_; ++level) {
268 std::vector<std::vector<size_t> > tmp;
269 tmp.resize(NumLocalParts_);
270
271 // cycle over all rows in the local graph (that is the overlapping
272 // graph). For each row, all columns will belong to the subgraph
273 // of row `i'.
274
275 int MaxNumEntries_tmp = Graph_->getLocalMaxNumRowEntries();
276 nonconst_local_inds_host_view_type Indices("Indices", MaxNumEntries_tmp);
277 nonconst_local_inds_host_view_type newIndices("newIndices", MaxNumEntries_tmp);
278
279 if (!maintainSparsity_) {
280 local_ordinal_type numLocalRows = Graph_->getLocalNumRows();
281 for (int part = 0; part < NumLocalParts_; ++part) {
282 for (size_t i = 0; i < Teuchos::as<size_t>(Parts_[part].size()); ++i) {
283 const local_ordinal_type LRID = Parts_[part][i];
284
285 size_t numIndices;
286 Graph_->getLocalRowCopy(LRID, Indices, numIndices);
287
288 for (size_t j = 0; j < numIndices; ++j) {
289 // use *local* indices only
290 const local_ordinal_type col = Indices[j];
291 if (col >= numLocalRows) {
292 continue;
293 }
294
295 // has this column already been inserted?
296 std::vector<size_t>::iterator where =
297 std::find(tmp[part].begin(), tmp[part].end(), Teuchos::as<size_t>(col));
298
299 if (where == tmp[part].end()) {
300 tmp[part].push_back(col);
301 }
302 }
303
304 // 10-Jan-2017 JHU : A possible optimization is to avoid the std::find's in the loop above,
305 // but instead sort and make unique afterwards. One would have to be careful to only sort/
306 // make unique the insertions associated with the current row LRID, as for each row, LRID
307 // may occur after all other col indices for row LRID (see comment about zero pivot below).
308
309 // has this column already been inserted?
310 std::vector<size_t>::iterator where =
311 std::find(tmp[part].begin(), tmp[part].end(), Teuchos::as<size_t>(LRID));
312
313 // This happens here b/c Vanka on Stokes with Stabilized elements will have
314 // a zero pivot entry if this gets pushed back first. So... Last.
315 if (where == tmp[part].end()) {
316 tmp[part].push_back(LRID);
317 }
318 }
319 } // for (int part = 0; ...
320
321 } else {
322 // maintainSparsity_ == true
323
324 for (int part = 0; part < NumLocalParts_; ++part) {
325 for (size_t i = 0; i < Teuchos::as<size_t>(Parts_[part].size()); ++i) {
326 const local_ordinal_type LRID = Parts_[part][i];
327
328 size_t numIndices;
329 Graph_->getLocalRowCopy(LRID, Indices, numIndices);
330 // JJH: the entries in Indices are already sorted. However, the Tpetra documentation states
331 // that we can't count on this always being true, hence we sort. Also note that there are
332 // unused entries at the end of Indices (it's sized to hold any row). This means we can't
333 // just use Indices.end() in sorting and in std::includes
334 Tpetra::sort(Indices, numIndices);
335
336 for (size_t j = 0; j < numIndices; ++j) {
337 // use *local* indices only
338 const local_ordinal_type col = Indices[j];
339 if (Teuchos::as<size_t>(col) >= Graph_->getLocalNumRows()) {
340 continue;
341 }
342
343 // has this column already been inserted?
344 std::vector<size_t>::iterator where =
345 std::find(tmp[part].begin(), tmp[part].end(), Teuchos::as<size_t>(col));
346
347 if (where == tmp[part].end()) {
348 // Check if row associated with "col" increases connectivity already defined by row LRID's stencil.
349 // If it does and maintainSparsity_ is true, do not add "col" to the current partition (block).
350 size_t numNewIndices;
351 Graph_->getLocalRowCopy(col, newIndices, numNewIndices);
352 Tpetra::sort(newIndices, numNewIndices);
353 auto Indices_rcp = Kokkos::Compat::persistingView<nonconst_local_inds_host_view_type>(Indices, 0, numIndices);
354 auto newIndices_rcp = Kokkos::Compat::persistingView<nonconst_local_inds_host_view_type>(newIndices, 0, numNewIndices);
355 bool isSubset = std::includes(Indices_rcp.begin(), Indices_rcp.begin() + numIndices,
356 newIndices_rcp.begin(), newIndices_rcp.begin() + numNewIndices);
357 if (isSubset) {
358 tmp[part].push_back(col);
359 }
360 }
361 }
362
363 // has this column already been inserted?
364 std::vector<size_t>::iterator where =
365 std::find(tmp[part].begin(), tmp[part].end(), Teuchos::as<size_t>(LRID));
366
367 // This happens here b/c Vanka on Stokes with Stabilized elements will have
368 // a zero pivot entry if this gets pushed back first. So... Last.
369 if (where == tmp[part].end()) {
370 tmp[part].push_back(LRID);
371 }
372 }
373 } // for (int part = 0;
374
375 } // if (maintainSparsity_) ... else
376
377 // now I convert the STL vectors into Teuchos Array RCP's
378 //
379 // FIXME (mfh 12 July 2013) You could have started with ArrayRCP
380 // in the first place (which implements push_back and iterators)
381 // and avoided the copy.
382 for (int i = 0; i < NumLocalParts_; ++i) {
383 Parts_[i].resize(tmp[i].size());
384 for (size_t j = 0; j < tmp[i].size(); ++j) {
385 Parts_[i][j] = tmp[i][j];
386 }
387 }
388 }
389}
390
391//==============================================================================
392template <class GraphType>
394 return IsComputed_;
395}
396
397//==============================================================================
398template <class GraphType>
399std::ostream&
401 Teuchos::FancyOStream fos(Teuchos::rcpFromRef(os));
402 fos.setOutputToRootOnly(0);
403 describe(fos);
404 return os;
405}
406
407//==============================================================================
408template <class GraphType>
410 std::ostringstream oss;
411 oss << Teuchos::Describable::description();
412 if (isComputed()) {
413 oss << "{status = computed";
414 } else {
415 oss << "{status = is not computed";
416 }
417 oss << "}";
418 return oss.str();
419}
420
421//==============================================================================
422template <class GraphType>
423void OverlappingPartitioner<GraphType>::describe(Teuchos::FancyOStream& os, const Teuchos::EVerbosityLevel verbLevel) const {
424 using std::endl;
425 if (verbLevel == Teuchos::VERB_NONE) {
426 return;
427 }
428
429 os << "================================================================================" << endl;
430 os << "Ifpack2::OverlappingPartitioner" << endl;
431 os << "Number of local rows = " << Graph_->getLocalNumRows() << endl;
432 os << "Number of global rows = " << Graph_->getGlobalNumRows() << endl;
433 os << "Number of local parts = " << NumLocalParts_ << endl;
434 os << "Overlapping level = " << OverlappingLevel_ << endl;
435 os << "Is computed = " << IsComputed_ << endl;
436 os << "================================================================================" << endl;
437}
438
439} // namespace Ifpack2
440
441#define IFPACK2_OVERLAPPINGPARTITIONER_INSTANT(LO, GO, N) \
442 template class Ifpack2::OverlappingPartitioner<Tpetra::CrsGraph<LO, GO, N> >; \
443 template class Ifpack2::OverlappingPartitioner<Tpetra::RowGraph<LO, GO, N> >;
444
445#endif // IFPACK2_OVERLAPPINGPARTITIONER_DEF_HPP
size_t numRowsInPart(const local_ordinal_type Part) const
the number of rows contained in the given partition.
Definition Ifpack2_OverlappingPartitioner_def.hpp:84
OverlappingPartitioner(const Teuchos::RCP< const row_graph_type > &graph)
Constructor.
Definition Ifpack2_OverlappingPartitioner_def.hpp:25
virtual std::ostream & print(std::ostream &os) const
Prints basic information on iostream. This function is used by operator<<.
Definition Ifpack2_OverlappingPartitioner_def.hpp:400
virtual void compute()
Computes the partitions. Returns 0 if successful.
Definition Ifpack2_OverlappingPartitioner_def.hpp:157
virtual void setParameters(Teuchos::ParameterList &List)
Set all the parameters for the partitioner.
Definition Ifpack2_OverlappingPartitioner_def.hpp:116
virtual bool isComputed() const
Returns true if partitions have been computed successfully.
Definition Ifpack2_OverlappingPartitioner_def.hpp:393
virtual void computeOverlappingPartitions()
Computes the partitions. Returns 0 if successful.
Definition Ifpack2_OverlappingPartitioner_def.hpp:208
int numLocalParts() const
Number of computed local partitions.
Definition Ifpack2_OverlappingPartitioner_def.hpp:37
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
Definition Ifpack2_OverlappingPartitioner_def.hpp:423
void rowsInPart(const local_ordinal_type Part, Teuchos::ArrayRCP< local_ordinal_type > &List) const
Fill List with the local indices of the rows in the (overlapping) partition Part.
Definition Ifpack2_OverlappingPartitioner_def.hpp:97
int overlappingLevel() const
The number of levels of overlap.
Definition Ifpack2_OverlappingPartitioner_def.hpp:42
virtual ~OverlappingPartitioner()
Destructor.
Definition Ifpack2_OverlappingPartitioner_def.hpp:34
virtual Teuchos::ArrayView< const local_ordinal_type > nonOverlappingPartition() const
A view of the local indices of the nonoverlapping partitions of each local row.
Definition Ifpack2_OverlappingPartitioner_def.hpp:109
std::string description() const
Return a simple one-line description of this object.
Definition Ifpack2_OverlappingPartitioner_def.hpp:409
local_ordinal_type operator()(const local_ordinal_type MyRow) const
Local index of the nonoverlapping partition of the given row.
Definition Ifpack2_OverlappingPartitioner_def.hpp:49
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:40