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