xref: /libCEED/tests/t525-operator.c (revision 356036fa84f714fa73ef64c9a80ce2028dde816f)
1 /// @file
2 /// Test setting QFunctionContext fields from Operator
3 /// \test Test setting QFunctionContext fields from Operator
4 #include <ceed.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 
8 #include "t500-operator.h"
9 
10 typedef struct {
11   int    count;
12   double other;
13 } TestContext1;
14 
15 typedef struct {
16   double time;
17   double other;
18 } TestContext2;
19 
20 int main(int argc, char **argv) {
21   Ceed                  ceed;
22   CeedQFunctionContext  qf_ctx_sub_1, qf_ctx_sub_2;
23   CeedContextFieldLabel count_label, other_label, time_label, bad_label;
24   CeedQFunction         qf_sub_1, qf_sub_2;
25   CeedOperator          op_sub_1, op_sub_2, op_composite;
26 
27   TestContext1 ctx_data_1 = {
28       .count = 42,
29       .other = -3.0,
30   };
31   TestContext2 ctx_data_2 = {
32       .time  = 1.0,
33       .other = -3.0,
34   };
35 
36   CeedInit(argv[1], &ceed);
37 
38   // First sub-operator
39   CeedQFunctionContextCreate(ceed, &qf_ctx_sub_1);
40   CeedQFunctionContextSetData(qf_ctx_sub_1, CEED_MEM_HOST, CEED_USE_POINTER, sizeof(TestContext1), &ctx_data_1);
41   CeedQFunctionContextRegisterInt32(qf_ctx_sub_1, "count", offsetof(TestContext1, count), 1, "some sort of counter");
42   CeedQFunctionContextRegisterDouble(qf_ctx_sub_1, "other", offsetof(TestContext1, other), 1, "some other value");
43 
44   CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_sub_1);
45   CeedQFunctionSetContext(qf_sub_1, qf_ctx_sub_1);
46 
47   CeedOperatorCreate(ceed, qf_sub_1, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_sub_1);
48 
49   // Check setting field in operator
50   CeedOperatorGetContextFieldLabel(op_sub_1, "count", &count_label);
51   int value_count = 43;
52   CeedOperatorSetContextInt32(op_sub_1, count_label, &value_count);
53   if (ctx_data_1.count != 43) printf("Incorrect context data for count: %" CeedInt_FMT " != 43", ctx_data_1.count);
54   {
55     const int *values;
56     size_t     num_values;
57 
58     CeedOperatorGetContextInt32Read(op_sub_1, count_label, &num_values, &values);
59     if (num_values != 1) printf("Incorrect number of count values, found %ld but expected 1", num_values);
60     if (values[0] != ctx_data_1.count) printf("Incorrect value found, found %d but expected %d", values[0], ctx_data_1.count);
61     CeedOperatorRestoreContextInt32Read(op_sub_1, count_label, &values);
62   }
63 
64   // Second sub-operator
65   CeedQFunctionContextCreate(ceed, &qf_ctx_sub_2);
66   CeedQFunctionContextSetData(qf_ctx_sub_2, CEED_MEM_HOST, CEED_USE_POINTER, sizeof(TestContext2), &ctx_data_2);
67   CeedQFunctionContextRegisterDouble(qf_ctx_sub_2, "time", offsetof(TestContext2, time), 1, "current time");
68   CeedQFunctionContextRegisterDouble(qf_ctx_sub_2, "other", offsetof(TestContext2, other), 1, "some other value");
69 
70   CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_sub_2);
71   CeedQFunctionSetContext(qf_sub_2, qf_ctx_sub_2);
72 
73   CeedOperatorCreate(ceed, qf_sub_2, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_sub_2);
74 
75   // Composite operator
76   CeedCompositeOperatorCreate(ceed, &op_composite);
77   CeedCompositeOperatorAddSub(op_composite, op_sub_1);
78   CeedCompositeOperatorAddSub(op_composite, op_sub_2);
79 
80   // Check setting field in context of single sub-operator for composite operator
81   CeedOperatorGetContextFieldLabel(op_composite, "time", &time_label);
82   double value_time = 2.0;
83   CeedOperatorSetContextDouble(op_composite, time_label, &value_time);
84   if (ctx_data_2.time != 2.0) printf("Incorrect context data for time: %f != 2.0\n", ctx_data_2.time);
85   {
86     const double *values;
87     size_t        num_values;
88 
89     CeedOperatorGetContextDoubleRead(op_composite, time_label, &num_values, &values);
90     if (num_values != 1) printf("Incorrect number of time values, found %ld but expected 1", num_values);
91     if (values[0] != ctx_data_2.time) printf("Incorrect value found, found %f but expected %f", values[0], ctx_data_2.time);
92     CeedOperatorRestoreContextDoubleRead(op_composite, time_label, &values);
93   }
94 
95   // Check setting field in context of multiple sub-operators for composite operator
96   CeedOperatorGetContextFieldLabel(op_composite, "other", &other_label);
97   // No issue requesting same label twice
98   CeedOperatorGetContextFieldLabel(op_composite, "other", &other_label);
99   double value_other = 9000.;
100   CeedOperatorSetContextDouble(op_composite, other_label, &value_other);
101   if (ctx_data_1.other != 9000.0) printf("Incorrect context data for other: %f != 2.0\n", ctx_data_1.other);
102   if (ctx_data_2.other != 9000.0) printf("Incorrect context data for other: %f != 2.0\n", ctx_data_2.other);
103 
104   // Check requesting label for field that doesn't exist returns NULL
105   CeedOperatorGetContextFieldLabel(op_composite, "bad", &bad_label);
106   if (bad_label) printf("Incorrect context label returned\n");
107 
108   {
109     // Check getting reference to QFunctionContext
110     CeedQFunctionContext ctx_copy = NULL;
111 
112     CeedOperatorGetContext(op_sub_1, &ctx_copy);
113     if (ctx_copy != qf_ctx_sub_1) printf("Incorrect QFunctionContext retrieved");
114 
115     CeedOperatorGetContext(op_sub_2, &ctx_copy);  // Destroys reference to qf_ctx_sub_1
116     if (ctx_copy != qf_ctx_sub_2) printf("Incorrect QFunctionContext retrieved");
117     CeedQFunctionContextDestroy(&ctx_copy);  // Cleanup to prevent leak
118   }
119 
120   CeedQFunctionContextDestroy(&qf_ctx_sub_1);
121   CeedQFunctionContextDestroy(&qf_ctx_sub_2);
122   CeedQFunctionDestroy(&qf_sub_1);
123   CeedQFunctionDestroy(&qf_sub_2);
124   CeedOperatorDestroy(&op_sub_1);
125   CeedOperatorDestroy(&op_sub_2);
126   CeedOperatorDestroy(&op_composite);
127   CeedDestroy(&ceed);
128   return 0;
129 }
130