Actual source code: partitioner.c

  1: #include <petsc/private/partitionerimpl.h>

  3: /*@C
  4:   PetscPartitionerSetType - Builds a particular PetscPartitioner

  6:   Collective on PetscPartitioner

  8:   Input Parameters:
  9: + part - The PetscPartitioner object
 10: - name - The kind of partitioner

 12:   Options Database Key:
 13: . -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types

 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

 22:   Level: intermediate

 24: .seealso: PetscPartitionerGetType(), PetscPartitionerCreate()
 25: @*/
 26: PetscErrorCode PetscPartitionerSetType(PetscPartitioner part, PetscPartitionerType name)
 27: {
 28:   PetscErrorCode (*r)(PetscPartitioner);
 29:   PetscBool      match;

 32:   PetscObjectTypeCompare((PetscObject) part, name, &match);
 33:   if (match) return 0;

 35:   PetscPartitionerRegisterAll();
 36:   PetscFunctionListFind(PetscPartitionerList, name, &r);

 39:   if (part->ops->destroy) {
 40:     (*part->ops->destroy)(part);
 41:   }
 42:   part->noGraph = PETSC_FALSE;
 43:   PetscMemzero(part->ops, sizeof(*part->ops));
 44:   PetscObjectChangeTypeName((PetscObject) part, name);
 45:   (*r)(part);
 46:   return 0;
 47: }

 49: /*@C
 50:   PetscPartitionerGetType - Gets the PetscPartitioner type name (as a string) from the object.

 52:   Not Collective

 54:   Input Parameter:
 55: . part - The PetscPartitioner

 57:   Output Parameter:
 58: . name - The PetscPartitioner type name

 60:   Level: intermediate

 62: .seealso: PetscPartitionerSetType(), PetscPartitionerCreate()
 63: @*/
 64: PetscErrorCode PetscPartitionerGetType(PetscPartitioner part, PetscPartitionerType *name)
 65: {
 68:   *name = ((PetscObject) part)->type_name;
 69:   return 0;
 70: }

 72: /*@C
 73:    PetscPartitionerViewFromOptions - View from Options

 75:    Collective on PetscPartitioner

 77:    Input Parameters:
 78: +  A - the PetscPartitioner object
 79: .  obj - Optional object
 80: -  name - command line option

 82:    Level: intermediate
 83: .seealso:  PetscPartitionerView(), PetscObjectViewFromOptions()
 84: @*/
 85: PetscErrorCode PetscPartitionerViewFromOptions(PetscPartitioner A,PetscObject obj,const char name[])
 86: {
 88:   PetscObjectViewFromOptions((PetscObject)A,obj,name);
 89:   return 0;
 90: }

 92: /*@
 93:   PetscPartitionerView - Views a PetscPartitioner

 95:   Collective on PetscPartitioner

 97:   Input Parameters:
 98: + part - the PetscPartitioner object to view
 99: - v    - the viewer

101:   Level: developer

103: .seealso: PetscPartitionerDestroy()
104: @*/
105: PetscErrorCode PetscPartitionerView(PetscPartitioner part, PetscViewer v)
106: {
107:   PetscMPIInt    size;
108:   PetscBool      isascii;

111:   if (!v) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) part), &v);
112:   PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii);
113:   if (isascii) {
114:     MPI_Comm_size(PetscObjectComm((PetscObject) part), &size);
115:     PetscViewerASCIIPrintf(v, "Graph Partitioner: %d MPI Process%s\n", size, size > 1 ? "es" : "");
116:     PetscViewerASCIIPrintf(v, "  type: %s\n", ((PetscObject)part)->type_name);
117:     PetscViewerASCIIPrintf(v, "  edge cut: %D\n", part->edgeCut);
118:     PetscViewerASCIIPrintf(v, "  balance: %.2g\n", part->balance);
119:     PetscViewerASCIIPrintf(v, "  use vertex weights: %d\n", part->usevwgt);
120:   }
121:   if (part->ops->view) (*part->ops->view)(part, v);
122:   return 0;
123: }

