xref: /libCEED/tests/t522-operator.c (revision d1d35e2f02dc969aee8debf3fd943dd784aa847a)
1b6faaefaSjeremylt /// @file
231e5b035Sjeremylt /// Test creation, action, and destruction for diffusion matrix operator
331e5b035Sjeremylt /// \test Test creation, action, and destruction for diffusion matrix operator
4b6faaefaSjeremylt #include <ceed.h>
5b6faaefaSjeremylt #include <stdlib.h>
6b6faaefaSjeremylt #include <math.h>
7b6faaefaSjeremylt #include "t320-basis.h"
8b6faaefaSjeremylt #include "t522-operator.h"
9b6faaefaSjeremylt 
10b6faaefaSjeremylt /* The mesh comprises of two rows of 3 quadralaterals followed by one row
11b6faaefaSjeremylt      of 6 triangles:
12b6faaefaSjeremylt    _ _ _
13b6faaefaSjeremylt   |_|_|_|
14b6faaefaSjeremylt   |_|_|_|
15b6faaefaSjeremylt   |/|/|/|
16b6faaefaSjeremylt 
17b6faaefaSjeremylt */
18b6faaefaSjeremylt 
19b6faaefaSjeremylt int main(int argc, char **argv) {
20b6faaefaSjeremylt   Ceed ceed;
21*d1d35e2fSjeremylt   CeedElemRestriction elem_restr_x_tet, elem_restr_u_tet,
22*d1d35e2fSjeremylt                       elem_restr_qd_i_tet,
23*d1d35e2fSjeremylt                       elem_restr_x_hex, elem_restr_u_hex,
24*d1d35e2fSjeremylt                       elem_restr_qd_i_hex;
25*d1d35e2fSjeremylt   CeedBasis basis_x_tet, basis_u_tet,
26*d1d35e2fSjeremylt             basis_x_hex, basis_u_hex;
27*d1d35e2fSjeremylt   CeedQFunction qf_setup_tet, qf_diff_tet,
28*d1d35e2fSjeremylt                 qf_setup_hex, qf_diff_hex;
29*d1d35e2fSjeremylt   CeedOperator op_setup_tet, op_diff_tet,
30*d1d35e2fSjeremylt                op_setup_hex, op_diff_hex,
31b6faaefaSjeremylt                op_setup, op_diff;
32*d1d35e2fSjeremylt   CeedVector q_data_tet, q_data_hex, X, U, V;
33b6faaefaSjeremylt   const CeedScalar *hv;
34*d1d35e2fSjeremylt   CeedInt num_elem_tet = 6, P_tet = 6, Q_tet = 4,
35*d1d35e2fSjeremylt           num_elem_hex = 6, P_hex = 3, Q_hex = 4, dim = 2;
36*d1d35e2fSjeremylt   CeedInt n_x = 3, n_y = 3,
37*d1d35e2fSjeremylt           n_x_tet = 3, n_y_tet = 1, n_x_hex = 3;
38b6faaefaSjeremylt   CeedInt row, col, offset;
39*d1d35e2fSjeremylt   CeedInt num_dofs = (n_x*2+1)*(n_y*2+1),
40*d1d35e2fSjeremylt           num_qpts_tet = num_elem_tet*Q_tet,
41*d1d35e2fSjeremylt           num_qpts_hex = num_elem_hex*Q_hex*Q_hex;
42*d1d35e2fSjeremylt   CeedInt ind_x_tet[num_elem_tet*P_tet],
43*d1d35e2fSjeremylt           ind_x_hex[num_elem_hex*P_hex*P_hex];
44*d1d35e2fSjeremylt   CeedScalar x[dim*num_dofs];
45*d1d35e2fSjeremylt   CeedScalar q_ref[dim*Q_tet], q_weight[Q_tet];
46*d1d35e2fSjeremylt   CeedScalar interp[P_tet*Q_tet], grad[dim*P_tet*Q_tet];
47b6faaefaSjeremylt 
48b6faaefaSjeremylt   CeedInit(argv[1], &ceed);
49b6faaefaSjeremylt 
50b6faaefaSjeremylt   // DoF Coordinates
51*d1d35e2fSjeremylt   for (CeedInt i=0; i<n_y*2+1; i++)
52*d1d35e2fSjeremylt     for (CeedInt j=0; j<n_x*2+1; j++) {
53*d1d35e2fSjeremylt       x[i+j*(n_y*2+1)+0*num_dofs] = (CeedScalar) i / (2*n_y);
54*d1d35e2fSjeremylt       x[i+j*(n_y*2+1)+1*num_dofs] = (CeedScalar) j / (2*n_x);
55b6faaefaSjeremylt     }
56*d1d35e2fSjeremylt   CeedVectorCreate(ceed, dim*num_dofs, &X);
57b6faaefaSjeremylt   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
58b6faaefaSjeremylt 
59b6faaefaSjeremylt   // Qdata Vectors
60*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_qpts_tet*dim*(dim+1)/2, &q_data_tet);
61*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_qpts_hex*dim*(dim+1)/2, &q_data_hex);
62b6faaefaSjeremylt 
63b6faaefaSjeremylt   // Tet Elements
64*d1d35e2fSjeremylt   for (CeedInt i=0; i<num_elem_tet/2; i++) {
65*d1d35e2fSjeremylt     col = i % n_x_tet;
66*d1d35e2fSjeremylt     row = i / n_x_tet;
67*d1d35e2fSjeremylt     offset = col*2 + row*(n_x_tet*2+1)*2;
68b6faaefaSjeremylt 
69*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  0] =  2 + offset;
70*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  1] =  9 + offset;
71*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  2] = 16 + offset;
72*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  3] =  1 + offset;
73*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  4] =  8 + offset;
74*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  5] =  0 + offset;
75b6faaefaSjeremylt 
76*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  6] = 14 + offset;
77*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  7] =  7 + offset;
78*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  8] =  0 + offset;
79*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet +  9] = 15 + offset;
80*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet + 10] =  8 + offset;
81*d1d35e2fSjeremylt     ind_x_tet[i*2*P_tet + 11] = 16 + offset;
82b6faaefaSjeremylt   }
83b6faaefaSjeremylt 
84b6faaefaSjeremylt   // -- Restrictions
85*d1d35e2fSjeremylt   CeedElemRestrictionCreate(ceed, num_elem_tet, P_tet, dim, num_dofs,
86*d1d35e2fSjeremylt                             dim*num_dofs,
87*d1d35e2fSjeremylt                             CEED_MEM_HOST, CEED_USE_POINTER, ind_x_tet,
88*d1d35e2fSjeremylt                             &elem_restr_x_tet);
89b6faaefaSjeremylt 
90*d1d35e2fSjeremylt   CeedElemRestrictionCreate(ceed, num_elem_tet, P_tet, 1, 1, num_dofs,
91*d1d35e2fSjeremylt                             CEED_MEM_HOST, CEED_USE_POINTER, ind_x_tet,
92*d1d35e2fSjeremylt                             &elem_restr_u_tet);
93*d1d35e2fSjeremylt   CeedInt strides_qd_tet[3] = {1, Q_tet, Q_tet *dim *(dim+1)/2};
94*d1d35e2fSjeremylt   CeedElemRestrictionCreateStrided(ceed, num_elem_tet, Q_tet, dim*(dim+1)/2,
95*d1d35e2fSjeremylt                                    dim*(dim+1)/2*num_qpts_tet, strides_qd_tet,
96*d1d35e2fSjeremylt                                    &elem_restr_qd_i_tet);
97b6faaefaSjeremylt 
98b6faaefaSjeremylt   // -- Bases
99*d1d35e2fSjeremylt   buildmats(q_ref, q_weight, interp, grad);
100*d1d35e2fSjeremylt   CeedBasisCreateH1(ceed, CEED_TRIANGLE, dim, P_tet, Q_tet, interp, grad, q_ref,
101*d1d35e2fSjeremylt                     q_weight, &basis_x_tet);
102b6faaefaSjeremylt 
103*d1d35e2fSjeremylt   buildmats(q_ref, q_weight, interp, grad);
104*d1d35e2fSjeremylt   CeedBasisCreateH1(ceed, CEED_TRIANGLE, 1, P_tet, Q_tet, interp, grad, q_ref,
105*d1d35e2fSjeremylt                     q_weight, &basis_u_tet);
106b6faaefaSjeremylt 
107b6faaefaSjeremylt   // -- QFunctions
108*d1d35e2fSjeremylt   CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup_tet);
109*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_setup_tet, "_weight", 1, CEED_EVAL_WEIGHT);
110*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_setup_tet, "dx", dim*dim, CEED_EVAL_GRAD);
111*d1d35e2fSjeremylt   CeedQFunctionAddOutput(qf_setup_tet, "rho", dim*(dim+1)/2, CEED_EVAL_NONE);
112b6faaefaSjeremylt 
113*d1d35e2fSjeremylt   CeedQFunctionCreateInterior(ceed, 1, diff, diff_loc, &qf_diff_tet);
114*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_diff_tet, "rho", dim*(dim+1)/2, CEED_EVAL_NONE);
115*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_diff_tet, "u", dim, CEED_EVAL_GRAD);
116*d1d35e2fSjeremylt   CeedQFunctionAddOutput(qf_diff_tet, "v", dim, CEED_EVAL_GRAD);
117b6faaefaSjeremylt 
118b6faaefaSjeremylt   // -- Operators
119b6faaefaSjeremylt   // ---- Setup Tet
120*d1d35e2fSjeremylt   CeedOperatorCreate(ceed, qf_setup_tet, CEED_QFUNCTION_NONE,
121*d1d35e2fSjeremylt                      CEED_QFUNCTION_NONE, &op_setup_tet);
122*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_tet, "_weight", CEED_ELEMRESTRICTION_NONE,
123*d1d35e2fSjeremylt                        basis_x_tet,
124a8d32208Sjeremylt                        CEED_VECTOR_NONE);
125*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_tet, "dx", elem_restr_x_tet, basis_x_tet,
126a8d32208Sjeremylt                        CEED_VECTOR_ACTIVE);
127*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_tet, "rho", elem_restr_qd_i_tet,
128*d1d35e2fSjeremylt                        CEED_BASIS_COLLOCATED, q_data_tet);
129b6faaefaSjeremylt   // ---- diff Tet
130*d1d35e2fSjeremylt   CeedOperatorCreate(ceed, qf_diff_tet, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
131*d1d35e2fSjeremylt                      &op_diff_tet);
132*d1d35e2fSjeremylt   CeedOperatorSetField(op_diff_tet, "rho", elem_restr_qd_i_tet,
133*d1d35e2fSjeremylt                        CEED_BASIS_COLLOCATED, q_data_tet);
134*d1d35e2fSjeremylt   CeedOperatorSetField(op_diff_tet, "u", elem_restr_u_tet, basis_u_tet,
135a8d32208Sjeremylt                        CEED_VECTOR_ACTIVE);
136*d1d35e2fSjeremylt   CeedOperatorSetField(op_diff_tet, "v", elem_restr_u_tet, basis_u_tet,
137a8d32208Sjeremylt                        CEED_VECTOR_ACTIVE);
138b6faaefaSjeremylt 
139b6faaefaSjeremylt   // Hex Elements
140*d1d35e2fSjeremylt   for (CeedInt i=0; i<num_elem_hex; i++) {
141*d1d35e2fSjeremylt     col = i % n_x_hex;
142*d1d35e2fSjeremylt     row = i / n_x_hex;
143*d1d35e2fSjeremylt     offset = (n_x_tet*2+1)*(n_y_tet*2)*(1+row) + col*2;
144*d1d35e2fSjeremylt     for (CeedInt j=0; j<P_hex; j++)
145*d1d35e2fSjeremylt       for (CeedInt k=0; k<P_hex; k++)
146*d1d35e2fSjeremylt         ind_x_hex[P_hex*(P_hex*i+k)+j] = offset + k*(n_x_hex*2+1) + j;
147b6faaefaSjeremylt   }
148b6faaefaSjeremylt 
149b6faaefaSjeremylt   // -- Restrictions
150*d1d35e2fSjeremylt   CeedElemRestrictionCreate(ceed, num_elem_hex, P_hex*P_hex, dim, num_dofs,
151*d1d35e2fSjeremylt                             dim*num_dofs,
152*d1d35e2fSjeremylt                             CEED_MEM_HOST, CEED_USE_POINTER, ind_x_hex,
153*d1d35e2fSjeremylt                             &elem_restr_x_hex);
154b6faaefaSjeremylt 
155*d1d35e2fSjeremylt   CeedElemRestrictionCreate(ceed, num_elem_hex, P_hex*P_hex, 1, 1, num_dofs,
156*d1d35e2fSjeremylt                             CEED_MEM_HOST, CEED_USE_POINTER, ind_x_hex,
157*d1d35e2fSjeremylt                             &elem_restr_u_hex);
158*d1d35e2fSjeremylt   CeedInt strides_qd_hex[3] = {1, Q_hex*Q_hex, Q_hex *Q_hex *dim *(dim+1)/2};
159*d1d35e2fSjeremylt   CeedElemRestrictionCreateStrided(ceed, num_elem_hex, Q_hex*Q_hex, dim*(dim+1)/2,
160*d1d35e2fSjeremylt                                    dim*(dim+1)/2*num_qpts_hex, strides_qd_hex,
161*d1d35e2fSjeremylt                                    &elem_restr_qd_i_hex);
162b6faaefaSjeremylt 
163b6faaefaSjeremylt   // -- Bases
164*d1d35e2fSjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, P_hex, Q_hex, CEED_GAUSS,
165*d1d35e2fSjeremylt                                   &basis_x_hex);
166*d1d35e2fSjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P_hex, Q_hex, CEED_GAUSS,
167*d1d35e2fSjeremylt                                   &basis_u_hex);
168b6faaefaSjeremylt 
169b6faaefaSjeremylt   // -- QFunctions
170*d1d35e2fSjeremylt   CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup_hex);
171*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_setup_hex, "_weight", 1, CEED_EVAL_WEIGHT);
172*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_setup_hex, "dx", dim*dim, CEED_EVAL_GRAD);
173*d1d35e2fSjeremylt   CeedQFunctionAddOutput(qf_setup_hex, "rho", dim*(dim+1)/2, CEED_EVAL_NONE);
174b6faaefaSjeremylt 
175*d1d35e2fSjeremylt   CeedQFunctionCreateInterior(ceed, 1, diff, diff_loc, &qf_diff_hex);
176*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_diff_hex, "rho", dim*(dim+1)/2, CEED_EVAL_NONE);
177*d1d35e2fSjeremylt   CeedQFunctionAddInput(qf_diff_hex, "u", dim, CEED_EVAL_GRAD);
178*d1d35e2fSjeremylt   CeedQFunctionAddOutput(qf_diff_hex, "v", dim, CEED_EVAL_GRAD);
179b6faaefaSjeremylt 
180b6faaefaSjeremylt   // -- Operators
181*d1d35e2fSjeremylt   CeedOperatorCreate(ceed, qf_setup_hex, CEED_QFUNCTION_NONE,
182*d1d35e2fSjeremylt                      CEED_QFUNCTION_NONE, &op_setup_hex);
183*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_hex, "_weight", CEED_ELEMRESTRICTION_NONE,
184*d1d35e2fSjeremylt                        basis_x_hex,
185a8d32208Sjeremylt                        CEED_VECTOR_NONE);
186*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_hex, "dx", elem_restr_x_hex, basis_x_hex,
187a8d32208Sjeremylt                        CEED_VECTOR_ACTIVE);
188*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_hex, "rho", elem_restr_qd_i_hex,
189*d1d35e2fSjeremylt                        CEED_BASIS_COLLOCATED, q_data_hex);
190b6faaefaSjeremylt 
191*d1d35e2fSjeremylt   CeedOperatorCreate(ceed, qf_diff_hex, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
192*d1d35e2fSjeremylt                      &op_diff_hex);
193*d1d35e2fSjeremylt   CeedOperatorSetField(op_diff_hex, "rho", elem_restr_qd_i_hex,
194*d1d35e2fSjeremylt                        CEED_BASIS_COLLOCATED, q_data_hex);
195*d1d35e2fSjeremylt   CeedOperatorSetField(op_diff_hex, "u", elem_restr_u_hex, basis_u_hex,
196a8d32208Sjeremylt                        CEED_VECTOR_ACTIVE);
197*d1d35e2fSjeremylt   CeedOperatorSetField(op_diff_hex, "v", elem_restr_u_hex, basis_u_hex,
198a8d32208Sjeremylt                        CEED_VECTOR_ACTIVE);
199b6faaefaSjeremylt 
200b6faaefaSjeremylt   // Composite Operators
201b6faaefaSjeremylt   CeedCompositeOperatorCreate(ceed, &op_setup);
202*d1d35e2fSjeremylt   CeedCompositeOperatorAddSub(op_setup, op_setup_tet);
203*d1d35e2fSjeremylt   CeedCompositeOperatorAddSub(op_setup, op_setup_hex);
204b6faaefaSjeremylt 
205b6faaefaSjeremylt   CeedCompositeOperatorCreate(ceed, &op_diff);
206*d1d35e2fSjeremylt   CeedCompositeOperatorAddSub(op_diff, op_diff_tet);
207*d1d35e2fSjeremylt   CeedCompositeOperatorAddSub(op_diff, op_diff_hex);
208b6faaefaSjeremylt 
209b6faaefaSjeremylt   // Apply Setup Operator
210e97ff134Sjeremylt   CeedOperatorApply(op_setup, X, CEED_VECTOR_NONE, CEED_REQUEST_IMMEDIATE);
211b6faaefaSjeremylt 
212b6faaefaSjeremylt   // Apply diff Operator
213*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_dofs, &U);
214b6faaefaSjeremylt   CeedVectorSetValue(U, 1.0);
215*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_dofs, &V);
216b6faaefaSjeremylt 
217b6faaefaSjeremylt   CeedOperatorApply(op_diff, U, V, CEED_REQUEST_IMMEDIATE);
218b6faaefaSjeremylt 
219b6faaefaSjeremylt   // Check output
220b6faaefaSjeremylt   CeedVectorGetArrayRead(V, CEED_MEM_HOST, &hv);
221*d1d35e2fSjeremylt   for (CeedInt i=0; i<num_dofs; i++)
222b6faaefaSjeremylt     if (fabs(hv[i])>1e-14) printf("Computed: %f != True: 0.0\n", hv[i]);
223b6faaefaSjeremylt   CeedVectorRestoreArrayRead(V, &hv);
224b6faaefaSjeremylt 
225b6faaefaSjeremylt   // Cleanup
226*d1d35e2fSjeremylt   CeedQFunctionDestroy(&qf_setup_tet);
227*d1d35e2fSjeremylt   CeedQFunctionDestroy(&qf_diff_tet);
228*d1d35e2fSjeremylt   CeedOperatorDestroy(&op_setup_tet);
229*d1d35e2fSjeremylt   CeedOperatorDestroy(&op_diff_tet);
230*d1d35e2fSjeremylt   CeedQFunctionDestroy(&qf_setup_hex);
231*d1d35e2fSjeremylt   CeedQFunctionDestroy(&qf_diff_hex);
232*d1d35e2fSjeremylt   CeedOperatorDestroy(&op_setup_hex);
233*d1d35e2fSjeremylt   CeedOperatorDestroy(&op_diff_hex);
234b6faaefaSjeremylt   CeedOperatorDestroy(&op_setup);
235b6faaefaSjeremylt   CeedOperatorDestroy(&op_diff);
236*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_u_tet);
237*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_x_tet);
238*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_qd_i_tet);
239*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_u_hex);
240*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_x_hex);
241*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_qd_i_hex);
242*d1d35e2fSjeremylt   CeedBasisDestroy(&basis_u_tet);
243*d1d35e2fSjeremylt   CeedBasisDestroy(&basis_x_tet);
244*d1d35e2fSjeremylt   CeedBasisDestroy(&basis_u_hex);
245*d1d35e2fSjeremylt   CeedBasisDestroy(&basis_x_hex);
246b6faaefaSjeremylt   CeedVectorDestroy(&X);
247b6faaefaSjeremylt   CeedVectorDestroy(&U);
248b6faaefaSjeremylt   CeedVectorDestroy(&V);
249*d1d35e2fSjeremylt   CeedVectorDestroy(&q_data_tet);
250*d1d35e2fSjeremylt   CeedVectorDestroy(&q_data_hex);
251b6faaefaSjeremylt   CeedDestroy(&ceed);
252b6faaefaSjeremylt   return 0;
253b6faaefaSjeremylt }
254