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