125: static PetscErrorCode PetscPartitionerGetDefaultType(MPI_Comm comm, const char **defaultType)
126: {
127:   PetscMPIInt    size;

129:   MPI_Comm_size(comm, &size);
130:   if (size == 1) {
131:     *defaultType = PETSCPARTITIONERSIMPLE;
132:   } else {
133: #if defined(PETSC_HAVE_PARMETIS)
134:     *defaultType = PETSCPARTITIONERPARMETIS;
135: #elif defined(PETSC_HAVE_PTSCOTCH)
136:     *defaultType = PETSCPARTITIONERPTSCOTCH;
137: #elif defined(PETSC_HAVE_CHACO)
138:     *defaultType = PETSCPARTITIONERCHACO;
139: #else
140:     *defaultType = PETSCPARTITIONERSIMPLE;
141: #endif
142:   }
143:   return 0;
144: }

146: /*@
147:   PetscPartitionerSetFromOptions - sets parameters in a PetscPartitioner from the options database

149:   Collective on PetscPartitioner

151:   Input Parameter:
152: . part - the PetscPartitioner object to set options for

154:   Options Database Keys:
155: +  -petscpartitioner_type <type> - Sets the PetscPartitioner type; use -help for a list of available types
156: .  -petscpartitioner_use_vertex_weights - Uses weights associated with the graph vertices
157: -  -petscpartitioner_view_graph - View the graph each time PetscPartitionerPartition is called. Viewer can be customized, see PetscOptionsGetViewer()

159:   Level: developer

161: .seealso: PetscPartitionerView(), PetscPartitionerSetType(), PetscPartitionerPartition()
162: @*/
163: PetscErrorCode PetscPartitionerSetFromOptions(PetscPartitioner part)
164: {
165:   const char    *currentType = NULL;
166:   char           name[256];
167:   PetscBool      flg;

171:   PetscObjectOptionsBegin((PetscObject) part);
172:   PetscPartitionerGetType(part, &currentType);
173:   PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, currentType, name, sizeof(name), &flg);
174:   if (flg) {
175:     PetscPartitionerSetType(part, name);
176:   }
177:   PetscOptionsBool("-petscpartitioner_use_vertex_weights","Use vertex weights","",part->usevwgt,&part->usevwgt,NULL);
178:   if (part->ops->setfromoptions) {
179:     (*part->ops->setfromoptions)(PetscOptionsObject,part);
180:   }
181:   PetscViewerDestroy(&part->viewer);
182:   PetscViewerDestroy(&part->viewerGraph);
183:   PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view", &part->viewer, NULL, NULL);
184:   PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, NULL, &part->viewGraph);
185:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
186:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part);
187:   PetscOptionsEnd();
188:   return 0;
189: }

191: /*@
192:   PetscPartitionerSetUp - Construct data structures for the PetscPartitioner

194:   Collective on PetscPartitioner

196:   Input Parameter:
197: . part - the PetscPartitioner object to setup

199:   Level: developer

201: .seealso: PetscPartitionerView(), PetscPartitionerDestroy()
202: @*/
203: PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part)
204: {
206:   if (part->ops->setup) (*part->ops->setup)(part);
207:   return 0;
208: }

210: /*@
211:   PetscPartitionerReset - Resets data structures for the PetscPartitioner

213:   Collective on PetscPartitioner

215:   Input Parameter:
216: . part - the PetscPartitioner object to reset

218:   Level: developer

220: .seealso: PetscPartitionerSetUp(), PetscPartitionerDestroy()
221: @*/
222: PetscErrorCode PetscPartitionerReset(PetscPartitioner part)
223: {
225:   if (part->ops->reset) (*part->ops->reset)(part);
226:   return 0;
227: }

229: /*@
230:   PetscPartitionerDestroy - Destroys a PetscPartitioner object

232:   Collective on PetscPartitioner

234:   Input Parameter:
235: . part - the PetscPartitioner object to destroy

237:   Level: developer

239: .seealso: PetscPartitionerView()
240: @*/
241: PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part)
242: {
243:   if (!*part) return 0;

246:   if (--((PetscObject)(*part))->refct > 0) {*part = NULL; return 0;}
247:   ((PetscObject) (*part))->refct = 0;

249:   PetscPartitionerReset(*part);

251:   PetscViewerDestroy(&(*part)->viewer);
252:   PetscViewerDestroy(&(*part)->viewerGraph);
253:   if ((*part)->ops->destroy) (*(*part)->ops->destroy)(*part);
254:   PetscHeaderDestroy(part);
255:   return 0;
256: }

