xref: /libCEED/tests/t540-operator.c (revision 3bd813ff881321d63f499fd87a0d6e6a47c6a2dc)
1*3bd813ffSjeremylt /// @file
2*3bd813ffSjeremylt /// Test creation and use of FDM element inverse
3*3bd813ffSjeremylt /// \test Test creation and use of FDM element inverse
4*3bd813ffSjeremylt #include <ceed.h>
5*3bd813ffSjeremylt #include <stdlib.h>
6*3bd813ffSjeremylt #include <math.h>
7*3bd813ffSjeremylt #include "t540-operator.h"
8*3bd813ffSjeremylt 
9*3bd813ffSjeremylt int main(int argc, char **argv) {
10*3bd813ffSjeremylt   Ceed ceed;
11*3bd813ffSjeremylt   CeedElemRestriction Erestrictxi, Erestrictui, Erestrictqi;
12*3bd813ffSjeremylt   CeedBasis bx, bu;
13*3bd813ffSjeremylt   CeedQFunction qf_setup_mass, qf_apply;
14*3bd813ffSjeremylt   CeedOperator op_setup_mass, op_apply, op_inv;
15*3bd813ffSjeremylt   CeedVector qdata_mass, X, U, V;
16*3bd813ffSjeremylt   CeedInt nelem = 1, P = 4, Q = 5, dim = 2;
17*3bd813ffSjeremylt   CeedInt ndofs = P*P, nqpts = nelem*Q*Q;
18*3bd813ffSjeremylt   CeedScalar x[dim*nelem*(2*2)];
19*3bd813ffSjeremylt   const CeedScalar *u;
20*3bd813ffSjeremylt 
21*3bd813ffSjeremylt   CeedInit(argv[1], &ceed);
22*3bd813ffSjeremylt 
23*3bd813ffSjeremylt   // DoF Coordinates
24*3bd813ffSjeremylt   for (CeedInt i=0; i<2; i++)
25*3bd813ffSjeremylt     for (CeedInt j=0; j<2; j++) {
26*3bd813ffSjeremylt       x[i+j*2+0*4] = i;
27*3bd813ffSjeremylt       x[i+j*2+1*4] = j;
28*3bd813ffSjeremylt     }
29*3bd813ffSjeremylt   CeedVectorCreate(ceed, dim*nelem*(2*2), &X);
30*3bd813ffSjeremylt   CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x);
31*3bd813ffSjeremylt 
32*3bd813ffSjeremylt   // Qdata Vector
33*3bd813ffSjeremylt   CeedVectorCreate(ceed, nqpts, &qdata_mass);
34*3bd813ffSjeremylt 
35*3bd813ffSjeremylt   // Element Setup
36*3bd813ffSjeremylt 
37*3bd813ffSjeremylt   // Restrictions
38*3bd813ffSjeremylt   CeedElemRestrictionCreateIdentity(ceed, nelem, 2*2, nelem*2*2, dim,
39*3bd813ffSjeremylt                                     &Erestrictxi);
40*3bd813ffSjeremylt 
41*3bd813ffSjeremylt   CeedElemRestrictionCreateIdentity(ceed, nelem, P*P, ndofs, 1, &Erestrictui);
42*3bd813ffSjeremylt 
43*3bd813ffSjeremylt   CeedElemRestrictionCreateIdentity(ceed, nelem, Q*Q, nqpts, 1, &Erestrictqi);
44*3bd813ffSjeremylt 
45*3bd813ffSjeremylt   // Bases
46*3bd813ffSjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, Q, CEED_GAUSS, &bx);
47*3bd813ffSjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, P, Q, CEED_GAUSS, &bu);
48*3bd813ffSjeremylt 
49*3bd813ffSjeremylt   // QFunction - setup mass
50*3bd813ffSjeremylt   CeedQFunctionCreateInterior(ceed, 1, setup_mass, setup_mass_loc,
51*3bd813ffSjeremylt                               &qf_setup_mass);
52*3bd813ffSjeremylt   CeedQFunctionAddInput(qf_setup_mass, "dx", dim*dim, CEED_EVAL_GRAD);
53*3bd813ffSjeremylt   CeedQFunctionAddInput(qf_setup_mass, "_weight", 1, CEED_EVAL_WEIGHT);
54*3bd813ffSjeremylt   CeedQFunctionAddOutput(qf_setup_mass, "qdata", 1, CEED_EVAL_NONE);
55*3bd813ffSjeremylt 
56*3bd813ffSjeremylt   // Operator - setup mass
57*3bd813ffSjeremylt   CeedOperatorCreate(ceed, qf_setup_mass, CEED_QFUNCTION_NONE,
58*3bd813ffSjeremylt                      CEED_QFUNCTION_NONE, &op_setup_mass);
59*3bd813ffSjeremylt   CeedOperatorSetField(op_setup_mass, "dx", Erestrictxi, CEED_NOTRANSPOSE, bx,
60*3bd813ffSjeremylt                        CEED_VECTOR_ACTIVE);
61*3bd813ffSjeremylt   CeedOperatorSetField(op_setup_mass, "_weight", Erestrictxi, CEED_NOTRANSPOSE,
62*3bd813ffSjeremylt                        bx, CEED_VECTOR_NONE);
63*3bd813ffSjeremylt   CeedOperatorSetField(op_setup_mass, "qdata", Erestrictqi, CEED_NOTRANSPOSE,
64*3bd813ffSjeremylt                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
65*3bd813ffSjeremylt 
66*3bd813ffSjeremylt   // Apply Setup Operator
67*3bd813ffSjeremylt   CeedOperatorApply(op_setup_mass, X, qdata_mass, CEED_REQUEST_IMMEDIATE);
68*3bd813ffSjeremylt 
69*3bd813ffSjeremylt   // QFunction - apply
70*3bd813ffSjeremylt   CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply);
71*3bd813ffSjeremylt   CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP);
72*3bd813ffSjeremylt   CeedQFunctionAddInput(qf_apply, "qdata_mass", 1, CEED_EVAL_NONE);
73*3bd813ffSjeremylt   CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP);
74*3bd813ffSjeremylt 
75*3bd813ffSjeremylt   // Operator - apply
76*3bd813ffSjeremylt   CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
77*3bd813ffSjeremylt                      &op_apply);
78*3bd813ffSjeremylt   CeedOperatorSetField(op_apply, "u", Erestrictui, CEED_NOTRANSPOSE, bu,
79*3bd813ffSjeremylt                        CEED_VECTOR_ACTIVE);
80*3bd813ffSjeremylt   CeedOperatorSetField(op_apply, "qdata_mass", Erestrictqi, CEED_NOTRANSPOSE,
81*3bd813ffSjeremylt                        CEED_BASIS_COLLOCATED, qdata_mass);
82*3bd813ffSjeremylt   CeedOperatorSetField(op_apply, "v", Erestrictui, CEED_NOTRANSPOSE, bu,
83*3bd813ffSjeremylt                        CEED_VECTOR_ACTIVE);
84*3bd813ffSjeremylt 
85*3bd813ffSjeremylt   // Apply original operator
86*3bd813ffSjeremylt   CeedVectorCreate(ceed, ndofs, &U);
87*3bd813ffSjeremylt   CeedVectorSetValue(U, 1.0);
88*3bd813ffSjeremylt   CeedVectorCreate(ceed, ndofs, &V);
89*3bd813ffSjeremylt   CeedVectorSetValue(V, 0.0);
90*3bd813ffSjeremylt   CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE);
91*3bd813ffSjeremylt 
92*3bd813ffSjeremylt   // Create FDM element inverse
93*3bd813ffSjeremylt   CeedOperatorCreateFDMElementInverse(op_apply, &op_inv, CEED_REQUEST_IMMEDIATE);
94*3bd813ffSjeremylt 
95*3bd813ffSjeremylt   // Apply FDM element inverse
96*3bd813ffSjeremylt   CeedOperatorApply(op_inv, V, U, CEED_REQUEST_IMMEDIATE);
97*3bd813ffSjeremylt 
98*3bd813ffSjeremylt   // Check output
99*3bd813ffSjeremylt   CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u);
100*3bd813ffSjeremylt   for (int i=0; i<ndofs; i++)
101*3bd813ffSjeremylt     if (fabs(u[i] - 1.0) > 1E-14)
102*3bd813ffSjeremylt       // LCOV_EXCL_START
103*3bd813ffSjeremylt       printf("[%d] Error in inverse: %f != 1.0\n", i, u[i]);
104*3bd813ffSjeremylt   // LCOV_EXCL_STOP
105*3bd813ffSjeremylt   CeedVectorRestoreArrayRead(U, &u);
106*3bd813ffSjeremylt 
107*3bd813ffSjeremylt   // Cleanup
108*3bd813ffSjeremylt   CeedQFunctionDestroy(&qf_setup_mass);
109*3bd813ffSjeremylt   CeedQFunctionDestroy(&qf_apply);
110*3bd813ffSjeremylt   CeedOperatorDestroy(&op_setup_mass);
111*3bd813ffSjeremylt   CeedOperatorDestroy(&op_apply);
112*3bd813ffSjeremylt   CeedOperatorDestroy(&op_inv);
113*3bd813ffSjeremylt   CeedElemRestrictionDestroy(&Erestrictui);
114*3bd813ffSjeremylt   CeedElemRestrictionDestroy(&Erestrictxi);
115*3bd813ffSjeremylt   CeedElemRestrictionDestroy(&Erestrictqi);
116*3bd813ffSjeremylt   CeedBasisDestroy(&bu);
117*3bd813ffSjeremylt   CeedBasisDestroy(&bx);
118*3bd813ffSjeremylt   CeedVectorDestroy(&X);
119*3bd813ffSjeremylt   CeedVectorDestroy(&qdata_mass);
120*3bd813ffSjeremylt   CeedVectorDestroy(&U);
121*3bd813ffSjeremylt   CeedVectorDestroy(&V);
122*3bd813ffSjeremylt   CeedDestroy(&ceed);
123*3bd813ffSjeremylt   return 0;
124*3bd813ffSjeremylt }
125