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) PetscCall((*part->ops->destroy)(part)); 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(0); 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(0); 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(0); 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 if (part->ops->view) PetscCall((*part->ops->view)(part, v)); 124 PetscFunctionReturn(0); 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(0); 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 if (part->ops->setfromoptions) PetscCall((*part->ops->setfromoptions)(PetscOptionsObject,part)); 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(PetscOptionsObject,(PetscObject) part)); 186 PetscOptionsEnd(); 187 PetscFunctionReturn(0); 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 if (part->ops->setup) PetscCall((*part->ops->setup)(part)); 207 PetscFunctionReturn(0); 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 if (part->ops->reset) PetscCall((*part->ops->reset)(part)); 227 PetscFunctionReturn(0); 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(0); 246 PetscValidHeaderSpecific((*part), PETSCPARTITIONER_CLASSID, 1); 247 248 if (--((PetscObject)(*part))->refct > 0) {*part = NULL; PetscFunctionReturn(0);} 249 ((PetscObject) (*part))->refct = 0; 250 251 PetscCall(PetscPartitionerReset(*part)); 252 253 PetscCall(PetscViewerDestroy(&(*part)->viewer)); 254 PetscCall(PetscViewerDestroy(&(*part)->viewerGraph)); 255 if ((*part)->ops->destroy) PetscCall((*(*part)->ops->destroy)(*part)); 256 PetscCall(PetscHeaderDestroy(part)); 257 PetscFunctionReturn(0); 258 } 259 260 /*@ 261 PetscPartitionerPartition - Partition a graph 262 263 Collective on PetscPartitioner 264 265 Input Parameters: 266 + part - The PetscPartitioner 267 . nparts - Number of partitions 268 . numVertices - Number of vertices in the local part of the graph 269 . start - row pointers for the local part of the graph (CSR style) 270 . adjacency - adjacency list (CSR style) 271 . vertexSection - PetscSection describing the absolute weight of each local vertex (can be NULL) 272 - targetSection - PetscSection describing the absolute weight of each partition (can be NULL) 273 274 Output Parameters: 275 + partSection - The PetscSection giving the division of points by partition 276 - partition - The list of points by partition 277 278 Options Database: 279 + -petscpartitioner_view - View the partitioner information 280 - -petscpartitioner_view_graph - View the graph we are partitioning 281 282 Notes: 283 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. 284 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. 285 286 Level: developer 287 288 .seealso `PetscPartitionerCreate()`, `PetscPartitionerSetType()`, `PetscSectionCreate()`, `PetscSectionSetChart()`, `PetscSectionSetDof()` 289 @*/ 290 PetscErrorCode PetscPartitionerPartition(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertexSection, PetscSection targetSection, PetscSection partSection, IS *partition) 291 { 292 PetscFunctionBegin; 293 PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 294 PetscValidLogicalCollectiveInt(part, nparts, 2); 295 PetscCheck(nparts > 0,PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_OUTOFRANGE, "Number of parts must be positive"); 296 PetscCheck(numVertices >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices must be non-negative"); 297 if (numVertices && !part->noGraph) { 298 PetscValidIntPointer(start, 4); 299 PetscValidIntPointer(start + numVertices, 4); 300 if (start[numVertices]) PetscValidIntPointer(adjacency, 5); 301 } 302 if (vertexSection) { 303 PetscInt s,e; 304 305 PetscValidHeaderSpecific(vertexSection, PETSC_SECTION_CLASSID, 6); 306 PetscCall(PetscSectionGetChart(vertexSection, &s, &e)); 307 PetscCheck(s <= 0 && e >= numVertices,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid vertexSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")",s,e); 308 } 309 if (targetSection) { 310 PetscInt s,e; 311 312 PetscValidHeaderSpecific(targetSection, PETSC_SECTION_CLASSID, 7); 313 PetscCall(PetscSectionGetChart(targetSection, &s, &e)); 314 PetscCheck(s <= 0 && e >= nparts,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid targetSection chart [%" PetscInt_FMT ",%" PetscInt_FMT ")",s,e); 315 } 316 PetscValidHeaderSpecific(partSection, PETSC_SECTION_CLASSID, 8); 317 PetscValidPointer(partition, 9); 318 319 PetscCall(PetscSectionReset(partSection)); 320 PetscCall(PetscSectionSetChart(partSection, 0, nparts)); 321 if (nparts == 1) { /* quick */ 322 PetscCall(PetscSectionSetDof(partSection, 0, numVertices)); 323 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)part),numVertices,0,1,partition)); 324 } else { 325 PetscCheck(part->ops->partition,PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "PetscPartitioner %s has no partitioning method", ((PetscObject)part)->type_name); 326 PetscCall((*part->ops->partition)(part, nparts, numVertices, start, adjacency, vertexSection, targetSection, partSection, partition)); 327 } 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(0); 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(0); 391 } 392