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