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
PetscPartitionerReset_Shell(PetscPartitioner part)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
PetscPartitionerDestroy_Shell(PetscPartitioner part)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
PetscPartitionerView_Shell_ASCII(PetscPartitioner part,PetscViewer viewer)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
PetscPartitionerView_Shell(PetscPartitioner part,PetscViewer viewer)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
PetscPartitionerSetFromOptions_Shell(PetscOptionItems * PetscOptionsObject,PetscPartitioner part)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
PetscPartitionerPartition_Shell(PetscPartitioner part,PetscInt nparts,PetscInt numVertices,PetscInt start[],PetscInt adjacency[],PetscSection vertSection,PetscSection targetSection,PetscSection partSection,IS * partition)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);CHKERRQ(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
PetscPartitionerInitialize_Shell(PetscPartitioner part)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
PetscPartitionerCreate_Shell(PetscPartitioner part)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 @*/
PetscPartitionerShellSetPartition(PetscPartitioner part,PetscInt size,const PetscInt sizes[],const PetscInt points[])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 @*/
PetscPartitionerShellSetRandom(PetscPartitioner part,PetscBool random)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 @*/
PetscPartitionerShellGetRandom(PetscPartitioner part,PetscBool * random)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