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