xref: /petsc/src/sys/tests/ex65.c (revision ed170139b2a0d64288c7bf97cedbc4d7d1412afc)
1*ed170139SJacob Faibussowitsch static const char help[] = "Test PetscFunctionList.\n";
2*ed170139SJacob Faibussowitsch 
3*ed170139SJacob Faibussowitsch #include <petscsys.h>
4*ed170139SJacob Faibussowitsch #include <petscviewer.h>
5*ed170139SJacob Faibussowitsch 
6*ed170139SJacob Faibussowitsch #define PETSC_DEFINE_FUNCTION_AND_STR(name) \
7*ed170139SJacob Faibussowitsch   static void name() \
8*ed170139SJacob Faibussowitsch   { \
9*ed170139SJacob Faibussowitsch     puts("called " PetscStringize(name) "()"); \
10*ed170139SJacob Faibussowitsch   } \
11*ed170139SJacob Faibussowitsch   static const char name##_str[] = PetscStringize(name)
12*ed170139SJacob Faibussowitsch 
13*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(foo);
14*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(bar);
15*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(baz);
16*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(bop);
17*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(qux);
18*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(quux);
19*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(blip);
20*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(blap);
21*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(blop);
22*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(graulty);
23*ed170139SJacob Faibussowitsch PETSC_DEFINE_FUNCTION_AND_STR(quix);
24*ed170139SJacob Faibussowitsch 
25*ed170139SJacob Faibussowitsch static const char *const all_names[]   = {foo_str, bar_str, baz_str, bop_str, qux_str, quux_str, blip_str, blap_str, blop_str, graulty_str, quix_str};
26*ed170139SJacob Faibussowitsch static void (*const all_funcs[])(void) = {foo, bar, baz, bop, qux, quux, blip, blap, blop, graulty, quix};
27*ed170139SJacob Faibussowitsch static const size_t num_names          = PETSC_STATIC_ARRAY_LENGTH(all_names);
28*ed170139SJacob Faibussowitsch static const size_t num_funcs          = PETSC_STATIC_ARRAY_LENGTH(all_funcs);
29*ed170139SJacob Faibussowitsch 
30*ed170139SJacob Faibussowitsch static PetscErrorCode TestPetscFunctionListCreate(PetscViewer viewer, PetscFunctionList *fl, PetscFunctionList *fl_dup)
31*ed170139SJacob Faibussowitsch {
32*ed170139SJacob Faibussowitsch   PetscFunctionBegin;
33*ed170139SJacob Faibussowitsch   // add the function
34*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(fl, foo_str, foo));
35*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(*fl, NULL));
36*ed170139SJacob Faibussowitsch   // remove it
37*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(fl, foo_str, NULL));
38*ed170139SJacob Faibussowitsch   PetscCheck(*fl, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Emptying PetscFunctionList has destroyed it!");
39*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(*fl, NULL));
40*ed170139SJacob Faibussowitsch   // should not do anything
41*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListClear(*fl));
42*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(*fl, viewer));
43*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(*fl, fl_dup));
44*ed170139SJacob Faibussowitsch   PetscCheck(*fl_dup, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Duplicating empty function list has not allocated a new one");
45*ed170139SJacob Faibussowitsch   // still empty
46*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(*fl, viewer));
47*ed170139SJacob Faibussowitsch   // also empty
48*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(*fl_dup, viewer));
49*ed170139SJacob Faibussowitsch   PetscFunctionReturn(0);
50*ed170139SJacob Faibussowitsch }
51*ed170139SJacob Faibussowitsch 
52*ed170139SJacob Faibussowitsch static PetscErrorCode TestPetscFunctionListFind(PetscViewer viewer, PetscFunctionList fl, PetscFunctionList fl_dup, size_t *fl_size, size_t *fl_dup_size)
53*ed170139SJacob Faibussowitsch {
54*ed170139SJacob Faibussowitsch   PetscFunctionBegin;
55*ed170139SJacob Faibussowitsch   // add a bunch of functions, and ensure they are all there
56*ed170139SJacob Faibussowitsch   for (size_t i = 0; i < num_funcs; ++i) {
57*ed170139SJacob Faibussowitsch     PetscVoidFunction func;
58*ed170139SJacob Faibussowitsch 
59*ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListAdd(&fl, all_names[i], all_funcs[i]));
60*ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListFind(fl, all_names[i], &func));
61*ed170139SJacob Faibussowitsch     PetscCheck(func == all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() immediately after inserting it! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)func, (void *)(PETSC_UINTPTR_T)(all_funcs[i]));
62*ed170139SJacob Faibussowitsch     // make sure the pointer is good
63*ed170139SJacob Faibussowitsch     func();
64*ed170139SJacob Faibussowitsch   }
65*ed170139SJacob Faibussowitsch 
66*ed170139SJacob Faibussowitsch   // ensure that none of them are missing
67*ed170139SJacob Faibussowitsch   for (size_t i = 0; i < num_funcs; ++i) {
68*ed170139SJacob Faibussowitsch     PetscVoidFunction func;
69*ed170139SJacob Faibussowitsch 
70*ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListFind(fl, all_names[i], &func));
71*ed170139SJacob Faibussowitsch     PetscCheck(func == all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() after inserting all functions! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)func, (void *)(PETSC_UINTPTR_T)(all_funcs[i]));
72*ed170139SJacob Faibussowitsch     // make sure the pointer is good
73*ed170139SJacob Faibussowitsch     func();
74*ed170139SJacob Faibussowitsch   }
75*ed170139SJacob Faibussowitsch 
76*ed170139SJacob Faibussowitsch   // appends to fl_dup
77*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListDuplicate(fl, &fl_dup));
78*ed170139SJacob Faibussowitsch 
79*ed170139SJacob Faibussowitsch   // ensure that none of them are missing
80*ed170139SJacob Faibussowitsch   for (size_t i = 0; i < num_funcs; ++i) {
81*ed170139SJacob Faibussowitsch     PetscVoidFunction fl_func, fl_dup_func;
82*ed170139SJacob Faibussowitsch 
83*ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListFind(fl, all_names[i], &fl_func));
84*ed170139SJacob Faibussowitsch     PetscCheck(fl_func == all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() after inserting all functions! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)fl_func, (void *)(PETSC_UINTPTR_T)(all_funcs[i]));
85*ed170139SJacob Faibussowitsch     // make sure the pointer is good
86*ed170139SJacob Faibussowitsch     fl_func();
87*ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListFind(fl_dup, all_names[i], &fl_dup_func));
88*ed170139SJacob Faibussowitsch     PetscCheck(fl_dup_func == fl_func, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() returned different results for %s() for duplicated function list. returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)fl_dup_func, (void *)(PETSC_UINTPTR_T)fl_func);
89*ed170139SJacob Faibussowitsch     fl_dup_func();
90*ed170139SJacob Faibussowitsch   }
91*ed170139SJacob Faibussowitsch 
92*ed170139SJacob Faibussowitsch   // same as in fl
93*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(fl_dup, viewer));
94*ed170139SJacob Faibussowitsch   // clearing fl should have no effect on fl_dup
95*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListClear(fl));
96*ed170139SJacob Faibussowitsch   // ensure that none of them are missing
97*ed170139SJacob Faibussowitsch   for (size_t i = 0; i < num_funcs; ++i) {
98*ed170139SJacob Faibussowitsch     PetscVoidFunction fl_dup_func;
99*ed170139SJacob Faibussowitsch 
100*ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListFind(fl_dup, all_names[i], &fl_dup_func));
101*ed170139SJacob Faibussowitsch     PetscCheck(fl_dup_func == all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() in duplicated function list after clearing original list! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)fl_dup_func, (void *)(PETSC_UINTPTR_T)(all_funcs[i]));
102*ed170139SJacob Faibussowitsch     fl_dup_func();
103*ed170139SJacob Faibussowitsch   }
104*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(fl_dup, viewer));
105*ed170139SJacob Faibussowitsch   *fl_size     = 0;
106*ed170139SJacob Faibussowitsch   *fl_dup_size = num_funcs;
107*ed170139SJacob Faibussowitsch   PetscFunctionReturn(0);
108*ed170139SJacob Faibussowitsch }
109*ed170139SJacob Faibussowitsch 
110*ed170139SJacob Faibussowitsch static PetscErrorCode TestPetscFunctionListGet(PetscViewer viewer, PetscFunctionList fl, PetscFunctionList fl_dup, size_t expected_fl_size, size_t expected_fl_dup_size)
111*ed170139SJacob Faibussowitsch {
112*ed170139SJacob Faibussowitsch   const char **array;
113*ed170139SJacob Faibussowitsch   int          n;
114*ed170139SJacob Faibussowitsch #define PetscCheckArrayPointer(expected_non_null, array) \
115*ed170139SJacob Faibussowitsch   PetscCheck((expected_non_null) ? (array) != NULL : (array) == NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListGet() returned invalid array (%p) for cleared function list, expected %s", (void *)(array), (expected_non_null) ? "non-null" : "null")
116*ed170139SJacob Faibussowitsch 
117*ed170139SJacob Faibussowitsch   PetscFunctionBegin;
118*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListGet(fl, &array, &n));
119*ed170139SJacob Faibussowitsch   PetscCheck((size_t)n == expected_fl_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListGet() returned unexpected size %d, expected %zu", n, expected_fl_size);
120*ed170139SJacob Faibussowitsch   PetscCheckArrayPointer(expected_fl_size, array);
121*ed170139SJacob Faibussowitsch 
122*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListGet(fl_dup, &array, &n));
123*ed170139SJacob Faibussowitsch   PetscCheck((size_t)n == expected_fl_dup_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListGet() returned unexpected size %d, expected %zu", n, expected_fl_dup_size);
124*ed170139SJacob Faibussowitsch   PetscCheckArrayPointer(expected_fl_dup_size, array);
125*ed170139SJacob Faibussowitsch   for (int i = 0; i < n; ++i) PetscCall(PetscViewerASCIIPrintf(viewer, "%d: %s\n", i + 1, array[i]));
126*ed170139SJacob Faibussowitsch   PetscCall(PetscFree(array));
127*ed170139SJacob Faibussowitsch   // ensure that free-ing the array is OK
128*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListView(fl_dup, viewer));
129*ed170139SJacob Faibussowitsch   PetscFunctionReturn(0);
130*ed170139SJacob Faibussowitsch #undef PetscCheckArrayPointer
131*ed170139SJacob Faibussowitsch }
132*ed170139SJacob Faibussowitsch 
133*ed170139SJacob Faibussowitsch int main(int argc, char *argv[])
134*ed170139SJacob Faibussowitsch {
135*ed170139SJacob Faibussowitsch   PetscViewer       viewer;
136*ed170139SJacob Faibussowitsch   PetscFunctionList fl = NULL, fl_dup = NULL;
137*ed170139SJacob Faibussowitsch   size_t            fl_size, fl_dup_size;
138*ed170139SJacob Faibussowitsch 
139*ed170139SJacob Faibussowitsch   PetscFunctionBeginUser;
140*ed170139SJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
141*ed170139SJacob Faibussowitsch   PetscCheck(num_names == num_funcs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of functions %zu != number of function names %zu", num_funcs, num_names);
142*ed170139SJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD, &viewer));
143*ed170139SJacob Faibussowitsch 
144*ed170139SJacob Faibussowitsch   PetscCall(TestPetscFunctionListCreate(viewer, &fl, &fl_dup));
145*ed170139SJacob Faibussowitsch   PetscCall(TestPetscFunctionListFind(viewer, fl, fl_dup, &fl_size, &fl_dup_size));
146*ed170139SJacob Faibussowitsch   PetscCall(TestPetscFunctionListGet(viewer, fl, fl_dup, fl_size, fl_dup_size));
147*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, PETSC_STDOUT, "my_prefix_", "-petsc_function_type", "Description", "PetscFunctionList", fl_dup, "foo", "bar"));
148*ed170139SJacob Faibussowitsch 
149*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&fl));
150*ed170139SJacob Faibussowitsch   PetscCheck(fl == NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed to destroy PetscFunctionList, pointer (%p) is non-null", (void *)fl);
151*ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&fl_dup));
152*ed170139SJacob Faibussowitsch   PetscCheck(fl_dup == NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed to destroy PetscFunctionList, pointer (%p) is non-null", (void *)fl_dup);
153*ed170139SJacob Faibussowitsch   PetscCall(PetscFinalize());
154*ed170139SJacob Faibussowitsch   return 0;
155*ed170139SJacob Faibussowitsch }
156*ed170139SJacob Faibussowitsch 
157*ed170139SJacob Faibussowitsch /*TEST
158*ed170139SJacob Faibussowitsch 
159*ed170139SJacob Faibussowitsch   test:
160*ed170139SJacob Faibussowitsch 
161*ed170139SJacob Faibussowitsch TEST*/
162