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 9abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerReset_Shell(PetscPartitioner part) 10abe9303eSLisandro Dalcin { 11abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 12abe9303eSLisandro Dalcin PetscErrorCode ierr; 13abe9303eSLisandro Dalcin 14abe9303eSLisandro Dalcin PetscFunctionBegin; 15abe9303eSLisandro Dalcin ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 16abe9303eSLisandro Dalcin ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 17abe9303eSLisandro Dalcin PetscFunctionReturn(0); 18abe9303eSLisandro Dalcin } 19abe9303eSLisandro Dalcin 20abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerDestroy_Shell(PetscPartitioner part) 21abe9303eSLisandro Dalcin { 22abe9303eSLisandro Dalcin PetscErrorCode ierr; 23abe9303eSLisandro Dalcin 24abe9303eSLisandro Dalcin PetscFunctionBegin; 25abe9303eSLisandro Dalcin ierr = PetscPartitionerReset_Shell(part);CHKERRQ(ierr); 26abe9303eSLisandro Dalcin ierr = PetscFree(part->data);CHKERRQ(ierr); 27abe9303eSLisandro Dalcin PetscFunctionReturn(0); 28abe9303eSLisandro Dalcin } 29abe9303eSLisandro Dalcin 30abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_Shell_ASCII(PetscPartitioner part, PetscViewer viewer) 31abe9303eSLisandro Dalcin { 32abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 33abe9303eSLisandro Dalcin PetscErrorCode ierr; 34abe9303eSLisandro Dalcin 35abe9303eSLisandro Dalcin PetscFunctionBegin; 36abe9303eSLisandro Dalcin if (p->random) { 37abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 38abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPrintf(viewer, "using random partition\n");CHKERRQ(ierr); 39abe9303eSLisandro Dalcin ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 40abe9303eSLisandro Dalcin } 41abe9303eSLisandro Dalcin PetscFunctionReturn(0); 42abe9303eSLisandro Dalcin } 43abe9303eSLisandro Dalcin 44abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerView_Shell(PetscPartitioner part, PetscViewer viewer) 45abe9303eSLisandro Dalcin { 46abe9303eSLisandro Dalcin PetscBool iascii; 47abe9303eSLisandro Dalcin PetscErrorCode ierr; 48abe9303eSLisandro Dalcin 49abe9303eSLisandro Dalcin PetscFunctionBegin; 50abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 51abe9303eSLisandro Dalcin PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 52abe9303eSLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 53abe9303eSLisandro Dalcin if (iascii) {ierr = PetscPartitionerView_Shell_ASCII(part, viewer);CHKERRQ(ierr);} 54abe9303eSLisandro Dalcin PetscFunctionReturn(0); 55abe9303eSLisandro Dalcin } 56abe9303eSLisandro Dalcin 57abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerSetFromOptions_Shell(PetscOptionItems *PetscOptionsObject, PetscPartitioner part) 58abe9303eSLisandro Dalcin { 59*d7cc930eSLisandro Dalcin PetscBool random = PETSC_FALSE, set; 60abe9303eSLisandro Dalcin PetscErrorCode ierr; 61abe9303eSLisandro Dalcin 62abe9303eSLisandro Dalcin PetscFunctionBegin; 63abe9303eSLisandro Dalcin ierr = PetscOptionsHead(PetscOptionsObject, "PetscPartitioner Shell Options");CHKERRQ(ierr); 64*d7cc930eSLisandro Dalcin ierr = PetscPartitionerShellGetRandom(part, &random);CHKERRQ(ierr); 65*d7cc930eSLisandro Dalcin ierr = PetscOptionsBool("-petscpartitioner_shell_random", "Use a random partition", "PetscPartitionerView", PETSC_FALSE, &random, &set);CHKERRQ(ierr); 66*d7cc930eSLisandro Dalcin if (set) {ierr = PetscPartitionerShellSetRandom(part, random);CHKERRQ(ierr);} 67abe9303eSLisandro Dalcin ierr = PetscOptionsTail();CHKERRQ(ierr); 68abe9303eSLisandro Dalcin PetscFunctionReturn(0); 69abe9303eSLisandro Dalcin } 70abe9303eSLisandro Dalcin 71abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerPartition_Shell(PetscPartitioner part, PetscInt nparts, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection vertSection, PetscSection targetSection, PetscSection partSection, IS *partition) 72abe9303eSLisandro Dalcin { 73abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 74abe9303eSLisandro Dalcin PetscInt np; 75abe9303eSLisandro Dalcin PetscErrorCode ierr; 76abe9303eSLisandro Dalcin 77abe9303eSLisandro Dalcin PetscFunctionBegin; 78abe9303eSLisandro Dalcin if (p->random) { 79abe9303eSLisandro Dalcin PetscRandom r; 80abe9303eSLisandro Dalcin PetscInt *sizes, *points, v, p; 81abe9303eSLisandro Dalcin PetscMPIInt rank; 82abe9303eSLisandro Dalcin 83abe9303eSLisandro Dalcin ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) part), &rank);CHKERRQ(ierr); 84abe9303eSLisandro Dalcin ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 85abe9303eSLisandro Dalcin ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) nparts);CHKERRQ(ierr); 86abe9303eSLisandro Dalcin ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); 87abe9303eSLisandro Dalcin ierr = PetscCalloc2(nparts, &sizes, numVertices, &points);CHKERRQ(ierr); 88abe9303eSLisandro Dalcin for (v = 0; v < numVertices; ++v) {points[v] = v;} 89abe9303eSLisandro Dalcin for (p = 0; p < nparts; ++p) {sizes[p] = numVertices/nparts + (PetscInt) (p < numVertices % nparts);} 90abe9303eSLisandro Dalcin for (v = numVertices-1; v > 0; --v) { 91abe9303eSLisandro Dalcin PetscReal val; 92abe9303eSLisandro Dalcin PetscInt w, tmp; 93abe9303eSLisandro Dalcin 94abe9303eSLisandro Dalcin ierr = PetscRandomSetInterval(r, 0.0, (PetscScalar) (v+1));CHKERRQ(ierr); 95abe9303eSLisandro Dalcin ierr = PetscRandomGetValueReal(r, &val);CHKERRQ(ierr); 96abe9303eSLisandro Dalcin w = PetscFloorReal(val); 97abe9303eSLisandro Dalcin tmp = points[v]; 98abe9303eSLisandro Dalcin points[v] = points[w]; 99abe9303eSLisandro Dalcin points[w] = tmp; 100abe9303eSLisandro Dalcin } 101abe9303eSLisandro Dalcin ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); 102abe9303eSLisandro Dalcin ierr = PetscPartitionerShellSetPartition(part, nparts, sizes, points);CHKERRQ(ierr); 103abe9303eSLisandro Dalcin ierr = PetscFree2(sizes, points);CHKERRQ(ierr); 104abe9303eSLisandro Dalcin } 105abe9303eSLisandro Dalcin if (!p->section) SETERRQ(PetscObjectComm((PetscObject) part), PETSC_ERR_ARG_WRONG, "Shell partitioner information not provided. Please call PetscPartitionerShellSetPartition()"); 106abe9303eSLisandro Dalcin ierr = PetscSectionGetChart(p->section, NULL, &np);CHKERRQ(ierr); 107abe9303eSLisandro Dalcin if (nparts != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of requested partitions %d != configured partitions %d", nparts, np); 108abe9303eSLisandro Dalcin ierr = ISGetLocalSize(p->partition, &np);CHKERRQ(ierr); 109abe9303eSLisandro Dalcin if (numVertices != np) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input vertices %d != configured vertices %d", numVertices, np); 110abe9303eSLisandro Dalcin ierr = PetscSectionCopy(p->section, partSection);CHKERRQ(ierr); 111abe9303eSLisandro Dalcin *partition = p->partition; 112abe9303eSLisandro Dalcin ierr = PetscObjectReference((PetscObject) p->partition);CHKERRQ(ierr); 113abe9303eSLisandro Dalcin PetscFunctionReturn(0); 114abe9303eSLisandro Dalcin } 115abe9303eSLisandro Dalcin 116abe9303eSLisandro Dalcin static PetscErrorCode PetscPartitionerInitialize_Shell(PetscPartitioner part) 117abe9303eSLisandro Dalcin { 118abe9303eSLisandro Dalcin PetscFunctionBegin; 119abe9303eSLisandro Dalcin part->noGraph = PETSC_TRUE; /* PetscPartitionerShell cannot overload the partition call, so it is safe for now */ 120abe9303eSLisandro Dalcin part->ops->view = PetscPartitionerView_Shell; 121abe9303eSLisandro Dalcin part->ops->setfromoptions = PetscPartitionerSetFromOptions_Shell; 122abe9303eSLisandro Dalcin part->ops->reset = PetscPartitionerReset_Shell; 123abe9303eSLisandro Dalcin part->ops->destroy = PetscPartitionerDestroy_Shell; 124abe9303eSLisandro Dalcin part->ops->partition = PetscPartitionerPartition_Shell; 125abe9303eSLisandro Dalcin PetscFunctionReturn(0); 126abe9303eSLisandro Dalcin } 127abe9303eSLisandro Dalcin 128abe9303eSLisandro Dalcin /*MC 129abe9303eSLisandro Dalcin PETSCPARTITIONERSHELL = "shell" - A PetscPartitioner object 130abe9303eSLisandro Dalcin 131abe9303eSLisandro Dalcin Level: intermediate 132abe9303eSLisandro Dalcin 133abe9303eSLisandro Dalcin Options Database Keys: 134abe9303eSLisandro Dalcin . -petscpartitioner_shell_random - Use a random partition 135abe9303eSLisandro Dalcin 136abe9303eSLisandro Dalcin .seealso: PetscPartitionerType, PetscPartitionerCreate(), PetscPartitionerSetType() 137abe9303eSLisandro Dalcin M*/ 138abe9303eSLisandro Dalcin 139abe9303eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscPartitionerCreate_Shell(PetscPartitioner part) 140abe9303eSLisandro Dalcin { 141abe9303eSLisandro Dalcin PetscPartitioner_Shell *p; 142abe9303eSLisandro Dalcin PetscErrorCode ierr; 143abe9303eSLisandro Dalcin 144abe9303eSLisandro Dalcin PetscFunctionBegin; 145abe9303eSLisandro Dalcin PetscValidHeaderSpecific(part, PETSCPARTITIONER_CLASSID, 1); 146abe9303eSLisandro Dalcin ierr = PetscNewLog(part, &p);CHKERRQ(ierr); 147abe9303eSLisandro Dalcin part->data = p; 148abe9303eSLisandro Dalcin 149abe9303eSLisandro Dalcin ierr = PetscPartitionerInitialize_Shell(part);CHKERRQ(ierr); 150abe9303eSLisandro Dalcin p->random = PETSC_FALSE; 151abe9303eSLisandro Dalcin PetscFunctionReturn(0); 152abe9303eSLisandro Dalcin } 153abe9303eSLisandro Dalcin 154abe9303eSLisandro Dalcin /*@C 155abe9303eSLisandro Dalcin PetscPartitionerShellSetPartition - Set an artifical partition for a mesh 156abe9303eSLisandro Dalcin 157abe9303eSLisandro Dalcin Collective on PetscPartitioner 158abe9303eSLisandro Dalcin 159abe9303eSLisandro Dalcin Input Parameters: 160abe9303eSLisandro Dalcin + part - The PetscPartitioner 161abe9303eSLisandro Dalcin . size - The number of partitions 162abe9303eSLisandro Dalcin . sizes - array of length size (or NULL) providing the number of points in each partition 163abe9303eSLisandro Dalcin - 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.) 164abe9303eSLisandro Dalcin 165abe9303eSLisandro Dalcin Level: developer 166abe9303eSLisandro Dalcin 167abe9303eSLisandro Dalcin Notes: 168abe9303eSLisandro Dalcin It is safe to free the sizes and points arrays after use in this routine. 169abe9303eSLisandro Dalcin 170abe9303eSLisandro Dalcin .seealso DMPlexDistribute(), PetscPartitionerCreate() 171abe9303eSLisandro Dalcin @*/ 172abe9303eSLisandro Dalcin PetscErrorCode PetscPartitionerShellSetPartition(PetscPartitioner part, PetscInt size, const PetscInt sizes[], const PetscInt points[]) 173abe9303eSLisandro Dalcin { 174abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 175abe9303eSLisandro Dalcin PetscInt proc, numPoints; 176abe9303eSLisandro Dalcin PetscErrorCode ierr; 177abe9303eSLisandro Dalcin 178abe9303eSLisandro Dalcin PetscFunctionBegin; 179abe9303eSLisandro Dalcin PetscValidHeaderSpecificType(part, PETSCPARTITIONER_CLASSID, 1, PETSCPARTITIONERSHELL); 180abe9303eSLisandro Dalcin if (sizes) {PetscValidPointer(sizes, 3);} 181abe9303eSLisandro Dalcin if (points) {PetscValidPointer(points, 4);} 182abe9303eSLisandro Dalcin ierr = PetscSectionDestroy(&p->section);CHKERRQ(ierr); 183abe9303eSLisandro Dalcin ierr = ISDestroy(&p->partition);CHKERRQ(ierr); 184abe9303eSLisandro Dalcin ierr = PetscSectionCreate(PetscObjectComm((PetscObject) part), &p->section);CHKERRQ(ierr); 185abe9303eSLisandro Dalcin ierr = PetscSectionSetChart(p->section, 0, size);CHKERRQ(ierr); 186abe9303eSLisandro Dalcin if (sizes) { 187abe9303eSLisandro Dalcin for (proc = 0; proc < size; ++proc) { 188abe9303eSLisandro Dalcin ierr = PetscSectionSetDof(p->section, proc, sizes[proc]);CHKERRQ(ierr); 189abe9303eSLisandro Dalcin } 190abe9303eSLisandro Dalcin } 191abe9303eSLisandro Dalcin ierr = PetscSectionSetUp(p->section);CHKERRQ(ierr); 192abe9303eSLisandro Dalcin ierr = PetscSectionGetStorageSize(p->section, &numPoints);CHKERRQ(ierr); 193abe9303eSLisandro Dalcin ierr = ISCreateGeneral(PetscObjectComm((PetscObject) part), numPoints, points, PETSC_COPY_VALUES, &p->partition);CHKERRQ(ierr); 194abe9303eSLisandro Dalcin PetscFunctionReturn(0); 195abe9303eSLisandro Dalcin } 196abe9303eSLisandro Dalcin 197abe9303eSLisandro Dalcin /*@ 198abe9303eSLisandro Dalcin PetscPartitionerShellSetRandom - Set the flag to use a random partition 199abe9303eSLisandro Dalcin 200abe9303eSLisandro Dalcin Collective on PetscPartitioner 201abe9303eSLisandro Dalcin 202abe9303eSLisandro Dalcin Input Parameters: 203abe9303eSLisandro Dalcin + part - The PetscPartitioner 204abe9303eSLisandro Dalcin - random - The flag to use a random partition 205abe9303eSLisandro Dalcin 206abe9303eSLisandro Dalcin Level: intermediate 207abe9303eSLisandro Dalcin 208abe9303eSLisandro Dalcin .seealso PetscPartitionerShellGetRandom(), PetscPartitionerCreate() 209abe9303eSLisandro Dalcin @*/ 210abe9303eSLisandro Dalcin PetscErrorCode PetscPartitionerShellSetRandom(PetscPartitioner part, PetscBool random) 211abe9303eSLisandro Dalcin { 212abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 213abe9303eSLisandro Dalcin 214abe9303eSLisandro Dalcin PetscFunctionBegin; 215abe9303eSLisandro Dalcin PetscValidHeaderSpecificType(part, PETSCPARTITIONER_CLASSID, 1, PETSCPARTITIONERSHELL); 216abe9303eSLisandro Dalcin p->random = random; 217abe9303eSLisandro Dalcin PetscFunctionReturn(0); 218abe9303eSLisandro Dalcin } 219abe9303eSLisandro Dalcin 220abe9303eSLisandro Dalcin /*@ 221abe9303eSLisandro Dalcin PetscPartitionerShellGetRandom - get the flag to use a random partition 222abe9303eSLisandro Dalcin 223abe9303eSLisandro Dalcin Collective on PetscPartitioner 224abe9303eSLisandro Dalcin 225abe9303eSLisandro Dalcin Input Parameter: 226abe9303eSLisandro Dalcin . part - The PetscPartitioner 227abe9303eSLisandro Dalcin 228abe9303eSLisandro Dalcin Output Parameter: 229abe9303eSLisandro Dalcin . random - The flag to use a random partition 230abe9303eSLisandro Dalcin 231abe9303eSLisandro Dalcin Level: intermediate 232abe9303eSLisandro Dalcin 233abe9303eSLisandro Dalcin .seealso PetscPartitionerShellSetRandom(), PetscPartitionerCreate() 234abe9303eSLisandro Dalcin @*/ 235abe9303eSLisandro Dalcin PetscErrorCode PetscPartitionerShellGetRandom(PetscPartitioner part, PetscBool *random) 236abe9303eSLisandro Dalcin { 237abe9303eSLisandro Dalcin PetscPartitioner_Shell *p = (PetscPartitioner_Shell *) part->data; 238abe9303eSLisandro Dalcin 239abe9303eSLisandro Dalcin PetscFunctionBegin; 240abe9303eSLisandro Dalcin PetscValidHeaderSpecificType(part, PETSCPARTITIONER_CLASSID, 1, PETSCPARTITIONERSHELL); 241abe9303eSLisandro Dalcin PetscValidPointer(random, 2); 242abe9303eSLisandro Dalcin *random = p->random; 243abe9303eSLisandro Dalcin PetscFunctionReturn(0); 244abe9303eSLisandro Dalcin } 245