xref: /petsc/src/sys/tests/ex62.c (revision 57d508425293f0bb93f59574d14951d8faac9af8)
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] = 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] = 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] = 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] = 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 
79   PetscFunctionBeginUser;
80   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "["));
81   for (PetscInt64 ii = 1; ii <= set[0]; ii++) {
82     PetscCall(PetscFormatConvert(" %" PetscInt64_FMT ",", text));
83     PetscCall(PetscPrintf(PETSC_COMM_WORLD, text, set[ii]));
84   }
85   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
86   PetscFunctionReturn(PETSC_SUCCESS);
87 }
88 
89 /* Check set equality */
90 PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
91 {
92   PetscInt ii;
93 
94   PetscFunctionBeginUser;
95   PetscAssert(set[0] == true_set[0], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
96   for (ii = 1; ii < set[0] + 1; ii++) PetscAssert(set[ii] == true_set[ii], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets are different");
97   PetscFunctionReturn(PETSC_SUCCESS);
98 }
99 
100 /* Tests functionality when two enpty sets are passed */
101 PetscErrorCode test_empty_empty()
102 {
103   PetscInt64 *set_a, *set_b;
104   PetscInt64  truth[] = {0};
105   PetscMPIInt length  = 1;
106 
107   PetscFunctionBeginUser;
108   PetscCall(PetscMalloc1(1, &set_a));
109   PetscCall(PetscMalloc1(1, &set_b));
110 
111   set_a[0] = 0;
112 
113   set_b[0] = 0;
114 
115   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
116   PetscCall(PrintSet(set_a));
117   PetscCall(AssertSetsEqual(set_a, truth));
118 
119   PetscCall(PetscFree(set_a));
120   PetscCall(PetscFree(set_b));
121   PetscFunctionReturn(PETSC_SUCCESS);
122 }
123 
124 /* Tests functionality when seta is empty */
125 PetscErrorCode test_a_empty()
126 {
127   PetscInt64 *set_a, *set_b;
128   PetscInt64  truth[] = {0};
129   PetscMPIInt length  = 1;
130 
131   PetscFunctionBeginUser;
132   PetscCall(PetscMalloc1(1, &set_a));
133   PetscCall(PetscMalloc1(2, &set_b));
134 
135   set_a[0] = 0;
136 
137   set_b[0] = 1;
138   set_b[1] = 1;
139 
140   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
141   PetscCall(PrintSet(set_a));
142   PetscCall(AssertSetsEqual(set_a, truth));
143 
144   PetscCall(PetscFree(set_a));
145   PetscCall(PetscFree(set_b));
146   PetscFunctionReturn(PETSC_SUCCESS);
147 }
148 
149 /* Tests functionality when setb is empty */
150 PetscErrorCode test_b_empty()
151 {
152   PetscInt64 *set_a, *set_b;
153   PetscInt64  truth[] = {0};
154   PetscMPIInt length  = 1;
155 
156   PetscFunctionBeginUser;
157   PetscCall(PetscMalloc1(2, &set_a));
158   PetscCall(PetscMalloc1(1, &set_b));
159 
160   set_a[0] = 1;
161   set_a[1] = 1;
162 
163   set_b[0] = 0;
164 
165   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
166   PetscCall(PrintSet(set_a));
167   PetscCall(AssertSetsEqual(set_a, truth));
168 
169   PetscCall(PetscFree(set_a));
170   PetscCall(PetscFree(set_b));
171   PetscFunctionReturn(PETSC_SUCCESS);
172 }
173 
174 /* Tests functionality when both sets are identical */
175 PetscErrorCode test_identical()
176 {
177   PetscInt64 *set_a, *set_b;
178   PetscInt64  truth[] = {3, 1, 4, 9};
179   PetscMPIInt length  = 4;
180 
181   PetscFunctionBeginUser;
182   PetscCall(PetscMalloc1(4, &set_a));
183   PetscCall(PetscMalloc1(4, &set_b));
184 
185   set_a[0] = 3;
186   set_a[1] = 1;
187   set_a[2] = 4;
188   set_a[3] = 9;
189 
190   set_b[0] = 3;
191   set_b[1] = 1;
192   set_b[2] = 4;
193   set_b[3] = 9;
194 
195   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
196   PetscCall(PrintSet(set_a));
197   PetscCall(AssertSetsEqual(set_a, truth));
198 
199   PetscCall(PetscFree(set_a));
200   PetscCall(PetscFree(set_b));
201   PetscFunctionReturn(PETSC_SUCCESS);
202 }
203 
204 /* Tests functionality when sets have no elements in common */
205 PetscErrorCode test_disjoint()
206 {
207   PetscInt64 *set_a, *set_b;
208   PetscInt64  truth[] = {0};
209   PetscMPIInt length  = 1;
210 
211   PetscFunctionBeginUser;
212   PetscCall(PetscMalloc1(4, &set_a));
213   PetscCall(PetscMalloc1(4, &set_b));
214 
215   set_a[0] = 3;
216   set_a[1] = 1;
217   set_a[2] = 4;
218   set_a[3] = 9;
219 
220   set_b[0] = 3;
221   set_b[1] = 2;
222   set_b[2] = 6;
223   set_b[3] = 8;
224 
225   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
226   PetscCall(PrintSet(set_a));
227   PetscCall(AssertSetsEqual(set_a, truth));
228 
229   PetscCall(PetscFree(set_a));
230   PetscCall(PetscFree(set_b));
231   PetscFunctionReturn(PETSC_SUCCESS);
232 }
233 
234 /* Tests functionality when sets only have one element in common */
235 PetscErrorCode test_single_common()
236 {
237   PetscInt64 *set_a, *set_b;
238   PetscInt64  truth[] = {1, 4};
239   PetscMPIInt length  = 1;
240 
241   PetscFunctionBeginUser;
242   PetscCall(PetscMalloc1(4, &set_a));
243   PetscCall(PetscMalloc1(5, &set_b));
244 
245   set_a[0] = 3;
246   set_a[1] = 1;
247   set_a[2] = 4;
248   set_a[3] = 9;
249 
250   set_b[0] = 3;
251   set_b[1] = 2;
252   set_b[2] = 4;
253   set_b[3] = 6;
254   set_b[4] = 8;
255 
256   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
257   PetscCall(PrintSet(set_a));
258   PetscCall(AssertSetsEqual(set_a, truth));
259 
260   PetscCall(PetscFree(set_a));
261   PetscCall(PetscFree(set_b));
262   PetscFunctionReturn(PETSC_SUCCESS);
263 }
264 
265 /* Specific test case flagged by PETSc issue #1247 */
266 PetscErrorCode test_issue_1247()
267 {
268   PetscInt64 *set_a, *set_b;
269   PetscInt64  truth[] = {0};
270   PetscMPIInt length  = 1;
271 
272   PetscFunctionBeginUser;
273   PetscCall(PetscMalloc1(3, &set_a));
274   PetscCall(PetscMalloc1(2, &set_b));
275 
276   set_a[0] = 2;
277   set_a[1] = 2;
278   set_a[2] = 3;
279 
280   set_b[0] = 1;
281   set_b[1] = 1;
282 
283   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
284   PetscCall(PrintSet(set_a));
285   PetscCall(AssertSetsEqual(set_a, truth));
286 
287   PetscCall(PetscFree(set_a));
288   PetscCall(PetscFree(set_b));
289   PetscFunctionReturn(PETSC_SUCCESS);
290 }
291 
292 /* Tests functionality when seta is empty and setb is large */
293 PetscErrorCode test_empty_big()
294 {
295   PetscInt64 *set_a, *set_b;
296   PetscInt64  truth[] = {0};
297   PetscMPIInt length  = 1;
298 
299   PetscFunctionBeginUser;
300   PetscCall(PetscMalloc1(1, &set_a));
301   PetscCall(Square(&set_b, 999));
302 
303   set_a[0] = 0;
304 
305   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
306   PetscCall(PrintSet(set_a));
307   PetscCall(AssertSetsEqual(set_a, truth));
308 
309   PetscCall(PetscFree(set_a));
310   PetscCall(PetscFree(set_b));
311   PetscFunctionReturn(PETSC_SUCCESS);
312 }
313 
314 /* Tests functionality when seta is small and setb is large */
315 PetscErrorCode test_small_big()
316 {
317   PetscInt64 *set_a, *set_b;
318   PetscInt64  truth[] = {3, 1, 4, 9};
319   PetscMPIInt length  = 1;
320 
321   PetscFunctionBeginUser;
322   PetscCall(PetscMalloc1(5, &set_a));
323   PetscCall(Square(&set_b, 999));
324 
325   set_a[0] = 4;
326   set_a[1] = 1;
327   set_a[2] = 4;
328   set_a[3] = 8;
329   set_a[4] = 9;
330 
331   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
332   PetscCall(PrintSet(set_a));
333   PetscCall(AssertSetsEqual(set_a, truth));
334 
335   PetscCall(PetscFree(set_a));
336   PetscCall(PetscFree(set_b));
337   PetscFunctionReturn(PETSC_SUCCESS);
338 }
339 
340 /* Tests functionality when seta is medium sized and setb is large */
341 PetscErrorCode test_moderate_big()
342 {
343   PetscInt64 *set_a, *set_b;
344   PetscInt64  truth[] = {2, 1, 144};
345   PetscMPIInt length  = 1;
346 
347   PetscFunctionBeginUser;
348   PetscCall(Fibonnaci(&set_a, 49));
349   PetscCall(Square(&set_b, 999));
350 
351   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
352   PetscCall(PrintSet(set_a));
353   PetscCall(AssertSetsEqual(set_a, truth));
354 
355   PetscCall(PetscFree(set_a));
356   PetscCall(PetscFree(set_b));
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /* Tests functionality when seta and setb are large */
361 PetscErrorCode test_big_big()
362 {
363   PetscInt64 *set_a, *set_b;
364   PetscInt64 *truth;
365   PetscMPIInt length = 1;
366 
367   PetscFunctionBeginUser;
368   PetscCall(Cube(&set_a, 999));
369   PetscCall(Square(&set_b, 999));
370 
371   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
372   PetscCall(PrintSet(set_a));
373 
374   PetscCall(Sixth(&truth, 9));
375   PetscCall(AssertSetsEqual(set_a, truth));
376 
377   PetscCall(PetscFree(set_a));
378   PetscCall(PetscFree(set_b));
379   PetscCall(PetscFree(truth));
380   PetscFunctionReturn(PETSC_SUCCESS);
381 }
382 
383 /* Tests functionality when setb is empty and setb is large */
384 PetscErrorCode test_big_empty()
385 {
386   PetscInt64 *set_a, *set_b;
387   PetscInt64  truth[] = {0};
388   PetscMPIInt length  = 1;
389 
390   PetscFunctionBeginUser;
391   PetscCall(Cube(&set_a, 999));
392   PetscCall(PetscMalloc1(1, &set_b));
393 
394   set_b[0] = 0;
395 
396   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
397   PetscCall(PrintSet(set_a));
398   PetscCall(AssertSetsEqual(set_a, truth));
399 
400   PetscCall(PetscFree(set_a));
401   PetscCall(PetscFree(set_b));
402   PetscFunctionReturn(PETSC_SUCCESS);
403 }
404 
405 /* Tests functionality when setb is small and setb is large */
406 PetscErrorCode test_big_small()
407 {
408   PetscInt64 *set_a, *set_b;
409   PetscInt64  truth[] = {2, 1, 8};
410   PetscMPIInt length  = 1;
411 
412   PetscFunctionBeginUser;
413   PetscCall(Cube(&set_a, 999));
414   PetscCall(PetscMalloc1(5, &set_b));
415 
416   set_b[0] = 4;
417   set_b[1] = 1;
418   set_b[2] = 4;
419   set_b[3] = 8;
420   set_b[4] = 9;
421 
422   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
423   PetscCall(PrintSet(set_a));
424   PetscCall(AssertSetsEqual(set_a, truth));
425 
426   PetscCall(PetscFree(set_a));
427   PetscCall(PetscFree(set_b));
428   PetscFunctionReturn(PETSC_SUCCESS);
429 }
430 
431 /* Tests functionality when setb is medium sized and setb is large */
432 PetscErrorCode test_big_moderate()
433 {
434   PetscInt64 *set_a, *set_b;
435   PetscInt64  truth[] = {2, 1, 8};
436   PetscMPIInt length  = 1;
437 
438   PetscFunctionBeginUser;
439   PetscCall(Cube(&set_a, 999));
440   PetscCall(Fibonnaci(&set_b, 49));
441 
442   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
443   PetscCall(PrintSet(set_a));
444   PetscCall(AssertSetsEqual(set_a, truth));
445 
446   PetscCall(PetscFree(set_a));
447   PetscCall(PetscFree(set_b));
448   PetscFunctionReturn(PETSC_SUCCESS);
449 }
450 
451 /* Tests functionality when seta and setb are large, in the opposite
452  order to test_big_big() */
453 PetscErrorCode test_big_big_reversed()
454 {
455   PetscInt64 *set_a, *set_b;
456   PetscInt64 *truth;
457   PetscMPIInt length = 1;
458 
459   PetscFunctionBeginUser;
460   PetscCall(Cube(&set_a, 999));
461   PetscCall(Square(&set_b, 999));
462 
463   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
464   PetscCall(PrintSet(set_a));
465 
466   PetscCall(Sixth(&truth, 9));
467   PetscCall(AssertSetsEqual(set_a, truth));
468 
469   PetscCall(PetscFree(set_a));
470   PetscCall(PetscFree(set_b));
471   PetscCall(PetscFree(truth));
472   PetscFunctionReturn(PETSC_SUCCESS);
473 }
474 
475 /* Main executes the individual tests in a predefined order */
476 int main(int argc, char **argv)
477 {
478   PetscFunctionBeginUser;
479   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
480 
481   /* Small tests */
482   /* Test different edge cases with small sets */
483   PetscCall(test_empty_empty());
484   PetscCall(test_a_empty());
485   PetscCall(test_b_empty());
486   PetscCall(test_identical());
487   PetscCall(test_disjoint());
488   PetscCall(test_single_common());
489   PetscCall(test_issue_1247());
490 
491   /* Big tests */
492   /* Test different edge cases with big sets */
493   PetscCall(test_empty_big());
494   PetscCall(test_small_big());
495   PetscCall(test_moderate_big());
496   PetscCall(test_big_big());
497   PetscCall(test_big_empty());
498   PetscCall(test_big_small());
499   PetscCall(test_big_moderate());
500   PetscCall(test_big_big_reversed());
501 
502   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
503   PetscCall(PetscFinalize());
504   return 0;
505 }
506 
507 /*TEST
508 
509    test:
510      suffix: 0
511 
512 TEST*/
513