xref: /petsc/src/sys/tests/ex62.c (revision 98d129c30f3ee9fdddc40fdbc5a989b7be64f888)
1 static char help[] = "Tests `PetscGarbageKeySortedIntersect()`\n\n";
2 
3 #include <petscsys.h>
4 #include <petsc/private/garbagecollector.h>
5 
6 /* This program tests `PetscGarbageKeySortedIntersect(), which is the
7    public (MPI) interface to
8    `PetscErrorCode GarbageKeySortedIntersect_Private()`.
9    Sets are sent packed in arrays, with the first entry as the number of
10    set elements and the sets the remaining elements. This is because the
11    MPI reduction operation must have the call signature:
12    void PetscGarbageKeySortedIntersect(void *inset, void *inoutset, PetscMPIInt *length, MPI_Datatype *dtype)
13    This is a thin wrapper for the private routine:
14    PetscErrorCode GarbageKeySortedIntersect_Private(PetscInt64 seta[], PetscInt *lena, PetscInt64 setb[], PetscInt lenb)
15    Where
16    seta = (PetscInt64 *)inoutset;
17    setb = (PetscInt64 *)inset;
18    And the arguments are passed as:
19    &seta[1], (PetscInt *)&seta[0], &setb[1], (PetscInt)setb[0]
20 */
21 
22 /* Populate a set with upto the first 49 unique Fibonnaci numbers */
23 PetscErrorCode Fibonnaci(PetscInt64 **set, PetscInt n)
24 {
25   PetscInt   ii;
26   PetscInt64 fib[] = {1,        2,        3,        5,        8,         13,        21,        34,        55,        89,         144,        233,        377,        610,        987,        1597,    2584,
27                       4181,     6765,     10946,    17711,    28657,     46368,     75025,     121393,    196418,    317811,     514229,     832040,     1346269,    2178309,    3524578,    5702887, 9227465,
28                       14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025};
29 
30   PetscFunctionBeginUser;
31   PetscAssert((n < 50), PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "n must be less than 50");
32   PetscCall(PetscMalloc1(n + 1, set));
33   (*set)[0] = (PetscInt64)n;
34   for (ii = 0; ii < n; ii++) { (*set)[ii + 1] = fib[ii]; }
35   PetscFunctionReturn(PETSC_SUCCESS);
36 }
37 
38 /* Populate a set with Square numbers */
39 PetscErrorCode Square(PetscInt64 **set, PetscInt n)
40 {
41   PetscInt64 ii;
42 
43   PetscFunctionBeginUser;
44   PetscCall(PetscMalloc1(n + 1, set));
45   (*set)[0] = (PetscInt64)n;
46   for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii; }
47   PetscFunctionReturn(PETSC_SUCCESS);
48 }
49 
50 /* Populate a set with Cube numbers */
51 PetscErrorCode Cube(PetscInt64 **set, PetscInt n)
52 {
53   PetscInt64 ii;
54 
55   PetscFunctionBeginUser;
56   PetscCall(PetscMalloc1(n + 1, set));
57   (*set)[0] = (PetscInt64)n;
58   for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii; }
59   PetscFunctionReturn(PETSC_SUCCESS);
60 }
61 
62 /* Populate a set with numbers to sixth power */
63 PetscErrorCode Sixth(PetscInt64 **set, PetscInt n)
64 {
65   PetscInt64 ii;
66 
67   PetscFunctionBeginUser;
68   PetscCall(PetscMalloc1(n + 1, set));
69   (*set)[0] = (PetscInt64)n;
70   for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii * ii * ii * ii; }
71   PetscFunctionReturn(PETSC_SUCCESS);
72 }
73 
74 /* Print out the contents of a set */
75 PetscErrorCode PrintSet(PetscInt64 *set)
76 {
77   char     text[64];
78   PetscInt ii;
79 
80   PetscFunctionBeginUser;
81   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "["));
82   for (ii = 1; ii <= (PetscInt)set[0]; ii++) {
83     PetscCall(PetscFormatConvert(" %" PetscInt64_FMT ",", text));
84     PetscCall(PetscPrintf(PETSC_COMM_WORLD, text, set[ii]));
85   }
86   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
87   PetscFunctionReturn(PETSC_SUCCESS);
88 }
89 
90 /* Check set equality */
91 PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
92 {
93   PetscInt ii;
94 
95   PetscFunctionBeginUser;
96   PetscAssert((set[0] == true_set[0]), PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
97   for (ii = 1; ii < set[0] + 1; ii++) PetscAssert((set[ii] == true_set[ii]), PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets are different");
98   PetscFunctionReturn(PETSC_SUCCESS);
99 }
100 
101 /* Tests functionality when two enpty sets are passed */
102 PetscErrorCode test_empty_empty()
103 {
104   PetscInt64 *set_a, *set_b;
105   PetscInt64  truth[] = {0};
106   PetscMPIInt length  = 1;
107 
108   PetscFunctionBeginUser;
109   PetscCall(PetscMalloc1(1, &set_a));
110   PetscCall(PetscMalloc1(1, &set_b));
111 
112   set_a[0] = 0;
113 
114   set_b[0] = 0;
115 
116   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
117   PetscCall(PrintSet(set_a));
118   PetscCall(AssertSetsEqual(set_a, truth));
119 
120   PetscCall(PetscFree(set_a));
121   PetscCall(PetscFree(set_b));
122   PetscFunctionReturn(PETSC_SUCCESS);
123 }
124 
125 /* Tests functionality when seta is empty */
126 PetscErrorCode test_a_empty()
127 {
128   PetscInt64 *set_a, *set_b;
129   PetscInt64  truth[] = {0};
130   PetscMPIInt length  = 1;
131 
132   PetscFunctionBeginUser;
133   PetscCall(PetscMalloc1(1, &set_a));
134   PetscCall(PetscMalloc1(2, &set_b));
135 
136   set_a[0] = 0;
137 
138   set_b[0] = 1;
139   set_b[1] = 1;
140 
141   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
142   PetscCall(PrintSet(set_a));
143   PetscCall(AssertSetsEqual(set_a, truth));
144 
145   PetscCall(PetscFree(set_a));
146   PetscCall(PetscFree(set_b));
147   PetscFunctionReturn(PETSC_SUCCESS);
148 }
149 
150 /* Tests functionality when setb is empty */
151 PetscErrorCode test_b_empty()
152 {
153   PetscInt64 *set_a, *set_b;
154   PetscInt64  truth[] = {0};
155   PetscMPIInt length  = 1;
156 
157   PetscFunctionBeginUser;
158   PetscCall(PetscMalloc1(2, &set_a));
159   PetscCall(PetscMalloc1(1, &set_b));
160 
161   set_a[0] = 1;
162   set_a[1] = 1;
163 
164   set_b[0] = 0;
165 
166   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
167   PetscCall(PrintSet(set_a));
168   PetscCall(AssertSetsEqual(set_a, truth));
169 
170   PetscCall(PetscFree(set_a));
171   PetscCall(PetscFree(set_b));
172   PetscFunctionReturn(PETSC_SUCCESS);
173 }
174 
175 /* Tests functionality when both sets are identical */
176 PetscErrorCode test_identical()
177 {
178   PetscInt64 *set_a, *set_b;
179   PetscInt64  truth[] = {3, 1, 4, 9};
180   PetscMPIInt length  = 4;
181 
182   PetscFunctionBeginUser;
183   PetscCall(PetscMalloc1(4, &set_a));
184   PetscCall(PetscMalloc1(4, &set_b));
185 
186   set_a[0] = 3;
187   set_a[1] = 1;
188   set_a[2] = 4;
189   set_a[3] = 9;
190 
191   set_b[0] = 3;
192   set_b[1] = 1;
193   set_b[2] = 4;
194   set_b[3] = 9;
195 
196   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
197   PetscCall(PrintSet(set_a));
198   PetscCall(AssertSetsEqual(set_a, truth));
199 
200   PetscCall(PetscFree(set_a));
201   PetscCall(PetscFree(set_b));
202   PetscFunctionReturn(PETSC_SUCCESS);
203 }
204 
205 /* Tests functionality when sets have no elements in common */
206 PetscErrorCode test_disjoint()
207 {
208   PetscInt64 *set_a, *set_b;
209   PetscInt64  truth[] = {0};
210   PetscMPIInt length  = 1;
211 
212   PetscFunctionBeginUser;
213   PetscCall(PetscMalloc1(4, &set_a));
214   PetscCall(PetscMalloc1(4, &set_b));
215 
216   set_a[0] = 3;
217   set_a[1] = 1;
218   set_a[2] = 4;
219   set_a[3] = 9;
220 
221   set_b[0] = 3;
222   set_b[1] = 2;
223   set_b[2] = 6;
224   set_b[3] = 8;
225 
226   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
227   PetscCall(PrintSet(set_a));
228   PetscCall(AssertSetsEqual(set_a, truth));
229 
230   PetscCall(PetscFree(set_a));
231   PetscCall(PetscFree(set_b));
232   PetscFunctionReturn(PETSC_SUCCESS);
233 }
234 
235 /* Tests functionality when sets only have one element in common */
236 PetscErrorCode test_single_common()
237 {
238   PetscInt64 *set_a, *set_b;
239   PetscInt64  truth[] = {1, 4};
240   PetscMPIInt length  = 1;
241 
242   PetscFunctionBeginUser;
243   PetscCall(PetscMalloc1(4, &set_a));
244   PetscCall(PetscMalloc1(5, &set_b));
245 
246   set_a[0] = 3;
247   set_a[1] = 1;
248   set_a[2] = 4;
249   set_a[3] = 9;
250 
251   set_b[0] = 3;
252   set_b[1] = 2;
253   set_b[2] = 4;
254   set_b[3] = 6;
255   set_b[4] = 8;
256 
257   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
258   PetscCall(PrintSet(set_a));
259   PetscCall(AssertSetsEqual(set_a, truth));
260 
261   PetscCall(PetscFree(set_a));
262   PetscCall(PetscFree(set_b));
263   PetscFunctionReturn(PETSC_SUCCESS);
264 }
265 
266 /* Specific test case flagged by PETSc issue #1247 */
267 PetscErrorCode test_issue_1247()
268 {
269   PetscInt64 *set_a, *set_b;
270   PetscInt64  truth[] = {0};
271   PetscMPIInt length  = 1;
272 
273   PetscFunctionBeginUser;
274   PetscCall(PetscMalloc1(3, &set_a));
275   PetscCall(PetscMalloc1(2, &set_b));
276 
277   set_a[0] = 2;
278   set_a[1] = 2;
279   set_a[2] = 3;
280 
281   set_b[0] = 1;
282   set_b[1] = 1;
283 
284   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
285   PetscCall(PrintSet(set_a));
286   PetscCall(AssertSetsEqual(set_a, truth));
287 
288   PetscCall(PetscFree(set_a));
289   PetscCall(PetscFree(set_b));
290   PetscFunctionReturn(PETSC_SUCCESS);
291 }
292 
293 /* Tests functionality when seta is empty and setb is large */
294 PetscErrorCode test_empty_big()
295 {
296   PetscInt64 *set_a, *set_b;
297   PetscInt64  truth[] = {0};
298   PetscMPIInt length  = 1;
299 
300   PetscFunctionBeginUser;
301   PetscCall(PetscMalloc1(1, &set_a));
302   PetscCall(Square(&set_b, 999));
303 
304   set_a[0] = 0;
305 
306   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
307   PetscCall(PrintSet(set_a));
308   PetscCall(AssertSetsEqual(set_a, truth));
309 
310   PetscCall(PetscFree(set_a));
311   PetscCall(PetscFree(set_b));
312   PetscFunctionReturn(PETSC_SUCCESS);
313 }
314 
315 /* Tests functionality when seta is small and setb is large */
316 PetscErrorCode test_small_big()
317 {
318   PetscInt64 *set_a, *set_b;
319   PetscInt64  truth[] = {3, 1, 4, 9};
320   PetscMPIInt length  = 1;
321 
322   PetscFunctionBeginUser;
323   PetscCall(PetscMalloc1(5, &set_a));
324   PetscCall(Square(&set_b, 999));
325 
326   set_a[0] = 4;
327   set_a[1] = 1;
328   set_a[2] = 4;
329   set_a[3] = 8;
330   set_a[4] = 9;
331 
332   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
333   PetscCall(PrintSet(set_a));
334   PetscCall(AssertSetsEqual(set_a, truth));
335 
336   PetscCall(PetscFree(set_a));
337   PetscCall(PetscFree(set_b));
338   PetscFunctionReturn(PETSC_SUCCESS);
339 }
340 
341 /* Tests functionality when seta is medium sized and setb is large */
342 PetscErrorCode test_moderate_big()
343 {
344   PetscInt64 *set_a, *set_b;
345   PetscInt64  truth[] = {2, 1, 144};
346   PetscMPIInt length  = 1;
347 
348   PetscFunctionBeginUser;
349   PetscCall(Fibonnaci(&set_a, 49));
350   PetscCall(Square(&set_b, 999));
351 
352   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
353   PetscCall(PrintSet(set_a));
354   PetscCall(AssertSetsEqual(set_a, truth));
355 
356   PetscCall(PetscFree(set_a));
357   PetscCall(PetscFree(set_b));
358   PetscFunctionReturn(PETSC_SUCCESS);
359 }
360 
361 /* Tests functionality when seta and setb are large */
362 PetscErrorCode test_big_big()
363 {
364   PetscInt64 *set_a, *set_b;
365   PetscInt64 *truth;
366   PetscMPIInt length = 1;
367 
368   PetscFunctionBeginUser;
369   PetscCall(Cube(&set_a, 999));
370   PetscCall(Square(&set_b, 999));
371 
372   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
373   PetscCall(PrintSet(set_a));
374 
375   PetscCall(Sixth(&truth, 9));
376   PetscCall(AssertSetsEqual(set_a, truth));
377 
378   PetscCall(PetscFree(set_a));
379   PetscCall(PetscFree(set_b));
380   PetscCall(PetscFree(truth));
381   PetscFunctionReturn(PETSC_SUCCESS);
382 }
383 
384 /* Tests functionality when setb is empty and setb is large */
385 PetscErrorCode test_big_empty()
386 {
387   PetscInt64 *set_a, *set_b;
388   PetscInt64  truth[] = {0};
389   PetscMPIInt length  = 1;
390 
391   PetscFunctionBeginUser;
392   PetscCall(Cube(&set_a, 999));
393   PetscCall(PetscMalloc1(1, &set_b));
394 
395   set_b[0] = 0;
396 
397   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
398   PetscCall(PrintSet(set_a));
399   PetscCall(AssertSetsEqual(set_a, truth));
400 
401   PetscCall(PetscFree(set_a));
402   PetscCall(PetscFree(set_b));
403   PetscFunctionReturn(PETSC_SUCCESS);
404 }
405 
406 /* Tests functionality when setb is small and setb is large */
407 PetscErrorCode test_big_small()
408 {
409   PetscInt64 *set_a, *set_b;
410   PetscInt64  truth[] = {2, 1, 8};
411   PetscMPIInt length  = 1;
412 
413   PetscFunctionBeginUser;
414   PetscCall(Cube(&set_a, 999));
415   PetscCall(PetscMalloc1(5, &set_b));
416 
417   set_b[0] = 4;
418   set_b[1] = 1;
419   set_b[2] = 4;
420   set_b[3] = 8;
421   set_b[4] = 9;
422 
423   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
424   PetscCall(PrintSet(set_a));
425   PetscCall(AssertSetsEqual(set_a, truth));
426 
427   PetscCall(PetscFree(set_a));
428   PetscCall(PetscFree(set_b));
429   PetscFunctionReturn(PETSC_SUCCESS);
430 }
431 
432 /* Tests functionality when setb is medium sized and setb is large */
433 PetscErrorCode test_big_moderate()
434 {
435   PetscInt64 *set_a, *set_b;
436   PetscInt64  truth[] = {2, 1, 8};
437   PetscMPIInt length  = 1;
438 
439   PetscFunctionBeginUser;
440   PetscCall(Cube(&set_a, 999));
441   PetscCall(Fibonnaci(&set_b, 49));
442 
443   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
444   PetscCall(PrintSet(set_a));
445   PetscCall(AssertSetsEqual(set_a, truth));
446 
447   PetscCall(PetscFree(set_a));
448   PetscCall(PetscFree(set_b));
449   PetscFunctionReturn(PETSC_SUCCESS);
450 }
451 
452 /* Tests functionality when seta and setb are large, in the opposite
453  order to test_big_big() */
454 PetscErrorCode test_big_big_reversed()
455 {
456   PetscInt64 *set_a, *set_b;
457   PetscInt64 *truth;
458   PetscMPIInt length = 1;
459 
460   PetscFunctionBeginUser;
461   PetscCall(Cube(&set_a, 999));
462   PetscCall(Square(&set_b, 999));
463 
464   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
465   PetscCall(PrintSet(set_a));
466 
467   PetscCall(Sixth(&truth, 9));
468   PetscCall(AssertSetsEqual(set_a, truth));
469 
470   PetscCall(PetscFree(set_a));
471   PetscCall(PetscFree(set_b));
472   PetscCall(PetscFree(truth));
473   PetscFunctionReturn(PETSC_SUCCESS);
474 }
475 
476 /* Main executes the individual tests in a predefined order */
477 int main(int argc, char **argv)
478 {
479   PetscFunctionBeginUser;
480   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
481 
482   /* Small tests */
483   /* Test different edge cases with small sets */
484   PetscCall(test_empty_empty());
485   PetscCall(test_a_empty());
486   PetscCall(test_b_empty());
487   PetscCall(test_identical());
488   PetscCall(test_disjoint());
489   PetscCall(test_single_common());
490   PetscCall(test_issue_1247());
491 
492   /* Big tests */
493   /* Test different edge cases with big sets */
494   PetscCall(test_empty_big());
495   PetscCall(test_small_big());
496   PetscCall(test_moderate_big());
497   PetscCall(test_big_big());
498   PetscCall(test_big_empty());
499   PetscCall(test_big_small());
500   PetscCall(test_big_moderate());
501   PetscCall(test_big_big_reversed());
502 
503   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
504   PetscCall(PetscFinalize());
505   return 0;
506 }
507 
508 /*TEST
509 
510    test:
511      suffix: 0
512 
513 TEST*/
514