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