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