xref: /libCEED/tests/t561-operator.c (revision e2f04181a00c6a5b9d49ef9d074211a68e322886)
1*e2f04181SAndrew T. Barker /// @file
2*e2f04181SAndrew T. Barker /// Test full assembly of Poisson operator
3*e2f04181SAndrew T. Barker /// \test Test full assembly of 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 "t534-operator.h"
8*e2f04181SAndrew T. Barker 
9*e2f04181SAndrew T. Barker int main(int argc, char **argv) {
10*e2f04181SAndrew T. Barker   Ceed ceed;
11*e2f04181SAndrew T. Barker   CeedElemRestriction Erestrictx, Erestrictu,
12*e2f04181SAndrew T. Barker                       Erestrictui, Erestrictqi;
13*e2f04181SAndrew T. Barker   CeedBasis bx, bu;
14*e2f04181SAndrew T. Barker   CeedQFunction qf_setup, qf_diff;
15*e2f04181SAndrew T. Barker   CeedOperator op_setup, op_diff;
16*e2f04181SAndrew T. Barker   CeedVector qdata, X, U, V;
17*e2f04181SAndrew T. Barker   CeedInt P = 3, Q = 4, dim = 2;
18*e2f04181SAndrew T. Barker   CeedInt nx = 3, ny = 2;
19*e2f04181SAndrew T. Barker   CeedInt nelem = nx * ny;
20*e2f04181SAndrew T. Barker   CeedInt ndofs = (nx*2+1)*(ny*2+1), nqpts = nelem*Q*Q;
21*e2f04181SAndrew T. Barker   CeedInt indx[nelem*P*P];
22*e2f04181SAndrew T. Barker   CeedScalar assembled[ndofs*ndofs];
23*e2f04181SAndrew T. Barker   CeedScalar x[dim*ndofs], assembledTrue[ndofs*ndofs];
24*e2f04181SAndrew T. Barker   CeedScalar *u;
25*e2f04181SAndrew T. Barker   const CeedScalar *v;
26*e2f04181SAndrew T. Barker 
27*e2f04181SAndrew T. Barker   CeedInit(argv[1], &ceed);
28*e2f04181SAndrew T. Barker 
29*e2f04181SAndrew T. Barker   // DoF Coordinates
30*e2f04181SAndrew T. Barker   for (CeedInt i=0; i<nx*2+1; i++)
31*e2f04181SAndrew T. Barker     for (CeedInt j=0; j<ny*2+1; j++) {
32*e2f04181SAndrew T. Barker       x[i+j*(nx*2+1)+0*ndofs] = (CeedScalar) i / (2*nx);
33*e2f04181SAndrew T. Barker       x[i+j*(nx*2+1)+1*ndofs] = (CeedScalar) j / (2*ny);
34*e2f04181SAndrew T. Barker     }
35*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, dim*ndofs, &X);
36*e2f04181SAndrew T. Barker   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
37*e2f04181SAndrew T. Barker 
38*e2f04181SAndrew T. Barker   // Qdata Vector
39*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, nqpts*dim*(dim+1)/2, &qdata);
40*e2f04181SAndrew T. Barker 
41*e2f04181SAndrew T. Barker   // Element Setup
42*e2f04181SAndrew T. Barker   for (CeedInt i=0; i<nelem; i++) {
43*e2f04181SAndrew T. Barker     CeedInt col, row, offset;
44*e2f04181SAndrew T. Barker     col = i % nx;
45*e2f04181SAndrew T. Barker     row = i / nx;
46*e2f04181SAndrew T. Barker     offset = col*(P-1) + row*(nx*2+1)*(P-1);
47*e2f04181SAndrew T. Barker     for (CeedInt j=0; j<P; j++)
48*e2f04181SAndrew T. Barker       for (CeedInt k=0; k<P; k++)
49*e2f04181SAndrew T. Barker         indx[P*(P*i+k)+j] = offset + k*(nx*2+1) + j;
50*e2f04181SAndrew T. Barker   }
51*e2f04181SAndrew T. Barker 
52*e2f04181SAndrew T. Barker   // Restrictions
53*e2f04181SAndrew T. Barker   CeedElemRestrictionCreate(ceed, nelem, P*P, dim, ndofs, dim*ndofs,
54*e2f04181SAndrew T. Barker                             CEED_MEM_HOST, CEED_USE_POINTER, indx, &Erestrictx);
55*e2f04181SAndrew T. Barker 
56*e2f04181SAndrew T. Barker   CeedElemRestrictionCreate(ceed, nelem, P*P, 1, 1, ndofs, CEED_MEM_HOST,
57*e2f04181SAndrew T. Barker                             CEED_USE_POINTER, indx, &Erestrictu);
58*e2f04181SAndrew T. Barker   CeedInt stridesu[3] = {1, Q*Q, Q*Q};
59*e2f04181SAndrew T. Barker   CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, 1, nqpts, stridesu,
60*e2f04181SAndrew T. Barker                                    &Erestrictui);
61*e2f04181SAndrew T. Barker 
62*e2f04181SAndrew T. Barker   CeedInt stridesqd[3] = {1, Q*Q, Q *Q *dim *(dim+1)/2};
63*e2f04181SAndrew T. Barker   CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, dim*(dim+1)/2,
64*e2f04181SAndrew T. Barker                                    dim*(dim+1)/2*nqpts,
65*e2f04181SAndrew T. Barker                                    stridesqd, &Erestrictqi);
66*e2f04181SAndrew T. Barker 
67*e2f04181SAndrew T. Barker   // Bases
68*e2f04181SAndrew T. Barker   CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, P, Q, CEED_GAUSS, &bx);
69*e2f04181SAndrew T. Barker   CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &bu);
70*e2f04181SAndrew T. Barker 
71*e2f04181SAndrew T. Barker   // QFunction - setup
72*e2f04181SAndrew T. Barker   CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup);
73*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_setup, "dx", dim*dim, CEED_EVAL_GRAD);
74*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_setup, "_weight", 1, CEED_EVAL_WEIGHT);
75*e2f04181SAndrew T. Barker   CeedQFunctionAddOutput(qf_setup, "qdata", dim*(dim+1)/2, CEED_EVAL_NONE);
76*e2f04181SAndrew T. Barker 
77*e2f04181SAndrew T. Barker   // Operator - setup
78*e2f04181SAndrew T. Barker   CeedOperatorCreate(ceed, qf_setup, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
79*e2f04181SAndrew T. Barker                      &op_setup);
80*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup, "dx", Erestrictx, bx, CEED_VECTOR_ACTIVE);
81*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup, "_weight", CEED_ELEMRESTRICTION_NONE, bx,
82*e2f04181SAndrew T. Barker                        CEED_VECTOR_NONE);
83*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_setup, "qdata", Erestrictqi, CEED_BASIS_COLLOCATED,
84*e2f04181SAndrew T. Barker                        CEED_VECTOR_ACTIVE);
85*e2f04181SAndrew T. Barker 
86*e2f04181SAndrew T. Barker   // Apply Setup Operator
87*e2f04181SAndrew T. Barker   CeedOperatorApply(op_setup, X, qdata, CEED_REQUEST_IMMEDIATE);
88*e2f04181SAndrew T. Barker 
89*e2f04181SAndrew T. Barker   // QFunction - apply
90*e2f04181SAndrew T. Barker   CeedQFunctionCreateInterior(ceed, 1, diff, diff_loc, &qf_diff);
91*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_diff, "du", dim, CEED_EVAL_GRAD);
92*e2f04181SAndrew T. Barker   CeedQFunctionAddInput(qf_diff, "qdata", dim*(dim+1)/2, CEED_EVAL_NONE);
93*e2f04181SAndrew T. Barker   CeedQFunctionAddOutput(qf_diff, "dv", dim, CEED_EVAL_GRAD);
94*e2f04181SAndrew T. Barker 
95*e2f04181SAndrew T. Barker   // Operator - apply
96*e2f04181SAndrew T. Barker   CeedOperatorCreate(ceed, qf_diff, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
97*e2f04181SAndrew T. Barker                      &op_diff);
98*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_diff, "du", Erestrictu, bu, CEED_VECTOR_ACTIVE);
99*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_diff, "qdata", Erestrictqi, CEED_BASIS_COLLOCATED,
100*e2f04181SAndrew T. Barker                        qdata);
101*e2f04181SAndrew T. Barker   CeedOperatorSetField(op_diff, "dv", Erestrictu, bu, CEED_VECTOR_ACTIVE);
102*e2f04181SAndrew T. Barker 
103*e2f04181SAndrew T. Barker   // Fully assemble operator
104*e2f04181SAndrew T. Barker   for (int k=0; k<ndofs*ndofs; ++k) {
105*e2f04181SAndrew T. Barker     assembled[k] = 0.0;
106*e2f04181SAndrew T. Barker     assembledTrue[k] = 0.0;
107*e2f04181SAndrew T. Barker   }
108*e2f04181SAndrew T. Barker   CeedInt nentries;
109*e2f04181SAndrew T. Barker   CeedInt *rows;
110*e2f04181SAndrew T. Barker   CeedInt *cols;
111*e2f04181SAndrew T. Barker   CeedVector values;
112*e2f04181SAndrew T. Barker   CeedOperatorLinearAssembleSymbolic(op_diff, &nentries, &rows, &cols);
113*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, nentries, &values);
114*e2f04181SAndrew T. Barker   CeedOperatorLinearAssemble(op_diff, values);
115*e2f04181SAndrew T. Barker   const CeedScalar *vals;
116*e2f04181SAndrew T. Barker   CeedVectorGetArrayRead(values, CEED_MEM_HOST, &vals);
117*e2f04181SAndrew T. Barker   for (int k=0; k<nentries; ++k) {
118*e2f04181SAndrew T. Barker     assembled[rows[k]*ndofs + cols[k]] += vals[k];
119*e2f04181SAndrew T. Barker   }
120*e2f04181SAndrew T. Barker   CeedVectorRestoreArrayRead(values, &vals);
121*e2f04181SAndrew T. Barker 
122*e2f04181SAndrew T. Barker   // Manually assemble operator
123*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, ndofs, &U);
124*e2f04181SAndrew T. Barker   CeedVectorSetValue(U, 0.0);
125*e2f04181SAndrew T. Barker   CeedVectorCreate(ceed, ndofs, &V);
126*e2f04181SAndrew T. Barker   for (int i=0; i<ndofs; i++) {
127*e2f04181SAndrew T. Barker     // Set input
128*e2f04181SAndrew T. Barker     CeedVectorGetArray(U, CEED_MEM_HOST, &u);
129*e2f04181SAndrew T. Barker     u[i] = 1.0;
130*e2f04181SAndrew T. Barker     if (i)
131*e2f04181SAndrew T. Barker       u[i-1] = 0.0;
132*e2f04181SAndrew T. Barker     CeedVectorRestoreArray(U, &u);
133*e2f04181SAndrew T. Barker 
134*e2f04181SAndrew T. Barker     // Compute entries for column i
135*e2f04181SAndrew T. Barker     CeedOperatorApply(op_diff, U, V, CEED_REQUEST_IMMEDIATE);
136*e2f04181SAndrew T. Barker 
137*e2f04181SAndrew T. Barker     CeedVectorGetArrayRead(V, CEED_MEM_HOST, &v);
138*e2f04181SAndrew T. Barker     for (int k=0; k<ndofs; k++) {
139*e2f04181SAndrew T. Barker       assembledTrue[i*ndofs + k] = v[k];
140*e2f04181SAndrew T. Barker     }
141*e2f04181SAndrew T. Barker     CeedVectorRestoreArrayRead(V, &v);
142*e2f04181SAndrew T. Barker   }
143*e2f04181SAndrew T. Barker 
144*e2f04181SAndrew T. Barker   // Check output
145*e2f04181SAndrew T. Barker   for (int i=0; i<ndofs; i++)
146*e2f04181SAndrew T. Barker     for (int j=0; j<ndofs; j++)
147*e2f04181SAndrew T. Barker       if (fabs(assembled[j*ndofs+i] - assembledTrue[j*ndofs+i]) > 1e-14)
148*e2f04181SAndrew T. Barker         // LCOV_EXCL_START
149*e2f04181SAndrew T. Barker         printf("[%d,%d] Error in assembly: %f != %f\n", i, j,
150*e2f04181SAndrew T. Barker                assembled[j*ndofs+i], assembledTrue[j*ndofs+i]);
151*e2f04181SAndrew T. Barker   // LCOV_EXCL_STOP
152*e2f04181SAndrew T. Barker 
153*e2f04181SAndrew T. Barker   // Cleanup
154*e2f04181SAndrew T. Barker   free(rows);
155*e2f04181SAndrew T. Barker   free(cols);
156*e2f04181SAndrew T. Barker   CeedVectorDestroy(&values);
157*e2f04181SAndrew T. Barker   CeedQFunctionDestroy(&qf_setup);
158*e2f04181SAndrew T. Barker   CeedQFunctionDestroy(&qf_diff);
159*e2f04181SAndrew T. Barker   CeedOperatorDestroy(&op_setup);
160*e2f04181SAndrew T. Barker   CeedOperatorDestroy(&op_diff);
161*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictu);
162*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictx);
163*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictui);
164*e2f04181SAndrew T. Barker   CeedElemRestrictionDestroy(&Erestrictqi);
165*e2f04181SAndrew T. Barker   CeedBasisDestroy(&bu);
166*e2f04181SAndrew T. Barker   CeedBasisDestroy(&bx);
167*e2f04181SAndrew T. Barker   CeedVectorDestroy(&X);
168*e2f04181SAndrew T. Barker   CeedVectorDestroy(&qdata);
169*e2f04181SAndrew T. Barker   CeedVectorDestroy(&U);
170*e2f04181SAndrew T. Barker   CeedVectorDestroy(&V);
171*e2f04181SAndrew T. Barker   CeedDestroy(&ceed);
172*e2f04181SAndrew T. Barker   return 0;
173*e2f04181SAndrew T. Barker }
174