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