xref: /petsc/src/dm/partitioner/impls/shell/partshell.c (revision d7cc930e14e615e9907267aaa472dd0ccceeab82)
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