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