xref: /libCEED/tests/t537-operator.c (revision d965c7a71afb833cd21b66efc6c6ec81679c68a9)
1*d965c7a7SJeremy L Thompson /// @file
2*d965c7a7SJeremy L Thompson /// Test assembly of mass matrix operator point block diagonal
3*d965c7a7SJeremy L Thompson /// \test Test assembly of mass matrix operator point block diagonal
4*d965c7a7SJeremy L Thompson #include <ceed.h>
5*d965c7a7SJeremy L Thompson #include <stdlib.h>
6*d965c7a7SJeremy L Thompson #include <math.h>
7*d965c7a7SJeremy L Thompson #include "t537-operator.h"
8*d965c7a7SJeremy L Thompson 
9*d965c7a7SJeremy L Thompson int main(int argc, char **argv) {
10*d965c7a7SJeremy L Thompson   Ceed ceed;
11*d965c7a7SJeremy L Thompson   CeedElemRestriction Erestrictx, Erestrictu,
12*d965c7a7SJeremy L Thompson                       Erestrictui;
13*d965c7a7SJeremy L Thompson   CeedBasis bx, bu;
14*d965c7a7SJeremy L Thompson   CeedQFunction qf_setup, qf_mass;
15*d965c7a7SJeremy L Thompson   CeedOperator op_setup, op_mass;
16*d965c7a7SJeremy L Thompson   CeedVector qdata, X, A, U, V;
17*d965c7a7SJeremy L Thompson   CeedInt nelem = 6, P = 3, Q = 4, dim = 2, ncomp = 2;
18*d965c7a7SJeremy L Thompson   CeedInt nx = 3, ny = 2;
19*d965c7a7SJeremy L Thompson   CeedInt ndofs = (nx*2+1)*(ny*2+1), nqpts = nelem*Q*Q;
20*d965c7a7SJeremy L Thompson   CeedInt indx[nelem*P*P];
21*d965c7a7SJeremy L Thompson   CeedScalar x[dim*ndofs], assembledTrue[ncomp*ncomp*ndofs];
22*d965c7a7SJeremy L Thompson   CeedScalar *u;
23*d965c7a7SJeremy L Thompson   const CeedScalar *a, *v;
24*d965c7a7SJeremy L Thompson 
25*d965c7a7SJeremy L Thompson   CeedInit(argv[1], &ceed);
26*d965c7a7SJeremy L Thompson 
27*d965c7a7SJeremy L Thompson   // DoF Coordinates
28*d965c7a7SJeremy L Thompson   for (CeedInt i=0; i<nx*2+1; i++)
29*d965c7a7SJeremy L Thompson     for (CeedInt j=0; j<ny*2+1; j++) {
30*d965c7a7SJeremy L Thompson       x[i+j*(nx*2+1)+0*ndofs] = (CeedScalar) i / (2*nx);
31*d965c7a7SJeremy L Thompson       x[i+j*(nx*2+1)+1*ndofs] = (CeedScalar) j / (2*ny);
32*d965c7a7SJeremy L Thompson     }
33*d965c7a7SJeremy L Thompson   CeedVectorCreate(ceed, dim*ndofs, &X);
34*d965c7a7SJeremy L Thompson   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
35*d965c7a7SJeremy L Thompson 
36*d965c7a7SJeremy L Thompson   // Qdata Vector
37*d965c7a7SJeremy L Thompson   CeedVectorCreate(ceed, nqpts, &qdata);
38*d965c7a7SJeremy L Thompson 
39*d965c7a7SJeremy L Thompson   // Element Setup
40*d965c7a7SJeremy L Thompson   for (CeedInt i=0; i<nelem; i++) {
41*d965c7a7SJeremy L Thompson     CeedInt col, row, offset;
42*d965c7a7SJeremy L Thompson     col = i % nx;
43*d965c7a7SJeremy L Thompson     row = i / nx;
44*d965c7a7SJeremy L Thompson     offset = col*(P-1) + row*(nx*2+1)*(P-1);
45*d965c7a7SJeremy L Thompson     for (CeedInt j=0; j<P; j++)
46*d965c7a7SJeremy L Thompson       for (CeedInt k=0; k<P; k++)
47*d965c7a7SJeremy L Thompson         indx[P*(P*i+k)+j] = offset + k*(nx*2+1) + j;
48*d965c7a7SJeremy L Thompson   }
49*d965c7a7SJeremy L Thompson 
50*d965c7a7SJeremy L Thompson   // Restrictions
51*d965c7a7SJeremy L Thompson   CeedElemRestrictionCreate(ceed, nelem, P*P, dim, ndofs, dim*ndofs,
52*d965c7a7SJeremy L Thompson                             CEED_MEM_HOST, CEED_USE_POINTER, indx, &Erestrictx);
53*d965c7a7SJeremy L Thompson   CeedElemRestrictionCreate(ceed, nelem, P*P, ncomp, ndofs, ncomp*ndofs,
54*d965c7a7SJeremy L Thompson                             CEED_MEM_HOST, CEED_USE_POINTER, indx, &Erestrictu);
55*d965c7a7SJeremy L Thompson   CeedInt stridesu[3] = {1, Q*Q, Q*Q};
56*d965c7a7SJeremy L Thompson   CeedElemRestrictionCreateStrided(ceed, nelem, Q*Q, 1, nqpts, stridesu,
57*d965c7a7SJeremy L Thompson                                    &Erestrictui);
58*d965c7a7SJeremy L Thompson 
59*d965c7a7SJeremy L Thompson   // Bases
60*d965c7a7SJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, P, Q, CEED_GAUSS, &bx);
61*d965c7a7SJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncomp, P, Q, CEED_GAUSS, &bu);
62*d965c7a7SJeremy L Thompson 
63*d965c7a7SJeremy L Thompson   // QFunctions
64*d965c7a7SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup);
65*d965c7a7SJeremy L Thompson   CeedQFunctionAddInput(qf_setup, "_weight", 1, CEED_EVAL_WEIGHT);
66*d965c7a7SJeremy L Thompson   CeedQFunctionAddInput(qf_setup, "dx", dim*dim, CEED_EVAL_GRAD);
67*d965c7a7SJeremy L Thompson   CeedQFunctionAddOutput(qf_setup, "rho", 1, CEED_EVAL_NONE);
68*d965c7a7SJeremy L Thompson 
69*d965c7a7SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass);
70*d965c7a7SJeremy L Thompson   CeedQFunctionAddInput(qf_mass, "rho", 1, CEED_EVAL_NONE);
71*d965c7a7SJeremy L Thompson   CeedQFunctionAddInput(qf_mass, "u", ncomp, CEED_EVAL_INTERP);
72*d965c7a7SJeremy L Thompson   CeedQFunctionAddOutput(qf_mass, "v", ncomp, CEED_EVAL_INTERP);
73*d965c7a7SJeremy L Thompson 
74*d965c7a7SJeremy L Thompson   // Operators
75*d965c7a7SJeremy L Thompson   CeedOperatorCreate(ceed, qf_setup, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
76*d965c7a7SJeremy L Thompson                      &op_setup);
77*d965c7a7SJeremy L Thompson   CeedOperatorSetField(op_setup, "_weight", CEED_ELEMRESTRICTION_NONE, bx,
78*d965c7a7SJeremy L Thompson                        CEED_VECTOR_NONE);
79*d965c7a7SJeremy L Thompson   CeedOperatorSetField(op_setup, "dx", Erestrictx, bx, CEED_VECTOR_ACTIVE);
80*d965c7a7SJeremy L Thompson   CeedOperatorSetField(op_setup, "rho", Erestrictui, CEED_BASIS_COLLOCATED,
81*d965c7a7SJeremy L Thompson                        CEED_VECTOR_ACTIVE);
82*d965c7a7SJeremy L Thompson 
83*d965c7a7SJeremy L Thompson   CeedOperatorCreate(ceed, qf_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
84*d965c7a7SJeremy L Thompson                      &op_mass);
85*d965c7a7SJeremy L Thompson   CeedOperatorSetField(op_mass, "rho", Erestrictui, CEED_BASIS_COLLOCATED,
86*d965c7a7SJeremy L Thompson                        qdata);
87*d965c7a7SJeremy L Thompson   CeedOperatorSetField(op_mass, "u", Erestrictu, bu, CEED_VECTOR_ACTIVE);
88*d965c7a7SJeremy L Thompson   CeedOperatorSetField(op_mass, "v", Erestrictu, bu, CEED_VECTOR_ACTIVE);
89*d965c7a7SJeremy L Thompson 
90*d965c7a7SJeremy L Thompson   // Apply Setup Operator
91*d965c7a7SJeremy L Thompson   CeedOperatorApply(op_setup, X, qdata, CEED_REQUEST_IMMEDIATE);
92*d965c7a7SJeremy L Thompson 
93*d965c7a7SJeremy L Thompson   // Assemble diagonal
94*d965c7a7SJeremy L Thompson   CeedOperatorAssembleLinearPointBlockDiagonal(op_mass, &A,
95*d965c7a7SJeremy L Thompson       CEED_REQUEST_IMMEDIATE);
96*d965c7a7SJeremy L Thompson 
97*d965c7a7SJeremy L Thompson   // Manually assemble diagonal
98*d965c7a7SJeremy L Thompson   CeedVectorCreate(ceed, ncomp*ndofs, &U);
99*d965c7a7SJeremy L Thompson   CeedVectorSetValue(U, 0.0);
100*d965c7a7SJeremy L Thompson   CeedVectorCreate(ceed, ncomp*ndofs, &V);
101*d965c7a7SJeremy L Thompson   for (int i=0; i<ncomp*ncomp*ndofs; i++)
102*d965c7a7SJeremy L Thompson     assembledTrue[i] = 0.0;
103*d965c7a7SJeremy L Thompson   CeedInt indOld = -1;
104*d965c7a7SJeremy L Thompson   for (int i=0; i<ndofs; i++) {
105*d965c7a7SJeremy L Thompson     for (int j=0; j<ncomp; j++) {
106*d965c7a7SJeremy L Thompson       // Set input
107*d965c7a7SJeremy L Thompson       CeedVectorGetArray(U, CEED_MEM_HOST, &u);
108*d965c7a7SJeremy L Thompson       CeedInt ind = i + j*ndofs;
109*d965c7a7SJeremy L Thompson       u[ind] = 1.0;
110*d965c7a7SJeremy L Thompson       if (ind > 0)
111*d965c7a7SJeremy L Thompson         u[indOld] = 0.0;
112*d965c7a7SJeremy L Thompson       indOld = ind;
113*d965c7a7SJeremy L Thompson       CeedVectorRestoreArray(U, &u);
114*d965c7a7SJeremy L Thompson 
115*d965c7a7SJeremy L Thompson       // Compute effect of DoF i, comp j
116*d965c7a7SJeremy L Thompson       CeedOperatorApply(op_mass, U, V, CEED_REQUEST_IMMEDIATE);
117*d965c7a7SJeremy L Thompson 
118*d965c7a7SJeremy L Thompson       // Retrieve entry
119*d965c7a7SJeremy L Thompson       CeedVectorGetArrayRead(V, CEED_MEM_HOST, &v);
120*d965c7a7SJeremy L Thompson       for (int k = 0; k<ncomp; k++)
121*d965c7a7SJeremy L Thompson         assembledTrue[i*ncomp*ncomp + k*ncomp + j] += v[i + k*ndofs];
122*d965c7a7SJeremy L Thompson       CeedVectorRestoreArrayRead(V, &v);
123*d965c7a7SJeremy L Thompson     }
124*d965c7a7SJeremy L Thompson   }
125*d965c7a7SJeremy L Thompson 
126*d965c7a7SJeremy L Thompson   // Check output
127*d965c7a7SJeremy L Thompson   CeedVectorGetArrayRead(A, CEED_MEM_HOST, &a);
128*d965c7a7SJeremy L Thompson   for (int i=0; i<ncomp*ncomp*ndofs; i++)
129*d965c7a7SJeremy L Thompson     if (fabs(a[i] - assembledTrue[i]) > 1e-14)
130*d965c7a7SJeremy L Thompson       // LCOV_EXCL_START
131*d965c7a7SJeremy L Thompson       printf("[%d] Error in assembly: %f != %f\n", i, a[i], assembledTrue[i]);
132*d965c7a7SJeremy L Thompson   // LCOV_EXCL_STOP
133*d965c7a7SJeremy L Thompson   CeedVectorRestoreArrayRead(A, &a);
134*d965c7a7SJeremy L Thompson 
135*d965c7a7SJeremy L Thompson   // Cleanup
136*d965c7a7SJeremy L Thompson   CeedQFunctionDestroy(&qf_setup);
137*d965c7a7SJeremy L Thompson   CeedQFunctionDestroy(&qf_mass);
138*d965c7a7SJeremy L Thompson   CeedOperatorDestroy(&op_setup);
139*d965c7a7SJeremy L Thompson   CeedOperatorDestroy(&op_mass);
140*d965c7a7SJeremy L Thompson   CeedElemRestrictionDestroy(&Erestrictu);
141*d965c7a7SJeremy L Thompson   CeedElemRestrictionDestroy(&Erestrictx);
142*d965c7a7SJeremy L Thompson   CeedElemRestrictionDestroy(&Erestrictui);
143*d965c7a7SJeremy L Thompson   CeedBasisDestroy(&bu);
144*d965c7a7SJeremy L Thompson   CeedBasisDestroy(&bx);
145*d965c7a7SJeremy L Thompson   CeedVectorDestroy(&X);
146*d965c7a7SJeremy L Thompson   CeedVectorDestroy(&A);
147*d965c7a7SJeremy L Thompson   CeedVectorDestroy(&qdata);
148*d965c7a7SJeremy L Thompson   CeedVectorDestroy(&U);
149*d965c7a7SJeremy L Thompson   CeedVectorDestroy(&V);
150*d965c7a7SJeremy L Thompson   CeedDestroy(&ceed);
151*d965c7a7SJeremy L Thompson   return 0;
152*d965c7a7SJeremy L Thompson }
153