xref: /libCEED/tests/t563-operator.c (revision e2f04181a00c6a5b9d49ef9d074211a68e322886)
1*e2f04181SAndrew T. Barker /// @file
2*e2f04181SAndrew T. Barker /// Test full assembly of mass and Poisson operator (see t536)
3*e2f04181SAndrew T. Barker /// \test Test full assembly of mass and Poisson operator
4*e2f04181SAndrew T. Barker #include <ceed.h>
5*e2f04181SAndrew T. Barker #include <stdlib.h>
6*e2f04181SAndrew T. Barker #include <math.h>
7*e2f04181SAndrew T. Barker #include "t320-basis.h"
8*e2f04181SAndrew T. Barker #include "t535-operator.h"
9*e2f04181SAndrew T. Barker 
10*e2f04181SAndrew T. Barker int main(int argc, char **argv) {
11*e2f04181SAndrew T. Barker   Ceed ceed;
12*e2f04181SAndrew T. Barker   CeedElemRestriction Erestrictx, Erestrictu,
13*e2f04181SAndrew T. Barker                       Erestrictui, Erestrictqi;
14*e2f04181SAndrew T. Barker   CeedBasis bx, bu;
15*e2f04181SAndrew T. Barker   CeedQFunction qf_setup_mass, qf_setup_diff, qf_apply;
16*e2f04181SAndrew T. Barker   CeedOperator op_setup_mass, op_setup_diff, op_apply;
17*e2f04181SAndrew T. Barker   CeedVector qdata_mass, qdata_diff, X, U, V;
18*e2f04181SAndrew T. Barker   CeedInt nelem = 12, dim = 2, P = 6, Q = 4;
19*e2f04181SAndrew T. Barker   CeedInt nx = 3, ny = 2;
20*e2f04181SAndrew T. Barker   CeedInt row, col, offset;
21*e2f04181SAndrew T. Barker   CeedInt ndofs = (nx*2+1)*(ny*2+1), nqpts = nelem*Q;
22*e2f04181SAndrew T. Barker   CeedInt indx[nelem*P*P];
23*e2f04181SAndrew T. Barker   CeedScalar assembled[ndofs*ndofs];
24*e2f04181SAndrew T. Barker   CeedScalar x[dim*ndofs], assembledTrue[ndofs*ndofs];
25*e2f04181SAndrew T. Barker   CeedScalar qref[dim*Q], qweight[Q];
26*e2f04181SAndrew T. Barker   CeedScalar interp[P*Q], grad[dim*P*Q];
27*e2f04181SAndrew T. Barker   CeedScalar *u;
28*e2f04181SAndrew T. Barker   const CeedScalar *v;
29*e2f04181SAndrew T. Barker 
30*e2f04181SAndrew T. Barker   CeedInit(argv[1], &ceed);
31*e2f04181SAndrew T. Barker 
32*e2f04181SAndrew T. Barker   // DoF Coordinates
33*e2f04181SAndrew T. Barker   for (CeedInt i=0; i<ndofs; i++) {
34*e2f04181SAndrew T. Barker     x[i] = (1. / (nx*2)) * (CeedScalar) (i % (nx*2+1));
35*e2f04181SAndrew T. Barker     x[i+ndofs] = (1. / (ny*2)) * (CeedScalar) (i / (nx*2+1));
36*e2f04181SAndrew T. Barker   }
37*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, dim*ndofs, &X);
38*e2f04181SAndrew T. Barker   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
39*e2f04181SAndrew T. Barker 
40*e2f04181SAndrew T. Barker   // Qdata Vectors
41*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, nqpts, &qdata_mass);
42*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, nqpts*dim*(dim+1)/2, &qdata_diff);
43*e2f04181SAndrew T. Barker 
44*e2f04181SAndrew T. Barker   // Element Setup
45*e2f04181SAndrew T. Barker   for (CeedInt i=0; i<nelem/2; i++) {
46*e2f04181SAndrew T. Barker     col = i % nx;
47*e2f04181SAndrew T. Barker     row = i / nx;
48*e2f04181SAndrew T. Barker     offset = col*2 + row*(nx*2+1)*2;
49*e2f04181SAndrew T. Barker 
50*e2f04181SAndrew T. Barker     indx[i*2*P +  0] =  2 + offset;
51*e2f04181SAndrew T. Barker     indx[i*2*P +  1] =  9 + offset;
52*e2f04181SAndrew T. Barker     indx[i*2*P +  2] = 16 + offset;
53*e2f04181SAndrew T. Barker     indx[i*2*P +  3] =  1 + offset;
54*e2f04181SAndrew T. Barker     indx[i*2*P +  4] =  8 + offset;
55*e2f04181SAndrew T. Barker     indx[i*2*P +  5] =  0 + offset;
56*e2f04181SAndrew T. Barker 
57*e2f04181SAndrew T. Barker     indx[i*2*P +  6] = 14 + offset;
58*e2f04181SAndrew T. Barker     indx[i*2*P +  7] =  7 + offset;
59*e2f04181SAndrew T. Barker     indx[i*2*P +  8] =  0 + offset;
60*e2f04181SAndrew T. Barker     indx[i*2*P +  9] = 15 + offset;
61*e2f04181SAndrew T. Barker     indx[i*2*P + 10] =  8 + offset;
62*e2f04181SAndrew T. Barker     indx[i*2*P + 11] = 16 + offset;
63*e2f04181SAndrew T. Barker   }
64*e2f04181SAndrew T. Barker 
65*e2f04181SAndrew T. Barker   // Restrictions
66*e2f04181SAndrew T. Barker   CeedElemRestrictionCreate(ceed, nelem, P, dim, ndofs, dim*ndofs,
67*e2f04181SAndrew T. Barker                             CEED_MEM_HOST, CEED_USE_POINTER, indx, &Erestrictx);
68*e2f04181SAndrew T. Barker 
69*e2f04181SAndrew T. Barker   CeedElemRestrictionCreate(ceed, nelem, P, 1, 1, ndofs, CEED_MEM_HOST,
70*e2f04181SAndrew T. Barker                             CEED_USE_POINTER, indx, &Erestrictu);
71*e2f04181SAndrew T. Barker   CeedInt stridesu[3] = {1, Q, Q};
72*e2f04181SAndrew T. Barker   CeedElemRestrictionCreateStrided(ceed, nelem, Q, 1, nqpts, stridesu,
73*e2f04181SAndrew T. Barker                                    &Erestrictui);
74*e2f04181SAndrew T. Barker 
75*e2f04181SAndrew T. Barker   CeedInt stridesqd[3] = {1, Q, Q *dim *(dim+1)/2};
76*e2f04181SAndrew T. Barker   CeedElemRestrictionCreateStrided(ceed, nelem, Q, dim*(dim+1)/2,
77*e2f04181SAndrew T. Barker                                    dim*(dim+1)/2*nqpts,
78*e2f04181SAndrew T. Barker                                    stridesqd, &Erestrictqi);
79*e2f04181SAndrew T. Barker 
80*e2f04181SAndrew T. Barker   // Bases
81*e2f04181SAndrew T. Barker   buildmats(qref, qweight, interp, grad);
82*e2f04181SAndrew T. Barker   CeedBasisCreateH1(ceed, CEED_TRIANGLE, dim, P, Q, interp, grad, qref,
83*e2f04181SAndrew T. Barker                     qweight, &bx);
84*e2f04181SAndrew T. Barker 
85*e2f04181SAndrew T. Barker   buildmats(qref, qweight, interp, grad);
86*e2f04181SAndrew T. Barker   CeedBasisCreateH1(ceed, CEED_TRIANGLE, 1, P, Q, interp, grad, qref,
87*e2f04181SAndrew T. Barker                     qweight, &bu);
88*e2f04181SAndrew T. Barker 
89*e2f04181SAndrew T. Barker   // QFunction - setup mass
90*e2f04181SAndrew T. Barker   CeedQFunctionCreateInterior(ceed, 1, setup_mass, setup_mass_loc,
91*e2f04181SAndrew T. Barker                               &qf_setup_mass);
92*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_setup_mass, "dx", dim*dim, CEED_EVAL_GRAD);
93*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_setup_mass, "_weight", 1, CEED_EVAL_WEIGHT);
94*e2f04181SAndrew T. Barker   CeedQFunctionAddOutput(qf_setup_mass, "qdata", 1, CEED_EVAL_NONE);
95*e2f04181SAndrew T. Barker 
96*e2f04181SAndrew T. Barker   // Operator - setup mass
97*e2f04181SAndrew T. Barker   CeedOperatorCreate(ceed, qf_setup_mass, CEED_QFUNCTION_NONE,
98*e2f04181SAndrew T. Barker                      CEED_QFUNCTION_NONE, &op_setup_mass);
99*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup_mass, "dx", Erestrictx, bx, CEED_VECTOR_ACTIVE);
100*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup_mass, "_weight", CEED_ELEMRESTRICTION_NONE, bx,
101*e2f04181SAndrew T. Barker                        CEED_VECTOR_NONE);
102*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup_mass, "qdata", Erestrictui,
103*e2f04181SAndrew T. Barker                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
104*e2f04181SAndrew T. Barker 
105*e2f04181SAndrew T. Barker   // QFunction - setup diff
106*e2f04181SAndrew T. Barker   CeedQFunctionCreateInterior(ceed, 1, setup_diff, setup_diff_loc,
107*e2f04181SAndrew T. Barker                               &qf_setup_diff);
108*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_setup_diff, "dx", dim*dim, CEED_EVAL_GRAD);
109*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_setup_diff, "_weight", 1, CEED_EVAL_WEIGHT);
110*e2f04181SAndrew T. Barker   CeedQFunctionAddOutput(qf_setup_diff, "qdata", dim*(dim+1)/2, CEED_EVAL_NONE);
111*e2f04181SAndrew T. Barker 
112*e2f04181SAndrew T. Barker   // Operator - setup diff
113*e2f04181SAndrew T. Barker   CeedOperatorCreate(ceed, qf_setup_diff, CEED_QFUNCTION_NONE,
114*e2f04181SAndrew T. Barker                      CEED_QFUNCTION_NONE, &op_setup_diff);
115*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup_diff, "dx", Erestrictx, bx, CEED_VECTOR_ACTIVE);
116*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup_diff, "_weight", CEED_ELEMRESTRICTION_NONE, bx,
117*e2f04181SAndrew T. Barker                        CEED_VECTOR_NONE);
118*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup_diff, "qdata", Erestrictqi,
119*e2f04181SAndrew T. Barker                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
120*e2f04181SAndrew T. Barker 
121*e2f04181SAndrew T. Barker   // Apply Setup Operators
122*e2f04181SAndrew T. Barker   CeedOperatorApply(op_setup_mass, X, qdata_mass, CEED_REQUEST_IMMEDIATE);
123*e2f04181SAndrew T. Barker   CeedOperatorApply(op_setup_diff, X, qdata_diff, CEED_REQUEST_IMMEDIATE);
124*e2f04181SAndrew T. Barker 
125*e2f04181SAndrew T. Barker   // QFunction - apply
126*e2f04181SAndrew T. Barker   CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply);
127*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_apply, "du", dim, CEED_EVAL_GRAD);
128*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_apply, "qdata_mass", 1, CEED_EVAL_NONE);
129*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_apply, "qdata_diff", dim*(dim+1)/2, CEED_EVAL_NONE);
130*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP);
131*e2f04181SAndrew T. Barker   CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP);
132*e2f04181SAndrew T. Barker   CeedQFunctionAddOutput(qf_apply, "dv", dim, CEED_EVAL_GRAD);
133*e2f04181SAndrew T. Barker 
134*e2f04181SAndrew T. Barker   // Operator - apply
135*e2f04181SAndrew T. Barker   CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
136*e2f04181SAndrew T. Barker                      &op_apply);
137*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_apply, "du", Erestrictu, bu, CEED_VECTOR_ACTIVE);
138*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_apply, "qdata_mass", Erestrictui,
139*e2f04181SAndrew T. Barker                        CEED_BASIS_COLLOCATED, qdata_mass);
140*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_apply, "qdata_diff", Erestrictqi,
141*e2f04181SAndrew T. Barker                        CEED_BASIS_COLLOCATED, qdata_diff);
142*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_apply, "u", Erestrictu, bu, CEED_VECTOR_ACTIVE);
143*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_apply, "v", Erestrictu, bu, CEED_VECTOR_ACTIVE);
144*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_apply, "dv", Erestrictu, bu, CEED_VECTOR_ACTIVE);
145*e2f04181SAndrew T. Barker 
146*e2f04181SAndrew T. Barker   // Fully assemble operator
147*e2f04181SAndrew T. Barker   for (int k=0; k<ndofs*ndofs; ++k) {
148*e2f04181SAndrew T. Barker     assembled[k] = 0.0;
149*e2f04181SAndrew T. Barker     assembledTrue[k] = 0.0;
150*e2f04181SAndrew T. Barker   }
151*e2f04181SAndrew T. Barker   CeedInt nentries;
152*e2f04181SAndrew T. Barker   CeedInt *rows;
153*e2f04181SAndrew T. Barker   CeedInt *cols;
154*e2f04181SAndrew T. Barker   CeedVector values;
155*e2f04181SAndrew T. Barker   CeedOperatorLinearAssembleSymbolic(op_apply, &nentries, &rows, &cols);
156*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, nentries, &values);
157*e2f04181SAndrew T. Barker   CeedOperatorLinearAssemble(op_apply, values);
158*e2f04181SAndrew T. Barker   const CeedScalar *vals;
159*e2f04181SAndrew T. Barker   CeedVectorGetArrayRead(values, CEED_MEM_HOST, &vals);
160*e2f04181SAndrew T. Barker   for (int k=0; k<nentries; ++k) {
161*e2f04181SAndrew T. Barker     assembled[rows[k]*ndofs + cols[k]] += vals[k];
162*e2f04181SAndrew T. Barker   }
163*e2f04181SAndrew T. Barker   CeedVectorRestoreArrayRead(values, &vals);
164*e2f04181SAndrew T. Barker 
165*e2f04181SAndrew T. Barker   // Manually assemble operator
166*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, ndofs, &U);
167*e2f04181SAndrew T. Barker   CeedVectorSetValue(U, 0.0);
168*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, ndofs, &V);
169*e2f04181SAndrew T. Barker   for (int i=0; i<ndofs; i++) {
170*e2f04181SAndrew T. Barker     // Set input
171*e2f04181SAndrew T. Barker     CeedVectorGetArray(U, CEED_MEM_HOST, &u);
172*e2f04181SAndrew T. Barker     u[i] = 1.0;
173*e2f04181SAndrew T. Barker     if (i)
174*e2f04181SAndrew T. Barker       u[i-1] = 0.0;
175*e2f04181SAndrew T. Barker     CeedVectorRestoreArray(U, &u);
176*e2f04181SAndrew T. Barker 
177*e2f04181SAndrew T. Barker     // Compute entries for column i
178*e2f04181SAndrew T. Barker     CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE);
179*e2f04181SAndrew T. Barker 
180*e2f04181SAndrew T. Barker     CeedVectorGetArrayRead(V, CEED_MEM_HOST, &v);
181*e2f04181SAndrew T. Barker     for (int k=0; k<ndofs; k++) {
182*e2f04181SAndrew T. Barker       assembledTrue[i*ndofs + k] = v[k];
183*e2f04181SAndrew T. Barker     }
184*e2f04181SAndrew T. Barker     CeedVectorRestoreArrayRead(V, &v);
185*e2f04181SAndrew T. Barker   }
186*e2f04181SAndrew T. Barker 
187*e2f04181SAndrew T. Barker   // Check output
188*e2f04181SAndrew T. Barker   for (int i=0; i<ndofs; i++)
189*e2f04181SAndrew T. Barker     for (int j=0; j<ndofs; j++)
190*e2f04181SAndrew T. Barker       if (fabs(assembled[j*ndofs+i] - assembledTrue[j*ndofs+i]) > 1e-14)
191*e2f04181SAndrew T. Barker         // LCOV_EXCL_START
192*e2f04181SAndrew T. Barker         printf("[%d,%d] Error in assembly: %f != %f\n", i, j,
193*e2f04181SAndrew T. Barker                assembled[j*ndofs+i], assembledTrue[j*ndofs+i]);
194*e2f04181SAndrew T. Barker   // LCOV_EXCL_STOP
195*e2f04181SAndrew T. Barker 
196*e2f04181SAndrew T. Barker   // Cleanup
197*e2f04181SAndrew T. Barker   free(rows);
198*e2f04181SAndrew T. Barker   free(cols);
199*e2f04181SAndrew T. Barker   CeedVectorDestroy(&values);
200*e2f04181SAndrew T. Barker   CeedQFunctionDestroy(&qf_setup_mass);
201*e2f04181SAndrew T. Barker   CeedQFunctionDestroy(&qf_setup_diff);
202*e2f04181SAndrew T. Barker   CeedQFunctionDestroy(&qf_apply);
203*e2f04181SAndrew T. Barker   CeedOperatorDestroy(&op_setup_mass);
204*e2f04181SAndrew T. Barker   CeedOperatorDestroy(&op_setup_diff);
205*e2f04181SAndrew T. Barker   CeedOperatorDestroy(&op_apply);
206*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictu);
207*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictx);
208*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictui);
209*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictqi);
210*e2f04181SAndrew T. Barker   CeedBasisDestroy(&bu);
211*e2f04181SAndrew T. Barker   CeedBasisDestroy(&bx);
212*e2f04181SAndrew T. Barker   CeedVectorDestroy(&X);
213*e2f04181SAndrew T. Barker   CeedVectorDestroy(&qdata_mass);
214*e2f04181SAndrew T. Barker   CeedVectorDestroy(&qdata_diff);
215*e2f04181SAndrew T. Barker   CeedVectorDestroy(&U);
216*e2f04181SAndrew T. Barker   CeedVectorDestroy(&V);
217*e2f04181SAndrew T. Barker   CeedDestroy(&ceed);
218*e2f04181SAndrew T. Barker   return 0;
219*e2f04181SAndrew T. Barker }
220