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