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