258: /*@
259:   PetscPartitionerPartition - Partition a graph

261:   Collective on PetscPartitioner

263:   Input Parameters:
264: + part    - The PetscPartitioner
265: . nparts  - Number of partitions
266: . numVertices - Number of vertices in the local part of the graph
267: . start - row pointers for the local part of the graph (CSR style)
268: . adjacency - adjacency list (CSR style)
269: . vertexSection - PetscSection describing the absolute weight of each local vertex (can be NULL)
270: - targetSection - PetscSection describing the absolute weight of each partition (can be NULL)

272:   Output Parameters:
273: + partSection     - The PetscSection giving the division of points by partition
274: - partition       - The list of points by partition

276:   Options Database:
277: + -petscpartitioner_view - View the partitioner information
278: - -petscpartitioner_view_graph - View the graph we are partitioning

280:   Notes:
281:     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.
282:     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.

284:   Level: developer

286: .seealso PetscPartitionerCreate(), PetscPartitionerSetType(), PetscSectionCreate(), PetscSectionSetChart(), PetscSectionSetDof()
287: @*/
288: PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertexSection, PetscSection targetSection, PetscSection partSection, IS *partition)
289: {
294:   if (numVertices && !part->noGraph) {
298:   }
299:   if (vertexSection) {
300:     PetscInt s,e;

303:     PetscSectionGetChart(vertexSection, &s, &e);
305:   }
306:   if (targetSection) {
307:     PetscInt s,e;

310:     PetscSectionGetChart(targetSection, &s, &e);
312:   }

316:   PetscSectionReset(partSection);
317:   PetscSectionSetChart(partSection, 0, nparts);
318:   if (nparts == 1) { /* quick */
319:     PetscSectionSetDof(partSection, 0, numVertices);
320:     ISCreateStride(PetscObjectComm((PetscObject)part),numVertices,0,1,partition);
321:   } else {
323:     (*part->ops->partition)(part, nparts, numVertices, start, adjacency, vertexSection, targetSection, partSection, partition);
324:   }
325:   PetscSectionSetUp(partSection);
326:   if (part->viewerGraph) {
327:     PetscViewer viewer = part->viewerGraph;
328:     PetscBool   isascii;
329:     PetscInt    v, i;
330:     PetscMPIInt rank;

332:     MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);
333:     PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);
334:     if (isascii) {
335:       PetscViewerASCIIPushSynchronized(viewer);
336:       PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %D\n", rank, numVertices);
337:       for (v = 0; v < numVertices; ++v) {
338:         const PetscInt s = start[v];
339:         const PetscInt e = start[v+1];

341:         PetscViewerASCIISynchronizedPrintf(viewer, "[%d]  ", rank);
342:         for (i = s; i < e; ++i) PetscViewerASCIISynchronizedPrintf(viewer, "%D ", adjacency[i]);
343:         PetscViewerASCIISynchronizedPrintf(viewer, "[%D-%D)\n", s, e);
344:       }
345:       PetscViewerFlush(viewer);
346:       PetscViewerASCIIPopSynchronized(viewer);
347:     }
348:   }
349:   if (part->viewer) {
350:     PetscPartitionerView(part,part->viewer);
351:   }
352:   return 0;
353: }

355: /*@
356:   PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType().

358:   Collective

360:   Input Parameter:
361: . comm - The communicator for the PetscPartitioner object

363:   Output Parameter:
364: . part - The PetscPartitioner object

366:   Level: beginner

368: .seealso: PetscPartitionerSetType(), PetscPartitionerDestroy()
369: @*/
370: PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part)
371: {
372:   PetscPartitioner p;
373:   const char       *partitionerType = NULL;

376:   *part = NULL;
377:   PetscPartitionerInitializePackage();

379:   PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView);
380:   PetscPartitionerGetDefaultType(comm, &partitionerType);
381:   PetscPartitionerSetType(p, partitionerType);

383:   p->edgeCut = 0;
384:   p->balance = 0.0;
385:   p->usevwgt = PETSC_TRUE;

387:   *part = p;
388:   return 0;
389: }