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