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