1abe9303eSLisandro Dalcin #include <petsc/private/partitionerimpl.h> /*I "petscpartitioner.h" I*/ 2abe9303eSLisandro Dalcin 3abe9303eSLisandro Dalcin typedef struct { 4abe9303eSLisandro Dalcin PetscSection section; /* Sizes for each partition */ 5abe9303eSLisandro Dalcin IS partition; /* Points in each partition */ 6abe9303eSLisandro Dalcin PetscBool random; /* Flag for a random partition */ 7abe9303eSLisandro Dalcin } PetscPartitioner_Shell; 8abe9303eSLisandro Dalcin 9d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerReset_Shell(PetscPartitioner part) 10d71ae5a4SJacob Faibussowitsch { 11abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *)part->data; 12abe9303eSLisandro Dalcin 13abe9303eSLisandro Dalcin PetscFunctionBegin; 149566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&p->section)); 159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&p->partition)); 163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17abe9303eSLisandro Dalcin } 18abe9303eSLisandro Dalcin 19d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 20d71ae5a4SJacob Faibussowitsch { 21abe9303eSLisandro Dalcin PetscFunctionBegin; 229566063dSJacob Faibussowitsch PetscCall(PetscPartitionerReset_Shell(part)); 239566063dSJacob Faibussowitsch PetscCall(PetscFree(part->data)); 243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25abe9303eSLisandro Dalcin } 26abe9303eSLisandro Dalcin 27d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerView_Shell_ASCII(PetscPartitioner part, PetscViewer viewer) 28d71ae5a4SJacob Faibussowitsch { 29abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *)part->data; 30abe9303eSLisandro Dalcin 31abe9303eSLisandro Dalcin PetscFunctionBegin; 32abe9303eSLisandro Dalcin if (p->random) { 339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "using random partition\n")); 359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 36abe9303eSLisandro Dalcin } 373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38abe9303eSLisandro Dalcin } 39abe9303eSLisandro Dalcin 40d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 41d71ae5a4SJacob Faibussowitsch { 42abe9303eSLisandro Dalcin PetscBool iascii; 43abe9303eSLisandro Dalcin 44abe9303eSLisandro Dalcin PetscFunctionBegin; 45abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 46abe9303eSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 489566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscPartitionerView_Shell_ASCII(part, viewer)); 493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50abe9303eSLisandro Dalcin } 51abe9303eSLisandro Dalcin 52d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscPartitioner part, PetscOptionItems *PetscOptionsObject) 53d71ae5a4SJacob Faibussowitsch { 54*6166d6f7SMatthew G. Knepley PetscInt sizes[16], points[1024]; 55*6166d6f7SMatthew G. Knepley PetscInt Npart = 16, Npoints = 1024; 56*6166d6f7SMatthew G. Knepley PetscBool random = PETSC_FALSE, set, flgSizes, flgPoints; 57*6166d6f7SMatthew G. Knepley PetscMPIInt rank; 58abe9303eSLisandro Dalcin 59abe9303eSLisandro Dalcin PetscFunctionBegin; 60*6166d6f7SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)part), &rank)); 61d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "PetscPartitioner Shell Options"); 629566063dSJacob Faibussowitsch PetscCall(PetscPartitionerShellGetRandom(part, &random)); 639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &random, &set)); 649566063dSJacob Faibussowitsch if (set) PetscCall(PetscPartitionerShellSetRandom(part, random)); 65*6166d6f7SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-petscpartitioner_shell_sizes", "The size of each partition on rank 0", "PetscPartitionerShellSetPartition", sizes, &Npart, &flgSizes)); 66*6166d6f7SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-petscpartitioner_shell_points", "The points in each partition on rank 0", "PetscPartitionerShellSetPartition", points, &Npoints, &flgPoints)); 67*6166d6f7SMatthew G. Knepley PetscCheck(!(flgSizes ^ flgPoints), PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_WRONG, "Must specify both the partition sizes and points"); 68*6166d6f7SMatthew G. Knepley if (flgSizes) { 69*6166d6f7SMatthew G. Knepley PetscInt Np = 0; 70*6166d6f7SMatthew G. Knepley 71*6166d6f7SMatthew G. Knepley for (PetscInt i = 0; i < Npart; ++i) Np += sizes[i]; 72*6166d6f7SMatthew G. Knepley PetscCheck(Np == Npoints, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_WRONG, "Number of input points %" PetscInt_FMT " != %" PetscInt_FMT " sum of partition sizes", Npoints, Np); 73*6166d6f7SMatthew G. Knepley if (!rank) PetscCall(PetscPartitionerShellSetPartition(part, Npart, sizes, points)); 74*6166d6f7SMatthew G. Knepley else { 75*6166d6f7SMatthew G. Knepley PetscCall(PetscArrayzero(sizes, Npart)); 76*6166d6f7SMatthew G. Knepley PetscCall(PetscPartitionerShellSetPartition(part, Npart, sizes, points)); 77*6166d6f7SMatthew G. Knepley } 78*6166d6f7SMatthew G. Knepley } 79d0609cedSBarry Smith PetscOptionsHeadEnd(); 803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81abe9303eSLisandro Dalcin } 82abe9303eSLisandro Dalcin 8321c92275SMatthew G. Knepley static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection edgeSection, PetscSection targetSection, PetscSection partSection, IS *partition) 84d71ae5a4SJacob Faibussowitsch { 85abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *)part->data; 86abe9303eSLisandro Dalcin PetscInt np; 87abe9303eSLisandro Dalcin 88abe9303eSLisandro Dalcin PetscFunctionBegin; 89abe9303eSLisandro Dalcin if (p->random) { 90abe9303eSLisandro Dalcin PetscRandom r; 91abe9303eSLisandro Dalcin PetscInt *sizes, *points, v, p; 92abe9303eSLisandro Dalcin PetscMPIInt rank; 93abe9303eSLisandro Dalcin 949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)part), &rank)); 959566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r)); 969566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0.0, (PetscScalar)nparts)); 979566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(r)); 989566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nparts, &sizes, numVertices, &points)); 99ad540459SPierre Jolivet for (v = 0; v < numVertices; ++v) points[v] = v; 100ad540459SPierre Jolivet for (p = 0; p < nparts; ++p) sizes[p] = numVertices / nparts + (PetscInt)(p < numVertices % nparts); 101abe9303eSLisandro Dalcin for (v = numVertices - 1; v > 0; --v) { 102abe9303eSLisandro Dalcin PetscReal val; 103abe9303eSLisandro Dalcin PetscInt w, tmp; 104abe9303eSLisandro Dalcin 1059566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0.0, (PetscScalar)(v + 1))); 1069566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValueReal(r, &val)); 107abe9303eSLisandro Dalcin w = PetscFloorReal(val); 108abe9303eSLisandro Dalcin tmp = points[v]; 109abe9303eSLisandro Dalcin points[v] = points[w]; 110abe9303eSLisandro Dalcin points[w] = tmp; 111abe9303eSLisandro Dalcin } 1129566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r)); 1139566063dSJacob Faibussowitsch PetscCall(PetscPartitionerShellSetPartition(part, nparts, sizes, points)); 1149566063dSJacob Faibussowitsch PetscCall(PetscFree2(sizes, points)); 115abe9303eSLisandro Dalcin } 11628b400f6SJacob Faibussowitsch PetscCheck(p->section, PetscObjectComm((PetscObject)part), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 1179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(p->section, NULL, &np)); 11863a3b9bcSJacob Faibussowitsch PetscCheck(nparts == np, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %" PetscInt_FMT " != configured partitions %" PetscInt_FMT, nparts, np); 1199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(p->partition, &np)); 12063a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == np, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %" PetscInt_FMT " != configured vertices %" PetscInt_FMT, numVertices, np); 1219566063dSJacob Faibussowitsch PetscCall(PetscSectionCopy(p->section, partSection)); 122abe9303eSLisandro Dalcin *partition = p->partition; 1239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)p->partition)); 1243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 125abe9303eSLisandro Dalcin } 126abe9303eSLisandro Dalcin 127d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 128d71ae5a4SJacob Faibussowitsch { 129abe9303eSLisandro Dalcin PetscFunctionBegin; 130abe9303eSLisandro Dalcin part->noGraph = PETSC_TRUE; /* PetscPartitionerShell cannot overload the partition call, so it is safe for now */ 131abe9303eSLisandro Dalcin part->ops->view = PetscPartitionerView_Shell; 132abe9303eSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 133abe9303eSLisandro Dalcin part->ops->reset = PetscPartitionerReset_Shell; 134abe9303eSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_Shell; 135abe9303eSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_Shell; 1363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 137abe9303eSLisandro Dalcin } 138abe9303eSLisandro Dalcin 139abe9303eSLisandro Dalcin /*MC 140abe9303eSLisandro Dalcin PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 141abe9303eSLisandro Dalcin 142abe9303eSLisandro Dalcin Level: intermediate 143abe9303eSLisandro Dalcin 144abe9303eSLisandro Dalcin Options Database Keys: 145abe9303eSLisandro Dalcin . -petscpartitioner_shell_random - Use a random partition 146abe9303eSLisandro Dalcin 147db781477SPatrick Sanan .seealso: `PetscPartitionerType`, `PetscPartitionerCreate()`, `PetscPartitionerSetType()` 148abe9303eSLisandro Dalcin M*/ 149abe9303eSLisandro Dalcin 150d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 151d71ae5a4SJacob Faibussowitsch { 152abe9303eSLisandro Dalcin PetscPartitioner_Shell *p; 153abe9303eSLisandro Dalcin 154abe9303eSLisandro Dalcin PetscFunctionBegin; 155abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 1564dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&p)); 157abe9303eSLisandro Dalcin part->data = p; 158abe9303eSLisandro Dalcin 1599566063dSJacob Faibussowitsch PetscCall(PetscPartitionerInitialize_Shell(part)); 160abe9303eSLisandro Dalcin p->random = PETSC_FALSE; 1613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 162abe9303eSLisandro Dalcin } 163abe9303eSLisandro Dalcin 164abe9303eSLisandro Dalcin /*@C 16535cb6cd3SPierre Jolivet PetscPartitionerShellSetPartition - Set an artificial partition for a mesh 166abe9303eSLisandro Dalcin 16720f4b53cSBarry Smith Collective 168abe9303eSLisandro Dalcin 169abe9303eSLisandro Dalcin Input Parameters: 17020f4b53cSBarry Smith + part - The `PetscPartitioner` 171abe9303eSLisandro Dalcin . size - The number of partitions 17220f4b53cSBarry Smith . sizes - array of length size (or `NULL`) providing the number of points in each partition 17320f4b53cSBarry Smith - points - array of length sum(sizes) (may be `NULL` iff sizes is `NULL`), a permutation of the points that groups those assigned to each partition in order (i.e., partition 0 first, partition 1 next, etc.) 174abe9303eSLisandro Dalcin 175abe9303eSLisandro Dalcin Level: developer 176abe9303eSLisandro Dalcin 17720f4b53cSBarry Smith Note: 178abe9303eSLisandro Dalcin It is safe to free the sizes and points arrays after use in this routine. 179abe9303eSLisandro Dalcin 180a4e35b19SJacob Faibussowitsch .seealso: `DMPlexDistribute()`, `PetscPartitionerCreate()` 181abe9303eSLisandro Dalcin @*/ 182d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 183d71ae5a4SJacob Faibussowitsch { 184abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *)part->data; 185abe9303eSLisandro Dalcin PetscInt proc, numPoints; 186abe9303eSLisandro Dalcin 187abe9303eSLisandro Dalcin PetscFunctionBegin; 188abe9303eSLisandro Dalcin PetscValidHeaderSpecificType(part, PETSCPARTITIONER_CLASSID, 1, PETSCPARTITIONERSHELL); 1894f572ea9SToby Isaac if (sizes) PetscAssertPointer(sizes, 3); 1904f572ea9SToby Isaac if (points) PetscAssertPointer(points, 4); 1919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&p->section)); 1929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&p->partition)); 1939566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)part), &p->section)); 1949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(p->section, 0, size)); 195abe9303eSLisandro Dalcin if (sizes) { 19648a46eb9SPierre Jolivet for (proc = 0; proc < size; ++proc) PetscCall(PetscSectionSetDof(p->section, proc, sizes[proc])); 197abe9303eSLisandro Dalcin } 1989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(p->section)); 1999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(p->section, &numPoints)); 2009566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)part), numPoints, points, PETSC_COPY_VALUES, &p->partition)); 2013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 202abe9303eSLisandro Dalcin } 203abe9303eSLisandro Dalcin 204abe9303eSLisandro Dalcin /*@ 205abe9303eSLisandro Dalcin PetscPartitionerShellSetRandom - Set the flag to use a random partition 206abe9303eSLisandro Dalcin 20720f4b53cSBarry Smith Collective 208abe9303eSLisandro Dalcin 209abe9303eSLisandro Dalcin Input Parameters: 21020f4b53cSBarry Smith + part - The `PetscPartitioner` 211abe9303eSLisandro Dalcin - random - The flag to use a random partition 212abe9303eSLisandro Dalcin 213abe9303eSLisandro Dalcin Level: intermediate 214abe9303eSLisandro Dalcin 215a4e35b19SJacob Faibussowitsch .seealso: `PetscPartitionerShellGetRandom()`, `PetscPartitionerCreate()` 216abe9303eSLisandro Dalcin @*/ 217d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 218d71ae5a4SJacob Faibussowitsch { 219abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *)part->data; 220abe9303eSLisandro Dalcin 221abe9303eSLisandro Dalcin PetscFunctionBegin; 222abe9303eSLisandro Dalcin PetscValidHeaderSpecificType(part, PETSCPARTITIONER_CLASSID, 1, PETSCPARTITIONERSHELL); 223abe9303eSLisandro Dalcin p->random = random; 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225abe9303eSLisandro Dalcin } 226abe9303eSLisandro Dalcin 227abe9303eSLisandro Dalcin /*@ 228abe9303eSLisandro Dalcin PetscPartitionerShellGetRandom - get the flag to use a random partition 229abe9303eSLisandro Dalcin 23020f4b53cSBarry Smith Collective 231abe9303eSLisandro Dalcin 232abe9303eSLisandro Dalcin Input Parameter: 23320f4b53cSBarry Smith . part - The `PetscPartitioner` 234abe9303eSLisandro Dalcin 235abe9303eSLisandro Dalcin Output Parameter: 236abe9303eSLisandro Dalcin . random - The flag to use a random partition 237abe9303eSLisandro Dalcin 238abe9303eSLisandro Dalcin Level: intermediate 239abe9303eSLisandro Dalcin 240a4e35b19SJacob Faibussowitsch .seealso: `PetscPartitionerShellSetRandom()`, `PetscPartitionerCreate()` 241abe9303eSLisandro Dalcin @*/ 242d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 243d71ae5a4SJacob Faibussowitsch { 244abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *)part->data; 245abe9303eSLisandro Dalcin 246abe9303eSLisandro Dalcin PetscFunctionBegin; 247abe9303eSLisandro Dalcin PetscValidHeaderSpecificType(part, PETSCPARTITIONER_CLASSID, 1, PETSCPARTITIONERSHELL); 2484f572ea9SToby Isaac PetscAssertPointer(random, 2); 249abe9303eSLisandro Dalcin *random = p->random; 2503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 251abe9303eSLisandro Dalcin } 252