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: %" PetscInt_FMT "\n", part->edgeCut)); 122 PetscCall(PetscViewerASCIIPrintf(v, " balance: %.2g\n", (double)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 174 PetscFunctionBegin; 175 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 176 PetscObjectOptionsBegin((PetscObject) part); 177 PetscCall(PetscPartitionerGetType(part, ¤tType)); 178 PetscCall(PetscOptionsFList("-petscpartitioner_type", "Graph partitioner", "PetscPartitionerSetType", PetscPartitionerList, currentType, name, sizeof(name), &flg)); 179 if (flg) { 180 PetscCall(PetscPartitionerSetType(part, name)); 181 } 182 PetscCall(PetscOptionsBool("-petscpartitioner_use_vertex_weights","Use vertex weights","",part->usevwgt,&part->usevwgt,NULL)); 183 if (part->ops->setfromoptions) { 184 PetscCall((*part->ops->setfromoptions)(PetscOptionsObject,part)); 185 } 186 PetscCall(PetscViewerDestroy(&part->viewer)); 187 PetscCall(PetscViewerDestroy(&part->viewerGraph)); 188 PetscCall(PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view", &part->viewer, NULL, NULL)); 189 PetscCall(PetscOptionsGetViewer(((PetscObject) part)->comm, ((PetscObject) part)->options, ((PetscObject) part)->prefix, "-petscpartitioner_view_graph", &part->viewerGraph, NULL, &part->viewGraph)); 190 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 191 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) part)); 192 PetscOptionsEnd(); 193 PetscFunctionReturn(0); 194 } 195 196 /*@ 197 PetscPartitionerSetUp - Construct data structures for the PetscPartitioner 198 199 Collective on PetscPartitioner 200 201 Input Parameter: 202 . part - the PetscPartitioner object to setup 203 204 Level: developer 205 206 .seealso: PetscPartitionerView(), PetscPartitionerDestroy() 207 @*/ 208 PetscErrorCode PetscPartitionerSetUp(PetscPartitioner part) 209 { 210 PetscFunctionBegin; 211 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 212 if (part->ops->setup) PetscCall((*part->ops->setup)(part)); 213 PetscFunctionReturn(0); 214 } 215 216 /*@ 217 PetscPartitionerReset - Resets data structures for the PetscPartitioner 218 219 Collective on PetscPartitioner 220 221 Input Parameter: 222 . part - the PetscPartitioner object to reset 223 224 Level: developer 225 226 .seealso: PetscPartitionerSetUp(), PetscPartitionerDestroy() 227 @*/ 228 PetscErrorCode PetscPartitionerReset(PetscPartitioner part) 229 { 230 PetscFunctionBegin; 231 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 232 if (part->ops->reset) PetscCall((*part->ops->reset)(part)); 233 PetscFunctionReturn(0); 234 } 235 236 /*@ 237 PetscPartitionerDestroy - Destroys a PetscPartitioner object 238 239 Collective on PetscPartitioner 240 241 Input Parameter: 242 . part - the PetscPartitioner object to destroy 243 244 Level: developer 245 246 .seealso: PetscPartitionerView() 247 @*/ 248 PetscErrorCode PetscPartitionerDestroy(PetscPartitioner *part) 249 { 250 PetscFunctionBegin; 251 if (!*part) PetscFunctionReturn(0); 252 PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 253 254 if (--((PetscObject)(*part))->refct > 0) {*part = NULL; PetscFunctionReturn(0);} 255 ((PetscObject) (*part))->refct = 0; 256 257 PetscCall(PetscPartitionerReset(*part)); 258 259 PetscCall(PetscViewerDestroy(&(*part)->viewer)); 260 PetscCall(PetscViewerDestroy(&(*part)->viewerGraph)); 261 if ((*part)->ops->destroy) PetscCall((*(*part)->ops->destroy)(*part)); 262 PetscCall(PetscHeaderDestroy(part)); 263 PetscFunctionReturn(0); 264 } 265 266 /*@ 267 PetscPartitionerPartition - Partition a graph 268 269 Collective on PetscPartitioner 270 271 Input Parameters: 272 + part - The PetscPartitioner 273 . nparts - Number of partitions 274 . numVertices - Number of vertices in the local part of the graph 275 . start - row pointers for the local part of the graph (CSR style) 276 . adjacency - adjacency list (CSR style) 277 . vertexSection - PetscSection describing the absolute weight of each local vertex (can be NULL) 278 - targetSection - PetscSection describing the absolute weight of each partition (can be NULL) 279 280 Output Parameters: 281 + partSection - The PetscSection giving the division of points by partition 282 - partition - The list of points by partition 283 284 Options Database: 285 + -petscpartitioner_view - View the partitioner information 286 - -petscpartitioner_view_graph - View the graph we are partitioning 287 288 Notes: 289 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. 290 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. 291 292 Level: developer 293 294 .seealso PetscPartitionerCreate(), PetscPartitionerSetType(), PetscSectionCreate(), PetscSectionSetChart(), PetscSectionSetDof() 295 @*/ 296 PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertexSection, PetscSection targetSection, PetscSection partSection, IS *partition) 297 { 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 300 PetscValidLogicalCollectiveInt(part, nparts, 2); 301 PetscCheck(nparts > 0,PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Number of parts must be positive"); 302 PetscCheck(numVertices >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices must be non-negative"); 303 if (numVertices && !part->noGraph) { 304 PetscValidIntPointer(start, 4); 305 PetscValidIntPointer(start + numVertices, 4); 306 if (start[numVertices]) PetscValidIntPointer(adjacency, 5); 307 } 308 if (vertexSection) { 309 PetscInt s,e; 310 311 PetscValidHeaderSpecific(vertexSection, PETSC_SECTION_CLASSID, 6); 312 PetscCall(PetscSectionGetChart(vertexSection, &s, &e)); 313 PetscCheckFalse(s > 0 || e < numVertices,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid vertexSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")",s,e); 314 } 315 if (targetSection) { 316 PetscInt s,e; 317 318 PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 7); 319 PetscCall(PetscSectionGetChart(targetSection, &s, &e)); 320 PetscCheckFalse(s > 0 || e < nparts,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid targetSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")",s,e); 321 } 322 PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 8); 323 PetscValidPointer(partition, 9); 324 325 PetscCall(PetscSectionReset(partSection)); 326 PetscCall(PetscSectionSetChart(partSection, 0, nparts)); 327 if (nparts == 1) { /* quick */ 328 PetscCall(PetscSectionSetDof(partSection, 0, numVertices)); 329 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)part),numVertices,0,1,partition)); 330 } else { 331 PetscCheck(part->ops->partition,PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "PetscPartitioner %s has no partitioning method", ((PetscObject)part)->type_name); 332 PetscCall((*part->ops->partition)(part, nparts, numVertices, start, adjacency, vertexSection, targetSection, partSection, partition)); 333 } 334 PetscCall(PetscSectionSetUp(partSection)); 335 if (part->viewerGraph) { 336 PetscViewer viewer = part->viewerGraph; 337 PetscBool isascii; 338 PetscInt v, i; 339 PetscMPIInt rank; 340 341 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank)); 342 PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii)); 343 if (isascii) { 344 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 345 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]Nv: %" PetscInt_FMT "\n", rank, numVertices)); 346 for (v = 0; v < numVertices; ++v) { 347 const PetscInt s = start[v]; 348 const PetscInt e = start[v+1]; 349 350 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] ", rank)); 351 for (i = s; i < e; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT " ", adjacency[i])); 352 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%" PetscInt_FMT "-%" PetscInt_FMT ")\n", s, e)); 353 } 354 PetscCall(PetscViewerFlush(viewer)); 355 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 356 } 357 } 358 if (part->viewer) { 359 PetscCall(PetscPartitionerView(part,part->viewer)); 360 } 361 PetscFunctionReturn(0); 362 } 363 364 /*@ 365 PetscPartitionerCreate - Creates an empty PetscPartitioner object. The type can then be set with PetscPartitionerSetType(). 366 367 Collective 368 369 Input Parameter: 370 . comm - The communicator for the PetscPartitioner object 371 372 Output Parameter: 373 . part - The PetscPartitioner object 374 375 Level: beginner 376 377 .seealso: PetscPartitionerSetType(), PetscPartitionerDestroy() 378 @*/ 379 PetscErrorCode PetscPartitionerCreate(MPI_Comm comm, PetscPartitioner *part) 380 { 381 PetscPartitioner p; 382 const char *partitionerType = NULL; 383 384 PetscFunctionBegin; 385 PetscValidPointer(part, 2); 386 *part = NULL; 387 PetscCall(PetscPartitionerInitializePackage()); 388 389 PetscCall(PetscHeaderCreate(p, PETSCPARTITIONER_CLASSID, "PetscPartitioner", "Graph Partitioner", "PetscPartitioner", comm, PetscPartitionerDestroy, PetscPartitionerView)); 390 PetscCall(PetscPartitionerGetDefaultType(comm, &partitionerType)); 391 PetscCall(PetscPartitionerSetType(p, partitionerType)); 392 393 p->edgeCut = 0; 394 p->balance = 0.0; 395 p->usevwgt = PETSC_TRUE; 396 397 *part = p; 398 PetscFunctionReturn(0); 399 } 400