1 static char help[] = "Tests PetscPartitioner.\n\n";
2
3 #include <petscpartitioner.h>
4
main(int argc,char ** argv)5 int main(int argc, char **argv)
6 {
7 PetscPartitioner p;
8 PetscSection partSection, vertexSection = NULL, targetSection = NULL;
9 IS partition, is;
10 PetscMPIInt size, rank;
11 PetscInt nparts, i;
12 PetscInt nv = 4;
13 PetscInt vv[5] = {0, 2, 4, 6, 8};
14 PetscInt vadj[8] = {3, 1, 0, 2, 1, 3, 2, 0};
15 PetscBool sequential;
16 PetscBool vwgts = PETSC_FALSE;
17 PetscBool pwgts = PETSC_FALSE;
18
19 PetscFunctionBeginUser;
20 PetscCall(PetscInitialize(&argc, &argv, NULL, help));
21 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
22 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
23 nparts = size;
24 PetscCall(PetscOptionsGetInt(NULL, NULL, "-nparts", &nparts, NULL));
25 PetscCall(PetscOptionsGetBool(NULL, NULL, "-vwgts", &vwgts, NULL));
26 PetscCall(PetscOptionsGetBool(NULL, NULL, "-pwgts", &pwgts, NULL));
27
28 /* create PetscPartitioner */
29 PetscCall(PetscPartitionerCreate(PETSC_COMM_WORLD, &p));
30 PetscCall(PetscPartitionerSetType(p, PETSCPARTITIONERSIMPLE));
31 PetscCall(PetscPartitionerSetFromOptions(p));
32
33 /* create partition section */
34 PetscCall(PetscSectionCreate(PETSC_COMM_WORLD, &partSection));
35
36 if (vwgts) { /* create vertex weights section */
37 PetscCall(PetscSectionCreate(PETSC_COMM_WORLD, &vertexSection));
38 PetscCall(PetscSectionSetChart(vertexSection, 0, nv));
39 for (i = 0; i < nv; i++) PetscCall(PetscSectionSetDof(vertexSection, i, 1));
40 PetscCall(PetscSectionSetUp(vertexSection));
41 }
42
43 if (pwgts) { /* create partition weights section */
44 PetscCall(PetscSectionCreate(PETSC_COMM_WORLD, &targetSection));
45 PetscCall(PetscSectionSetChart(targetSection, 0, nparts));
46 for (i = 0; i < nparts; i++) PetscCall(PetscSectionSetDof(targetSection, i, 1));
47 PetscCall(PetscSectionSetUp(targetSection));
48 }
49
50 if (PetscDefined(USE_LOG)) { /* Test logging */
51 PetscLogEvent event;
52
53 PetscCall(PetscLogEventRegister("MyPartitionerEvent", PETSCPARTITIONER_CLASSID, &event));
54 { /* PetscLogEventExcludeClass is broken, new events are not deactivated */
55 char logList[256];
56 PetscBool opt, pkg;
57
58 PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
59 if (opt) {
60 PetscCall(PetscStrInList("partitioner", logList, ',', &pkg));
61 if (pkg) PetscCall(PetscLogEventExcludeClass(PETSCPARTITIONER_CLASSID));
62 }
63 }
64 PetscCall(PetscLogEventBegin(event, p, NULL, NULL, NULL));
65 PetscCall(PetscLogEventEnd(event, p, NULL, NULL, NULL));
66 }
67
68 /* test setup and reset */
69 PetscCall(PetscPartitionerSetUp(p));
70 PetscCall(PetscPartitionerReset(p));
71
72 /* test partitioning an empty graph */
73 PetscCall(PetscPartitionerPartition(p, nparts, 0, NULL, NULL, vertexSection, NULL, targetSection, partSection, &partition));
74 PetscCall(PetscObjectSetName((PetscObject)partSection, "NULL SECTION"));
75 PetscCall(PetscSectionView(partSection, NULL));
76 PetscCall(ISOnComm(partition, PETSC_COMM_WORLD, PETSC_USE_POINTER, &is));
77 PetscCall(PetscObjectSetName((PetscObject)is, "NULL PARTITION"));
78 PetscCall(ISView(is, NULL));
79 PetscCall(ISDestroy(&is));
80 PetscCall(ISDestroy(&partition));
81
82 /* test view from options */
83 PetscCall(PetscPartitionerViewFromOptions(p, NULL, "-part_view"));
84
85 /* test partitioning a graph on one process only (not main) */
86 if (rank == size - 1) {
87 PetscCall(PetscPartitionerPartition(p, nparts, nv, vv, vadj, vertexSection, NULL, targetSection, partSection, &partition));
88 } else {
89 PetscCall(PetscPartitionerPartition(p, nparts, 0, NULL, NULL, vertexSection, NULL, targetSection, partSection, &partition));
90 }
91 PetscCall(PetscObjectSetName((PetscObject)partSection, "SEQ SECTION"));
92 PetscCall(PetscSectionView(partSection, NULL));
93 PetscCall(ISOnComm(partition, PETSC_COMM_WORLD, PETSC_USE_POINTER, &is));
94 PetscCall(PetscObjectSetName((PetscObject)is, "SEQ PARTITION"));
95 PetscCall(ISView(is, NULL));
96 PetscCall(ISDestroy(&is));
97 PetscCall(ISDestroy(&partition));
98
99 PetscCall(PetscObjectTypeCompareAny((PetscObject)p, &sequential, PETSCPARTITIONERCHACO, NULL));
100 if (sequential) goto finally;
101
102 /* test partitioning a graph on a subset of the processes only */
103 if (rank % 2) {
104 PetscCall(PetscPartitionerPartition(p, nparts, 0, NULL, NULL, NULL, NULL, targetSection, partSection, &partition));
105 } else {
106 PetscInt i, totv = nv * ((size + 1) / 2), *pvadj;
107
108 PetscCall(PetscMalloc1(2 * nv, &pvadj));
109 for (i = 0; i < nv; i++) {
110 pvadj[2 * i] = (nv * (rank / 2) + totv + i - 1) % totv;
111 pvadj[2 * i + 1] = (nv * (rank / 2) + totv + i + 1) % totv;
112 }
113 PetscCall(PetscPartitionerPartition(p, nparts, nv, vv, pvadj, NULL, NULL, targetSection, partSection, &partition));
114 PetscCall(PetscFree(pvadj));
115 }
116 PetscCall(PetscObjectSetName((PetscObject)partSection, "PARVOID SECTION"));
117 PetscCall(PetscSectionView(partSection, NULL));
118 PetscCall(ISOnComm(partition, PETSC_COMM_WORLD, PETSC_USE_POINTER, &is));
119 PetscCall(PetscObjectSetName((PetscObject)is, "PARVOID PARTITION"));
120 PetscCall(ISView(is, NULL));
121 PetscCall(ISDestroy(&is));
122 PetscCall(ISDestroy(&partition));
123
124 finally:
125 PetscCall(PetscSectionDestroy(&partSection));
126 PetscCall(PetscSectionDestroy(&vertexSection));
127 PetscCall(PetscSectionDestroy(&targetSection));
128 PetscCall(PetscPartitionerDestroy(&p));
129 PetscCall(PetscFinalize());
130 return 0;
131 }
132
133 /*TEST
134
135 test:
136 suffix: default
137
138 testset:
139 requires: defined(PETSC_USE_LOG)
140 args: -petscpartitioner_type simple -log_view
141 filter: grep MyPartitionerEvent | cut -d " " -f 1
142 test:
143 suffix: log_include
144 test:
145 suffix: log_exclude
146 args: -log_exclude partitioner
147 output_file: output/empty.out
148
149 test:
150 suffix: simple
151 nsize: {{1 2 3}separate output}
152 args: -nparts {{1 2 3}separate output} -pwgts {{false true}separate output} -petscpartitioner_type simple -petscpartitioner_view
153
154 test:
155 suffix: shell
156 nsize: {{1 2 3}separate output}
157 args: -nparts {{1 2 3}separate output} -petscpartitioner_type shell -petscpartitioner_shell_random -petscpartitioner_view
158
159 test:
160 suffix: gather
161 nsize: {{1 2 3}separate output}
162 args: -nparts {{1 2 3}separate output} -petscpartitioner_type gather -petscpartitioner_view -petscpartitioner_view_graph
163
164 test:
165 requires: parmetis
166 suffix: parmetis
167 nsize: {{1 2 3}separate output}
168 args: -nparts {{1 2 3}separate output} -pwgts {{false true}} -vwgts {{false true}}
169 args: -petscpartitioner_type parmetis -petscpartitioner_view -petscpartitioner_view_graph
170
171 test:
172 requires: parmetis
173 suffix: parmetis_type
174 nsize: {{1 2}}
175 args: -petscpartitioner_type parmetis -part_view
176 args: -petscpartitioner_parmetis_type {{kway rb}separate output}
177 filter: grep "ParMetis type"
178
179 test:
180 requires: ptscotch
181 suffix: ptscotch
182 nsize: {{1 2 3}separate output}
183 args: -nparts {{1 2 3}separate output} -pwgts {{false true}separate output} -vwgts {{false true}}
184 args: -petscpartitioner_type ptscotch -petscpartitioner_view -petscpartitioner_view_graph
185
186 test:
187 requires: ptscotch
188 suffix: ptscotch_strategy
189 nsize: {{1 2}}
190 args: -petscpartitioner_type ptscotch -part_view
191 args: -petscpartitioner_ptscotch_strategy {{DEFAULT QUALITY SPEED BALANCE SAFETY SCALABILITY RECURSIVE REMAP}separate output}
192 filter: grep "partitioning strategy"
193
194 test:
195 requires: chaco
196 suffix: chaco
197 nsize: {{1 2 3}separate output}
198 args: -nparts {{1}separate output} -petscpartitioner_type chaco -petscpartitioner_view -petscpartitioner_view_graph
199
200 test:
201 TODO: non reproducible (uses C stdlib rand())
202 requires: chaco
203 suffix: chaco
204 nsize: {{1 2 3}separate output}
205 args: -nparts {{2 3}separate output} -petscpartitioner_type chaco -petscpartitioner_view -petscpartitioner_view_graph
206
207 TEST*/
208