1*abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h> /*I "petscpartitioner.h" I*/ 2*abe9303eSLisandro Dalcin 3*abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 4*abe9303eSLisandro Dalcin #include <parmetis.h> 5*abe9303eSLisandro Dalcin #endif 6*abe9303eSLisandro Dalcin 7*abe9303eSLisandro Dalcin PetscBool ParMetisPartitionerCite = PETSC_FALSE; 8*abe9303eSLisandro Dalcin const char ParMetisPartitionerCitation[] = 9*abe9303eSLisandro Dalcin "@article{KarypisKumar98,\n" 10*abe9303eSLisandro Dalcin " author = {George Karypis and Vipin Kumar},\n" 11*abe9303eSLisandro Dalcin " title = {A Parallel Algorithm for Multilevel Graph Partitioning and Sparse Matrix Ordering},\n" 12*abe9303eSLisandro Dalcin " journal = {Journal of Parallel and Distributed Computing},\n" 13*abe9303eSLisandro Dalcin " volume = {48},\n" 14*abe9303eSLisandro Dalcin " pages = {71--85},\n" 15*abe9303eSLisandro Dalcin " year = {1998}\n" 16*abe9303eSLisandro Dalcin " doi = {https://doi.org/10.1006/jpdc.1997.1403}\n" 17*abe9303eSLisandro Dalcin "}\n"; 18*abe9303eSLisandro Dalcin 19*abe9303eSLisandro Dalcin typedef struct { 20*abe9303eSLisandro Dalcin MPI_Comm pcomm; 21*abe9303eSLisandro Dalcin PetscInt ptype; 22*abe9303eSLisandro Dalcin PetscReal imbalanceRatio; 23*abe9303eSLisandro Dalcin PetscInt debugFlag; 24*abe9303eSLisandro Dalcin PetscInt randomSeed; 25*abe9303eSLisandro Dalcin } PetscPartitioner_ParMetis; 26*abe9303eSLisandro Dalcin 27*abe9303eSLisandro Dalcin static const char *ptypes[] = {"kway", "rb"}; 28*abe9303eSLisandro Dalcin 29*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_ParMetis(PetscPartitioner part) 30*abe9303eSLisandro Dalcin { 31*abe9303eSLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 32*abe9303eSLisandro Dalcin PetscErrorCode ierr; 33*abe9303eSLisandro Dalcin 34*abe9303eSLisandro Dalcin PetscFunctionBegin; 35*abe9303eSLisandro Dalcin ierr = MPI_Comm_free(&p->pcomm);CHKERRQ(ierr); 36*abe9303eSLisandro Dalcin ierr = PetscFree(part->data);CHKERRQ(ierr); 37*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 38*abe9303eSLisandro Dalcin } 39*abe9303eSLisandro Dalcin 40*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_ParMetis_ASCII(PetscPartitioner part, PetscViewer viewer) 41*abe9303eSLisandro Dalcin { 42*abe9303eSLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 43*abe9303eSLisandro Dalcin PetscErrorCode ierr; 44*abe9303eSLisandro Dalcin 45*abe9303eSLisandro Dalcin PetscFunctionBegin; 46*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 47*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "ParMetis type: %s\n", ptypes[p->ptype]);CHKERRQ(ierr); 48*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "load imbalance ratio %g\n", (double) p->imbalanceRatio);CHKERRQ(ierr); 49*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "debug flag %D\n", p->debugFlag);CHKERRQ(ierr); 50*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "random seed %D\n", p->randomSeed);CHKERRQ(ierr); 51*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 52*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 53*abe9303eSLisandro Dalcin } 54*abe9303eSLisandro Dalcin 55*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_ParMetis(PetscPartitioner part, PetscViewer viewer) 56*abe9303eSLisandro Dalcin { 57*abe9303eSLisandro Dalcin PetscBool iascii; 58*abe9303eSLisandro Dalcin PetscErrorCode ierr; 59*abe9303eSLisandro Dalcin 60*abe9303eSLisandro Dalcin PetscFunctionBegin; 61*abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 62*abe9303eSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 63*abe9303eSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 64*abe9303eSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_ParMetis_ASCII(part, viewer);CHKERRQ(ierr);} 65*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 66*abe9303eSLisandro Dalcin } 67*abe9303eSLisandro Dalcin 68*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_ParMetis(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 69*abe9303eSLisandro Dalcin { 70*abe9303eSLisandro Dalcin PetscPartitioner_ParMetis *p = (PetscPartitioner_ParMetis *) part->data; 71*abe9303eSLisandro Dalcin PetscErrorCode ierr; 72*abe9303eSLisandro Dalcin 73*abe9303eSLisandro Dalcin PetscFunctionBegin; 74*abe9303eSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner ParMetis Options");CHKERRQ(ierr); 75*abe9303eSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_parmetis_type", "Partitioning method", "", ptypes, 2, ptypes[p->ptype], &p->ptype, NULL);CHKERRQ(ierr); 76*abe9303eSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_parmetis_imbalance_ratio", "Load imbalance ratio limit", "", p->imbalanceRatio, &p->imbalanceRatio, NULL);CHKERRQ(ierr); 77*abe9303eSLisandro Dalcin ierr = PetscOptionsInt("-petscpartitioner_parmetis_debug", "Debugging flag", "", p->debugFlag, &p->debugFlag, NULL);CHKERRQ(ierr); 78*abe9303eSLisandro Dalcin ierr = PetscOptionsInt("-petscpartitioner_parmetis_seed", "Random seed", "", p->randomSeed, &p->randomSeed, NULL);CHKERRQ(ierr); 79*abe9303eSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 80*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 81*abe9303eSLisandro Dalcin } 82*abe9303eSLisandro Dalcin 83*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_ParMetis(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 84*abe9303eSLisandro Dalcin { 85*abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PARMETIS) 86*abe9303eSLisandro Dalcin PetscPartitioner_ParMetis *pm = (PetscPartitioner_ParMetis *) part->data; 87*abe9303eSLisandro Dalcin MPI_Comm comm; 88*abe9303eSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 89*abe9303eSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 90*abe9303eSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 91*abe9303eSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 92*abe9303eSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 93*abe9303eSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 94*abe9303eSLisandro Dalcin PetscInt wgtflag = 0; /* Indicates which weights are present */ 95*abe9303eSLisandro Dalcin PetscInt numflag = 0; /* Indicates initial offset (0 or 1) */ 96*abe9303eSLisandro Dalcin PetscInt ncon = 1; /* The number of weights per vertex */ 97*abe9303eSLisandro Dalcin PetscInt metis_ptype = pm->ptype; /* kway or recursive bisection */ 98*abe9303eSLisandro Dalcin real_t *tpwgts; /* The fraction of vertex weights assigned to each partition */ 99*abe9303eSLisandro Dalcin real_t *ubvec; /* The balance intolerance for vertex weights */ 100*abe9303eSLisandro Dalcin PetscInt options[64]; /* Options */ 101*abe9303eSLisandro Dalcin PetscInt v, i, *assignment, *points; 102*abe9303eSLisandro Dalcin PetscMPIInt p, size, rank; 103*abe9303eSLisandro Dalcin PetscBool hasempty = PETSC_FALSE; 104*abe9303eSLisandro Dalcin PetscErrorCode ierr; 105*abe9303eSLisandro Dalcin 106*abe9303eSLisandro Dalcin PetscFunctionBegin; 107*abe9303eSLisandro Dalcin ierr = PetscObjectGetComm((PetscObject) part, &comm);CHKERRQ(ierr); 108*abe9303eSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 109*abe9303eSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 110*abe9303eSLisandro Dalcin /* Calculate vertex distribution */ 111*abe9303eSLisandro Dalcin ierr = PetscMalloc4(size+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr); 112*abe9303eSLisandro Dalcin vtxdist[0] = 0; 113*abe9303eSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 114*abe9303eSLisandro Dalcin for (p = 2; p <= size; ++p) { 115*abe9303eSLisandro Dalcin hasempty = (PetscBool)(hasempty || !vtxdist[p-1] || !vtxdist[p]); 116*abe9303eSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 117*abe9303eSLisandro Dalcin } 118*abe9303eSLisandro Dalcin /* null graph */ 119*abe9303eSLisandro Dalcin if (vtxdist[size] == 0) { 120*abe9303eSLisandro Dalcin ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 121*abe9303eSLisandro Dalcin ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 122*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 123*abe9303eSLisandro Dalcin } 124*abe9303eSLisandro Dalcin /* Calculate partition weights */ 125*abe9303eSLisandro Dalcin if (targetSection) { 126*abe9303eSLisandro Dalcin PetscInt p; 127*abe9303eSLisandro Dalcin real_t sumt = 0.0; 128*abe9303eSLisandro Dalcin 129*abe9303eSLisandro Dalcin for (p = 0; p < nparts; ++p) { 130*abe9303eSLisandro Dalcin PetscInt tpd; 131*abe9303eSLisandro Dalcin 132*abe9303eSLisandro Dalcin ierr = PetscSectionGetDof(targetSection,p,&tpd);CHKERRQ(ierr); 133*abe9303eSLisandro Dalcin sumt += tpd; 134*abe9303eSLisandro Dalcin tpwgts[p] = tpd; 135*abe9303eSLisandro Dalcin } 136*abe9303eSLisandro Dalcin if (sumt) { /* METIS/ParMETIS do not like exactly zero weight */ 137*abe9303eSLisandro Dalcin for (p = 0, sumt = 0.0; p < nparts; ++p) { 138*abe9303eSLisandro Dalcin tpwgts[p] = PetscMax(tpwgts[p],PETSC_SMALL); 139*abe9303eSLisandro Dalcin sumt += tpwgts[p]; 140*abe9303eSLisandro Dalcin } 141*abe9303eSLisandro Dalcin for (p = 0; p < nparts; ++p) tpwgts[p] /= sumt; 142*abe9303eSLisandro Dalcin for (p = 0, sumt = 0.0; p < nparts-1; ++p) sumt += tpwgts[p]; 143*abe9303eSLisandro Dalcin tpwgts[nparts - 1] = 1. - sumt; 144*abe9303eSLisandro Dalcin } 145*abe9303eSLisandro Dalcin } else { 146*abe9303eSLisandro Dalcin for (p = 0; p < nparts; ++p) tpwgts[p] = 1.0/nparts; 147*abe9303eSLisandro Dalcin } 148*abe9303eSLisandro Dalcin ubvec[0] = pm->imbalanceRatio; 149*abe9303eSLisandro Dalcin 150*abe9303eSLisandro Dalcin /* Weight cells */ 151*abe9303eSLisandro Dalcin if (vertSection) { 152*abe9303eSLisandro Dalcin ierr = PetscMalloc1(nvtxs,&vwgt);CHKERRQ(ierr); 153*abe9303eSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 154*abe9303eSLisandro Dalcin ierr = PetscSectionGetDof(vertSection, v, &vwgt[v]);CHKERRQ(ierr); 155*abe9303eSLisandro Dalcin } 156*abe9303eSLisandro Dalcin wgtflag |= 2; /* have weights on graph vertices */ 157*abe9303eSLisandro Dalcin } 158*abe9303eSLisandro Dalcin 159*abe9303eSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 160*abe9303eSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 161*abe9303eSLisandro Dalcin if (rank == p) { 162*abe9303eSLisandro Dalcin ierr = METIS_SetDefaultOptions(options); /* initialize all defaults */ 163*abe9303eSLisandro Dalcin options[METIS_OPTION_DBGLVL] = pm->debugFlag; 164*abe9303eSLisandro Dalcin options[METIS_OPTION_SEED] = pm->randomSeed; 165*abe9303eSLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_SetDefaultOptions()"); 166*abe9303eSLisandro Dalcin if (metis_ptype == 1) { 167*abe9303eSLisandro Dalcin PetscStackPush("METIS_PartGraphRecursive"); 168*abe9303eSLisandro Dalcin ierr = METIS_PartGraphRecursive(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 169*abe9303eSLisandro Dalcin PetscStackPop; 170*abe9303eSLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphRecursive()"); 171*abe9303eSLisandro Dalcin } else { 172*abe9303eSLisandro Dalcin /* 173*abe9303eSLisandro Dalcin It would be nice to activate the two options below, but they would need some actual testing. 174*abe9303eSLisandro Dalcin - Turning on these options may exercise path of the METIS code that have bugs and may break production runs. 175*abe9303eSLisandro Dalcin - If CONTIG is set to 1, METIS will exit with error if the graph is disconnected, despite the manual saying the option is ignored in such case. 176*abe9303eSLisandro Dalcin */ 177*abe9303eSLisandro Dalcin /* options[METIS_OPTION_CONTIG] = 1; */ /* try to produce partitions that are contiguous */ 178*abe9303eSLisandro Dalcin /* options[METIS_OPTION_MINCONN] = 1; */ /* minimize the maximum degree of the subdomain graph */ 179*abe9303eSLisandro Dalcin PetscStackPush("METIS_PartGraphKway"); 180*abe9303eSLisandro Dalcin ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment); 181*abe9303eSLisandro Dalcin PetscStackPop; 182*abe9303eSLisandro Dalcin if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()"); 183*abe9303eSLisandro Dalcin } 184*abe9303eSLisandro Dalcin } 185*abe9303eSLisandro Dalcin } else { 186*abe9303eSLisandro Dalcin MPI_Comm pcomm = pm->pcomm; 187*abe9303eSLisandro Dalcin 188*abe9303eSLisandro Dalcin options[0] = 1; /*use options */ 189*abe9303eSLisandro Dalcin options[1] = pm->debugFlag; 190*abe9303eSLisandro Dalcin options[2] = (pm->randomSeed == -1) ? 15 : pm->randomSeed; /* default is GLOBAL_SEED=15 from `libparmetis/defs.h` */ 191*abe9303eSLisandro Dalcin 192*abe9303eSLisandro Dalcin if (hasempty) { /* parmetis does not support empty graphs on some of the processes */ 193*abe9303eSLisandro Dalcin PetscInt cnt; 194*abe9303eSLisandro Dalcin 195*abe9303eSLisandro Dalcin ierr = MPI_Comm_split(pm->pcomm,!!nvtxs,rank,&pcomm);CHKERRQ(ierr); 196*abe9303eSLisandro Dalcin for (p=0,cnt=0;p<size;p++) { 197*abe9303eSLisandro Dalcin if (vtxdist[p+1] != vtxdist[p]) { 198*abe9303eSLisandro Dalcin vtxdist[cnt+1] = vtxdist[p+1]; 199*abe9303eSLisandro Dalcin cnt++; 200*abe9303eSLisandro Dalcin } 201*abe9303eSLisandro Dalcin } 202*abe9303eSLisandro Dalcin } 203*abe9303eSLisandro Dalcin if (nvtxs) { 204*abe9303eSLisandro Dalcin PetscStackPush("ParMETIS_V3_PartKway"); 205*abe9303eSLisandro Dalcin ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &part->edgeCut, assignment, &pcomm); 206*abe9303eSLisandro Dalcin PetscStackPop; 207*abe9303eSLisandro Dalcin if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error %d in ParMETIS_V3_PartKway()", ierr); 208*abe9303eSLisandro Dalcin } 209*abe9303eSLisandro Dalcin if (hasempty) { 210*abe9303eSLisandro Dalcin ierr = MPI_Comm_free(&pcomm);CHKERRQ(ierr); 211*abe9303eSLisandro Dalcin } 212*abe9303eSLisandro Dalcin } 213*abe9303eSLisandro Dalcin 214*abe9303eSLisandro Dalcin /* Convert to PetscSection+IS */ 215*abe9303eSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 216*abe9303eSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 217*abe9303eSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 218*abe9303eSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 219*abe9303eSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 220*abe9303eSLisandro Dalcin } 221*abe9303eSLisandro Dalcin } 222*abe9303eSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 223*abe9303eSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 224*abe9303eSLisandro Dalcin ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr); 225*abe9303eSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 226*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 227*abe9303eSLisandro Dalcin #else 228*abe9303eSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-parmetis."); 229*abe9303eSLisandro Dalcin #endif 230*abe9303eSLisandro Dalcin } 231*abe9303eSLisandro Dalcin 232*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_ParMetis(PetscPartitioner part) 233*abe9303eSLisandro Dalcin { 234*abe9303eSLisandro Dalcin PetscFunctionBegin; 235*abe9303eSLisandro Dalcin part->noGraph = PETSC_FALSE; 236*abe9303eSLisandro Dalcin part->ops->view = PetscPartitionerView_ParMetis; 237*abe9303eSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_ParMetis; 238*abe9303eSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_ParMetis; 239*abe9303eSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_ParMetis; 240*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 241*abe9303eSLisandro Dalcin } 242*abe9303eSLisandro Dalcin 243*abe9303eSLisandro Dalcin /*MC 244*abe9303eSLisandro Dalcin PETSCPARTITIONERPARMETIS = "parmetis" - A PetscPartitioner object using the ParMETIS library 245*abe9303eSLisandro Dalcin 246*abe9303eSLisandro Dalcin Level: intermediate 247*abe9303eSLisandro Dalcin 248*abe9303eSLisandro Dalcin Options Database Keys: 249*abe9303eSLisandro Dalcin + -petscpartitioner_parmetis_type <string> - ParMETIS partitioning type. Either "kway" or "rb" (recursive bisection) 250*abe9303eSLisandro Dalcin . -petscpartitioner_parmetis_imbalance_ratio <value> - Load imbalance ratio limit 251*abe9303eSLisandro Dalcin . -petscpartitioner_parmetis_debug <int> - Debugging flag passed to ParMETIS/METIS routines 252*abe9303eSLisandro Dalcin - -petscpartitioner_parmetis_seed <int> - Random seed 253*abe9303eSLisandro Dalcin 254*abe9303eSLisandro Dalcin Notes: when the graph is on a single process, this partitioner actually calls METIS and not ParMETIS 255*abe9303eSLisandro Dalcin 256*abe9303eSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 257*abe9303eSLisandro Dalcin M*/ 258*abe9303eSLisandro Dalcin 259*abe9303eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_ParMetis(PetscPartitioner part) 260*abe9303eSLisandro Dalcin { 261*abe9303eSLisandro Dalcin PetscPartitioner_ParMetis *p; 262*abe9303eSLisandro Dalcin PetscErrorCode ierr; 263*abe9303eSLisandro Dalcin 264*abe9303eSLisandro Dalcin PetscFunctionBegin; 265*abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 266*abe9303eSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 267*abe9303eSLisandro Dalcin part->data = p; 268*abe9303eSLisandro Dalcin 269*abe9303eSLisandro Dalcin ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)part),&p->pcomm);CHKERRQ(ierr); 270*abe9303eSLisandro Dalcin p->ptype = 0; 271*abe9303eSLisandro Dalcin p->imbalanceRatio = 1.05; 272*abe9303eSLisandro Dalcin p->debugFlag = 0; 273*abe9303eSLisandro Dalcin p->randomSeed = -1; /* defaults to GLOBAL_SEED=15 from `libparmetis/defs.h` */ 274*abe9303eSLisandro Dalcin 275*abe9303eSLisandro Dalcin ierr = PetscPartitionerInitialize_ParMetis(part);CHKERRQ(ierr); 276*abe9303eSLisandro Dalcin ierr = PetscCitationsRegister(ParMetisPartitionerCitation, &ParMetisPartitionerCite);CHKERRQ(ierr); 277*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 278*abe9303eSLisandro Dalcin } 279*abe9303eSLisandro Dalcin 280