xref: /libCEED/tests/t532-operator.c (revision d1d35e2f02dc969aee8debf3fd943dd784aa847a)
11d102b48SJeremy L Thompson /// @file
21d102b48SJeremy L Thompson /// Test assembly of mass and Poisson operator QFunction
31d102b48SJeremy L Thompson /// \test Test assembly of mass and Poisson operator QFunction
41d102b48SJeremy L Thompson #include <ceed.h>
51d102b48SJeremy L Thompson #include <stdlib.h>
61d102b48SJeremy L Thompson #include <math.h>
71d102b48SJeremy L Thompson #include "t532-operator.h"
81d102b48SJeremy L Thompson 
91d102b48SJeremy L Thompson int main(int argc, char **argv) {
101d102b48SJeremy L Thompson   Ceed ceed;
11*d1d35e2fSjeremylt   CeedElemRestriction elem_restr_x, elem_restr_u,
12*d1d35e2fSjeremylt                       elem_restr_qd_mass_i, elem_restr_qd_diff_i, elem_restr_lin_i;
13*d1d35e2fSjeremylt   CeedBasis basis_x, basis_u;
141d102b48SJeremy L Thompson   CeedQFunction qf_setup_mass, qf_setup_diff, qf_apply, qf_apply_lin;
151d102b48SJeremy L Thompson   CeedOperator op_setup_mass, op_setup_diff, op_apply, op_apply_lin;
16*d1d35e2fSjeremylt   CeedVector q_data_mass, q_data_diff, X, A, u, v;
17*d1d35e2fSjeremylt   CeedInt num_elem = 6, P = 3, Q = 4, dim = 2;
181d102b48SJeremy L Thompson   CeedInt nx = 3, ny = 2;
19*d1d35e2fSjeremylt   CeedInt num_dofs = (nx*2+1)*(ny*2+1), num_qpts = num_elem*Q*Q;
20*d1d35e2fSjeremylt   CeedInt ind_x[num_elem*P*P];
21*d1d35e2fSjeremylt   CeedScalar x[dim*num_dofs];
221d102b48SJeremy L Thompson 
231d102b48SJeremy L Thompson   CeedInit(argv[1], &ceed);
241d102b48SJeremy L Thompson 
251d102b48SJeremy L Thompson   // DoF Coordinates
261d102b48SJeremy L Thompson   for (CeedInt i=0; i<nx*2+1; i++)
271d102b48SJeremy L Thompson     for (CeedInt j=0; j<ny*2+1; j++) {
28*d1d35e2fSjeremylt       x[i+j*(nx*2+1)+0*num_dofs] = (CeedScalar) i / (2*nx);
29*d1d35e2fSjeremylt       x[i+j*(nx*2+1)+1*num_dofs] = (CeedScalar) j / (2*ny);
301d102b48SJeremy L Thompson     }
31*d1d35e2fSjeremylt   CeedVectorCreate(ceed, dim*num_dofs, &X);
321d102b48SJeremy L Thompson   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
331d102b48SJeremy L Thompson 
341d102b48SJeremy L Thompson   // Qdata Vectors
35*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_qpts, &q_data_mass);
36*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_qpts*dim*(dim+1)/2, &q_data_diff);
371d102b48SJeremy L Thompson 
381d102b48SJeremy L Thompson   // Element Setup
39*d1d35e2fSjeremylt   for (CeedInt i=0; i<num_elem; i++) {
401d102b48SJeremy L Thompson     CeedInt col, row, offset;
411d102b48SJeremy L Thompson     col = i % nx;
421d102b48SJeremy L Thompson     row = i / nx;
431d102b48SJeremy L Thompson     offset = col*(P-1) + row*(nx*2+1)*(P-1);
441d102b48SJeremy L Thompson     for (CeedInt j=0; j<P; j++)
451d102b48SJeremy L Thompson       for (CeedInt k=0; k<P; k++)
46*d1d35e2fSjeremylt         ind_x[P*(P*i+k)+j] = offset + k*(nx*2+1) + j;
471d102b48SJeremy L Thompson   }
481d102b48SJeremy L Thompson 
491d102b48SJeremy L Thompson   // Restrictions
50*d1d35e2fSjeremylt   CeedElemRestrictionCreate(ceed, num_elem, P*P, dim, num_dofs, dim*num_dofs,
51*d1d35e2fSjeremylt                             CEED_MEM_HOST, CEED_USE_POINTER, ind_x, &elem_restr_x);
521d102b48SJeremy L Thompson 
53*d1d35e2fSjeremylt   CeedElemRestrictionCreate(ceed, num_elem, P*P, 1, 1, num_dofs, CEED_MEM_HOST,
54*d1d35e2fSjeremylt                             CEED_USE_POINTER, ind_x, &elem_restr_u);
55*d1d35e2fSjeremylt   CeedInt strides_qd_mass[3] = {1, Q*Q, Q*Q};
56*d1d35e2fSjeremylt   CeedElemRestrictionCreateStrided(ceed, num_elem, Q*Q, 1, num_qpts,
57*d1d35e2fSjeremylt                                    strides_qd_mass,
58*d1d35e2fSjeremylt                                    &elem_restr_qd_mass_i);
591d102b48SJeremy L Thompson 
60*d1d35e2fSjeremylt   CeedInt strides_qd_diff[3] = {1, Q*Q, Q *Q *dim *(dim+1)/2};
61*d1d35e2fSjeremylt   CeedElemRestrictionCreateStrided(ceed, num_elem, Q*Q, dim*(dim+1)/2,
62*d1d35e2fSjeremylt                                    dim*(dim+1)/2*num_qpts,
63*d1d35e2fSjeremylt                                    strides_qd_diff, &elem_restr_qd_diff_i);
641d102b48SJeremy L Thompson 
651d102b48SJeremy L Thompson   // Bases
66*d1d35e2fSjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, P, Q, CEED_GAUSS, &basis_x);
67*d1d35e2fSjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &basis_u);
681d102b48SJeremy L Thompson 
691d102b48SJeremy L Thompson   // QFunction - setup mass
701d102b48SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, setup_mass, setup_mass_loc,
711d102b48SJeremy L Thompson                               &qf_setup_mass);
721d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_setup_mass, "dx", dim*dim, CEED_EVAL_GRAD);
731d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_setup_mass, "_weight", 1, CEED_EVAL_WEIGHT);
741d102b48SJeremy L Thompson   CeedQFunctionAddOutput(qf_setup_mass, "qdata", 1, CEED_EVAL_NONE);
751d102b48SJeremy L Thompson 
761d102b48SJeremy L Thompson   // Operator - setup mass
77442e7f0bSjeremylt   CeedOperatorCreate(ceed, qf_setup_mass, CEED_QFUNCTION_NONE,
78442e7f0bSjeremylt                      CEED_QFUNCTION_NONE, &op_setup_mass);
79*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_mass, "dx", elem_restr_x, basis_x,
80*d1d35e2fSjeremylt                        CEED_VECTOR_ACTIVE);
81*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_mass, "_weight", CEED_ELEMRESTRICTION_NONE,
82*d1d35e2fSjeremylt                        basis_x,
83a8d32208Sjeremylt                        CEED_VECTOR_NONE);
84*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_mass, "qdata", elem_restr_qd_mass_i,
851d102b48SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
861d102b48SJeremy L Thompson 
871d102b48SJeremy L Thompson   // QFunction - setup diff
881d102b48SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, setup_diff, setup_diff_loc,
891d102b48SJeremy L Thompson                               &qf_setup_diff);
901d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_setup_diff, "dx", dim*dim, CEED_EVAL_GRAD);
911d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_setup_diff, "_weight", 1, CEED_EVAL_WEIGHT);
921d102b48SJeremy L Thompson   CeedQFunctionAddOutput(qf_setup_diff, "qdata", dim*(dim+1)/2, CEED_EVAL_NONE);
931d102b48SJeremy L Thompson 
941d102b48SJeremy L Thompson   // Operator - setup diff
95442e7f0bSjeremylt   CeedOperatorCreate(ceed, qf_setup_diff, CEED_QFUNCTION_NONE,
96442e7f0bSjeremylt                      CEED_QFUNCTION_NONE, &op_setup_diff);
97*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_diff, "dx", elem_restr_x, basis_x,
98*d1d35e2fSjeremylt                        CEED_VECTOR_ACTIVE);
99*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_diff, "_weight", CEED_ELEMRESTRICTION_NONE,
100*d1d35e2fSjeremylt                        basis_x,
101a8d32208Sjeremylt                        CEED_VECTOR_NONE);
102*d1d35e2fSjeremylt   CeedOperatorSetField(op_setup_diff, "qdata", elem_restr_qd_diff_i,
1031d102b48SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
1041d102b48SJeremy L Thompson 
1051d102b48SJeremy L Thompson   // Apply Setup Operators
106*d1d35e2fSjeremylt   CeedOperatorApply(op_setup_mass, X, q_data_mass, CEED_REQUEST_IMMEDIATE);
107*d1d35e2fSjeremylt   CeedOperatorApply(op_setup_diff, X, q_data_diff, CEED_REQUEST_IMMEDIATE);
1081d102b48SJeremy L Thompson 
1091d102b48SJeremy L Thompson   // QFunction - apply
1101d102b48SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply);
1111d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply, "du", dim, CEED_EVAL_GRAD);
1121d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply, "qdata_mass", 1, CEED_EVAL_NONE);
1131d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply, "qdata_diff", dim*(dim+1)/2, CEED_EVAL_NONE);
1141d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP);
1151d102b48SJeremy L Thompson   CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP);
1161d102b48SJeremy L Thompson   CeedQFunctionAddOutput(qf_apply, "dv", dim, CEED_EVAL_GRAD);
1171d102b48SJeremy L Thompson 
1181d102b48SJeremy L Thompson   // Operator - apply
119442e7f0bSjeremylt   CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
120442e7f0bSjeremylt                      &op_apply);
121*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply, "du", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE);
122*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply, "qdata_mass", elem_restr_qd_mass_i,
123*d1d35e2fSjeremylt                        CEED_BASIS_COLLOCATED, q_data_mass);
124*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply, "qdata_diff", elem_restr_qd_diff_i,
125*d1d35e2fSjeremylt                        CEED_BASIS_COLLOCATED, q_data_diff);
126*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply, "u", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE);
127*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply, "v", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE);
128*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply, "dv", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE);
1291d102b48SJeremy L Thompson 
1301d102b48SJeremy L Thompson   // Apply original operator
131*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_dofs, &u);
1321d102b48SJeremy L Thompson   CeedVectorSetValue(u, 1.0);
133*d1d35e2fSjeremylt   CeedVectorCreate(ceed, num_dofs, &v);
1341d102b48SJeremy L Thompson   CeedVectorSetValue(v, 0.0);
1351d102b48SJeremy L Thompson   CeedOperatorApply(op_apply, u, v, CEED_REQUEST_IMMEDIATE);
1361d102b48SJeremy L Thompson 
1371d102b48SJeremy L Thompson   // Check output
1381d102b48SJeremy L Thompson   CeedScalar area = 0.0;
1391d102b48SJeremy L Thompson   const CeedScalar *vv;
1401d102b48SJeremy L Thompson   CeedVectorGetArrayRead(v, CEED_MEM_HOST, &vv);
141*d1d35e2fSjeremylt   for (CeedInt i=0; i<num_dofs; i++)
1421d102b48SJeremy L Thompson     area += vv[i];
1431d102b48SJeremy L Thompson   CeedVectorRestoreArrayRead(v, &vv);
1444e367ab1Sjeremylt   if (fabs(area - 1.0) > 1e-14)
1451d102b48SJeremy L Thompson     // LCOV_EXCL_START
1461d102b48SJeremy L Thompson     printf("Error: True operator computed area = %f != 1.0\n", area);
1471d102b48SJeremy L Thompson   // LCOV_EXCL_STOP
1481d102b48SJeremy L Thompson 
1491d102b48SJeremy L Thompson   // Assemble QFunction
150*d1d35e2fSjeremylt   CeedOperatorLinearAssembleQFunction(op_apply, &A, &elem_restr_lin_i,
1511d102b48SJeremy L Thompson                                       CEED_REQUEST_IMMEDIATE);
1521d102b48SJeremy L Thompson 
1531d102b48SJeremy L Thompson   // QFunction - apply assembled
1541d102b48SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, apply_lin, apply_lin_loc, &qf_apply_lin);
1551d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply_lin, "du", dim, CEED_EVAL_GRAD);
1561d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply_lin, "qdata", (dim+1)*(dim+1), CEED_EVAL_NONE);
1571d102b48SJeremy L Thompson   CeedQFunctionAddInput(qf_apply_lin, "u", 1, CEED_EVAL_INTERP);
1581d102b48SJeremy L Thompson   CeedQFunctionAddOutput(qf_apply_lin, "v", 1, CEED_EVAL_INTERP);
1591d102b48SJeremy L Thompson   CeedQFunctionAddOutput(qf_apply_lin, "dv", dim, CEED_EVAL_GRAD);
1601d102b48SJeremy L Thompson 
1611d102b48SJeremy L Thompson   // Operator - apply assembled
162442e7f0bSjeremylt   CeedOperatorCreate(ceed, qf_apply_lin, CEED_QFUNCTION_NONE,
163442e7f0bSjeremylt                      CEED_QFUNCTION_NONE, &op_apply_lin);
164*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply_lin, "du", elem_restr_u, basis_u,
165*d1d35e2fSjeremylt                        CEED_VECTOR_ACTIVE);
166*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply_lin, "qdata", elem_restr_lin_i,
1671d102b48SJeremy L Thompson                        CEED_BASIS_COLLOCATED, A);
168*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply_lin, "u", elem_restr_u, basis_u,
169*d1d35e2fSjeremylt                        CEED_VECTOR_ACTIVE);
170*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply_lin, "v", elem_restr_u, basis_u,
171*d1d35e2fSjeremylt                        CEED_VECTOR_ACTIVE);
172*d1d35e2fSjeremylt   CeedOperatorSetField(op_apply_lin, "dv", elem_restr_u, basis_u,
173*d1d35e2fSjeremylt                        CEED_VECTOR_ACTIVE);
1741d102b48SJeremy L Thompson 
1751d102b48SJeremy L Thompson   // Apply assembled QFunction operator
1761d102b48SJeremy L Thompson   CeedVectorSetValue(v, 0.0);
1771d102b48SJeremy L Thompson   CeedOperatorApply(op_apply_lin, u, v, CEED_REQUEST_IMMEDIATE);
1781d102b48SJeremy L Thompson 
1791d102b48SJeremy L Thompson   // Check output
1801d102b48SJeremy L Thompson   area = 0.0;
1811d102b48SJeremy L Thompson   CeedVectorGetArrayRead(v, CEED_MEM_HOST, &vv);
182*d1d35e2fSjeremylt   for (CeedInt i=0; i<num_dofs; i++)
1831d102b48SJeremy L Thompson     area += vv[i];
1841d102b48SJeremy L Thompson   CeedVectorRestoreArrayRead(v, &vv);
1854e367ab1Sjeremylt   if (fabs(area - 1.0) > 1e-14)
1861d102b48SJeremy L Thompson     // LCOV_EXCL_START
1871d102b48SJeremy L Thompson     printf("Error: Assembled operator computed area = %f != 1.0\n", area);
1881d102b48SJeremy L Thompson   // LCOV_EXCL_STOP
1891d102b48SJeremy L Thompson 
1901d102b48SJeremy L Thompson   // Cleanup
1911d102b48SJeremy L Thompson   CeedQFunctionDestroy(&qf_setup_mass);
1921d102b48SJeremy L Thompson   CeedQFunctionDestroy(&qf_setup_diff);
1931d102b48SJeremy L Thompson   CeedQFunctionDestroy(&qf_apply);
1941d102b48SJeremy L Thompson   CeedQFunctionDestroy(&qf_apply_lin);
1951d102b48SJeremy L Thompson   CeedOperatorDestroy(&op_setup_mass);
1961d102b48SJeremy L Thompson   CeedOperatorDestroy(&op_setup_diff);
1971d102b48SJeremy L Thompson   CeedOperatorDestroy(&op_apply);
1981d102b48SJeremy L Thompson   CeedOperatorDestroy(&op_apply_lin);
199*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_u);
200*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_x);
201*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_qd_mass_i);
202*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_qd_diff_i);
203*d1d35e2fSjeremylt   CeedElemRestrictionDestroy(&elem_restr_lin_i);
204*d1d35e2fSjeremylt   CeedBasisDestroy(&basis_u);
205*d1d35e2fSjeremylt   CeedBasisDestroy(&basis_x);
2061d102b48SJeremy L Thompson   CeedVectorDestroy(&X);
2071d102b48SJeremy L Thompson   CeedVectorDestroy(&A);
208*d1d35e2fSjeremylt   CeedVectorDestroy(&q_data_mass);
209*d1d35e2fSjeremylt   CeedVectorDestroy(&q_data_diff);
2101d102b48SJeremy L Thompson   CeedVectorDestroy(&u);
2111d102b48SJeremy L Thompson   CeedVectorDestroy(&v);
2121d102b48SJeremy L Thompson   CeedDestroy(&ceed);
2131d102b48SJeremy L Thompson   return 0;
2141d102b48SJeremy L Thompson }
215