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