1 #include <petsc/private/partitionerimpl.h> /*I "petscpartitioner.h" I*/
2
3 /*@
4 PetscPartitionerSetType - Builds a particular `PetscPartitioner`
5
6 Collective
7
8 Input Parameters:
9 + part - The `PetscPartitioner` object
10 - name - The kind of partitioner
11
12 Options Database Key:
13 . -petscpartitioner_type <type> - Sets the `PetscPartitioner` type
14
15 Level: intermediate
16
17 Note:
18 .vb
19 PETSCPARTITIONERCHACO - The Chaco partitioner (--download-chaco)
20 PETSCPARTITIONERPARMETIS - The ParMetis partitioner (--download-parmetis)
21 PETSCPARTITIONERSHELL - A shell partitioner implemented by the user
22 PETSCPARTITIONERSIMPLE - A simple partitioner that divides cells into equal, contiguous chunks
23 PETSCPARTITIONERGATHER - Gathers all cells onto process 0
24 .ve
25
26 .seealso: `PetscPartitionerGetType()`, `PetscPartitionerCreate()`
27 @*/
PetscPartitionerSetType(PetscPartitioner part,PetscPartitionerType name)28 PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name)
29 {
30 PetscErrorCode (*r)(PetscPartitioner);
31 PetscBool match;
32
33 PetscFunctionBegin;
34 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
35 PetscCall(PetscObjectTypeCompare((PetscObject)part, name, &match));
36 if (match) PetscFunctionReturn(PETSC_SUCCESS);
37
38 PetscCall(PetscPartitionerRegisterAll());
39 PetscCall(PetscFunctionListFind(PetscPartitionerList, name, &r));
40 PetscCheck(r, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscPartitioner type: %s", name);
41
42 PetscTryTypeMethod(part, destroy);
43 part->noGraph = PETSC_FALSE;
44 PetscCall(PetscMemzero(part->ops, sizeof(*part->ops)));
45 PetscCall(PetscObjectChangeTypeName((PetscObject)part, name));
46 PetscCall((*r)(part));
47 PetscFunctionReturn(PETSC_SUCCESS);
48 }
49
50 /*@
51 PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object.
52
53 Not Collective
54
55 Input Parameter:
56 . part - The PetscPartitioner
57
58 Output Parameter:
59 . name - The PetscPartitioner type name
60
61 Level: intermediate
62
63 .seealso: `PetscPartitionerSetType()`, `PetscPartitionerCreate()`
64 @*/
PetscPartitionerGetType(PetscPartitioner part,PetscPartitionerType * name)65 PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name)
66 {
67 PetscFunctionBegin;
68 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
69 PetscAssertPointer(name, 2);
70 *name = ((PetscObject)part)->type_name;
71 PetscFunctionReturn(PETSC_SUCCESS);
72 }
73
74 /*@
75 PetscPartitionerViewFromOptions - View a `PetscPartitioner` object based on options in the options database
76
77 Collective
78
79 Input Parameters:
80 + A - the `PetscPartitioner` object
81 . obj - Optional `PetscObject` that provides the options prefix
82 - name - command line option
83
84 Level: intermediate
85
86 Note:
87 See `PetscObjectViewFromOptions()` for the various forms of viewers that may be used
88
89 .seealso: `PetscPartitionerView()`, `PetscObjectViewFromOptions()`
90 @*/
PetscPartitionerViewFromOptions(PetscPartitioner A,PetscObject obj,const char name[])91 PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner A, PetscObject obj, const char name[])
92 {
93 PetscFunctionBegin;
94 PetscValidHeaderSpecific(A, PETSCPARTITIONER_CLASSID, 1);
95 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
96 PetscFunctionReturn(PETSC_SUCCESS);
97 }
98
99 /*@
100 PetscPartitionerView - Views a `PetscPartitioner`
101
102 Collective
103
104 Input Parameters:
105 + part - the `PetscPartitioner` object to view
106 - v - the viewer
107
108 Level: developer
109
110 .seealso: `PetscPartitionerDestroy()`
111 @*/
PetscPartitionerView(PetscPartitioner part,PetscViewer v)112 PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v)
113 {
114 PetscMPIInt size;
115 PetscBool isascii;
116
117 PetscFunctionBegin;
118 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
119 if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)part), &v));
120 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
121 if (isascii && part->printHeader) {
122 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)part), &size));
123 PetscCall(PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : ""));
124 PetscCall(PetscViewerASCIIPrintf(v, " type: %s\n", ((PetscObject)part)->type_name));
125 PetscCall(PetscViewerASCIIPrintf(v, " edge cut: %" PetscInt_FMT "\n", part->edgeCut));
126 PetscCall(PetscViewerASCIIPrintf(v, " balance: %.2g\n", (double)part->balance));
127 PetscCall(PetscViewerASCIIPrintf(v, " use vertex weights: %d\n", part->usevwgt));
128 PetscCall(PetscViewerASCIIPrintf(v, " use edge weights: %d\n", part->useewgt));
129 }
130 PetscTryTypeMethod(part, view, v);
131 PetscFunctionReturn(PETSC_SUCCESS);
132 }
133
PetscPartitionerGetDefaultType(MPI_Comm comm,const char ** defaultType)134 static PetscErrorCode PetscPartitionerGetDefaultType(MPI_Comm comm, const char **defaultType)
135 {
136 PetscMPIInt size;
137
138 PetscFunctionBegin;
139 PetscCallMPI(MPI_Comm_size(comm, &size));
140 if (size == 1) {
141 *defaultType = PETSCPARTITIONERSIMPLE;
142 } else {
143 #if defined(PETSC_HAVE_PARMETIS)
144 *defaultType = PETSCPARTITIONERPARMETIS;
145 #elif defined(PETSC_HAVE_PTSCOTCH)
146 *defaultType = PETSCPARTITIONERPTSCOTCH;
147 #elif defined(PETSC_HAVE_CHACO)
148 *defaultType = PETSCPARTITIONERCHACO;
149 #else
150 *defaultType = PETSCPARTITIONERSIMPLE;
151 #endif
152 }
153 PetscFunctionReturn(PETSC_SUCCESS);
154 }
155
156 /*@
157 PetscPartitionerSetFromOptions - sets parameters in a `PetscPartitioner` from the options database
158
159 Collective
160
161 Input Parameter:
162 . part - the `PetscPartitioner` object to set options for
163
164 Options Database Keys:
165 + -petscpartitioner_type <type> - Sets the `PetscPartitioner` type; use -help for a list of available types
166 . -petscpartitioner_use_vertex_weights - Uses weights associated with the graph vertices
167 - -petscpartitioner_view_graph - View the graph each time PetscPartitionerPartition is called. Viewer can be customized, see `PetscOptionsCreateViewer()`
168
169 Level: developer
170
171 .seealso: `PetscPartitionerView()`, `PetscPartitionerSetType()`, `PetscPartitionerPartition()`
172 @*/
PetscPartitionerSetFromOptions(PetscPartitioner part)173 PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part)
174 {
175 const char *currentType = NULL;
176 char name[256];
177 PetscBool flg;
178
179 PetscFunctionBegin;
180 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
181 PetscObjectOptionsBegin((PetscObject)part);
182 PetscCall(PetscPartitionerGetType(part, ¤tType));
183 PetscCall(PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, currentType, name, sizeof(name), &flg));
184 if (flg) PetscCall(PetscPartitionerSetType(part, name));
185 PetscCall(PetscOptionsBool("-petscpartitioner_use_vertex_weights", "Use vertex weights", "", part->usevwgt, &part->usevwgt, NULL));
186 PetscCall(PetscOptionsBool("-petscpartitioner_use_edge_weights", "Use edge weights", "", part->useewgt, &part->useewgt, NULL));
187 PetscTryTypeMethod(part, setfromoptions, PetscOptionsObject);
188 PetscCall(PetscViewerDestroy(&part->viewer));
189 PetscCall(PetscViewerDestroy(&part->viewerGraph));
190 PetscCall(PetscOptionsCreateViewer(((PetscObject)part)->comm, ((PetscObject)part)->options, ((PetscObject)part)->prefix, "-petscpartitioner_view", &part->viewer, &part->viewerFmt, NULL));
191 PetscCall(PetscOptionsCreateViewer(((PetscObject)part)->comm, ((PetscObject)part)->options, ((PetscObject)part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, NULL, NULL));
192 /* process any options handlers added with PetscObjectAddOptionsHandler() */
193 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)part, PetscOptionsObject));
194 PetscOptionsEnd();
195 PetscFunctionReturn(PETSC_SUCCESS);
196 }
197
198 /*@
199 PetscPartitionerSetUp - Construct data structures for the `PetscPartitioner`
200
201 Collective
202
203 Input Parameter:
204 . part - the `PetscPartitioner` object to setup
205
206 Level: developer
207
208 .seealso: `PetscPartitionerView()`, `PetscPartitionerDestroy()`
209 @*/
PetscPartitionerSetUp(PetscPartitioner part)210 PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part)
211 {
212 PetscFunctionBegin;
213 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
214 PetscTryTypeMethod(part, setup);
215 PetscFunctionReturn(PETSC_SUCCESS);
216 }
217
218 /*@
219 PetscPartitionerReset - Resets data structures for the `PetscPartitioner`
220
221 Collective
222
223 Input Parameter:
224 . part - the `PetscPartitioner` object to reset
225
226 Level: developer
227
228 .seealso: `PetscPartitionerSetUp()`, `PetscPartitionerDestroy()`
229 @*/
PetscPartitionerReset(PetscPartitioner part)230 PetscErrorCode PetscPartitionerReset(PetscPartitioner part)
231 {
232 PetscFunctionBegin;
233 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
234 PetscTryTypeMethod(part, reset);
235 PetscFunctionReturn(PETSC_SUCCESS);
236 }
237
238 /*@
239 PetscPartitionerDestroy - Destroys a `PetscPartitioner` object
240
241 Collective
242
243 Input Parameter:
244 . part - the `PetscPartitioner` object to destroy
245
246 Level: developer
247
248 .seealso: `PetscPartitionerView()`
249 @*/
PetscPartitionerDestroy(PetscPartitioner * part)250 PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part)
251 {
252 PetscFunctionBegin;
253 if (!*part) PetscFunctionReturn(PETSC_SUCCESS);
254 PetscValidHeaderSpecific(*part, PETSCPARTITIONER_CLASSID, 1);
255
256 if (--((PetscObject)*part)->refct > 0) {
257 *part = NULL;
258 PetscFunctionReturn(PETSC_SUCCESS);
259 }
260 ((PetscObject)*part)->refct = 0;
261
262 PetscCall(PetscPartitionerReset(*part));
263
264 PetscCall(PetscViewerDestroy(&(*part)->viewer));
265 PetscCall(PetscViewerDestroy(&(*part)->viewerGraph));
266 PetscTryTypeMethod(*part, destroy);
267 PetscCall(PetscHeaderDestroy(part));
268 PetscFunctionReturn(PETSC_SUCCESS);
269 }
270
271 /*@
272 PetscPartitionerPartition - Partition a graph
273
274 Collective
275
276 Input Parameters:
277 + part - The `PetscPartitioner`
278 . nparts - Number of partitions
279 . numVertices - Number of vertices in the local part of the graph
280 . start - row pointers for the local part of the graph (CSR style)
281 . adjacency - adjacency list (CSR style)
282 . vertexSection - PetscSection describing the absolute weight of each local vertex (can be `NULL`)
283 . edgeSection - PetscSection describing the absolute weight of each local edge (can be `NULL`)
284 - targetSection - PetscSection describing the absolute weight of each partition (can be `NULL`)
285
286 Output Parameters:
287 + partSection - The `PetscSection` giving the division of points by partition
288 - partition - The list of points by partition
289
290 Options Database Keys:
291 + -petscpartitioner_view - View the partitioner information
292 - -petscpartitioner_view_graph - View the graph we are partitioning
293
294 Level: developer
295
296 Notes:
297 The chart of the vertexSection (if present) must contain [0,numVertices), with the number of dofs in the section specifying the absolute weight for each vertex.
298 The chart of the targetSection (if present) must contain [0,nparts), with the number of dofs in the section specifying the absolute weight for each partition. This information must be the same across processes, PETSc does not check it.
299
300 .seealso: `PetscPartitionerCreate()`, `PetscPartitionerSetType()`, `PetscSectionCreate()`, `PetscSectionSetChart()`, `PetscSectionSetDof()`
301 @*/
PetscPartitionerPartition(PetscPartitioner part,PetscInt nparts,PetscInt numVertices,PetscInt start[],PetscInt adjacency[],PetscSection vertexSection,PetscSection edgeSection,PetscSection targetSection,PetscSection partSection,IS * partition)302 PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertexSection, PetscSection edgeSection, PetscSection targetSection, PetscSection partSection, IS *partition)
303 {
304 PetscFunctionBegin;
305 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1);
306 PetscValidLogicalCollectiveInt(part, nparts, 2);
307 PetscCheck(nparts > 0, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_OUTOFRANGE, "Number of parts must be positive");
308 PetscCheck(numVertices >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices must be non-negative");
309 if (numVertices && !part->noGraph) {
310 PetscAssertPointer(start, 4);
311 PetscAssertPointer(start + numVertices, 4);
312 if (start[numVertices]) PetscAssertPointer(adjacency, 5);
313 }
314 if (vertexSection) {
315 PetscInt s, e;
316
317 PetscValidHeaderSpecific(vertexSection, PETSC_SECTION_CLASSID, 6);
318 PetscCall(PetscSectionGetChart(vertexSection, &s, &e));
319 PetscCheck(s <= 0 && e >= numVertices, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid vertexSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")", s, e);
320 }
321 if (edgeSection) {
322 PetscInt s, e;
323
324 PetscValidHeaderSpecific(edgeSection, PETSC_SECTION_CLASSID, 7);
325 PetscCall(PetscSectionGetChart(edgeSection, &s, &e));
326 PetscCheck(s <= 0 && e >= start[numVertices], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid edgeSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")", s, e);
327 }
328 if (targetSection) {
329 PetscInt s, e;
330
331 PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 8);
332 PetscCall(PetscSectionGetChart(targetSection, &s, &e));
333 PetscCheck(s <= 0 && e >= nparts, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid targetSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")", s, e);
334 }
335 PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 9);
336 PetscAssertPointer(partition, 10);
337
338 PetscCall(PetscSectionReset(partSection));
339 PetscCall(PetscSectionSetChart(partSection, 0, nparts));
340 if (nparts == 1) { /* quick */
341 PetscCall(PetscSectionSetDof(partSection, 0, numVertices));
342 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)part), numVertices, 0, 1, partition));
343 } else PetscUseTypeMethod(part, partition, nparts, numVertices, start, adjacency, vertexSection, edgeSection, targetSection, partSection, partition);
344 PetscCall(PetscSectionSetUp(partSection));
345 if (part->viewerGraph) {
346 PetscViewer viewer = part->viewerGraph;
347 PetscBool isascii;
348 PetscInt v, i;
349 PetscMPIInt rank;
350
351 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
352 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
353 if (isascii) {
354 PetscCall(PetscViewerASCIIPushSynchronized(viewer));
355 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %" PetscInt_FMT "\n", rank, numVertices));
356 for (v = 0; v < numVertices; ++v) {
357 const PetscInt s = start[v];
358 const PetscInt e = start[v + 1];
359
360 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank));
361 for (i = s; i < e; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT " ", adjacency[i]));
362 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%" PetscInt_FMT "-%" PetscInt_FMT ")\n", s, e));
363 }
364 PetscCall(PetscViewerFlush(viewer));
365 PetscCall(PetscViewerASCIIPopSynchronized(viewer));
366 }
367 }
368 if (part->viewer) {
369 PetscCall(PetscViewerPushFormat(part->viewer, part->viewerFmt));
370 PetscCall(PetscPartitionerView(part, part->viewer));
371 PetscCall(PetscViewerPopFormat(part->viewer));
372 }
373 PetscFunctionReturn(PETSC_SUCCESS);
374 }
375
376 /*@
377 PetscPartitionerCreate - Creates an empty `PetscPartitioner` object. The type can then be set with `PetscPartitionerSetType()`.
378
379 Collective
380
381 Input Parameter:
382 . comm - The communicator for the `PetscPartitioner` object
383
384 Output Parameter:
385 . part - The `PetscPartitioner` object
386
387 Level: beginner
388
389 .seealso: `PetscPartitionerSetType()`, `PetscPartitionerDestroy()`
390 @*/
PetscPartitionerCreate(MPI_Comm comm,PetscPartitioner * part)391 PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part)
392 {
393 PetscPartitioner p;
394 const char *partitionerType = NULL;
395
396 PetscFunctionBegin;
397 PetscAssertPointer(part, 2);
398 *part = NULL;
399 PetscCall(PetscPartitionerInitializePackage());
400
401 PetscCall(PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView));
402 PetscCall(PetscPartitionerGetDefaultType(comm, &partitionerType));
403 PetscCall(PetscPartitionerSetType(p, partitionerType));
404
405 p->usevwgt = PETSC_TRUE;
406 p->printHeader = PETSC_TRUE;
407
408 *part = p;
409 PetscFunctionReturn(PETSC_SUCCESS);
410 }
411