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