xref: /libCEED/tests/t538-operator.c (revision c04a41a732cea3148b46ee2e65fa9c6567e2e3ca)
1*c04a41a7SJeremy L Thompson /// @file
2*c04a41a7SJeremy L Thompson /// Test assembly of composite operator diagonal
3*c04a41a7SJeremy L Thompson /// \test Test assembly of composite operator diagonal
4*c04a41a7SJeremy L Thompson #include <ceed.h>
5*c04a41a7SJeremy L Thompson #include <stdlib.h>
6*c04a41a7SJeremy L Thompson #include <math.h>
7*c04a41a7SJeremy L Thompson 
8*c04a41a7SJeremy L Thompson int main(int argc, char **argv) {
9*c04a41a7SJeremy L Thompson   Ceed ceed;
10*c04a41a7SJeremy L Thompson   CeedElemRestriction Erestrictx, Erestrictu,
11*c04a41a7SJeremy L Thompson                       Erestrictui, ErestrictqiMass, ErestrictqiDiff;
12*c04a41a7SJeremy L Thompson   CeedBasis bx, bu;
13*c04a41a7SJeremy L Thompson   CeedQFunction qf_setupMass, qf_mass, qf_setupDiff, qf_diff;
14*c04a41a7SJeremy L Thompson   CeedOperator op_setupMass, op_mass, op_setupDiff, op_diff, op_apply;
15*c04a41a7SJeremy L Thompson   CeedVector qdataMass, qdataDiff, X, A, U, V;
16*c04a41a7SJeremy L Thompson   CeedInt nelem = 6, P = 3, Q = 4, dim = 2;
17*c04a41a7SJeremy L Thompson   CeedInt nx = 3, ny = 2;
18*c04a41a7SJeremy L Thompson   CeedInt ndofs = (nx*2+1)*(ny*2+1), nqpts = nelem*Q*Q;
19*c04a41a7SJeremy L Thompson   CeedInt indx[nelem*P*P];
20*c04a41a7SJeremy L Thompson   CeedScalar x[dim*ndofs], assembledTrue[ndofs];
21*c04a41a7SJeremy L Thompson   CeedScalar *u;
22*c04a41a7SJeremy L Thompson   const CeedScalar *a, *v;
23*c04a41a7SJeremy L Thompson 
24*c04a41a7SJeremy L Thompson   CeedInit(argv[1], &ceed);
25*c04a41a7SJeremy L Thompson 
26*c04a41a7SJeremy L Thompson   // DoF Coordinates
27*c04a41a7SJeremy L Thompson   for (CeedInt i=0; i<nx*2+1; i++)
28*c04a41a7SJeremy L Thompson     for (CeedInt j=0; j<ny*2+1; j++) {
29*c04a41a7SJeremy L Thompson       x[i+j*(nx*2+1)+0*ndofs] = (CeedScalar) i / (2*nx);
30*c04a41a7SJeremy L Thompson       x[i+j*(nx*2+1)+1*ndofs] = (CeedScalar) j / (2*ny);
31*c04a41a7SJeremy L Thompson     }
32*c04a41a7SJeremy L Thompson   CeedVectorCreate(ceed, dim*ndofs, &X);
33*c04a41a7SJeremy L Thompson   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
34*c04a41a7SJeremy L Thompson 
35*c04a41a7SJeremy L Thompson   // Qdata Vectors
36*c04a41a7SJeremy L Thompson   CeedVectorCreate(ceed, nqpts, &qdataMass);
37*c04a41a7SJeremy L Thompson   CeedVectorCreate(ceed, nqpts*dim*(dim+1)/2, &qdataDiff);
38*c04a41a7SJeremy L Thompson 
39*c04a41a7SJeremy L Thompson   // Element Setup
40*c04a41a7SJeremy L Thompson   for (CeedInt i=0; i<nelem; i++) {
41*c04a41a7SJeremy L Thompson     CeedInt col, row, offset;
42*c04a41a7SJeremy L Thompson     col = i % nx;
43*c04a41a7SJeremy L Thompson     row = i / nx;
44*c04a41a7SJeremy L Thompson     offset = col*(P-1) + row*(nx*2+1)*(P-1);
45*c04a41a7SJeremy L Thompson     for (CeedInt j=0; j<P; j++)
46*c04a41a7SJeremy L Thompson       for (CeedInt k=0; k<P; k++)
47*c04a41a7SJeremy L Thompson         indx[P*(P*i+k)+j] = offset + k*(nx*2+1) + j;
48*c04a41a7SJeremy L Thompson   }
49*c04a41a7SJeremy L Thompson 
50*c04a41a7SJeremy L Thompson   // Restrictions
51*c04a41a7SJeremy L Thompson   CeedElemRestrictionCreate(ceed, nelem, P*P, dim, ndofs, dim*ndofs,
52*c04a41a7SJeremy L Thompson                             CEED_MEM_HOST, CEED_USE_POINTER, indx, &Erestrictx);
53*c04a41a7SJeremy L Thompson 
54*c04a41a7SJeremy L Thompson   CeedElemRestrictionCreate(ceed, nelem, P*P, 1, 1, ndofs, CEED_MEM_HOST,
55*c04a41a7SJeremy L Thompson                             CEED_USE_POINTER, indx, &Erestrictu);
56*c04a41a7SJeremy L Thompson   CeedInt stridesu[3] = {1, Q*Q, Q*Q};
57*c04a41a7SJeremy L Thompson   CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, 1, nqpts, stridesu,
58*c04a41a7SJeremy L Thompson                                    &Erestrictui);
59*c04a41a7SJeremy L Thompson 
60*c04a41a7SJeremy L Thompson   CeedInt stridesqdMass[3] = {1, Q*Q, Q*Q};
61*c04a41a7SJeremy L Thompson   CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, 1, nqpts,
62*c04a41a7SJeremy L Thompson                                    stridesqdMass, &ErestrictqiMass);
63*c04a41a7SJeremy L Thompson   CeedInt stridesqdDiff[3] = {1, Q*Q, Q*Q*dim*(dim+1)/2}; /* *NOPAD* */
64*c04a41a7SJeremy L Thompson   CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, dim*(dim+1)/2,
65*c04a41a7SJeremy L Thompson                                    dim*(dim+1)/2*nqpts,
66*c04a41a7SJeremy L Thompson                                    stridesqdDiff, &ErestrictqiDiff);
67*c04a41a7SJeremy L Thompson 
68*c04a41a7SJeremy L Thompson   // Bases
69*c04a41a7SJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, P, Q, CEED_GAUSS, &bx);
70*c04a41a7SJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &bu);
71*c04a41a7SJeremy L Thompson 
72*c04a41a7SJeremy L Thompson   // QFunction - setup mass
73*c04a41a7SJeremy L Thompson   CeedQFunctionCreateInteriorByName(ceed, "Mass2DBuild", &qf_setupMass);
74*c04a41a7SJeremy L Thompson 
75*c04a41a7SJeremy L Thompson   // Operator - setup mass
76*c04a41a7SJeremy L Thompson   CeedOperatorCreate(ceed, qf_setupMass, CEED_QFUNCTION_NONE,
77*c04a41a7SJeremy L Thompson                      CEED_QFUNCTION_NONE, &op_setupMass);
78*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_setupMass, "dx", Erestrictx, bx, CEED_VECTOR_ACTIVE);
79*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_setupMass, "weights", CEED_ELEMRESTRICTION_NONE, bx,
80*c04a41a7SJeremy L Thompson                        CEED_VECTOR_NONE);
81*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_setupMass, "qdata", ErestrictqiMass,
82*c04a41a7SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
83*c04a41a7SJeremy L Thompson 
84*c04a41a7SJeremy L Thompson   // QFunction - setup diffusion
85*c04a41a7SJeremy L Thompson   CeedQFunctionCreateInteriorByName(ceed, "Poisson2DBuild", &qf_setupDiff);
86*c04a41a7SJeremy L Thompson 
87*c04a41a7SJeremy L Thompson   // Operator - setup diffusion
88*c04a41a7SJeremy L Thompson   CeedOperatorCreate(ceed, qf_setupDiff, CEED_QFUNCTION_NONE,
89*c04a41a7SJeremy L Thompson                      CEED_QFUNCTION_NONE, &op_setupDiff);
90*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_setupDiff, "dx", Erestrictx, bx, CEED_VECTOR_ACTIVE);
91*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_setupDiff, "weights", CEED_ELEMRESTRICTION_NONE, bx,
92*c04a41a7SJeremy L Thompson                        CEED_VECTOR_NONE);
93*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_setupDiff, "qdata", ErestrictqiDiff,
94*c04a41a7SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
95*c04a41a7SJeremy L Thompson 
96*c04a41a7SJeremy L Thompson   // Apply Setup Operators
97*c04a41a7SJeremy L Thompson   CeedOperatorApply(op_setupMass, X, qdataMass, CEED_REQUEST_IMMEDIATE);
98*c04a41a7SJeremy L Thompson   CeedOperatorApply(op_setupDiff, X, qdataDiff, CEED_REQUEST_IMMEDIATE);
99*c04a41a7SJeremy L Thompson 
100*c04a41a7SJeremy L Thompson   // QFunction - apply mass
101*c04a41a7SJeremy L Thompson   CeedQFunctionCreateInteriorByName(ceed, "MassApply", &qf_mass);
102*c04a41a7SJeremy L Thompson 
103*c04a41a7SJeremy L Thompson   // Operator - apply mass
104*c04a41a7SJeremy L Thompson   CeedOperatorCreate(ceed, qf_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
105*c04a41a7SJeremy L Thompson                      &op_mass);
106*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_mass, "u", Erestrictu, bu, CEED_VECTOR_ACTIVE);
107*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_mass, "qdata", ErestrictqiMass, CEED_BASIS_COLLOCATED,
108*c04a41a7SJeremy L Thompson                        qdataMass);
109*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_mass, "v", Erestrictu, bu, CEED_VECTOR_ACTIVE);
110*c04a41a7SJeremy L Thompson 
111*c04a41a7SJeremy L Thompson   // QFunction - apply diff
112*c04a41a7SJeremy L Thompson   CeedQFunctionCreateInteriorByName(ceed, "Poisson2DApply", &qf_diff);
113*c04a41a7SJeremy L Thompson 
114*c04a41a7SJeremy L Thompson   // Operator - apply
115*c04a41a7SJeremy L Thompson   CeedOperatorCreate(ceed, qf_diff, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
116*c04a41a7SJeremy L Thompson                      &op_diff);
117*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_diff, "du", Erestrictu, bu, CEED_VECTOR_ACTIVE);
118*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_diff, "qdata", ErestrictqiDiff, CEED_BASIS_COLLOCATED,
119*c04a41a7SJeremy L Thompson                        qdataDiff);
120*c04a41a7SJeremy L Thompson   CeedOperatorSetField(op_diff, "dv", Erestrictu, bu, CEED_VECTOR_ACTIVE);
121*c04a41a7SJeremy L Thompson 
122*c04a41a7SJeremy L Thompson   // Composite operator
123*c04a41a7SJeremy L Thompson   CeedCompositeOperatorCreate(ceed, &op_apply);
124*c04a41a7SJeremy L Thompson   CeedCompositeOperatorAddSub(op_apply, op_mass);
125*c04a41a7SJeremy L Thompson   CeedCompositeOperatorAddSub(op_apply, op_diff);
126*c04a41a7SJeremy L Thompson 
127*c04a41a7SJeremy L Thompson   // Assemble diagonal
128*c04a41a7SJeremy L Thompson   CeedOperatorAssembleLinearDiagonal(op_apply, &A, CEED_REQUEST_IMMEDIATE);
129*c04a41a7SJeremy L Thompson 
130*c04a41a7SJeremy L Thompson   // Manually assemble diagonal
131*c04a41a7SJeremy L Thompson   CeedVectorCreate(ceed, ndofs, &U);
132*c04a41a7SJeremy L Thompson   CeedVectorSetValue(U, 0.0);
133*c04a41a7SJeremy L Thompson   CeedVectorCreate(ceed, ndofs, &V);
134*c04a41a7SJeremy L Thompson   for (int i=0; i<ndofs; i++) {
135*c04a41a7SJeremy L Thompson     // Set input
136*c04a41a7SJeremy L Thompson     CeedVectorGetArray(U, CEED_MEM_HOST, &u);
137*c04a41a7SJeremy L Thompson     u[i] = 1.0;
138*c04a41a7SJeremy L Thompson     if (i)
139*c04a41a7SJeremy L Thompson       u[i-1] = 0.0;
140*c04a41a7SJeremy L Thompson     CeedVectorRestoreArray(U, &u);
141*c04a41a7SJeremy L Thompson 
142*c04a41a7SJeremy L Thompson     // Compute diag entry for DoF i
143*c04a41a7SJeremy L Thompson     CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE);
144*c04a41a7SJeremy L Thompson 
145*c04a41a7SJeremy L Thompson     // Retrieve entry
146*c04a41a7SJeremy L Thompson     CeedVectorGetArrayRead(V, CEED_MEM_HOST, &v);
147*c04a41a7SJeremy L Thompson     assembledTrue[i] = v[i];
148*c04a41a7SJeremy L Thompson     CeedVectorRestoreArrayRead(V, &v);
149*c04a41a7SJeremy L Thompson   }
150*c04a41a7SJeremy L Thompson 
151*c04a41a7SJeremy L Thompson   // Check output
152*c04a41a7SJeremy L Thompson   CeedVectorGetArrayRead(A, CEED_MEM_HOST, &a);
153*c04a41a7SJeremy L Thompson   for (int i=0; i<ndofs; i++)
154*c04a41a7SJeremy L Thompson     if (fabs(a[i] - assembledTrue[i]) > 1e-13)
155*c04a41a7SJeremy L Thompson       // LCOV_EXCL_START
156*c04a41a7SJeremy L Thompson       printf("[%d] Error in assembly: %f != %f\n", i, a[i], assembledTrue[i]);
157*c04a41a7SJeremy L Thompson   // LCOV_EXCL_STOP
158*c04a41a7SJeremy L Thompson   CeedVectorRestoreArrayRead(A, &a);
159*c04a41a7SJeremy L Thompson 
160*c04a41a7SJeremy L Thompson   // Cleanup
161*c04a41a7SJeremy L Thompson   CeedQFunctionDestroy(&qf_setupMass);
162*c04a41a7SJeremy L Thompson   CeedQFunctionDestroy(&qf_setupDiff);
163*c04a41a7SJeremy L Thompson   CeedQFunctionDestroy(&qf_diff);
164*c04a41a7SJeremy L Thompson   CeedQFunctionDestroy(&qf_mass);
165*c04a41a7SJeremy L Thompson   CeedOperatorDestroy(&op_setupMass);
166*c04a41a7SJeremy L Thompson   CeedOperatorDestroy(&op_setupDiff);
167*c04a41a7SJeremy L Thompson   CeedOperatorDestroy(&op_mass);
168*c04a41a7SJeremy L Thompson   CeedOperatorDestroy(&op_diff);
169*c04a41a7SJeremy L Thompson   CeedOperatorDestroy(&op_apply);
170*c04a41a7SJeremy L Thompson   CeedElemRestrictionDestroy(&Erestrictu);
171*c04a41a7SJeremy L Thompson   CeedElemRestrictionDestroy(&Erestrictx);
172*c04a41a7SJeremy L Thompson   CeedElemRestrictionDestroy(&Erestrictui);
173*c04a41a7SJeremy L Thompson   CeedElemRestrictionDestroy(&ErestrictqiMass);
174*c04a41a7SJeremy L Thompson   CeedElemRestrictionDestroy(&ErestrictqiDiff);
175*c04a41a7SJeremy L Thompson   CeedBasisDestroy(&bu);
176*c04a41a7SJeremy L Thompson   CeedBasisDestroy(&bx);
177*c04a41a7SJeremy L Thompson   CeedVectorDestroy(&X);
178*c04a41a7SJeremy L Thompson   CeedVectorDestroy(&A);
179*c04a41a7SJeremy L Thompson   CeedVectorDestroy(&qdataMass);
180*c04a41a7SJeremy L Thompson   CeedVectorDestroy(&qdataDiff);
181*c04a41a7SJeremy L Thompson   CeedVectorDestroy(&U);
182*c04a41a7SJeremy L Thompson   CeedVectorDestroy(&V);
183*c04a41a7SJeremy L Thompson   CeedDestroy(&ceed);
184*c04a41a7SJeremy L Thompson   return 0;
185*c04a41a7SJeremy L Thompson }
186