xref: /libCEED/tests/t554-operator.c (revision 75f0d5a43978d294e569c8e99a70cefd4b888bc4)
1*75f0d5a4SJeremy L Thompson /// @file
2*75f0d5a4SJeremy L Thompson /// Test creation, action, and destruction for mass matrix composite operator with multigrid level, tensor basis and interpolation basis generation
3*75f0d5a4SJeremy L Thompson /// \test Test creation, action, and destruction for mass matrix composite operator with multigrid level, tensor basis and interpolation basis
4*75f0d5a4SJeremy L Thompson /// generation
5*75f0d5a4SJeremy L Thompson #include <ceed.h>
6*75f0d5a4SJeremy L Thompson #include <math.h>
7*75f0d5a4SJeremy L Thompson #include <stdlib.h>
8*75f0d5a4SJeremy L Thompson 
9*75f0d5a4SJeremy L Thompson #include "t502-operator.h"
10*75f0d5a4SJeremy L Thompson 
11*75f0d5a4SJeremy L Thompson int main(int argc, char **argv) {
12*75f0d5a4SJeremy L Thompson   Ceed              ceed;
13*75f0d5a4SJeremy L Thompson   CeedOperator      op_mass_c, op_mass_f, op_prolong, op_restrict;
14*75f0d5a4SJeremy L Thompson   CeedVector        X, U_c, U_f, V_c, V_f, p_mult_f;
15*75f0d5a4SJeremy L Thompson   const CeedScalar *hv;
16*75f0d5a4SJeremy L Thompson   CeedInt           num_elem = 15, num_elem_sub = 5, num_sub_ops = 3, P_c = 3, P_f = 5, Q = 8, num_comp = 2;
17*75f0d5a4SJeremy L Thompson   CeedInt           num_dofs_x = num_elem + 1, num_dofs_u_c = num_elem * (P_c - 1) + 1, num_dofs_u_f = num_elem * (P_f - 1) + 1;
18*75f0d5a4SJeremy L Thompson   CeedInt           ind_u_c[num_elem_sub * P_c], ind_u_f[num_elem_sub * P_f], ind_x[num_elem_sub * 2];
19*75f0d5a4SJeremy L Thompson   CeedScalar        x[num_dofs_x];
20*75f0d5a4SJeremy L Thompson   CeedScalar        sum;
21*75f0d5a4SJeremy L Thompson 
22*75f0d5a4SJeremy L Thompson   CeedInit(argv[1], &ceed);
23*75f0d5a4SJeremy L Thompson 
24*75f0d5a4SJeremy L Thompson   // Composite operators
25*75f0d5a4SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_mass_c);
26*75f0d5a4SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_mass_f);
27*75f0d5a4SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_prolong);
28*75f0d5a4SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_restrict);
29*75f0d5a4SJeremy L Thompson 
30*75f0d5a4SJeremy L Thompson   // Coordinates
31*75f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_dofs_x; i++) x[i] = (CeedScalar)i / (num_dofs_x - 1);
32*75f0d5a4SJeremy L Thompson   CeedVectorCreate(ceed, num_dofs_x, &X);
33*75f0d5a4SJeremy L Thompson   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
34*75f0d5a4SJeremy L Thompson 
35*75f0d5a4SJeremy L Thompson   // Setup fine suboperators
36*75f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_sub_ops; i++) {
37*75f0d5a4SJeremy L Thompson     CeedVector          q_data;
38*75f0d5a4SJeremy L Thompson     CeedElemRestriction elem_restr_x, elem_restr_qd_i, elem_restr_u_f;
39*75f0d5a4SJeremy L Thompson     CeedBasis           basis_x, basis_u_f;
40*75f0d5a4SJeremy L Thompson     CeedQFunction       qf_setup, qf_mass;
41*75f0d5a4SJeremy L Thompson     CeedOperator        sub_op_setup, sub_op_mass_f;
42*75f0d5a4SJeremy L Thompson 
43*75f0d5a4SJeremy L Thompson     // -- QData
44*75f0d5a4SJeremy L Thompson     CeedVectorCreate(ceed, num_elem * Q, &q_data);
45*75f0d5a4SJeremy L Thompson 
46*75f0d5a4SJeremy L Thompson     // -- Restrictions
47*75f0d5a4SJeremy L Thompson     CeedInt offset = num_elem_sub * i;
48*75f0d5a4SJeremy L Thompson     for (CeedInt j = 0; j < num_elem_sub; j++) {
49*75f0d5a4SJeremy L Thompson       ind_x[2 * j + 0] = offset + j;
50*75f0d5a4SJeremy L Thompson       ind_x[2 * j + 1] = offset + j + 1;
51*75f0d5a4SJeremy L Thompson     }
52*75f0d5a4SJeremy L Thompson     CeedElemRestrictionCreate(ceed, num_elem_sub, 2, 1, 1, num_dofs_x, CEED_MEM_HOST, CEED_COPY_VALUES, ind_x, &elem_restr_x);
53*75f0d5a4SJeremy L Thompson 
54*75f0d5a4SJeremy L Thompson     offset = num_elem_sub * i * (P_f - 1);
55*75f0d5a4SJeremy L Thompson     for (CeedInt j = 0; j < num_elem_sub; j++) {
56*75f0d5a4SJeremy L Thompson       for (CeedInt k = 0; k < P_f; k++) {
57*75f0d5a4SJeremy L Thompson         ind_u_f[P_f * j + k] = offset + j * (P_f - 1) + k;
58*75f0d5a4SJeremy L Thompson       }
59*75f0d5a4SJeremy L Thompson     }
60*75f0d5a4SJeremy L Thompson     CeedElemRestrictionCreate(ceed, num_elem_sub, P_f, num_comp, num_dofs_u_f, num_comp * num_dofs_u_f, CEED_MEM_HOST, CEED_COPY_VALUES, ind_u_f,
61*75f0d5a4SJeremy L Thompson                               &elem_restr_u_f);
62*75f0d5a4SJeremy L Thompson 
63*75f0d5a4SJeremy L Thompson     CeedInt strides_qd[3] = {1, Q, Q};
64*75f0d5a4SJeremy L Thompson     CeedElemRestrictionCreateStrided(ceed, num_elem_sub, Q, 1, Q * num_elem, strides_qd, &elem_restr_qd_i);
65*75f0d5a4SJeremy L Thompson 
66*75f0d5a4SJeremy L Thompson     // -- Bases
67*75f0d5a4SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, 2, Q, CEED_GAUSS, &basis_x);
68*75f0d5a4SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, 1, num_comp, P_f, Q, CEED_GAUSS, &basis_u_f);
69*75f0d5a4SJeremy L Thompson 
70*75f0d5a4SJeremy L Thompson     // -- QFunctions
71*75f0d5a4SJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup);
72*75f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_setup, "weight", 1, CEED_EVAL_WEIGHT);
73*75f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_setup, "dx", 1 * 1, CEED_EVAL_GRAD);
74*75f0d5a4SJeremy L Thompson     CeedQFunctionAddOutput(qf_setup, "qdata", 1, CEED_EVAL_NONE);
75*75f0d5a4SJeremy L Thompson 
76*75f0d5a4SJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass);
77*75f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_mass, "qdata", 1, CEED_EVAL_NONE);
78*75f0d5a4SJeremy L Thompson     CeedQFunctionAddInput(qf_mass, "u", num_comp, CEED_EVAL_INTERP);
79*75f0d5a4SJeremy L Thompson     CeedQFunctionAddOutput(qf_mass, "v", num_comp, CEED_EVAL_INTERP);
80*75f0d5a4SJeremy L Thompson 
81*75f0d5a4SJeremy L Thompson     // -- Operators
82*75f0d5a4SJeremy L Thompson     CeedOperatorCreate(ceed, qf_setup, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sub_op_setup);
83*75f0d5a4SJeremy L Thompson     CeedOperatorCreate(ceed, qf_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &sub_op_mass_f);
84*75f0d5a4SJeremy L Thompson 
85*75f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_setup, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE);
86*75f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_setup, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE);
87*75f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_setup, "qdata", elem_restr_qd_i, CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
88*75f0d5a4SJeremy L Thompson 
89*75f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_mass_f, "qdata", elem_restr_qd_i, CEED_BASIS_COLLOCATED, q_data);
90*75f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_mass_f, "u", elem_restr_u_f, basis_u_f, CEED_VECTOR_ACTIVE);
91*75f0d5a4SJeremy L Thompson     CeedOperatorSetField(sub_op_mass_f, "v", elem_restr_u_f, basis_u_f, CEED_VECTOR_ACTIVE);
92*75f0d5a4SJeremy L Thompson 
93*75f0d5a4SJeremy L Thompson     // -- Create qdata
94*75f0d5a4SJeremy L Thompson     CeedOperatorApply(sub_op_setup, X, q_data, CEED_REQUEST_IMMEDIATE);
95*75f0d5a4SJeremy L Thompson 
96*75f0d5a4SJeremy L Thompson     // -- Composite operators
97*75f0d5a4SJeremy L Thompson     CeedCompositeOperatorAddSub(op_mass_f, sub_op_mass_f);
98*75f0d5a4SJeremy L Thompson 
99*75f0d5a4SJeremy L Thompson     // -- Cleanup
100*75f0d5a4SJeremy L Thompson     CeedVectorDestroy(&q_data);
101*75f0d5a4SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restr_u_f);
102*75f0d5a4SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restr_x);
103*75f0d5a4SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restr_qd_i);
104*75f0d5a4SJeremy L Thompson     CeedBasisDestroy(&basis_u_f);
105*75f0d5a4SJeremy L Thompson     CeedBasisDestroy(&basis_x);
106*75f0d5a4SJeremy L Thompson     CeedQFunctionDestroy(&qf_setup);
107*75f0d5a4SJeremy L Thompson     CeedQFunctionDestroy(&qf_mass);
108*75f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_setup);
109*75f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_mass_f);
110*75f0d5a4SJeremy L Thompson   }
111*75f0d5a4SJeremy L Thompson 
112*75f0d5a4SJeremy L Thompson   // Scale for suboperator multiplicity
113*75f0d5a4SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_f, &p_mult_f);
114*75f0d5a4SJeremy L Thompson   CeedCompositeOperatorGetMultiplicity(op_mass_f, 0, NULL, p_mult_f);
115*75f0d5a4SJeremy L Thompson 
116*75f0d5a4SJeremy L Thompson   // Setup coarse and prolong/restriction suboperators
117*75f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_sub_ops; i++) {
118*75f0d5a4SJeremy L Thompson     CeedElemRestriction elem_restr_u_c;
119*75f0d5a4SJeremy L Thompson     CeedBasis           basis_u_c;
120*75f0d5a4SJeremy L Thompson     CeedOperator       *sub_ops_mass_f, sub_op_mass_c, sub_op_prolong, sub_op_restrict;
121*75f0d5a4SJeremy L Thompson 
122*75f0d5a4SJeremy L Thompson     // -- Fine grid operator
123*75f0d5a4SJeremy L Thompson     CeedOperatorGetSubList(op_mass_f, &sub_ops_mass_f);
124*75f0d5a4SJeremy L Thompson 
125*75f0d5a4SJeremy L Thompson     // -- Restrictions
126*75f0d5a4SJeremy L Thompson     CeedInt offset = num_elem_sub * i * (P_c - 1);
127*75f0d5a4SJeremy L Thompson     for (CeedInt j = 0; j < num_elem_sub; j++) {
128*75f0d5a4SJeremy L Thompson       for (CeedInt k = 0; k < P_c; k++) {
129*75f0d5a4SJeremy L Thompson         ind_u_c[P_c * j + k] = offset + j * (P_c - 1) + k;
130*75f0d5a4SJeremy L Thompson       }
131*75f0d5a4SJeremy L Thompson     }
132*75f0d5a4SJeremy L Thompson     CeedElemRestrictionCreate(ceed, num_elem_sub, P_c, num_comp, num_dofs_u_c, num_comp * num_dofs_u_c, CEED_MEM_HOST, CEED_COPY_VALUES, ind_u_c,
133*75f0d5a4SJeremy L Thompson                               &elem_restr_u_c);
134*75f0d5a4SJeremy L Thompson 
135*75f0d5a4SJeremy L Thompson     // -- Bases
136*75f0d5a4SJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, 1, num_comp, P_c, Q, CEED_GAUSS, &basis_u_c);
137*75f0d5a4SJeremy L Thompson 
138*75f0d5a4SJeremy L Thompson     // -- Create multigrid level
139*75f0d5a4SJeremy L Thompson     CeedOperatorMultigridLevelCreate(sub_ops_mass_f[i], p_mult_f, elem_restr_u_c, basis_u_c, &sub_op_mass_c, &sub_op_prolong, &sub_op_restrict);
140*75f0d5a4SJeremy L Thompson 
141*75f0d5a4SJeremy L Thompson     // -- Composite operators
142*75f0d5a4SJeremy L Thompson     CeedCompositeOperatorAddSub(op_mass_c, sub_op_mass_c);
143*75f0d5a4SJeremy L Thompson     CeedCompositeOperatorAddSub(op_prolong, sub_op_prolong);
144*75f0d5a4SJeremy L Thompson     CeedCompositeOperatorAddSub(op_restrict, sub_op_restrict);
145*75f0d5a4SJeremy L Thompson 
146*75f0d5a4SJeremy L Thompson     // -- Cleanup
147*75f0d5a4SJeremy L Thompson     CeedElemRestrictionDestroy(&elem_restr_u_c);
148*75f0d5a4SJeremy L Thompson     CeedBasisDestroy(&basis_u_c);
149*75f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_mass_c);
150*75f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_prolong);
151*75f0d5a4SJeremy L Thompson     CeedOperatorDestroy(&sub_op_restrict);
152*75f0d5a4SJeremy L Thompson   }
153*75f0d5a4SJeremy L Thompson 
154*75f0d5a4SJeremy L Thompson   // Coarse problem
155*75f0d5a4SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_c, &U_c);
156*75f0d5a4SJeremy L Thompson   CeedVectorSetValue(U_c, 1.0);
157*75f0d5a4SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_c, &V_c);
158*75f0d5a4SJeremy L Thompson   CeedOperatorApply(op_mass_c, U_c, V_c, CEED_REQUEST_IMMEDIATE);
159*75f0d5a4SJeremy L Thompson 
160*75f0d5a4SJeremy L Thompson   // Check output
161*75f0d5a4SJeremy L Thompson   CeedVectorGetArrayRead(V_c, CEED_MEM_HOST, &hv);
162*75f0d5a4SJeremy L Thompson   sum = 0.;
163*75f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_comp * num_dofs_u_c; i++) {
164*75f0d5a4SJeremy L Thompson     sum += hv[i];
165*75f0d5a4SJeremy L Thompson   }
166*75f0d5a4SJeremy L Thompson   if (fabs(sum - 2.) > 1000. * CEED_EPSILON) printf("Computed Area Coarse Grid: %f != True Area: 2.0\n", sum);
167*75f0d5a4SJeremy L Thompson   CeedVectorRestoreArrayRead(V_c, &hv);
168*75f0d5a4SJeremy L Thompson 
169*75f0d5a4SJeremy L Thompson   // Prolong coarse u
170*75f0d5a4SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_f, &U_f);
171*75f0d5a4SJeremy L Thompson   CeedOperatorApply(op_prolong, U_c, U_f, CEED_REQUEST_IMMEDIATE);
172*75f0d5a4SJeremy L Thompson 
173*75f0d5a4SJeremy L Thompson   // Fine problem
174*75f0d5a4SJeremy L Thompson   CeedVectorCreate(ceed, num_comp * num_dofs_u_f, &V_f);
175*75f0d5a4SJeremy L Thompson   CeedOperatorApply(op_mass_f, U_f, V_f, CEED_REQUEST_IMMEDIATE);
176*75f0d5a4SJeremy L Thompson 
177*75f0d5a4SJeremy L Thompson   // Check output
178*75f0d5a4SJeremy L Thompson   CeedVectorGetArrayRead(V_f, CEED_MEM_HOST, &hv);
179*75f0d5a4SJeremy L Thompson   sum = 0.;
180*75f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_comp * num_dofs_u_f; i++) {
181*75f0d5a4SJeremy L Thompson     sum += hv[i];
182*75f0d5a4SJeremy L Thompson   }
183*75f0d5a4SJeremy L Thompson   if (fabs(sum - 2.) > 1000. * CEED_EPSILON) printf("Computed Area Fine Grid: %f != True Area: 2.0\n", sum);
184*75f0d5a4SJeremy L Thompson   CeedVectorRestoreArrayRead(V_f, &hv);
185*75f0d5a4SJeremy L Thompson 
186*75f0d5a4SJeremy L Thompson   // Restrict state to coarse grid
187*75f0d5a4SJeremy L Thompson   CeedOperatorApply(op_restrict, V_f, V_c, CEED_REQUEST_IMMEDIATE);
188*75f0d5a4SJeremy L Thompson 
189*75f0d5a4SJeremy L Thompson   // Check output
190*75f0d5a4SJeremy L Thompson   CeedVectorGetArrayRead(V_c, CEED_MEM_HOST, &hv);
191*75f0d5a4SJeremy L Thompson   sum = 0.;
192*75f0d5a4SJeremy L Thompson   for (CeedInt i = 0; i < num_comp * num_dofs_u_c; i++) {
193*75f0d5a4SJeremy L Thompson     sum += hv[i];
194*75f0d5a4SJeremy L Thompson   }
195*75f0d5a4SJeremy L Thompson   if (fabs(sum - 2.) > 1000. * CEED_EPSILON) printf("Computed Area Coarse Grid: %f != True Area: 2.0\n", sum);
196*75f0d5a4SJeremy L Thompson   CeedVectorRestoreArrayRead(V_c, &hv);
197*75f0d5a4SJeremy L Thompson 
198*75f0d5a4SJeremy L Thompson   // Cleanup
199*75f0d5a4SJeremy L Thompson   CeedVectorDestroy(&X);
200*75f0d5a4SJeremy L Thompson   CeedVectorDestroy(&U_c);
201*75f0d5a4SJeremy L Thompson   CeedVectorDestroy(&U_f);
202*75f0d5a4SJeremy L Thompson   CeedVectorDestroy(&V_c);
203*75f0d5a4SJeremy L Thompson   CeedVectorDestroy(&V_f);
204*75f0d5a4SJeremy L Thompson   CeedVectorDestroy(&p_mult_f);
205*75f0d5a4SJeremy L Thompson   CeedOperatorDestroy(&op_mass_c);
206*75f0d5a4SJeremy L Thompson   CeedOperatorDestroy(&op_mass_f);
207*75f0d5a4SJeremy L Thompson   CeedOperatorDestroy(&op_prolong);
208*75f0d5a4SJeremy L Thompson   CeedOperatorDestroy(&op_restrict);
209*75f0d5a4SJeremy L Thompson   CeedDestroy(&ceed);
210*75f0d5a4SJeremy L Thompson   return 0;
211*75f0d5a4SJeremy L Thompson }
212