1*abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h> /*I "petscpartitioner.h" I*/ 2*abe9303eSLisandro Dalcin 3*abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 4*abe9303eSLisandro Dalcin EXTERN_C_BEGIN 5*abe9303eSLisandro Dalcin #include <ptscotch.h> 6*abe9303eSLisandro Dalcin EXTERN_C_END 7*abe9303eSLisandro Dalcin #endif 8*abe9303eSLisandro Dalcin 9*abe9303eSLisandro Dalcin PetscBool PTScotchPartitionerCite = PETSC_FALSE; 10*abe9303eSLisandro Dalcin const char PTScotchPartitionerCitation[] = 11*abe9303eSLisandro Dalcin "@article{PTSCOTCH,\n" 12*abe9303eSLisandro Dalcin " author = {C. Chevalier and F. Pellegrini},\n" 13*abe9303eSLisandro Dalcin " title = {{PT-SCOTCH}: a tool for efficient parallel graph ordering},\n" 14*abe9303eSLisandro Dalcin " journal = {Parallel Computing},\n" 15*abe9303eSLisandro Dalcin " volume = {34},\n" 16*abe9303eSLisandro Dalcin " number = {6},\n" 17*abe9303eSLisandro Dalcin " pages = {318--331},\n" 18*abe9303eSLisandro Dalcin " year = {2008},\n" 19*abe9303eSLisandro Dalcin " doi = {https://doi.org/10.1016/j.parco.2007.12.001}\n" 20*abe9303eSLisandro Dalcin "}\n"; 21*abe9303eSLisandro Dalcin 22*abe9303eSLisandro Dalcin typedef struct { 23*abe9303eSLisandro Dalcin MPI_Comm pcomm; 24*abe9303eSLisandro Dalcin PetscInt strategy; 25*abe9303eSLisandro Dalcin PetscReal imbalance; 26*abe9303eSLisandro Dalcin } PetscPartitioner_PTScotch; 27*abe9303eSLisandro Dalcin 28*abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 29*abe9303eSLisandro Dalcin 30*abe9303eSLisandro Dalcin #define CHKERRPTSCOTCH(ierr) do { if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling PT-Scotch library"); } while(0) 31*abe9303eSLisandro Dalcin 32*abe9303eSLisandro Dalcin static int PTScotch_Strategy(PetscInt strategy) 33*abe9303eSLisandro Dalcin { 34*abe9303eSLisandro Dalcin switch (strategy) { 35*abe9303eSLisandro Dalcin case 0: return SCOTCH_STRATDEFAULT; 36*abe9303eSLisandro Dalcin case 1: return SCOTCH_STRATQUALITY; 37*abe9303eSLisandro Dalcin case 2: return SCOTCH_STRATSPEED; 38*abe9303eSLisandro Dalcin case 3: return SCOTCH_STRATBALANCE; 39*abe9303eSLisandro Dalcin case 4: return SCOTCH_STRATSAFETY; 40*abe9303eSLisandro Dalcin case 5: return SCOTCH_STRATSCALABILITY; 41*abe9303eSLisandro Dalcin case 6: return SCOTCH_STRATRECURSIVE; 42*abe9303eSLisandro Dalcin case 7: return SCOTCH_STRATREMAP; 43*abe9303eSLisandro Dalcin default: return SCOTCH_STRATDEFAULT; 44*abe9303eSLisandro Dalcin } 45*abe9303eSLisandro Dalcin } 46*abe9303eSLisandro Dalcin 47*abe9303eSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_Seq(SCOTCH_Num strategy, double imbalance, SCOTCH_Num n, SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 48*abe9303eSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num tpart[], SCOTCH_Num part[]) 49*abe9303eSLisandro Dalcin { 50*abe9303eSLisandro Dalcin SCOTCH_Graph grafdat; 51*abe9303eSLisandro Dalcin SCOTCH_Strat stradat; 52*abe9303eSLisandro Dalcin SCOTCH_Num vertnbr = n; 53*abe9303eSLisandro Dalcin SCOTCH_Num edgenbr = xadj[n]; 54*abe9303eSLisandro Dalcin SCOTCH_Num* velotab = vtxwgt; 55*abe9303eSLisandro Dalcin SCOTCH_Num* edlotab = adjwgt; 56*abe9303eSLisandro Dalcin SCOTCH_Num flagval = strategy; 57*abe9303eSLisandro Dalcin double kbalval = imbalance; 58*abe9303eSLisandro Dalcin PetscErrorCode ierr; 59*abe9303eSLisandro Dalcin 60*abe9303eSLisandro Dalcin PetscFunctionBegin; 61*abe9303eSLisandro Dalcin { 62*abe9303eSLisandro Dalcin PetscBool flg = PETSC_TRUE; 63*abe9303eSLisandro Dalcin ierr = PetscOptionsDeprecatedNoObject("-petscpartititoner_ptscotch_vertex_weight",NULL,"3.13","Use -petscpartitioner_use_vertex_weights");CHKERRQ(ierr); 64*abe9303eSLisandro Dalcin ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 65*abe9303eSLisandro Dalcin if (!flg) velotab = NULL; 66*abe9303eSLisandro Dalcin } 67*abe9303eSLisandro Dalcin ierr = SCOTCH_graphInit(&grafdat);CHKERRPTSCOTCH(ierr); 68*abe9303eSLisandro Dalcin ierr = SCOTCH_graphBuild(&grafdat, 0, vertnbr, xadj, xadj + 1, velotab, NULL, edgenbr, adjncy, edlotab);CHKERRPTSCOTCH(ierr); 69*abe9303eSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 70*abe9303eSLisandro Dalcin ierr = SCOTCH_stratGraphMapBuild(&stradat, flagval, nparts, kbalval);CHKERRPTSCOTCH(ierr); 71*abe9303eSLisandro Dalcin if (tpart) { 72*abe9303eSLisandro Dalcin SCOTCH_Arch archdat; 73*abe9303eSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 74*abe9303eSLisandro Dalcin ierr = SCOTCH_archCmpltw(&archdat, nparts, tpart);CHKERRPTSCOTCH(ierr); 75*abe9303eSLisandro Dalcin ierr = SCOTCH_graphMap(&grafdat, &archdat, &stradat, part);CHKERRPTSCOTCH(ierr); 76*abe9303eSLisandro Dalcin SCOTCH_archExit(&archdat); 77*abe9303eSLisandro Dalcin } else { 78*abe9303eSLisandro Dalcin ierr = SCOTCH_graphPart(&grafdat, nparts, &stradat, part);CHKERRPTSCOTCH(ierr); 79*abe9303eSLisandro Dalcin } 80*abe9303eSLisandro Dalcin SCOTCH_stratExit(&stradat); 81*abe9303eSLisandro Dalcin SCOTCH_graphExit(&grafdat); 82*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 83*abe9303eSLisandro Dalcin } 84*abe9303eSLisandro Dalcin 85*abe9303eSLisandro Dalcin static PetscErrorCode PTScotch_PartGraph_MPI(SCOTCH_Num strategy, double imbalance, SCOTCH_Num vtxdist[], SCOTCH_Num xadj[], SCOTCH_Num adjncy[], 86*abe9303eSLisandro Dalcin SCOTCH_Num vtxwgt[], SCOTCH_Num adjwgt[], SCOTCH_Num nparts, SCOTCH_Num tpart[], SCOTCH_Num part[], MPI_Comm comm) 87*abe9303eSLisandro Dalcin { 88*abe9303eSLisandro Dalcin PetscMPIInt procglbnbr; 89*abe9303eSLisandro Dalcin PetscMPIInt proclocnum; 90*abe9303eSLisandro Dalcin SCOTCH_Arch archdat; 91*abe9303eSLisandro Dalcin SCOTCH_Dgraph grafdat; 92*abe9303eSLisandro Dalcin SCOTCH_Dmapping mappdat; 93*abe9303eSLisandro Dalcin SCOTCH_Strat stradat; 94*abe9303eSLisandro Dalcin SCOTCH_Num vertlocnbr; 95*abe9303eSLisandro Dalcin SCOTCH_Num edgelocnbr; 96*abe9303eSLisandro Dalcin SCOTCH_Num* veloloctab = vtxwgt; 97*abe9303eSLisandro Dalcin SCOTCH_Num* edloloctab = adjwgt; 98*abe9303eSLisandro Dalcin SCOTCH_Num flagval = strategy; 99*abe9303eSLisandro Dalcin double kbalval = imbalance; 100*abe9303eSLisandro Dalcin PetscErrorCode ierr; 101*abe9303eSLisandro Dalcin 102*abe9303eSLisandro Dalcin PetscFunctionBegin; 103*abe9303eSLisandro Dalcin { 104*abe9303eSLisandro Dalcin PetscBool flg = PETSC_TRUE; 105*abe9303eSLisandro Dalcin ierr = PetscOptionsDeprecatedNoObject("-petscpartititoner_ptscotch_vertex_weight",NULL,"3.13","Use -petscpartitioner_use_vertex_weights");CHKERRQ(ierr); 106*abe9303eSLisandro Dalcin ierr = PetscOptionsGetBool(NULL, NULL, "-petscpartititoner_ptscotch_vertex_weight", &flg, NULL);CHKERRQ(ierr); 107*abe9303eSLisandro Dalcin if (!flg) veloloctab = NULL; 108*abe9303eSLisandro Dalcin } 109*abe9303eSLisandro Dalcin ierr = MPI_Comm_size(comm, &procglbnbr);CHKERRQ(ierr); 110*abe9303eSLisandro Dalcin ierr = MPI_Comm_rank(comm, &proclocnum);CHKERRQ(ierr); 111*abe9303eSLisandro Dalcin vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; 112*abe9303eSLisandro Dalcin edgelocnbr = xadj[vertlocnbr]; 113*abe9303eSLisandro Dalcin 114*abe9303eSLisandro Dalcin ierr = SCOTCH_dgraphInit(&grafdat, comm);CHKERRPTSCOTCH(ierr); 115*abe9303eSLisandro Dalcin ierr = SCOTCH_dgraphBuild(&grafdat, 0, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab);CHKERRPTSCOTCH(ierr); 116*abe9303eSLisandro Dalcin ierr = SCOTCH_stratInit(&stradat);CHKERRPTSCOTCH(ierr); 117*abe9303eSLisandro Dalcin ierr = SCOTCH_stratDgraphMapBuild(&stradat, flagval, procglbnbr, nparts, kbalval);CHKERRQ(ierr); 118*abe9303eSLisandro Dalcin ierr = SCOTCH_archInit(&archdat);CHKERRPTSCOTCH(ierr); 119*abe9303eSLisandro Dalcin if (tpart) { /* target partition weights */ 120*abe9303eSLisandro Dalcin ierr = SCOTCH_archCmpltw(&archdat, nparts, tpart);CHKERRPTSCOTCH(ierr); 121*abe9303eSLisandro Dalcin } else { 122*abe9303eSLisandro Dalcin ierr = SCOTCH_archCmplt(&archdat, nparts);CHKERRPTSCOTCH(ierr); 123*abe9303eSLisandro Dalcin } 124*abe9303eSLisandro Dalcin ierr = SCOTCH_dgraphMapInit(&grafdat, &mappdat, &archdat, part);CHKERRPTSCOTCH(ierr); 125*abe9303eSLisandro Dalcin 126*abe9303eSLisandro Dalcin ierr = SCOTCH_dgraphMapCompute(&grafdat, &mappdat, &stradat);CHKERRPTSCOTCH(ierr); 127*abe9303eSLisandro Dalcin SCOTCH_dgraphMapExit(&grafdat, &mappdat); 128*abe9303eSLisandro Dalcin SCOTCH_archExit(&archdat); 129*abe9303eSLisandro Dalcin SCOTCH_stratExit(&stradat); 130*abe9303eSLisandro Dalcin SCOTCH_dgraphExit(&grafdat); 131*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 132*abe9303eSLisandro Dalcin } 133*abe9303eSLisandro Dalcin 134*abe9303eSLisandro Dalcin #endif /* PETSC_HAVE_PTSCOTCH */ 135*abe9303eSLisandro Dalcin 136*abe9303eSLisandro Dalcin static const char *const 137*abe9303eSLisandro Dalcin PTScotchStrategyList[] = { 138*abe9303eSLisandro Dalcin "DEFAULT", 139*abe9303eSLisandro Dalcin "QUALITY", 140*abe9303eSLisandro Dalcin "SPEED", 141*abe9303eSLisandro Dalcin "BALANCE", 142*abe9303eSLisandro Dalcin "SAFETY", 143*abe9303eSLisandro Dalcin "SCALABILITY", 144*abe9303eSLisandro Dalcin "RECURSIVE", 145*abe9303eSLisandro Dalcin "REMAP" 146*abe9303eSLisandro Dalcin }; 147*abe9303eSLisandro Dalcin 148*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_PTScotch(PetscPartitioner part) 149*abe9303eSLisandro Dalcin { 150*abe9303eSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 151*abe9303eSLisandro Dalcin PetscErrorCode ierr; 152*abe9303eSLisandro Dalcin 153*abe9303eSLisandro Dalcin PetscFunctionBegin; 154*abe9303eSLisandro Dalcin ierr = MPI_Comm_free(&p->pcomm);CHKERRQ(ierr); 155*abe9303eSLisandro Dalcin ierr = PetscFree(part->data);CHKERRQ(ierr); 156*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 157*abe9303eSLisandro Dalcin } 158*abe9303eSLisandro Dalcin 159*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch_ASCII(PetscPartitioner part, PetscViewer viewer) 160*abe9303eSLisandro Dalcin { 161*abe9303eSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 162*abe9303eSLisandro Dalcin PetscErrorCode ierr; 163*abe9303eSLisandro Dalcin 164*abe9303eSLisandro Dalcin PetscFunctionBegin; 165*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 166*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer,"using partitioning strategy %s\n",PTScotchStrategyList[p->strategy]);CHKERRQ(ierr); 167*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer,"using load imbalance ratio %g\n",(double)p->imbalance);CHKERRQ(ierr); 168*abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 169*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 170*abe9303eSLisandro Dalcin } 171*abe9303eSLisandro Dalcin 172*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_PTScotch(PetscPartitioner part, PetscViewer viewer) 173*abe9303eSLisandro Dalcin { 174*abe9303eSLisandro Dalcin PetscBool iascii; 175*abe9303eSLisandro Dalcin PetscErrorCode ierr; 176*abe9303eSLisandro Dalcin 177*abe9303eSLisandro Dalcin PetscFunctionBegin; 178*abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 179*abe9303eSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 180*abe9303eSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 181*abe9303eSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_PTScotch_ASCII(part, viewer);CHKERRQ(ierr);} 182*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 183*abe9303eSLisandro Dalcin } 184*abe9303eSLisandro Dalcin 185*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_PTScotch(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 186*abe9303eSLisandro Dalcin { 187*abe9303eSLisandro Dalcin PetscPartitioner_PTScotch *p = (PetscPartitioner_PTScotch *) part->data; 188*abe9303eSLisandro Dalcin const char *const *slist = PTScotchStrategyList; 189*abe9303eSLisandro Dalcin PetscInt nlist = (PetscInt)(sizeof(PTScotchStrategyList)/sizeof(PTScotchStrategyList[0])); 190*abe9303eSLisandro Dalcin PetscBool flag; 191*abe9303eSLisandro Dalcin PetscErrorCode ierr; 192*abe9303eSLisandro Dalcin 193*abe9303eSLisandro Dalcin PetscFunctionBegin; 194*abe9303eSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner PTScotch Options");CHKERRQ(ierr); 195*abe9303eSLisandro Dalcin ierr = PetscOptionsEList("-petscpartitioner_ptscotch_strategy","Partitioning strategy","",slist,nlist,slist[p->strategy],&p->strategy,&flag);CHKERRQ(ierr); 196*abe9303eSLisandro Dalcin ierr = PetscOptionsReal("-petscpartitioner_ptscotch_imbalance","Load imbalance ratio","",p->imbalance,&p->imbalance,&flag);CHKERRQ(ierr); 197*abe9303eSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 198*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 199*abe9303eSLisandro Dalcin } 200*abe9303eSLisandro Dalcin 201*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_PTScotch(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 202*abe9303eSLisandro Dalcin { 203*abe9303eSLisandro Dalcin #if defined(PETSC_HAVE_PTSCOTCH) 204*abe9303eSLisandro Dalcin MPI_Comm comm; 205*abe9303eSLisandro Dalcin PetscInt nvtxs = numVertices; /* The number of vertices in full graph */ 206*abe9303eSLisandro Dalcin PetscInt *vtxdist; /* Distribution of vertices across processes */ 207*abe9303eSLisandro Dalcin PetscInt *xadj = start; /* Start of edge list for each vertex */ 208*abe9303eSLisandro Dalcin PetscInt *adjncy = adjacency; /* Edge lists for all vertices */ 209*abe9303eSLisandro Dalcin PetscInt *vwgt = NULL; /* Vertex weights */ 210*abe9303eSLisandro Dalcin PetscInt *adjwgt = NULL; /* Edge weights */ 211*abe9303eSLisandro Dalcin PetscInt v, i, *assignment, *points; 212*abe9303eSLisandro Dalcin PetscMPIInt size, rank, p; 213*abe9303eSLisandro Dalcin PetscBool hasempty = PETSC_FALSE; 214*abe9303eSLisandro Dalcin PetscInt *tpwgts = NULL; 215*abe9303eSLisandro Dalcin PetscErrorCode ierr; 216*abe9303eSLisandro Dalcin 217*abe9303eSLisandro Dalcin PetscFunctionBegin; 218*abe9303eSLisandro Dalcin ierr = PetscObjectGetComm((PetscObject)part,&comm);CHKERRQ(ierr); 219*abe9303eSLisandro Dalcin ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 220*abe9303eSLisandro Dalcin ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 221*abe9303eSLisandro Dalcin ierr = PetscMalloc2(size+1,&vtxdist,PetscMax(nvtxs,1),&assignment);CHKERRQ(ierr); 222*abe9303eSLisandro Dalcin /* Calculate vertex distribution */ 223*abe9303eSLisandro Dalcin vtxdist[0] = 0; 224*abe9303eSLisandro Dalcin ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr); 225*abe9303eSLisandro Dalcin for (p = 2; p <= size; ++p) { 226*abe9303eSLisandro Dalcin hasempty = (PetscBool)(hasempty || !vtxdist[p-1] || !vtxdist[p]); 227*abe9303eSLisandro Dalcin vtxdist[p] += vtxdist[p-1]; 228*abe9303eSLisandro Dalcin } 229*abe9303eSLisandro Dalcin /* null graph */ 230*abe9303eSLisandro Dalcin if (vtxdist[size] == 0) { 231*abe9303eSLisandro Dalcin ierr = PetscFree2(vtxdist, assignment);CHKERRQ(ierr); 232*abe9303eSLisandro Dalcin ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 233*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 234*abe9303eSLisandro Dalcin } 235*abe9303eSLisandro Dalcin 236*abe9303eSLisandro Dalcin /* Calculate vertex weights */ 237*abe9303eSLisandro Dalcin if (vertSection) { 238*abe9303eSLisandro Dalcin ierr = PetscMalloc1(nvtxs,&vwgt);CHKERRQ(ierr); 239*abe9303eSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 240*abe9303eSLisandro Dalcin ierr = PetscSectionGetDof(vertSection, v, &vwgt[v]);CHKERRQ(ierr); 241*abe9303eSLisandro Dalcin } 242*abe9303eSLisandro Dalcin } 243*abe9303eSLisandro Dalcin 244*abe9303eSLisandro Dalcin /* Calculate partition weights */ 245*abe9303eSLisandro Dalcin if (targetSection) { 246*abe9303eSLisandro Dalcin PetscInt sumw; 247*abe9303eSLisandro Dalcin 248*abe9303eSLisandro Dalcin ierr = PetscCalloc1(nparts,&tpwgts);CHKERRQ(ierr); 249*abe9303eSLisandro Dalcin for (p = 0, sumw = 0; p < nparts; ++p) { 250*abe9303eSLisandro Dalcin ierr = PetscSectionGetDof(targetSection,p,&tpwgts[p]);CHKERRQ(ierr); 251*abe9303eSLisandro Dalcin sumw += tpwgts[p]; 252*abe9303eSLisandro Dalcin } 253*abe9303eSLisandro Dalcin if (!sumw) { 254*abe9303eSLisandro Dalcin ierr = PetscFree(tpwgts);CHKERRQ(ierr); 255*abe9303eSLisandro Dalcin } 256*abe9303eSLisandro Dalcin } 257*abe9303eSLisandro Dalcin 258*abe9303eSLisandro Dalcin { 259*abe9303eSLisandro Dalcin PetscPartitioner_PTScotch *pts = (PetscPartitioner_PTScotch *) part->data; 260*abe9303eSLisandro Dalcin int strat = PTScotch_Strategy(pts->strategy); 261*abe9303eSLisandro Dalcin double imbal = (double)pts->imbalance; 262*abe9303eSLisandro Dalcin 263*abe9303eSLisandro Dalcin for (p = 0; !vtxdist[p+1] && p < size; ++p); 264*abe9303eSLisandro Dalcin if (vtxdist[p+1] == vtxdist[size]) { 265*abe9303eSLisandro Dalcin if (rank == p) { 266*abe9303eSLisandro Dalcin ierr = PTScotch_PartGraph_Seq(strat, imbal, nvtxs, xadj, adjncy, vwgt, adjwgt, nparts, tpwgts, assignment);CHKERRQ(ierr); 267*abe9303eSLisandro Dalcin } 268*abe9303eSLisandro Dalcin } else { 269*abe9303eSLisandro Dalcin MPI_Comm pcomm = pts->pcomm; 270*abe9303eSLisandro Dalcin 271*abe9303eSLisandro Dalcin if (hasempty) { 272*abe9303eSLisandro Dalcin PetscInt cnt; 273*abe9303eSLisandro Dalcin 274*abe9303eSLisandro Dalcin ierr = MPI_Comm_split(pts->pcomm,!!nvtxs,rank,&pcomm);CHKERRQ(ierr); 275*abe9303eSLisandro Dalcin for (p=0,cnt=0;p<size;p++) { 276*abe9303eSLisandro Dalcin if (vtxdist[p+1] != vtxdist[p]) { 277*abe9303eSLisandro Dalcin vtxdist[cnt+1] = vtxdist[p+1]; 278*abe9303eSLisandro Dalcin cnt++; 279*abe9303eSLisandro Dalcin } 280*abe9303eSLisandro Dalcin } 281*abe9303eSLisandro Dalcin }; 282*abe9303eSLisandro Dalcin if (nvtxs) { 283*abe9303eSLisandro Dalcin ierr = PTScotch_PartGraph_MPI(strat, imbal, vtxdist, xadj, adjncy, vwgt, adjwgt, nparts, tpwgts, assignment, pcomm);CHKERRQ(ierr); 284*abe9303eSLisandro Dalcin } 285*abe9303eSLisandro Dalcin if (hasempty) { 286*abe9303eSLisandro Dalcin ierr = MPI_Comm_free(&pcomm);CHKERRQ(ierr); 287*abe9303eSLisandro Dalcin } 288*abe9303eSLisandro Dalcin } 289*abe9303eSLisandro Dalcin } 290*abe9303eSLisandro Dalcin ierr = PetscFree(vwgt);CHKERRQ(ierr); 291*abe9303eSLisandro Dalcin ierr = PetscFree(tpwgts);CHKERRQ(ierr); 292*abe9303eSLisandro Dalcin 293*abe9303eSLisandro Dalcin /* Convert to PetscSection+IS */ 294*abe9303eSLisandro Dalcin for (v = 0; v < nvtxs; ++v) {ierr = PetscSectionAddDof(partSection, assignment[v], 1);CHKERRQ(ierr);} 295*abe9303eSLisandro Dalcin ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr); 296*abe9303eSLisandro Dalcin for (p = 0, i = 0; p < nparts; ++p) { 297*abe9303eSLisandro Dalcin for (v = 0; v < nvtxs; ++v) { 298*abe9303eSLisandro Dalcin if (assignment[v] == p) points[i++] = v; 299*abe9303eSLisandro Dalcin } 300*abe9303eSLisandro Dalcin } 301*abe9303eSLisandro Dalcin if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 302*abe9303eSLisandro Dalcin ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 303*abe9303eSLisandro Dalcin 304*abe9303eSLisandro Dalcin ierr = PetscFree2(vtxdist,assignment);CHKERRQ(ierr); 305*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 306*abe9303eSLisandro Dalcin #else 307*abe9303eSLisandro Dalcin SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-ptscotch."); 308*abe9303eSLisandro Dalcin #endif 309*abe9303eSLisandro Dalcin } 310*abe9303eSLisandro Dalcin 311*abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_PTScotch(PetscPartitioner part) 312*abe9303eSLisandro Dalcin { 313*abe9303eSLisandro Dalcin PetscFunctionBegin; 314*abe9303eSLisandro Dalcin part->noGraph = PETSC_FALSE; 315*abe9303eSLisandro Dalcin part->ops->view = PetscPartitionerView_PTScotch; 316*abe9303eSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_PTScotch; 317*abe9303eSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_PTScotch; 318*abe9303eSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_PTScotch; 319*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 320*abe9303eSLisandro Dalcin } 321*abe9303eSLisandro Dalcin 322*abe9303eSLisandro Dalcin /*MC 323*abe9303eSLisandro Dalcin PETSCPARTITIONERPTSCOTCH = "ptscotch" - A PetscPartitioner object using the PT-Scotch library 324*abe9303eSLisandro Dalcin 325*abe9303eSLisandro Dalcin Level: intermediate 326*abe9303eSLisandro Dalcin 327*abe9303eSLisandro Dalcin Options Database Keys: 328*abe9303eSLisandro Dalcin + -petscpartitioner_ptscotch_strategy <string> - PT-Scotch strategy. Choose one of default quality speed balance safety scalability recursive remap 329*abe9303eSLisandro Dalcin - -petscpartitioner_ptscotch_imbalance <val> - Load imbalance ratio 330*abe9303eSLisandro Dalcin 331*abe9303eSLisandro Dalcin Notes: when the graph is on a single process, this partitioner actually uses Scotch and not PT-Scotch 332*abe9303eSLisandro Dalcin 333*abe9303eSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 334*abe9303eSLisandro Dalcin M*/ 335*abe9303eSLisandro Dalcin 336*abe9303eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_PTScotch(PetscPartitioner part) 337*abe9303eSLisandro Dalcin { 338*abe9303eSLisandro Dalcin PetscPartitioner_PTScotch *p; 339*abe9303eSLisandro Dalcin PetscErrorCode ierr; 340*abe9303eSLisandro Dalcin 341*abe9303eSLisandro Dalcin PetscFunctionBegin; 342*abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 343*abe9303eSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 344*abe9303eSLisandro Dalcin part->data = p; 345*abe9303eSLisandro Dalcin 346*abe9303eSLisandro Dalcin ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)part),&p->pcomm);CHKERRQ(ierr); 347*abe9303eSLisandro Dalcin p->strategy = 0; 348*abe9303eSLisandro Dalcin p->imbalance = 0.01; 349*abe9303eSLisandro Dalcin 350*abe9303eSLisandro Dalcin ierr = PetscPartitionerInitialize_PTScotch(part);CHKERRQ(ierr); 351*abe9303eSLisandro Dalcin ierr = PetscCitationsRegister(PTScotchPartitionerCitation, &PTScotchPartitionerCite);CHKERRQ(ierr); 352*abe9303eSLisandro Dalcin PetscFunctionReturn(0); 353*abe9303eSLisandro Dalcin } 354