xref: /libCEED/tests/t554-operator.c (revision 4fee36f0a30516a0b5ad51bf7eb3b32d83efd623)
175f0d5a4SJeremy L Thompson /// @file
275f0d5a4SJeremy L Thompson /// Test creation, action, and destruction for mass matrix composite operator with multigrid level, tensor basis and interpolation basis generation
375f0d5a4SJeremy L Thompson /// \test Test creation, action, and destruction for mass matrix composite operator with multigrid level, tensor basis and interpolation basis
475f0d5a4SJeremy L Thompson /// generation
575f0d5a4SJeremy L Thompson #include <ceed.h>
675f0d5a4SJeremy L Thompson #include <math.h>
775f0d5a4SJeremy L Thompson #include <stdlib.h>
875f0d5a4SJeremy L Thompson 
975f0d5a4SJeremy L Thompson #include "t502-operator.h"
1075f0d5a4SJeremy L Thompson 
1175f0d5a4SJeremy L Thompson int main(int argc, char **argv) {
1275f0d5a4SJeremy L Thompson   Ceed         ceed;
13*4fee36f0SJeremy L Thompson   CeedOperator op_mass_coarse, op_mass_fine, op_prolong, op_restrict;
14*4fee36f0SJeremy L Thompson   CeedVector   x, u_coarse, u_fine, v_coarse, v_fine, p_mult_fine;
15*4fee36f0SJeremy L Thompson   CeedInt      num_elem = 15, num_elem_sub = 5, num_sub_ops = 3, p_coarse = 3, p_fine = 5, q = 8, num_comp = 2;
16*4fee36f0SJeremy L Thompson   CeedInt      num_dofs_x = num_elem + 1, num_dofs_u_coarse = num_elem * (p_coarse - 1) + 1, num_dofs_u_fine = num_elem * (p_fine - 1) + 1;
17*4fee36f0SJeremy L Thompson   CeedInt      ind_u_coarse[num_elem_sub * p_coarse], ind_u_fine[num_elem_sub * p_fine], ind_x[num_elem_sub * 2];
1875f0d5a4SJeremy L Thompson 
1975f0d5a4SJeremy L Thompson   CeedInit(argv[1], &ceed);
2075f0d5a4SJeremy L Thompson 
21*4fee36f0SJeremy L Thompson   // Vectors
22*4fee36f0SJeremy L Thompson   CeedVectorCreate(ceed, num_dofs_x, &x);
23*4fee36f0SJeremy L Thompson   {
24*4fee36f0SJeremy L Thompson     CeedScalar x_array[num_dofs_x];
25*4fee36f0SJeremy L Thompson 
26*4fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < num_dofs_x; i++) x_array[i] = (CeedScalar)i / (num_dofs_x - 1);
27*4fee36f0SJeremy L Thompson     CeedVectorSetArray(x, CEED_MEM_HOST, CEED_COPY_VALUES, x_array);
28*4fee36f0SJeremy L Thompson   }
29*4fee36f0SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_coarse, &u_coarse);
30*4fee36f0SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_coarse, &v_coarse);
31*4fee36f0SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_fine, &u_fine);
32*4fee36f0SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_fine, &v_fine);
33*4fee36f0SJeremy L Thompson 
3475f0d5a4SJeremy L Thompson   // Composite operators
35*4fee36f0SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_mass_coarse);
36*4fee36f0SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_mass_fine);
3775f0d5a4SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_prolong);
3875f0d5a4SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_restrict);
3975f0d5a4SJeremy L Thompson 
4075f0d5a4SJeremy L Thompson   // Setup fine suboperators
4175f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_sub_ops; i++) {
4275f0d5a4SJeremy L Thompson     CeedVector          q_data;
43*4fee36f0SJeremy L Thompson     CeedElemRestriction elem_restriction_x, elem_restriction_q_data, elem_restriction_u_fine;
44*4fee36f0SJeremy L Thompson     CeedBasis           basis_x, basis_u_fine;
4575f0d5a4SJeremy L Thompson     CeedQFunction       qf_setup, qf_mass;
46*4fee36f0SJeremy L Thompson     CeedOperator        sub_op_setup, sub_op_mass_fine;
4775f0d5a4SJeremy L Thompson 
4875f0d5a4SJeremy L Thompson     // -- QData
49*4fee36f0SJeremy L Thompson     CeedVectorCreate(ceed, num_elem * q, &q_data);
5075f0d5a4SJeremy L Thompson 
5175f0d5a4SJeremy L Thompson     // -- Restrictions
5275f0d5a4SJeremy L Thompson     CeedInt offset = num_elem_sub * i;
5375f0d5a4SJeremy L Thompson     for (CeedInt j = 0; j < num_elem_sub; j++) {
5475f0d5a4SJeremy L Thompson       ind_x[2 * j + 0] = offset + j;
5575f0d5a4SJeremy L Thompson       ind_x[2 * j + 1] = offset + j + 1;
5675f0d5a4SJeremy L Thompson     }
57*4fee36f0SJeremy L Thompson     CeedElemRestrictionCreate(ceed, num_elem_sub, 2, 1, 1, num_dofs_x, CEED_MEM_HOST, CEED_COPY_VALUES, ind_x, &elem_restriction_x);
5875f0d5a4SJeremy L Thompson 
59*4fee36f0SJeremy L Thompson     offset = num_elem_sub * i * (p_fine - 1);
6075f0d5a4SJeremy L Thompson     for (CeedInt j = 0; j < num_elem_sub; j++) {
61*4fee36f0SJeremy L Thompson       for (CeedInt k = 0; k < p_fine; k++) {
62*4fee36f0SJeremy L Thompson         ind_u_fine[p_fine * j + k] = offset + j * (p_fine - 1) + k;
6375f0d5a4SJeremy L Thompson       }
6475f0d5a4SJeremy L Thompson     }
65*4fee36f0SJeremy L Thompson     CeedElemRestrictionCreate(ceed, num_elem_sub, p_fine, num_comp, num_dofs_u_fine, num_comp * num_dofs_u_fine, CEED_MEM_HOST, CEED_COPY_VALUES,
66*4fee36f0SJeremy L Thompson                               ind_u_fine, &elem_restriction_u_fine);
6775f0d5a4SJeremy L Thompson 
68*4fee36f0SJeremy L Thompson     CeedInt strides_q_data[3] = {1, q, q};
69*4fee36f0SJeremy L Thompson     CeedElemRestrictionCreateStrided(ceed, num_elem_sub, q, 1, q * num_elem, strides_q_data, &elem_restriction_q_data);
7075f0d5a4SJeremy L Thompson 
7175f0d5a4SJeremy L Thompson     // -- Bases
72*4fee36f0SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, 2, q, CEED_GAUSS, &basis_x);
73*4fee36f0SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, 1, num_comp, p_fine, q, CEED_GAUSS, &basis_u_fine);
7475f0d5a4SJeremy L Thompson 
7575f0d5a4SJeremy L Thompson     // -- QFunctions
7675f0d5a4SJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup);
7775f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_setup, "weight", 1, CEED_EVAL_WEIGHT);
7875f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_setup, "dx", 1 * 1, CEED_EVAL_GRAD);
7975f0d5a4SJeremy L Thompson     CeedQFunctionAddOutput(qf_setup, "q data", 1, CEED_EVAL_NONE);
8075f0d5a4SJeremy L Thompson 
8175f0d5a4SJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass);
8275f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_mass, "q data", 1, CEED_EVAL_NONE);
8375f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_mass, "u", num_comp, CEED_EVAL_INTERP);
8475f0d5a4SJeremy L Thompson     CeedQFunctionAddOutput(qf_mass, "v", num_comp, CEED_EVAL_INTERP);
8575f0d5a4SJeremy L Thompson 
8675f0d5a4SJeremy L Thompson     // -- Operators
8775f0d5a4SJeremy L Thompson     CeedOperatorCreate(ceed, qf_setup, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sub_op_setup);
8875f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_setup, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE);
89*4fee36f0SJeremy L Thompson     CeedOperatorSetField(sub_op_setup, "dx", elem_restriction_x, basis_x, CEED_VECTOR_ACTIVE);
90*4fee36f0SJeremy L Thompson     CeedOperatorSetField(sub_op_setup, "q data", elem_restriction_q_data, CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
9175f0d5a4SJeremy L Thompson 
92*4fee36f0SJeremy L Thompson     CeedOperatorCreate(ceed, qf_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sub_op_mass_fine);
93*4fee36f0SJeremy L Thompson     CeedOperatorSetField(sub_op_mass_fine, "q data", elem_restriction_q_data, CEED_BASIS_COLLOCATED, q_data);
94*4fee36f0SJeremy L Thompson     CeedOperatorSetField(sub_op_mass_fine, "u", elem_restriction_u_fine, basis_u_fine, CEED_VECTOR_ACTIVE);
95*4fee36f0SJeremy L Thompson     CeedOperatorSetField(sub_op_mass_fine, "v", elem_restriction_u_fine, basis_u_fine, CEED_VECTOR_ACTIVE);
9675f0d5a4SJeremy L Thompson 
9775f0d5a4SJeremy L Thompson     // -- Create qdata
98*4fee36f0SJeremy L Thompson     CeedOperatorApply(sub_op_setup, x, q_data, CEED_REQUEST_IMMEDIATE);
9975f0d5a4SJeremy L Thompson 
10075f0d5a4SJeremy L Thompson     // -- Composite operators
101*4fee36f0SJeremy L Thompson     CeedCompositeOperatorAddSub(op_mass_fine, sub_op_mass_fine);
10275f0d5a4SJeremy L Thompson 
10375f0d5a4SJeremy L Thompson     // -- Cleanup
10475f0d5a4SJeremy L Thompson     CeedVectorDestroy(&q_data);
105*4fee36f0SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restriction_u_fine);
106*4fee36f0SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restriction_x);
107*4fee36f0SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restriction_q_data);
108*4fee36f0SJeremy L Thompson     CeedBasisDestroy(&basis_u_fine);
10975f0d5a4SJeremy L Thompson     CeedBasisDestroy(&basis_x);
11075f0d5a4SJeremy L Thompson     CeedQFunctionDestroy(&qf_setup);
11175f0d5a4SJeremy L Thompson     CeedQFunctionDestroy(&qf_mass);
11275f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_setup);
113*4fee36f0SJeremy L Thompson     CeedOperatorDestroy(&sub_op_mass_fine);
11475f0d5a4SJeremy L Thompson   }
11575f0d5a4SJeremy L Thompson 
11675f0d5a4SJeremy L Thompson   // Scale for suboperator multiplicity
117*4fee36f0SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_fine, &p_mult_fine);
118*4fee36f0SJeremy L Thompson   CeedCompositeOperatorGetMultiplicity(op_mass_fine, 0, NULL, p_mult_fine);
11975f0d5a4SJeremy L Thompson 
12075f0d5a4SJeremy L Thompson   // Setup coarse and prolong/restriction suboperators
12175f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_sub_ops; i++) {
122*4fee36f0SJeremy L Thompson     CeedElemRestriction elem_restriction_u_coarse;
123*4fee36f0SJeremy L Thompson     CeedBasis           basis_u_coarse;
124*4fee36f0SJeremy L Thompson     CeedOperator       *sub_ops_mass_fine, sub_op_mass_coarse, sub_op_prolong, sub_op_restrict;
12575f0d5a4SJeremy L Thompson 
12675f0d5a4SJeremy L Thompson     // -- Fine grid operator
127*4fee36f0SJeremy L Thompson     CeedCompositeOperatorGetSubList(op_mass_fine, &sub_ops_mass_fine);
12875f0d5a4SJeremy L Thompson 
12975f0d5a4SJeremy L Thompson     // -- Restrictions
130*4fee36f0SJeremy L Thompson     CeedInt offset = num_elem_sub * i * (p_coarse - 1);
13175f0d5a4SJeremy L Thompson     for (CeedInt j = 0; j < num_elem_sub; j++) {
132*4fee36f0SJeremy L Thompson       for (CeedInt k = 0; k < p_coarse; k++) {
133*4fee36f0SJeremy L Thompson         ind_u_coarse[p_coarse * j + k] = offset + j * (p_coarse - 1) + k;
13475f0d5a4SJeremy L Thompson       }
13575f0d5a4SJeremy L Thompson     }
136*4fee36f0SJeremy L Thompson     CeedElemRestrictionCreate(ceed, num_elem_sub, p_coarse, num_comp, num_dofs_u_coarse, num_comp * num_dofs_u_coarse, CEED_MEM_HOST,
137*4fee36f0SJeremy L Thompson                               CEED_COPY_VALUES, ind_u_coarse, &elem_restriction_u_coarse);
13875f0d5a4SJeremy L Thompson 
13975f0d5a4SJeremy L Thompson     // -- Bases
140*4fee36f0SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, 1, num_comp, p_coarse, q, CEED_GAUSS, &basis_u_coarse);
14175f0d5a4SJeremy L Thompson 
14275f0d5a4SJeremy L Thompson     // -- Create multigrid level
143*4fee36f0SJeremy L Thompson     CeedOperatorMultigridLevelCreate(sub_ops_mass_fine[i], p_mult_fine, elem_restriction_u_coarse, basis_u_coarse, &sub_op_mass_coarse,
144*4fee36f0SJeremy L Thompson                                      &sub_op_prolong, &sub_op_restrict);
14575f0d5a4SJeremy L Thompson 
14675f0d5a4SJeremy L Thompson     // -- Composite operators
147*4fee36f0SJeremy L Thompson     CeedCompositeOperatorAddSub(op_mass_coarse, sub_op_mass_coarse);
14875f0d5a4SJeremy L Thompson     CeedCompositeOperatorAddSub(op_prolong, sub_op_prolong);
14975f0d5a4SJeremy L Thompson     CeedCompositeOperatorAddSub(op_restrict, sub_op_restrict);
15075f0d5a4SJeremy L Thompson 
15175f0d5a4SJeremy L Thompson     // -- Cleanup
152*4fee36f0SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restriction_u_coarse);
153*4fee36f0SJeremy L Thompson     CeedBasisDestroy(&basis_u_coarse);
154*4fee36f0SJeremy L Thompson     CeedOperatorDestroy(&sub_op_mass_coarse);
15575f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_prolong);
15675f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_restrict);
15775f0d5a4SJeremy L Thompson   }
15875f0d5a4SJeremy L Thompson 
15975f0d5a4SJeremy L Thompson   // Coarse problem
160*4fee36f0SJeremy L Thompson   CeedVectorSetValue(u_coarse, 1.0);
161*4fee36f0SJeremy L Thompson   CeedOperatorApply(op_mass_coarse, u_coarse, v_coarse, CEED_REQUEST_IMMEDIATE);
16275f0d5a4SJeremy L Thompson 
16375f0d5a4SJeremy L Thompson   // Check output
164*4fee36f0SJeremy L Thompson   {
165*4fee36f0SJeremy L Thompson     const CeedScalar *v_array;
166*4fee36f0SJeremy L Thompson     CeedScalar        sum = 0.;
167*4fee36f0SJeremy L Thompson 
168*4fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(v_coarse, CEED_MEM_HOST, &v_array);
169*4fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < num_comp * num_dofs_u_coarse; i++) {
170*4fee36f0SJeremy L Thompson       sum += v_array[i];
17175f0d5a4SJeremy L Thompson     }
172*4fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(v_coarse, &v_array);
17375f0d5a4SJeremy L Thompson     if (fabs(sum - 2.) > 1000. * CEED_EPSILON) printf("Computed Area Coarse Grid: %f != True Area: 2.0\n", sum);
174*4fee36f0SJeremy L Thompson   }
17575f0d5a4SJeremy L Thompson 
17675f0d5a4SJeremy L Thompson   // Prolong coarse u
177*4fee36f0SJeremy L Thompson   CeedOperatorApply(op_prolong, u_coarse, u_fine, CEED_REQUEST_IMMEDIATE);
17875f0d5a4SJeremy L Thompson 
17975f0d5a4SJeremy L Thompson   // Fine problem
180*4fee36f0SJeremy L Thompson   CeedOperatorApply(op_mass_fine, u_fine, v_fine, CEED_REQUEST_IMMEDIATE);
18175f0d5a4SJeremy L Thompson 
18275f0d5a4SJeremy L Thompson   // Check output
183*4fee36f0SJeremy L Thompson   {
184*4fee36f0SJeremy L Thompson     const CeedScalar *v_array;
185*4fee36f0SJeremy L Thompson     CeedScalar        sum = 0.;
186*4fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(v_fine, CEED_MEM_HOST, &v_array);
187*4fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < num_comp * num_dofs_u_fine; i++) {
188*4fee36f0SJeremy L Thompson       sum += v_array[i];
18975f0d5a4SJeremy L Thompson     }
190*4fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(v_fine, &v_array);
191*4fee36f0SJeremy L Thompson 
19275f0d5a4SJeremy L Thompson     if (fabs(sum - 2.) > 1000. * CEED_EPSILON) printf("Computed Area Fine Grid: %f != True Area: 2.0\n", sum);
193*4fee36f0SJeremy L Thompson   }
19475f0d5a4SJeremy L Thompson   // Restrict state to coarse grid
195*4fee36f0SJeremy L Thompson   CeedOperatorApply(op_restrict, v_fine, v_coarse, CEED_REQUEST_IMMEDIATE);
19675f0d5a4SJeremy L Thompson 
19775f0d5a4SJeremy L Thompson   // Check output
198*4fee36f0SJeremy L Thompson   {
199*4fee36f0SJeremy L Thompson     const CeedScalar *v_array;
200*4fee36f0SJeremy L Thompson     CeedScalar        sum = 0.;
201*4fee36f0SJeremy L Thompson 
202*4fee36f0SJeremy L Thompson     CeedVectorGetArrayRead(v_coarse, CEED_MEM_HOST, &v_array);
203*4fee36f0SJeremy L Thompson     for (CeedInt i = 0; i < num_comp * num_dofs_u_coarse; i++) {
204*4fee36f0SJeremy L Thompson       sum += v_array[i];
20575f0d5a4SJeremy L Thompson     }
206*4fee36f0SJeremy L Thompson     CeedVectorRestoreArrayRead(v_coarse, &v_array);
20775f0d5a4SJeremy L Thompson     if (fabs(sum - 2.) > 1000. * CEED_EPSILON) printf("Computed Area Coarse Grid: %f != True Area: 2.0\n", sum);
208*4fee36f0SJeremy L Thompson   }
20975f0d5a4SJeremy L Thompson 
21075f0d5a4SJeremy L Thompson   // Cleanup
211*4fee36f0SJeremy L Thompson   CeedVectorDestroy(&x);
212*4fee36f0SJeremy L Thompson   CeedVectorDestroy(&u_coarse);
213*4fee36f0SJeremy L Thompson   CeedVectorDestroy(&u_fine);
214*4fee36f0SJeremy L Thompson   CeedVectorDestroy(&v_coarse);
215*4fee36f0SJeremy L Thompson   CeedVectorDestroy(&v_fine);
216*4fee36f0SJeremy L Thompson   CeedVectorDestroy(&p_mult_fine);
217*4fee36f0SJeremy L Thompson   CeedOperatorDestroy(&op_mass_coarse);
218*4fee36f0SJeremy L Thompson   CeedOperatorDestroy(&op_mass_fine);
21975f0d5a4SJeremy L Thompson   CeedOperatorDestroy(&op_prolong);
22075f0d5a4SJeremy L Thompson   CeedOperatorDestroy(&op_restrict);
22175f0d5a4SJeremy L Thompson   CeedDestroy(&ceed);
22275f0d5a4SJeremy L Thompson   return 0;
22375f0d5a4SJeremy L Thompson }
224